v0.16.0
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;
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,
232 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
233 simple->getProblemName(), "U", "ADJOINT_FIELD", RowColData::ROW, grad,
234 INSERT_VALUES, SCATTER_FORWARD);
235 CHKERR postprocessElastic(0, grad, adjoint_vector,
236 dJ_du); // Post-process initial solution
237
238 // Testing gradient
240
241 // Optimization complete - results available in solution vectors
242 MOFEM_LOG("WORLD", Sev::inform) << "Topology optimization completed";
243
245};
246//! [Run problem]
247
248//! [Read mesh]
249/**
250 * @brief Read mesh from file and setup material/boundary condition meshsets
251 *
252 * This function loads the finite element mesh from file and processes
253 * associated meshsets that define material properties and boundary conditions.
254 * The mesh is typically generated using CUBIT and exported in .h5m format.
255 *
256 * Meshsets are used to group elements/faces by:
257 * - Material properties (for different material blocks)
258 * - Boundary conditions (for applying loads and constraints)
259 * - Optimization regions (for topology optimization)
260 *
261 * @return MoFEMErrorCode Success or error code
262 */
266 CHKERR simple->getOptions(); // Read command line options
267 CHKERR simple->loadFile(); // Load mesh from file
268 // Add meshsets if config file provided
269 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
271}
272//! [Read mesh]
273
274//! [Set up problem]
275/**
276 * @brief Setup finite element fields, approximation spaces and degrees of freedom
277 *
278 * This function configures the finite element problem by:
279 * 1. Setting up the displacement field "U" with vector approximation
280 * 2. Setting up the geometry field "GEOMETRY" for mesh deformation
281 * 3. Defining polynomial approximation order and basis functions
282 * 4. Creating degrees of freedom on mesh entities
283 *
284 * The displacement field uses H1 vector space for standard elasticity.
285 * The geometry field allows mesh modification during topology optimization.
286 * Different basis functions (Ainsworth-Legendre vs Demkowicz) can be selected.
287 *
288 * @return MoFEMErrorCode Success or error code
289 */
293
294 // Select basis functions for finite element approximation
295 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
296 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
297 PetscInt choice_base_value = AINSWORTH;
298 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
299 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
300
301 switch (choice_base_value) {
302 case AINSWORTH:
304 MOFEM_LOG("WORLD", Sev::inform)
305 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
306 break;
307 case DEMKOWICZ:
309 MOFEM_LOG("WORLD", Sev::inform)
310 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
311 break;
312 default:
313 base = LASTBASE;
314 break;
315 }
316
317 // Add finite element fields
318 /**
319 * Setup displacement field "U" - the primary unknown in elasticity
320 * This field represents displacement vector at each node/DOF
321 */
322 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
323 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
324 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &fieldOrder,
325 PETSC_NULLPTR);
326
327 /**
328 * Setup geometry field "GEOMETRY" - used for mesh deformation in optimization
329 * This field stores current nodal coordinates and can be modified
330 * during topology optimization to represent design changes
331 */
332 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
333
334 // Set polynomial approximation order for both fields
335 CHKERR simple->setFieldOrder("U", fieldOrder);
336 CHKERR simple->setFieldOrder("GEOMETRY", fieldOrder);
337 CHKERR simple->setUp();
338
339 // Project higher-order geometry representation onto geometry field
340 /**
341 * For higher-order elements, this projects the exact geometry
342 * onto the geometry field to maintain curved boundaries accurately
343 */
344 auto project_ho_geometry = [&]() {
345 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
346 return mField.loop_dofs("GEOMETRY", ent_method);
347 };
348 CHKERR project_ho_geometry();
349
350 // Check if plane strain assumption should be used
351 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
352 &is_plane_strain, PETSC_NULLPTR);
353
355}
356//! [Set up problem]
357
358//! [Setup adjoint]
362
363 // Create adjoint data manager and field
364 auto create_adjoint_dm = [&]() {
365 auto adjoint_dm = createDM(mField.get_comm(), "DMMOFEM");
366
367 constexpr int adjoint_field_order = 1;
368
369 auto add_field = [&]() {
371 CHKERR mField.add_field("ADJOINT_FIELD", H1, base, SPACE_DIM);
372 CHKERR mField.add_ents_to_field_by_dim(simple->getBoundaryMeshSet(),
373 SPACE_DIM - 1, "ADJOINT_FIELD");
374 for (auto tt = MBEDGE;
375 tt <= moab::CN::TypeDimensionMap[SPACE_DIM - 1].second; ++tt)
376 CHKERR mField.set_field_order(simple->getBoundaryMeshSet(), tt,
377 "ADJOINT_FIELD", adjoint_field_order);
378 CHKERR mField.set_field_order(simple->getBoundaryMeshSet(), MBVERTEX,
379 "ADJOINT_FIELD", 1);
382 };
383
384 auto add_adjoint_fe_impl = [&]() {
386 CHKERR mField.add_finite_element("ADJOINT_DOMAIN_FE");
388 "ADJOINT_FIELD");
390 "U");
392 "ADJOINT_FIELD");
394 "U");
396 "GEOMETRY");
397
398 CHKERR mField.add_finite_element("ADJOINT_BOUNDARY_FE");
400 "ADJOINT_FIELD");
402 "U");
404 "ADJOINT_FIELD");
406 "U");
408 "GEOMETRY");
409
411 simple->getMeshset(), SPACE_DIM, "ADJOINT_DOMAIN_FE");
413 simple->getBoundaryMeshSet(), SPACE_DIM - 1, "ADJOINT_BOUNDARY_FE");
414 CHKERR mField.build_finite_elements("ADJOINT_DOMAIN_FE");
415 CHKERR mField.build_finite_elements("ADJOINT_BOUNDARY_FE");
416
417 CHKERR mField.build_adjacencies(simple->getBitRefLevel(),
418 simple->getBitRefLevelMask());
419
421 };
422
423 auto set_adjoint_dm_imp = [&]() {
425 CHKERR DMMoFEMCreateMoFEM(adjoint_dm, &mField, "ADJOINT",
426 simple->getBitRefLevel(),
427 simple->getBitRefLevelMask());
428 CHKERR DMMoFEMSetDestroyProblem(adjoint_dm, PETSC_TRUE);
429 CHKERR DMSetFromOptions(adjoint_dm);
430 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_DOMAIN_FE");
431 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_BOUNDARY_FE");
432 CHKERR DMMoFEMSetSquareProblem(adjoint_dm, PETSC_FALSE);
433 CHKERR DMMoFEMSetIsPartitioned(adjoint_dm, PETSC_TRUE);
434 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
435 PETSC_TRUE;
436 CHKERR DMSetUp(adjoint_dm);
437 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
438 PETSC_FALSE;
440 };
441
442 CHK_THROW_MESSAGE(add_field(), "add adjoint field");
443 CHK_THROW_MESSAGE(add_adjoint_fe_impl(), "add adjoint fe");
444 CHK_THROW_MESSAGE(set_adjoint_dm_imp(), "set adjoint dm");
445
446 return adjoint_dm;
447 };
448
449 adjointDM = create_adjoint_dm();
450
452}
453//! [Setup adjoint]
454
455//! [Boundary condition]
459 auto bc_mng = mField.getInterface<BcManager>();
460
461 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
462 "U", 0, 0);
463 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
464 "U", 1, 1);
465 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
466 "U", 2, 2);
467 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
468 "REMOVE_ALL", "U", 0, 3);
469 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
470 simple->getProblemName(), "U");
471
472 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_X",
473 "ADJOINT_FIELD", 0, 0);
474 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Y",
475 "ADJOINT_FIELD", 1, 1);
476 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_Z",
477 "ADJOINT_FIELD", 2, 2);
478 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "REMOVE_ALL",
479 "ADJOINT_FIELD", 0, 3);
480 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_X", "ADJOINT_FIELD",
481 0, 0);
482 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Y", "ADJOINT_FIELD",
483 1, 1);
484 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_Z", "ADJOINT_FIELD",
485 2, 2);
486 CHKERR bc_mng->removeBlockDOFsOnEntities("ADJOINT", "FIX_ALL",
487 "ADJOINT_FIELD", 0, 3);
488
490}
491//! [Boundary condition]
492
493//! [Push operators to pipeline]
496 auto pip = mField.getInterface<PipelineManager>();
497
498 //! [Integration rule]
499 auto integration_rule = [](int, int, int approx_order) {
500 return 2 * approx_order + 1;
501 };
502
503 auto integration_rule_bc = [](int, int, int approx_order) {
504 return 2 * approx_order + 1;
505 };
506
508 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
509 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
510 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
511 //! [Integration rule]
512
514 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
516 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
518 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
520 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
521
522 //! [Push domain stiffness matrix to pipeline]
523 // Add LHS operator for elasticity (stiffness matrix)
524 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
525 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
526 //! [Push domain stiffness matrix to pipeline]
527
528 // Add RHS operator for internal forces
529 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
530 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
531
532 //! [Push Body forces]
534 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
535 //! [Push Body forces]
536
537 //! [Push natural boundary conditions]
538 // Add force boundary condition
540 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
541 // Add case for mix type of BCs
543 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::noisy);
544 //! [Push natural boundary conditions]
546}
547//! [Push operators to pipeline]
548
549//! [Solve]
553 auto dm = simple->getDM();
554 auto f = createDMVector(dm);
555 auto d = vectorDuplicate(f);
556 CHKERR VecZeroEntries(d);
557 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
558
559 auto set_essential_bc = [&]() {
561 // This is low level pushing finite elements (pipelines) to solver
562
563 auto ksp_ctx_ptr = getDMKspCtx(dm);
564 auto pre_proc_rhs = boost::make_shared<FEMethod>();
565 auto post_proc_rhs = boost::make_shared<FEMethod>();
566 auto post_proc_lhs = boost::make_shared<FEMethod>();
567
568 auto get_pre_proc_hook = [&]() {
570 {});
571 };
572 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
573
574 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
576
578 post_proc_rhs, 1.)();
580 };
581
582 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
584
586 post_proc_lhs, 1.)();
588 };
589
590 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
591 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
592
593 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
594 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
595 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
597 };
598
599 auto setup_and_solve = [&](auto solver) {
601 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
602 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp";
603 CHKERR KSPSetUp(solver);
604 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp <= Done";
605 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve";
606 CHKERR KSPSolve(solver, f, d);
607 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve <= Done";
609 };
610
611 MOFEM_LOG_CHANNEL("TIMER");
612 MOFEM_LOG_TAG("TIMER", "timer");
613
614 CHKERR set_essential_bc();
615 CHKERR setup_and_solve(kspElastic);
616
617 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
618 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
619 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
620
621 auto evaluate_field_at_the_point = [&]() {
623
624 int coords_dim = 3;
625 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
626 PetscBool do_eval_field = PETSC_FALSE;
627 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
628 field_eval_coords.data(), &coords_dim,
630
631 if (do_eval_field) {
632
633 vectorFieldPtr = boost::make_shared<MatrixDouble>();
634 auto field_eval_data =
635 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
636
638 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
639
640 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
641 auto no_rule = [](int, int, int) { return -1; };
642 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
643 field_eval_fe_ptr->getRuleHook = no_rule;
644
645 field_eval_fe_ptr->getOpPtrVector().push_back(
647
649 ->evalFEAtThePoint<SPACE_DIM>(
650 field_eval_coords.data(), 1e-12, simple->getProblemName(),
651 simple->getDomainFEName(), field_eval_data,
653 QUIET);
654
655 if (vectorFieldPtr->size1()) {
656 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
657 if constexpr (SPACE_DIM == 2)
658 MOFEM_LOG("FieldEvaluator", Sev::inform)
659 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
660 else
661 MOFEM_LOG("FieldEvaluator", Sev::inform)
662 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
663 << " U_Z: " << t_disp(2);
664 }
665
667 }
669 };
670
671 CHKERR evaluate_field_at_the_point();
672
674}
675//! [Solve]
676
677//! [Postprocess results]
679 SmartPetscObj<Vec> gradient_vector,
680 SmartPetscObj<Vec> adjoint_vector,
681 SmartPetscObj<Vec> dJ_du) {
684 std::vector<std::pair<std::string, SmartPetscObj<Vec>>> additional_vecs;
685 if (gradient_vector) {
686 additional_vecs.emplace_back("GRADIENT", gradient_vector);
687 }
688 if (adjoint_vector) {
689 additional_vecs.emplace_back("ADJOINT", adjoint_vector);
690 }
691 if (dJ_du) {
692 additional_vecs.emplace_back("dJ_dU", dJ_du);
693 }
696 mField, simple->getDM(), simple->getDomainFEName(),
697 "out_elastic_" + std::to_string(iter) + ".h5m", additional_vecs,
698 {}, Sev::noisy);
700}
701//! [Postprocess results]
702
704
705
706template <int DIM> inline auto diff_symmetrize(FTensor::Number<DIM>) {
707
708 FTensor::Index<'i', DIM> i;
709 FTensor::Index<'j', DIM> j;
710 FTensor::Index<'k', DIM> k;
711 FTensor::Index<'l', DIM> l;
712
714
715 t_diff(i, j, k, l) = 0;
716 t_diff(0, 0, 0, 0) = 1;
717 t_diff(1, 1, 1, 1) = 1;
718
719 t_diff(1, 0, 1, 0) = 0.5;
720 t_diff(1, 0, 0, 1) = 0.5;
721
722 t_diff(0, 1, 0, 1) = 0.5;
723 t_diff(0, 1, 1, 0) = 0.5;
724
725 if constexpr (DIM == 3) {
726 t_diff(2, 2, 2, 2) = 1;
727
728 t_diff(2, 0, 2, 0) = 0.5;
729 t_diff(2, 0, 0, 2) = 0.5;
730 t_diff(0, 2, 0, 2) = 0.5;
731 t_diff(0, 2, 2, 0) = 0.5;
732
733 t_diff(2, 1, 2, 1) = 0.5;
734 t_diff(2, 1, 1, 2) = 0.5;
735 t_diff(1, 2, 1, 2) = 0.5;
736 t_diff(1, 2, 2, 1) = 0.5;
737 }
738
739 return t_diff;
740};
741
742struct OpStateSensitivity : public DomainBaseOp {
745 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
746 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
747 boost::shared_ptr<MatrixDouble> u_ptr)
748 : OP(field_name, field_name, DomainEleOp::OPROW), pythonPtr(python_ptr),
749 commPtr(comm_ptr), uPtr(u_ptr) {}
750
757
758 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
759 auto nb_gauss_pts = getGaussPts().size2();
760
761 auto objective_dstress =
762 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
763 auto objective_dstrain =
764 boost::make_shared<MatrixDouble>(nb_gauss_pts, symm_size);
765 auto objective_du =
766 boost::make_shared<MatrixDouble>(nb_gauss_pts, SPACE_DIM);
767
768 auto evaluate_python = [&]() {
770 auto &coords = OP::getCoordsAtGaussPts();
771 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
772 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
773 objective_dstress);
774 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
775 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
776 objective_dstrain);
777 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
778 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
779 objective_du);
780
781 auto vol = OP::getMeasure();
782 auto t_w = OP::getFTensor0IntegrationWeight();
783
784 auto t_D =
785 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
786 auto t_row_grad = data.getFTensor1DiffN<SPACE_DIM>();
787 auto t_row_base = data.getFTensor0N();
788
789 auto t_obj_dstress =
790 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
791 auto t_obj_dstrain =
792 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
793 auto t_obj_du = getFTensor1FromMat<SPACE_DIM>(*objective_du);
794
795 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
796 const double alpha = t_w * vol;
798 t_adjoint_stress(i, j) =
799 t_D(i, j, k, l) * t_obj_dstress(k, l) + t_obj_dstrain(i, j);
800
801 auto t_nf = OP::template getNf<SPACE_DIM>();
802 int rr = 0;
803 for (; rr != OP::nbRows / SPACE_DIM; rr++) {
804 t_nf(j) += alpha * t_row_grad(i) * t_adjoint_stress(i, j);
805 t_nf(j) += alpha * t_row_base * t_obj_du(j);
806
807 ++t_row_grad;
808 ++t_row_base;
809 ++t_nf;
810 }
811
812 for (; rr < OP::nbRowBaseFunctions; ++rr) {
813 ++t_row_grad;
814 ++t_row_base;
815 }
816 ++t_obj_dstrain;
817 ++t_obj_dstress;
818 ++t_obj_du;
819 ++t_w;
820 }
822 };
823 CHKERR evaluate_python();
825 }
826
827private:
828 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
829 boost::shared_ptr<HookeOps::CommonData> commPtr;
830 boost::shared_ptr<MatrixDouble> uPtr;
831};
834
835 OpObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
836 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
837 boost::shared_ptr<MatrixDouble> jac_ptr,
838 boost::shared_ptr<MatrixDouble> u_ptr,
839 boost::shared_ptr<double> glob_objective_ptr)
840 : OP(NOSPACE, OP::OPSPACE), pythonPtr(python_ptr), commPtr(comm_ptr),
841 jacPtr(jac_ptr), uPtr(u_ptr), globObjectivePtr(glob_objective_ptr) {}
842
843 /**
844 * @brief Compute objective function contributions at element level
845 *
846 * Evaluates Python objective function with current displacement and stress
847 * state, and accumulates global objective value and gradients.
848 */
849 MoFEMErrorCode doWork(int side, EntityType type,
852
853 auto nb_gauss_pts =
854 getGaussPts().size2(); // number of gauss points in the element
855
856 auto objective_ptr = boost::make_shared<MatrixDouble>(
857 1, nb_gauss_pts); // objective function values at gauss points
858
859 auto evaluate_python = [&]() {
861 auto &coords = OP::getCoordsAtGaussPts();
862 CHKERR pythonPtr->evalInteriorObjectiveFunction(
863 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
864 objective_ptr);
865
866 auto t_obj = getFTensor0FromMat(*objective_ptr);
867
868 auto vol = OP::getMeasure();
869 auto t_w = getFTensor0IntegrationWeight();
870 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
871
872 auto alpha = t_w * vol;
873 (*globObjectivePtr) += alpha * t_obj;
874
875 ++t_w;
876
877 ++t_obj;
878 }
880 };
881
882 CHKERR evaluate_python();
883
885 }
886
887private:
888 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
889 boost::shared_ptr<HookeOps::CommonData> commPtr;
890 boost::shared_ptr<MatrixDouble> jacPtr;
891 boost::shared_ptr<MatrixDouble> uPtr;
892 boost::shared_ptr<double> globObjectivePtr;
893};
894
895struct OpAdJointObjective : public DomainBaseOp {
897
898 OpAdJointObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
899 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
900 boost::shared_ptr<MatrixDouble> jac_ptr,
901 boost::shared_ptr<MatrixDouble> u_ptr,
902 boost::shared_ptr<MatrixDouble> grad_lambda_u_ptr,
903 boost::shared_ptr<double> glob_objective_ptr)
904 : OP("ADJOINT_FIELD", "ADJOINT_FIELD", OP::OPROW), pythonPtr(python_ptr),
905 commPtr(comm_ptr), jacPtr(jac_ptr), uPtr(u_ptr),
906 gradLambdaUPtr(grad_lambda_u_ptr),
907 globObjectivePtr(glob_objective_ptr) {}
908
909 /**
910 * @brief Compute objective function contributions at element level
911 *
912 * Evaluates Python objective function with current displacement and stress
913 * state, and accumulates global objective value and gradients.
914 */
917
918 const auto nb_gauss_pts =
919 getGaussPts().size2(); // number of gauss points in the element
920 const auto nb_dofs = data.getIndices().size();
921 const auto nb_base_funcs = data.getN().size2() / SPACE_DIM;
922
923 // Define tensor indices for calculations
928
931
932 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) /
933 2; // size of symmetric tensor in Voigt notation
934
935 auto t_diff_symm = diff_symmetrize(
937 SPACE_DIM>()); // fourth order tensor for symmetrization to convert from gradient to strain
938
939 auto objective_ptr = boost::make_shared<MatrixDouble>(
940 1, nb_gauss_pts); // objective function values at gauss points
941 auto objective_dstress = boost::make_shared<MatrixDouble>(
942 nb_gauss_pts,
943 symm_size); // objective function gradient w.r.t. stress at gauss points
944 auto objective_dstrain = boost::make_shared<MatrixDouble>(
945 nb_gauss_pts,
946 symm_size); // objective function gradient w.r.t. strain at gauss points
947 // The dJ/du contribution is assembled separately by OpStateSensitivity.
948
949 auto evaluate_python = [&]() {
951 auto &coords = OP::getCoordsAtGaussPts();
952 CHKERR pythonPtr->evalInteriorObjectiveFunction(
953 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
954 objective_ptr);
955 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
956 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
957 objective_dstress);
958 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
959 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
960 objective_dstrain);
961
962 auto t_grad_u =
963 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
964 auto t_D =
965 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*(commPtr->matDPtr));
966 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jacPtr));
967 auto t_grad_lambda_u =
968 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*gradLambdaUPtr);
969
970 auto t_obj = getFTensor0FromMat(*objective_ptr);
971 auto t_obj_dstress =
972 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
973 auto t_obj_dstrain =
974 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
975
976 auto vol = OP::getMeasure();
977 auto t_w = getFTensor0IntegrationWeight();
978 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
979 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
980 auto alpha = t_w * vol;
981 (*globObjectivePtr) += alpha * t_obj;
982
983 auto t_det = determinantTensor(t_jac);
985 CHKERR invertTensor(t_jac, t_det, t_inv_jac);
986
988 t_diff_inv_jac;
989 t_diff_inv_jac(i, j, I, J) =
990 -t_inv_jac(i, I) * t_inv_jac(J, j);
992 t_diff_grad;
993 t_diff_grad(i, j, I, J) = t_grad_u(i, k) * t_diff_inv_jac(k, j, I, J);
995 t_d_strain;
996 t_d_strain(i, j, I, J) =
997 t_diff_symm(i, j, k, l) * t_diff_grad(k, l, I, J);
998
999 auto t_local_grad_vector = OP::template getNf<SPACE_DIM>();
1000 int bb = 0;
1001 for (; bb != nb_dofs/ SPACE_DIM; bb++) {
1002
1004 t_coef(I) = (t_inv_jac(J, I) * t_base_diff(J)) * t_det;
1005
1006 t_local_grad_vector(I) +=
1007 alpha * (
1008
1009 ((t_obj_dstress(k, l) * t_D(k, l, i, j)) +
1010 t_obj_dstrain(i, j)) *
1011 (t_d_strain(i, j, I, J) * t_base_diff(J))
1012
1013 +
1014
1015 t_obj * t_coef(I)
1016
1017 );
1018
1019 t_local_grad_vector(I) -=
1020 alpha * (t_grad_lambda_u(i, j) * t_D(i, j, k, l)) *
1021 (t_d_strain(k, l, I, J) * t_base_diff(J));
1022
1023 ++t_local_grad_vector;
1024 ++t_base_diff;
1025 }
1026 for (; bb < nb_base_funcs; ++bb) {
1027 ++t_base_diff;
1028 }
1029
1030 ++t_w;
1031 ++t_jac;
1032
1033 ++t_obj;
1034 ++t_obj_dstress;
1035 ++t_obj_dstrain;
1036
1037 ++t_grad_u;
1038 ++t_grad_lambda_u;
1039 }
1041 };
1042
1043 CHKERR evaluate_python();
1044
1046 }
1047
1048private:
1049 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
1050 boost::shared_ptr<HookeOps::CommonData> commPtr;
1051 boost::shared_ptr<MatrixDouble> jacPtr;
1052 boost::shared_ptr<MatrixDouble> uPtr;
1053 boost::shared_ptr<MatrixDouble> gradLambdaUPtr;
1054
1055 boost::shared_ptr<double> globObjectivePtr;
1056};
1057
1058MoFEMErrorCode Example::calculateGradient(PetscReal *objective_function_value,
1059 Vec objective_function_gradient,
1060 Vec lambda, Vec dJ_du) {
1061 MOFEM_LOG_CHANNEL("WORLD");
1063 auto simple = mField.getInterface<Simple>();
1064 auto dm = simple->getDM();
1065
1066 auto get_essential_fe = [this]() {
1067 auto post_proc_rhs = boost::make_shared<FEMethod>();
1068 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
1071 post_proc_rhs, 0)();
1073 };
1074 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1075 return post_proc_rhs;
1076 };
1077
1078 auto get_objective_fe = [&](auto lambda_vec, auto glob_objective_ptr,
1079 auto fe_rule) {
1080 auto fe_obj = boost::make_shared<DomainEle>(mField);
1081 fe_obj->getRuleHook = fe_rule;
1082 auto &pip = fe_obj->getOpPtrVector();
1084
1085 auto jac_ptr = boost::make_shared<MatrixDouble>();
1086 auto u_ptr = boost::make_shared<MatrixDouble>();
1087 auto grad_lambda_ptr = boost::make_shared<MatrixDouble>();
1088
1090 "GEOMETRY", jac_ptr));
1091 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1092 auto lambda_smart_vec = SmartPetscObj<Vec>(lambda_vec, true);
1094 "U", grad_lambda_ptr, lambda_smart_vec));
1095
1096 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1097 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1098 pip.push_back(new OpAdJointObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1099 grad_lambda_ptr,
1100 glob_objective_ptr));
1101 return fe_obj;
1102 };
1103
1104 auto evaluate_objective_terms =
1105 [&](auto objective_fe, auto objective_ptr) {
1107 *objective_ptr = 0.0;
1108 CHKERR VecZeroEntries(objective_function_gradient);
1109 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1110 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1111 objective_fe->f = objective_function_gradient;
1112 CHKERR DMoFEMLoopFiniteElements(adjointDM, "ADJOINT_DOMAIN_FE",
1113 objective_fe);
1114 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1115 mField.get_comm());
1116 CHKERR VecAssemblyBegin(objective_function_gradient);
1117 CHKERR VecAssemblyEnd(objective_function_gradient);
1118 CHKERR VecGhostUpdateBegin(objective_function_gradient, ADD_VALUES,
1119 SCATTER_REVERSE);
1120 CHKERR VecGhostUpdateEnd(objective_function_gradient, ADD_VALUES,
1121 SCATTER_REVERSE);
1123 };
1124
1125 auto calculate_variance_of_objective_function_dJ_du = [&]() {
1127 auto fe = boost::make_shared<DomainEle>(mField);
1128 fe->getRuleHook = [](int, int, int p_data) {
1129 return 2 * p_data + p_data - 1;
1130 };
1131 auto &pip = fe->getOpPtrVector();
1133 auto u_ptr = boost::make_shared<MatrixDouble>();
1134 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1135 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1136 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1137 pip.push_back(new OpStateSensitivity("U", pythonPtr, common_ptr, u_ptr));
1138 CHKERR VecZeroEntries(dJ_du);
1139 fe->f = dJ_du;
1141 CHKERR VecAssemblyBegin(dJ_du);
1142 CHKERR VecAssemblyEnd(dJ_du);
1143 auto post_proc_rhs = get_essential_fe();
1144 post_proc_rhs->f = dJ_du;
1146 post_proc_rhs.get());
1148 };
1149
1150 auto calculate_adjoint_lambda = [&]() {
1152
1153 MOFEM_LOG("WORLD", Sev::inform) << "Solving for adjoint variable lambda";
1154 CHKERR VecZeroEntries(lambda);
1155 CHKERR KSPSolveTranspose(kspElastic, dJ_du, lambda);
1156 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1157 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1159 };
1160
1161 auto fe_rule = [](int, int, int p_data) { return 2 * p_data + p_data - 1; };
1162 auto objective_ptr_value = boost::make_shared<double>(0.0);
1163 auto objective_fe = get_objective_fe(lambda, objective_ptr_value, fe_rule);
1164
1165 auto adjoint = [&]() {
1167
1168 CHKERR calculate_variance_of_objective_function_dJ_du();
1169 CHKERR calculate_adjoint_lambda();
1170 CHKERR evaluate_objective_terms(objective_fe, objective_ptr_value);
1171 *objective_function_value = *objective_ptr_value;
1172
1173 MOFEM_LOG("WORLD", Sev::verbose)
1174 << "Objective function: " << *objective_function_value;
1175
1176 CHKERR VecAssemblyBegin(objective_function_gradient);
1177 CHKERR VecAssemblyEnd(objective_function_gradient);
1178 CHKERR VecGhostUpdateBegin(lambda, INSERT_VALUES, SCATTER_FORWARD);
1179 CHKERR VecGhostUpdateEnd(lambda, INSERT_VALUES, SCATTER_FORWARD);
1180
1182 };
1183
1184 switch (derivative_type) {
1185
1186 case ADJOINT:
1187 MOFEM_LOG("WORLD", Sev::inform) << "Running Adjoint Sensitivity...";
1188 CHKERR adjoint();
1189 break;
1190
1191 default:
1192 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1193 "Wrong sensitivity type selected");
1194 }
1195
1196 CHKERR VecAssemblyBegin(objective_function_gradient);
1197 CHKERR VecAssemblyEnd(objective_function_gradient);
1198
1200}
1201//! [calculateGradient]
1202
1203//! [Finite difference check]
1206
1207 PetscBool gradient_fd_check = PETSC_FALSE;
1208 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, PETSC_NULLPTR, "-gradient_fd_check",
1209 &gradient_fd_check, PETSC_NULLPTR);
1210 if (gradient_fd_check) {
1211
1212 PetscInt nb_modes = 5;
1213 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR,
1214 "-gradient_nb_modes", &nb_modes, PETSC_NULLPTR);
1215
1216 auto simple = mField.getInterface<Simple>();
1217 auto dm = simple->getDM();
1218 auto *adj_problem_ptr = getProblemPtr(adjointDM);
1219
1220 auto fe_rule = [](int, int, int p_data) { return 2 * p_data + p_data - 1; };
1221 auto get_objective_fe = [&](auto glob_objective_ptr, auto fe_rule) {
1222 auto fe_obj_fe = boost::make_shared<DomainEle>(mField);
1223 fe_obj_fe->getRuleHook = fe_rule;
1224 auto &pip = fe_obj_fe->getOpPtrVector();
1226 auto jac_ptr = boost::make_shared<MatrixDouble>();
1227 auto u_ptr = boost::make_shared<MatrixDouble>();
1229 "GEOMETRY", jac_ptr));
1230 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1231 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, I, DomainEleOp>(
1232 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1233 pip.push_back(new OpObjective(pythonPtr, common_ptr, jac_ptr, u_ptr,
1234 glob_objective_ptr));
1235 return fe_obj_fe;
1236 };
1237
1238 auto f = boost::make_shared<double>(0.);
1239 auto fe_obj = get_objective_fe(f, fe_rule);
1240 CacheTupleSharedPtr tmp_cache_ptr = boost::make_shared<CacheTuple>();
1241 CHKERR mField.cache_problem_entities(simple->getProblemName(),
1242 tmp_cache_ptr);
1243
1244 auto evaluate_objective_terms = [&](auto objective_fe, auto objective_ptr,
1245 double &objective_value) {
1247 *objective_ptr = 0.0;
1249 objective_fe);
1250 MPI_Allreduce(MPI_IN_PLACE, objective_ptr.get(), 1, MPI_DOUBLE, MPI_SUM,
1251 mField.get_comm());
1252 objective_value = *objective_ptr;
1254 };
1255
1256 auto geometry_bit_number = mField.get_field_bit_number("GEOMETRY");
1257 for (PetscInt mode = 0; mode < nb_modes; ++mode) {
1258 MOFEM_LOG_CHANNEL("WORLD");
1259 MOFEM_LOG("WORLD", Sev::verbose) << "Processing mode: " << mode;
1260
1261 auto &adj_dofs =
1262 adj_problem_ptr->getNumeredRowDofsPtr()->get<PetscGlobalIdx_mi_tag>();
1263 auto &dofs = mField.get_dofs()->get<Unique_mi_tag>();
1264
1265 auto a_dof = adj_dofs.find(mode);
1266 if (a_dof != adj_dofs.end()) {
1267 auto ent = (*a_dof)->getEnt();
1268 auto dof_idx = (*a_dof)->getEntDofIdx();
1270 dof_idx,
1271 FieldEntity::getLocalUniqueIdCalculate(geometry_bit_number, ent));
1272 auto dof = dofs.find(uid);
1273 if (dof != dofs.end()) {
1274 auto org_geom_val = (*dof)->getFieldData();
1275 constexpr double eps = 1e-6;
1276
1277 (*dof)->getFieldData() = org_geom_val + eps;
1278 CHKERR KSPReset(kspElastic);
1280 double f_plus;
1281 CHKERR evaluate_objective_terms(fe_obj, f, f_plus);
1282
1283 (*dof)->getFieldData() = org_geom_val - eps;
1284 CHKERR KSPReset(kspElastic);
1286 double f_minus;
1287 CHKERR evaluate_objective_terms(fe_obj, f, f_minus);
1288
1289 double *g_array;
1290 CHKERR VecGetArray(gradient_vector, &g_array);
1291 if ((*a_dof)->getHasLocalIndex()) {
1292 auto adjoint_grad = g_array[(*a_dof)->getPetscLocalDofIdx()];
1293 auto finite_diff_grad = (f_plus - f_minus) / (2 * eps);
1294 auto err = std::abs(adjoint_grad - finite_diff_grad) /
1295 std::max(std::abs(adjoint_grad),
1296 std::abs(finite_diff_grad));
1297 MOFEM_LOG("WORLD", Sev::inform)
1298 << "Mode: " << mode << ", Adjoint gradient: " << adjoint_grad
1299 << ", Finite difference gradient: " << finite_diff_grad
1300 << ", Relative error: "
1301 << std::abs(adjoint_grad - finite_diff_grad) /
1302 std::max(std::abs(adjoint_grad),
1303 std::abs(finite_diff_grad));
1304 constexpr double tol = 1e-4;
1305 if (err > tol) {
1306 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1307 "Gradient check failed for mode %d: relative error %e is "
1308 "greater than tolerance %e",
1309 mode, err, tol);
1310 }
1311 }
1312
1313 CHKERR VecRestoreArray(gradient_vector, &g_array);
1314
1315 constexpr bool restore_solution = false;
1316 if constexpr (restore_solution) {
1317 (*dof)->getFieldData() = org_geom_val;
1318 CHKERR KSPReset(kspElastic);
1320 }
1321 }
1322 }
1323 }
1324 }
1325
1327}
1328//! [Finite difference check]
1329
1330static char help[] = "...\n\n";
1331
1332int main(int argc, char *argv[]) {
1333
1334 // Initialize Python environment for objective function interface
1335 Py_Initialize();
1336 np::initialize();
1337
1338 // Initialize MoFEM/PETSc and MOAB data structures
1339 const char param_file[] = "param_file.petsc";
1340 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1341
1342 auto core_log = logging::core::get();
1343 core_log->add_sink(
1345
1346 core_log->add_sink(
1347 LogManager::createSink(LogManager::getStrmSync(), "FieldEvaluator"));
1348 LogManager::setLog("FieldEvaluator");
1349 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
1350
1351 try {
1352
1353 //! [Register MoFEM discrete manager in PETSc]
1354 DMType dm_name = "DMMOFEM";
1355 CHKERR DMRegister_MoFEM(dm_name);
1356 DMType dm_name_mg = "DMMOFEM_MG";
1358 //! [Register MoFEM discrete manager in PETSc
1359
1360 //! [Create MoAB]
1361 moab::Core mb_instance; ///< mesh database
1362 moab::Interface &moab = mb_instance; ///< mesh database interface
1363 //! [Create MoAB]
1364
1365 //! [Create MoFEM]
1366 MoFEM::Core core(moab); ///< finite element database
1367 MoFEM::Interface &m_field = core; ///< finite element database interface
1368 //! [Create MoFEM]
1369
1370 //! [Example]
1371
1372 Example ex(m_field);
1373 CHKERR ex.runProblem();
1374 //! [Example]
1375 }
1377
1379
1380 if (Py_FinalizeEx() < 0) {
1381 exit(120);
1382 }
1383}
1384
1386 const std::string block_name, int dim) {
1387 Range r;
1388
1389 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
1390 auto bcs = mesh_mng->getCubitMeshsetPtr(
1391
1392 std::regex((boost::format("%s(.*)") % block_name).str())
1393
1394 );
1395
1396 for (auto bc : bcs) {
1397 Range faces;
1398 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
1399 faces, true),
1400 "get meshset ents");
1401 r.merge(faces);
1402 }
1403
1404 for (auto dd = dim - 1; dd >= 0; --dd) {
1405 if (dd >= 0) {
1406 Range ents;
1407 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(r, dd, false, ents,
1408 moab::Interface::UNION),
1409 "get adjs");
1410 r.merge(ents);
1411 } else {
1412 Range verts;
1413 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(r, verts),
1414 "get verts");
1415 r.merge(verts);
1416 }
1418 m_field.getInterface<CommInterface>()->synchroniseEntities(r), "comm");
1419 }
1420
1421 return r;
1422};
1423
1424MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
1425 const Range r) {
1427 auto out_meshset = get_temp_meshset_ptr(moab);
1428 CHKERR moab.add_entities(*out_meshset, r);
1429 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
1431};
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)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
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:706
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:703
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
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)
const double eps
Definition HenckyOps.hpp:13
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)
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: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
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:227
MoFEMErrorCode setupProblem()
MoFEMErrorCode postprocessElastic(int iter, SmartPetscObj< Vec > adjoint_vector=nullptr)
Post-process and output results.
Definition adjoint.cpp:1326
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 getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
const std::string getDomainFEName() const
Get the Domain FE Name.
Definition Simple.hpp:429
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:898
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:915
boost::shared_ptr< MatrixDouble > jacPtr
Definition adjoint.cpp:1752
boost::shared_ptr< double > globObjectivePtr
Definition gradient.cpp:892
ForcesAndSourcesCore::UserDataOperator OP
Definition gradient.cpp:833
boost::shared_ptr< MatrixDouble > jacPtr
Definition gradient.cpp:890
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:835
boost::shared_ptr< MatrixDouble > uPtr
Definition gradient.cpp:891
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Compute objective function contributions at element level.
Definition gradient.cpp:849
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition gradient.cpp:889
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition gradient.cpp:888
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:744
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &data)
Definition gradient.cpp:751
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
double tol
#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
auto save_range
constexpr int SPACE_DIM
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle BoundaryEle
PostProcEleByDim< SPACE_DIM >::SideEle SideEle
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle