v0.14.0
Loading...
Searching...
No Matches
adolc_plasticity.cpp
Go to the documentation of this file.
1/**
2 * \file adolc_plasticity.cpp
3 * \ingroup adoc_plasticity
4 * \example adolc_plasticity.cpp
5 *
6 * \brife Implementation of plasticity problem using ADOLC-C
7 *
8 */
9#include <MoFEM.hpp>
10#include <MatrixFunction.hpp>
11
12using namespace MoFEM;
13
14constexpr int SPACE_DIM =
15 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
16
18
19/** Select finite element type for integration on domain based on problem
20 * dimension
21 */
23
24/** Select finite element type for integrate on boundary based on problem
25 * dimension
26 */
29/** Operators used to assemble domain integrals
30 */
31using DomainEleOp = DomainEle::UserDataOperator;
32
33/** Operators used to assemble boundary integrals
34 */
35using BoundaryEleOp = BoundaryEle::UserDataOperator;
36
37/** Linear forms used to integrate body forces
38 */
41
42/** Select linear froms reading data from blockest (e.g. "BODY_FORCE") and
43 * applying body force.
44 */
47
48// Select natural BC boundary condition
49
50// Use natural boundary conditions implemented with adv-1 example which includes
51// spring BC
52#include <ContactNaturalBC.hpp>
53
54/** Use Gauss quadrature rule and PETSc assembly to integrate neural boundary
55 * conditions. Select linear forms operators.
56 */
59
60/* Use specialization from adv-1 integrating boundary conditions on forces and
61 * with springs. OP is used to integrate the right hand side
62 */
65
66/** Use Gauss quadrature rule and PETSc assembly to integrate neural boundary
67 * conditions. Select bi-linear forms operators.
68 */
71
72/** Use specialization from adv-1 integrating boundary conditions on forces and
73 * with springs
74 */
77
78// Note: We create only skin post-processing mesh.
79
80template <int DIM>
81struct ElementsAndOps; //< Select finite elements and operators used for
82 // postprocessing and contact space
83
84template <> struct ElementsAndOps<2> {
88 static constexpr FieldSpace CONTACT_SPACE = HCURL;
89};
90
91template <> struct ElementsAndOps<3> {
95 static constexpr FieldSpace CONTACT_SPACE = HDIV;
96};
97// Define contact space by dimension
101
105
106double scale = 1.;
107#include <HenckyOps.hpp>
108#include <ADOLCPlasticity.hpp>
111using namespace HenckyOps;
112using namespace ADOLCPlasticity;
113#ifdef ADD_CONTACT
114#ifdef PYTHON_SDF
115#include <boost/python.hpp>
116#include <boost/python/def.hpp>
117#include <boost/python/numpy.hpp>
118namespace bp = boost::python;
119namespace np = boost::python::numpy;
120#endif
121namespace ContactOps {
122
123double cn_contact = 0.1;
124
125}; // namespace ContactOps
126
127#include <ContactOps.hpp>
128#endif // ADD_CONTACT
129
131
132 PlasticProblem(MoFEM::Interface &m_field) : mField(m_field) {}
133
135
136private:
138
147
148 int approxOrder = 2;
149 int geomOrder = 2;
150 PetscBool largeStrain = PETSC_FALSE; ///< Large strain flag
152 boost::shared_ptr<ClosestPointProjection> cpPtr; ///< Closest point
153 ///< projection
154#ifdef ADD_CONTACT
155#ifdef PYTHON_SDF
156 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
157#endif
158#endif // ADD_CONTACT
159};
160
161//! [Run problem]
174//! [Run problem]
175
176//! [Read mesh]
180 CHKERR simple->getOptions();
181 CHKERR simple->loadFile();
182
183 if (simple->getDim() != SPACE_DIM)
184 SETERRQ2(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
185 "Wrong dimension of mesh %d != %d", simple->getDim(), SPACE_DIM);
186
187 // Check if mesh has boundary conditions tag and set yield strength as elastic
188 Tag th_boundary_conditions;
189 ErrorCode rval_bc = mField.get_moab().tag_get_handle(
190 "BOUNDARY_CONDITIONS", 1, MB_TYPE_INTEGER, th_boundary_conditions,
191 MB_TAG_SPARSE);
192
193 // Set yield strength as elastic if boundary conditions tag is set
194 if (rval_bc == MB_SUCCESS) {
195
196 auto yield_strength_compressive = std::numeric_limits<double>::max();
197 auto yield_strength_tension = std::numeric_limits<double>::max();
198
199 Tag th_compressive_yield_stress;
200 Tag th_tension_yield_stress;
201
202 ErrorCode rval_compressive = mField.get_moab().tag_get_handle(
203 "Yield_Strength_C", 1, MB_TYPE_DOUBLE, th_compressive_yield_stress,
204 MB_TAG_SPARSE);
205
206 ErrorCode rval_tension = mField.get_moab().tag_get_handle(
207 "Yield_Strength_T", 1, MB_TYPE_DOUBLE, th_tension_yield_stress,
208 MB_TAG_SPARSE);
209
210 Range fe_ents;
211 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, fe_ents);
212
213 for (auto fe_ent : fe_ents) {
214 Range nodes;
215 // get nodes of the element
216 CHKERR mField.get_moab().get_adjacencies(&fe_ent, 1, 0, false, nodes);
217
218 std::vector<double> v_bc_val;
219 for (auto node : nodes) {
220 int bc_val;
221 CHKERR mField.get_moab().tag_get_data(th_boundary_conditions, &node, 1,
222 static_cast<void *>(&bc_val));
223 v_bc_val.push_back(bc_val);
224 }
225
226 // Set yield strength as elastic if boundary conditions is FIX_X or
227 // CONTACT
228 if (std::find_if(v_bc_val.begin(), v_bc_val.end(), [](int val) {
229 return val == 5 || val == 20;
230 }) != v_bc_val.end()) {
231
232 if (rval_compressive == MB_SUCCESS) {
233
234 CHKERR mField.get_moab().tag_set_data(th_compressive_yield_stress,
235 &fe_ent, 1,
236 &yield_strength_compressive);
237 } else {
238 MOFEM_LOG("ADOLCPlasticityWold", Sev::warning)
239 << "Yield_Strength_C tag does not exist using default value";
240 }
241 if (rval_tension == MB_SUCCESS) {
242
243 CHKERR mField.get_moab().tag_set_data(
244 th_tension_yield_stress, &fe_ent, 1, &yield_strength_tension);
245 } else {
246 MOFEM_LOG("ADOLCPlasticityWold", Sev::warning)
247 << "Yield_Strength_T tag does not exist using default value";
248 }
249 }
250 }
251 }
252
254}
255//! [Read mesh]
256
257//! [Set up problem]
261
262 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
263 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
264 PetscInt choice_base_value = AINSWORTH;
265 CHKERR PetscOptionsGetEList(PETSC_NULL, NULL, "-base", list_bases,
266 LASBASETOPT, &choice_base_value, PETSC_NULL);
267 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &approxOrder, PETSC_NULL);
268 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-geom_order", &geomOrder,
269 PETSC_NULL);
270 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-large_strain", &largeStrain,
271 PETSC_NULL);
272
273 switch (choice_base_value) {
274 case AINSWORTH:
276 MOFEM_LOG("WORLD", Sev::inform)
277 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
278 break;
279 case DEMKOWICZ:
281 MOFEM_LOG("WORLD", Sev::inform)
282 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
283 break;
284 default:
286 break;
287 }
288
289 // Add field
290 CHKERR simple->addDomainField("U", H1, approxBase, SPACE_DIM);
291 CHKERR simple->addBoundaryField("U", H1, approxBase, SPACE_DIM);
292 CHKERR simple->addDataField("GEOMETRY", H1, approxBase, SPACE_DIM);
293
294#ifdef ADD_CONTACT
295 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
296 SPACE_DIM);
297 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
298 SPACE_DIM);
299 auto get_skin = [&]() {
300 Range body_ents;
301 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
302 Skinner skin(&mField.get_moab());
303 Range skin_ents;
304 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
305 return skin_ents;
306 };
307
308 auto filter_blocks = [&](auto skin) {
309 bool is_contact_block = false;
310 Range contact_range;
311 for (auto m :
313
314 (boost::format("%s(.*)") % "CONTACT").str()
315
316 ))
317
318 ) {
319 is_contact_block =
320 true; ///< bloks interation is collectibe, so that is set irrespective
321 ///< if there are enerities in given rank or not in the block
322 MOFEM_LOG("CONTACT", Sev::inform)
323 << "Find contact block set: " << m->getName();
324 auto meshset = m->getMeshset();
325 Range contact_meshset_range;
326 CHKERR mField.get_moab().get_entities_by_dimension(
327 meshset, SPACE_DIM - 1, contact_meshset_range, true);
328
329 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
330 contact_meshset_range);
331 contact_range.merge(contact_meshset_range);
332 }
333 if (is_contact_block) {
334 MOFEM_LOG("SYNC", Sev::inform)
335 << "Nb entities in contact surface: " << contact_range.size();
337 skin = intersect(skin, contact_range);
338 }
339 return skin;
340 };
341
342 auto filter_true_skin = [&](auto skin) {
343 Range boundary_ents;
344 ParallelComm *pcomm =
345 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
346 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
347 PSTATUS_NOT, -1, &boundary_ents);
348 return boundary_ents;
349 };
350
351 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
352#ifdef ADD_CONTACT
353 CHKERR simple->setFieldOrder("SIGMA", 0);
354 CHKERR simple->setFieldOrder("SIGMA", approxOrder - 1, &boundary_ents);
355 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn_contact",
356 &ContactOps::cn_contact, PETSC_NULL);
357 MOFEM_LOG("CONTACT", Sev::inform) << "cn_contact " << ContactOps::cn_contact;
358
359#endif
360
361#ifdef PYTHON_SDF
362 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
363 CHKERR sdfPythonPtr->sdfInit("sdf.py");
364 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
365#endif
366#endif
367
368 CHKERR simple->setFieldOrder("U", approxOrder);
369 CHKERR simple->setFieldOrder("GEOMETRY", geomOrder);
370 CHKERR simple->setUp();
371
372 auto project_ho_geometry = [&]() {
373 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
374 return mField.loop_dofs("GEOMETRY", ent_method);
375 };
376 PetscBool project_geometry = PETSC_TRUE;
377 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-project_geometry",
378 &project_geometry, PETSC_NULL);
379 if (project_geometry) {
380 CHKERR project_ho_geometry();
381 }
382
383 //! [Material models selection]
384
385 /**
386 * FIXME: Here only array of material models is initalized. Each model has
387 * unique set of the ADOL-C tags. Pointer is attached based on block name to
388 * which entity belongs. That will enable heterogeneity of the model, in
389 * addition of heterogeneity of the material properties.
390 */
391
392 enum MaterialModel {
393 VonMisses,
394 VonMissesPlaneStress,
395 Paraboloidal,
396 HeterogeneousParaboloidal,
397 LastModel
398 };
399 const char *list_materials[LastModel] = {"VonMisses", "VonMissesPlaneStress",
400 "Paraboloidal","HeterogeneousParaboloidal"};
401 PetscInt choice_material = VonMisses;
402 CHKERR PetscOptionsGetEList(PETSC_NULL, NULL, "-material", list_materials,
403 LastModel, &choice_material, PETSC_NULL);
404
405 switch (choice_material) {
406 case VonMisses:
408 break;
409 case VonMissesPlaneStress:
410 if (SPACE_DIM != 2)
411 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
412 "VonMissesPlaneStrain is only for 2D case");
414 break;
415 case Paraboloidal:
417 break;
418 case HeterogeneousParaboloidal:
420 break;
421 default:
422 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "Wrong material model");
423 }
424
426 cpPtr->integrationRule = [](int, int, int p) { return 2 * (p - 2); };
427
428 //! [Material models selection]
429
431}
432//! [Set up problem]
433
434//! [Boundary condition]
437 auto *pipeline_mng = mField.getInterface<PipelineManager>();
439 auto bc_mng = mField.getInterface<BcManager>();
440 auto time_scale = boost::make_shared<TimeScale>();
441
442 auto rule = [](int, int, int p) { return 2 * p; };
443 CHKERR pipeline_mng->setDomainRhsIntegrationRule(cpPtr->integrationRule);
444 CHKERR pipeline_mng->setDomainLhsIntegrationRule(cpPtr->integrationRule);
445 CHKERR pipeline_mng->setBoundaryRhsIntegrationRule(rule);
446 CHKERR pipeline_mng->setBoundaryLhsIntegrationRule(rule);
447
449 pipeline_mng->getOpBoundaryLhsPipeline(), {HDIV}, "GEOMETRY");
450 pipeline_mng->getOpBoundaryLhsPipeline().push_back(
452
454 pipeline_mng->getOpBoundaryRhsPipeline(), {HDIV}, "GEOMETRY");
455 pipeline_mng->getOpBoundaryRhsPipeline().push_back(
457
458 // Add Natural BCs to RHS
460 pipeline_mng->getOpBoundaryRhsPipeline(), mField, "U", {time_scale},
461 Sev::inform);
462 // Add Natural BCs to LHS
464 pipeline_mng->getOpBoundaryLhsPipeline(), mField, "U", Sev::inform);
465
466#ifdef ADD_CONTACT
467 CHKERR
469 pipeline_mng->getOpBoundaryLhsPipeline(), "SIGMA", "U");
470 CHKERR
472 mField, pipeline_mng->getOpBoundaryLhsPipeline(),
473 simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
474 cpPtr->integrationRule);
475
476 CHKERR
478 pipeline_mng->getOpBoundaryRhsPipeline(), "SIGMA", "U");
479#endif // ADD_CONTACT
480
481 //! Add body froces
483 pipeline_mng->getOpDomainRhsPipeline(), mField, "U", {time_scale},
484 "BODY_FORCE", Sev::inform);
485
486 // Essential BC
487 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
488 "U", 0, 0);
489 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
490 "U", 1, 1);
491 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
492 "U", 2, 2);
493#ifdef ADD_CONTACT
494 for (auto b : {"FIX_X", "REMOVE_X"})
495 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
496 "SIGMA", 0, 0, false, true);
497 for (auto b : {"FIX_Y", "REMOVE_Y"})
498 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
499 "SIGMA", 1, 1, false, true);
500 for (auto b : {"FIX_Z", "REMOVE_Z"})
501 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
502 "SIGMA", 2, 2, false, true);
503 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
504 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
505 "SIGMA", 0, 3, false, true);
506 CHKERR bc_mng->removeBlockDOFsOnEntities(
507 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
508#endif
509
510 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
511 simple->getProblemName(), "U");
512
514}
515//! [Boundary condition]
516
517//! [Push operators to pipeline]
520 auto *simple = mField.getInterface<Simple>();
521 auto *pipeline_mng = mField.getInterface<PipelineManager>();
522
523 // assemble operator to the right hand side
524 auto add_domain_ops_lhs = [&](auto &pip) {
526 // push forward finite element bases from reference to physical element
528 "GEOMETRY");
529 // create local common data
530 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
531
532 if (largeStrain) {
533 CHKERR
535 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
536 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
537 PETSC>::template BiLinearForm<GAUSS>;
538
539 using OpKPiola =
540 typename B::template OpGradTensorGrad<1, SPACE_DIM, SPACE_DIM, 1>;
541
542 pip.push_back(
543 new OpKPiola("U", "U", common_data_ptr->getMatTangentPtr()));
544 } else {
546 "U", common_data_ptr->getGradAtGaussPtsPtr()));
548 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
549 }
550
552 };
553
554 auto add_domain_ops_rhs = [&](auto &pip) {
556 // push forward finite element bases from reference to physical element
558 "GEOMETRY");
559 // create local common data
560 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
561
562 if (largeStrain) {
563 CHKERR
565 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
566 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
567 PETSC>::template LinearForm<GAUSS>;
570 pip.push_back(
571 new OpInternalForcePiola("U", common_data_ptr->getStressMatrixPtr()));
572 } else {
574 "U", common_data_ptr->getGradAtGaussPtsPtr()));
576 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
577 }
578
579#ifdef ADD_CONTACT
581 pip, "SIGMA", "U");
582#endif // ADD_CONTACT
584 };
585
586 // Push operators to the left hand side pipeline. Indicate that domain (i.e.
587 // volume/interior) element is used.
588 CHKERR add_domain_ops_lhs(pipeline_mng->getOpDomainLhsPipeline());
589 // Push operators to the right hand side pipeline.
590 CHKERR add_domain_ops_rhs(pipeline_mng->getOpDomainRhsPipeline());
591
593}
594//! [Push operators to pipeline]
595
596/**
597 * @brief Monitor solution
598 *
599 * This functions is called by TS solver at the end of each step. It is used
600 * to output results to the hard drive.
601 */
602struct Monitor : public FEMethod {
604 std::pair<boost::shared_ptr<PostProcEleDomain>,
605 boost::shared_ptr<PostProcEleBdy>>
606 pair_post_proc_fe,
607 boost::shared_ptr<DomainEle> reaction_fe,
608 std::vector<boost::shared_ptr<ScalingMethod>> smv)
609 : dM(dm), reactionFE(reaction_fe), vecOfTimeScalingMethods(smv) {
611 domainPostProcFe = pair_post_proc_fe.first;
612 skinPostProcFe = pair_post_proc_fe.second;
613
614 MoFEM::Interface *m_field_ptr;
615 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
616#ifdef ADD_CONTACT
617 auto get_integrate_traction = [&]() {
618 auto integrate_traction = boost::make_shared<BoundaryEle>(*m_field_ptr);
619 auto common_data_ptr = boost::make_shared<ContactOps::CommonData>();
622 integrate_traction->getOpPtrVector(), {HDIV}, "GEOMETRY")),
623 "Apply transform");
624 // We have to integrate on curved face geometry, thus integration weight
625 // have to adjusted.
626 integrate_traction->getOpPtrVector().push_back(
628 integrate_traction->getRuleHook = [](int, int, int approx_order) {
629 return 2 * approx_order + 2 - 1;
630 };
631
635 integrate_traction->getOpPtrVector(), "SIGMA", 0)),
636 "push operators to calculate traction");
637
638 return integrate_traction;
639 };
640
641 integrateTraction = get_integrate_traction();
642#endif
643 }
646 int save_every_nth_step = 1;
647 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-save_every_nth_step",
648 &save_every_nth_step, PETSC_NULL);
649#ifdef ADD_CONTACT
650 auto print_traction = [&](const std::string msg) {
652 MoFEM::Interface *m_field_ptr;
653 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
654 if (!m_field_ptr->get_comm_rank()) {
655 const double *t_ptr;
656 CHKERR VecGetArrayRead(ContactOps::CommonData::totalTraction, &t_ptr);
657 MOFEM_LOG_C("CONTACT", Sev::inform, "%s time %3.4e %3.4e %3.4e %3.4e",
658 msg.c_str(), ts_t, t_ptr[0], t_ptr[1], t_ptr[2]);
660 &t_ptr);
661 }
663 };
664#endif
665
666 auto make_vtk = [&]() {
668 if (domainPostProcFe) {
671 CHKERR domainPostProcFe->writeFile(
672 "out_plastic_" + boost::lexical_cast<std::string>(ts_step) +
673 ".h5m");
674 }
675 if (skinPostProcFe) {
678 CHKERR skinPostProcFe->writeFile(
679 "out_skin_plastic_" + boost::lexical_cast<std::string>(ts_step) +
680 ".h5m");
681 }
683 };
684
685 if (!(ts_step % save_every_nth_step)) {
686 CHKERR make_vtk();
687 }
688 if (reactionFE) {
689 CHKERR VecZeroEntries(fRes);
690 reactionFE->f = fRes;
692 CHKERR VecAssemblyBegin(fRes);
693 CHKERR VecAssemblyEnd(fRes);
694 CHKERR VecGhostUpdateBegin(fRes, ADD_VALUES, SCATTER_REVERSE);
695 CHKERR VecGhostUpdateEnd(fRes, ADD_VALUES, SCATTER_REVERSE);
696
697 MoFEM::Interface *m_field_ptr;
698 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
700 *m_field_ptr, reactionFE, fRes)();
701
702 double nrm;
703 CHKERR VecNorm(fRes, NORM_2, &nrm);
704 MOFEM_LOG("PlasticPrb", Sev::verbose)
705 << "Residual norm " << nrm << " at time step " << ts_step;
706 }
707
708#ifdef ADD_CONTACT
709 auto calculate_traction = [&] {
716 };
717#endif
718
719 auto get_min_max_displacement = [&]() {
721 MoFEM::Interface *m_field_ptr;
722 CHKERR DMoFEMGetInterfacePtr(dM, &m_field_ptr);
723
724 std::array<double, 4> a_min = {DBL_MAX, DBL_MAX, DBL_MAX, 0};
725 std::array<double, 4> a_max = {-DBL_MAX, -DBL_MAX, -DBL_MAX, 0};
726
727 auto get_min_max = [&](boost::shared_ptr<FieldEntity> field_entity_ptr) {
729 int d = 0;
730 for (auto v : field_entity_ptr->getEntFieldData()) {
731 a_min[d] = std::min(a_min[d], v);
732 a_max[d] = std::max(a_max[d], v);
733 ++d;
734 }
736 };
737
738 a_min[SPACE_DIM] = 0;
739 a_max[SPACE_DIM] = 0;
740
741 Range verts;
742 CHKERR m_field_ptr->get_field_entities_by_type("U", MBVERTEX, verts);
743 CHKERR m_field_ptr->getInterface<FieldBlas>()->fieldLambdaOnEntities(
744 get_min_max, "U", &verts);
745
746 auto mpi_reduce = [&](auto &a, auto op) {
747 std::array<double, 3> a_mpi = {0, 0, 0};
748 MPI_Allreduce(a.data(), a_mpi.data(), 3, MPI_DOUBLE, op,
749 m_field_ptr->get_comm());
750 return a_mpi;
751 };
752
753 auto a_min_mpi = mpi_reduce(a_min, MPI_MIN);
754 auto a_max_mpi = mpi_reduce(a_max, MPI_MAX);
755
756 MOFEM_LOG("PlasticPrb", Sev::inform)
757 << "Min displacement " << a_min_mpi[0] << " " << a_min_mpi[1] << " "
758 << a_min_mpi[2];
759 MOFEM_LOG("PlasticPrb", Sev::inform)
760 << "Max displacement " << a_max_mpi[0] << " " << a_max_mpi[1] << " "
761 << a_max_mpi[2];
763 };
764 CHKERR get_min_max_displacement();
765#ifdef ADD_CONTACT
766 CHKERR calculate_traction();
767 CHKERR print_traction("Contact force");
768#endif
769 double scale = 1;
770 for (auto s : vecOfTimeScalingMethods) {
771 scale *= s->getScale(this->ts_t);
772 }
773
774 MOFEM_LOG("PlasticPrb", Sev::inform)
775 << "Time: " << this->ts_t << " scale: " << scale;
776
778 }
779
780private:
782 boost::shared_ptr<PostProcEleDomain> domainPostProcFe;
783 boost::shared_ptr<PostProcEleBdy> skinPostProcFe;
784 boost::shared_ptr<FEMethod> reactionFE;
785
786 boost::shared_ptr<BoundaryEle> integrateTraction;
787
790};
791
792static boost::shared_ptr<TSUpdate> ts_update_ptr = nullptr;
793
794//! [Solve]
797 auto *simple = mField.getInterface<Simple>();
798 auto *pipeline_mng = mField.getInterface<PipelineManager>();
799
800 auto dm = simple->getDM();
801 auto time_scale = boost::make_shared<TimeScale>();
802 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
803
804 // Setup postprocessing
805 auto create_post_proc_fe = [dm, this, simple]() {
806 //! [DG projection]
807 // Post-process domain, i.e. volume elements. If 3d case creates stresses
808 // are evaluated at points which are trace of the volume element on boundary
809 auto post_proc_ele_domain = [this](auto &pip_domain, auto &fe_name) {
810 // Push bases on reference element to the phyiscal element
812 pip_domain, {H1, HDIV}, "GEOMETRY");
813
814 // calculate displacement gradients at nodes of post processing mesh. For
815 // gradient DG projection is obsolete, since displacements can be
816 // evaluated at arbitrary points.
817 auto grad_ptr = boost::make_shared<MatrixDouble>();
818 pip_domain.push_back(
820 grad_ptr));
821
822 // Create operator to run (neted) pipeline in operator. InteriorElem
823 // element will have iteration rule and bases as domain element used to
824 // solve problem, and remember history variables.
825 using InteriorElem = DomainEle;
826 auto op_this = new OpLoopThis<InteriorElem>(mField, fe_name, Sev::noisy);
827 // add interior element to post-processing pipeline
828 pip_domain.push_back(op_this);
829
830 // get pointer to interior element, which is in essence pipeline which
831 // pipeline.
832 auto fe_physics = op_this->getThisFEPtr();
833
834 auto evaluate_stress_on_physical_element = [&]() {
835 // evaluate stress and plastic strain at Gauss points
836 fe_physics->getRuleHook = cpPtr->integrationRule;
838 fe_physics->getOpPtrVector(), {H1});
839 auto common_data_ptr =
840 boost::make_shared<ADOLCPlasticity::CommonData>();
841 // note that gradient of displacements is evaluate again, at
842 // physical nodes
843 if (largeStrain) {
844 CHKERR
846 mField, "U", fe_physics->getOpPtrVector(), "ADOLCMAT", common_data_ptr, cpPtr);
847
848 } else {
849 fe_physics->getOpPtrVector().push_back(
851 "U", common_data_ptr->getGradAtGaussPtsPtr()));
852 CHKERR cpPtr->addMatBlockOps(mField, fe_physics->getOpPtrVector(), "ADOLCMAT", Sev::inform);
853 fe_physics->getOpPtrVector().push_back(getRawPtrOpCalculateStress<SPACE_DIM, SMALL_STRAIN>(
854 mField, common_data_ptr, cpPtr, false));
855 }
856 return common_data_ptr;
857 };
858
859 auto dg_projection_froward_and_back = [&](auto &common_data_ptr) {
860 // here we do actual projection of stress and plastic strain to DG space
861 int dg_order = approxOrder - 1;
862 auto entity_data_l2 =
863 boost::make_shared<EntitiesFieldData>(MBENTITYSET);
864 auto mass_ptr =
865 boost::make_shared<MatrixDouble>(); //< projection operator (mass
866 // matrix)
867 fe_physics->getOpPtrVector().push_back(new OpDGProjectionMassMatrix(
868 dg_order, mass_ptr, entity_data_l2, approxBase, L2));
869
870 auto coeffs_ptr_stress = boost::make_shared<MatrixDouble>();
871 // project stress on DG space on physical element
872 fe_physics->getOpPtrVector().push_back(new OpDGProjectionCoefficients(
873 common_data_ptr->getStressMatrixPtr(), coeffs_ptr_stress, mass_ptr,
874 entity_data_l2, approxBase, L2));
875 // project strains plastic strains DG space on physical element
876 auto coeffs_ptr_plastic_strain = boost::make_shared<MatrixDouble>();
877 fe_physics->getOpPtrVector().push_back(new OpDGProjectionCoefficients(
878 common_data_ptr->getPlasticStrainMatrixPtr(),
879 coeffs_ptr_plastic_strain, mass_ptr, entity_data_l2, approxBase,
880 L2));
881
882 // project stress and plastic strain for DG space on post-process
883 // element
884 pip_domain.push_back(new OpDGProjectionEvaluation(
885 common_data_ptr->getStressMatrixPtr(), coeffs_ptr_stress,
886 entity_data_l2, approxBase, L2));
887 pip_domain.push_back(new OpDGProjectionEvaluation(
888 common_data_ptr->getPlasticStrainMatrixPtr(),
889 coeffs_ptr_plastic_strain, entity_data_l2, approxBase, L2));
890 };
891
892 auto common_data_ptr = evaluate_stress_on_physical_element();
893 dg_projection_froward_and_back(common_data_ptr);
894
895 return boost::make_tuple(grad_ptr, common_data_ptr->getStressMatrixPtr(),
896 common_data_ptr->getPlasticStrainMatrixPtr());
897 };
898 //! [DG projection]
899
900 // Create tags on post-processing mesh, i.e. those tags are visible in
901 // Preview
902 auto add_post_proc_map = [&](auto post_proc_fe, auto u_ptr, auto grad_ptr,
903 auto stress_ptr, auto plastic_strain_ptr,
904 auto contact_stress_ptr, auto X_ptr) {
905 using OpPPMapSPACE_DIM = OpPostProcMapInMoab<SPACE_DIM, SPACE_DIM>;
906 post_proc_fe->getOpPtrVector().push_back(
907
908 new OpPPMapSPACE_DIM(
909
910 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
911
912 {},
913
914 {{"U", u_ptr}, {"GEOMETRY", X_ptr}},
915
916 {{"GRAD", grad_ptr}, {"SIGMA", contact_stress_ptr}},
917
918 {}
919
920 )
921
922 );
923
924 using OpPPMap3D = OpPostProcMapInMoab<3, 3>;
925 if (largeStrain) {
926 post_proc_fe->getOpPtrVector().push_back(
927
928 new OpPPMap3D(
929
930 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
931
932 {},
933
934 {},
935
936 {{"PK1", stress_ptr}},
937
938 {{"PLASTIC_STRAIN", plastic_strain_ptr}}
939
940 )
941
942 );
943 } else {
944 post_proc_fe->getOpPtrVector().push_back(
945
946 new OpPPMap3D(
947
948 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
949
950 {},
951
952 {},
953
954 {},
955
956 {{"STRESS", stress_ptr}, {"PLASTIC_STRAIN", plastic_strain_ptr}}
957
958 )
959
960 );
961 }
962
963 return post_proc_fe;
964 };
965
966 auto vol_post_proc = [this, simple, post_proc_ele_domain,
967 add_post_proc_map]() {
968 PetscBool post_proc_vol = PETSC_FALSE;
969 if (SPACE_DIM == 2)
970 post_proc_vol = PETSC_TRUE;
971
972 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_vol",
973 &post_proc_vol, PETSC_NULL);
974 if (post_proc_vol == PETSC_FALSE)
975 return boost::shared_ptr<PostProcEleDomain>();
976 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(mField);
977 auto u_ptr = boost::make_shared<MatrixDouble>();
978 post_proc_fe->getOpPtrVector().push_back(
980 auto X_ptr = boost::make_shared<MatrixDouble>();
981 post_proc_fe->getOpPtrVector().push_back(
982 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", X_ptr));
983 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
984#ifdef ADD_CONTACT
985 post_proc_fe->getOpPtrVector().push_back(
987 "SIGMA", contact_stress_ptr));
988#else
989 contact_stress_ptr = nullptr;
990#endif
991 auto [grad_ptr, stress_ptr, plastic_strain_ptr] = post_proc_ele_domain(
992 post_proc_fe->getOpPtrVector(), simple->getDomainFEName());
993
994 return add_post_proc_map(post_proc_fe, u_ptr, grad_ptr, stress_ptr,
995 plastic_strain_ptr, contact_stress_ptr, X_ptr);
996 };
997
998 auto skin_post_proc = [this, simple, post_proc_ele_domain,
999 add_post_proc_map]() {
1000 // create skin of the volume mesh for post-processing,
1001 // i.e. boundary of the volume mesh
1002 PetscBool post_proc_skin = PETSC_TRUE;
1003 if (SPACE_DIM == 2)
1004 post_proc_skin = PETSC_FALSE;
1005
1006 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_skin",
1007 &post_proc_skin, PETSC_NULL);
1008
1009 if (post_proc_skin == PETSC_FALSE)
1010 return boost::shared_ptr<PostProcEleBdy>();
1011
1012 auto post_proc_fe = boost::make_shared<PostProcEleBdy>(mField);
1013 auto u_ptr = boost::make_shared<MatrixDouble>();
1014 post_proc_fe->getOpPtrVector().push_back(
1016 auto X_ptr = boost::make_shared<MatrixDouble>();
1017 post_proc_fe->getOpPtrVector().push_back(
1018 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", X_ptr));
1019 auto contact_stress_ptr = boost::make_shared<MatrixDouble>();
1020 auto op_loop_side =
1021 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
1022 auto [grad_ptr, stress_ptr, plastic_strain_ptr] = post_proc_ele_domain(
1023 op_loop_side->getOpPtrVector(), simple->getDomainFEName());
1024#ifdef ADD_CONTACT
1025 op_loop_side->getOpPtrVector().push_back(
1027 "SIGMA", contact_stress_ptr));
1028#else
1029 contact_stress_ptr = nullptr;
1030#endif
1031 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
1032
1033 return add_post_proc_map(post_proc_fe, u_ptr, grad_ptr, stress_ptr,
1034 plastic_strain_ptr, contact_stress_ptr, X_ptr);
1035 };
1036
1037 return std::make_pair(vol_post_proc(), skin_post_proc());
1038 };
1039
1040 auto create_reaction_fe = [&]() {
1041 auto fe_ptr = boost::make_shared<DomainEle>(mField);
1042 fe_ptr->getRuleHook = cpPtr->integrationRule;
1043
1044 auto &pip = fe_ptr->getOpPtrVector();
1046 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
1047
1048 if (largeStrain) {
1049 CHKERR
1051 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
1052 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1053 PETSC>::template LinearForm<GAUSS>;
1054 using OpInternalForcePiola =
1055 typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
1056 pip.push_back(
1057 new OpInternalForcePiola("U", common_data_ptr->getStressMatrixPtr()));
1058 } else {
1060 "U", common_data_ptr->getGradAtGaussPtsPtr()));
1062 mField, "U", pip, "ADOLCMAT", common_data_ptr, cpPtr);
1063 }
1064
1065 return fe_ptr;
1066 };
1067
1068 auto add_extra_finite_elements_to_ksp_solver_pipelines = [&]() {
1070
1071 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1072 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1073 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1074
1075 auto get_bc_hook_rhs = [this, pre_proc_ptr, time_scale]() {
1078 {time_scale}, false)();
1080 };
1081
1082 pre_proc_ptr->preProcessHook = get_bc_hook_rhs;
1083
1084 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
1087 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
1089 mField, post_proc_rhs_ptr, 1.)();
1091 };
1092 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
1095 mField, post_proc_lhs_ptr, 1.)();
1097 };
1098 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1099 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs;
1100
1101 // This is low level pushing finite elements (pipelines) to solver
1102 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1103 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1104 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1105 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1106 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1108 };
1109
1110 // Add extra finite elements to SNES solver pipelines to resolve essential
1111 // boundary conditions
1112 CHKERR add_extra_finite_elements_to_ksp_solver_pipelines();
1113
1114 auto create_monitor_fe = [dm, time_scale](auto &&post_proc_fe,
1115 auto &&reaction_fe) {
1116 return boost::make_shared<Monitor>(
1117 dm, post_proc_fe, reaction_fe,
1118 std::vector<boost::shared_ptr<ScalingMethod>>{time_scale});
1119 };
1120
1121 //! [Set up post-step]
1122 auto set_up_post_step = [&](auto ts) {
1124
1125 // create finite element (pipeline) and populate it with operators to
1126 // update history variables
1127 auto create_update_ptr = [&]() {
1128 auto fe_ptr = boost::make_shared<DomainEle>(mField);
1129 fe_ptr->getRuleHook = cpPtr->integrationRule;
1130 AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(fe_ptr->getOpPtrVector(),
1131 {H1});
1132 auto common_data_ptr = boost::make_shared<ADOLCPlasticity::CommonData>();
1133
1134 if (largeStrain) {
1136 DomainEleOp>(
1137 mField, "U", fe_ptr->getOpPtrVector(), "ADOLCMAT", common_data_ptr,
1138 cpPtr);
1139 } else {
1140 fe_ptr->getOpPtrVector().push_back(
1142 "U", common_data_ptr->getGradAtGaussPtsPtr()));
1143 CHKERR cpPtr->addMatBlockOps(mField, fe_ptr->getOpPtrVector(),
1144 "ADOLCMAT", Sev::noisy);
1145 fe_ptr->getOpPtrVector().push_back(
1147 cpPtr, false));
1148 }
1149
1151 opFactoryDomainUpdate<SPACE_DIM>(mField, fe_ptr->getOpPtrVector(),
1152 "ADOLCMAT", common_data_ptr, cpPtr),
1153 "push update ops");
1154 return fe_ptr;
1155 };
1156
1157 // ts_update_ptr is global static variable
1159 createTSUpdate(simple->getDomainFEName(), create_update_ptr());
1160
1161 //! [TS post-step function]
1162 // This is pure "C" function which we can to the TS solver
1163 auto ts_step_post_proc = [](TS ts) {
1165 if (ts_update_ptr)
1166 CHKERR ts_update_ptr->postProcess(ts);
1168 };
1169 //! [TS post-step function]
1170
1171 // finally set up post-step
1172 CHKERR TSSetPostStep(ts, ts_step_post_proc);
1174 };
1175 //! [Set up post-step]
1176
1177 // Set monitor which postprocessing results and saves them to the hard drive
1178 auto set_up_monitor = [&](auto ts) {
1180 boost::shared_ptr<FEMethod> null_fe;
1181 auto monitor_ptr =
1182 create_monitor_fe(create_post_proc_fe(), create_reaction_fe());
1183 CHKERR DMMoFEMTSSetMonitor(dm, ts, simple->getDomainFEName(), null_fe,
1184 null_fe, monitor_ptr);
1186 };
1187
1188 auto set_section_monitor = [&](auto solver) {
1190 SNES snes;
1191 CHKERR TSGetSNES(solver, &snes);
1192 CHKERR SNESMonitorSet(snes,
1193 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
1194 void *))MoFEMSNESMonitorFields,
1195 (void *)(snes_ctx_ptr.get()), nullptr);
1197 };
1198
1199 auto set_up_adapt = [&](auto ts) {
1201 CHKERR TSAdaptRegister(TSADAPTMOFEM, TSAdaptCreateMoFEM);
1202 TSAdapt adapt;
1203 CHKERR TSGetAdapt(ts, &adapt);
1205 };
1206
1207 //! [Create TS]
1208 auto ts = pipeline_mng->createTSIM();
1209
1210 // Set time solver
1211 double ftime = 1;
1212 CHKERR TSSetMaxTime(ts, ftime);
1213 CHKERR TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);
1214 auto D = createDMVector(simple->getDM());
1215#ifdef ADD_CONTACT
1217#endif
1218 CHKERR TSSetSolution(ts, D);
1219 CHKERR set_section_monitor(ts);
1220
1221 // Set monitor, step adaptivity, and post-step to update history variables
1222 CHKERR set_up_monitor(ts);
1223 CHKERR set_up_post_step(ts);
1224 CHKERR set_up_adapt(ts);
1225 CHKERR TSSetFromOptions(ts);
1226
1227 CHKERR TSSolve(ts, NULL);
1228 //! [Create TS]
1229
1230 CHKERR TSGetTime(ts, &ftime);
1231
1232 PetscInt steps, snesfails, rejects, nonlinits, linits;
1233 CHKERR TSGetStepNumber(ts, &steps);
1234 CHKERR TSGetSNESFailures(ts, &snesfails);
1235 CHKERR TSGetStepRejections(ts, &rejects);
1236 CHKERR TSGetSNESIterations(ts, &nonlinits);
1237 CHKERR TSGetKSPIterations(ts, &linits);
1238 MOFEM_LOG_C("PlasticPrb", Sev::inform,
1239 "steps %d (%d rejected, %d SNES fails), ftime %g, nonlinits "
1240 "%d, linits %d",
1241 steps, rejects, snesfails, ftime, nonlinits, linits);
1242
1244}
1245//! [Solve]
1246
1247//! [Getting norms]
1250
1251 auto simple = mField.getInterface<Simple>();
1252 auto dm = simple->getDM();
1253
1254 auto T = createDMVector(simple->getDM());
1255 CHKERR DMoFEMMeshToLocalVector(simple->getDM(), T, INSERT_VALUES,
1256 SCATTER_FORWARD);
1257 double nrm2;
1258 CHKERR VecNorm(T, NORM_2, &nrm2);
1259 MOFEM_LOG("PlasticPrb", Sev::inform) << "Solution norm " << nrm2;
1260
1261 auto post_proc_norm_fe = boost::make_shared<DomainEle>(mField);
1262
1263 post_proc_norm_fe->getRuleHook = cpPtr->integrationRule;
1264
1266 post_proc_norm_fe->getOpPtrVector(), {H1});
1267
1268 enum NORMS { U_NORM_L2 = 0, PIOLA_NORM, LAST_NORM };
1269 auto norms_vec =
1271 (mField.get_comm_rank() == 0) ? LAST_NORM : 0, LAST_NORM);
1272 CHKERR VecZeroEntries(norms_vec);
1273
1274 auto u_ptr = boost::make_shared<MatrixDouble>();
1275 post_proc_norm_fe->getOpPtrVector().push_back(
1277
1278 post_proc_norm_fe->getOpPtrVector().push_back(
1279 new OpCalcNormL2Tensor1<SPACE_DIM>(u_ptr, norms_vec, U_NORM_L2));
1280
1281 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
1282 post_proc_norm_fe);
1283
1284 CHKERR VecAssemblyBegin(norms_vec);
1285 CHKERR VecAssemblyEnd(norms_vec);
1286
1287 MOFEM_LOG_CHANNEL("SELF"); // Clear channel from old tags
1288 if (mField.get_comm_rank() == 0) {
1289 const double *norms;
1290 CHKERR VecGetArrayRead(norms_vec, &norms);
1291 MOFEM_TAG_AND_LOG("SELF", Sev::inform, "example")
1292 << "norm_u: " << std::scientific << std::sqrt(norms[U_NORM_L2]);
1293 CHKERR VecRestoreArrayRead(norms_vec, &norms);
1294 }
1295
1297}
1298//! [Getting norms]
1299
1300//! [Postprocessing results]
1303 PetscInt test_nb = 0;
1304 PetscBool test_flg = PETSC_FALSE;
1305 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-test", &test_nb, &test_flg);
1306
1307 if (test_flg) {
1308 auto simple = mField.getInterface<Simple>();
1309 auto T = createDMVector(simple->getDM());
1310 CHKERR DMoFEMMeshToLocalVector(simple->getDM(), T, INSERT_VALUES,
1311 SCATTER_FORWARD);
1312 double nrm2;
1313 CHKERR VecNorm(T, NORM_2, &nrm2);
1314 MOFEM_LOG("PlasticPrb", Sev::verbose) << "Regression norm " << nrm2;
1315 double regression_value = 0;
1316 switch (test_nb) {
1317 default:
1318 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID, "Wrong test number.");
1319 break;
1320 }
1321 if (fabs(nrm2 - regression_value) > 1e-2)
1322 SETERRQ2(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1323 "Regression test field; wrong norm value. %6.4e != %6.4e", nrm2,
1324 regression_value);
1325 }
1327}
1328//! [Postprocessing results]
1329
1330//! [Check]
1338//! [Check]
1339
1340static char help[] = "...\n\n";
1341
1342int main(int argc, char *argv[]) {
1343
1344#ifdef ADD_CONTACT
1345#ifdef PYTHON_SDF
1346 Py_Initialize();
1347 np::initialize();
1348#endif
1349#endif // ADD_CONTACT
1350
1351 // Initialisation of MoFEM/PETSc and MOAB data structures
1352 const char param_file[] = "param_file.petsc";
1353 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1354
1355 // Add logging channel for example
1356 auto core_log = logging::core::get();
1357 core_log->add_sink(
1359 LogManager::setLog("PlasticPrb");
1360 MOFEM_LOG_TAG("PlasticPrb", "PlasticPrb");
1361 MOFEM_LOG("PlasticPrb", Sev::inform) << "SPACE_DIM " << SPACE_DIM;
1362#ifdef ADD_CONTACT
1363 core_log->add_sink(
1365 LogManager::setLog("CONTACT");
1366 MOFEM_LOG_TAG("CONTACT", "Contact");
1367#endif // ADD_CONTACT
1368
1369 try {
1370
1371 //! [Register MoFEM discrete manager in PETSc]
1372 DMType dm_name = "DMMOFEM";
1373 CHKERR DMRegister_MoFEM(dm_name);
1374 //! [Register MoFEM discrete manager in PETSc
1375
1376 //! [Create MoAB]
1377 moab::Core mb_instance; ///< mesh database
1378 moab::Interface &moab = mb_instance; ///< mesh database interface
1379 //! [Create MoAB]
1380
1381 //! [Create MoFEM]
1382 MoFEM::Core core(moab); ///< finite element database
1383 MoFEM::Interface &m_field = core; ///< finite element database interface
1384 //! [Create MoFEM]
1385
1386 //! [PlasticProblem]
1387 PlasticProblem ex(m_field);
1388 CHKERR ex.runProblem();
1389 //! [PlasticProblem]
1390 }
1392
1394#ifdef ADD_CONTACT
1395#ifdef PYTHON_SDF
1396 if (Py_FinalizeEx() < 0) {
1397 exit(120);
1398 }
1399#endif
1400#endif // ADD_CONTACT
1401 return 0;
1402}
Matetial models for plasticity.
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define TSADAPTMOFEM
Definition TsCtx.hpp:10
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
static char help[]
[Check]
constexpr int SPACE_DIM
double scale
static boost::shared_ptr< TSUpdate > ts_update_ptr
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle DomainEle
constexpr FieldSpace CONTACT_SPACE
constexpr double a
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
#define CATCH_ERRORS
Catch errors.
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()
FieldSpace
approximation spaces
Definition definitions.h:82
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
MoFEMErrorCode opFactoryDomainUpdate(MoFEM::Interface &m_field, Pip &pip, std::string block_name, boost::shared_ptr< CommonData > common_data_ptr, boost::shared_ptr< ClosestPointProjection > cp_ptr)
Push operators to update history variables.
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:523
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
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:586
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1099
PetscErrorCode DMoFEMGetInterfacePtr(DM dm, MoFEM::Interface **m_field_ptr)
Get pointer to MoFEM::Interface.
Definition DMMoFEM.cpp:414
virtual MoFEMErrorCode get_field_entities_by_type(const std::string name, EntityType type, Range &ents) const =0
get entities in the field by type
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
double D
const double v
phase velocity of light in medium (cm/ns)
MoFEMErrorCode opFactoryDomainHenckyStrainLhs(MoFEM::Interface &m_field, std::string field_name, Pip &pip, std::string block_name, boost::shared_ptr< ADOLCPlasticity::CommonData > common_data_ptr, boost::shared_ptr< ClosestPointProjection > cp_ptr)
MoFEMErrorCode opFactoryDomainHenckyStrainRhs(MoFEM::Interface &m_field, std::string field_name, Pip &pip, std::string block_name, boost::shared_ptr< ADOLCPlasticity::CommonData > common_data_ptr, boost::shared_ptr< ClosestPointProjection > cp_ptr)
auto createMaterial(std::array< int, ClosestPointProjection::LAST_TAPE > tapes_tags={0, 1, 2})
ForcesAndSourcesCore::UserDataOperator * getRawPtrOpCalculateStress(MoFEM::Interface &m_field, boost::shared_ptr< CommonData > common_data_ptr, boost::shared_ptr< ClosestPointProjection > cp_ptr, bool calc_lhs)
Get opreator to calulate stress.
boost::shared_ptr< TSUpdate > createTSUpdate(std::string fe_name, boost::shared_ptr< FEMethod > fe_ptr)
MoFEMErrorCode opFactoryDomainRhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
double cn_contact
Definition contact.cpp:100
MoFEMErrorCode opFactoryBoundaryToDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string fe_domain_name, std::string sigma, std::string u, std::string geom, ForcesAndSourcesCore::RuleHookFun rule, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryBoundaryRhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryBoundaryLhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryCalculateTraction(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HenckyOps::CommonData > common_ptr, Sev sev)
MoFEMErrorCode opFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HenckyOps::CommonData > common_ptr, Sev sev)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
Definition DMMoFEM.cpp:1056
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1141
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:232
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
std::vector< boost::shared_ptr< ScalingMethod > > VecOfTimeScalingMethods
Vector of time scaling methods.
Definition Natural.hpp:20
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1127
PetscErrorCode TSAdaptCreateMoFEM(TSAdapt adapt)
Craete MOFEM adapt.
Definition TsCtx.cpp:797
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
int save_every_nth_step
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
constexpr FieldSpace CONTACT_SPACE
Definition plastic.cpp:52
static constexpr int approx_order
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradTensorGrad< 1, SPACE_DIM, SPACE_DIM, 1 > OpKPiola
[Only used for dynamics]
Definition seepage.cpp:63
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForcePiola
Definition seepage.cpp:65
FTensor::Index< 'm', 3 > m
static SmartPetscObj< Vec > totalTraction
static auto createTotalTraction(MoFEM::Interface &m_field)
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
Definition plastic.cpp:29
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
Definition plastic.cpp:36
Add operators pushing bases from local to physical configuration.
boost::weak_ptr< CacheTuple > getCacheWeakPtr() const
Get the cache weak ptr object.
Simple interface for fast problem set-up.
Definition BcManager.hpp:25
Managing BitRefLevels.
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:112
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:76
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 enforce essential constrains.
Definition Essential.hpp:25
Class (Function) to calculate residual side diagonal.
Definition Essential.hpp:49
structure for User Loop Methods on finite elements
Basic algebra on fields.
Definition FieldBlas.hpp:21
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.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Get norm of input MatrixDouble for Tensor1.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Get field gradients at integration pts for scalar filed rank 0, i.e. vector field.
Get values at integration pts for tensor filed rank 1, i.e. vector field.
Element used to execute operators on side of the element.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
PipelineManager interface.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
intrusive_ptr for managing petsc objects
PetscReal ts_t
time
PetscInt ts_step
time step number
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
[Push operators to pipeline]
boost::shared_ptr< PostProcEleDomain > domainPostProcFe
boost::shared_ptr< BoundaryEle > integrateTraction
boost::shared_ptr< FEMethod > reactionFE
Monitor(SmartPetscObj< DM > dm, std::pair< boost::shared_ptr< PostProcEleDomain >, boost::shared_ptr< PostProcEleBdy > > pair_post_proc_fe, boost::shared_ptr< DomainEle > reaction_fe, std::vector< boost::shared_ptr< ScalingMethod > > smv)
VecOfTimeScalingMethods vecOfTimeScalingMethods
boost::shared_ptr< PostProcEleBdy > skinPostProcFe
SmartPetscObj< Vec > fRes
SmartPetscObj< DM > dM
MoFEMErrorCode postProcess()
function is run at the end of loop
PlasticProblem(MoFEM::Interface &m_field)
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode readMesh()
[Run problem]
FieldApproximationBase approxBase
MoFEMErrorCode outputResults()
[Getting norms]
boost::shared_ptr< ClosestPointProjection > cpPtr
MoFEMErrorCode checkResults()
[Postprocessing results]
MoFEMErrorCode boundaryCondition()
[Set up problem]
MoFEM::Interface & mField
PetscBool largeStrain
Large strain flag.
MoFEMErrorCode assembleSystem()
[Boundary condition]
MoFEMErrorCode gettingNorms()
[Solve]
MoFEMErrorCode runProblem()
[Run problem]
MoFEMErrorCode solveSystem()
[Solve]