v0.15.0
Loading...
Searching...
No Matches
elastic.cpp
Go to the documentation of this file.
1/**
2 * @file elastic.cpp
3 * @brief elastic example
4 * @version 0.13.2
5 * @date 2022-09-19
6 *
7 * @copyright Copyright (c) 2022
8 *
9 */
10
11#include <MoFEM.hpp>
12
13using namespace MoFEM;
14
15constexpr int BASE_DIM = 1; //< Dimension of the base functions
16
17//! [Define dimension]
18constexpr int SPACE_DIM =
19 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
20//! [Define dimension]
22 ? AssemblyType::BLOCK_SCHUR
23 : AssemblyType::PETSC; //< selected assembly type
24
25constexpr IntegrationType I =
26 IntegrationType::GAUSS; //< selected integration type
27
28//! [Define entities]
33using DomainEleOp = DomainEle::UserDataOperator;
34using BoundaryEleOp = BoundaryEle::UserDataOperator;
35//! [Define entities]
36
37struct DomainBCs {};
38struct BoundaryBCs {};
39
46
47template <int DIM> struct PostProcEleByDim;
48
49template <> struct PostProcEleByDim<2> {
53};
54
55template <> struct PostProcEleByDim<3> {
59};
60
64constexpr double young_modulus = 1;
65constexpr double poisson_ratio = 0.3;
66constexpr double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
67constexpr double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
68
69PetscBool is_plane_strain = PETSC_FALSE;
70
71#include <ElasticSpring.hpp>
72#include <FluidLevel.hpp>
73#include <CalculateTraction.hpp>
74#include <NaturalDomainBC.hpp>
75#include <NaturalBoundaryBC.hpp>
76#include <HookeOps.hpp>
77
78struct Example {
79
80 Example(MoFEM::Interface &m_field) : mField(m_field) {}
81
83
84private:
86
87 boost::shared_ptr<MatrixDouble> vectorFieldPtr = nullptr;
88
96};
97
98//! [Run problem]
109}
110//! [Run problem]
111
112//! [Read mesh]
117 CHKERR simple->loadFile();
118 // Add meshsets if config file provided
119 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
121}
122//! [Read mesh]
123
124//! [Set up problem]
128
129 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
130 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
131 PetscInt choice_base_value = AINSWORTH;
132 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
133 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
134
136 switch (choice_base_value) {
137 case AINSWORTH:
139 MOFEM_LOG("WORLD", Sev::inform)
140 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
141 break;
142 case DEMKOWICZ:
144 MOFEM_LOG("WORLD", Sev::inform)
145 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
146 break;
147 default:
148 base = LASTBASE;
149 break;
150 }
151
152 // Add field
153 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
154 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
155 int order = 3;
156 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
157
158 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
159
160 CHKERR simple->setFieldOrder("U", order);
161 CHKERR simple->setFieldOrder("GEOMETRY", 2);
162 CHKERR simple->setUp();
163
164 auto project_ho_geometry = [&]() {
165 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
166 return mField.loop_dofs("GEOMETRY", ent_method);
167 };
168 CHKERR project_ho_geometry();
169
170 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain", &is_plane_strain,
171 PETSC_NULLPTR);
172
174}
175//! [Set up problem]
176
177//! [Boundary condition]
181 auto bc_mng = mField.getInterface<BcManager>();
182
183 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
184 "U", 0, 0);
185 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
186 "U", 1, 1);
187 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
188 "U", 2, 2);
189 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
190 "REMOVE_ALL", "U", 0, 3);
191 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
192 simple->getProblemName(), "U");
193
195}
196//! [Boundary condition]
197
198//! [Push operators to pipeline]
201 auto pip = mField.getInterface<PipelineManager>();
202
203 //! [Integration rule]
204 auto integration_rule = [](int, int, int approx_order) {
205 return 2 * approx_order + 1;
206 };
207
208 auto integration_rule_bc = [](int, int, int approx_order) {
209 return 2 * approx_order + 1;
210 };
211
213 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
214 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
215 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
216 //! [Integration rule]
217
219 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
221 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
223 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
225 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
226
227 //! [Push domain stiffness matrix to pipeline]
228 // Add LHS operator for elasticity (stiffness matrix)
230 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
231 //! [Push domain stiffness matrix to pipeline]
232
233 // Add RHS operator for internal forces
235 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
236
237 //! [Push Body forces]
239 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
240 //! [Push Body forces]
241
242 //! [Push natural boundary conditions]
243 // Add force boundary condition
245 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
246 // Add case for mix type of BCs
248 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::verbose);
249 //! [Push natural boundary conditions]
251}
252//! [Push operators to pipeline]
253
254struct SetUpSchur {
255 static boost::shared_ptr<SetUpSchur>
258
259protected:
260 SetUpSchur() = default;
261};
262
263//! [Solve]
267 auto pip = mField.getInterface<PipelineManager>();
268 auto solver = pip->createKSP();
269 CHKERR KSPSetFromOptions(solver);
270
271 auto dm = simple->getDM();
272 auto D = createDMVector(dm);
273 auto F = vectorDuplicate(D);
274
275 auto set_essential_bc = [&]() {
277 // This is low level pushing finite elements (pipelines) to solver
278 auto ksp_ctx_ptr = getDMKspCtx(dm);
279
280 auto pre_proc_rhs = boost::make_shared<FEMethod>();
281 auto post_proc_rhs = boost::make_shared<FEMethod>();
282 auto post_proc_lhs = boost::make_shared<FEMethod>();
283
284 auto get_pre_proc_hook = [&]() {
286 {});
287 };
288 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
289
290 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
292
294 post_proc_rhs, 1.)();
296 };
297
298 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
300
302 post_proc_lhs, 1.)();
304 };
305
306 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
307 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
308
309 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
310 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
311 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
313 };
314
315 auto setup_and_solve = [&]() {
317 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
318 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp";
319 CHKERR KSPSetUp(solver);
320 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp <= Done";
321 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve";
322 CHKERR KSPSolve(solver, F, D);
323 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve <= Done";
325 };
326
327 MOFEM_LOG_CHANNEL("TIMER");
328 MOFEM_LOG_TAG("TIMER", "timer");
329
330 CHKERR set_essential_bc();
331
332 if (A == AssemblyType::BLOCK_SCHUR || A == AssemblyType::SCHUR) {
333 auto schur_ptr = SetUpSchur::createSetUpSchur(mField);
334 CHKERR schur_ptr->setUp(solver);
335 CHKERR setup_and_solve();
336 } else {
337 CHKERR setup_and_solve();
338 }
339
340 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
341 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
342 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
343
344 auto evaluate_field_at_the_point = [&]() {
346
347 int coords_dim = 3;
348 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
349 PetscBool do_eval_field = PETSC_FALSE;
350 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
351 field_eval_coords.data(), &coords_dim,
353
354 if (do_eval_field) {
355
356 vectorFieldPtr = boost::make_shared<MatrixDouble>();
357 auto field_eval_data =
358 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
359
361 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
362
363 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
364 auto no_rule = [](int, int, int) { return -1; };
365 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
366 field_eval_fe_ptr->getRuleHook = no_rule;
367
368 field_eval_fe_ptr->getOpPtrVector().push_back(
370
372 ->evalFEAtThePoint<SPACE_DIM>(
373 field_eval_coords.data(), 1e-12, simple->getProblemName(),
374 simple->getDomainFEName(), field_eval_data,
376 QUIET);
377
378 if (vectorFieldPtr->size1()) {
380 if constexpr (SPACE_DIM == 2)
381 MOFEM_LOG("FieldEvaluator", Sev::inform)
382 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
383 else
384 MOFEM_LOG("FieldEvaluator", Sev::inform)
385 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
386 << " U_Z: " << t_disp(2);
387 }
388
390 }
392 };
393
394 CHKERR evaluate_field_at_the_point();
395
397}
398//! [Solve]
399
400//! [Postprocess results]
404 auto pip = mField.getInterface<PipelineManager>();
405 auto det_ptr = boost::make_shared<VectorDouble>();
406 auto jac_ptr = boost::make_shared<MatrixDouble>();
407 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
408 //! [Postprocess clean]
409 pip->getDomainRhsFE().reset();
410 pip->getDomainLhsFE().reset();
411 pip->getBoundaryRhsFE().reset();
412 pip->getBoundaryLhsFE().reset();
413 //! [Postprocess clean]
414
415 //! [Postprocess initialise]
416 auto post_proc_mesh = boost::make_shared<moab::Core>();
417 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
418 mField, post_proc_mesh);
419 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
420 mField, post_proc_mesh);
421 //! [Postprocess initialise]
422
423 // lamdaa function to calculate dispalcement, strain and stress
424 auto calculate_stress_ops = [&](auto &pip) {
425 // Add H1 geometry ops
427
428 // Use HookeOps commonDataFactory to get matStrainPtr and matCauchyStressPtr
430 mField, pip, "U", "MAT_ELASTIC", Sev::verbose);
431
432 // Store U and GEOMETRY values if needed
433 auto u_ptr = boost::make_shared<MatrixDouble>();
434 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
435 auto x_ptr = boost::make_shared<MatrixDouble>();
436 pip.push_back(
437 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
438
439 // Return what you need: displacements, coordinates, strain, stress
440 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
441 common_ptr->getMatCauchyStress());
442 };
443
444 auto get_tag_id_on_pmesh = [&](bool post_proc_skin) {
445 int def_val_int = 0;
446 Tag tag_mat;
447 CHKERR mField.get_moab().tag_get_handle(
448 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
449 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
450 auto meshset_vec_ptr =
451 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
452 std::regex((boost::format("%s(.*)") % "MAT_ELASTIC").str()));
453
454 Range skin_ents;
455 std::unique_ptr<Skinner> skin_ptr;
456 if (post_proc_skin) {
457 skin_ptr = std::make_unique<Skinner>(&mField.get_moab());
458 auto boundary_meshset = simple->getBoundaryMeshSet();
459 CHKERR mField.get_moab().get_entities_by_handle(boundary_meshset,
460 skin_ents, true);
461 }
462
463 for (auto m : meshset_vec_ptr) {
464 Range ents_3d;
465 CHKERR mField.get_moab().get_entities_by_handle(m->getMeshset(), ents_3d,
466 true);
467 int const id = m->getMeshsetId();
468 ents_3d = ents_3d.subset_by_dimension(SPACE_DIM);
469 if (post_proc_skin) {
470 Range skin_faces;
471 CHKERR skin_ptr->find_skin(0, ents_3d, false, skin_faces);
472 ents_3d = intersect(skin_ents, skin_faces);
473 }
474 CHKERR mField.get_moab().tag_clear_data(tag_mat, ents_3d, &id);
475 }
476
477 return tag_mat;
478 };
479
480 auto post_proc_domain = [&](auto post_proc_mesh) {
481 auto post_proc_fe =
482 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
484
485 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
486 calculate_stress_ops(post_proc_fe->getOpPtrVector());
487
488 post_proc_fe->getOpPtrVector().push_back(
489
490 new OpPPMap(
491
492 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
493
494 {},
495
496 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
497
498 {},
499
500 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
501
502 )
503
504 );
505
506 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(false)});
507 return post_proc_fe;
508 };
509
510 auto post_proc_boundary = [&](auto post_proc_mesh) {
511 auto post_proc_fe =
512 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
514 post_proc_fe->getOpPtrVector(), {}, "GEOMETRY");
515 auto op_loop_side =
516 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
517 // push ops to side element, through op_loop_side operator
518 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
519 calculate_stress_ops(op_loop_side->getOpPtrVector());
520 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
521 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
522 post_proc_fe->getOpPtrVector().push_back(
523 new ElasticExample::OpCalculateTraction(mat_stress_ptr,
524 mat_traction_ptr));
525
527
528 post_proc_fe->getOpPtrVector().push_back(
529
530 new OpPPMap(
531
532 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
533
534 {},
535
536 {{"U", u_ptr}, {"GEOMETRY", x_ptr}, {"T", mat_traction_ptr}},
537
538 {},
539
540 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
541
542 )
543
544 );
545
546 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(true)});
547 return post_proc_fe;
548 };
549
550 PetscBool post_proc_skin_only = PETSC_FALSE;
551 if (SPACE_DIM == 3) {
552 post_proc_skin_only = PETSC_TRUE;
553 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin_only",
554 &post_proc_skin_only, PETSC_NULLPTR);
555 }
556 if (post_proc_skin_only == PETSC_FALSE) {
557 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
558 } else {
559 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
560 }
561
563 post_proc_begin->getFEMethod());
564 CHKERR pip->loopFiniteElements();
566 post_proc_end->getFEMethod());
567
568 CHKERR post_proc_end->writeFile("out_elastic.h5m");
570}
571//! [Postprocess results]
572
573//! [Check]
575 MOFEM_LOG_CHANNEL("WORLD");
577 auto pip = mField.getInterface<PipelineManager>();
579 pip->getDomainRhsFE().reset();
580 pip->getDomainLhsFE().reset();
581 pip->getBoundaryRhsFE().reset();
582 pip->getBoundaryLhsFE().reset();
583
584 auto integration_rule = [](int, int, int p_data) { return 2 * p_data + 1; };
585 CHKERR pip->setDomainRhsIntegrationRule(integration_rule);
586 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule);
587
589 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
591 pip->getOpBoundaryRhsPipeline(), {}, "GEOMETRY");
592
593 // Add RHS operators for internal forces
595 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
596
598 pip->getOpDomainRhsPipeline(), mField, "U", Sev::verbose);
599
601 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::verbose);
602
603 auto dm = simple->getDM();
604 auto res = createDMVector(dm);
605 CHKERR VecSetDM(res, PETSC_NULLPTR);
606
607 pip->getDomainRhsFE()->f = res;
608 pip->getBoundaryRhsFE()->f = res;
609
610 CHKERR VecZeroEntries(res);
611
612 CHKERR pip->loopFiniteElements();
613 // CHKERR mField.getInterface<FieldBlas>()->fieldScale(-1, "U");
614
615 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
616 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
617 CHKERR VecAssemblyBegin(res);
618 CHKERR VecAssemblyEnd(res);
619
620 auto zero_residual_at_constrains = [&]() {
622 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
623 auto get_post_proc_hook_rhs = [&]() {
626 mField, fe_post_proc_ptr, res)();
628 mField, fe_post_proc_ptr, 0, res)();
630 };
631 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
632 CHKERR DMoFEMPostProcessFiniteElements(dm, fe_post_proc_ptr.get());
634 };
635
636 CHKERR zero_residual_at_constrains();
637
638 double nrm2;
639 CHKERR VecNorm(res, NORM_2, &nrm2);
640 MOFEM_LOG_CHANNEL("WORLD");
641 MOFEM_LOG_C("WORLD", Sev::inform, "residual = %3.4e\n", nrm2);
642
643 int test = 0;
644 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-test", &test, PETSC_NULLPTR);
645 if (test > 0) {
646 auto post_proc_residual = [&](auto dm, auto f_res, auto out_name) {
648 auto post_proc_fe =
649 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(mField);
651 auto u_vec = boost::make_shared<MatrixDouble>();
652 post_proc_fe->getOpPtrVector().push_back(
653 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_vec, f_res));
654 post_proc_fe->getOpPtrVector().push_back(
655
656 new OpPPMap(
657
658 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
659
660 {},
661
662 {{"RES", u_vec}},
663
664 {}, {})
665
666 );
667
668 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
669 post_proc_fe);
670 post_proc_fe->writeFile(out_name);
672 };
673
674 CHKERR post_proc_residual(simple->getDM(), res, "res.h5m");
675
676 constexpr double eps = 1e-8;
677 if (nrm2 > eps)
678 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
679 "Residual is not zero");
680 }
681 if (test == 2) {
682 if (!vectorFieldPtr || vectorFieldPtr->size1() == 0) {
683 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
684 "atom test %d failed: Field Evaluator did not provide result",
685 test);
686 }
687 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
688 double Ux_ref = 0.46;
689 double Uy_ref = -0.015;
690 constexpr double eps = 1e-8;
691 if (fabs(t_disp(0) - Ux_ref) > eps || fabs(t_disp(1) - Uy_ref) > eps) {
692 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
693 "atom test %d failed: Ux_ref = %3.6e, computed = %3.6e, Uy_ref "
694 "= %3.6e",
695 test, Ux_ref, t_disp(0), Uy_ref);
696 }
697 }
699}
700//! [Check]
701
702static char help[] = "...\n\n";
703
704int main(int argc, char *argv[]) {
705
706 // Initialisation of MoFEM/PETSc and MOAB data structures
707 const char param_file[] = "param_file.petsc";
708 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
709
710 auto core_log = logging::core::get();
711 core_log->add_sink(
713
714 core_log->add_sink(
716 LogManager::setLog("FieldEvaluator");
717 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
718
719 try {
720
721 //! [Register MoFEM discrete manager in PETSc]
722 DMType dm_name = "DMMOFEM";
723 CHKERR DMRegister_MoFEM(dm_name);
724 DMType dm_name_mg = "DMMOFEM_MG";
726 //! [Register MoFEM discrete manager in PETSc
727
728 //! [Create MoAB]
729 moab::Core mb_instance; ///< mesh database
730 moab::Interface &moab = mb_instance; ///< mesh database interface
731 //! [Create MoAB]
732
733 //! [Create MoFEM]
734 MoFEM::Core core(moab); ///< finite element database
735 MoFEM::Interface &m_field = core; ///< finite element database interface
736 //! [Create MoFEM]
737
738 //! [Example]
739 Example ex(m_field);
740 CHKERR ex.runProblem();
741 //! [Example]
742 }
744
746}
747
748struct SetUpSchurImpl : public SetUpSchur {
749
751 if (S) {
754 "Is expected that schur matrix is not allocated. This is "
755 "possible only is PC is set up twice");
756 }
757 }
758 virtual ~SetUpSchurImpl() = default;
759
761
762private:
768
770
772
777};
778
781 auto pip = mField.getInterface<PipelineManager>();
782 PC pc;
783 CHKERR KSPGetPC(solver, &pc);
784 PetscBool is_pcfs = PETSC_FALSE;
785 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
786 if (is_pcfs) {
787 if (S) {
790 "Is expected that schur matrix is not allocated. This is "
791 "possible only is PC is set up twice");
792 }
795
796 // Add data to DM storage
798 CHKERR MatSetDM(S, PETSC_NULLPTR);
799 CHKERR MatSetBlockSize(S, SPACE_DIM);
800 CHKERR MatSetOption(S, MAT_SYMMETRIC, PETSC_TRUE);
801
803 CHKERR setPC(pc);
804
805 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
806 // Set DM to use shell block matrix
807 DM solver_dm;
808 CHKERR KSPGetDM(solver, &solver_dm);
809 CHKERR DMSetMatType(solver_dm, MATSHELL);
810 }
811 CHKERR KSPSetUp(solver);
813
814 } else {
815 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
816 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
817 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
818 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
819 }
821}
822
826 CHKERR mField.get_moab().get_entities_by_dimension(simple->getMeshset(),
828 CHKERR mField.get_moab().get_entities_by_handle(simple->getMeshset(),
829 subEnts);
830 subEnts = subtract(subEnts, volEnts);
832};
833
837
838 auto create_dm = [&](const char *name, auto &ents, auto dm_type) {
839 auto dm = createDM(mField.get_comm(), dm_type);
840 auto create_dm_imp = [&]() {
842 CHKERR DMMoFEMCreateSubDM(dm, simple->getDM(), name);
843 CHKERR DMMoFEMSetSquareProblem(dm, PETSC_TRUE);
844 CHKERR DMMoFEMAddElement(dm, simple->getDomainFEName());
845 auto sub_ents_ptr = boost::make_shared<Range>(ents);
846 CHKERR DMMoFEMAddSubFieldRow(dm, "U", sub_ents_ptr);
847 CHKERR DMMoFEMAddSubFieldCol(dm, "U", sub_ents_ptr);
848 CHKERR DMSetUp(dm);
850 };
852 create_dm_imp(),
853 "Error in creating schurDM. It is possible that schurDM is "
854 "already created");
855 return dm;
856 };
857
858 schurDM = create_dm("SCHUR", subEnts, "DMMOFEM_MG");
859 blockDM = create_dm("BLOCK", volEnts, "DMMOFEM");
860
861 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
862
863 auto get_nested_mat_data = [&]() -> boost::shared_ptr<NestSchurData> {
864 auto block_mat_data =
866
867 {{
868
869 simple->getDomainFEName(),
870
871 {{"U", "U"}
872
873 }}}
874
875 );
876
878
879 {schurDM, blockDM}, block_mat_data,
880
881 {"U"}, {boost::make_shared<Range>(volEnts)}
882
883 );
884 };
885
886 auto nested_mat_data = get_nested_mat_data();
887
888 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
889 }
890
892}
893
897 auto pip = mField.getInterface<PipelineManager>();
898
899 // Boundary
900 auto dm_is = getDMSubData(schurDM)->getSmartRowIs();
901 auto ao_up = createAOMappingIS(dm_is, PETSC_NULLPTR);
902 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
903 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
904 {"U"}, {boost::make_shared<Range>(volEnts)}, ao_up, S, true, true));
905 // Domain
906 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
907 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
908 {"U"}, {boost::make_shared<Range>(volEnts)}, ao_up, S, true, true));
909
910 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
911 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
912
913 pre_proc_schur_lhs_ptr->preProcessHook = [this]() {
915 if (S) {
916 CHKERR MatZeroEntries(S);
917 }
918 MOFEM_LOG("TIMER", Sev::inform) << "Lhs Assemble Begin";
920 };
921
922 post_proc_schur_lhs_ptr->postProcessHook = [this, post_proc_schur_lhs_ptr,
923 ao_up]() {
925 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
926 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
928 mField, post_proc_schur_lhs_ptr, 1, S, ao_up)();
929 MOFEM_LOG("TIMER", Sev::inform) << "Lhs Assemble End";
931 };
932
933 auto ksp_ctx_ptr = getDMKspCtx(simple->getDM());
934 ksp_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_schur_lhs_ptr);
935 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_schur_lhs_ptr);
936
938}
939
943 SmartPetscObj<IS> vol_is;
944 mField.getInterface<ISManager>()->isCreateProblemFieldAndRank(
945 simple->getProblemName(), ROW, "U", 0, SPACE_DIM, vol_is, &volEnts);
946 CHKERR PCFieldSplitSetIS(pc, NULL, vol_is);
947 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
949}
950
953
954 auto get_pc = [](auto ksp) {
955 PC pc_raw;
956 CHKERR KSPGetPC(ksp, &pc_raw);
957 return SmartPetscObj<PC>(pc_raw, true); // bump reference
958 };
959
960 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
962 auto A = createDMBlockMat(simple->getDM());
963 auto P = createDMNestSchurMat(simple->getDM());
964 CHKERR PCSetOperators(pc, A, P);
965
966 KSP *subksp;
967 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
968 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
969
970 auto set_pc_p_mg = [](auto dm, auto pc, auto S) {
972 CHKERR PCSetDM(pc, dm);
973 PetscBool same = PETSC_FALSE;
974 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
975 if (same) {
976 MOFEM_LOG("TIMER", Sev::inform) << "Set up MG";
978 pc, createPCMGSetUpViaApproxOrdersCtx(dm, S, true));
979 CHKERR PCSetFromOptions(pc);
980 }
982 };
983
984 auto set_pc_ksp = [&](auto dm, auto pc, auto S) {
986 PetscBool same = PETSC_FALSE;
987 PetscObjectTypeCompare((PetscObject)pc, PCKSP, &same);
988 if (same) {
989 MOFEM_LOG("TIMER", Sev::inform) << "Set up inner KSP for PCKSP";
990 CHKERR PCSetFromOptions(pc);
991 KSP inner_ksp;
992 CHKERR PCKSPGetKSP(pc, &inner_ksp);
993 CHKERR KSPSetFromOptions(inner_ksp);
994 PC inner_pc;
995 CHKERR KSPGetPC(inner_ksp, &inner_pc);
996 CHKERR PCSetFromOptions(inner_pc);
997 CHKERR set_pc_p_mg(dm, inner_pc, S);
998 }
1000 };
1001
1002 CHKERR set_pc_ksp(schurDM, get_pc(subksp[1]), S);
1003 CHKERR set_pc_p_mg(schurDM, get_pc(subksp[1]), S);
1004
1005 CHKERR PetscFree(subksp);
1006 }
1008}
1009
1010boost::shared_ptr<SetUpSchur>
1012 return boost::shared_ptr<SetUpSchur>(new SetUpSchurImpl(m_field));
1013}
Calculate traction for linear problem.
Implementation of elastic spring bc.
Natural boundary condition applying pressure from fluid.
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
PetscBool is_plane_strain
Definition adjoint.cpp:78
constexpr int SPACE_DIM
[Define dimension]
Definition adjoint.cpp:22
int main()
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
@ 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 nme:nme847.
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
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ 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
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
static char help[]
[Check]
Definition elastic.cpp:702
PetscBool is_plane_strain
Definition elastic.cpp:69
constexpr int SPACE_DIM
[Define dimension]
Definition elastic.cpp:18
constexpr double poisson_ratio
Definition elastic.cpp:65
constexpr int BASE_DIM
Definition elastic.cpp:15
constexpr double shear_modulus_G
Definition elastic.cpp:67
constexpr IntegrationType I
Definition elastic.cpp:25
constexpr double bulk_modulus_K
Definition elastic.cpp:66
constexpr double young_modulus
Definition elastic.cpp:64
@ F
auto integration_rule
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
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 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)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
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)
Get smart vector from DM.
Definition DMMoFEM.hpp:1102
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1059
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
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.
double D
MoFEMErrorCode opFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HookeOps::CommonData > common_ptr, Sev sev)
Assemble domain LHS K factory (LHS first overload) Initializes and pushes operators to assemble the L...
Definition HookeOps.hpp:302
auto commonDataFactory(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string block_name, Sev sev, double scale=1)
Definition HookeOps.hpp:208
MoFEMErrorCode opFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HookeOps::CommonData > common_ptr, Sev sev, bool is_non_linear=false)
Factory function to create and push internal force operators for the domain RHS. (RHS first overload)...
Definition HookeOps.hpp:242
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
OpSchurAssembleBase * createOpSchurAssembleEnd(std::vector< std::string > fields_name, std::vector< boost::shared_ptr< Range > > field_ents, SmartPetscObj< AO > ao, SmartPetscObj< Mat > schur, bool sym_schur, bool symm_op)
Construct a new Op Schur Assemble End object.
Definition Schur.cpp:2585
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:2627
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat)
createPCMGSetUpViaApproxOrdersCtx
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:1116
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1160
FTensor::Tensor1< FTensor::PackPtr< T *, S >, Tensor_Dim > getFTensor1FromMat(ublas::matrix< T, L, A > &data)
Get tensor rank 1 (vector) form data matrix.
MoFEMErrorCode PCMGSetUpViaApproxOrders(PC pc, boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > ctx, int verb)
Function build MG structure.
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create a Mat Diag Blocks object.
Definition Schur.cpp:1082
boost::shared_ptr< NestSchurData > createSchurNestedMatrixStruture(std::pair< SmartPetscObj< DM >, SmartPetscObj< DM > > dms, boost::shared_ptr< BlockStructure > block_mat_data_ptr, std::vector< std::string > fields_names, std::vector< boost::shared_ptr< Range > > field_ents, bool add_preconditioner_block)
Get the Schur Nest Mat Array object.
Definition Schur.cpp:2343
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1554
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1086
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:2580
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1079
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
[Define entities]
Definition elastic.cpp:37
[Example]
Definition plastic.cpp:216
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
FieldApproximationBase base
Definition plot_base.cpp:68
MoFEMErrorCode checkResults()
MoFEMErrorCode solveSystem()
Example(MoFEM::Interface &m_field)
Definition elastic.cpp:80
MoFEMErrorCode runProblem()
MoFEM::Interface & mField
Definition plastic.cpp:226
MoFEMErrorCode setupProblem()
MoFEMErrorCode outputResults()
boost::shared_ptr< MatrixDouble > vectorFieldPtr
Definition elastic.cpp:87
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
Definition BcManager.hpp:29
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:118
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
Data on single entity (This is passed as argument to DataOperator::doWork)
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 calculate residual side diagonal.
Definition Essential.hpp:49
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Field evaluator interface.
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
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 values at integration pts for tensor field rank 1, i.e. vector field.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
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
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
MoFEMErrorCode setUp(SmartPetscObj< KSP > solver)
virtual ~SetUpSchurImpl()=default
SmartPetscObj< Mat > S
MoFEMErrorCode createSubDM()
MoFEMErrorCode setDiagonalPC(PC pc)
SetUpSchurImpl(MoFEM::Interface &m_field)
Definition elastic.cpp:750
SmartPetscObj< DM > schurDM
Definition contact.cpp:1037
MoFEMErrorCode setEntities()
Definition elastic.cpp:823
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
SmartPetscObj< DM > blockDM
Definition contact.cpp:1038
MoFEMErrorCode setPC(PC pc)
MoFEMErrorCode setOperator()
MoFEM::Interface & mField
[Push operators to pipeline]
SetUpSchur()=default
virtual MoFEMErrorCode setUp(SmartPetscObj< KSP > solver)=0
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)