v0.15.4
Loading...
Searching...
No Matches
ElasticExample.hpp
Go to the documentation of this file.
1/**
2 * @file ElasticExample.hpp
3 *
4 * @brief Implementation of elastic example class
5 *
6 * @copyright Copyright (c) 2025
7 *
8 */
9
10#include <ElasticSpring.hpp>
11#include <FluidLevel.hpp>
12#include <CalculateTraction.hpp>
13#include <NaturalDomainBC.hpp>
14#include <NaturalBoundaryBC.hpp>
15#include <HookeOps.hpp>
16
18
19 ElasticExample(MoFEM::Interface &m_field) : mField(m_field) {}
20
21 MoFEMErrorCode runProblem();
22
23protected:
25 boost::shared_ptr<MatrixDouble> vectorFieldPtr = nullptr;
26
27 MoFEMErrorCode readMesh();
28 MoFEMErrorCode setupProblem();
29 MoFEMErrorCode boundaryCondition();
30 MoFEMErrorCode assembleSystem();
31 MoFEMErrorCode solveSystem();
32 MoFEMErrorCode outputResults();
33 MoFEMErrorCode checkResults();
34
35 // Auxiliary functions
36 virtual MoFEMErrorCode kspSetUpAndSolve(SmartPetscObj<KSP> solver);
37};
38
39//! [Run problem]
51//! [Run problem]
52
53//! [Read mesh]
54MoFEMErrorCode ElasticExample::readMesh() {
56 auto simple = mField.getInterface<Simple>();
57 CHKERR simple->getOptions();
58 CHKERR simple->loadFile();
59 // Add meshsets if config file provided
60 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
62}
63//! [Read mesh]
64
65//! [Set up problem]
68 Simple *simple = mField.getInterface<Simple>();
69
70 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
71 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
72 PetscInt choice_base_value = AINSWORTH;
73 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
74 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
75
77 switch (choice_base_value) {
78 case AINSWORTH:
80 MOFEM_LOG("WORLD", Sev::inform)
81 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
82 break;
83 case DEMKOWICZ:
85 MOFEM_LOG("WORLD", Sev::inform)
86 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
87 break;
88 default:
89 base = LASTBASE;
90 break;
91 }
92
93 // Add field
94 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
95 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
96 int order = 3;
97 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
98
99 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
100
101 CHKERR simple->setFieldOrder("U", order);
102 CHKERR simple->setFieldOrder("GEOMETRY", 2);
103 CHKERR simple->setUp();
104
105 auto project_ho_geometry = [&]() {
106 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
107 return mField.loop_dofs("GEOMETRY", ent_method);
108 };
109 CHKERR project_ho_geometry();
110
112}
113//! [Set up problem]
114
115//! [Boundary condition]
118 auto simple = mField.getInterface<Simple>();
119 auto bc_mng = mField.getInterface<BcManager>();
120
121 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
122 "U", 0, 0);
123 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
124 "U", 1, 1);
125 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
126 "U", 2, 2);
127 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
128 "REMOVE_ALL", "U", 0, 3);
129 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
130 simple->getProblemName(), "U");
131
133}
134//! [Boundary condition]
135
136//! [Push operators to pipeline]
139 auto pip = mField.getInterface<PipelineManager>();
140
141 //! [Integration rule]
142 auto integration_rule = [](int, int, int approx_order) {
143 return 2 * approx_order + 1;
144 };
145
146 auto integration_rule_bc = [](int, int, int approx_order) {
147 return 2 * approx_order + 1;
148 };
149
150 CHKERR pip->setDomainRhsIntegrationRule(integration_rule);
151 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
152 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
153 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
154 //! [Integration rule]
155
157 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
159 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
161 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
163 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
164
165 //! [Push domain stiffness matrix to pipeline]
166 // Add LHS operator for elasticity (stiffness matrix)
167 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, A, I, DomainEleOp>(
168 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
169 //! [Push domain stiffness matrix to pipeline]
170
171 // Add RHS operator for internal forces
172 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
173 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
174
175 //! [Push Body forces]
177 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
178 //! [Push Body forces]
179
180 //! [Push natural boundary conditions]
181 // Add force boundary condition
183 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
184 // Add case for mix type of BCs
186 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::verbose);
187 //! [Push natural boundary conditions]
189}
190//! [Push operators to pipeline]
191
192// ! [KSP set up]
193MoFEMErrorCode ElasticExample::kspSetUpAndSolve(SmartPetscObj<KSP> solver) {
195
196 MOFEM_LOG_CHANNEL("TIMER");
197 MOFEM_LOG_TAG("TIMER", "timer");
198
199 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
200 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp";
201 CHKERR KSPSetUp(solver);
202 MOFEM_LOG("TIMER", Sev::inform) << "KSPSetUp <= Done";
203
204 DM dm;
205 CHKERR KSPGetDM(solver, &dm);
206 auto D = createDMVector(dm);
207 auto F = vectorDuplicate(D);
208
209 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve";
210 CHKERR KSPSolve(solver, F, D);
211 MOFEM_LOG("TIMER", Sev::inform) << "KSPSolve <= Done";
212
213 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
214 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
215 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
216
218};
219// ! [KSP set up]
220
221//! [Solve]
224
225 auto simple = mField.getInterface<Simple>();
226 auto pip = mField.getInterface<PipelineManager>();
227 auto solver = pip->createKSP();
228 CHKERR KSPSetFromOptions(solver);
229
230 auto set_essential_bc = [this]() {
232 // This is low level pushing finite elements (pipelines) to solver
233 auto simple = mField.getInterface<Simple>();
234 auto dm = simple->getDM();
235 auto ksp_ctx_ptr = getDMKspCtx(dm);
236
237 auto pre_proc_rhs = boost::make_shared<FEMethod>();
238 auto post_proc_rhs = boost::make_shared<FEMethod>();
239 auto post_proc_lhs = boost::make_shared<FEMethod>();
240
241 auto get_pre_proc_hook = [this, pre_proc_rhs]() {
242 return EssentialPreProc<DisplacementCubitBcData>(mField, pre_proc_rhs,
243 {});
244 };
245 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
246
247 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
249
250 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(mField,
251 post_proc_rhs, 1.)();
253 };
254
255 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
257
258 CHKERR EssentialPostProcLhs<DisplacementCubitBcData>(mField,
259 post_proc_lhs, 1.)();
261 };
262
263 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
264 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
265
266 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
267 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
268 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
270 };
271
272 auto evaluate_field_at_the_point = [&]() {
274
275 int coords_dim = 3;
276 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
277 PetscBool do_eval_field = PETSC_FALSE;
278 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
279 field_eval_coords.data(), &coords_dim,
281
282 if (do_eval_field) {
283
284 vectorFieldPtr = boost::make_shared<MatrixDouble>();
285 auto field_eval_data =
286 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
287
288 CHKERR mField.getInterface<FieldEvaluatorInterface>()
289 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
290
291 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
292 auto no_rule = [](int, int, int) { return -1; };
293 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
294 field_eval_fe_ptr->getRuleHook = no_rule;
295
296 field_eval_fe_ptr->getOpPtrVector().push_back(
297 new OpCalculateVectorFieldValues<SPACE_DIM>("U", vectorFieldPtr));
298
299 CHKERR mField.getInterface<FieldEvaluatorInterface>()
300 ->evalFEAtThePoint<SPACE_DIM>(
301 field_eval_coords.data(), 1e-12, simple->getProblemName(),
302 simple->getDomainFEName(), field_eval_data,
304 QUIET);
305
306 if (vectorFieldPtr->size1()) {
307 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
308 if constexpr (SPACE_DIM == 2)
309 MOFEM_LOG("FieldEvaluator", Sev::inform)
310 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
311 else
312 MOFEM_LOG("FieldEvaluator", Sev::inform)
313 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
314 << " U_Z: " << t_disp(2);
315 }
316
318 }
320 };
321
322 CHKERR set_essential_bc();
323 CHKERR kspSetUpAndSolve(solver);
324 CHKERR evaluate_field_at_the_point();
325
327}
328//! [Solve]
329
330//! [Postprocess results]
333 auto simple = mField.getInterface<Simple>();
334 auto pip = mField.getInterface<PipelineManager>();
335 auto det_ptr = boost::make_shared<VectorDouble>();
336 auto jac_ptr = boost::make_shared<MatrixDouble>();
337 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
338 //! [Postprocess clean]
339 pip->getDomainRhsFE().reset();
340 pip->getDomainLhsFE().reset();
341 pip->getBoundaryRhsFE().reset();
342 pip->getBoundaryLhsFE().reset();
343 //! [Postprocess clean]
344
345 //! [Postprocess initialise]
346 auto post_proc_mesh = boost::make_shared<moab::Core>();
347 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
348 mField, post_proc_mesh);
349 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
350 mField, post_proc_mesh);
351 //! [Postprocess initialise]
352
353 // lamdaa function to calculate dispalcement, strain and stress
354 auto calculate_stress_ops = [&](auto &pip) {
355 // Add H1 geometry ops
357
358 // Use HookeOps commonDataFactory to get matStrainPtr and matCauchyStressPtr
359 auto common_ptr = HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEle>(
360 mField, pip, "U", "MAT_ELASTIC", Sev::verbose);
361
362 // Store U and GEOMETRY values if needed
363 auto u_ptr = boost::make_shared<MatrixDouble>();
364 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
365 auto x_ptr = boost::make_shared<MatrixDouble>();
366 pip.push_back(
367 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
368
369 // Return what you need: displacements, coordinates, strain, stress
370 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
371 common_ptr->getMatCauchyStress());
372 };
373
374 auto get_tag_id_on_pmesh = [&](bool post_proc_skin) {
375 int def_val_int = 0;
376 Tag tag_mat;
377 rval = mField.get_moab().tag_get_handle(
378 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
379 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
380 if (rval == MB_ALREADY_ALLOCATED) {
381 return std::vector<Tag>{};
382 } else {
383 MOAB_THROW(rval);
384 }
385 auto meshset_vec_ptr =
386 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
387 std::regex((boost::format("%s(.*)") % "MAT_ELASTIC").str()));
388
389 Range skin_ents;
390 std::unique_ptr<Skinner> skin_ptr;
391 if (post_proc_skin) {
392 skin_ptr = std::make_unique<Skinner>(&mField.get_moab());
393 auto boundary_meshset = simple->getBoundaryMeshSet();
394 CHKERR mField.get_moab().get_entities_by_handle(boundary_meshset,
395 skin_ents, true);
396 }
397
398 for (auto m : meshset_vec_ptr) {
399 Range ents_3d;
400 CHKERR mField.get_moab().get_entities_by_handle(m->getMeshset(), ents_3d,
401 true);
402 int const id = m->getMeshsetId();
403 ents_3d = ents_3d.subset_by_dimension(SPACE_DIM);
404 if (post_proc_skin) {
405 Range skin_faces;
406 CHKERR skin_ptr->find_skin(0, ents_3d, false, skin_faces);
407 ents_3d = intersect(skin_ents, skin_faces);
408 }
409 CHKERR mField.get_moab().tag_clear_data(tag_mat, ents_3d, &id);
410 }
411
412 return std::vector<Tag>{tag_mat};
413 };
414
415 auto post_proc_domain = [&](auto post_proc_mesh) {
416 auto post_proc_fe =
417 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
418 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
419
420 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
421 calculate_stress_ops(post_proc_fe->getOpPtrVector());
422
423 post_proc_fe->getOpPtrVector().push_back(
424
425 new OpPPMap(
426
427 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
428
429 {},
430
431 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
432
433 {},
434
435 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
436
437 )
438
439 );
440
441 post_proc_fe->setTagsToTransfer(get_tag_id_on_pmesh(false));
442 return post_proc_fe;
443 };
444
445 auto post_proc_boundary = [&](auto post_proc_mesh) {
446 auto post_proc_fe =
447 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
449 post_proc_fe->getOpPtrVector(), {}, "GEOMETRY");
450 auto op_loop_side =
451 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
452 // push ops to side element, through op_loop_side operator
453 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr] =
454 calculate_stress_ops(op_loop_side->getOpPtrVector());
455 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
456 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
457 post_proc_fe->getOpPtrVector().push_back(
458 new ElasticOps::OpCalculateTraction(mat_stress_ptr, mat_traction_ptr));
459
460 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
461
462 post_proc_fe->getOpPtrVector().push_back(
463
464 new OpPPMap(
465
466 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
467
468 {},
469
470 {{"U", u_ptr}, {"GEOMETRY", x_ptr}, {"T", mat_traction_ptr}},
471
472 {},
473
474 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
475
476 )
477
478 );
479
480 post_proc_fe->setTagsToTransfer(get_tag_id_on_pmesh(true));
481 return post_proc_fe;
482 };
483
484 PetscBool post_proc_skin_only = PETSC_FALSE;
485 if (SPACE_DIM == 3) {
486 post_proc_skin_only = PETSC_TRUE;
487 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin_only",
488 &post_proc_skin_only, PETSC_NULLPTR);
489 }
490 if (post_proc_skin_only == PETSC_FALSE) {
491 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
492 } else {
493 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
494 }
495
497 post_proc_begin->getFEMethod());
498 CHKERR pip->loopFiniteElements();
500 post_proc_end->getFEMethod());
501
502 CHKERR post_proc_end->writeFile("out_elastic.h5m");
504}
505//! [Postprocess results]
506
507//! [Check]
509 MOFEM_LOG_CHANNEL("WORLD");
510 auto simple = mField.getInterface<Simple>();
511 auto pip = mField.getInterface<PipelineManager>();
513 pip->getDomainRhsFE().reset();
514 pip->getDomainLhsFE().reset();
515 pip->getBoundaryRhsFE().reset();
516 pip->getBoundaryLhsFE().reset();
517
518 auto integration_rule = [](int, int, int p_data) { return 2 * p_data + 1; };
519 CHKERR pip->setDomainRhsIntegrationRule(integration_rule);
520 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule);
521
523 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
525 pip->getOpBoundaryRhsPipeline(), {}, "GEOMETRY");
526
527 // Add RHS operators for internal forces
528 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, A, I, DomainEleOp>(
529 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::verbose);
530
532 pip->getOpDomainRhsPipeline(), mField, "U", Sev::verbose);
533
535 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::verbose);
536
537 auto dm = simple->getDM();
538 auto res = createDMVector(dm);
539 CHKERR VecSetDM(res, PETSC_NULLPTR);
540
541 pip->getDomainRhsFE()->f = res;
542 pip->getBoundaryRhsFE()->f = res;
543
544 CHKERR VecZeroEntries(res);
545
546 CHKERR pip->loopFiniteElements();
547 // CHKERR mField.getInterface<FieldBlas>()->fieldScale(-1, "U");
548
549 CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
550 CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
551 CHKERR VecAssemblyBegin(res);
552 CHKERR VecAssemblyEnd(res);
553
554 auto zero_residual_at_constrains = [&]() {
556 auto fe_post_proc_ptr = boost::make_shared<FEMethod>();
557 auto get_post_proc_hook_rhs = [&]() {
559 CHKERR EssentialPreProcReaction<DisplacementCubitBcData>(
560 mField, fe_post_proc_ptr, res)();
561 CHKERR EssentialPostProcRhs<DisplacementCubitBcData>(
562 mField, fe_post_proc_ptr, 0, res)();
564 };
565 fe_post_proc_ptr->postProcessHook = get_post_proc_hook_rhs;
566 CHKERR DMoFEMPostProcessFiniteElements(dm, fe_post_proc_ptr.get());
568 };
569
570 CHKERR zero_residual_at_constrains();
571
572 double nrm2;
573 CHKERR VecNorm(res, NORM_2, &nrm2);
574 MOFEM_LOG_CHANNEL("WORLD");
575 MOFEM_LOG_C("WORLD", Sev::inform, "residual = %3.4e\n", nrm2);
576
577 int test = 0;
578 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-test", &test, PETSC_NULLPTR);
579 if (test > 0) {
580 auto post_proc_residual = [&](auto dm, auto f_res, auto out_name) {
582 auto post_proc_fe =
583 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(mField);
584 using OpPPMap = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
585 auto u_vec = boost::make_shared<MatrixDouble>();
586 post_proc_fe->getOpPtrVector().push_back(
587 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_vec, f_res));
588 post_proc_fe->getOpPtrVector().push_back(
589
590 new OpPPMap(
591
592 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
593
594 {},
595
596 {{"RES", u_vec}},
597
598 {}, {})
599
600 );
601
602 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
603 post_proc_fe);
604 post_proc_fe->writeFile(out_name);
606 };
607
608 CHKERR post_proc_residual(simple->getDM(), res, "res.h5m");
609
610 constexpr double eps = 1e-8;
611 if (nrm2 > eps)
612 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
613 "Residual is not zero");
614 }
615 if (test == 2) {
616 if (!vectorFieldPtr || vectorFieldPtr->size1() == 0) {
617 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
618 "atom test %d failed: Field Evaluator did not provide result",
619 test);
620 }
621 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*vectorFieldPtr);
622 double Ux_ref = 0.46;
623 double Uy_ref = -0.03;
624 constexpr double eps = 1e-8;
625 if (fabs(t_disp(0) - Ux_ref) > eps || fabs(t_disp(1) - Uy_ref) > eps) {
626 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
627 "atom test %d failed: Ux_ref = %3.6e, computed = %3.6e, Uy_ref "
628 "= %3.6e, computed = %3.6e",
629 test, Ux_ref, t_disp(0), Uy_ref, t_disp(1));
630 }
631 }
633}
634//! [Check]
#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
static const double eps
constexpr int SPACE_DIM
@ QUIET
@ 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 MOAB_THROW(err)
Check error code of MoAB function 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
@ F
auto integration_rule
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
#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
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
MoFEMErrorCode solveSystem()
[Solve]
MoFEMErrorCode outputResults()
[Solve]
MoFEMErrorCode assembleSystem()
[Boundary condition]
MoFEMErrorCode setupProblem()
[Read mesh]
virtual MoFEMErrorCode kspSetUpAndSolve(SmartPetscObj< KSP > solver)
[Push operators to pipeline]
MoFEMErrorCode runProblem()
[Run problem]
MoFEM::Interface & mField
MoFEMErrorCode boundaryCondition()
[Set up problem]
MoFEMErrorCode checkResults()
[Postprocess results]
MoFEMErrorCode readMesh()
[Run problem]
boost::shared_ptr< MatrixDouble > vectorFieldPtr
ElasticExample(MoFEM::Interface &m_field)
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.
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
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.
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.