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 boost::shared_ptr<MatrixDouble> vectorFieldPtr =
125 nullptr; ///< Field values at evaluation points
126
127 // Problem setup methods
133
134 // Analysis methods
135 MoFEMErrorCode solveElastic(); ///< Solve forward elastic problem
137 int iter, SmartPetscObj<Vec> gradient_vector = nullptr,
138 SmartPetscObj<Vec> adjoint_vector = nullptr,
139 SmartPetscObj<Vec> dJ_du = nullptr); ///< Post-process and output results
140
141 /// Calculate objective function gradient using adjoint method
142 MoFEMErrorCode calculateGradient(PetscReal *objective_function_value,
143 Vec objective_function_gradient,
144 Vec adjoint_vector, Vec dJ_du);
145
146 MoFEMErrorCode testGradient(Vec gradient_vector);
147
148 // Problem configuration
149 FieldApproximationBase base; ///< Choice of finite element basis functions
150 int fieldOrder = 2; ///< Polynomial order for approximation
151
152 // Solver and data management
153 SmartPetscObj<KSP> kspElastic; ///< Linear solver for elastic problem
154 SmartPetscObj<DM> adjointDM; ///< Data manager for adjoint problem
155 boost::shared_ptr<ObjectiveFunctionData>
156 pythonPtr; ///< Interface to Python objective function
157};
158
159//! [Run topology optimization problem]
162
163 // Read objective function from Python file
164 char objective_function_file_name[255] = "objective_function.py";
166 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
167 objective_function_file_name, 255, PETSC_NULLPTR);
168
169 // Verify that the Python objective function file exists
170 auto file_exists = [](std::string myfile) {
171 std::ifstream file(myfile.c_str());
172 if (file) {
173 return true;
174 }
175 return false;
176 };
177 if (!file_exists(objective_function_file_name)) {
178 MOFEM_LOG("WORLD", Sev::error) << "Objective function file NOT found: "
179 << objective_function_file_name;
180 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "file NOT found");
181 }
182
183 // Create Python interface for objective function
184 pythonPtr = create_python_objective_function(objective_function_file_name);
185
186 char sensitivity_method_name[32] = "adjoint";
187 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
188 "-sensitivity_method", sensitivity_method_name,
189 sizeof(sensitivity_method_name), PETSC_NULLPTR);
190 std::string sensitivity_method = sensitivity_method_name;
191 std::transform(sensitivity_method.begin(), sensitivity_method.end(),
192 sensitivity_method.begin(),
193 [](unsigned char c) { return std::tolower(c); });
194 if (sensitivity_method == "direct") {
196 } else if (sensitivity_method == "adjoint") {
198 } else {
199 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
200 "Unknown -sensitivity_method. Use 'direct' or 'adjoint'.");
201 }
202 MOFEM_LOG("WORLD", Sev::inform)
203 << "Sensitivity method: " << sensitivity_method;
204
205 // Setup finite element problems
206 CHKERR readMesh(); // Read mesh and meshsets
207 CHKERR setupProblem(); // Setup displacement field and geometry field
208 CHKERR setupAdJoint(); // Setup adjoint field for sensitivity analysis
209 CHKERR boundaryCondition(); // Apply essential boundary conditions
210 CHKERR assembleSystem(); // Setup finite element operators
211
212 // Create linear solver for elastic problem
213 auto pip = mField.getInterface<PipelineManager>();
214 kspElastic = pip->createKSP();
215 CHKERR KSPSetFromOptions(kspElastic);
216
217 // Solve initial elastic problem
219 CHKERR postprocessElastic(-1); // Post-process initial solution
220
221 double f;
222 auto g = createDMVector(adjointDM);
224 auto adjoint_vector = createDMVector(simple->getDM());
225 auto dJ_du = createDMVector(simple->getDM());
226 CHKERR calculateGradient(&f, g, adjoint_vector, dJ_du);
227 MOFEM_LOG("WORLD", Sev::inform) << "Objective function value: " << f;
228
229 auto grad = createDMVector(simple->getDM());
230 CHKERR DMoFEMMeshToLocalVector(adjointDM, g, INSERT_VALUES, SCATTER_REVERSE);
231 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
232 simple->getProblemName(), "U", "ADJOINT_FIELD", RowColData::ROW, grad,
233 INSERT_VALUES, SCATTER_FORWARD);
234 CHKERR postprocessElastic(0, grad, adjoint_vector,
235 dJ_du); // Post-process initial solution
236
237 // Testing gradient
239
240 // Optimization complete - results available in solution vectors
241 MOFEM_LOG("WORLD", Sev::inform) << "Topology optimization completed";
242
244};
245//! [Run problem]
246
247//! [Read mesh]
248/**
249 * @brief Read mesh from file and setup material/boundary condition meshsets
250 *
251 * This function loads the finite element mesh from file and processes
252 * associated meshsets that define material properties and boundary conditions.
253 * The mesh is typically generated using CUBIT and exported in .h5m format.
254 *
255 * Meshsets are used to group elements/faces by:
256 * - Material properties (for different material blocks)
257 * - Boundary conditions (for applying loads and constraints)
258 * - Optimization regions (for topology optimization)
259 *
260 * @return MoFEMErrorCode Success or error code
261 */
265 CHKERR simple->getOptions(); // Read command line options
266 CHKERR simple->loadFile(); // Load mesh from file
267 // Add meshsets if config file provided
268 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
270}
271//! [Read mesh]
272
273//! [Set up problem]
274/**
275 * @brief Setup finite element fields, approximation spaces and degrees of freedom
276 *
277 * This function configures the finite element problem by:
278 * 1. Setting up the displacement field "U" with vector approximation
279 * 2. Setting up the geometry field "GEOMETRY" for mesh deformation
280 * 3. Defining polynomial approximation order and basis functions
281 * 4. Creating degrees of freedom on mesh entities
282 *
283 * The displacement field uses H1 vector space for standard elasticity.
284 * The geometry field allows mesh modification during topology optimization.
285 * Different basis functions (Ainsworth-Legendre vs Demkowicz) can be selected.
286 *
287 * @return MoFEMErrorCode Success or error code
288 */
292
293 // Select basis functions for finite element approximation
294 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
295 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
296 PetscInt choice_base_value = AINSWORTH;
297 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
298 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
299
300 switch (choice_base_value) {
301 case AINSWORTH:
303 MOFEM_LOG("WORLD", Sev::inform)
304 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
305 break;
306 case DEMKOWICZ:
308 MOFEM_LOG("WORLD", Sev::inform)
309 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
310 break;
311 default:
312 base = LASTBASE;
313 break;
314 }
315
316 // Add finite element fields
317 /**
318 * Setup displacement field "U" - the primary unknown in elasticity
319 * This field represents displacement vector at each node/DOF
320 */
323 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &fieldOrder,
324 PETSC_NULLPTR);
325
326 /**
327 * Setup geometry field "GEOMETRY" - used for mesh deformation in optimization
328 * This field stores current nodal coordinates and can be modified
329 * during topology optimization to represent design changes
330 */
331 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
332
333 // Set polynomial approximation order for both fields
337
338 // Project higher-order geometry representation onto geometry field
339 /**
340 * For higher-order elements, this projects the exact geometry
341 * onto the geometry field to maintain curved boundaries accurately
342 */
343 auto project_ho_geometry = [&]() {
344 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
345 return mField.loop_dofs("GEOMETRY", ent_method);
346 };
347 CHKERR project_ho_geometry();
348
349 // Check if plane strain assumption should be used
350 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
351 &is_plane_strain, PETSC_NULLPTR);
352
354}
355//! [Set up problem]
356
357//! [Setup adjoint]
361
362 // Create adjoint data manager and field
363 auto create_adjoint_dm = [&]() {
364 auto adjoint_dm = createDM(mField.get_comm(), "DMMOFEM");
365
366 constexpr int adjoint_field_order = 1;
367
368 auto add_field = [&]() {
370 CHKERR mField.add_field("ADJOINT_FIELD", H1, base, SPACE_DIM);
372 SPACE_DIM - 1, "ADJOINT_FIELD");
373 for (auto tt = MBEDGE;
374 tt <= moab::CN::TypeDimensionMap[SPACE_DIM - 1].second; ++tt)
376 "ADJOINT_FIELD", adjoint_field_order);
378 "ADJOINT_FIELD", 1);
381 };
382
383 auto add_adjoint_fe_impl = [&]() {
385 CHKERR mField.add_finite_element("ADJOINT_DOMAIN_FE");
387 "ADJOINT_FIELD");
389 "U");
391 "ADJOINT_FIELD");
393 "U");
395 "GEOMETRY");
396
397 CHKERR mField.add_finite_element("ADJOINT_BOUNDARY_FE");
399 "ADJOINT_FIELD");
401 "U");
403 "ADJOINT_FIELD");
405 "U");
407 "GEOMETRY");
408
410 simple->getMeshset(), SPACE_DIM, "ADJOINT_DOMAIN_FE");
412 simple->getBoundaryMeshSet(), SPACE_DIM - 1, "ADJOINT_BOUNDARY_FE");
413 CHKERR mField.build_finite_elements("ADJOINT_DOMAIN_FE");
414 CHKERR mField.build_finite_elements("ADJOINT_BOUNDARY_FE");
415
418
420 };
421
422 auto set_adjoint_dm_imp = [&]() {
424 CHKERR DMMoFEMCreateMoFEM(adjoint_dm, &mField, "ADJOINT",
427 CHKERR DMMoFEMSetDestroyProblem(adjoint_dm, PETSC_TRUE);
428 CHKERR DMSetFromOptions(adjoint_dm);
429 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_DOMAIN_FE");
430 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_BOUNDARY_FE");
431 CHKERR DMMoFEMSetSquareProblem(adjoint_dm, PETSC_FALSE);
432 CHKERR DMMoFEMSetIsPartitioned(adjoint_dm, PETSC_TRUE);
433 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
434 PETSC_TRUE;
435 CHKERR DMSetUp(adjoint_dm);
436 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
437 PETSC_FALSE;
439 };
440
441 CHK_THROW_MESSAGE(add_field(), "add adjoint field");
442 CHK_THROW_MESSAGE(add_adjoint_fe_impl(), "add adjoint fe");
443 CHK_THROW_MESSAGE(set_adjoint_dm_imp(), "set adjoint dm");
444
445 return adjoint_dm;
446 };
447
448 adjointDM = create_adjoint_dm();
449
451}
452//! [Setup adjoint]
453
454//! [Boundary condition]
458 auto bc_mng = mField.getInterface<BcManager>();
459
460 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
461 "U", 0, 0);
462 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
463 "U", 1, 1);
464 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
465 "U", 2, 2);
466 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
467 "REMOVE_ALL", "U", 0, 3);
468 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
469 simple->getProblemName(), "U");
470
471 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_X",
472 "ADJOINT_FIELD", 0, 0);
473 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Y",
474 "ADJOINT_FIELD", 1, 1);
475 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Z",
476 "ADJOINT_FIELD", 2, 2);
477 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_ALL",
478 "ADJOINT_FIELD", 0, 3);
479 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_X", "ADJOINT_FIELD",
480 0, 0);
481 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Y", "ADJOINT_FIELD",
482 1, 1);
483 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Z", "ADJOINT_FIELD",
484 2, 2);
485 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_ALL",
486 "ADJOINT_FIELD", 0, 3);
487
489}
490//! [Boundary condition]
491
492//! [Push operators to pipeline]
495 auto pip = mField.getInterface<PipelineManager>();
496
497 //! [Integration rule]
498 auto integration_rule = [](int, int, int approx_order) {
499 return 2 * approx_order + 1;
500 };
501
502 auto integration_rule_bc = [](int, int, int approx_order) {
503 return 2 * approx_order + 1;
504 };
505
507 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
508 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
509 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
510 //! [Integration rule]
511
513 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
515 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
517 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
519 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
520
521 //! [Push domain stiffness matrix to pipeline]
522 // Add LHS operator for elasticity (stiffness matrix)
523 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
524 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
525 //! [Push domain stiffness matrix to pipeline]
526
527 // Add RHS operator for internal forces
528 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
529 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
530
531 //! [Push Body forces]
533 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
534 //! [Push Body forces]
535
536 //! [Push natural boundary conditions]
537 // Add force boundary condition
539 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
540 // Add case for mix type of BCs
542 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::noisy);
543 //! [Push natural boundary conditions]
545}
546//! [Push operators to pipeline]
547
548//! [Solve]
552 auto dm = simple->getDM();
553 auto f = createDMVector(dm);
554 auto d = vectorDuplicate(f);
555 CHKERR VecZeroEntries(d);
556 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
557
558 auto set_essential_bc = [&]() {
560 // This is low level pushing finite elements (pipelines) to solver
561
562 auto ksp_ctx_ptr = getDMKspCtx(dm);
563 auto pre_proc_rhs = boost::make_shared<FEMethod>();
564 auto post_proc_rhs = boost::make_shared<FEMethod>();
565 auto post_proc_lhs = boost::make_shared<FEMethod>();
566
567 auto get_pre_proc_hook = [&]() {
569 {});
570 };
571 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
572
573 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
575
577 post_proc_rhs, 1.)();
579 };
580
581 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
583
585 post_proc_lhs, 1.)();
587 };
588
589 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
590 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
591
592 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
593 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
594 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
596 };
597
598 auto setup_and_solve = [&](auto solver) {
600 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
601 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp";
602 CHKERR KSPSetUp(solver);
603 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp <= Done";
604 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve";
605 CHKERR KSPSolve(solver, f, d);
606 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve <= Done";
608 };
609
610 MOFEM_LOG_CHANNEL("TIMER");
611 MOFEM_LOG_TAG("TIMER", "timer");
612
613 CHKERR set_essential_bc();
614 CHKERR setup_and_solve(kspElastic);
615
616 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
617 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
618 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
619
620 auto evaluate_field_at_the_point = [&]() {
622
623 int coords_dim = 3;
624 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
625 PetscBool do_eval_field = PETSC_FALSE;
626 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
627 field_eval_coords.data(), &coords_dim,
629
630 if (do_eval_field) {
631
632 vectorFieldPtr = boost::make_shared<MatrixDouble>();
633 auto field_eval_data =
634 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
635
637 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
638
639 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
640 auto no_rule = [](int, int, int) { return -1; };
641 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
642 field_eval_fe_ptr->getRuleHook = no_rule;
643
644 field_eval_fe_ptr->getOpPtrVector().push_back(
646
648 ->evalFEAtThePoint<SPACE_DIM>(
649 field_eval_coords.data(), 1e-12, simple->getProblemName(),
650 simple->getDomainFEName(), field_eval_data,
652 QUIET);
653
654 if (vectorFieldPtr->size1()) {
655 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
656 if constexpr (SPACE_DIM == 2)
657 MOFEM_LOG("FieldEvaluator", Sev::inform)
658 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
659 else
660 MOFEM_LOG("FieldEvaluator", Sev::inform)
661 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
662 << " U_Z: " << t_disp(2);
663 }
664
666 }
668 };
669
670 CHKERR evaluate_field_at_the_point();
671
673}
674//! [Solve]
675
676//! [Postprocess results]
678 SmartPetscObj<Vec> gradient_vector,
679 SmartPetscObj<Vec> adjoint_vector,
680 SmartPetscObj<Vec> dJ_du) {
683 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
684 if (gradient_vector) {
685 additional_vecs.emplace_back("GRADIENT", gradient_vector);
686 }
687 if (adjoint_vector) {
688 additional_vecs.emplace_back("ADJOINT", adjoint_vector);
689 }
690 if (dJ_du) {
691 additional_vecs.emplace_back("dJ_dU", dJ_du);
692 }
696 "out_elastic_" + std::to_string(iter) + ".h5m", additional_vecs,
697 {}, Sev::noisy);
699}
700//! [Postprocess results]
701
703
704
705template <int DIM> inline auto diff_symmetrize(FTensor::Number<DIM>) {
706
707 FTensor::Index<'i', DIM> i;
708 FTensor::Index<'j', DIM> j;
709 FTensor::Index<'k', DIM> k;
710 FTensor::Index<'l', DIM> l;
711
713
714 t_diff(i, j, k, l) = 0;
715 t_diff(0, 0, 0, 0) = 1;
716 t_diff(1, 1, 1, 1) = 1;
717
718 t_diff(1, 0, 1, 0) = 0.5;
719 t_diff(1, 0, 0, 1) = 0.5;
720
721 t_diff(0, 1, 0, 1) = 0.5;
722 t_diff(0, 1, 1, 0) = 0.5;
723
724 if constexpr (DIM == 3) {
725 t_diff(2, 2, 2, 2) = 1;
726
727 t_diff(2, 0, 2, 0) = 0.5;
728 t_diff(2, 0, 0, 2) = 0.5;
729 t_diff(0, 2, 0, 2) = 0.5;
730 t_diff(0, 2, 2, 0) = 0.5;
731
732 t_diff(2, 1, 2, 1) = 0.5;
733 t_diff(2, 1, 1, 2) = 0.5;
734 t_diff(1, 2, 1, 2) = 0.5;
735 t_diff(1, 2, 2, 1) = 0.5;
736 }
737
738 return t_diff;
739};
740
741struct OpStateSensitivity : public DomainBaseOp {
744 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
745 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
746 boost::shared_ptr<MatrixDouble> u_ptr)
747 : OP(field_name, field_name, DomainEleOp::OPROW), pythonPtr(python_ptr),
748 commPtr(comm_ptr), uPtr(u_ptr) {}
749
756
757 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
758 auto nb_gauss_pts = getGaussPts().size2();
759
760 auto objective_dstress =
761 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
762 auto objective_dstrain =
763 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
764 auto objective_du =
765 boost::make_shared<MatrixDouble>(nb_gauss_pts, SPACE_DIM);
766
767 auto evaluate_python = [&]() {
769 auto &coords = OP::getCoordsAtGaussPts();
770 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
771 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
772 objective_dstress);
773 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
774 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
775 objective_dstrain);
776 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
777 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
778 objective_du);
779
780 auto vol = OP::getMeasure();
781 auto t_w = OP::getFTensor0IntegrationWeight();
782
783 auto t_D =
784 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
785 auto t_row_grad = data.getFTensor1DiffN<SPACE_DIM>();
786 auto t_row_base = data.getFTensor0N();
787
788 auto t_obj_dstress =
789 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
790 auto t_obj_dstrain =
791 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
792 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
793
794 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
795 const double alpha = t_w * vol;
797 t_adjoint_stress(i, j) =
798 t_D(i, j, k, l) * t_obj_dstress(k, l) + t_obj_dstrain(i, j);
799
800 auto t_nf = OP::template getNf<SPACE_DIM>();
801 int rr = 0;
802 for (; rr != OP::nbRows / SPACE_DIM; rr++) {
803 t_nf(j) += alpha * t_row_grad(i) * t_adjoint_stress(i, j);
804 t_nf(j) += alpha * t_row_base * t_obj_du(j);
805
806 ++t_row_grad;
807 ++t_row_base;
808 ++t_nf;
809 }
810
811 for (; rr < OP::nbRowBaseFunctions; ++rr) {
812 ++t_row_grad;
813 ++t_row_base;
814 }
815 ++t_obj_dstrain;
816 ++t_obj_dstress;
817 ++t_obj_du;
818 ++t_w;
819 }
821 };
822 CHKERR evaluate_python();
824 }
825
826private:
827 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
828 boost::shared_ptr<HookeOps::CommonData> commPtr;
829 boost::shared_ptr<MatrixDouble> uPtr;
830};
833
834 OpObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
835 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
836 boost::shared_ptr<MatrixDouble> jac_ptr,
837 boost::shared_ptr<MatrixDouble> u_ptr,
838 boost::shared_ptr<double> glob_objective_ptr)
839 : OP(NOSPACE, OP::OPSPACE), pythonPtr(python_ptr), commPtr(comm_ptr),
840 jacPtr(jac_ptr), uPtr(u_ptr), globObjectivePtr(glob_objective_ptr) {}
841
842 /**
843 * @brief Compute objective function contributions at element level
844 *
845 * Evaluates Python objective function with current displacement and stress
846 * state, and accumulates global objective value and gradients.
847 */
848 MoFEMErrorCode doWork(int side, EntityType type,
851
852 auto nb_gauss_pts =
853 getGaussPts().size2(); // number of gauss points in the element
854
855 auto objective_ptr = boost::make_shared<MatrixDouble>(
856 1, nb_gauss_pts); // objective function values at gauss points
857
858 auto evaluate_python = [&]() {
860 auto &coords = OP::getCoordsAtGaussPts();
861 CHKERR pythonPtr->evalInteriorObjectiveFunction(
862 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
863 objective_ptr);
864
865 auto t_obj = getFTensor0FromMat(*objective_ptr);
866
867 auto vol = OP::getMeasure();
868 auto t_w = getFTensor0IntegrationWeight();
869 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
870
871 auto alpha = t_w * vol;
872 (*globObjectivePtr) += alpha * t_obj;
873
874 ++t_w;
875
876 ++t_obj;
877 }
879 };
880
881 CHKERR evaluate_python();
882
884 }
885
886private:
887 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
888 boost::shared_ptr<HookeOps::CommonData> commPtr;
889 boost::shared_ptr<MatrixDouble> jacPtr;
890 boost::shared_ptr<MatrixDouble> uPtr;
891 boost::shared_ptr<double> globObjectivePtr;
892};
893
894struct OpAdJointObjective : public DomainBaseOp {
896
897 OpAdJointObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
898 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
899 boost::shared_ptr<MatrixDouble> jac_ptr,
900 boost::shared_ptr<MatrixDouble> u_ptr,
901 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
902 boost::shared_ptr<double> glob_objective_ptr)
903 : OP("ADJOINT_FIELD", "ADJOINT_FIELD", OP::OPROW), pythonPtr(python_ptr),
904 commPtr(comm_ptr), jacPtr(jac_ptr), uPtr(u_ptr),
905 gradLambdaUPtr(grad_lambda_u_ptr),
906 globObjectivePtr(glob_objective_ptr) {}
907
908 /**
909 * @brief Compute objective function contributions at element level
910 *
911 * Evaluates Python objective function with current displacement and stress
912 * state, and accumulates global objective value and gradients.
913 */
916
917 const auto nb_gauss_pts =
918 getGaussPts().size2(); // number of gauss points in the element
919 const auto nb_dofs = data.getIndices().size();
920 const auto nb_base_funcs = data.getN().size2() / SPACE_DIM;
921
922 // Define tensor indices for calculations
927
930
931 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) /
932 2; // size of symmetric tensor in Voigt notation
933
934 auto t_diff_symm = diff_symmetrize(
936 SPACE_DIM>()); // fourth order tensor for symmetrization to convert from gradient to strain
937
938 auto objective_ptr = boost::make_shared<MatrixDouble>(
939 1, nb_gauss_pts); // objective function values at gauss points
940 auto objective_dstress = boost::make_shared<MatrixDouble>(
941 nb_gauss_pts,
942 symm_size); // objective function gradient w.r.t. stress at gauss points
943 auto objective_dstrain = boost::make_shared<MatrixDouble>(
944 nb_gauss_pts,
945 symm_size); // objective function gradient w.r.t. strain at gauss points
946 // The dJ/du contribution is assembled separately by OpStateSensitivity.
947
948 auto evaluate_python = [&]() {
950 auto &coords = OP::getCoordsAtGaussPts();
951 CHKERR pythonPtr->evalInteriorObjectiveFunction(
952 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
953 objective_ptr);
954 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
955 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
956 objective_dstress);
957 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
958 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
959 objective_dstrain);
960
961 auto t_grad_u =
962 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
963 auto t_D =
964 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
965 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jacPtr));
966 auto t_grad_lambda_u =
967 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*gradLambdaUPtr);
968
969 auto t_obj = getFTensor0FromMat(*objective_ptr);
970 auto t_obj_dstress =
971 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
972 auto t_obj_dstrain =
973 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
974
975 auto vol = OP::getMeasure();
976 auto t_w = getFTensor0IntegrationWeight();
977 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
978 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
979 auto alpha = t_w * vol;
980 (*globObjectivePtr) += alpha * t_obj;
981
982 auto t_det = determinantTensor(t_jac);
984 CHKERR invertTensor(t_jac, t_det, t_inv_jac);
985
987 t_diff_inv_jac;
988 t_diff_inv_jac(i, j, I, J) =
989 -t_inv_jac(i, I) * t_inv_jac(J, j);
991 t_diff_grad;
992 t_diff_grad(i, j, I, J) = t_grad_u(i, k) * t_diff_inv_jac(k, j, I, J);
994 t_d_strain;
995 t_d_strain(i, j, I, J) =
996 t_diff_symm(i, j, k, l) * t_diff_grad(k, l, I, J);
997
998 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
999 int bb = 0;
1000 for (; bb != nb_dofs/ SPACE_DIM; bb++) {
1001
1003 t_coef(I) = (t_inv_jac(J, I) * t_base_diff(J)) * t_det;
1004
1005 t_local_grad_vector(I) +=
1006 alpha * (
1007
1008 ((t_obj_dstress(k, l) * t_D(k, l, i, j)) +
1009 t_obj_dstrain(i, j)) *
1010 (t_d_strain(i, j, I, J) * t_base_diff(J))
1011
1012 +
1013
1014 t_obj * t_coef(I)
1015
1016 );
1017
1018 t_local_grad_vector(I) -=
1019 alpha * (t_grad_lambda_u(i, j) * t_D(i, j, k, l)) *
1020 (t_d_strain(k, l, I, J) * t_base_diff(J));
1021
1022 ++t_local_grad_vector;
1023 ++t_base_diff;
1024 }
1025 for (; bb < nb_base_funcs; ++bb) {
1026 ++t_base_diff;
1027 }
1028
1029 ++t_w;
1030 ++t_jac;
1031
1032 ++t_obj;
1033 ++t_obj_dstress;
1034 ++t_obj_dstrain;
1035
1036 ++t_grad_u;
1037 ++t_grad_lambda_u;
1038 }
1040 };
1041
1042 CHKERR evaluate_python();
1043
1045 }
1046
1047private:
1048 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
1049 boost::shared_ptr<HookeOps::CommonData> commPtr;
1050 boost::shared_ptr<MatrixDouble> jacPtr;
1051 boost::shared_ptr<MatrixDouble> uPtr;
1052 boost::shared_ptr<MatrixDouble> gradLambdaUPtr;
1053
1054 boost::shared_ptr<double> globObjectivePtr;
1055};
1056
1057MoFEMErrorCode Example::calculateGradient(PetscReal *objective_function_value,
1058 Vec objective_function_gradient,
1059 Vec lambda, Vec dJ_du) {
1060 MOFEM_LOG_CHANNEL("WORLD");
1062 auto simple = mField.getInterface<Simple>();
1063 auto dm = simple->getDM();
1064
1065 auto get_essential_fe = [this]() {
1066 auto post_proc_rhs = boost::make_shared<FEMethod>();
1067 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
1070 post_proc_rhs, 0)();
1072 };
1073 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1074 return post_proc_rhs;
1075 };
1076
1077 auto get_objective_fe = [&](auto lambda_vec, auto glob_objective_ptr,
1078 auto fe_rule) {
1079 auto fe_obj = boost::make_shared<DomainEle>(mField);
1080 fe_obj->getRuleHook = fe_rule;
1081 auto &pip = fe_obj->getOpPtrVector();
1083
1084 auto jac_ptr = boost::make_shared<MatrixDouble>();
1085 auto u_ptr = boost::make_shared<MatrixDouble>();
1086 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1087
1089 "GEOMETRY", jac_ptr));
1090 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1091 auto lambda_smart_vec = SmartPetscObj<Vec>(lambda_vec, true);
1093 "U", grad_lambda_ptr, lambda_smart_vec));
1094
1095 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1096 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1097 pip.push_back(new OpAdJointObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1098 grad_lambda_ptr,
1099 glob_objective_ptr));
1100 return fe_obj;
1101 };
1102
1103 auto evaluate_objective_terms =
1104 [&](auto objective_fe, auto objective_ptr) {
1106 *objective_ptr = 0.0;
1107 CHKERR VecZeroEntries(objective_function_gradient);
1108 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1109 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1110 objective_fe->f = objective_function_gradient;
1111 CHKERR DMoFEMLoopFiniteElements(adjointDM, "ADJOINT_DOMAIN_FE",
1112 objective_fe);
1113 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1114 mField.get_comm());
1115 CHKERR VecAssemblyBegin(objective_function_gradient);
1116 CHKERR VecAssemblyEnd(objective_function_gradient);
1117 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1118 SCATTER_REVERSE);
1119 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1120 SCATTER_REVERSE);
1122 };
1123
1124 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1126 auto fe = boost::make_shared<DomainEle>(mField);
1127 fe->getRuleHook = [](int, int, int p_data) {
1128 return 2 * p_data + p_data - 1;
1129 };
1130 auto &pip = fe->getOpPtrVector();
1132 auto u_ptr = boost::make_shared<MatrixDouble>();
1133 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1134 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1135 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1136 pip.push_back(new OpStateSensitivity("U", pythonPtr, common_ptr, u_ptr));
1137 CHKERR VecZeroEntries(dJ_du);
1138 fe->f = dJ_du;
1140 CHKERR VecAssemblyBegin(dJ_du);
1141 CHKERR VecAssemblyEnd(dJ_du);
1142 auto post_proc_rhs = get_essential_fe();
1143 post_proc_rhs->f = dJ_du;
1145 post_proc_rhs.get());
1147 };
1148
1149 auto calculate_adjoint_lambda = [&]() {
1151
1152 MOFEM_LOG("WORLD", Sev::inform) << "Solving for adjoint variable lambda";
1153 CHKERR VecZeroEntries(lambda);
1154 CHKERR KSPSolveTranspose(kspElastic, dJ_du, lambda);
1155 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1156 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1158 };
1159
1160 auto fe_rule = [](int, int, int p_data) { return 2 * p_data + p_data - 1; };
1161 auto objective_ptr_value = boost::make_shared<double>(0.0);
1162 auto objective_fe = get_objective_fe(lambda, objective_ptr_value, fe_rule);
1163
1164 auto adjoint = [&]() {
1166
1167 CHKERR calculate_variance_of_objective_function_dJ_du();
1168 CHKERR calculate_adjoint_lambda();
1169 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1170 *objective_function_value = *objective_ptr_value;
1171
1172 MOFEM_LOG("WORLD", Sev::verbose)
1173 << "Objective function: " << *objective_function_value;
1174
1175 CHKERR VecAssemblyBegin(objective_function_gradient);
1176 CHKERR VecAssemblyEnd(objective_function_gradient);
1177 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1178 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1179
1181 };
1182
1183 switch (derivative_type) {
1184
1185 case ADJOINT:
1186 MOFEM_LOG("WORLD", Sev::inform) << "Running Adjoint Sensitivity...";
1187 CHKERR adjoint();
1188 break;
1189
1190 default:
1191 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1192 "Wrong sensitivity type selected");
1193 }
1194
1195 CHKERR VecAssemblyBegin(objective_function_gradient);
1196 CHKERR VecAssemblyEnd(objective_function_gradient);
1197
1199}
1200//! [calculateGradient]
1201
1202//! [Finite difference check]
1205
1206 PetscBool gradient_fd_check = PETSC_FALSE;
1207 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, PETSC_NULLPTR, "-gradient_fd_check",
1208 &gradient_fd_check, PETSC_NULLPTR);
1209 if (gradient_fd_check) {
1210
1211 PetscInt nb_modes = 5;
1212 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR,
1213 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1214
1215 auto simple = mField.getInterface<Simple>();
1216 auto dm = simple->getDM();
1217 auto *adj_problem_ptr = getProblemPtr(adjointDM);
1218
1219 auto fe_rule = [](int, int, int p_data) { return 2 * p_data + p_data - 1; };
1220 auto get_objective_fe = [&](auto glob_objective_ptr, auto fe_rule) {
1221 auto fe_obj_fe = boost::make_shared<DomainEle>(mField);
1222 fe_obj_fe->getRuleHook = fe_rule;
1223 auto &pip = fe_obj_fe->getOpPtrVector();
1225 auto jac_ptr = boost::make_shared<MatrixDouble>();
1226 auto u_ptr = boost::make_shared<MatrixDouble>();
1228 "GEOMETRY", jac_ptr));
1229 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1230 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1231 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1232 pip.push_back(new OpObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1233 glob_objective_ptr));
1234 return fe_obj_fe;
1235 };
1236
1237 auto f = boost::make_shared<double>(0.);
1238 auto fe_obj = get_objective_fe(f, fe_rule);
1239 CacheTupleSharedPtr tmp_cache_ptr = boost::make_shared<CacheTuple>();
1241 tmp_cache_ptr);
1242
1243 auto evaluate_objective_terms = [&](auto objective_fe, auto objective_ptr,
1244 double &objective_value) {
1246 *objective_ptr = 0.0;
1248 objective_fe);
1249 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1250 mField.get_comm());
1251 objective_value = *objective_ptr;
1253 };
1254
1255 auto geometry_bit_number = mField.get_field_bit_number("GEOMETRY");
1256 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1257 MOFEM_LOG_CHANNEL("WORLD");
1258 MOFEM_LOG("WORLD", Sev::verbose) << "Processing mode: " << mode;
1259
1260 auto &adj_dofs =
1261 adj_problem_ptr->getNumeredRowDofsPtr()->get<PetscGlobalIdx_mi_tag>();
1262 auto &dofs = mField.get_dofs()->get<Unique_mi_tag>();
1263
1264 auto a_dof = adj_dofs.find(mode);
1265 if (a_dof != adj_dofs.end()) {
1266 auto ent = (*a_dof)->getEnt();
1267 auto dof_idx = (*a_dof)->getEntDofIdx();
1269 dof_idx,
1270 FieldEntity::getLocalUniqueIdCalculate(geometry_bit_number, ent));
1271 auto dof = dofs.find(uid);
1272 if (dof != dofs.end()) {
1273 auto org_geom_val = (*dof)->getFieldData();
1274 constexpr double eps = 1e-6;
1275
1276 (*dof)->getFieldData() = org_geom_val + eps;
1277 CHKERR KSPReset(kspElastic);
1279 double f_plus;
1280 CHKERR evaluate_objective_terms(fe_obj, f, f_plus);
1281
1282 (*dof)->getFieldData() = org_geom_val - eps;
1283 CHKERR KSPReset(kspElastic);
1285 double f_minus;
1286 CHKERR evaluate_objective_terms(fe_obj, f, f_minus);
1287
1288 double *g_array;
1289 CHKERR VecGetArray(gradient_vector, &g_array);
1290 if ((*a_dof)->getHasLocalIndex()) {
1291 auto adjoint_grad = g_array[(*a_dof)->getPetscLocalDofIdx()];
1292 auto finite_diff_grad = (f_plus - f_minus) / (2 * eps);
1293 auto err = std::abs(adjoint_grad - finite_diff_grad) /
1294 std::max(std::abs(adjoint_grad),
1295 std::abs(finite_diff_grad));
1296 MOFEM_LOG("WORLD", Sev::inform)
1297 << "Mode: " << mode << ", Adjoint gradient: " << adjoint_grad
1298 << ", Finite difference gradient: " << finite_diff_grad
1299 << ", Relative error: "
1300 << std::abs(adjoint_grad - finite_diff_grad) /
1301 std::max(std::abs(adjoint_grad),
1302 std::abs(finite_diff_grad));
1303 constexpr double tol = 1e-4;
1304 if (err > tol) {
1305 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1306 "Gradient check failed for mode %d: relative error %e is "
1307 "greater than tolerance %e",
1308 mode, err, tol);
1309 }
1310 }
1311
1312 CHKERR VecRestoreArray(gradient_vector, &g_array);
1313
1314 constexpr bool restore_solution = false;
1315 if constexpr (restore_solution) {
1316 (*dof)->getFieldData() = org_geom_val;
1317 CHKERR KSPReset(kspElastic);
1319 }
1320 }
1321 }
1322 }
1323 }
1324
1326}
1327//! [Finite difference check]
1328
1329static char help[] = "...\n\n";
1330
1331int main(int argc, char *argv[]) {
1332
1333 // Initialize Python environment for objective function interface
1334 Py_Initialize();
1335 np::initialize();
1336
1337 // Initialize MoFEM/PETSc and MOAB data structures
1338 const char param_file[] = "param_file.petsc";
1339 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1340
1341 auto core_log = logging::core::get();
1342 core_log->add_sink(
1344
1345 core_log->add_sink(
1346 LogManager::createSink(LogManager::getStrmSync(), "FieldEvaluator"));
1347 LogManager::setLog("FieldEvaluator");
1348 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
1349
1350 try {
1351
1352 //! [Register MoFEM discrete manager in PETSc]
1353 DMType dm_name = "DMMOFEM";
1354 CHKERR DMRegister_MoFEM(dm_name);
1355 DMType dm_name_mg = "DMMOFEM_MG";
1357 //! [Register MoFEM discrete manager in PETSc
1358
1359 //! [Create MoAB]
1360 moab::Core mb_instance; ///< mesh database
1361 moab::Interface &moab = mb_instance; ///< mesh database interface
1362 //! [Create MoAB]
1363
1364 //! [Create MoFEM]
1365 MoFEM::Core core(moab); ///< finite element database
1366 MoFEM::Interface &m_field = core; ///< finite element database interface
1367 //! [Create MoFEM]
1368
1369 //! [Example]
1370
1371 Example ex(m_field);
1372 CHKERR ex.runProblem();
1373 //! [Example]
1374 }
1376
1378
1379 if (Py_FinalizeEx() < 0) {
1380 exit(120);
1381 }
1382}
1383
1385 const std::string block_name, int dim) {
1386 Range r;
1387
1388 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
1389 auto bcs = mesh_mng->getCubitMeshsetPtr(
1390
1391 std::regex((boost::format("%s(.*)") % block_name).str())
1392
1393 );
1394
1395 for (auto bc : bcs) {
1396 Range faces;
1397 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
1398 faces, true),
1399 "get meshset ents");
1400 r.merge(faces);
1401 }
1402
1403 for (auto dd = dim - 1; dd >= 0; --dd) {
1404 if (dd >= 0) {
1405 Range ents;
1406 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(r, dd, false, ents,
1407 moab::Interface::UNION),
1408 "get adjs");
1409 r.merge(ents);
1410 } else {
1411 Range verts;
1412 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(r, verts),
1413 "get verts");
1414 r.merge(verts);
1415 }
1417 m_field.getInterface<CommInterface>()->synchroniseEntities(r), "comm");
1418 }
1419
1420 return r;
1421};
1422
1423MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
1424 const Range r) {
1426 auto out_meshset = get_temp_meshset_ptr(moab);
1427 CHKERR moab.add_entities(*out_meshset, r);
1428 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
1430};
std::string type
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Interface for Python-based objective function evaluation in topology optimization.
#define FTENSOR_INDEX(DIM, I)
SensitivityMethod derivative_type
Definition adjoint.cpp:109
SensitivityMethod
Definition adjoint.cpp:107
@ DIRECT
Definition adjoint.cpp:107
@ ADJOINT
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_ATOM_TEST_INVALID
Definition definitions.h:40
@ 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
auto diff_symmetrize(FTensor::Number< DIM >)
Definition gradient.cpp:705
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
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:702
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:1113
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
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:114
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
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:514
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:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
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
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
double tol
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:434
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, 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:1251
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:1182
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string py_file)
Factory function to create Python-integrated objective function interface.
constexpr auto field_name
static constexpr int approx_order
PetscBool is_plane_strain
Definition seepage.cpp:177
constexpr double g
Boundary conditions marker.
Definition elastic.cpp:39
[Define entities]
Definition elastic.cpp:38
[Example]
Definition plastic.cpp:216
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
SmartPetscObj< KSP > kspElastic
Linear solver for elastic problem.
Definition adjoint.cpp:167
MoFEMErrorCode testGradient(Vec gradient_vector)
[calculateGradient]
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:1763
MoFEMErrorCode setupAdJoint()
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:226
MoFEMErrorCode setupProblem()
MoFEMErrorCode postprocessElastic(int iter, SmartPetscObj< Vec > adjoint_vector=nullptr)
Post-process and output results.
Definition adjoint.cpp:1326
SmartPetscObj< EPS > eps
MoFEMErrorCode solveElastic()
Solve forward elastic problem.
boost::shared_ptr< MatrixDouble > vectorFieldPtr
Field values at evaluation points.
Definition adjoint.cpp:137
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
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
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
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:1751
ForcesAndSourcesCore::UserDataOperator OP
Definition adjoint.cpp:1588
boost::shared_ptr< double > globObjectivePtr
Definition adjoint.cpp:1759
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:897
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:1750
boost::shared_ptr< MatrixDouble > gradLambdaUPtr
boost::shared_ptr< MatrixDouble > uPtr
Definition adjoint.cpp:1757
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
Definition gradient.cpp:914
boost::shared_ptr< MatrixDouble > jacPtr
Definition adjoint.cpp:1752
boost::shared_ptr< double > globObjectivePtr
Definition gradient.cpp:891
ForcesAndSourcesCore::UserDataOperator OP
Definition gradient.cpp:832
boost::shared_ptr< MatrixDouble > jacPtr
Definition gradient.cpp:889
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:834
boost::shared_ptr< MatrixDouble > uPtr
Definition gradient.cpp:890
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
Definition gradient.cpp:848
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition gradient.cpp:888
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition gradient.cpp:887
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition adjoint.cpp:1584
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:743
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Definition gradient.cpp:750
boost::shared_ptr< MatrixDouble > uPtr
Definition adjoint.cpp:1585
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:1583
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
auto save_range
constexpr int SPACE_DIM
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle