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
17//! [Define dimension]
18constexpr int SPACE_DIM =
19 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
20//! [Define dimension]
21constexpr AssemblyType A = (SCHUR_ASSEMBLE)
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 {};
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));
69PetscBool is_plane_strain = PETSC_FALSE;
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_NULL, NULL, "-base", list_bases,
133 LASBASETOPT, &choice_base_value, PETSC_NULL);
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_NULL, "", "-order", &order, PETSC_NULL);
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_NULL, "", "-plane_strain", &is_plane_strain,
171 PETSC_NULL);
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
194 // adding MPCs
195 CHKERR bc_mng->addBlockDOFsToMPCs(simple->getProblemName(), "U");
196
198}
199//! [Boundary condition]
200
201//! [Push operators to pipeline]
204 auto pip = mField.getInterface<PipelineManager>();
205
206 //! [Integration rule]
207 auto integration_rule = [](int, int, int approx_order) {
208 return 2 * approx_order + 1;
209 };
210
211 auto integration_rule_bc = [](int, int, int approx_order) {
212 return 2 * approx_order + 1;
213 };
214
216 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
217 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
218 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
219 //! [Integration rule]
220
222 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
224 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
226 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
228 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
229
230 //! [Push domain stiffness matrix to pipeline]
231 // Add LHS operator for elasticity (stiffness matrix)
232 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
233 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
234 //! [Push domain stiffness matrix to pipeline]
235
236 // Add RHS operator for internal forces
237 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
238 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
239
240 //! [Push Body forces]
242 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
243 //! [Push Body forces]
244
245 //! [Push natural boundary conditions]
246 // Add force boundary condition
248 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
249 // Add case for mix type of BCs
251 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::verbose);
252 //! [Push natural boundary conditions]
254}
255//! [Push operators to pipeline]
256
257struct SetUpSchur {
258 static boost::shared_ptr<SetUpSchur>
261
262protected:
263 SetUpSchur() = default;
264};
265
266//! [Solve]
270 auto pip = mField.getInterface<PipelineManager>();
271 auto solver = pip->createKSP();
272 CHKERR KSPSetFromOptions(solver);
273
274 auto dm = simple->getDM();
275 auto D = createDMVector(dm);
276 auto F = vectorDuplicate(D);
277
278 auto set_essential_bc = [&]() {
280 // This is low level pushing finite elements (pipelines) to solver
281 auto ksp_ctx_ptr = getDMKspCtx(dm);
282
283 auto pre_proc_rhs = boost::make_shared<FEMethod>();
284 auto post_proc_rhs = boost::make_shared<FEMethod>();
285 auto post_proc_lhs = boost::make_shared<FEMethod>();
286
287 auto get_pre_proc_hook = [&]() {
289 {});
290 };
291 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
292
293 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
295
297 post_proc_rhs, 1.)();
298 CHKERR EssentialPostProcRhs<MPCsType>(mField, post_proc_rhs, 1.)();
300 };
301
302 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
304
306 post_proc_lhs, 1.)();
309 };
310
311 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
312 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
313
314 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
315 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
316 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
318 };
319
320 auto setup_and_solve = [&]() {
322 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
323 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp";
324 CHKERR KSPSetUp(solver);
325 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp <= Done";
326 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve";
327 CHKERR KSPSolve(solver, F, D);
328 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve <= Done";
330 };
331
332 MOFEM_LOG_CHANNEL("TIMER");
333 MOFEM_LOG_TAG("TIMER", "timer");
334
335 CHKERR set_essential_bc();
336
337 if (A == AssemblyType::BLOCK_SCHUR || A == AssemblyType::SCHUR) {
338 auto schur_ptr = SetUpSchur::createSetUpSchur(mField);
339 CHKERR schur_ptr->setUp(solver);
340 CHKERR setup_and_solve();
341 } else {
342 CHKERR setup_and_solve();
343 }
344
345 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
346 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
347 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
348
349 auto evaluate_field_at_the_point = [&]() {
351
352 int coords_dim = SPACE_DIM;
353 std::array<double, SPACE_DIM> field_eval_coords;
354 PetscBool do_eval_field = PETSC_FALSE;
355 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
356 field_eval_coords.data(), &coords_dim,
358
359 if (do_eval_field) {
360
361 vectorFieldPtr = boost::make_shared<MatrixDouble>();
362 auto field_eval_data =
363 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
364
366 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
367
368 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
369 auto no_rule = [](int, int, int) { return -1; };
370 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
371 field_eval_fe_ptr->getRuleHook = no_rule;
372
373 field_eval_fe_ptr->getOpPtrVector().push_back(
375
377 ->evalFEAtThePoint<SPACE_DIM>(
378 field_eval_coords.data(), 1e-12, simple->getProblemName(),
379 simple->getDomainFEName(), field_eval_data,
381 QUIET);
382
383 if (vectorFieldPtr->size1()) {
384 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
385 if constexpr (SPACE_DIM == 2)
386 MOFEM_LOG("FieldEvaluator", Sev::inform)
387 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
388 else
389 MOFEM_LOG("FieldEvaluator", Sev::inform)
390 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
391 << " U_Z: " << t_disp(2);
392 }
393
395 }
397 };
398
399 CHKERR evaluate_field_at_the_point();
400
402}
403//! [Solve]
404
405//! [Postprocess results]
409 auto pip = mField.getInterface<PipelineManager>();
410 auto det_ptr = boost::make_shared<VectorDouble>();
411 auto jac_ptr = boost::make_shared<MatrixDouble>();
412 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
413 //! [Postprocess clean]
414 pip->getDomainRhsFE().reset();
415 pip->getDomainLhsFE().reset();
416 pip->getBoundaryRhsFE().reset();
417 pip->getBoundaryLhsFE().reset();
418 //! [Postprocess clean]
419
420 //! [Postprocess initialise]
421 auto post_proc_mesh = boost::make_shared<moab::Core>();
422 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
423 mField, post_proc_mesh);
424 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
425 mField, post_proc_mesh);
426 //! [Postprocess initialise]
427
428 // lamdaa function to calculate dispalcement, strain and stress
429 auto calculate_stress_ops = [&](auto &pip) {
430 // Add H1 geometry ops
432
433 // Use HookeOps commonDataFactory to get matStrainPtr and matCauchyStressPtr
434 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEle>(
435 mField, pip, "U", "MAT_ELASTIC", Sev::verbose);
436
437 // Store U and GEOMETRY values if needed
438 auto u_ptr = boost::make_shared<MatrixDouble>();
439 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
440 auto x_ptr = boost::make_shared<MatrixDouble>();
441 pip.push_back(
442 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
443
444 // Return what you need: displacements, coordinates, strain, stress
445 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
446 common_ptr->getMatCauchyStress());
447 };
448
449 auto get_tag_id_on_pmesh = [&](bool post_proc_skin) {
450 int def_val_int = 0;
451 Tag tag_mat;
452 CHKERR mField.get_moab().tag_get_handle(
453 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
454 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
455 auto meshset_vec_ptr =
456 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
457 std::regex((boost::format("%s(.*)") % "MAT_ELASTIC").str()));
458
459 Range skin_ents;
460 std::unique_ptr<Skinner> skin_ptr;
461 if (post_proc_skin) {
462 skin_ptr = std::make_unique<Skinner>(&mField.get_moab());
463 auto boundary_meshset = simple->getBoundaryMeshSet();
464 CHKERR mField.get_moab().get_entities_by_handle(boundary_meshset,
465 skin_ents, true);
466 }
467
468 for (auto m : meshset_vec_ptr) {
469 Range ents_3d;
470 CHKERR mField.get_moab().get_entities_by_handle(m->getMeshset(), ents_3d,
471 true);
472 int const id = m->getMeshsetId();
473 ents_3d = ents_3d.subset_by_dimension(SPACE_DIM);
474 if (post_proc_skin) {
475 Range skin_faces;
476 CHKERR skin_ptr->find_skin(0, ents_3d, false, skin_faces);
477 ents_3d = intersect(skin_ents, skin_faces);
478 }
479 CHKERR mField.get_moab().tag_clear_data(tag_mat, ents_3d, &id);
480 }
481
482 return tag_mat;
483 };
484
485 auto post_proc_domain = [&](auto post_proc_mesh) {
486 auto post_proc_fe =
487 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
489
490 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
491 calculate_stress_ops(post_proc_fe->getOpPtrVector());
492
493 post_proc_fe->getOpPtrVector().push_back(
494
495 new OpPPMap(
496
497 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
498
499 {},
500
501 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
502
503 {},
504
505 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
506
507 )
508
509 );
510
511 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(false)});
512 return post_proc_fe;
513 };
514
515 auto post_proc_boundary = [&](auto post_proc_mesh) {
516 auto post_proc_fe =
517 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
519 post_proc_fe->getOpPtrVector(), {}, "GEOMETRY");
520 auto op_loop_side =
521 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
522 // push ops to side element, through op_loop_side operator
523 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
524 calculate_stress_ops(op_loop_side->getOpPtrVector());
525 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
526 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
527 post_proc_fe->getOpPtrVector().push_back(
528 new ElasticExample::OpCalculateTraction(mat_stress_ptr,
529 mat_traction_ptr));
530
532
533 post_proc_fe->getOpPtrVector().push_back(
534
535 new OpPPMap(
536
537 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
538
539 {},
540
541 {{"U", u_ptr}, {"GEOMETRY", x_ptr}, {"T", mat_traction_ptr}},
542
543 {},
544
545 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
546
547 )
548
549 );
550
551 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(true)});
552 return post_proc_fe;
553 };
554
555 PetscBool post_proc_skin_only = PETSC_FALSE;
556 if (SPACE_DIM == 3) {
557 post_proc_skin_only = PETSC_TRUE;
558 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_skin_only",
559 &post_proc_skin_only, PETSC_NULL);
560 }
561 if (post_proc_skin_only == PETSC_FALSE) {
562 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
563 } else {
564 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
565 }
566
568 post_proc_begin->getFEMethod());
569 CHKERR pip->loopFiniteElements();
571 post_proc_end->getFEMethod());
572
573 CHKERR post_proc_end->writeFile("out_elastic.h5m");
575}
576//! [Postprocess results]
577
578//! [Check]
580 MOFEM_LOG_CHANNEL("WORLD");
582 auto pip = mField.getInterface<PipelineManager>();
584 pip->getDomainRhsFE().reset();
585 pip->getDomainLhsFE().reset();
586 pip->getBoundaryRhsFE().reset();
587 pip->getBoundaryLhsFE().reset();
588
589 auto integration_rule = [](int, int, int p_data) { return 2 * p_data + 1; };
590 CHKERR pip->setDomainRhsIntegrationRule(integration_rule);
591 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule);
592
594 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
596 pip->getOpBoundaryRhsPipeline(), {}, "GEOMETRY");
597
598 // Add RHS operators for internal forces
599 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
600 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
601
603 pip->getOpDomainRhsPipeline(), mField, "U", Sev::verbose);
604
606 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::verbose);
607
608 auto dm = simple->getDM();
609 auto res = createDMVector(dm);
610 CHKERR VecSetDM(res, PETSC_NULL);
611
612 pip->getDomainRhsFE()->f = res;
613 pip->getBoundaryRhsFE()->f = res;
614
615 CHKERR VecZeroEntries(res);
616
617 CHKERR pip->loopFiniteElements();
618 // CHKERR mField.getInterface<FieldBlas>()->fieldScale(-1, "U");
619
620 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
621 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
622 CHKERR VecAssemblyBegin(res);
623 CHKERR VecAssemblyEnd(res);
624
625 auto zero_residual_at_constrains = [&]() {
627 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
628 auto get_post_proc_hook_rhs = [&]() {
631 mField, fe_post_proc_ptr, res)();
633 mField, fe_post_proc_ptr, 0, res)();
634 CHKERR EssentialPostProcRhs<MPCsType>(mField, fe_post_proc_ptr, 0, res)();
636 };
637 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
638 CHKERR DMoFEMPostProcessFiniteElements(dm, fe_post_proc_ptr.get());
640 };
641
642 CHKERR zero_residual_at_constrains();
643
644 double nrm2;
645 CHKERR VecNorm(res, NORM_2, &nrm2);
646 MOFEM_LOG_CHANNEL("WORLD");
647 MOFEM_LOG_C("WORLD", Sev::inform, "residual = %3.4e\n", nrm2);
648
649 int test = 0;
650 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-test", &test, PETSC_NULL);
651 if (test > 0) {
652 auto post_proc_residual = [&](auto dm, auto f_res, auto out_name) {
654 auto post_proc_fe =
655 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(mField);
657 auto u_vec = boost::make_shared<MatrixDouble>();
658 post_proc_fe->getOpPtrVector().push_back(
659 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_vec, f_res));
660 post_proc_fe->getOpPtrVector().push_back(
661
662 new OpPPMap(
663
664 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
665
666 {},
667
668 {{"RES", u_vec}},
669
670 {}, {})
671
672 );
673
674 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
675 post_proc_fe);
676 post_proc_fe->writeFile(out_name);
678 };
679
680 CHKERR post_proc_residual(simple->getDM(), res, "res.h5m");
681
682 constexpr double eps = 1e-8;
683 if (nrm2 > eps)
684 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
685 "Residual is not zero");
686 }
687 if (test == 2) {
688 if (!vectorFieldPtr || vectorFieldPtr->size1() == 0) {
689 SETERRQ1(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
690 "atom test %d failed: Field Evaluator did not provide result",
691 test);
692 }
693 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
694 double Ux_ref = 0.46;
695 double Uy_ref = -0.015;
696 constexpr double eps = 1e-8;
697 if (fabs(t_disp(0) - Ux_ref) > eps || fabs(t_disp(1) - Uy_ref) > eps) {
698 SETERRQ4(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
699 "atom test %d failed: Ux_ref = %3.6e, computed = %3.6e, Uy_ref "
700 "= %3.6e",
701 test, Ux_ref, t_disp(0), Uy_ref);
702 }
703 }
705}
706//! [Check]
707
708static char help[] = "...\n\n";
709
710int main(int argc, char *argv[]) {
711
712 // Initialisation of MoFEM/PETSc and MOAB data structures
713 const char param_file[] = "param_file.petsc";
714 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
715
716 auto core_log = logging::core::get();
717 core_log->add_sink(
719
720 core_log->add_sink(
722 LogManager::setLog("FieldEvaluator");
723 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
724
725 try {
726
727 //! [Register MoFEM discrete manager in PETSc]
728 DMType dm_name = "DMMOFEM";
729 CHKERR DMRegister_MoFEM(dm_name);
730 DMType dm_name_mg = "DMMOFEM_MG";
732 //! [Register MoFEM discrete manager in PETSc
733
734 //! [Create MoAB]
735 moab::Core mb_instance; ///< mesh database
736 moab::Interface &moab = mb_instance; ///< mesh database interface
737 //! [Create MoAB]
738
739 //! [Create MoFEM]
740 MoFEM::Core core(moab); ///< finite element database
741 MoFEM::Interface &m_field = core; ///< finite element database interface
742 //! [Create MoFEM]
743
744 //! [Example]
745 Example ex(m_field);
746 CHKERR ex.runProblem();
747 //! [Example]
748 }
750
752}
753
754struct SetUpSchurImpl : public SetUpSchur {
755
757 if (S) {
760 "Is expected that schur matrix is not allocated. This is "
761 "possible only is PC is set up twice");
762 }
763 }
764 virtual ~SetUpSchurImpl() = default;
765
767
768private:
774
776
778
783};
784
787 auto pip = mField.getInterface<PipelineManager>();
788 PC pc;
789 CHKERR KSPGetPC(solver, &pc);
790 PetscBool is_pcfs = PETSC_FALSE;
791 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
792 if (is_pcfs) {
793 if (S) {
796 "Is expected that schur matrix is not allocated. This is "
797 "possible only is PC is set up twice");
798 }
801
802 // Add data to DM storage
804 CHKERR MatSetDM(S, PETSC_NULL);
805 CHKERR MatSetBlockSize(S, SPACE_DIM);
806 CHKERR MatSetOption(S, MAT_SYMMETRIC, PETSC_TRUE);
807
809 CHKERR setPC(pc);
810
811 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
812 // Set DM to use shell block matrix
813 DM solver_dm;
814 CHKERR KSPGetDM(solver, &solver_dm);
815 CHKERR DMSetMatType(solver_dm, MATSHELL);
816 }
817 CHKERR KSPSetUp(solver);
819
820 } else {
821 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
822 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
823 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
824 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd({}, {}));
825 }
827}
828
832 CHKERR mField.get_moab().get_entities_by_dimension(simple->getMeshset(),
834 CHKERR mField.get_moab().get_entities_by_handle(simple->getMeshset(),
835 subEnts);
836 subEnts = subtract(subEnts, volEnts);
838};
839
843
844 auto create_dm = [&](const char *name, auto &ents, auto dm_type) {
845 auto dm = createDM(mField.get_comm(), dm_type);
846 auto create_dm_imp = [&]() {
848 CHKERR DMMoFEMCreateSubDM(dm, simple->getDM(), name);
849 CHKERR DMMoFEMSetSquareProblem(dm, PETSC_TRUE);
850 CHKERR DMMoFEMAddElement(dm, simple->getDomainFEName());
851 auto sub_ents_ptr = boost::make_shared<Range>(ents);
852 CHKERR DMMoFEMAddSubFieldRow(dm, "U", sub_ents_ptr);
853 CHKERR DMMoFEMAddSubFieldCol(dm, "U", sub_ents_ptr);
854 CHKERR DMSetUp(dm);
856 };
858 create_dm_imp(),
859 "Error in creating schurDM. It is possible that schurDM is "
860 "already created");
861 return dm;
862 };
863
864 schurDM = create_dm("SCHUR", subEnts, "DMMOFEM_MG");
865 blockDM = create_dm("BLOCK", volEnts, "DMMOFEM");
866
867 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
868
869 auto get_nested_mat_data = [&]() -> boost::shared_ptr<NestSchurData> {
870 auto block_mat_data =
872
873 {{
874
875 simple->getDomainFEName(),
876
877 {{"U", "U"}
878
879 }}}
880
881 );
882
884
885 {schurDM, blockDM}, block_mat_data,
886
887 {"U"}, {boost::make_shared<Range>(volEnts)}
888
889 );
890 };
891
892 auto nested_mat_data = get_nested_mat_data();
893
894 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
895 }
896
898}
899
903 auto pip = mField.getInterface<PipelineManager>();
904
905 // Boundary
906 auto dm_is = getDMSubData(schurDM)->getSmartRowIs();
907 auto ao_up = createAOMappingIS(dm_is, PETSC_NULL);
908 pip->getOpBoundaryLhsPipeline().push_front(createOpSchurAssembleBegin());
909 pip->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
910 {"U"}, {boost::make_shared<Range>(volEnts)}, ao_up, S, true, true));
911 // Domain
912 pip->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
913 pip->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
914 {"U"}, {boost::make_shared<Range>(volEnts)}, ao_up, S, true, true));
915
916 auto pre_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
917 auto post_proc_schur_lhs_ptr = boost::make_shared<FEMethod>();
918
919 pre_proc_schur_lhs_ptr->preProcessHook = [this]() {
921 if (S) {
922 CHKERR MatZeroEntries(S);
923 }
924 MOFEM_LOG("TIMER", Sev::inform) << "Lhs Assemble Begin";
926 };
927
928 post_proc_schur_lhs_ptr->postProcessHook = [this, post_proc_schur_lhs_ptr,
929 ao_up]() {
931 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
932 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
934 mField, post_proc_schur_lhs_ptr, 1, S, ao_up)();
935 MOFEM_LOG("TIMER", Sev::inform) << "Lhs Assemble End";
937 };
938
939 auto ksp_ctx_ptr = getDMKspCtx(simple->getDM());
940 ksp_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_schur_lhs_ptr);
941 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_schur_lhs_ptr);
942
944}
945
949 SmartPetscObj<IS> vol_is;
950 mField.getInterface<ISManager>()->isCreateProblemFieldAndRank(
951 simple->getProblemName(), ROW, "U", 0, SPACE_DIM, vol_is, &volEnts);
952 CHKERR PCFieldSplitSetIS(pc, NULL, vol_is);
953 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
955}
956
959
960 auto get_pc = [](auto ksp) {
961 PC pc_raw;
962 CHKERR KSPGetPC(ksp, &pc_raw);
963 return SmartPetscObj<PC>(pc_raw, true); // bump reference
964 };
965
966 if constexpr (A == AssemblyType::BLOCK_SCHUR) {
968 auto A = createDMBlockMat(simple->getDM());
969 auto P = createDMNestSchurMat(simple->getDM());
970 CHKERR PCSetOperators(pc, A, P);
971
972 KSP *subksp;
973 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
974 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
975
976 auto set_pc_p_mg = [](auto dm, auto pc, auto S) {
978 CHKERR PCSetDM(pc, dm);
979 PetscBool same = PETSC_FALSE;
980 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
981 if (same) {
982 MOFEM_LOG("TIMER", Sev::inform) << "Set up MG";
984 pc, createPCMGSetUpViaApproxOrdersCtx(dm, S, true));
985 CHKERR PCSetFromOptions(pc);
986 }
988 };
989
990 auto set_pc_ksp = [&](auto dm, auto pc, auto S) {
992 PetscBool same = PETSC_FALSE;
993 PetscObjectTypeCompare((PetscObject)pc, PCKSP, &same);
994 if (same) {
995 MOFEM_LOG("TIMER", Sev::inform) << "Set up inner KSP for PCKSP";
996 CHKERR PCSetFromOptions(pc);
997 KSP inner_ksp;
998 CHKERR PCKSPGetKSP(pc, &inner_ksp);
999 CHKERR KSPSetFromOptions(inner_ksp);
1000 PC inner_pc;
1001 CHKERR KSPGetPC(inner_ksp, &inner_pc);
1002 CHKERR PCSetFromOptions(inner_pc);
1003 CHKERR set_pc_p_mg(dm, inner_pc, S);
1004 }
1006 };
1007
1008 CHKERR set_pc_ksp(schurDM, get_pc(subksp[1]), S);
1009 CHKERR set_pc_p_mg(schurDM, get_pc(subksp[1]), S);
1010
1011 CHKERR PetscFree(subksp);
1012 }
1014}
1015
1016boost::shared_ptr<SetUpSchur>
1018 return boost::shared_ptr<SetUpSchur>(new SetUpSchurImpl(m_field));
1019}
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
PetscBool is_plane_strain
Definition adjoint.cpp:42
int main()
static const double eps
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
#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
Order displacement.
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
@ 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:1234
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1191
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]
@ PETSC
Standard PETSc assembly.
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
constexpr double eps
Definition HenckyOps.hpp:13
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:1248
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1292
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:1218
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:1211
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
Boundary conditions marker.
Definition elastic.cpp:39
[Define entities]
Definition elastic.cpp:38
[Example]
Definition plastic.cpp:216
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
FieldApproximationBase base
Choice of finite element basis functions
Definition plot_base.cpp:68
MoFEMErrorCode checkResults()
MoFEMErrorCode solveSystem()
Example(MoFEM::Interface &m_field)
Definition elastic.cpp:80
MoFEMErrorCode runProblem()
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:226
MoFEMErrorCode setupProblem()
MoFEMErrorCode outputResults()
boost::shared_ptr< MatrixDouble > vectorFieldPtr
Field values at evaluation points.
Definition adjoint.cpp:187
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
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
Specialization for double precision vector field values calculation.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
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< 2 >::FaceSideEle SideEle
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:756
SmartPetscObj< DM > schurDM
Definition contact.cpp:1025
MoFEMErrorCode setEntities()
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
SmartPetscObj< DM > blockDM
Definition contact.cpp:1026
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)
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
static char help[]
Definition elastic.cpp:68
PetscBool is_plane_strain
Definition elastic.cpp:69
constexpr int SPACE_DIM
[Define dimension]
Definition elastic.cpp:19
constexpr double poisson_ratio
Definition elastic.cpp:65
constexpr int BASE_DIM
Definition elastic.cpp:16
constexpr double shear_modulus_G
Definition elastic.cpp:67
constexpr IntegrationType I
Definition elastic.cpp:26
constexpr double bulk_modulus_K
Definition elastic.cpp:66
constexpr AssemblyType A
[Define dimension]
Definition elastic.cpp:22
constexpr double young_modulus
Definition elastic.cpp:64
constexpr int SPACE_DIM