v0.16.3
Loading...
Searching...
No Matches
plastic.cpp
Go to the documentation of this file.
1/**
2 * \file plastic.cpp
3 * \example mofem/tutorials/adv-0_plasticity/plastic.cpp
4 *
5 * Plasticity in 2d and 3d
6 *
7 */
8
9/* The above code is a preprocessor directive in C++ that checks if the macro
10"EXECUTABLE_DIMENSION" has been defined. If it has not been defined, it replaces
11the " */
12#ifndef EXECUTABLE_DIMENSION
13 #define EXECUTABLE_DIMENSION 3
14#endif
15
16// #undef ADD_CONTACT
17
18#include <MoFEM.hpp>
19#include <MatrixFunction.hpp>
20#include <IntegrationRules.hpp>
21
22using namespace MoFEM;
23
24template <int DIM> struct ElementsAndOps;
25
26template <> struct ElementsAndOps<2> {
30 static constexpr FieldSpace CONTACT_SPACE = HCURL;
31};
32
33template <> struct ElementsAndOps<3> {
37 static constexpr FieldSpace CONTACT_SPACE = HDIV;
38};
39
40constexpr int SPACE_DIM =
41 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
42constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
43
44constexpr AssemblyType AT =
45 (SCHUR_ASSEMBLE) ? AssemblyType::BLOCK_SCHUR
46 : AssemblyType::PETSC; //< selected assembly type
48 IntegrationType::GAUSS; //< selected integration type
49
53
56using DomainEleOp = DomainEle::UserDataOperator;
58using BoundaryEleOp = BoundaryEle::UserDataOperator;
63
64inline double iso_hardening_exp(double tau, double b_iso) {
65 return std::exp(
66 std::max(static_cast<double>(std::numeric_limits<float>::min_exponent10),
67 -b_iso * tau));
68}
69
70/**
71 * Isotropic hardening
72 */
73inline double iso_hardening(double tau, double H, double Qinf, double b_iso,
74 double sigmaY) {
75 return H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso)) + sigmaY;
76}
77
78inline double iso_hardening_dtau(double tau, double H, double Qinf,
79 double b_iso) {
80 auto r = [&](auto tau) {
81 return H + Qinf * b_iso * iso_hardening_exp(tau, b_iso);
82 };
83 constexpr double eps = 1e-12;
84 return std::max(r(tau), eps * r(0));
85}
86
87/**
88 * Kinematic hardening
89 */
90template <typename T, int DIM>
91inline auto
93 double C1_k) {
94 FTensor::Index<'i', DIM> i;
95 FTensor::Index<'j', DIM> j;
97 if (C1_k < std::numeric_limits<double>::epsilon()) {
98 t_alpha(i, j) = 0;
99 return t_alpha;
100 }
101 t_alpha(i, j) = C1_k * t_plastic_strain(i, j);
102 return t_alpha;
103}
104
105template <int DIM>
107 FTensor::Index<'i', DIM> i;
108 FTensor::Index<'j', DIM> j;
109 FTensor::Index<'k', DIM> k;
110 FTensor::Index<'l', DIM> l;
113 t_diff(i, j, k, l) = C1_k * (t_kd(i, k) ^ t_kd(j, l)) / 4.;
114 return t_diff;
115}
116
117PetscBool is_large_strains = PETSC_TRUE; ///< Large strains
118PetscBool set_timer = PETSC_FALSE; ///< Set timer
119PetscBool do_eval_field = PETSC_FALSE; ///< Evaluate field
120
121int atom_test = 0; ///< Atom test
122
123double scale = 1.;
124
125double young_modulus = 206913; ///< Young modulus
126double poisson_ratio = 0.29; ///< Poisson ratio
127double sigmaY = 450; ///< Yield stress
128double H = 129; ///< Hardening
129double visH = 0; ///< Viscous hardening
130double zeta = 5e-2; ///< Viscous hardening
131double Qinf = 265; ///< Saturation yield stress
132double b_iso = 16.93; ///< Saturation exponent
133double C1_k = 0; ///< Kinematic hardening
134
135double cn0 = 1;
136double cn1 = 1;
137
138int order = 2; ///< Order displacement
139int tau_order = order - 2; ///< Order of tau files
140int ep_order = order - 1; ///< Order of ep files
141int geom_order = 2; ///< Order if fixed.
142
143PetscBool is_quasi_static = PETSC_TRUE;
144double rho = 0.0;
145double alpha_damping = 0;
146
147#include <HenckyOps.hpp>
148#include <PlasticOps.hpp>
149#include <PlasticNaturalBCs.hpp>
150
151#ifdef ADD_CONTACT
152 #ifdef ENABLE_PYTHON_BINDING
153 #include <boost/python.hpp>
154 #include <boost/python/def.hpp>
155 #include <boost/python/numpy.hpp>
156namespace bp = boost::python;
157namespace np = boost::python::numpy;
158 #endif
159
160namespace ContactOps {
161
162double cn_contact = 0.1;
163
164}; // namespace ContactOps
165
166 #include <ContactOps.hpp>
167#endif // ADD_CONTACT
168
178
179using namespace PlasticOps;
180using namespace HenckyOps;
181
182namespace PlasticOps {
183
184template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM> struct AddHOOps;
185
186template <> struct AddHOOps<2, 3, 3> {
187 AddHOOps() = delete;
188 static MoFEMErrorCode
189 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
190 std::vector<FieldSpace> space, std::string geom_field_name);
191};
192
193template <> struct AddHOOps<1, 2, 2> {
194 AddHOOps() = delete;
195 static MoFEMErrorCode
196 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
197 std::vector<FieldSpace> space, std::string geom_field_name);
198};
199
200template <> struct AddHOOps<3, 3, 3> {
201 AddHOOps() = delete;
202 static MoFEMErrorCode
203 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
204 std::vector<FieldSpace> space, std::string geom_field_name);
205};
206
207template <> struct AddHOOps<2, 2, 2> {
208 AddHOOps() = delete;
209 static MoFEMErrorCode
210 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
211 std::vector<FieldSpace> space, std::string geom_field_name);
212};
213
214} // namespace PlasticOps
215
216struct Example {
217
218 Example(MoFEM::Interface &m_field) : mField(m_field) {}
219
221
222 enum { VOL, COUNT };
223 static inline std::array<double, 2> meshVolumeAndCount = {0, 0};
224
225private:
227
234
235 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
236 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
237 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
238
241 double getScale(const double time) {
242 return scale * MoFEM::TimeScale::getScale(time);
243 };
244 };
245
246#ifdef ADD_CONTACT
247 #ifdef ENABLE_PYTHON_BINDING
248 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
249 #endif
250#endif // ADD_CONTACT
251};
252
253//! [Run problem]
258 CHKERR bC();
259 CHKERR OPs();
260 PetscBool test_ops = PETSC_FALSE;
261 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_operators", &test_ops,
262 PETSC_NULLPTR);
263 if (test_ops == PETSC_FALSE) {
264 CHKERR tsSolve();
265 } else {
267 }
269}
270//! [Run problem]
271
272//! [Set up problem]
276
277 Range domain_ents;
278 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
279 true);
280 auto get_ents_by_dim = [&](const auto dim) {
281 if (dim == SPACE_DIM) {
282 return domain_ents;
283 } else {
284 Range ents;
285 if (dim == 0)
286 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
287 else
288 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
289 return ents;
290 }
291 };
292
293 auto get_base = [&]() {
294 auto domain_ents = get_ents_by_dim(SPACE_DIM);
295 if (domain_ents.empty())
296 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
297 const auto type = type_from_handle(domain_ents[0]);
298 switch (type) {
299 case MBQUAD:
301 case MBHEX:
303 case MBTRI:
305 case MBTET:
307 default:
308 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
309 }
310 return NOBASE;
311 };
312
313 const auto base = get_base();
314 MOFEM_LOG("PLASTICITY", Sev::inform)
315 << "Base " << ApproximationBaseNames[base];
316
319 CHKERR simple->addDomainField("TAU", L2, base, 1);
321
322 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
323
324 PetscBool order_edge = PETSC_FALSE;
325 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_edge", &order_edge,
326 PETSC_NULLPTR);
327 PetscBool order_face = PETSC_FALSE;
328 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_face", &order_face,
329 PETSC_NULLPTR);
330 PetscBool order_volume = PETSC_FALSE;
331 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_volume", &order_volume,
332 PETSC_NULLPTR);
333
335
336 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order edge " << order_edge
337 ? "true"
338 : "false";
339 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order face " << order_face
340 ? "true"
341 : "false";
342 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order volume " << order_volume
343 ? "true"
344 : "false";
345
346 auto ents = get_ents_by_dim(0);
347 if (order_edge)
348 ents.merge(get_ents_by_dim(1));
349 if (order_face)
350 ents.merge(get_ents_by_dim(2));
351 if (order_volume)
352 ents.merge(get_ents_by_dim(3));
353 CHKERR simple->setFieldOrder("U", order, &ents);
354 } else {
356 }
359
361
362#ifdef ADD_CONTACT
364 SPACE_DIM);
366 SPACE_DIM);
367
368 auto get_skin = [&]() {
369 Range body_ents;
370 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
371 Skinner skin(&mField.get_moab());
372 Range skin_ents;
373 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
374 return skin_ents;
375 };
376
377 auto filter_blocks = [&](auto skin) {
378 bool is_contact_block = true;
379 Range contact_range;
380 for (auto m :
381 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
382
383 (boost::format("%s(.*)") % "CONTACT").str()
384
385 ))
386
387 ) {
388 is_contact_block =
389 true; ///< blocs interation is collective, so that is set irrespective
390 ///< if there are entities in given rank or not in the block
391 MOFEM_LOG("CONTACT", Sev::inform)
392 << "Find contact block set: " << m->getName();
393 auto meshset = m->getMeshset();
394 Range contact_meshset_range;
395 CHKERR mField.get_moab().get_entities_by_dimension(
396 meshset, SPACE_DIM - 1, contact_meshset_range, true);
397
398 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
399 contact_meshset_range);
400 contact_range.merge(contact_meshset_range);
401 }
402 if (is_contact_block) {
403 MOFEM_LOG("SYNC", Sev::inform)
404 << "Nb entities in contact surface: " << contact_range.size();
406 skin = intersect(skin, contact_range);
407 }
408 return skin;
409 };
410
411 auto filter_true_skin = [&](auto skin) {
412 Range boundary_ents;
413 ParallelComm *pcomm =
414 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
415 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
416 PSTATUS_NOT, -1, &boundary_ents);
417 return boundary_ents;
418 };
419
420 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
421 CHKERR simple->setFieldOrder("SIGMA", 0);
422 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
423#endif
424
427
428 auto project_ho_geometry = [&]() {
429 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
430 return mField.loop_dofs("GEOMETRY", ent_method);
431 };
432 PetscBool project_geometry = PETSC_TRUE;
433 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
434 &project_geometry, PETSC_NULLPTR);
435 if (project_geometry) {
436 CHKERR project_ho_geometry();
437 }
438
439 auto get_volume = [&]() {
440 using VolOp = DomainEle::UserDataOperator;
441 auto *op_ptr = new VolOp(NOSPACE, VolOp::OPSPACE);
442 std::array<double, 2> volume_and_count;
443 op_ptr->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
444 EntityType type,
447 auto op_ptr = static_cast<VolOp *>(base_op_ptr);
448 volume_and_count[VOL] += op_ptr->getMeasure();
449 volume_and_count[COUNT] += 1;
450 // in necessary at integration over Gauss points.
452 };
453 volume_and_count = {0, 0};
454 auto fe = boost::make_shared<DomainEle>(mField);
455 fe->getOpPtrVector().push_back(op_ptr);
456
457 auto dm = simple->getDM();
460 "cac volume");
461 std::array<double, 2> tot_volume_and_count;
462 MPI_Allreduce(volume_and_count.data(), tot_volume_and_count.data(),
463 volume_and_count.size(), MPI_DOUBLE, MPI_SUM,
464 mField.get_comm());
465 return tot_volume_and_count;
466 };
467
468 meshVolumeAndCount = get_volume();
469 MOFEM_LOG("PLASTICITY", Sev::inform)
470 << "Mesh volume " << meshVolumeAndCount[VOL] << " nb. of elements "
472
474}
475//! [Set up problem]
476
477//! [Create common data]
480
481 auto get_command_line_parameters = [&]() {
483
484 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale, PETSC_NULLPTR);
485 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
486 &young_modulus, PETSC_NULLPTR);
487 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
488 &poisson_ratio, PETSC_NULLPTR);
489 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening", &H, PETSC_NULLPTR);
490 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening_viscous", &visH,
491 PETSC_NULLPTR);
492 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-yield_stress", &sigmaY,
493 PETSC_NULLPTR);
494 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn0", &cn0, PETSC_NULLPTR);
495 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn1", &cn1, PETSC_NULLPTR);
496 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-zeta", &zeta, PETSC_NULLPTR);
497 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-Qinf", &Qinf, PETSC_NULLPTR);
498 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-b_iso", &b_iso, PETSC_NULLPTR);
499 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-C1_k", &C1_k, PETSC_NULLPTR);
500 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strains",
501 &is_large_strains, PETSC_NULLPTR);
502 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-set_timer", &set_timer,
503 PETSC_NULLPTR);
504 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
505 PETSC_NULLPTR);
506
507 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
508 PetscBool tau_order_is_set; ///< true if tau order is set
509 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-tau_order", &tau_order,
510 &tau_order_is_set);
511 PetscBool ep_order_is_set; ///< true if tau order is set
512 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-ep_order", &ep_order,
513 &ep_order_is_set);
514 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
515 PETSC_NULLPTR);
516
517 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho, PETSC_NULLPTR);
518 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
519 &alpha_damping, PETSC_NULLPTR);
520
521 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
522 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
523 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
524 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
525 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
526 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
527 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
528 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
529 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
530 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
531 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
532
533 if (tau_order_is_set == PETSC_FALSE)
534 tau_order = order - 2;
535 if (ep_order_is_set == PETSC_FALSE)
536 ep_order = order - 1;
537
538 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
539 MOFEM_LOG("PLASTICITY", Sev::inform)
540 << "Ep approximation order " << ep_order;
541 MOFEM_LOG("PLASTICITY", Sev::inform)
542 << "Tau approximation order " << tau_order;
543 MOFEM_LOG("PLASTICITY", Sev::inform)
544 << "Geometry approximation order " << geom_order;
545
546 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
547 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
548
549 PetscBool is_scale = PETSC_TRUE;
550 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_scale", &is_scale,
551 PETSC_NULLPTR);
552 if (is_scale) {
554 }
555
556 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
557
558#ifdef ADD_CONTACT
559 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn_contact",
560 &ContactOps::cn_contact, PETSC_NULLPTR);
561 MOFEM_LOG("CONTACT", Sev::inform)
562 << "cn_contact " << ContactOps::cn_contact;
563#endif // ADD_CONTACT
564
565 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-quasi_static",
566 &is_quasi_static, PETSC_NULLPTR);
567 MOFEM_LOG("PLASTICITY", Sev::inform)
568 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
569
571 };
572
573 CHKERR get_command_line_parameters();
574
575#ifdef ADD_CONTACT
576 #ifdef ENABLE_PYTHON_BINDING
577 auto file_exists = [](std::string myfile) {
578 std::ifstream file(myfile.c_str());
579 if (file) {
580 return true;
581 }
582 return false;
583 };
584 char sdf_file_name[255] = "sdf.py";
585 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
586 sdf_file_name, 255, PETSC_NULLPTR);
587
588 if (file_exists(sdf_file_name)) {
589 MOFEM_LOG("CONTACT", Sev::inform) << sdf_file_name << " file found";
590 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
591 CHKERR sdfPythonPtr->sdfInit(sdf_file_name);
592 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
593 } else {
594 MOFEM_LOG("CONTACT", Sev::warning) << sdf_file_name << " file NOT found";
595 }
596 #endif
597#endif // ADD_CONTACT
598
600}
601//! [Create common data]
602
603//! [Boundary condition]
606
608 auto bc_mng = mField.getInterface<BcManager>();
609
610 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
611 "U", 0, 0);
612 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
613 "U", 1, 1);
614 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
615 "U", 2, 2);
616 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
617 "REMOVE_ALL", "U", 0, 3);
618
619#ifdef ADD_CONTACT
620 for (auto b : {"FIX_X", "REMOVE_X"})
621 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
622 "SIGMA", 0, 0, false, true);
623 for (auto b : {"FIX_Y", "REMOVE_Y"})
624 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
625 "SIGMA", 1, 1, false, true);
626 for (auto b : {"FIX_Z", "REMOVE_Z"})
627 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
628 "SIGMA", 2, 2, false, true);
629 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
630 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
631 "SIGMA", 0, 3, false, true);
632 CHKERR bc_mng->removeBlockDOFsOnEntities(
633 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
634#endif
635
636 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
637 simple->getProblemName(), "U");
638
639 auto &bc_map = bc_mng->getBcMapByBlockName();
640 for (auto bc : bc_map)
641 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
642
644}
645//! [Boundary condition]
646
647//! [Push operators to pipeline]
650 auto pip_mng = mField.getInterface<PipelineManager>();
651
652 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
653
654 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order - 1; };
655
656 auto add_boundary_ops_lhs_mechanical = [&](auto &pip) {
658
660 pip, {HDIV}, "GEOMETRY");
661 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
662
663 // Add Natural BCs to LHS
665 pip, mField, "U", Sev::inform);
666
667#ifdef ADD_CONTACT
669 CHKERR
670 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
671 pip, "SIGMA", "U");
672 CHKERR
673 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
674 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
675 vol_rule);
676#endif // ADD_CONTACT
677
679 };
680
681 auto add_boundary_ops_rhs_mechanical = [&](auto &pip) {
683
685 pip, {HDIV}, "GEOMETRY");
686 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
687
688 // Add Natural BCs to RHS
690 pip, mField, "U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
691
692#ifdef ADD_CONTACT
693 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
694 pip, "SIGMA", "U");
695#endif // ADD_CONTACT
696
698 };
699
700 auto add_domain_ops_lhs = [this](auto &pip) {
703 pip, {H1, HDIV}, "GEOMETRY");
704
705 if (is_quasi_static == PETSC_FALSE) {
706
707 //! [Only used for dynamics]
710 //! [Only used for dynamics]
711
712 auto get_inertia_and_mass_damping = [this](const double, const double,
713 const double) {
714 auto *pip = mField.getInterface<PipelineManager>();
715 auto &fe_domain_lhs = pip->getDomainLhsFE();
716 return (rho / scale) * fe_domain_lhs->ts_aa +
717 (alpha_damping / scale) * fe_domain_lhs->ts_a;
718 };
719 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
720 }
721
722 CHKERR PlasticOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
723 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
724
726 };
727
728 auto add_domain_ops_rhs = [this](auto &pip) {
730
732 pip, {H1, HDIV}, "GEOMETRY");
733
735 pip, mField, "U",
736 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
737 Sev::inform);
738
739 // only in case of dynamics
740 if (is_quasi_static == PETSC_FALSE) {
741
742 //! [Only used for dynamics]
745 //! [Only used for dynamics]
746
747 auto mat_acceleration = boost::make_shared<MatrixDouble>();
749 "U", mat_acceleration));
750 pip.push_back(
751 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
752 return rho / scale;
753 }));
754 if (alpha_damping > 0) {
755 auto mat_velocity = boost::make_shared<MatrixDouble>();
756 pip.push_back(
757 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
758 pip.push_back(
759 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
760 return alpha_damping / scale;
761 }));
762 }
763 }
764
765 CHKERR PlasticOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
766 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
767
768#ifdef ADD_CONTACT
769 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
770 pip, "SIGMA", "U");
771#endif // ADD_CONTACT
772
774 };
775
776 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
777 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
778
779 // Boundary
780 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
781 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
782
783 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
784 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
785
786 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
787 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
788
789 auto create_reaction_pipeline = [&](auto &pip) {
792 pip, {H1}, "GEOMETRY");
793 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
794 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
796 };
797
798 CHKERR pip_mng->setEvaluationIntegrationRule(vol_rule);
799 CHKERR create_reaction_pipeline(pip_mng->getOpEvaluationPipeline());
800 auto &reaction_fe = pip_mng->getEvaluationFE();
801 reaction_fe->postProcessHook =
803
805}
806//! [Push operators to pipeline]
807
808//! [Solve]
809struct SetUpSchur {
810
811 /**
812 * @brief Create data structure for handling Schur complement
813 *
814 * @param m_field
815 * @param sub_dm Schur complement sub dm
816 * @param field_split_it IS of Schur block
817 * @param ao_map AO map from sub dm to main problem
818 * @return boost::shared_ptr<SetUpSchur>
819 */
820 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
821
822 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
823 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
824
825 );
826 virtual MoFEMErrorCode setUp(TS solver) = 0;
827
828protected:
829 SetUpSchur() = default;
830};
831
834
837 ISManager *is_manager = mField.getInterface<ISManager>();
838
839 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
840
841 auto set_section_monitor = [&](auto solver) {
843 SNES snes;
844 CHKERR TSGetSNES(solver, &snes);
845 CHKERR SNESMonitorSet(snes,
846 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
848 (void *)(snes_ctx_ptr.get()), nullptr);
850 };
851
852 auto create_post_process_elements = [&]() {
853 auto push_vol_ops = [this](auto &pip) {
855 pip, {H1, HDIV}, "GEOMETRY");
856
857 auto [common_plastic_ptr, common_hencky_ptr] =
858 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
859 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU", 1., Sev::inform);
860
861 if (common_hencky_ptr) {
862 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
863 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
864 }
865
866 return std::make_pair(common_plastic_ptr, common_hencky_ptr);
867 };
868
869 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
871
872 auto &pip = pp_fe->getOpPtrVector();
873
874 auto [common_plastic_ptr, common_hencky_ptr] = p;
875
877
878 auto x_ptr = boost::make_shared<MatrixDouble>();
879 pip.push_back(
880 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
881 auto u_ptr = boost::make_shared<MatrixDouble>();
882 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
883
884 if (is_large_strains) {
885
886 pip.push_back(
887
888 new OpPPMap(
889
890 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
891
892 {{"PLASTIC_SURFACE",
893 common_plastic_ptr->getPlasticSurfacePtr()},
894 {"PLASTIC_MULTIPLIER",
895 common_plastic_ptr->getPlasticTauPtr()}},
896
897 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
898
899 {{"GRAD", common_hencky_ptr->matGradPtr},
900 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
901
902 {{"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
903 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
904 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
905
906 )
907
908 );
909
910 } else {
911
912 pip.push_back(
913
914 new OpPPMap(
915
916 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
917
918 {{"PLASTIC_SURFACE",
919 common_plastic_ptr->getPlasticSurfacePtr()},
920 {"PLASTIC_MULTIPLIER",
921 common_plastic_ptr->getPlasticTauPtr()}},
922
923 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
924
925 {},
926
927 {{"STRAIN", common_plastic_ptr->mStrainPtr},
928 {"STRESS", common_plastic_ptr->mStressPtr},
929 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
930 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
931
932 )
933
934 );
935 }
936
938 };
939
940 PetscBool post_proc_vol;
941 PetscBool post_proc_skin;
942
943 if constexpr (SPACE_DIM == 2) {
944 post_proc_vol = PETSC_TRUE;
945 post_proc_skin = PETSC_FALSE;
946 } else {
947 post_proc_vol = PETSC_FALSE;
948 post_proc_skin = PETSC_TRUE;
949 }
950 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol", &post_proc_vol,
951 PETSC_NULLPTR);
952 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
953 &post_proc_skin, PETSC_NULLPTR);
954
955 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
956 post_proc_vol]() {
957 if (post_proc_vol == PETSC_FALSE)
958 return boost::shared_ptr<PostProcEle>();
959 auto pp_fe = boost::make_shared<PostProcEle>(mField);
961 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
962 "push_vol_post_proc_ops");
963 return pp_fe;
964 };
965
966 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
967 post_proc_skin]() {
968 if (post_proc_skin == PETSC_FALSE)
969 return boost::shared_ptr<SkinPostProcEle>();
970
971 auto simple = mField.getInterface<Simple>();
972 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
973 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
974 SPACE_DIM, Sev::verbose);
975 pp_fe->getOpPtrVector().push_back(op_side);
976 CHK_MOAB_THROW(push_vol_post_proc_ops(
977 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
978 "push_vol_post_proc_ops");
979 return pp_fe;
980 };
981
982 return std::make_pair(vol_post_proc(), skin_post_proc());
983 };
984
985 auto scatter_create = [&](auto D, auto coeff) {
987 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
988 ROW, "U", coeff, coeff, is);
989 int loc_size;
990 CHKERR ISGetLocalSize(is, &loc_size);
991 Vec v;
992 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
993 VecScatter scatter;
994 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
995 return std::make_tuple(SmartPetscObj<Vec>(v),
997 };
998
999 boost::shared_ptr<SetPtsData> field_eval_data;
1000 boost::shared_ptr<MatrixDouble> u_field_ptr;
1001
1002 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1003 int coords_dim = 3;
1004 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
1005 field_eval_coords.data(), &coords_dim,
1006 &do_eval_field);
1007
1008 boost::shared_ptr<std::map<std::string, boost::shared_ptr<VectorDouble>>>
1009 scalar_field_ptrs = boost::make_shared<
1010 std::map<std::string, boost::shared_ptr<VectorDouble>>>();
1011 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1012 vector_field_ptrs = boost::make_shared<
1013 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1014 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1015 sym_tensor_field_ptrs = boost::make_shared<
1016 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1017 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1018 tensor_field_ptrs = boost::make_shared<
1019 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1020
1021 if (do_eval_field) {
1022 auto u_field_ptr = boost::make_shared<MatrixDouble>();
1023 field_eval_data =
1024 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
1025
1026 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
1027 field_eval_data, simple->getDomainFEName());
1028
1029 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1030 auto no_rule = [](int, int, int) { return -1; };
1031 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1032 field_eval_fe_ptr->getRuleHook = no_rule;
1033
1035 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV}, "GEOMETRY");
1036
1037 auto [common_plastic_ptr, common_hencky_ptr] =
1038 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1039 mField, "MAT_PLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U",
1040 "EP", "TAU", 1., Sev::inform);
1041
1042 field_eval_fe_ptr->getOpPtrVector().push_back(
1043 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_field_ptr));
1044
1045 if ((common_plastic_ptr) && (common_hencky_ptr) && (scalar_field_ptrs)) {
1046 if (is_large_strains) {
1047 scalar_field_ptrs->insert(
1048 {"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1049 scalar_field_ptrs->insert(
1050 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1051 vector_field_ptrs->insert({"U", u_field_ptr});
1052 sym_tensor_field_ptrs->insert(
1053 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1054 sym_tensor_field_ptrs->insert(
1055 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1056 sym_tensor_field_ptrs->insert(
1057 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()});
1058 tensor_field_ptrs->insert({"GRAD", common_hencky_ptr->matGradPtr});
1059 tensor_field_ptrs->insert(
1060 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()});
1061 } else {
1062 scalar_field_ptrs->insert(
1063 {"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1064 scalar_field_ptrs->insert(
1065 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1066 vector_field_ptrs->insert({"U", u_field_ptr});
1067 sym_tensor_field_ptrs->insert(
1068 {"STRAIN", common_plastic_ptr->mStrainPtr});
1069 sym_tensor_field_ptrs->insert(
1070 {"STRESS", common_plastic_ptr->mStressPtr});
1071 sym_tensor_field_ptrs->insert(
1072 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1073 sym_tensor_field_ptrs->insert(
1074 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1075 }
1076 }
1077 }
1078
1079 auto test_monitor_ptr = boost::make_shared<FEMethod>();
1080
1081 auto set_time_monitor = [&](auto dm, auto solver) {
1083 boost::shared_ptr<Monitor<SPACE_DIM>> monitor_ptr(new Monitor<SPACE_DIM>(
1084 dm, create_post_process_elements(), uXScatter, uYScatter, uZScatter,
1085 field_eval_coords, field_eval_data, scalar_field_ptrs,
1086 vector_field_ptrs, sym_tensor_field_ptrs, tensor_field_ptrs));
1087 boost::shared_ptr<ForcesAndSourcesCore> null;
1088
1089 test_monitor_ptr->postProcessHook = [&]() {
1091
1092 if (atom_test && fabs(test_monitor_ptr->ts_t - 0.5) < 1e-12 &&
1093 test_monitor_ptr->ts_step == 25) {
1094
1095 if (scalar_field_ptrs->at("PLASTIC_MULTIPLIER")->size()) {
1096 auto t_tau =
1097 getFTensor0FromVec(*scalar_field_ptrs->at("PLASTIC_MULTIPLIER"));
1098 MOFEM_LOG("PlasticSync", Sev::inform) << "Eval point tau: " << t_tau;
1099
1100 if (atom_test == 1 && fabs(t_tau - 0.688861) > 1e-5) {
1101 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1102 "atom test %d failed: wrong plastic multiplier value",
1103 atom_test);
1104 }
1105 }
1106
1107 if (vector_field_ptrs->at("U")->size1()) {
1109 auto t_disp =
1110 getFTensor1FromMat<SPACE_DIM>(*vector_field_ptrs->at("U"));
1111 MOFEM_LOG("PlasticSync", Sev::inform) << "Eval point U: " << t_disp;
1112
1113 if (atom_test == 1 && fabs(t_disp(0) - 0.25 / 2.) > 1e-5 ||
1114 fabs(t_disp(1) + 0.0526736) > 1e-5) {
1115 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1116 "atom test %d failed: wrong displacement value",
1117 atom_test);
1118 }
1119 }
1120
1121 if (sym_tensor_field_ptrs->at("PLASTIC_STRAIN")->size1()) {
1122 auto t_plastic_strain = getFTensor2SymmetricFromMat<SPACE_DIM>(
1123 *sym_tensor_field_ptrs->at("PLASTIC_STRAIN"));
1124 MOFEM_LOG("PlasticSync", Sev::inform)
1125 << "Eval point EP: " << t_plastic_strain;
1126
1127 if (atom_test == 1 &&
1128 fabs(t_plastic_strain(0, 0) - 0.221943) > 1e-5 ||
1129 fabs(t_plastic_strain(0, 1)) > 1e-5 ||
1130 fabs(t_plastic_strain(1, 1) + 0.110971) > 1e-5) {
1131 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1132 "atom test %d failed: wrong plastic strain value",
1133 atom_test);
1134 }
1135 }
1136
1137 if (tensor_field_ptrs->at("FIRST_PIOLA")->size1()) {
1138 auto t_piola_stress = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(
1139 *tensor_field_ptrs->at("FIRST_PIOLA"));
1140 MOFEM_LOG("PlasticSync", Sev::inform)
1141 << "Eval point Piola stress: " << t_piola_stress;
1142
1143 if (atom_test == 1 && fabs((t_piola_stress(0, 0) - 198.775) /
1144 t_piola_stress(0, 0)) > 1e-5 ||
1145 fabs(t_piola_stress(0, 1)) + fabs(t_piola_stress(1, 0)) +
1146 fabs(t_piola_stress(1, 1)) >
1147 1e-5) {
1148 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1149 "atom test %d failed: wrong Piola stress value",
1150 atom_test);
1151 }
1152 }
1153 }
1154
1155 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
1157 };
1158
1159 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
1160 monitor_ptr, null, test_monitor_ptr);
1161
1163 };
1164
1165 auto set_schur_pc = [&](auto solver,
1166 boost::shared_ptr<SetUpSchur> &schur_ptr) {
1168
1169 auto name_prb = simple->getProblemName();
1170
1171 // create sub dm for Schur complement
1172 auto create_schur_dm = [&](SmartPetscObj<DM> base_dm,
1173 SmartPetscObj<DM> &dm_sub) {
1175 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
1176 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SCHUR");
1177 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1178 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1179 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
1180 for (auto f : {"U"}) {
1183 }
1184 CHKERR DMSetUp(dm_sub);
1185
1187 };
1188
1189 auto create_block_dm = [&](SmartPetscObj<DM> base_dm,
1190 SmartPetscObj<DM> &dm_sub) {
1192 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
1193 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "BLOCK");
1194 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1195 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1196 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
1197#ifdef ADD_CONTACT
1198 for (auto f : {"SIGMA", "EP", "TAU"}) {
1201 }
1202#else
1203 for (auto f : {"EP", "TAU"}) {
1206 }
1207#endif
1208 CHKERR DMSetUp(dm_sub);
1210 };
1211
1212 // Create nested (sub BC) Schur DM
1213 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
1214
1215 SmartPetscObj<DM> dm_schur;
1216 CHKERR create_schur_dm(simple->getDM(), dm_schur);
1217 SmartPetscObj<DM> dm_block;
1218 CHKERR create_block_dm(simple->getDM(), dm_block);
1219
1220#ifdef ADD_CONTACT
1221
1222 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1223 auto block_mat_data = createBlockMatStructure(
1224 simple->getDM(),
1225
1226 {
1227
1228 {simple->getDomainFEName(),
1229
1230 {{"U", "U"},
1231 {"SIGMA", "SIGMA"},
1232 {"U", "SIGMA"},
1233 {"SIGMA", "U"},
1234 {"EP", "EP"},
1235 {"TAU", "TAU"},
1236 {"U", "EP"},
1237 {"EP", "U"},
1238 {"EP", "TAU"},
1239 {"TAU", "EP"},
1240 {"TAU", "U"}
1241
1242 }},
1243
1244 {simple->getBoundaryFEName(),
1245
1246 {{"SIGMA", "SIGMA"}, {"U", "SIGMA"}, {"SIGMA", "U"}
1247
1248 }}
1249
1250 }
1251
1252 );
1253
1255
1256 {dm_schur, dm_block}, block_mat_data,
1257
1258 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, true
1259
1260 );
1261 };
1262
1263#else
1264
1265 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1266 auto block_mat_data =
1268
1269 {{simple->getDomainFEName(),
1270
1271 {{"U", "U"},
1272 {"EP", "EP"},
1273 {"TAU", "TAU"},
1274 {"U", "EP"},
1275 {"EP", "U"},
1276 {"EP", "TAU"},
1277 {"TAU", "U"},
1278 {"TAU", "EP"}
1279
1280 }}}
1281
1282 );
1283
1285
1286 {dm_schur, dm_block}, block_mat_data,
1287
1288 {"EP", "TAU"}, {nullptr, nullptr}, false
1289
1290 );
1291 };
1292
1293#endif
1294
1295 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
1296 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
1297
1298 auto block_is = getDMSubData(dm_block)->getSmartRowIs();
1299 auto ao_schur = getDMSubData(dm_schur)->getSmartRowMap();
1300
1301 // Indices has to be map fro very to level, while assembling Schur
1302 // complement.
1303 schur_ptr =
1304 SetUpSchur::createSetUpSchur(mField, dm_schur, block_is, ao_schur);
1305 CHKERR schur_ptr->setUp(solver);
1306 }
1307
1309 };
1310
1311 auto dm = simple->getDM();
1312 auto D = createDMVector(dm);
1313 auto DD = vectorDuplicate(D);
1314 CHKERR VecSetDM(D, PETSC_NULLPTR);
1315 CHKERR VecSetDM(DD, PETSC_NULLPTR);
1316 uXScatter = scatter_create(D, 0);
1317 uYScatter = scatter_create(D, 1);
1318 if constexpr (SPACE_DIM == 3)
1319 uZScatter = scatter_create(D, 2);
1320
1321 auto create_solver = [pip_mng]() {
1322 if (is_quasi_static == PETSC_TRUE)
1323 return pip_mng->createTSIM();
1324 else
1325 return pip_mng->createTSIM2();
1326 };
1327
1328 auto solver = create_solver();
1329
1330 auto active_pre_lhs = []() {
1332 std::fill(PlasticOps::CommonData::activityData.begin(),
1335 };
1336
1337 auto active_post_lhs = [&]() {
1339 auto get_iter = [&]() {
1340 SNES snes;
1341 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
1342 int iter;
1343 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
1344 "Can not get iter");
1345 return iter;
1346 };
1347
1348 auto iter = get_iter();
1349 if (iter >= 0) {
1350
1351 std::array<int, 5> activity_data;
1352 std::fill(activity_data.begin(), activity_data.end(), 0);
1353 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
1354 activity_data.data(), activity_data.size(), MPI_INT,
1355 MPI_SUM, mField.get_comm());
1356
1357 int &active_points = activity_data[0];
1358 int &avtive_full_elems = activity_data[1];
1359 int &avtive_elems = activity_data[2];
1360 int &nb_points = activity_data[3];
1361 int &nb_elements = activity_data[4];
1362
1363 if (nb_points) {
1364
1365 double proc_nb_points =
1366 100 * static_cast<double>(active_points) / nb_points;
1367 double proc_nb_active =
1368 100 * static_cast<double>(avtive_elems) / nb_elements;
1369 double proc_nb_full_active = 100;
1370 if (avtive_elems)
1371 proc_nb_full_active =
1372 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
1373
1374 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1375 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
1376 "elements %d "
1377 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1378 iter, nb_points, active_points, proc_nb_points,
1379 avtive_elems, proc_nb_active, avtive_full_elems,
1380 proc_nb_full_active, iter);
1381 }
1382 }
1383
1385 };
1386
1387 auto add_active_dofs_elem = [&](auto dm) {
1389 auto fe_pre_proc = boost::make_shared<FEMethod>();
1390 fe_pre_proc->preProcessHook = active_pre_lhs;
1391 auto fe_post_proc = boost::make_shared<FEMethod>();
1392 fe_post_proc->postProcessHook = active_post_lhs;
1393 auto ts_ctx_ptr = getDMTsCtx(dm);
1394 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1395 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1397 };
1398
1399 auto set_essential_bc = [&](auto dm, auto solver) {
1401 // This is low level pushing finite elements (pipelines) to solver
1402
1403 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1404 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1405 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1406 auto ts_ctx_ptr = getDMTsCtx(dm);
1407 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1408 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1409 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1410 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1411
1412 // Add boundary condition scaling
1413 auto disp_time_scale = boost::make_shared<TimeScale>();
1414
1415 auto get_bc_hook_rhs = [&]() {
1417 mField, pre_proc_ptr, {disp_time_scale}, false);
1418 };
1419 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1420
1421 auto waak_post_proc_rhs_ptr = boost::weak_ptr<FEMethod>(
1422 post_proc_rhs_ptr); // fe method passed to lambda, have to be weak ptr to avoid circular shared ptr reference
1423 auto get_post_proc_hook_rhs = [this, waak_post_proc_rhs_ptr]() {
1426 mField, waak_post_proc_rhs_ptr.lock(), nullptr, Sev::verbose)();
1428 mField, waak_post_proc_rhs_ptr.lock(), 1.)();
1430 };
1431 auto get_post_proc_hook_lhs = [&]() {
1433 mField, post_proc_lhs_ptr, 1.);
1434 };
1435
1436 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1437 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1438
1440 };
1441
1442 auto B = createDMMatrix(dm);
1443 if (is_quasi_static == PETSC_FALSE) {
1444 CHKERR TSSetIJacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
1445 } else {
1446 CHKERR TSSetI2Jacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
1447 }
1448 if (is_quasi_static == PETSC_TRUE) {
1449 CHKERR TSSetSolution(solver, D);
1450 } else {
1451 CHKERR TS2SetSolution(solver, D, DD);
1452 }
1453 CHKERR set_section_monitor(solver);
1454 CHKERR set_time_monitor(dm, solver);
1455 CHKERR TSSetFromOptions(solver);
1456
1457 CHKERR add_active_dofs_elem(dm);
1458 boost::shared_ptr<SetUpSchur> schur_ptr;
1459 CHKERR set_schur_pc(solver, schur_ptr);
1460 CHKERR set_essential_bc(dm, solver);
1461
1462 MOFEM_LOG_CHANNEL("TIMER");
1463 MOFEM_LOG_TAG("TIMER", "timer");
1464 if (set_timer)
1465 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
1466 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
1467 CHKERR TSSetUp(solver);
1468 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
1469 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
1470 CHKERR TSSolve(solver, NULL);
1471 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
1472
1473 if (mField.get_comm_rank() == 0) {
1474 auto ts_ctx_ptr = getDMTsCtx(dm);
1476 "ts_manager_graph.dot");
1477 }
1478
1480}
1481//! [Solve]
1482
1483//! [TestOperators]
1486
1487 // get operators tester
1488 auto simple = mField.getInterface<Simple>();
1489 auto opt = mField.getInterface<OperatorsTester>(); // get interface to
1490 // OperatorsTester
1491 auto pip = mField.getInterface<PipelineManager>(); // get interface to
1492 // pipeline manager
1493
1494 constexpr double eps = 1e-9;
1495
1496 auto x = opt->setRandomFields(simple->getDM(), {
1497
1498 {"U", {-1e-4, 1e-4}},
1499
1500 {"EP", {-1e-4, 1e-4}},
1501
1502 {"TAU", {0, 1e-4}}
1503
1504 });
1505
1506 auto dot_x_plastic_active =
1507 opt->setRandomFields(simple->getDM(), {
1508
1509 {"U", {-1, 1}},
1510
1511 {"EP", {-1, 1}},
1512
1513 {"TAU", {0.1, 0.5}}
1514
1515 });
1516 auto diff_x_plastic_active =
1517 opt->setRandomFields(simple->getDM(), {
1518
1519 {"U", {-1, 1}},
1520
1521 {"EP", {-1, 1}},
1522
1523 {"TAU", {-1, 1}}
1524
1525 });
1526
1527 auto dot_x_elastic =
1528 opt->setRandomFields(simple->getDM(), {
1529
1530 {"U", {-1, 1}},
1531
1532 {"EP", {-1, 1}},
1533
1534 {"TAU", {-1, -0.1}}
1535
1536 });
1537 auto diff_x_elastic =
1538 opt->setRandomFields(simple->getDM(), {
1539
1540 {"U", {-1, 1}},
1541
1542 {"EP", {-1, 1}},
1543
1544 {"TAU", {-1, 1}}
1545
1546 });
1547
1548 auto test_domain_ops = [&](auto fe_name, auto lhs_pipeline, auto rhs_pipeline,
1549 auto dot_x, auto diff_x) {
1551
1552 auto diff_res = opt->checkCentralFiniteDifference(
1553 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1554 SmartPetscObj<Vec>(), diff_x, 0, 0.5, eps);
1555
1556 // Calculate norm of difference between directional derivative calculated
1557 // from finite difference, and tangent matrix.
1558 double fnorm;
1559 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1560 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1561 "Test consistency of tangent matrix %3.4e", fnorm);
1562
1563 constexpr double err = 1e-5;
1564 if (fnorm > err)
1565 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1566 "Norm of directional derivative too large err = %3.4e", fnorm);
1567
1569 };
1570
1571 MOFEM_LOG("PLASTICITY", Sev::inform) << "Elastic active";
1572 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1573 pip->getDomainRhsFE(), dot_x_elastic, diff_x_elastic);
1574
1575 MOFEM_LOG("PLASTICITY", Sev::inform) << "Plastic active";
1576 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1577 pip->getDomainRhsFE(), dot_x_plastic_active,
1578 diff_x_plastic_active);
1579
1581};
1582
1583//! [TestOperators]
1584
1585static char help[] = "...\n\n";
1586
1587int main(int argc, char *argv[]) {
1588
1589#ifdef ADD_CONTACT
1590 #ifdef ENABLE_PYTHON_BINDING
1591 Py_Initialize();
1592 np::initialize();
1593 #endif
1594#endif // ADD_CONTACT
1595
1596 // Initialisation of MoFEM/PETSc and MOAB data structures
1597 const char param_file[] = "param_file.petsc";
1598 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1599
1600 // Add logging channel for example
1601 auto core_log = logging::core::get();
1602 core_log->add_sink(
1604 core_log->add_sink(
1606 LogManager::setLog("PLASTICITY");
1607 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
1608
1609#ifdef ADD_CONTACT
1610 core_log->add_sink(
1612 LogManager::setLog("CONTACT");
1613 MOFEM_LOG_TAG("CONTACT", "Contact");
1614#endif // ADD_CONTACT
1615
1616 core_log->add_sink(
1618 LogManager::setLog("PlasticSync");
1619 MOFEM_LOG_TAG("PlasticSync", "PlasticSync");
1620
1621 try {
1622
1623 //! [Register MoFEM discrete manager in PETSc]
1624 DMType dm_name = "DMMOFEM";
1625 CHKERR DMRegister_MoFEM(dm_name);
1626 //! [Register MoFEM discrete manager in PETSc
1627
1628 //! [Create MoAB]
1629 moab::Core mb_instance; ///< mesh database
1630 moab::Interface &moab = mb_instance; ///< mesh database interface
1631 //! [Create MoAB]
1632
1633 //! [Create MoFEM]
1634 MoFEM::Core core(moab); ///< finite element database
1635 MoFEM::Interface &m_field = core; ///< finite element database interface
1636 //! [Create MoFEM]
1637
1638 //! [Load mesh]
1639 Simple *simple = m_field.getInterface<Simple>();
1641 CHKERR simple->loadFile();
1642 //! [Load mesh]
1643
1644 //! [Example]
1645 Example ex(m_field);
1646 CHKERR ex.runProblem();
1647 //! [Example]
1648 }
1650
1652
1653#ifdef ADD_CONTACT
1654 #ifdef ENABLE_PYTHON_BINDING
1655 if (Py_FinalizeEx() < 0) {
1656 exit(120);
1657 }
1658 #endif
1659#endif // ADD_CONTACT
1660
1661 return 0;
1662}
1663
1664struct SetUpSchurImpl : public SetUpSchur {
1665
1667 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
1668 : SetUpSchur(), mField(m_field), subDM(sub_dm),
1669 fieldSplitIS(field_split_is), aoSchur(ao_up) {
1670 if (S) {
1672 "Is expected that schur matrix is not "
1673 "allocated. This is "
1674 "possible only is if PC is set up twice");
1675 }
1676 }
1677 virtual ~SetUpSchurImpl() { S.reset(); }
1678
1679 MoFEMErrorCode setUp(TS solver);
1682
1683private:
1685
1687 SmartPetscObj<DM> subDM; ///< field split sub dm
1688 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
1689 SmartPetscObj<AO> aoSchur; ///> main DM to subDM
1690};
1691
1694 auto simple = mField.getInterface<Simple>();
1695 auto pip_mng = mField.getInterface<PipelineManager>();
1696
1697 SNES snes;
1698 CHKERR TSGetSNES(solver, &snes);
1699 KSP ksp;
1700 CHKERR SNESGetKSP(snes, &ksp);
1701 CHKERR KSPSetFromOptions(ksp);
1702
1703 PC pc;
1704 CHKERR KSPGetPC(ksp, &pc);
1705 PetscBool is_pcfs = PETSC_FALSE;
1706 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1707 if (is_pcfs) {
1708 if (S) {
1710 "Is expected that schur matrix is not "
1711 "allocated. This is "
1712 "possible only is if PC is set up twice");
1713 }
1714
1716 CHKERR MatSetBlockSize(S, SPACE_DIM);
1717
1718 // Set DM to use shell block matrix
1719 DM solver_dm;
1720 CHKERR TSGetDM(solver, &solver_dm);
1721 CHKERR DMSetMatType(solver_dm, MATSHELL);
1722
1723 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1724 auto A = createDMBlockMat(simple->getDM());
1725 auto P = createDMNestSchurMat(simple->getDM());
1726
1727 if (is_quasi_static == PETSC_TRUE) {
1728 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1729 Mat A, Mat B, void *ctx) {
1730 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1731 };
1732 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1733 } else {
1734 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1735 PetscReal a, PetscReal aa, Mat A, Mat B,
1736 void *ctx) {
1737 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1738 };
1739 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1740 }
1741 CHKERR KSPSetOperators(ksp, A, P);
1742
1743 auto set_ops = [&]() {
1745 auto pip_mng = mField.getInterface<PipelineManager>();
1746
1747#ifndef ADD_CONTACT
1748 // Boundary
1749 pip_mng->getOpBoundaryLhsPipeline().push_front(
1751 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1752
1753 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1754
1755 ));
1756 // Domain
1757 pip_mng->getOpDomainLhsPipeline().push_front(
1759 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1760
1761 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1762
1763 ));
1764#else
1765
1766 double eps_stab = 1e-4;
1767 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
1768 PETSC_NULLPTR);
1769
1772 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1773
1774 // Boundary
1775 pip_mng->getOpBoundaryLhsPipeline().push_front(
1777 pip_mng->getOpBoundaryLhsPipeline().push_back(
1778 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
1779 return eps_stab;
1780 }));
1781 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1782
1783 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1784 false, false
1785
1786 ));
1787 // Domain
1788 pip_mng->getOpDomainLhsPipeline().push_front(
1790 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1791
1792 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1793 false, false
1794
1795 ));
1796#endif // ADD_CONTACT
1798 };
1799
1800 auto set_assemble_elems = [&]() {
1802 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1803 schur_asmb_pre_proc->preProcessHook = [this]() {
1805 CHKERR MatZeroEntries(S);
1806 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
1808 };
1809 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1810 auto weak_schur_asmb_post_proc = boost::weak_ptr<FEMethod>(
1811 schur_asmb_post_proc); // fe method passed to lambda, have to be weak ptr to avoid circular shared ptr reference
1812
1813 schur_asmb_post_proc->postProcessHook = [this,
1814 weak_schur_asmb_post_proc]() {
1816 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
1817
1818 // Apply essential constrains to Schur complement
1819 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1820 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1822 mField, weak_schur_asmb_post_proc.lock(), 1, S, aoSchur)();
1823
1825 };
1826 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1827 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1828 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1830 };
1831
1832 auto set_pc = [&]() {
1834 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
1835 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1837 };
1838
1839 auto set_diagonal_pc = [&]() {
1841 KSP *subksp;
1842 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
1843 auto get_pc = [](auto ksp) {
1844 PC pc_raw;
1845 CHKERR KSPGetPC(ksp, &pc_raw);
1846 return SmartPetscObj<PC>(pc_raw,
1847 true); // bump reference
1848 };
1849 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1850 CHKERR PetscFree(subksp);
1852 };
1853
1854 CHKERR set_ops();
1855 CHKERR set_pc();
1856 CHKERR set_assemble_elems();
1857
1858 CHKERR TSSetUp(solver);
1859 CHKERR KSPSetUp(ksp);
1860 CHKERR set_diagonal_pc();
1861
1862 } else {
1863 pip_mng->getOpBoundaryLhsPipeline().push_front(
1865 pip_mng->getOpBoundaryLhsPipeline().push_back(
1866 createOpSchurAssembleEnd({}, {}));
1867 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1868 pip_mng->getOpDomainLhsPipeline().push_back(
1869 createOpSchurAssembleEnd({}, {}));
1870 }
1871
1872 // fieldSplitIS.reset();
1873 // aoSchur.reset();
1875}
1876
1877boost::shared_ptr<SetUpSchur>
1879 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
1880 SmartPetscObj<AO> ao_up) {
1881 return boost::shared_ptr<SetUpSchur>(
1882 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
1883}
1884
1885namespace PlasticOps {
1886
1888 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1889 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1891 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
1893}
1894
1896 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1897 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1899 CHKERR MoFEM::AddHOOps<1, 2, 2>::add(pipeline, spaces, geom_field_name);
1901}
1902
1903template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM>
1905scaleL2(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1906 std::string geom_field_name) {
1908
1909 auto jac_ptr = boost::make_shared<MatrixDouble>();
1910 auto det_ptr = boost::make_shared<VectorDouble>();
1912 geom_field_name, jac_ptr));
1913 pipeline.push_back(new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, nullptr));
1914
1915 auto scale_ptr = boost::make_shared<double>(1.);
1917 Example::meshVolumeAndCount[1]; // average volume of elements
1919 auto op_scale = new OP(NOSPACE, OP::OPSPACE);
1920 op_scale->doWorkRhsHook = [scale_ptr, det_ptr,
1921 scale](DataOperator *base_op_ptr, int, EntityType,
1923 *scale_ptr = scale / det_ptr->size(); // distribute average element size
1924 // over integration points
1925 return 0;
1926 };
1927 pipeline.push_back(op_scale);
1928
1931 pipeline.push_back(
1932 new OpScaleBaseBySpaceInverseOfMeasure(L2, base, det_ptr, scale_ptr));
1933 }
1934
1936}
1937
1939 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1940 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1942 constexpr bool scale_l2 = false;
1943 if (scale_l2) {
1944 CHKERR scaleL2<3, 3, 3>(pipeline, geom_field_name);
1945 }
1946 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
1947 nullptr, nullptr, nullptr);
1949}
1950
1952 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1953 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1955 constexpr bool scale_l2 = false;
1956 if (scale_l2) {
1957 CHKERR scaleL2<2, 2, 2>(pipeline, geom_field_name);
1958 }
1959 CHKERR MoFEM::AddHOOps<2, 2, 2>::add(pipeline, spaces, geom_field_name,
1960 nullptr, nullptr, nullptr);
1962}
1963
1964} // namespace PlasticOps
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
std::string type
#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
int main()
constexpr double a
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Kronecker Delta class symmetric.
@ ROW
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ AINSWORTH_LOBATTO_BASE
Definition definitions.h:62
@ NOBASE
Definition definitions.h:59
@ 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
@ NOSPACE
Definition definitions.h:83
@ 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 ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
static const char *const ApproximationBaseNames[]
Definition definitions.h:72
#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
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 1, SPACE_DIM, SPACE_DIM > OpInertiaForce
constexpr auto t_kd
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 DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
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:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1194
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
@ BLOCK_PRECONDITIONER_SCHUR
Block preconditioner Schur 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.
FTensor::Index< 'i', SPACE_DIM > i
double D
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
double cn_contact
Definition contact.cpp:97
const FTensor::Tensor2< T, Dim, Dim > Vec
[HenckyOps]
Definition HenckyOps.hpp:12
static const double eps
Definition HenckyOps.hpp:14
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
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:1046
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobian in TS solver.
Definition TsCtx.cpp:169
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1279
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:2663
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:600
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:2705
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)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1295
PetscErrorCode TsSetI2Jacobian(TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, PetscReal a, PetscReal aa, Mat A, Mat B, void *ctx)
Calculation Jacobian for second order PDE in time.
Definition TsCtx.cpp:519
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:2421
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1555
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1265
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1221
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:2658
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1214
MoFEMErrorCode scaleL2(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string geom_field_name)
Definition plastic.cpp:1905
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
Definition plate.cpp:58
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
FTensor::Index< 'm', 3 > m
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
Definition plastic.cpp:29
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
Definition plastic.cpp:36
[Operators_definition]
double getScale(const double time)
Get scaling at given time.
Definition plastic.cpp:241
[Example]
Definition plastic.cpp:216
static std::array< double, 2 > meshVolumeAndCount
Definition plastic.cpp:223
MoFEMErrorCode testOperators()
[Solve]
Definition plastic.cpp:1484
MoFEMErrorCode tsSolve()
Definition plastic.cpp:832
FieldApproximationBase base
Choice of finite element basis functions.
Definition plot_base.cpp:68
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition plastic.cpp:236
Simple * simple
MoFEMErrorCode createCommonData()
[Set up problem]
Definition plastic.cpp:478
SmartPetscObj< Mat > H
Example(MoFEM::Interface &m_field)
Definition plastic.cpp:218
MoFEMErrorCode OPs()
[Boundary condition]
Definition plastic.cpp:648
MoFEMErrorCode runProblem()
[Run problem]
Definition plastic.cpp:254
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:226
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition plastic.cpp:237
MoFEMErrorCode setupProblem()
[Run problem]
Definition plastic.cpp:273
MoFEMErrorCode bC()
[Create common data]
Definition plastic.cpp:604
SmartPetscObj< EPS > eps
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition plastic.cpp:235
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
base operator to do operations at Gauss Pt. level
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.
SetIntegrationPtsMethodData SetPtsData
double getMeasure() const
get measure of element
@ OPSPACE
operator do Work is execute on space data
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
Operator for inverting matrices at integration points.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
Scale base functions by inverses of measure of element.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEM::VolumeElementForcesAndSourcesCore VolEle
boost::shared_ptr< FEMethod > & getDomainLhsFE()
Get domain left-hand side finite element.
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEM::EdgeElementForcesAndSourcesCore EdgeEle
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode addBoundaryField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on boundary.
Definition Simple.cpp:355
MoFEMErrorCode addFieldToEmptyFieldBlocks(const std::string row_field, const std::string col_field) const
Add empty block to problem.
Definition Simple.cpp:834
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
MoFEMErrorCode addDataField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add data field.
Definition Simple.cpp:393
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
Definition Simple.cpp:735
const std::string getProblemName() const
Get the Problem Name.
Definition Simple.hpp:450
const std::string getDomainFEName() const
Get the Domain FE Name.
Definition Simple.hpp:429
intrusive_ptr for managing petsc objects
Force scale operator for reading two columns.
double getScale(const double time)
Get scaling at a given time.
TimeScale(std::string file_name="", bool error_if_file_not_given=false, ScalingFun def_scaling_fun=[](double time) { return time;})
TimeScale constructor.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
static std::array< int, 5 > activityData
SmartPetscObj< DM > subDM
field split sub dm
Definition plastic.cpp:1687
SmartPetscObj< Mat > S
SmartPetscObj< AO > aoSchur
Definition plastic.cpp:1689
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition plastic.cpp:1688
SetUpSchurImpl(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
Definition plastic.cpp:1666
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
virtual ~SetUpSchurImpl()
Definition plastic.cpp:1677
MoFEMErrorCode postProc()
MoFEMErrorCode preProc()
MoFEM::Interface & mField
[Push operators to pipeline]
SetUpSchur()=default
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
virtual MoFEMErrorCode setUp(TS solver)=0
constexpr AssemblyType AT
VolEle::UserDataOperator VolOp
PetscBool order_face
PetscBool order_edge
PetscBool order_volume
double young_modulus
Young modulus.
Definition plastic.cpp:125
constexpr AssemblyType AT
Definition plastic.cpp:44
double C1_k
Kinematic hardening.
Definition plastic.cpp:133
double Qinf
Saturation yield stress.
Definition plastic.cpp:131
constexpr IntegrationType IT
Definition plastic.cpp:47
static char help[]
[TestOperators]
Definition plastic.cpp:1585
double rho
Definition plastic.cpp:144
int atom_test
Atom test.
Definition plastic.cpp:121
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
PetscBool is_quasi_static
Definition plastic.cpp:143
double alpha_damping
Definition plastic.cpp:145
constexpr int SPACE_DIM
Definition plastic.cpp:40
double visH
Viscous hardening.
Definition plastic.cpp:129
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:126
auto kinematic_hardening(FTensor::Tensor2_symmetric< T, DIM > &t_plastic_strain, double C1_k)
Definition plastic.cpp:92
PetscBool set_timer
Set timer.
Definition plastic.cpp:118
double iso_hardening_dtau(double tau, double H, double Qinf, double b_iso)
Definition plastic.cpp:78
double scale
Definition plastic.cpp:123
constexpr auto size_symm
Definition plastic.cpp:42
double zeta
Viscous hardening.
Definition plastic.cpp:130
double H
Hardening.
Definition plastic.cpp:128
int tau_order
Order of tau files.
Definition plastic.cpp:139
double iso_hardening_exp(double tau, double b_iso)
Definition plastic.cpp:64
double cn0
Definition plastic.cpp:135
int order
Order displacement.
Definition plastic.cpp:138
double b_iso
Saturation exponent.
Definition plastic.cpp:132
PetscBool is_large_strains
Large strains.
Definition plastic.cpp:117
int geom_order
Order if fixed.
Definition plastic.cpp:141
double sigmaY
Yield stress.
Definition plastic.cpp:127
double iso_hardening(double tau, double H, double Qinf, double b_iso, double sigmaY)
Definition plastic.cpp:73
auto kinematic_hardening_dplastic_strain(double C1_k)
Definition plastic.cpp:106
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
int ep_order
Order of ep files.
Definition plastic.cpp:140
double cn1
Definition plastic.cpp:136
constexpr FieldSpace CONTACT_SPACE
Definition plastic.cpp:52
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
constexpr int SPACE_DIM
[Define dimension]
Definition elastic.cpp:18
constexpr AssemblyType A
[Define dimension]
Definition elastic.cpp:21
constexpr int SPACE_DIM