v0.16.0
Loading...
Searching...
No Matches
NonlinearElasticExample.hpp
Go to the documentation of this file.
1/**
2 * @file NonlinearElasticExample.hpp
3 * @example mofem/tutorials/vec-2_nonlinear_elasticity/src/NonlinearElasticExample.hpp
4 * @date 2025-10-5
5 *
6 * @copyright Anonymous authors (c) 2025 under the MIT license (see LICENSE for
7 * details)
8 */
9
10#ifdef WITH_ADOL_C
11 #include <MatOps.hpp>
12 #include <MatElastic.hpp>
13 #include <MatHuHu.hpp>
14 #include <MatGenericElastic.hpp>
16 #ifdef WITH_ADOL_C_SIMPLE_DAMAGE
18 #endif
19#endif
20
22
24
25 MoFEMErrorCode runProblem();
26
27protected:
29 boost::shared_ptr<DomainEle> updateFe;
30 boost::shared_ptr<DomainEle> reactionFe;
31 boost::shared_ptr<PostProcEleDomain> postProcDomainFe;
32 boost::shared_ptr<PostProcEleBdy> postProcBdyFe;
33 PetscBool useAdolcMaterial = PETSC_FALSE;
34
35 MoFEMErrorCode readMesh();
36 MoFEMErrorCode setupProblem();
37 MoFEMErrorCode boundaryCondition();
38 MoFEMErrorCode assembleSystemHencky();
39 MoFEMErrorCode assembleSystemAdolc();
40 MoFEMErrorCode opTest();
41 MoFEMErrorCode TsSolve();
42 MoFEMErrorCode gettingNorms();
43 MoFEMErrorCode outputResults();
44 MoFEMErrorCode checkResults();
45
47
48 static MoFEMErrorCode
50 elasticExamplePtr = example_ptr;
51 return 0;
52 }
53 static MoFEMErrorCode postStepDestroy() {
54 elasticExamplePtr = nullptr;
55 return 0;
56 }
57 static MoFEMErrorCode preStepFun(TS ts) { return 0; }
58 static MoFEMErrorCode postStepFun(TS ts) {
60 (void)ts;
62 auto dm = simple->getDM();
64 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
66 }
68 }
69
70 private:
72 };
73
74 std::vector<Tag>
75 listTagsToTransfer; ///< list of tags to transfer to postprocessor
76
77#ifdef WITH_ADOL_C
78 static inline constexpr int modelType =
79 (SPACE_DIM == 3) ? MatOps::MODEL_3D : MatOps::MODEL_2D_PLANE_STRAIN;
80 boost::shared_ptr<MatOps::PhysicalEquations> physicalEquationsPtr;
81 boost::shared_ptr<MatOps::PhysicalEquations> physicalHuHuPtr;
82#endif
83
84 static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
85 Skinner skin(&m_field.get_moab());
86 Range skin_ents;
87 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
88 return skin_ents;
89 };
90
91 static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
92 Range boundary_ents;
93 ParallelComm *pcomm =
94 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
95 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
96 PSTATUS_SHARED | PSTATUS_MULTISHARED,
97 PSTATUS_NOT, -1, &boundary_ents),
98 "filter_pstatus");
99 return boundary_ents;
100 };
101};
102
103//! [Run problem]
109
110 PetscBool test_op = PETSC_FALSE;
111 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_op", &test_op,
112 PETSC_NULLPTR);
113
114 if (useAdolcMaterial == PETSC_TRUE) {
116 } else {
118 }
119
120 if (test_op == PETSC_TRUE) {
121 CHKERR opTest();
122 }
123 CHKERR TsSolve();
128}
129//! [Run problem]
130
131//! [Read mesh]
134 auto simple = mField.getInterface<Simple>();
135 CHKERR simple->getOptions();
136 CHKERR simple->loadFile();
138}
139//! [Read mesh]
140
141//! [Set up problem]
144 Simple *simple = mField.getInterface<Simple>();
145
146 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
147 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
148 PetscInt choice_base_value = AINSWORTH;
149 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
150 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
151
153 switch (choice_base_value) {
154 case AINSWORTH:
156 MOFEM_LOG("WORLD", Sev::inform)
157 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
158 break;
159 case DEMKOWICZ:
161 MOFEM_LOG("WORLD", Sev::inform)
162 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
163 break;
164 default:
165 base = LASTBASE;
166 break;
167 }
168
169 // Add field
170 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
171 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
172 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
173 int order = 2;
174 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
175 CHKERR simple->setFieldOrder("U", order);
176 CHKERR simple->setFieldOrder("GEOMETRY", 2);
177 CHKERR simple->setUp();
178
179 auto project_ho_geometry = [&]() {
180 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
181 return mField.loop_dofs("GEOMETRY", ent_method);
182 };
183 CHKERR project_ho_geometry();
184
185 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-use_adolc_material",
186 &useAdolcMaterial, PETSC_NULLPTR);
187#ifndef WITH_ADOL_C
188 if (useAdolcMaterial == PETSC_TRUE) {
189 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
190 "ADOL-C support is not enabled. Please reconfigure with "
191 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
192 }
193#endif
194 if (useAdolcMaterial == PETSC_TRUE) {
195 MOFEM_LOG("WORLD", Sev::inform) << "Use ADOL-C material model";
196 } else {
197 MOFEM_LOG("WORLD", Sev::inform) << "Use Hencky material model";
198 }
199
200 auto tag_meshest = [&]() {
202
203 auto set_block = [&](auto name, int dim) {
204 std::map<int, Range> map;
205 auto set_tag_impl = [&](auto name) {
207 auto mesh_mng = mField.getInterface<MeshsetsManager>();
208 auto bcs = mesh_mng->getCubitMeshsetPtr(
209
210 std::regex((boost::format("%s(.*)") % name).str())
211
212 );
213 std::map<int, int> ids_map;
214 int bit_id = 1;
215 for (auto bc : bcs) {
216 int id = bc->getMeshsetId();
217 ids_map[id] = bit_id;
218 bit_id <<= 1;
219 }
220 for (auto bc : bcs) {
221 Range r;
222 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
223 true);
224 map[ids_map[bc->getMeshsetId()]] = r;
225 MOFEM_LOG("EXAMPLE", Sev::inform)
226 << "Block " << name << " id " << bc->getMeshsetId() << " : "
227 << ids_map[bc->getMeshsetId()] << " has " << r.size()
228 << " entities";
229 }
231 };
232
233 CHKERR set_tag_impl(name);
234
235 return std::make_pair(name, map);
236 };
237
238 auto set_skin = [&](auto &&map) {
239 for (auto &m : map.second) {
240 auto s = filter_true_skin(mField, get_skin(mField, m.second));
241 m.second.swap(s);
242 MOFEM_LOG("EXAMPLE", Sev::inform)
243 << "Skin for block " << map.first << " id " << m.first << " has "
244 << m.second.size() << " entities";
245 }
246 return map;
247 };
248
249 auto set_tag = [&](auto &&map) {
250 Tag th;
251 auto name = map.first;
252 int def_val[] = {-1};
253 CHK_MOAB_THROW(mField.get_moab().tag_get_handle(
254 name, 1, MB_TYPE_INTEGER, th,
255 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
256 "create tag");
257 for (auto &m : map.second) {
258 int id = m.first;
259 for (auto ent : m.second) {
260 int current_id;
262 mField.get_moab().tag_get_data(th, &ent, 1, &current_id),
263 "get tag data");
264 if (current_id != -1) {
265 id |= current_id;
266 }
267 CHK_MOAB_THROW(mField.get_moab().tag_set_data(th, &ent, 1, &id),
268 "set tag data");
269 }
270 }
271 return th;
272 };
273
274 if (SPACE_DIM == 3) {
275 listTagsToTransfer.push_back(set_tag(set_block("MAT_", 3)));
276 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_", 3))));
277 } else {
278 listTagsToTransfer.push_back(set_tag(set_block("MAT_", 2)));
279 }
280
282 };
283
284 CHKERR tag_meshest();
285
287}
288//! [Set up problem]
289
290//! [Boundary condition]
291
294 auto *pipeline_mng = mField.getInterface<PipelineManager>();
295 auto simple = mField.getInterface<Simple>();
296 auto bc_mng = mField.getInterface<BcManager>();
297 auto time_scale = boost::make_shared<ExampleTimeScale>();
298
300 pipeline_mng->getOpBoundaryRhsPipeline(), mField, "U", {time_scale},
301 "FORCE", "PRESSURE", Sev::inform);
302
303 //! [Define gravity vector]
305 pipeline_mng->getOpDomainRhsPipeline(), mField, "U", {time_scale},
306 "BODY_FORCE", Sev::inform);
307
308 // Essential BC
309 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
310 "U", 0, 0);
311 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
312 "U", 1, 1);
313 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
314 "U", 2, 2);
315 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
316 simple->getProblemName(), "U");
317
319}
320//! [Boundary condition]
321
322//! [Push operators to pipeline]
325
326 auto *pipeline_mng = mField.getInterface<PipelineManager>();
327
328 auto integration_rule = [](int, int, int approx_order) {
329 return 2 * (approx_order - 1) + 1;
330 };
331
332 CHKERR pipeline_mng->setDomainRhsIntegrationRule(integration_rule);
333 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
334 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
335
336 auto add_domain_ops_lhs = [&](auto &pip) {
339 "GEOMETRY");
340 CHKERR
341 HenckyOps::opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
342 mField, pip, "U", "MAT_ELASTIC", Sev::inform);
344 };
345
346 auto add_domain_ops_rhs = [&](auto &pip) {
349 "GEOMETRY");
350 CHKERR
351 HenckyOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
352 mField, pip, "U", "MAT_ELASTIC", Sev::inform);
354 };
355
356 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
357 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
358
359 // push operators to reaction pipeline
360 reactionFe = boost::make_shared<DomainEle>(mField);
361 reactionFe->getRuleHook = integration_rule;
362 CHKERR add_domain_ops_rhs(reactionFe->getOpPtrVector());
363 reactionFe->postProcessHook =
364 EssentialPreProcReaction<DisplacementCubitBcData>(mField, reactionFe);
365
366 PetscBool post_proc_vol;
367 PetscBool post_proc_skin;
368
369 if constexpr (SPACE_DIM == 2) {
370 post_proc_vol = PETSC_TRUE;
371 post_proc_skin = PETSC_FALSE;
372 } else {
373 post_proc_vol = PETSC_FALSE;
374 post_proc_skin = PETSC_TRUE;
375 }
376
377 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol",
378 &post_proc_vol, PETSC_NULLPTR);
379 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
380 &post_proc_skin, PETSC_NULLPTR);
381
382 // Setup postprocessing
383 auto create_post_proc_fe = [&]() {
384 auto post_proc_ele_domain = [this](auto &pip_domain) {
386 "GEOMETRY");
387 auto common_ptr = commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
388 mField, pip_domain, "U", "MAT_ELASTIC", Sev::inform);
389 return common_ptr;
390 };
391
392 auto post_proc_map = [&](auto &pip, auto u_ptr, auto common_ptr) {
394
395 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
396
397 pip->getOpPtrVector().push_back(
398
399 new OpPPMap(pip->getPostProcMesh(), pip->getMapGaussPts(), {},
400 {{"U", u_ptr}},
401 {{"GRAD", common_ptr->matGradPtr},
402 {"FIRST_PIOLA", common_ptr->getMatFirstPiolaStress()}},
403 {}));
405 };
406
407 auto push_post_proc_bdy = [&](auto &pip_bdy) {
408 if (post_proc_skin == PETSC_FALSE)
409 return boost::shared_ptr<PostProcEleBdy>();
410 auto simple = mField.getInterface<Simple>();
411 auto domain_fe_name = simple->getDomainFEName();
412 auto u_ptr = boost::make_shared<MatrixDouble>();
413 pip_bdy->getOpPtrVector().push_back(
414 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
415 auto op_loop_side =
416 new OpLoopSide<SideEle>(mField, domain_fe_name, SPACE_DIM);
417 auto common_ptr = post_proc_ele_domain(op_loop_side->getOpPtrVector());
418 pip_bdy->getOpPtrVector().push_back(op_loop_side);
419 CHKERR post_proc_map(pip_bdy, u_ptr, common_ptr);
420 return pip_bdy;
421 };
422
423 auto push_post_proc_domain = [&](auto &pip_domain) {
424 if (post_proc_vol == PETSC_FALSE)
425 return boost::shared_ptr<PostProcEleDomain>();
426
427 auto u_ptr = boost::make_shared<MatrixDouble>();
428 pip_domain->getOpPtrVector().push_back(
429 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
430 auto common_ptr = post_proc_ele_domain(pip_domain->getOpPtrVector());
431
432 CHKERR post_proc_map(pip_domain, u_ptr, common_ptr);
433
434 return pip_domain;
435 };
436
437 auto post_proc_fe_domain = boost::make_shared<PostProcEleDomain>(mField);
438 auto post_proc_fe_bdy = boost::make_shared<PostProcEleBdy>(mField);
439
440 return std::make_pair(push_post_proc_domain(post_proc_fe_domain),
441 push_post_proc_bdy(post_proc_fe_bdy));
442 };
443
444 auto post_proc_pair = create_post_proc_fe();
445 postProcDomainFe = post_proc_pair.first;
446 postProcBdyFe = post_proc_pair.second;
447
449}
450//! [Push operators to pipeline]
451
454
455 // get operators tester
456 auto simple = mField.getInterface<Simple>();
457 auto opt = mField.getInterface<OperatorsTester>(); // get interface to
458 // OperatorsTester
459 auto pip = mField.getInterface<PipelineManager>(); // get interface to
460 // pipeline manager
461
462 constexpr double eps = 1e-9;
463
464 auto x = opt->setRandomFields(simple->getDM(), {
465
466 {"U", {-1e-6, 1e-6}}
467
468 });
469
470 auto dot_x = opt->setRandomFields(simple->getDM(), {
471
472 {"U", {-1, 1}}
473
474 });
475
476 auto diff_x = opt->setRandomFields(simple->getDM(), {
477
478 {"U", {-1, 1}}
479
480 });
481
482 auto test_domain_ops = [&](auto fe_name, auto lhs_pipeline,
483 auto rhs_pipeline) {
485
486 auto diff_res = opt->checkCentralFiniteDifference(
487 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
488 SmartPetscObj<Vec>(), diff_x, 0, 0.5, eps);
489
490 // Calculate norm of difference between directional derivative calculated
491 // from finite difference, and tangent matrix.
492 double fnorm;
493 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
494 MOFEM_LOG_C("EXAMPLE", Sev::inform,
495 "Test consistency of tangent matrix %3.4e", fnorm);
496
497 constexpr double err = 1e-5;
498 if (fnorm > err)
499 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
500 "Norm of directional derivative too large err = %3.4e", fnorm);
501
503 };
504
505 MOFEM_LOG("EXAMPLE", Sev::inform)
506 << "Test operators with finite difference of directional "
507 "derivative";
508 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
509 pip->getDomainRhsFE());
510
512}
513
516
517 auto *simple = mField.getInterface<Simple>();
518 auto *pipeline_mng = mField.getInterface<PipelineManager>();
519
520 auto integration_rule = [](int, int, int approx_order) {
521 return 2 * (approx_order - 1) + 1;
522 };
523
524 CHKERR pipeline_mng->setDomainRhsIntegrationRule(integration_rule);
525 CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
526 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(integration_rule);
527
528#ifdef WITH_ADOL_C
529 auto mat_ops_data_ptr = MatOps::createMatOpsDataPtr();
533 modelType>(
534 mat_ops_data_ptr,
536 }
537
538 #ifdef WITH_ADOL_C_GENERIC_ELASTIC
539 {
540 auto generic_physical_equations_ptr =
542 modelType>(
543 mat_ops_data_ptr,
545
547 // In example, lets do a simple linear elastic material, so we can verify the tangent matrix
548 generic_physical_equations_ptr->hookEvaluateVariable =
550 generic_physical_equations_ptr->hookEvaluateDerivatives =
552 generic_physical_equations_ptr->hookUpdateState =
554
555 CHKERR generic_physical_equations_ptr->getOptions(&mField);
556 CHKERR generic_physical_equations_ptr->recordTape();
557
558 auto &material_map = getMetaElasticMap(physicalEquationsPtr);
559 material_map[generic_physical_equations_ptr->tAg] =
560 generic_physical_equations_ptr;
561 physicalEquationsPtr->tAg = generic_physical_equations_ptr->tAg;
562 }
563 #endif // WITH_ADOL_C_GENERIC_ELASTIC
564
565 #ifdef WITH_ADOL_C_SIMPLE_DAMAGE
566 {
567 auto generic_physical_equations_ptr =
569 modelType>(
571 "GenericElasticSimpleDamage"));
572
574 mField, boost::dynamic_pointer_cast<MatOps::GenericElastic>(
575 generic_physical_equations_ptr));
576
577 CHKERR generic_physical_equations_ptr->getOptions(&mField);
578 CHKERR generic_physical_equations_ptr->recordTape();
579
580 auto &material_map = getMetaElasticMap(physicalEquationsPtr);
581 material_map[generic_physical_equations_ptr->tAg] =
582 generic_physical_equations_ptr;
583 physicalEquationsPtr->tAg = generic_physical_equations_ptr->tAg;
584 }
585 #endif // WITH_ADOL_C_SIMPLE_DAMAGE
586
588 CHKERR physicalEquationsPtr->getOptions(&mField);
589 CHKERR physicalEquationsPtr->recordTape();
590 }
591
592 if (!physicalHuHuPtr) {
593 const int tag_hu_hu = MatOps::MatOpsTagsRegistry::setTagName("HuHU");
595 MatOps::createMatOpsPhysicalEquationsPtr<MatOps::HUHU, modelType>(
596 MatOps::createMatOpsDataPtr(), tag_hu_hu);
597 CHKERR physicalHuHuPtr->getOptions(&mField);
598 CHKERR physicalHuHuPtr->recordTape();
599 }
600
601 auto add_domain_ops_lhs = [&](auto &pip) {
604 "GEOMETRY");
607 template opLhsFactory<PETSC, GAUSS, DomainEleOp>(
608 mField, pip, "U", physicalEquationsPtr);
609 }
610 if (physicalHuHuPtr) {
612 template opLhsFactory<PETSC, GAUSS, DomainEleOp>(
613 mField, pip, simple->getDomainFEName(), "U", physicalHuHuPtr);
614 }
616 };
617
618 auto add_domain_ops_rhs = [&](auto &pip) {
621 "GEOMETRY");
624 template opRhsFactory<PETSC, GAUSS, DomainEleOp>(
625 mField, pip, "U", physicalEquationsPtr);
626 }
627 if (physicalHuHuPtr) {
629 template opRhsFactory<PETSC, GAUSS, DomainEleOp>(
630 mField, pip, simple->getDomainFEName(), "U", physicalHuHuPtr);
631 }
633 };
634
635 auto add_domain_ops_update = [&](auto &pip) {
638 "GEOMETRY");
642 }
644 };
645
646 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
647 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
648
649 updateFe = boost::make_shared<DomainEle>(mField);
650 updateFe->getRuleHook = integration_rule;
651 CHKERR add_domain_ops_update(updateFe->getOpPtrVector());
652
653 reactionFe = boost::make_shared<DomainEle>(mField);
654 reactionFe->getRuleHook = integration_rule;
655 CHKERR add_domain_ops_rhs(reactionFe->getOpPtrVector());
656 reactionFe->postProcessHook =
657 EssentialPreProcReaction<DisplacementCubitBcData>(mField, reactionFe);
658
659 PetscBool post_proc_vol;
660 PetscBool post_proc_skin;
661
662 if constexpr (SPACE_DIM == 2) {
663 post_proc_vol = PETSC_TRUE;
664 post_proc_skin = PETSC_FALSE;
665 } else {
666 post_proc_vol = PETSC_FALSE;
667 post_proc_skin = PETSC_TRUE;
668 }
669
670 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol",
671 &post_proc_vol, PETSC_NULLPTR);
672 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
673 &post_proc_skin, PETSC_NULLPTR);
674
675 // Setup postprocessing
676 auto create_post_proc_fe = [&]() {
677 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
678
679 auto post_proc_ele_domain = [&](auto &pip_domain) {
682 "GEOMETRY");
686 }
688 };
689
690 auto post_proc_map = [&](auto &pip, auto u_ptr) {
693 auto grad_ptr =
694 physicalEquationsPtr->matOpsDataPtr->getCommonDataPtr("grad");
695 auto first_piola_ptr =
696 physicalEquationsPtr->matOpsDataPtr->getCommonDataPtr("P");
697 pip->getOpPtrVector().push_back(new OpPPMap(
698 pip->getPostProcMesh(), pip->getMapGaussPts(), {}, {{"U", u_ptr}},
699 {{"GRAD", grad_ptr}, {"FIRST_PIOLA", first_piola_ptr}}, {}));
700 }
702 };
703
704 auto push_post_proc_bdy = [&](auto &pip_bdy) {
705 if (post_proc_skin == PETSC_FALSE)
706 return boost::shared_ptr<PostProcEleBdy>();
707 auto simple = mField.getInterface<Simple>();
708 auto domain_fe_name = simple->getDomainFEName();
709 auto u_ptr = boost::make_shared<MatrixDouble>();
710 pip_bdy->getOpPtrVector().push_back(
711 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
712 auto op_loop_side =
713 new OpLoopSide<SideEle>(mField, domain_fe_name, SPACE_DIM);
714 CHKERR post_proc_ele_domain(op_loop_side->getOpPtrVector());
715 pip_bdy->getOpPtrVector().push_back(op_loop_side);
716 CHKERR post_proc_map(pip_bdy, u_ptr);
717 return pip_bdy;
718 };
719
720 auto push_post_proc_domain = [&](auto &pip_domain) {
721 if (post_proc_vol == PETSC_FALSE)
722 return boost::shared_ptr<PostProcEleDomain>();
723 auto u_ptr = boost::make_shared<MatrixDouble>();
724 pip_domain->getOpPtrVector().push_back(
725 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
726 CHKERR post_proc_ele_domain(pip_domain->getOpPtrVector());
727
729 auto state_data_ptr = physicalEquationsPtr->matOpsDataPtr;
730 auto state_tags = physicalEquationsPtr->matOpsDataPtr->getStateTags();
731 if (!state_tags.empty()) {
732 auto simple = mField.getInterface<Simple>();
733 int state_order = 2;
734 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &state_order,
735 PETSC_NULLPTR);
736 auto op_loop_this = new OpLoopThis<DomainEle>(
737 mField, simple->getDomainFEName(), Sev::noisy);
738 op_loop_this->getThisFEPtr()->getRuleHook = integration_rule;
739 pip_domain->getOpPtrVector().push_back(op_loop_this);
740 CHKERR addTagDGProjectionOps<SPACE_DIM, SPACE_DIM>(
741 mField.get_moab(), pip_domain->getOpPtrVector(),
742 op_loop_this->getThisFEPtr()->getOpPtrVector(),
743 pip_domain->getPostProcMesh(), pip_domain->getMapGaussPts(),
744 state_tags, state_order);
745 }
746 }
747
748 CHKERR post_proc_map(pip_domain, u_ptr);
749
750 return pip_domain;
751 };
752
753 auto post_proc_fe_domain = boost::make_shared<PostProcEleDomain>(mField);
754 auto post_proc_fe_bdy = boost::make_shared<PostProcEleBdy>(mField);
755
756 return std::make_pair(push_post_proc_domain(post_proc_fe_domain),
757 push_post_proc_bdy(post_proc_fe_bdy));
758 };
759
760 auto post_proc_pair = create_post_proc_fe();
761 postProcDomainFe = post_proc_pair.first;
762 postProcBdyFe = post_proc_pair.second;
763
764#else
765 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
766 "ADOL-C support is not enabled. Please reconfigure with "
767 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
768
769#endif // WITH_ADOL
771}
772
773//! [TS Solve]
776 auto *simple = mField.getInterface<Simple>();
777 auto *pipeline_mng = mField.getInterface<PipelineManager>();
778
779 auto dm = simple->getDM();
780 auto ts = pipeline_mng->createTSIM();
781
782 auto add_extra_finite_elements_to_solver_pipelines = [&]() {
784
785 auto pre_proc_ptr = boost::make_shared<FEMethod>();
786 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
787 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
788
789 auto time_scale = boost::make_shared<ExampleTimeScale>();
790
791 auto get_bc_hook_rhs = [this, pre_proc_ptr, time_scale]() {
793 CHKERR EssentialPreProc<DisplacementCubitBcData>(mField, pre_proc_ptr,
794 {time_scale}, false)();
796 };
797
798 pre_proc_ptr->preProcessHook = get_bc_hook_rhs;
799
800 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
802 CHKERR EssentialPreProcReaction<DisplacementCubitBcData>(
803 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
804 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(
805 mField, post_proc_rhs_ptr, 1.)();
807 };
808 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
810 CHKERR EssentialPostProcLhs<DisplacementCubitBcData>(
811 mField, post_proc_lhs_ptr, 1.)();
813 };
814 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
815 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs;
816
817 // This is low level pushing finite elements (pipelines) to solver
818 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
819 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
820 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
821 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
822 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
824 };
825
826 // Add extra finite elements to SNES solver pipelines to resolve essential
827 // boundary conditions
828 CHKERR add_extra_finite_elements_to_solver_pipelines();
829
830 auto create_monitor_fe = [dm](auto &&post_proc_fe, auto &&reactionFe) {
831 return boost::make_shared<Monitor>(dm.get(), post_proc_fe, reactionFe);
832 };
833
834 // Set monitor which postprocessing results and saves them to the hard drive
835 boost::shared_ptr<FEMethod> null_fe;
837 CHKERR postProcDomainFe->setTagsToTransfer(
838 std::vector<Tag>(listTagsToTransfer));
839 if (postProcBdyFe)
840 CHKERR postProcBdyFe->setTagsToTransfer(
841 std::vector<Tag>(listTagsToTransfer));
842 auto monitor_ptr = create_monitor_fe(
843 std::make_pair(postProcDomainFe, postProcBdyFe), reactionFe);
844 CHKERR DMMoFEMTSSetMonitor(dm, ts, simple->getDomainFEName(), null_fe,
845 null_fe, monitor_ptr);
846
847 // Set time solver
848 double ftime = 1;
849 CHKERR TSSetMaxTime(ts, ftime);
850 CHKERR TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
851
852 auto B = createDMMatrix(dm);
853 CHKERR TSSetI2Jacobian(ts, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
854 auto D = createDMVector(simple->getDM());
855 CHKERR TSSetSolution(ts, D);
856 CHKERR TSSetFromOptions(ts);
857
859 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
860 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
861 CHKERR TSSolve(ts, NULL);
863
864 CHKERR TSGetTime(ts, &ftime);
865
866 PetscInt steps, snesfails, rejects, nonlinits, linits;
867 CHKERR TSGetStepNumber(ts, &steps);
868 CHKERR TSGetSNESFailures(ts, &snesfails);
869 CHKERR TSGetStepRejections(ts, &rejects);
870 CHKERR TSGetSNESIterations(ts, &nonlinits);
871 CHKERR TSGetKSPIterations(ts, &linits);
872 MOFEM_LOG_C("EXAMPLE", Sev::inform,
873 "steps %d (%d rejected, %d SNES fails), ftime %g, nonlinits "
874 "%d, linits %d",
875 steps, rejects, snesfails, ftime, nonlinits, linits);
876
878}
879//! [TS Solve]
880
881//! [Getting norms]
884
885 auto simple = mField.getInterface<Simple>();
886 auto dm = simple->getDM();
887
888 auto T = createDMVector(simple->getDM());
889 CHKERR DMoFEMMeshToLocalVector(simple->getDM(), T, INSERT_VALUES,
890 SCATTER_FORWARD);
891 double nrm2;
892 CHKERR VecNorm(T, NORM_2, &nrm2);
893 MOFEM_LOG("EXAMPLE", Sev::inform) << "Solution norm " << nrm2;
894
895 auto post_proc_norm_fe = boost::make_shared<DomainEle>(mField);
896
897 auto post_proc_norm_rule_hook = [](int, int, int p) -> int { return 2 * p; };
898 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
899
901 post_proc_norm_fe->getOpPtrVector(), {H1}, "GEOMETRY");
902
903 enum NORMS { U_NORM_L2 = 0, PIOLA_NORM, LAST_NORM };
904 auto norms_vec =
905 createVectorMPI(mField.get_comm(),
906 (mField.get_comm_rank() == 0) ? LAST_NORM : 0, LAST_NORM);
907 CHKERR VecZeroEntries(norms_vec);
908
909 auto u_ptr = boost::make_shared<MatrixDouble>();
910 post_proc_norm_fe->getOpPtrVector().push_back(
911 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
912
913 post_proc_norm_fe->getOpPtrVector().push_back(
914 new OpCalcNormL2Tensor1<SPACE_DIM>(u_ptr, norms_vec, U_NORM_L2));
915
916 if (useAdolcMaterial == PETSC_TRUE) {
917#ifdef WITH_ADOL_C
920 opPostProcFactory(mField, post_proc_norm_fe->getOpPtrVector(), "U",
922 auto m_P = physicalEquationsPtr->matOpsDataPtr->getCommonDataPtr("P");
923 post_proc_norm_fe->getOpPtrVector().push_back(
924 new OpCalcNormL2Tensor2<SPACE_DIM, SPACE_DIM>(m_P, norms_vec,
925 PIOLA_NORM));
926 }
927#else
928 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
929 "ADOL-C support is not enabled. Please reconfigure with "
930 "-DWITH_ADOL_C=ON and recompile to use AdolC material model.");
931#endif
932 } else {
933 auto common_ptr = commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
934 mField, post_proc_norm_fe->getOpPtrVector(), "U", "MAT_ELASTIC",
935 Sev::inform);
936 post_proc_norm_fe->getOpPtrVector().push_back(
937 new OpCalcNormL2Tensor2<SPACE_DIM, SPACE_DIM>(
938 common_ptr->getMatFirstPiolaStress(), norms_vec, PIOLA_NORM));
939 }
940
941 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
942 post_proc_norm_fe);
943
944 CHKERR VecAssemblyBegin(norms_vec);
945 CHKERR VecAssemblyEnd(norms_vec);
946
947 MOFEM_LOG_CHANNEL("SELF"); // Clear channel from old tags
948 if (mField.get_comm_rank() == 0) {
949 const double *norms;
950 CHKERR VecGetArrayRead(norms_vec, &norms);
951 MOFEM_TAG_AND_LOG("SELF", Sev::inform, "example")
952 << "norm_u: " << std::scientific << std::sqrt(norms[U_NORM_L2]);
953 MOFEM_TAG_AND_LOG("SELF", Sev::inform, "example")
954 << "norm_piola: " << std::scientific << std::sqrt(norms[PIOLA_NORM]);
955 CHKERR VecRestoreArrayRead(norms_vec, &norms);
956 }
957
959}
960//! [Getting norms]
961
962//! [Postprocessing results]
967//! [Postprocessing results]
968
969//! [Check]
972 PetscInt test_nb = 0;
973 PetscBool test_flg = PETSC_FALSE;
974 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-test", &test_nb, &test_flg);
975
976 if (test_flg) {
977 auto simple = mField.getInterface<Simple>();
978 auto T = createDMVector(simple->getDM());
979 CHKERR DMoFEMMeshToLocalVector(simple->getDM(), T, INSERT_VALUES,
980 SCATTER_FORWARD);
981 double nrm2;
982 CHKERR VecNorm(T, NORM_2, &nrm2);
983 MOFEM_LOG("EXAMPLE", Sev::verbose) << "Regression norm " << nrm2;
984 double regression_value = 0;
985 switch (test_nb) {
986 case 1:
987 regression_value = 3.5112e-01;
988 break;
989 case 2:
990 regression_value = 1.8841e+00;
991 break;
992 case 3:
993 regression_value = 1.8841e+00;
994 break;
995 default:
996 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID, "Wrong test number.");
997 break;
998 }
999 if (fabs(nrm2 - regression_value) > 1e-2)
1000 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1001 "Regression test field; wrong norm value. %6.4e != %6.4e", nrm2,
1002 regression_value);
1003 }
1005}
1006//! [Check]
#define MOFEM_LOG_C(channel, severity, format,...)
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
static const double eps
constexpr int SPACE_DIM
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 MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ H1
continuous field
Definition definitions.h:85
#define MYPCOMM_INDEX
default communicator number PCOMM
#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_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 ...
constexpr int order
auto integration_rule
#define MOFEM_LOG(channel, severity)
Log.
#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.
double D
MoFEMErrorCode configureSimpleDamage(MoFEM::Interface &m_field, boost::shared_ptr< MatOps::GenericElastic > physical_ptr)
@ MODEL_3D
Definition MatOps.hpp:171
boost::shared_ptr< PhysicalEquations > createMatOpsPhysicalEquationsPtr(boost::shared_ptr< MatOpsData > mat_ops_data_ptr, int tag)
boost::shared_ptr< MatOpsData > createMatOpsDataPtr()
Definition MatOps.cpp:671
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
static MoFEMErrorCode hookEvaluateVariable(boost::shared_ptr< MatOps::MatOpsData > mat_ops_data_ptr, int, EntityHandle, int)
static MoFEMErrorCode hookEvaluateDerivatives(boost::shared_ptr< MatOps::MatOpsData > mat_ops_data_ptr, int, EntityHandle, int)
static MoFEMErrorCode hookUpdateState(boost::shared_ptr< MatOps::MatOpsData >, int, EntityHandle, int)
static int setTagName(std::string name, int tag=-1)
Definition MatOps.cpp:30
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Post post-proc data at points from hash maps.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
static NonlinearElasticExample * elasticExamplePtr
static MoFEMErrorCode postStepInitialise(NonlinearElasticExample *example_ptr)
NonlinearElasticExample(MoFEM::Interface &m_field)
MoFEMErrorCode runProblem()
[Run problem]
boost::shared_ptr< PostProcEleBdy > postProcBdyFe
boost::shared_ptr< DomainEle > reactionFe
std::vector< Tag > listTagsToTransfer
list of tags to transfer to postprocessor
boost::shared_ptr< MatOps::PhysicalEquations > physicalEquationsPtr
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode readMesh()
[Run problem]
MoFEMErrorCode assembleSystemHencky()
[Boundary condition]
MoFEMErrorCode boundaryCondition()
[Set up problem]
MoFEMErrorCode opTest()
[Push operators to pipeline]
boost::shared_ptr< PostProcEleDomain > postProcDomainFe
MoFEMErrorCode TsSolve()
[TS Solve]
MoFEMErrorCode outputResults()
[Getting norms]
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
MoFEMErrorCode checkResults()
[Postprocessing results]
boost::shared_ptr< MatOps::PhysicalEquations > physicalHuHuPtr
MoFEMErrorCode gettingNorms()
[TS Solve]
boost::shared_ptr< DomainEle > updateFe