v0.16.3
Loading...
Searching...
No Matches
gradient.cpp
Go to the documentation of this file.
1/**
2 * @file gradient.cpp
3 */
4
5#include <boost/python.hpp>
6#include <boost/python/def.hpp>
7#include <boost/python/numpy.hpp>
8namespace bp = boost::python;
9namespace np = boost::python::numpy;
10
11#include <MoFEM.hpp>
12
13using namespace MoFEM;
14
15//! [Constants and material properties]
16constexpr int BASE_DIM = 1; ///< Dimension of the base functions
17
18//! [Define dimension]
19constexpr int SPACE_DIM =
20 EXECUTABLE_DIMENSION; ///< Space dimension of problem (2D or 3D), set at compile time
21
22//! [Define dimension]
23constexpr AssemblyType A =
24 AssemblyType::PETSC; ///< Use PETSc for matrix/vector assembly
25constexpr IntegrationType I =
26 IntegrationType::GAUSS; ///< Use Gauss quadrature for integration
27
28//! [Material properties for linear elasticity]
29constexpr double young_modulus = 1; ///< Young's modulus E
30constexpr double poisson_ratio = 0.3; ///< Poisson's ratio ν
31constexpr double bulk_modulus_K =
33 (3 * (1 - 2 * poisson_ratio)); ///< Bulk modulus K = E/(3(1-2ν))
34constexpr double shear_modulus_G =
35 young_modulus / (2 * (1 + poisson_ratio)); ///< Shear modulus G = E/(2(1+ν))
36
37PetscBool is_plane_strain =
38 PETSC_FALSE; ///< Flag for plane strain vs plane stress in 2D
39//! [Constants and material properties]
40
41//! [Define finite element types and operators]
42using EntData =
43 EntitiesFieldData::EntData; ///< Entity data for field operations
45 SPACE_DIM>::DomainEle; ///< Domain finite elements
47 SPACE_DIM>::BoundaryEle; ///< Boundary finite elements
48using DomainEleOp = DomainEle::UserDataOperator; ///< Domain element operators
50 BoundaryEle::UserDataOperator; ///< Boundary element operators
51//! [Define finite element types and operators]
52
53//! [Boundary condition types]
54struct DomainBCs {}; ///< Domain boundary conditions marker
55struct BoundaryBCs {}; ///< Boundary conditions marker
56
57//! [Natural boundary condition operators]
59 I>; ///< Domain RHS natural BCs
61 DomainRhsBCs::OpFlux<DomainBCs, 1, SPACE_DIM>; ///< Domain flux operator
63 I>; ///< Boundary RHS natural BCs
66 SPACE_DIM>; ///< Boundary flux operator
68 I>; ///< Boundary LHS natural BCs
71 SPACE_DIM>; ///< Boundary LHS flux operator
72
73template <int DIM> struct PostProcEleByDim;
74
75template <> struct PostProcEleByDim<2> {
79};
80
81template <> struct PostProcEleByDim<3> {
85};
86// Here you can see how the template is being used
90// Forward declaration
91template <int SPACE_DIM, IntegrationType I, typename OpBase>
92struct OpAdJointTestOp;
93
95
97
98#include <ElasticSpring.hpp>
99#include <FluidLevel.hpp>
100#include <CalculateTraction.hpp>
101#include <NaturalDomainBC.hpp>
102#include <NaturalBoundaryBC.hpp>
103#include <HookeOps.hpp>
104#include <ElasticPostProc.hpp>
105
107using namespace ShapeOptimization;
108
110 const std::string block_name, int dim);
111
112MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
113 const Range r);
114struct Example {
115
116 Example(MoFEM::Interface &m_field) : mField(m_field) {}
117
118 /// Main driver function for the optimization process
120
121private:
122 MoFEM::Interface &mField; ///< Reference to MoFEM interface
123
124 // Problem setup methods
130
131 // Analysis methods
132 MoFEMErrorCode solveElastic(); ///< Solve forward elastic problem
134 int iter, SmartPetscObj<Vec> gradient_vector = nullptr,
135 SmartPetscObj<Vec> adjoint_vector = nullptr,
136 SmartPetscObj<Vec> dJ_du = nullptr); ///< Post-process and output results
137
138 /// Calculate objective function gradient using adjoint method
139 MoFEMErrorCode calculateGradient(PetscReal *objective_function_value,
140 Vec objective_function_gradient,
141 Vec adjoint_vector, Vec dJ_du);
142
143 MoFEMErrorCode checkResults(Vec gradient_vector);
144
145 // Problem configuration
146 FieldApproximationBase base; ///< Choice of finite element basis functions
147 int fieldOrder = 2; ///< Polynomial order for approximation
148
149 // Solver and data management
150 SmartPetscObj<KSP> kspElastic; ///< Linear solver for elastic problem
151 SmartPetscObj<DM> adjointDM; ///< Data manager for adjoint problem
152 boost::shared_ptr<ObjectiveFunctionData>
153 pythonPtr; ///< Interface to Python objective function
154};
155
156//! [Run topology optimization problem]
159
160 // Read objective function from Python file
161 char objective_function_file_name[255] = "objective_function.py";
163 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
164 objective_function_file_name, 255, PETSC_NULLPTR);
165
166 // Verify that the Python objective function file exists
167 auto file_exists = [](std::string myfile) {
168 std::ifstream file(myfile.c_str());
169 if (file) {
170 return true;
171 }
172 return false;
173 };
174 if (!file_exists(objective_function_file_name)) {
175 MOFEM_LOG("WORLD", Sev::error) << "Objective function file NOT found: "
176 << objective_function_file_name;
177 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "file NOT found");
178 }
179
180 // Create Python interface for objective function
181 pythonPtr = create_python_objective_function(objective_function_file_name);
182
183 char sensitivity_method_name[32] = "adjoint";
184 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
185 "-sensitivity_method", sensitivity_method_name,
186 sizeof(sensitivity_method_name), PETSC_NULLPTR);
187 std::string sensitivity_method = sensitivity_method_name;
188 std::transform(sensitivity_method.begin(), sensitivity_method.end(),
189 sensitivity_method.begin(),
190 [](unsigned char c) { return std::tolower(c); });
191 if (sensitivity_method == "direct") {
193 } else if (sensitivity_method == "adjoint") {
195 } else {
196 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
197 "Unknown -sensitivity_method. Use 'direct' or 'adjoint'.");
198 }
199 MOFEM_LOG("WORLD", Sev::inform)
200 << "Sensitivity method: " << sensitivity_method;
201
202 // Setup finite element problems
203 CHKERR readMesh(); // Read mesh and meshsets
204 CHKERR setupProblem(); // Setup displacement field and geometry field
205 CHKERR setupAdJoint(); // Setup adjoint field for sensitivity analysis
206 CHKERR boundaryCondition(); // Apply essential boundary conditions
207 CHKERR assembleSystem(); // Setup finite element operators
208
209 // Create linear solver for elastic problem
210 auto pip = mField.getInterface<PipelineManager>();
211 kspElastic = pip->createKSP();
212 CHKERR KSPSetFromOptions(kspElastic);
213
214 // Solve initial elastic problem
216 CHKERR postprocessElastic(-1); // Post-process initial solution
217
218 double f;
221 auto adjoint_vector = createDMVector(simple->getDM());
222 auto dJ_du = createDMVector(simple->getDM());
223 CHKERR calculateGradient(&f, g, adjoint_vector, dJ_du);
224 MOFEM_LOG("WORLD", Sev::inform) << "Objective function value: " << f;
225
226 auto grad = createDMVector(simple->getDM());
227 CHKERR DMoFEMMeshToLocalVector(adjointDM, g, INSERT_VALUES, SCATTER_REVERSE,
229 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
230 simple->getProblemName(), "U", "ADJOINT_FIELD", RowColData::ROW, grad,
231 INSERT_VALUES, SCATTER_FORWARD);
232 CHKERR postprocessElastic(0, grad, adjoint_vector,
233 dJ_du); // Post-process initial solution
234
236
237 // Optimization complete - results available in solution vectors
238 MOFEM_LOG("WORLD", Sev::inform) << "Topology optimization completed";
239
241};
242//! [Run problem]
243
244//! [Read mesh]
245/**
246 * @brief Read mesh from file and setup material/boundary condition meshsets
247 *
248 * This function loads the finite element mesh from file and processes
249 * associated meshsets that define material properties and boundary conditions.
250 * The mesh is typically generated using CUBIT and exported in .h5m format.
251 *
252 * Meshsets are used to group elements/faces by:
253 * - Material properties (for different material blocks)
254 * - Boundary conditions (for applying loads and constraints)
255 * - Optimization regions (for topology optimization)
256 *
257 * @return MoFEMErrorCode Success or error code
258 */
262 CHKERR simple->getOptions(); // Read command line options
263 CHKERR simple->loadFile(); // Load mesh from file
264 // Add meshsets if config file provided
265 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
267}
268//! [Read mesh]
269
270//! [Set up problem]
271/**
272 * @brief Setup finite element fields, approximation spaces and degrees of freedom
273 *
274 * This function configures the finite element problem by:
275 * 1. Setting up the displacement field "U" with vector approximation
276 * 2. Setting up the geometry field "GEOMETRY" for mesh deformation
277 * 3. Defining polynomial approximation order and basis functions
278 * 4. Creating degrees of freedom on mesh entities
279 *
280 * The displacement field uses H1 vector space for standard elasticity.
281 * The geometry field allows mesh modification during topology optimization.
282 * Different basis functions (Ainsworth-Legendre vs Demkowicz) can be selected.
283 *
284 * @return MoFEMErrorCode Success or error code
285 */
289
290 // Select basis functions for finite element approximation
291 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
292 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
293 PetscInt choice_base_value = AINSWORTH;
294 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
295 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
296
297 switch (choice_base_value) {
298 case AINSWORTH:
300 MOFEM_LOG("WORLD", Sev::inform)
301 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
302 break;
303 case DEMKOWICZ:
305 MOFEM_LOG("WORLD", Sev::inform)
306 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
307 break;
308 default:
309 base = LASTBASE;
310 break;
311 }
312
313 // Add finite element fields
314 /**
315 * Setup displacement field "U" - the primary unknown in elasticity
316 * This field represents displacement vector at each node/DOF
317 */
320 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &fieldOrder,
321 PETSC_NULLPTR);
322
323 /**
324 * Setup geometry field "GEOMETRY" - used for mesh deformation in optimization
325 * This field stores current nodal coordinates and can be modified
326 * during topology optimization to represent design changes
327 */
328 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
329
330 // Set polynomial approximation order for both fields
334
335 // Project higher-order geometry representation onto geometry field
336 /**
337 * For higher-order elements, this projects the exact geometry
338 * onto the geometry field to maintain curved boundaries accurately
339 */
340 auto project_ho_geometry = [&]() {
341 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
342 return mField.loop_dofs("GEOMETRY", ent_method);
343 };
344 CHKERR project_ho_geometry();
345
346 // Check if plane strain assumption should be used
347 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
348 &is_plane_strain, PETSC_NULLPTR);
349
351}
352//! [Set up problem]
353
354//! [Setup adjoint]
358
359 // Create adjoint data manager and field
360 auto create_adjoint_dm = [&]() {
361 auto adjoint_dm = createDM(mField.get_comm(), "DMMOFEM");
362
363 constexpr int adjoint_field_order = 1;
364
365 auto add_field = [&]() {
367 CHKERR mField.add_field("ADJOINT_FIELD", H1, base, SPACE_DIM);
369 SPACE_DIM - 1, "ADJOINT_FIELD");
370 for (auto tt = MBEDGE;
371 tt <= moab::CN::TypeDimensionMap[SPACE_DIM - 1].second; ++tt)
373 "ADJOINT_FIELD", adjoint_field_order);
375 "ADJOINT_FIELD", 1);
378 };
379
380 auto add_adjoint_fe_impl = [&]() {
382 CHKERR mField.add_finite_element("ADJOINT_DOMAIN_FE");
384 "ADJOINT_FIELD");
386 "U");
388 "ADJOINT_FIELD");
390 "U");
392 "GEOMETRY");
393
394 CHKERR mField.add_finite_element("ADJOINT_BOUNDARY_FE");
396 "ADJOINT_FIELD");
398 "U");
400 "ADJOINT_FIELD");
402 "U");
404 "GEOMETRY");
405
407 simple->getMeshset(), SPACE_DIM, "ADJOINT_DOMAIN_FE");
409 simple->getBoundaryMeshSet(), SPACE_DIM - 1, "ADJOINT_BOUNDARY_FE");
410 CHKERR mField.build_finite_elements("ADJOINT_DOMAIN_FE");
411 CHKERR mField.build_finite_elements("ADJOINT_BOUNDARY_FE");
412
415
417 };
418
419 auto set_adjoint_dm_imp = [&]() {
421 CHKERR DMMoFEMCreateMoFEM(adjoint_dm, &mField, "ADJOINT",
424 CHKERR DMMoFEMSetDestroyProblem(adjoint_dm, PETSC_TRUE);
425 CHKERR DMSetFromOptions(adjoint_dm);
426 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_DOMAIN_FE");
427 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_BOUNDARY_FE");
428 CHKERR DMMoFEMSetSquareProblem(adjoint_dm, PETSC_FALSE);
429 CHKERR DMMoFEMSetIsPartitioned(adjoint_dm, PETSC_TRUE);
430 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
431 PETSC_TRUE;
432 CHKERR DMSetUp(adjoint_dm);
433 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
434 PETSC_FALSE;
436 };
437
438 CHK_THROW_MESSAGE(add_field(), "add adjoint field");
439 CHK_THROW_MESSAGE(add_adjoint_fe_impl(), "add adjoint fe");
440 CHK_THROW_MESSAGE(set_adjoint_dm_imp(), "set adjoint dm");
441
442 return adjoint_dm;
443 };
444
445 adjointDM = create_adjoint_dm();
446
448}
449//! [Setup adjoint]
450
451//! [Boundary condition]
455 auto bc_mng = mField.getInterface<BcManager>();
456
457 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
458 "U", 0, 0);
459 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
460 "U", 1, 1);
461 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
462 "U", 2, 2);
463 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
464 "REMOVE_ALL", "U", 0, 3);
465 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
466 simple->getProblemName(), "U");
467
468 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_X",
469 "ADJOINT_FIELD", 0, 0);
470 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Y",
471 "ADJOINT_FIELD", 1, 1);
472 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Z",
473 "ADJOINT_FIELD", 2, 2);
474 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_ALL",
475 "ADJOINT_FIELD", 0, 3);
476 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_X", "ADJOINT_FIELD",
477 0, 0);
478 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Y", "ADJOINT_FIELD",
479 1, 1);
480 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Z", "ADJOINT_FIELD",
481 2, 2);
482 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_ALL",
483 "ADJOINT_FIELD", 0, 3);
484
486}
487//! [Boundary condition]
488
489//! [Push operators to pipeline]
492 auto pip = mField.getInterface<PipelineManager>();
493
494 //! [Integration rule]
495 auto integration_rule = [](int, int, int approx_order) {
496 return 2 * approx_order + 1;
497 };
498
499 auto integration_rule_bc = [](int, int, int approx_order) {
500 return 2 * approx_order + 1;
501 };
502
504 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
505 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
506 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
507 //! [Integration rule]
508
510 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
512 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
514 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
516 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
517
518 //! [Push domain stiffness matrix to pipeline]
519 // Add LHS operator for elasticity (stiffness matrix)
520 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
521 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
522 //! [Push domain stiffness matrix to pipeline]
523
524 // Add RHS operator for internal forces
525 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
526 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
527
528 //! [Push Body forces]
530 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
531 //! [Push Body forces]
532
533 //! [Push natural boundary conditions]
534 // Add force boundary condition
536 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
537 // Add case for mix type of BCs
539 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::noisy);
540 //! [Push natural boundary conditions]
542}
543//! [Push operators to pipeline]
544
545//! [Solve]
549 auto dm = simple->getDM();
550 auto f = createDMVector(dm);
551 auto d = vectorDuplicate(f);
552 CHKERR VecZeroEntries(d);
553 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
554
555 auto set_essential_bc = [&]() {
557 // This is low level pushing finite elements (pipelines) to solver
558
559 auto ksp_ctx_ptr = getDMKspCtx(dm);
560 auto pre_proc_rhs = boost::make_shared<FEMethod>();
561 auto post_proc_rhs = boost::make_shared<FEMethod>();
562 auto post_proc_lhs = boost::make_shared<FEMethod>();
563
564 auto get_pre_proc_hook = [&]() {
566 {});
567 };
568 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
569
570 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
572
574 post_proc_rhs, 1.)();
576 };
577
578 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
580
582 post_proc_lhs, 1.)();
584 };
585
586 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
587 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
588
589 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
590 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
591 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
593 };
594
595 auto setup_and_solve = [&](auto solver) {
597 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
598 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp";
599 CHKERR KSPSetUp(solver);
600 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp <= Done";
601 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve";
602 CHKERR KSPSolve(solver, f, d);
603 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve <= Done";
605 };
606
607 MOFEM_LOG_CHANNEL("TIMER");
608 MOFEM_LOG_TAG("TIMER", "timer");
609
610 CHKERR set_essential_bc();
611 CHKERR setup_and_solve(kspElastic);
612
613 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
614 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
615 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
616
617 auto evaluate_field_at_the_point = [&]() {
619
620 int coords_dim = 3;
621 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
622 PetscBool do_eval_field = PETSC_FALSE;
623 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
624 field_eval_coords.data(), &coords_dim,
626
627 if (do_eval_field) {
628
629 auto vector_field_ptr = boost::make_shared<MatrixDouble>();
630 auto field_eval_data =
631 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
632
634 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
635
636 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
637 auto no_rule = [](int, int, int) { return -1; };
638 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
639 field_eval_fe_ptr->getRuleHook = no_rule;
640
641 field_eval_fe_ptr->getOpPtrVector().push_back(
642 new OpCalculateVectorFieldValues<SPACE_DIM>("U", vector_field_ptr));
643
645 ->evalFEAtThePoint<SPACE_DIM>(
646 field_eval_coords.data(), 1e-12, simple->getProblemName(),
647 simple->getDomainFEName(), field_eval_data,
649 QUIET);
650
651 if (vector_field_ptr->size1()) {
652 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vector_field_ptr);
653 if constexpr (SPACE_DIM == 2)
654 MOFEM_LOG("FieldEvaluator", Sev::inform)
655 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
656 else
657 MOFEM_LOG("FieldEvaluator", Sev::inform)
658 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
659 << " U_Z: " << t_disp(2);
660 }
661
663 }
665 };
666
667 CHKERR evaluate_field_at_the_point();
668
670}
671//! [Solve]
672
673//! [Postprocess results]
675 SmartPetscObj<Vec> gradient_vector,
676 SmartPetscObj<Vec> adjoint_vector,
677 SmartPetscObj<Vec> dJ_du) {
680 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
681 if (gradient_vector) {
682 additional_vecs.emplace_back("GRADIENT", gradient_vector);
683 }
684 if (adjoint_vector) {
685 additional_vecs.emplace_back("ADJOINT", adjoint_vector);
686 }
687 if (dJ_du) {
688 additional_vecs.emplace_back("dJ_dU", dJ_du);
689 }
693 "out_elastic_" + std::to_string(iter) + ".h5m", additional_vecs,
694 {}, Sev::noisy);
696}
697//! [Postprocess results]
698
700
701struct OpStateSensitivity : public DomainBaseOp {
704 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
705 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
706 boost::shared_ptr<MatrixDouble> u_ptr)
707 : OP(field_name, field_name, DomainEleOp::OPROW), pythonPtr(python_ptr),
708 commPtr(comm_ptr), uPtr(u_ptr) {}
709
716
717 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
718 auto nb_gauss_pts = getGaussPts().size2();
719
720 auto objective_dstress =
721 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
722 auto objective_dstrain =
723 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
724 auto objective_du =
725 boost::make_shared<MatrixDouble>(nb_gauss_pts, SPACE_DIM);
726
727 auto evaluate_python = [&]() {
729 auto &coords = OP::getCoordsAtGaussPts();
730 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
731 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
732 objective_dstress);
733 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
734 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
735 objective_dstrain);
736 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
737 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
738 objective_du);
739
740 auto vol = OP::getMeasure();
741 auto t_w = OP::getFTensor0IntegrationWeight();
742
743 auto t_D =
744 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
745 auto t_row_grad = data.getFTensor1DiffN<SPACE_DIM>();
746 auto t_row_base = data.getFTensor0N();
747
748 auto t_obj_dstress =
749 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
750 auto t_obj_dstrain =
751 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
752 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
753
754 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
755 const double alpha = t_w * vol;
757 t_adjoint_stress(i, j) =
758 t_D(i, j, k, l) * t_obj_dstress(k, l) + t_obj_dstrain(i, j);
759
760 auto t_nf = OP::template getNf<SPACE_DIM>();
761 int rr = 0;
762 for (; rr != OP::nbRows / SPACE_DIM; rr++) {
763 t_nf(j) += alpha * t_row_grad(i) * t_adjoint_stress(i, j);
764 t_nf(j) += alpha * t_row_base * t_obj_du(j);
765
766 ++t_row_grad;
767 ++t_row_base;
768 ++t_nf;
769 }
770
771 for (; rr < OP::nbRowBaseFunctions; ++rr) {
772 ++t_row_grad;
773 ++t_row_base;
774 }
775 ++t_obj_dstrain;
776 ++t_obj_dstress;
777 ++t_obj_du;
778 ++t_w;
779 }
781 };
782 CHKERR evaluate_python();
784 }
785
786private:
787 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
788 boost::shared_ptr<HookeOps::CommonData> commPtr;
789 boost::shared_ptr<MatrixDouble> uPtr;
790};
793
794 OpObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
795 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
796 boost::shared_ptr<MatrixDouble> jac_ptr,
797 boost::shared_ptr<MatrixDouble> u_ptr,
798 boost::shared_ptr<double> glob_objective_ptr)
799 : OP(NOSPACE, OP::OPSPACE), pythonPtr(python_ptr), commPtr(comm_ptr),
800 jacPtr(jac_ptr), uPtr(u_ptr), globObjectivePtr(glob_objective_ptr) {}
801
802 /**
803 * @brief Compute objective function contributions at element level
804 *
805 * Evaluates Python objective function with current displacement and stress
806 * state, and accumulates global objective value and gradients.
807 */
808 MoFEMErrorCode doWork(int side, EntityType type,
811
812 auto nb_gauss_pts =
813 getGaussPts().size2(); // number of gauss points in the element
814
815 auto objective_ptr = boost::make_shared<MatrixDouble>(
816 1, nb_gauss_pts); // objective function values at gauss points
817
818 auto evaluate_python = [&]() {
820 auto &coords = OP::getCoordsAtGaussPts();
821 CHKERR pythonPtr->evalInteriorObjectiveFunction(
822 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
823 objective_ptr);
824
825 auto t_obj = getFTensor0FromMat(*objective_ptr);
826
827 auto vol = OP::getMeasure();
828 auto t_w = getFTensor0IntegrationWeight();
829 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
830
831 auto alpha = t_w * vol;
832 (*globObjectivePtr) += alpha * t_obj;
833
834 ++t_w;
835
836 ++t_obj;
837 }
839 };
840
841 CHKERR evaluate_python();
842
844 }
845
846private:
847 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
848 boost::shared_ptr<HookeOps::CommonData> commPtr;
849 boost::shared_ptr<MatrixDouble> jacPtr;
850 boost::shared_ptr<MatrixDouble> uPtr;
851 boost::shared_ptr<double> globObjectivePtr;
852};
853
854struct OpAdJointObjective : public DomainBaseOp {
856
857 OpAdJointObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
858 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
859 boost::shared_ptr<MatrixDouble> jac_ptr,
860 boost::shared_ptr<MatrixDouble> u_ptr,
861 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
862 boost::shared_ptr<double> glob_objective_ptr)
863 : OP("ADJOINT_FIELD", "ADJOINT_FIELD", OP::OPROW), pythonPtr(python_ptr),
864 commPtr(comm_ptr), jacPtr(jac_ptr), uPtr(u_ptr),
865 gradLambdaUPtr(grad_lambda_u_ptr),
866 globObjectivePtr(glob_objective_ptr) {}
867
868 /**
869 * @brief Compute objective function contributions at element level
870 *
871 * Evaluates Python objective function with current displacement and stress
872 * state, and accumulates global objective value and gradients.
873 */
876
877 const auto nb_gauss_pts =
878 getGaussPts().size2(); // number of gauss points in the element
879 const auto nb_dofs = data.getIndices().size();
880 const auto nb_base_funcs = data.getN().size2() / SPACE_DIM;
881
882 // Define tensor indices for calculations
887
890
891 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) /
892 2; // size of symmetric tensor in Voigt notation
893
894 auto t_diff_symm = FTensor::diff_symmetrize<double>();
895 // fourth order tensor for symmetrization to convert from gradient to strain
896
897 auto objective_ptr = boost::make_shared<MatrixDouble>(
898 1, nb_gauss_pts); // objective function values at gauss points
899 auto objective_dstress = boost::make_shared<MatrixDouble>(
900 nb_gauss_pts,
901 symm_size); // objective function gradient w.r.t. stress at gauss points
902 auto objective_dstrain = boost::make_shared<MatrixDouble>(
903 nb_gauss_pts,
904 symm_size); // objective function gradient w.r.t. strain at gauss points
905 // The dJ/du contribution is assembled separately by OpStateSensitivity.
906
907 auto evaluate_python = [&]() {
909 auto &coords = OP::getCoordsAtGaussPts();
910 CHKERR pythonPtr->evalInteriorObjectiveFunction(
911 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
912 objective_ptr);
913 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
914 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
915 objective_dstress);
916 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
917 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
918 objective_dstrain);
919
920 auto t_grad_u =
921 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
922 auto t_D =
923 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
924 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jacPtr));
925 auto t_grad_lambda_u =
926 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*gradLambdaUPtr);
927
928 auto t_obj = getFTensor0FromMat(*objective_ptr);
929 auto t_obj_dstress =
930 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
931 auto t_obj_dstrain =
932 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
933
934 auto vol = OP::getMeasure();
935 auto t_w = getFTensor0IntegrationWeight();
936 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
937 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
938 auto alpha = t_w * vol;
939 (*globObjectivePtr) += alpha * t_obj;
940
941 auto t_det = determinantTensor(t_jac);
943 CHKERR invertTensor(t_jac, t_det, t_inv_jac);
944
946 t_diff_inv_jac;
947 t_diff_inv_jac(i, j, I, J) =
948 -t_inv_jac(i, I) * t_inv_jac(J, j);
950 t_diff_grad;
951 t_diff_grad(i, j, I, J) = t_grad_u(i, k) * t_diff_inv_jac(k, j, I, J);
953 t_d_strain;
954 t_d_strain(i, j, I, J) =
955 t_diff_symm(i, j, k, l) * t_diff_grad(k, l, I, J);
956
957 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
958 int bb = 0;
959 for (; bb != nb_dofs/ SPACE_DIM; bb++) {
960
962 t_coef(I) = (t_inv_jac(J, I) * t_base_diff(J)) * t_det;
963
964 t_local_grad_vector(I) +=
965 alpha * (
966
967 ((t_obj_dstress(k, l) * t_D(k, l, i, j)) +
968 t_obj_dstrain(i, j)) *
969 (t_d_strain(i, j, I, J) * t_base_diff(J))
970
971 +
972
973 t_obj * t_coef(I)
974
975 );
976
977 t_local_grad_vector(I) -=
978 alpha * (t_grad_lambda_u(i, j) * t_D(i, j, k, l)) *
979 (t_d_strain(k, l, I, J) * t_base_diff(J));
980
981 ++t_local_grad_vector;
982 ++t_base_diff;
983 }
984 for (; bb < nb_base_funcs; ++bb) {
985 ++t_base_diff;
986 }
987
988 ++t_w;
989 ++t_jac;
990
991 ++t_obj;
992 ++t_obj_dstress;
993 ++t_obj_dstrain;
994
995 ++t_grad_u;
996 ++t_grad_lambda_u;
997 }
999 };
1000
1001 CHKERR evaluate_python();
1002
1004 }
1005
1006private:
1007 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
1008 boost::shared_ptr<HookeOps::CommonData> commPtr;
1009 boost::shared_ptr<MatrixDouble> jacPtr;
1010 boost::shared_ptr<MatrixDouble> uPtr;
1011 boost::shared_ptr<MatrixDouble> gradLambdaUPtr;
1012
1013 boost::shared_ptr<double> globObjectivePtr;
1014};
1015
1016MoFEMErrorCode Example::calculateGradient(PetscReal *objective_function_value,
1017 Vec objective_function_gradient,
1018 Vec lambda, Vec dJ_du) {
1019 MOFEM_LOG_CHANNEL("WORLD");
1021 auto simple = mField.getInterface<Simple>();
1022 auto dm = simple->getDM();
1023
1024 auto get_essential_fe = [this]() {
1025 auto post_proc_rhs = boost::make_shared<FEMethod>();
1026 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
1029 post_proc_rhs, 0)();
1031 };
1032 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1033 return post_proc_rhs;
1034 };
1035
1036 auto get_objective_fe = [&](auto lambda_vec, auto glob_objective_ptr,
1037 auto fe_rule) {
1038 auto fe_obj = boost::make_shared<DomainEle>(mField);
1039 fe_obj->getRuleHook = fe_rule;
1040 auto &pip = fe_obj->getOpPtrVector();
1042
1043 auto jac_ptr = boost::make_shared<MatrixDouble>();
1044 auto u_ptr = boost::make_shared<MatrixDouble>();
1045 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1046
1048 "GEOMETRY", jac_ptr));
1049 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1050 auto lambda_smart_vec = SmartPetscObj<Vec>(lambda_vec, true);
1052 "U", grad_lambda_ptr, lambda_smart_vec));
1053
1054 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1055 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1056 pip.push_back(new OpAdJointObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1057 grad_lambda_ptr,
1058 glob_objective_ptr));
1059 return fe_obj;
1060 };
1061
1062 auto evaluate_objective_terms =
1063 [&](auto objective_fe, auto objective_ptr) {
1065 *objective_ptr = 0.0;
1066 CHKERR VecZeroEntries(objective_function_gradient);
1067 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1068 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1069 objective_fe->f = objective_function_gradient;
1070 CHKERR DMoFEMLoopFiniteElements(adjointDM, "ADJOINT_DOMAIN_FE",
1071 objective_fe);
1072 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1073 mField.get_comm());
1074 CHKERR VecAssemblyBegin(objective_function_gradient);
1075 CHKERR VecAssemblyEnd(objective_function_gradient);
1076 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1077 SCATTER_REVERSE);
1078 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1079 SCATTER_REVERSE);
1081 };
1082
1083 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1085 auto fe = boost::make_shared<DomainEle>(mField);
1086 fe->getRuleHook = [](int, int, int p_data) {
1087 return 2 * p_data + p_data - 1;
1088 };
1089 auto &pip = fe->getOpPtrVector();
1091 auto u_ptr = boost::make_shared<MatrixDouble>();
1092 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1093 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1094 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1095 pip.push_back(new OpStateSensitivity("U", pythonPtr, common_ptr, u_ptr));
1096 CHKERR VecZeroEntries(dJ_du);
1097 fe->f = dJ_du;
1099 CHKERR VecAssemblyBegin(dJ_du);
1100 CHKERR VecAssemblyEnd(dJ_du);
1101 auto post_proc_rhs = get_essential_fe();
1102 post_proc_rhs->f = dJ_du;
1104 post_proc_rhs.get());
1106 };
1107
1108 auto calculate_adjoint_lambda = [&]() {
1110
1111 MOFEM_LOG("WORLD", Sev::inform) << "Solving for adjoint variable lambda";
1112 CHKERR VecZeroEntries(lambda);
1113 CHKERR KSPSolveTranspose(kspElastic, dJ_du, lambda);
1114 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1115 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1117 };
1118
1119 auto fe_rule = [](int, int, int p_data) { return 2 * p_data + p_data - 1; };
1120 auto objective_ptr_value = boost::make_shared<double>(0.0);
1121 auto objective_fe = get_objective_fe(lambda, objective_ptr_value, fe_rule);
1122
1123 auto adjoint = [&]() {
1125
1126 CHKERR calculate_variance_of_objective_function_dJ_du();
1127 CHKERR calculate_adjoint_lambda();
1128 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1129 *objective_function_value = *objective_ptr_value;
1130
1131 MOFEM_LOG("WORLD", Sev::verbose)
1132 << "Objective function: " << *objective_function_value;
1133
1134 CHKERR VecAssemblyBegin(objective_function_gradient);
1135 CHKERR VecAssemblyEnd(objective_function_gradient);
1136 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1137 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1138
1140 };
1141
1142 switch (derivative_type) {
1143
1144 case ADJOINT:
1145 MOFEM_LOG("WORLD", Sev::inform) << "Running Adjoint Sensitivity...";
1146 CHKERR adjoint();
1147 break;
1148
1149 default:
1150 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1151 "Wrong sensitivity type selected");
1152 }
1153
1154 CHKERR VecAssemblyBegin(objective_function_gradient);
1155 CHKERR VecAssemblyEnd(objective_function_gradient);
1156
1158}
1159//! [calculateGradient]
1160
1161//! [Finite difference check]
1165
1166 CHKERR testing->addTestCommandLine("", 1, "gradient_fd", [&]() {
1168
1169 PetscInt nb_modes = 5;
1170 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR,
1171 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1172 PetscReal eps = 1e-6;
1173 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, PETSC_NULLPTR, "-gradient_fd_eps",
1174 &eps, PETSC_NULLPTR);
1175
1176 auto simple = mField.getInterface<Simple>();
1177 auto dm = simple->getDM();
1178 auto *adj_problem_ptr = getProblemPtr(adjointDM);
1179
1180 auto get_objective_fe = [&](auto glob_objective_ptr) {
1181 auto fe_obj_fe = boost::make_shared<DomainEle>(mField);
1182 fe_obj_fe->getRuleHook = [](int, int, int p_data) {
1183 return 2 * p_data + p_data - 1;
1184 };
1185 auto &pip = fe_obj_fe->getOpPtrVector();
1187 auto jac_ptr = boost::make_shared<MatrixDouble>();
1188 auto u_ptr = boost::make_shared<MatrixDouble>();
1190 "GEOMETRY", jac_ptr));
1191 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1192 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1193 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1194 pip.push_back(new OpObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1195 glob_objective_ptr));
1196 return fe_obj_fe;
1197 };
1198
1199 auto f = boost::make_shared<double>(0.);
1200 auto fe_obj = get_objective_fe(f);
1201 CacheTupleSharedPtr tmp_cache_ptr = boost::make_shared<CacheTuple>();
1203 tmp_cache_ptr);
1204
1205 auto evaluate_objective = [&](double &objective_value) {
1207 *f = 0.0;
1209 MPI_Allreduce(MPI_IN_PLACE, f.get(), 1, MPI_DOUBLE, MPI_SUM,
1210 mField.get_comm());
1211 objective_value = *f;
1213 };
1214
1215 auto &adj_dofs =
1216 adj_problem_ptr->getNumeredRowDofsPtr()->get<PetscGlobalIdx_mi_tag>();
1217 auto &dofs = mField.get_dofs()->get<Unique_mi_tag>();
1218 auto geometry_bit_number = mField.get_field_bit_number("GEOMETRY");
1219
1220 // Returns the geometry DOF perturbed by adjoint DOF "mode" on this rank,
1221 // or nullptr when the entity is not present locally. Every rank still
1222 // takes part in the collective solves below.
1223 auto get_geometry_dof = [&](PetscInt mode) -> const DofEntity * {
1224 auto a_dof = adj_dofs.find(mode);
1225 if (a_dof == adj_dofs.end())
1226 return nullptr;
1228 (*a_dof)->getEntDofIdx(),
1229 FieldEntity::getLocalUniqueIdCalculate(geometry_bit_number,
1230 (*a_dof)->getEnt()));
1231 auto dof = dofs.find(uid);
1232 return dof != dofs.end() ? dof->get() : nullptr;
1233 };
1234
1235 auto solve_and_evaluate = [&](const DofEntity *dof, double geom_val,
1236 double &objective_value) {
1238 if (dof)
1239 dof->getFieldData() = geom_val;
1240 CHKERR KSPReset(kspElastic);
1242 CHKERR evaluate_objective(objective_value);
1244 };
1245
1246 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1247 auto dof = get_geometry_dof(mode);
1248 const double org_geom_val = dof ? dof->getFieldData() : 0.;
1249
1250 double f_plus, f_minus;
1251 CHKERR solve_and_evaluate(dof, org_geom_val + eps, f_plus);
1252 CHKERR solve_and_evaluate(dof, org_geom_val - eps, f_minus);
1253 if (dof)
1254 dof->getFieldData() = org_geom_val;
1255 const double finite_diff_grad = (f_plus - f_minus) / (2 * eps);
1256
1257 // The adjoint gradient entry lives on the owning rank only; share it so
1258 // the collective check below sees one value everywhere.
1259 double owner_data[2] = {0., 0.};
1260 auto a_dof = adj_dofs.find(mode);
1261 if (a_dof != adj_dofs.end() && (*a_dof)->getHasLocalIndex()) {
1262 const double *g_array;
1263 CHKERR VecGetArrayRead(gradient_vector, &g_array);
1264 owner_data[0] = g_array[(*a_dof)->getPetscLocalDofIdx()];
1265 owner_data[1] = 1.;
1266 CHKERR VecRestoreArrayRead(gradient_vector, &g_array);
1267 }
1268 CHKERR MPI_Allreduce(MPI_IN_PLACE, owner_data, 2, MPI_DOUBLE, MPI_SUM,
1269 mField.get_comm());
1270 if (owner_data[1] == 0.)
1272 "Adjoint DOF for mode %d not found on any rank", mode);
1273 const double adjoint_grad = owner_data[0] / owner_data[1];
1274
1275 MOFEM_LOG("WORLD", Sev::inform)
1276 << "Mode: " << mode << ", Adjoint gradient: " << adjoint_grad
1277 << ", Finite difference gradient: " << finite_diff_grad;
1278 CHKERR testing->checkValue<TestType::DERIVATIVE>(
1279 "gradient mode " + std::to_string(mode), adjoint_grad,
1280 finite_diff_grad, {0., 1e-4});
1281 }
1282
1284 });
1285
1286 CHKERR testing->runTests();
1287
1289}
1290//! [Finite difference check]
1291
1292static char help[] = "...\n\n";
1293
1294int main(int argc, char *argv[]) {
1295
1296 // Initialize Python environment for objective function interface
1297 Py_Initialize();
1298 np::initialize();
1299
1300 // Initialize MoFEM/PETSc and MOAB data structures
1301 const char param_file[] = "param_file.petsc";
1302 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1303
1304 auto core_log = logging::core::get();
1305 core_log->add_sink(
1307
1308 core_log->add_sink(
1309 LogManager::createSink(LogManager::getStrmSync(), "FieldEvaluator"));
1310 LogManager::setLog("FieldEvaluator");
1311 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
1312
1313 try {
1314
1315 //! [Register MoFEM discrete manager in PETSc]
1316 DMType dm_name = "DMMOFEM";
1317 CHKERR DMRegister_MoFEM(dm_name);
1318 DMType dm_name_mg = "DMMOFEM_MG";
1320 //! [Register MoFEM discrete manager in PETSc
1321
1322 //! [Create MoAB]
1323 moab::Core mb_instance; ///< mesh database
1324 moab::Interface &moab = mb_instance; ///< mesh database interface
1325 //! [Create MoAB]
1326
1327 //! [Create MoFEM]
1328 MoFEM::Core core(moab); ///< finite element database
1329 MoFEM::Interface &m_field = core; ///< finite element database interface
1330 //! [Create MoFEM]
1331
1332 //! [Example]
1333
1334 Example ex(m_field);
1335 CHKERR ex.runProblem();
1336 //! [Example]
1337 }
1339
1341
1342 if (Py_FinalizeEx() < 0) {
1343 exit(120);
1344 }
1345}
1346
1348 const std::string block_name, int dim) {
1349 Range r;
1350
1351 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
1352 auto bcs = mesh_mng->getCubitMeshsetPtr(
1353
1354 std::regex((boost::format("%s(.*)") % block_name).str())
1355
1356 );
1357
1358 for (auto bc : bcs) {
1359 Range faces;
1360 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
1361 faces, true),
1362 "get meshset ents");
1363 r.merge(faces);
1364 }
1365
1366 for (auto dd = dim - 1; dd >= 0; --dd) {
1367 if (dd >= 0) {
1368 Range ents;
1369 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(r, dd, false, ents,
1370 moab::Interface::UNION),
1371 "get adjs");
1372 r.merge(ents);
1373 } else {
1374 Range verts;
1375 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(r, verts),
1376 "get verts");
1377 r.merge(verts);
1378 }
1380 m_field.getInterface<CommInterface>()->synchroniseEntities(r), "comm");
1381 }
1382
1383 return r;
1384};
1385
1386MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
1387 const Range r) {
1389 auto out_meshset = get_temp_meshset_ptr(moab);
1390 CHKERR moab.add_entities(*out_meshset, r);
1391 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
1393};
Calculate traction for linear problem.
Implementation of elastic spring bc.
Natural boundary condition applying pressure from fluid.
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
std::string type
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
std::string name
SensitivityMethod
Definition adjoint.cpp:107
int main()
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
@ QUIET
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ 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.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
auto integration_rule
static char help[]
[Finite difference check]
PetscBool is_plane_strain
Definition gradient.cpp:37
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle
Domain finite elements.
Definition gradient.cpp:45
constexpr int SPACE_DIM
[Define dimension]
Definition gradient.cpp:19
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
Definition gradient.cpp:88
SensitivityMethod derivative_type
Definition gradient.cpp:96
constexpr double poisson_ratio
Poisson's ratio ν
Definition gradient.cpp:30
constexpr int BASE_DIM
[Constants and material properties]
Definition gradient.cpp:16
constexpr double shear_modulus_G
Shear modulus G = E/(2(1+ν))
Definition gradient.cpp:34
constexpr IntegrationType I
Use Gauss quadrature for integration.
Definition gradient.cpp:25
constexpr double bulk_modulus_K
Bulk modulus K = E/(3(1-2ν))
Definition gradient.cpp:31
@ DIRECT
Definition gradient.cpp:94
@ ADJOINT
Definition gradient.cpp:94
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
Definition gradient.cpp:699
constexpr AssemblyType A
[Define dimension]
Definition gradient.cpp:23
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
Boundary finite elements.
Definition gradient.cpp:47
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
constexpr double young_modulus
[Material properties for linear elasticity]
Definition gradient.cpp:29
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1142
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:517
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:479
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:143
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:575
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:543
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:605
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1250
virtual const DofEntity_multiIndex * get_dofs() const =0
Get the dofs object.
virtual MoFEMErrorCode add_ents_to_finite_element_by_dim(const EntityHandle entities, const int dim, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
PetscBool testing
const double c
speed of light (cm/ns)
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
MoFEMErrorCode postProcessElasticResults(MoFEM::Interface &mField, SmartPetscObj< DM > dm, const std::string &domain_fe_name, const std::string &out_file_name, std::vector< std::pair< std::string, SmartPetscObj< Vec > > > extra_vectors={}, const std::vector< std::string > &tags_to_transfer={}, const Sev hooke_ops_sev=Sev::verbose)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:463
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
Definition DMMoFEM.hpp:1264
static MoFEMErrorCode invertTensor(FTensor::Tensor2< T1, DIM, DIM > &t, T2 &det, FTensor::Tensor2< T3, DIM, DIM > &inv_t)
static auto determinantTensor(FTensor::Tensor2< T, DIM, DIM > &t)
Calculate the determinant of a tensor of rank DIM.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto getFTensor0FromMat(M &data)
Get tensor rank 0 (scalar) form data vector.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
boost::shared_ptr< CacheTuple > CacheTupleSharedPtr
auto getProblemPtr(DM dm)
get problem pointer from DM
Definition DMMoFEM.hpp:1195
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string)
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:120
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62
constexpr auto field_name
static constexpr int approx_order
constexpr double g
Boundary conditions marker.
[Define entities]
Definition elastic.cpp:38
[Example]
Definition plastic.cpp:217
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Interface to Python objective function.
Definition adjoint.cpp:170
SmartPetscObj< DM > adjointDM
Data manager for adjoint problem.
Definition adjoint.cpp:168
FieldApproximationBase base
Choice of finite element basis functions.
Definition plot_base.cpp:68
Simple * simple
MoFEMErrorCode checkResults()
[Postprocess results]
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
Definition adjoint.cpp:167
int fieldOrder
Polynomial order for approximation.
Definition adjoint.cpp:164
Example(MoFEM::Interface &m_field)
Definition gradient.cpp:116
MoFEMErrorCode runProblem()
Main driver function for the optimization process.
MoFEMErrorCode calculateGradient(PetscReal *objective_function_value, Vec objective_function_gradient, Vec adjoint_vector)
Calculate objective function gradient using adjoint method.
Definition adjoint.cpp:1768
MoFEMErrorCode setupAdJoint()
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:227
MoFEMErrorCode setupProblem()
MoFEMErrorCode postprocessElastic(int iter, SmartPetscObj< Vec > adjoint_vector=nullptr)
Post-process and output results.
Definition adjoint.cpp:1368
SmartPetscObj< EPS > eps
MoFEMErrorCode solveElastic()
Solve forward elastic problem.
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
MoFEMErrorCode synchroniseEntities(Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
synchronize entity range on processors (collective)
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode cache_problem_entities(const std::string prb_name, CacheTupleWeakPtr cache_ptr)=0
Cache variables.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
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.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
keeps information about DOF on the entity
FieldData & getFieldData() const
static UId getUniqueIdCalculate(const DofIdx dof, UId ent_uid)
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
Field evaluator interface.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
int nbRows
number of dofs on rows
int nbRowBaseFunctions
number or row base functions
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
EntityHandle & getMeshset()
Get the MeshSet object.
Definition Simple.hpp:394
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
Definition Simple.cpp:191
MoFEMErrorCode addBoundaryField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on boundary.
Definition Simple.cpp:355
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
BitRefLevel & getBitRefLevelMask()
Get the BitRefLevelMask.
Definition Simple.hpp:422
MoFEMErrorCode addDataField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add data field.
Definition Simple.cpp:393
EntityHandle & getBoundaryMeshSet()
Get the BoundaryMeshSet object.
Definition Simple.hpp:401
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
Definition Simple.cpp:735
const std::string getProblemName() const
Get the Problem Name.
Definition Simple.hpp:450
const std::string getDomainFEName() const
Get the Domain FE Name.
Definition Simple.hpp:429
BitRefLevel & getBitRefLevel()
Get the BitRefLevel.
Definition Simple.hpp:415
intrusive_ptr for managing petsc objects
virtual MoFEMErrorCode addTestCommandLine(const std::string &prefix, int number, const std::string &name, TestHook hook)=0
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition adjoint.cpp:1756
ForcesAndSourcesCore::UserDataOperator OP
Definition adjoint.cpp:1594
boost::shared_ptr< double > globObjectivePtr
Definition adjoint.cpp:1764
OpAdJointObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > grad_lambda_u_ptr, boost::shared_ptr< double > glob_objective_ptr)
Definition gradient.cpp:857
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:1755
boost::shared_ptr< MatrixDouble > gradLambdaUPtr
boost::shared_ptr< MatrixDouble > uPtr
Definition adjoint.cpp:1762
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
Definition gradient.cpp:874
boost::shared_ptr< MatrixDouble > jacPtr
Definition adjoint.cpp:1757
boost::shared_ptr< double > globObjectivePtr
Definition gradient.cpp:851
ForcesAndSourcesCore::UserDataOperator OP
Definition gradient.cpp:792
boost::shared_ptr< MatrixDouble > jacPtr
Definition gradient.cpp:849
OpObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< double > glob_objective_ptr)
Definition gradient.cpp:794
boost::shared_ptr< MatrixDouble > uPtr
Definition gradient.cpp:850
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
Definition gradient.cpp:808
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition gradient.cpp:848
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition gradient.cpp:847
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition adjoint.cpp:1590
OpStateSensitivity(const std::string field_name, boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > u_ptr)
Definition gradient.cpp:703
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Class dedicated to integrate operator.
Definition gradient.cpp:710
boost::shared_ptr< MatrixDouble > uPtr
Definition adjoint.cpp:1591
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:1589
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
auto save_range