v0.16.3
Loading...
Searching...
No Matches
tao_ctx_constraints.cpp
Go to the documentation of this file.
1/** \file tao_ctx_constraints.cpp
2 * \brief Test TAO constraint pipelines and application evaluation hooks
3 */
4
5#include <MoFEM.hpp>
6
7using namespace MoFEM;
8
9static char help[] = "Test TaoCtx constraint callbacks.\n\n";
10
11int main(int argc, char *argv[]) {
12 MoFEM::Core::Initialize(&argc, &argv, nullptr, help);
13
14 try {
15 moab::Core moab_core;
16 MoFEM::Core mofem_core(moab_core);
17 MoFEM::Interface &m_field = mofem_core;
18
19 CHKERR DMRegister_MoFEM("DMMOFEM");
20
21 auto simple = m_field.getInterface<Simple>();
23 CHKERR simple->loadFile();
24 CHKERR simple->addDomainField("X", H1, AINSWORTH_LEGENDRE_BASE, 1);
25 CHKERR simple->setFieldOrder("X", 1);
26 CHKERR simple->setUp();
27
28 auto dm = simple->getDM();
29 auto x = createDMVector(dm);
30 auto c = vectorDuplicate(x);
31 auto J = createDMMatrix(dm);
32 auto diagonal = vectorDuplicate(x);
33
34 Tao tao;
35 CHKERR TaoCreate(PETSC_COMM_WORLD, &tao);
36 CHKERR TaoSetType(tao, TAOALMM);
37 CHKERR TaoSetSolution(tao, x);
38
39 TaoCtx tao_ctx(m_field, simple->getProblemName());
40
41 auto check_vector_pipeline = [&](auto context, const double value,
42 auto &pre_process, auto &post_process) {
43 auto pre = boost::make_shared<BasicMethod>();
44 auto post = boost::make_shared<BasicMethod>();
45 auto *pre_ptr = pre.get();
46 auto *post_ptr = post.get();
47
48 pre->preProcessHook = [pre_ptr, context, value, c]() {
50 if (pre_ptr->tao_ctx != context || pre_ptr->tao_c != c)
51 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
52 "Incorrect TAO constraint context");
53 CHKERR VecSet(pre_ptr->tao_c, value);
55 };
56 post->postProcessHook = [post_ptr, context, c]() {
58 if (post_ptr->tao_ctx != context || post_ptr->tao_c != c)
59 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
60 "Incorrect TAO constraint context");
62 };
63
64 pre_process.push_back(pre);
65 post_process.push_back(post);
66 };
67
68 auto check_jacobian_pipeline = [&](auto context, const double value,
69 auto &pre_process, auto &post_process) {
70 auto pre = boost::make_shared<BasicMethod>();
71 auto post = boost::make_shared<BasicMethod>();
72 auto *pre_ptr = pre.get();
73 auto *post_ptr = post.get();
74
75 pre->preProcessHook = [pre_ptr, context, value, J]() {
77 if (pre_ptr->tao_ctx != context || pre_ptr->tao_J != J ||
78 pre_ptr->tao_Jpre != J)
79 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
80 "Incorrect TAO constraint Jacobian context");
81 CHKERR MatShift(pre_ptr->tao_Jpre, value);
83 };
84 post->postProcessHook = [post_ptr, context, J]() {
86 if (post_ptr->tao_ctx != context || post_ptr->tao_J != J ||
87 post_ptr->tao_Jpre != J)
88 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
89 "Incorrect TAO constraint Jacobian context");
91 };
92
93 pre_process.push_back(pre);
94 post_process.push_back(post);
95 };
96
97 check_vector_pipeline(TaoMethod::CTX_TAO_EQUALITY_CONSTRAINT, 2.0,
100 check_vector_pipeline(TaoMethod::CTX_TAO_INEQUALITY_CONSTRAINT, 3.0,
103 check_jacobian_pipeline(TaoMethod::CTX_TAO_EQUALITY_JACOBIAN, 4.0,
106 check_jacobian_pipeline(TaoMethod::CTX_TAO_INEQUALITY_JACOBIAN, 5.0,
109
110 CHKERR TaoSetEqualityConstraintsRoutine(
111 tao, c, MoFEM::TaoSetEqualityConstraints, &tao_ctx);
112 CHKERR TaoSetInequalityConstraintsRoutine(
113 tao, c, MoFEM::TaoSetInequalityConstraints, &tao_ctx);
114 CHKERR TaoSetJacobianEqualityRoutine(
115 tao, J, J, MoFEM::TaoSetJacobianEquality, &tao_ctx);
116 CHKERR TaoSetJacobianInequalityRoutine(
117 tao, J, J, MoFEM::TaoSetJacobianInequality, &tao_ctx);
118
119 auto check_vector = [&](const double expected) {
121 CHKERR VecShift(c, -expected);
122 PetscReal norm;
123 CHKERR VecNorm(c, NORM_INFINITY, &norm);
124 if (norm > 10 * PETSC_MACHINE_EPSILON)
125 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
126 "Incorrect TAO constraint vector");
128 };
129
130 auto check_jacobian = [&](const double expected) {
132 CHKERR MatGetDiagonal(J, diagonal);
133 CHKERR VecShift(diagonal, -expected);
134 PetscReal norm;
135 CHKERR VecNorm(diagonal, NORM_INFINITY, &norm);
136 if (norm > 10 * PETSC_MACHINE_EPSILON)
137 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
138 "Incorrect TAO constraint Jacobian");
140 };
141
142 CHKERR TaoComputeEqualityConstraints(tao, x, c);
143 CHKERR check_vector(2.0);
144 CHKERR TaoComputeInequalityConstraints(tao, x, c);
145 CHKERR check_vector(3.0);
146 CHKERR TaoComputeJacobianEquality(tao, x, J, J);
147 CHKERR check_jacobian(4.0);
148 CHKERR TaoComputeJacobianInequality(tao, x, J, J);
149 CHKERR check_jacobian(5.0);
150
151 TaoCtx copied_ctx(m_field, simple->getProblemName());
152 CHKERR copied_ctx.copyLoops(tao_ctx);
153 if (copied_ctx.getPreProcEqualityConstraint().empty() ||
154 copied_ctx.getPreProcInequalityConstraint().empty() ||
155 copied_ctx.getPreProcEqualityJacobian().empty() ||
156 copied_ctx.getPreProcInequalityJacobian().empty())
157 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
158 "TAO constraint pipelines were not copied");
159 CHKERR copied_ctx.clearLoops();
160 if (!copied_ctx.getPreProcEqualityConstraint().empty() ||
161 !copied_ctx.getPreProcInequalityConstraint().empty() ||
162 !copied_ctx.getPreProcEqualityJacobian().empty() ||
163 !copied_ctx.getPreProcInequalityJacobian().empty())
164 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
165 "TAO constraint pipelines were not cleared");
166
167 // A reduced objective owns its mesh state and can reuse its gradient.
168 // Neither wrapper may scatter a trial or clear that cached result.
169 CHKERR VecZeroEntries(x);
170 CHKERR m_field.getInterface<VecManager>()->setLocalGhostVector(
171 simple->getProblemName(), COL, x, INSERT_VALUES, SCATTER_REVERSE);
172 CHKERR VecSet(x, 2.0);
173 auto gradient = vectorDuplicate(x);
174 auto expected_gradient = vectorDuplicate(x);
175 CHKERR VecSet(gradient, 7.0);
176 CHKERR VecCopy(gradient, expected_gradient);
177 PetscInt objective_calls = 0, gradient_calls = 0;
178 tao_ctx.getObjectiveHook() = [&](Tao, Vec trial, PetscReal *objective) {
180 if (trial != x)
181 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
182 "Incorrect TAO objective-hook controls");
183 ++objective_calls;
184 *objective = 3.0;
186 };
187 tao_ctx.getGradientHook() = [&](Tao, Vec trial, Vec g) {
189 PetscBool equal;
190 CHKERR VecEqual(g, expected_gradient, &equal);
191 if (trial != x || !equal)
192 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
193 "TAO gradient hook did not receive the cached gradient");
194 ++gradient_calls;
196 };
197 CHKERR ::TaoSetObjective(tao, MoFEM::TaoSetObjective, &tao_ctx);
198 CHKERR ::TaoSetGradient(tao, gradient, MoFEM::TaoSetGradient, &tao_ctx);
199 CHKERR ::TaoSetObjectiveAndGradient(
201 PetscReal objective;
202 CHKERR TaoComputeObjective(tao, x, &objective);
203 if (objective != 3.0 || objective_calls != 1 || gradient_calls != 0)
204 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
205 "Objective-only wrapper did not dispatch exclusively to its hook");
206 CHKERR TaoComputeGradient(tao, x, gradient);
207 if (objective_calls != 1 || gradient_calls != 1)
208 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
209 "Gradient-only wrapper did not dispatch exclusively to its hook");
210 CHKERR TaoComputeObjectiveAndGradient(tao, x, &objective, gradient);
211 PetscBool equal;
212 CHKERR VecEqual(gradient, expected_gradient, &equal);
213 if (objective != 3.0 || objective_calls != 2 || gradient_calls != 2 ||
214 !equal)
215 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
216 "Combined wrapper did not fall back to the separate hooks");
217 auto mesh_controls = vectorDuplicate(x);
218 CHKERR m_field.getInterface<VecManager>()->setLocalGhostVector(
219 simple->getProblemName(), COL, mesh_controls, INSERT_VALUES,
220 SCATTER_FORWARD);
221 PetscReal mesh_norm;
222 CHKERR VecNorm(mesh_controls, NORM_INFINITY, &mesh_norm);
223 if (mesh_norm != 0)
224 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
225 "TAO evaluation hooks implicitly scattered trial controls");
226
227 CHKERR TaoDestroy(&tao);
228 }
230
232 return 0;
233}
SmartPetscObj< Vec > diagonal
SmartPetscObj< Vec > gradient
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
@ COL
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1207
const double c
speed of light (cm/ns)
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode TaoSetObjective(Tao tao, Vec x, PetscReal *f, void *ctx)
Sets the objective function value for a TAO optimization context.
Definition TaoCtx.cpp:237
PetscErrorCode TaoSetJacobianInequality(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx)
Assemble the inequality constraint Jacobian.
Definition TaoCtx.cpp:502
PetscErrorCode TaoSetEqualityConstraints(Tao tao, Vec x, Vec c, void *ctx)
Evaluate equality constraints for a TAO optimization context.
Definition TaoCtx.cpp:468
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode TaoSetInequalityConstraints(Tao tao, Vec x, Vec c, void *ctx)
Evaluate inequality constraints for a TAO optimization context.
Definition TaoCtx.cpp:479
PetscErrorCode TaoSetJacobianEquality(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx)
Assemble the equality constraint Jacobian.
Definition TaoCtx.cpp:490
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
Definition TaoCtx.cpp:386
PetscErrorCode TaoSetGradient(Tao tao, Vec x, Vec f, void *ctx)
Sets the gradient vector for a TAO optimization context.
Definition TaoCtx.cpp:296
constexpr double g
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
Interface for TAO solvers.
Definition TaoCtx.hpp:14
MoFEMErrorCode copyLoops(const TaoCtx &tao_ctx)
Copy sequences from another TaoCtx.
Definition TaoCtx.cpp:41
BasicMethodsSequence & getPreProcEqualityConstraint()
Definition TaoCtx.hpp:137
BasicMethodsSequence & getPreProcEqualityJacobian()
Definition TaoCtx.hpp:159
BasicMethodsSequence & getPostProcInequalityConstraint()
Definition TaoCtx.hpp:151
ObjectiveHook & getObjectiveHook()
Get an optional objective evaluator.
Definition TaoCtx.hpp:184
BasicMethodsSequence & getPostProcInequalityJacobian()
Definition TaoCtx.hpp:173
BasicMethodsSequence & getPreProcInequalityJacobian()
Definition TaoCtx.hpp:170
MoFEMErrorCode clearLoops()
Clear loops.
Definition TaoCtx.cpp:67
GradientHook & getGradientHook()
Get an optional gradient evaluator.
Definition TaoCtx.hpp:193
BasicMethodsSequence & getPostProcEqualityConstraint()
Definition TaoCtx.hpp:140
BasicMethodsSequence & getPostProcEqualityJacobian()
Definition TaoCtx.hpp:162
BasicMethodsSequence & getPreProcInequalityConstraint()
Definition TaoCtx.hpp:148
@ CTX_TAO_EQUALITY_CONSTRAINT
Evaluating equality constraints.
@ CTX_TAO_EQUALITY_JACOBIAN
Assembling equality Jacobian.
@ CTX_TAO_INEQUALITY_JACOBIAN
Assembling inequality Jacobian.
@ CTX_TAO_INEQUALITY_CONSTRAINT
Evaluating inequality constraints.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
static char help[]