v0.16.0
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
52[[maybe_unused]] constexpr FieldSpace CONTACT_SPACE =
54
57using DomainEleOp = DomainEle::UserDataOperator;
59using BoundaryEleOp = BoundaryEle::UserDataOperator;
64
65inline double iso_hardening_exp(double tau, double b_iso) {
66 return std::exp(
67 std::max(static_cast<double>(std::numeric_limits<float>::min_exponent10),
68 -b_iso * tau));
69}
70
71/**
72 * Isotropic hardening
73 */
74inline double iso_hardening(double tau, double H, double Qinf, double b_iso,
75 double sigmaY) {
76 return H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso)) + sigmaY;
77}
78
79inline double iso_hardening_dtau(double tau, double H, double Qinf,
80 double b_iso) {
81 auto r = [&](auto tau) {
82 return H + Qinf * b_iso * iso_hardening_exp(tau, b_iso);
83 };
84 constexpr double eps = 1e-12;
85 return std::max(r(tau), eps * r(0));
86}
87
88/**
89 * Kinematic hardening
90 */
91template <typename T, int DIM>
92inline auto
94 double C1_k) {
95 FTensor::Index<'i', DIM> i;
96 FTensor::Index<'j', DIM> j;
98 if (C1_k < std::numeric_limits<double>::epsilon()) {
99 t_alpha(i, j) = 0;
100 return t_alpha;
101 }
102 t_alpha(i, j) = C1_k * t_plastic_strain(i, j);
103 return t_alpha;
104}
105
106template <int DIM>
108 FTensor::Index<'i', DIM> i;
109 FTensor::Index<'j', DIM> j;
110 FTensor::Index<'k', DIM> k;
111 FTensor::Index<'l', DIM> l;
114 t_diff(i, j, k, l) = C1_k * (t_kd(i, k) ^ t_kd(j, l)) / 4.;
115 return t_diff;
116}
117
118PetscBool is_large_strains = PETSC_TRUE; ///< Large strains
119PetscBool set_timer = PETSC_FALSE; ///< Set timer
120PetscBool do_eval_field = PETSC_FALSE; ///< Evaluate field
121
122int atom_test = 0; ///< Atom test
123
124double scale = 1.;
125
126double young_modulus = 206913; ///< Young modulus
127double poisson_ratio = 0.29; ///< Poisson ratio
128double sigmaY = 450; ///< Yield stress
129double H = 129; ///< Hardening
130double visH = 0; ///< Viscous hardening
131double zeta = 5e-2; ///< Viscous hardening
132double Qinf = 265; ///< Saturation yield stress
133double b_iso = 16.93; ///< Saturation exponent
134double C1_k = 0; ///< Kinematic hardening
135
136double cn0 = 1;
137double cn1 = 1;
138
139int order = 2; ///< Order displacement
140int tau_order = order - 2; ///< Order of tau files
141int ep_order = order - 1; ///< Order of ep files
142int geom_order = 2; ///< Order if fixed.
143
144PetscBool is_quasi_static = PETSC_TRUE;
145double rho = 0.0;
146double alpha_damping = 0;
147
148#include <HenckyOps.hpp>
149#include <PlasticOps.hpp>
150#include <PlasticNaturalBCs.hpp>
151
152#ifdef ADD_CONTACT
153 #ifdef ENABLE_PYTHON_BINDING
154 #include <boost/python.hpp>
155 #include <boost/python/def.hpp>
156 #include <boost/python/numpy.hpp>
157namespace bp = boost::python;
158namespace np = boost::python::numpy;
159 #endif
160
161namespace ContactOps {
162
163double cn_contact = 0.1;
164
165}; // namespace ContactOps
166
167 #include <ContactOps.hpp>
168#endif // ADD_CONTACT
169
179
180using namespace PlasticOps;
181using namespace HenckyOps;
182
183namespace PlasticOps {
184
185template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM> struct AddHOOps;
186
187template <> struct AddHOOps<2, 3, 3> {
188 AddHOOps() = delete;
189 static MoFEMErrorCode
190 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
191 std::vector<FieldSpace> space, std::string geom_field_name);
192};
193
194template <> struct AddHOOps<1, 2, 2> {
195 AddHOOps() = delete;
196 static MoFEMErrorCode
197 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
198 std::vector<FieldSpace> space, std::string geom_field_name);
199};
200
201template <> struct AddHOOps<3, 3, 3> {
202 AddHOOps() = delete;
203 static MoFEMErrorCode
204 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
205 std::vector<FieldSpace> space, std::string geom_field_name);
206};
207
208template <> struct AddHOOps<2, 2, 2> {
209 AddHOOps() = delete;
210 static MoFEMErrorCode
211 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
212 std::vector<FieldSpace> space, std::string geom_field_name);
213};
214
215} // namespace PlasticOps
216
217struct Example {
218
219 Example(MoFEM::Interface &m_field) : mField(m_field) {}
220
222
223 enum { VOL, COUNT };
224 static inline std::array<double, 2> meshVolumeAndCount = {0, 0};
225
226private:
228
235
236 boost::shared_ptr<DomainEle> reactionFe;
237
238 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
239 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
240 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
241
244 double getScale(const double time) {
245 return scale * MoFEM::TimeScale::getScale(time);
246 };
247 };
248
249#ifdef ADD_CONTACT
250 #ifdef ENABLE_PYTHON_BINDING
251 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
252 #endif
253#endif // ADD_CONTACT
254};
255
256//! [Run problem]
261 CHKERR bC();
262 CHKERR OPs();
263 PetscBool test_ops = PETSC_FALSE;
264 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_operators", &test_ops,
265 PETSC_NULLPTR);
266 if (test_ops == PETSC_FALSE) {
267 CHKERR tsSolve();
268 } else {
270 }
272}
273//! [Run problem]
274
275//! [Set up problem]
279
280 Range domain_ents;
281 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
282 true);
283 auto get_ents_by_dim = [&](const auto dim) {
284 if (dim == SPACE_DIM) {
285 return domain_ents;
286 } else {
287 Range ents;
288 if (dim == 0)
289 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
290 else
291 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
292 return ents;
293 }
294 };
295
296 auto get_base = [&]() {
297 auto domain_ents = get_ents_by_dim(SPACE_DIM);
298 if (domain_ents.empty())
299 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
300 const auto type = type_from_handle(domain_ents[0]);
301 switch (type) {
302 case MBQUAD:
304 case MBHEX:
306 case MBTRI:
308 case MBTET:
310 default:
311 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
312 }
313 return NOBASE;
314 };
315
316 const auto base = get_base();
317 MOFEM_LOG("PLASTICITY", Sev::inform)
318 << "Base " << ApproximationBaseNames[base];
319
320 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
321 CHKERR simple->addDomainField("EP", L2, base, size_symm);
322 CHKERR simple->addDomainField("TAU", L2, base, 1);
323 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
324
325 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
326
327 PetscBool order_edge = PETSC_FALSE;
328 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_edge", &order_edge,
329 PETSC_NULLPTR);
330 PetscBool order_face = PETSC_FALSE;
331 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_face", &order_face,
332 PETSC_NULLPTR);
333 PetscBool order_volume = PETSC_FALSE;
334 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-order_volume", &order_volume,
335 PETSC_NULLPTR);
336
338
339 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order edge " << order_edge
340 ? "true"
341 : "false";
342 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order face " << order_face
343 ? "true"
344 : "false";
345 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order volume " << order_volume
346 ? "true"
347 : "false";
348
349 auto ents = get_ents_by_dim(0);
350 if (order_edge)
351 ents.merge(get_ents_by_dim(1));
352 if (order_face)
353 ents.merge(get_ents_by_dim(2));
354 if (order_volume)
355 ents.merge(get_ents_by_dim(3));
356 CHKERR simple->setFieldOrder("U", order, &ents);
357 } else {
358 CHKERR simple->setFieldOrder("U", order);
359 }
360 CHKERR simple->setFieldOrder("EP", ep_order);
361 CHKERR simple->setFieldOrder("TAU", tau_order);
362
363 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
364
365#ifdef ADD_CONTACT
366 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
367 SPACE_DIM);
368 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
369 SPACE_DIM);
370
371 auto get_skin = [&]() {
372 Range body_ents;
373 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
374 Skinner skin(&mField.get_moab());
375 Range skin_ents;
376 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
377 return skin_ents;
378 };
379
380 auto filter_blocks = [&](auto skin) {
381 bool is_contact_block = true;
382 Range contact_range;
383 for (auto m :
384 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
385
386 (boost::format("%s(.*)") % "CONTACT").str()
387
388 ))
389
390 ) {
391 is_contact_block =
392 true; ///< blocs interation is collective, so that is set irrespective
393 ///< if there are entities in given rank or not in the block
394 MOFEM_LOG("CONTACT", Sev::inform)
395 << "Find contact block set: " << m->getName();
396 auto meshset = m->getMeshset();
397 Range contact_meshset_range;
398 CHKERR mField.get_moab().get_entities_by_dimension(
399 meshset, SPACE_DIM - 1, contact_meshset_range, true);
400
401 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
402 contact_meshset_range);
403 contact_range.merge(contact_meshset_range);
404 }
405 if (is_contact_block) {
406 MOFEM_LOG("SYNC", Sev::inform)
407 << "Nb entities in contact surface: " << contact_range.size();
409 skin = intersect(skin, contact_range);
410 }
411 return skin;
412 };
413
414 auto filter_true_skin = [&](auto skin) {
415 Range boundary_ents;
416 ParallelComm *pcomm =
417 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
418 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
419 PSTATUS_NOT, -1, &boundary_ents);
420 return boundary_ents;
421 };
422
423 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
424 CHKERR simple->setFieldOrder("SIGMA", 0);
425 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
426#endif
427
428 CHKERR simple->setUp();
429 CHKERR simple->addFieldToEmptyFieldBlocks("U", "TAU");
430
431 auto project_ho_geometry = [&]() {
432 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
433 return mField.loop_dofs("GEOMETRY", ent_method);
434 };
435 PetscBool project_geometry = PETSC_TRUE;
436 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
437 &project_geometry, PETSC_NULLPTR);
438 if (project_geometry) {
439 CHKERR project_ho_geometry();
440 }
441
442 auto get_volume = [&]() {
443 using VolOp = DomainEle::UserDataOperator;
444 auto *op_ptr = new VolOp(NOSPACE, VolOp::OPSPACE);
445 std::array<double, 2> volume_and_count;
446 op_ptr->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side,
447 EntityType type,
450 auto op_ptr = static_cast<VolOp *>(base_op_ptr);
451 volume_and_count[VOL] += op_ptr->getMeasure();
452 volume_and_count[COUNT] += 1;
453 // in necessary at integration over Gauss points.
455 };
456 volume_and_count = {0, 0};
457 auto fe = boost::make_shared<DomainEle>(mField);
458 fe->getOpPtrVector().push_back(op_ptr);
459
460 auto dm = simple->getDM();
462 DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(), fe),
463 "cac volume");
464 std::array<double, 2> tot_volume_and_count;
465 MPI_Allreduce(volume_and_count.data(), tot_volume_and_count.data(),
466 volume_and_count.size(), MPI_DOUBLE, MPI_SUM,
467 mField.get_comm());
468 return tot_volume_and_count;
469 };
470
471 meshVolumeAndCount = get_volume();
472 MOFEM_LOG("PLASTICITY", Sev::inform)
473 << "Mesh volume " << meshVolumeAndCount[VOL] << " nb. of elements "
475
477}
478//! [Set up problem]
479
480//! [Create common data]
483
484 auto get_command_line_parameters = [&]() {
486
487 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale, PETSC_NULLPTR);
488 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
489 &young_modulus, PETSC_NULLPTR);
490 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
491 &poisson_ratio, PETSC_NULLPTR);
492 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening", &H, PETSC_NULLPTR);
493 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening_viscous", &visH,
494 PETSC_NULLPTR);
495 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-yield_stress", &sigmaY,
496 PETSC_NULLPTR);
497 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn0", &cn0, PETSC_NULLPTR);
498 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn1", &cn1, PETSC_NULLPTR);
499 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-zeta", &zeta, PETSC_NULLPTR);
500 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-Qinf", &Qinf, PETSC_NULLPTR);
501 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-b_iso", &b_iso, PETSC_NULLPTR);
502 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-C1_k", &C1_k, PETSC_NULLPTR);
503 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strains",
504 &is_large_strains, PETSC_NULLPTR);
505 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-set_timer", &set_timer,
506 PETSC_NULLPTR);
507 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
508 PETSC_NULLPTR);
509
510 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order, PETSC_NULLPTR);
511 PetscBool tau_order_is_set; ///< true if tau order is set
512 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-tau_order", &tau_order,
513 &tau_order_is_set);
514 PetscBool ep_order_is_set; ///< true if tau order is set
515 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-ep_order", &ep_order,
516 &ep_order_is_set);
517 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
518 PETSC_NULLPTR);
519
520 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho, PETSC_NULLPTR);
521 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
522 &alpha_damping, PETSC_NULLPTR);
523
524 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
525 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
526 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
527 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
528 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
529 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
530 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
531 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
532 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
533 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
534 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
535
536 if (tau_order_is_set == PETSC_FALSE)
537 tau_order = order - 2;
538 if (ep_order_is_set == PETSC_FALSE)
539 ep_order = order - 1;
540
541 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
542 MOFEM_LOG("PLASTICITY", Sev::inform)
543 << "Ep approximation order " << ep_order;
544 MOFEM_LOG("PLASTICITY", Sev::inform)
545 << "Tau approximation order " << tau_order;
546 MOFEM_LOG("PLASTICITY", Sev::inform)
547 << "Geometry approximation order " << geom_order;
548
549 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
550 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
551
552 PetscBool is_scale = PETSC_TRUE;
553 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_scale", &is_scale,
554 PETSC_NULLPTR);
555 if (is_scale) {
557 }
558
559 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
560
561#ifdef ADD_CONTACT
562 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn_contact",
563 &ContactOps::cn_contact, PETSC_NULLPTR);
564 MOFEM_LOG("CONTACT", Sev::inform)
565 << "cn_contact " << ContactOps::cn_contact;
566#endif // ADD_CONTACT
567
568 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-quasi_static",
569 &is_quasi_static, PETSC_NULLPTR);
570 MOFEM_LOG("PLASTICITY", Sev::inform)
571 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
572
574 };
575
576 CHKERR get_command_line_parameters();
577
578#ifdef ADD_CONTACT
579 #ifdef ENABLE_PYTHON_BINDING
580 auto file_exists = [](std::string myfile) {
581 std::ifstream file(myfile.c_str());
582 if (file) {
583 return true;
584 }
585 return false;
586 };
587 char sdf_file_name[255] = "sdf.py";
588 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-sdf_file",
589 sdf_file_name, 255, PETSC_NULLPTR);
590
591 if (file_exists(sdf_file_name)) {
592 MOFEM_LOG("CONTACT", Sev::inform) << sdf_file_name << " file found";
593 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
594 CHKERR sdfPythonPtr->sdfInit(sdf_file_name);
595 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
596 } else {
597 MOFEM_LOG("CONTACT", Sev::warning) << sdf_file_name << " file NOT found";
598 }
599 #endif
600#endif // ADD_CONTACT
601
603}
604//! [Create common data]
605
606//! [Boundary condition]
609
611 auto bc_mng = mField.getInterface<BcManager>();
612
613 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
614 "U", 0, 0);
615 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
616 "U", 1, 1);
617 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
618 "U", 2, 2);
619 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
620 "REMOVE_ALL", "U", 0, 3);
621
622#ifdef ADD_CONTACT
623 for (auto b : {"FIX_X", "REMOVE_X"})
624 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
625 "SIGMA", 0, 0, false, true);
626 for (auto b : {"FIX_Y", "REMOVE_Y"})
627 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
628 "SIGMA", 1, 1, false, true);
629 for (auto b : {"FIX_Z", "REMOVE_Z"})
630 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
631 "SIGMA", 2, 2, false, true);
632 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
633 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
634 "SIGMA", 0, 3, false, true);
635 CHKERR bc_mng->removeBlockDOFsOnEntities(
636 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
637#endif
638
639 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
640 simple->getProblemName(), "U");
641
642 auto &bc_map = bc_mng->getBcMapByBlockName();
643 for (auto bc : bc_map)
644 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
645
647}
648//! [Boundary condition]
649
650//! [Push operators to pipeline]
653 auto pip_mng = mField.getInterface<PipelineManager>();
654
655 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
656
657 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order - 1; };
658
659 auto add_boundary_ops_lhs_mechanical = [&](auto &pip) {
661
663 pip, {HDIV}, "GEOMETRY");
664 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
665
666 // Add Natural BCs to LHS
668 pip, mField, "U", Sev::inform);
669
670#ifdef ADD_CONTACT
672 CHKERR
673 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
674 pip, "SIGMA", "U");
675 CHKERR
676 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
677 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
678 vol_rule);
679#endif // ADD_CONTACT
680
682 };
683
684 auto add_boundary_ops_rhs_mechanical = [&](auto &pip) {
686
688 pip, {HDIV}, "GEOMETRY");
689 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
690
691 // Add Natural BCs to RHS
693 pip, mField, "U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
694
695#ifdef ADD_CONTACT
696 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
697 pip, "SIGMA", "U");
698#endif // ADD_CONTACT
699
701 };
702
703 auto add_domain_ops_lhs = [this](auto &pip) {
706 pip, {H1, HDIV}, "GEOMETRY");
707
708 if (is_quasi_static == PETSC_FALSE) {
709
710 //! [Only used for dynamics]
713 //! [Only used for dynamics]
714
715 auto get_inertia_and_mass_damping = [this](const double, const double,
716 const double) {
717 auto *pip = mField.getInterface<PipelineManager>();
718 auto &fe_domain_lhs = pip->getDomainLhsFE();
719 return (rho / scale) * fe_domain_lhs->ts_aa +
720 (alpha_damping / scale) * fe_domain_lhs->ts_a;
721 };
722 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
723 }
724
725 CHKERR PlasticOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
726 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
727
729 };
730
731 auto add_domain_ops_rhs = [this](auto &pip) {
733
735 pip, {H1, HDIV}, "GEOMETRY");
736
738 pip, mField, "U",
739 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
740 Sev::inform);
741
742 // only in case of dynamics
743 if (is_quasi_static == PETSC_FALSE) {
744
745 //! [Only used for dynamics]
748 //! [Only used for dynamics]
749
750 auto mat_acceleration = boost::make_shared<MatrixDouble>();
752 "U", mat_acceleration));
753 pip.push_back(
754 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
755 return rho / scale;
756 }));
757 if (alpha_damping > 0) {
758 auto mat_velocity = boost::make_shared<MatrixDouble>();
759 pip.push_back(
760 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
761 pip.push_back(
762 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
763 return alpha_damping / scale;
764 }));
765 }
766 }
767
768 CHKERR PlasticOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
769 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
770
771#ifdef ADD_CONTACT
772 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
773 pip, "SIGMA", "U");
774#endif // ADD_CONTACT
775
777 };
778
779 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
780 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
781
782 // Boundary
783 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
784 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
785
786 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
787 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
788
789 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
790 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
791
792 auto create_reaction_pipeline = [&](auto &pip) {
795 pip, {H1}, "GEOMETRY");
796 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
797 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
799 };
800
801 reactionFe = boost::make_shared<DomainEle>(mField);
802 reactionFe->getRuleHook = vol_rule;
803 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
804 reactionFe->postProcessHook =
806
808}
809//! [Push operators to pipeline]
810
811//! [Solve]
812struct SetUpSchur {
813
814 /**
815 * @brief Create data structure for handling Schur complement
816 *
817 * @param m_field
818 * @param sub_dm Schur complement sub dm
819 * @param field_split_it IS of Schur block
820 * @param ao_map AO map from sub dm to main problem
821 * @return boost::shared_ptr<SetUpSchur>
822 */
823 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
824
825 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
826 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
827
828 );
829 virtual MoFEMErrorCode setUp(TS solver) = 0;
830
831protected:
832 SetUpSchur() = default;
833};
834
837
840 ISManager *is_manager = mField.getInterface<ISManager>();
841
842 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
843
844 auto set_section_monitor = [&](auto solver) {
846 SNES snes;
847 CHKERR TSGetSNES(solver, &snes);
848 CHKERR SNESMonitorSet(snes,
849 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
851 (void *)(snes_ctx_ptr.get()), nullptr);
853 };
854
855 auto create_post_process_elements = [&]() {
856 auto push_vol_ops = [this](auto &pip) {
858 pip, {H1, HDIV}, "GEOMETRY");
859
860 auto [common_plastic_ptr, common_hencky_ptr] =
861 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
862 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU", 1., Sev::inform);
863
864 if (common_hencky_ptr) {
865 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
866 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
867 }
868
869 return std::make_pair(common_plastic_ptr, common_hencky_ptr);
870 };
871
872 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
874
875 auto &pip = pp_fe->getOpPtrVector();
876
877 auto [common_plastic_ptr, common_hencky_ptr] = p;
878
880
881 auto x_ptr = boost::make_shared<MatrixDouble>();
882 pip.push_back(
883 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
884 auto u_ptr = boost::make_shared<MatrixDouble>();
885 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
886
887 if (is_large_strains) {
888
889 pip.push_back(
890
891 new OpPPMap(
892
893 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
894
895 {{"PLASTIC_SURFACE",
896 common_plastic_ptr->getPlasticSurfacePtr()},
897 {"PLASTIC_MULTIPLIER",
898 common_plastic_ptr->getPlasticTauPtr()}},
899
900 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
901
902 {{"GRAD", common_hencky_ptr->matGradPtr},
903 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
904
905 {{"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
906 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
907 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
908
909 )
910
911 );
912
913 } else {
914
915 pip.push_back(
916
917 new OpPPMap(
918
919 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
920
921 {{"PLASTIC_SURFACE",
922 common_plastic_ptr->getPlasticSurfacePtr()},
923 {"PLASTIC_MULTIPLIER",
924 common_plastic_ptr->getPlasticTauPtr()}},
925
926 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
927
928 {},
929
930 {{"STRAIN", common_plastic_ptr->mStrainPtr},
931 {"STRESS", common_plastic_ptr->mStressPtr},
932 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
933 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
934
935 )
936
937 );
938 }
939
941 };
942
943 PetscBool post_proc_vol;
944 PetscBool post_proc_skin;
945
946 if constexpr (SPACE_DIM == 2) {
947 post_proc_vol = PETSC_TRUE;
948 post_proc_skin = PETSC_FALSE;
949 } else {
950 post_proc_vol = PETSC_FALSE;
951 post_proc_skin = PETSC_TRUE;
952 }
953 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol", &post_proc_vol,
954 PETSC_NULLPTR);
955 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
956 &post_proc_skin, PETSC_NULLPTR);
957
958 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
959 post_proc_vol]() {
960 if (post_proc_vol == PETSC_FALSE)
961 return boost::shared_ptr<PostProcEle>();
962 auto pp_fe = boost::make_shared<PostProcEle>(mField);
964 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
965 "push_vol_post_proc_ops");
966 return pp_fe;
967 };
968
969 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
970 post_proc_skin]() {
971 if (post_proc_skin == PETSC_FALSE)
972 return boost::shared_ptr<SkinPostProcEle>();
973
974 auto simple = mField.getInterface<Simple>();
975 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
976 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
977 SPACE_DIM, Sev::verbose);
978 pp_fe->getOpPtrVector().push_back(op_side);
979 CHK_MOAB_THROW(push_vol_post_proc_ops(
980 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
981 "push_vol_post_proc_ops");
982 return pp_fe;
983 };
984
985 return std::make_pair(vol_post_proc(), skin_post_proc());
986 };
987
988 auto scatter_create = [&](auto D, auto coeff) {
990 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
991 ROW, "U", coeff, coeff, is);
992 int loc_size;
993 CHKERR ISGetLocalSize(is, &loc_size);
994 Vec v;
995 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
996 VecScatter scatter;
997 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
998 return std::make_tuple(SmartPetscObj<Vec>(v),
1000 };
1001
1002 boost::shared_ptr<SetPtsData> field_eval_data;
1003 boost::shared_ptr<MatrixDouble> u_field_ptr;
1004
1005 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1006 int coords_dim = 3;
1007 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
1008 field_eval_coords.data(), &coords_dim,
1009 &do_eval_field);
1010
1011 boost::shared_ptr<std::map<std::string, boost::shared_ptr<VectorDouble>>>
1012 scalar_field_ptrs = boost::make_shared<
1013 std::map<std::string, boost::shared_ptr<VectorDouble>>>();
1014 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1015 vector_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 sym_tensor_field_ptrs = boost::make_shared<
1019 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1020 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
1021 tensor_field_ptrs = boost::make_shared<
1022 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
1023
1024 if (do_eval_field) {
1025 auto u_field_ptr = boost::make_shared<MatrixDouble>();
1026 field_eval_data =
1027 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
1028
1029 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
1030 field_eval_data, simple->getDomainFEName());
1031
1032 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1033 auto no_rule = [](int, int, int) { return -1; };
1034 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1035 field_eval_fe_ptr->getRuleHook = no_rule;
1036
1038 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV}, "GEOMETRY");
1039
1040 auto [common_plastic_ptr, common_hencky_ptr] =
1041 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1042 mField, "MAT_PLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U",
1043 "EP", "TAU", 1., Sev::inform);
1044
1045 field_eval_fe_ptr->getOpPtrVector().push_back(
1046 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_field_ptr));
1047
1048 if ((common_plastic_ptr) && (common_hencky_ptr) && (scalar_field_ptrs)) {
1049 if (is_large_strains) {
1050 scalar_field_ptrs->insert(
1051 {"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1052 scalar_field_ptrs->insert(
1053 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1054 vector_field_ptrs->insert({"U", u_field_ptr});
1055 sym_tensor_field_ptrs->insert(
1056 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1057 sym_tensor_field_ptrs->insert(
1058 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1059 sym_tensor_field_ptrs->insert(
1060 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()});
1061 tensor_field_ptrs->insert({"GRAD", common_hencky_ptr->matGradPtr});
1062 tensor_field_ptrs->insert(
1063 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()});
1064 } else {
1065 scalar_field_ptrs->insert(
1066 {"PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()});
1067 scalar_field_ptrs->insert(
1068 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()});
1069 vector_field_ptrs->insert({"U", u_field_ptr});
1070 sym_tensor_field_ptrs->insert(
1071 {"STRAIN", common_plastic_ptr->mStrainPtr});
1072 sym_tensor_field_ptrs->insert(
1073 {"STRESS", common_plastic_ptr->mStressPtr});
1074 sym_tensor_field_ptrs->insert(
1075 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()});
1076 sym_tensor_field_ptrs->insert(
1077 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()});
1078 }
1079 }
1080 }
1081
1082 auto test_monitor_ptr = boost::make_shared<FEMethod>();
1083
1084 auto set_time_monitor = [&](auto dm, auto solver) {
1086 boost::shared_ptr<Monitor<SPACE_DIM>> monitor_ptr(new Monitor<SPACE_DIM>(
1087 dm, create_post_process_elements(), reactionFe, uXScatter, uYScatter,
1088 uZScatter, field_eval_coords, field_eval_data, scalar_field_ptrs,
1089 vector_field_ptrs, sym_tensor_field_ptrs, tensor_field_ptrs));
1090 boost::shared_ptr<ForcesAndSourcesCore> null;
1091
1092 test_monitor_ptr->postProcessHook = [&]() {
1094
1095 if (atom_test && fabs(test_monitor_ptr->ts_t - 0.5) < 1e-12 &&
1096 test_monitor_ptr->ts_step == 25) {
1097
1098 if (scalar_field_ptrs->at("PLASTIC_MULTIPLIER")->size()) {
1099 auto t_tau =
1100 getFTensor0FromVec(*scalar_field_ptrs->at("PLASTIC_MULTIPLIER"));
1101 MOFEM_LOG("PlasticSync", Sev::inform) << "Eval point tau: " << t_tau;
1102
1103 if (atom_test == 1 && fabs(t_tau - 0.688861) > 1e-5) {
1104 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1105 "atom test %d failed: wrong plastic multiplier value",
1106 atom_test);
1107 }
1108 }
1109
1110 if (vector_field_ptrs->at("U")->size1()) {
1112 auto t_disp =
1113 getFTensor1FromMat<SPACE_DIM>(*vector_field_ptrs->at("U"));
1114 MOFEM_LOG("PlasticSync", Sev::inform) << "Eval point U: " << t_disp;
1115
1116 if (atom_test == 1 && fabs(t_disp(0) - 0.25 / 2.) > 1e-5 ||
1117 fabs(t_disp(1) + 0.0526736) > 1e-5) {
1118 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1119 "atom test %d failed: wrong displacement value",
1120 atom_test);
1121 }
1122 }
1123
1124 if (sym_tensor_field_ptrs->at("PLASTIC_STRAIN")->size1()) {
1125 auto t_plastic_strain = getFTensor2SymmetricFromMat<SPACE_DIM>(
1126 *sym_tensor_field_ptrs->at("PLASTIC_STRAIN"));
1127 MOFEM_LOG("PlasticSync", Sev::inform)
1128 << "Eval point EP: " << t_plastic_strain;
1129
1130 if (atom_test == 1 &&
1131 fabs(t_plastic_strain(0, 0) - 0.221943) > 1e-5 ||
1132 fabs(t_plastic_strain(0, 1)) > 1e-5 ||
1133 fabs(t_plastic_strain(1, 1) + 0.110971) > 1e-5) {
1134 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1135 "atom test %d failed: wrong plastic strain value",
1136 atom_test);
1137 }
1138 }
1139
1140 if (tensor_field_ptrs->at("FIRST_PIOLA")->size1()) {
1141 auto t_piola_stress = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(
1142 *tensor_field_ptrs->at("FIRST_PIOLA"));
1143 MOFEM_LOG("PlasticSync", Sev::inform)
1144 << "Eval point Piola stress: " << t_piola_stress;
1145
1146 if (atom_test == 1 && fabs((t_piola_stress(0, 0) - 198.775) /
1147 t_piola_stress(0, 0)) > 1e-5 ||
1148 fabs(t_piola_stress(0, 1)) + fabs(t_piola_stress(1, 0)) +
1149 fabs(t_piola_stress(1, 1)) >
1150 1e-5) {
1151 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1152 "atom test %d failed: wrong Piola stress value",
1153 atom_test);
1154 }
1155 }
1156 }
1157
1158 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
1160 };
1161
1162 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
1163 monitor_ptr, null, test_monitor_ptr);
1164
1166 };
1167
1168 auto set_schur_pc = [&](auto solver,
1169 boost::shared_ptr<SetUpSchur> &schur_ptr) {
1171
1172 auto name_prb = simple->getProblemName();
1173
1174 // create sub dm for Schur complement
1175 auto create_schur_dm = [&](SmartPetscObj<DM> base_dm,
1176 SmartPetscObj<DM> &dm_sub) {
1178 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
1179 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SCHUR");
1180 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1181 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1182 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
1183 for (auto f : {"U"}) {
1186 }
1187 CHKERR DMSetUp(dm_sub);
1188
1190 };
1191
1192 auto create_block_dm = [&](SmartPetscObj<DM> base_dm,
1193 SmartPetscObj<DM> &dm_sub) {
1195 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
1196 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "BLOCK");
1197 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1198 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1199 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
1200#ifdef ADD_CONTACT
1201 for (auto f : {"SIGMA", "EP", "TAU"}) {
1204 }
1205#else
1206 for (auto f : {"EP", "TAU"}) {
1209 }
1210#endif
1211 CHKERR DMSetUp(dm_sub);
1213 };
1214
1215 // Create nested (sub BC) Schur DM
1216 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
1217
1218 SmartPetscObj<DM> dm_schur;
1219 CHKERR create_schur_dm(simple->getDM(), dm_schur);
1220 SmartPetscObj<DM> dm_block;
1221 CHKERR create_block_dm(simple->getDM(), dm_block);
1222
1223#ifdef ADD_CONTACT
1224
1225 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1226 auto block_mat_data = createBlockMatStructure(
1227 simple->getDM(),
1228
1229 {
1230
1231 {simple->getDomainFEName(),
1232
1233 {{"U", "U"},
1234 {"SIGMA", "SIGMA"},
1235 {"U", "SIGMA"},
1236 {"SIGMA", "U"},
1237 {"EP", "EP"},
1238 {"TAU", "TAU"},
1239 {"U", "EP"},
1240 {"EP", "U"},
1241 {"EP", "TAU"},
1242 {"TAU", "EP"},
1243 {"TAU", "U"}
1244
1245 }},
1246
1247 {simple->getBoundaryFEName(),
1248
1249 {{"SIGMA", "SIGMA"}, {"U", "SIGMA"}, {"SIGMA", "U"}
1250
1251 }}
1252
1253 }
1254
1255 );
1256
1258
1259 {dm_schur, dm_block}, block_mat_data,
1260
1261 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, true
1262
1263 );
1264 };
1265
1266#else
1267
1268 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1269 auto block_mat_data =
1271
1272 {{simple->getDomainFEName(),
1273
1274 {{"U", "U"},
1275 {"EP", "EP"},
1276 {"TAU", "TAU"},
1277 {"U", "EP"},
1278 {"EP", "U"},
1279 {"EP", "TAU"},
1280 {"TAU", "U"},
1281 {"TAU", "EP"}
1282
1283 }}}
1284
1285 );
1286
1288
1289 {dm_schur, dm_block}, block_mat_data,
1290
1291 {"EP", "TAU"}, {nullptr, nullptr}, false
1292
1293 );
1294 };
1295
1296#endif
1297
1298 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
1299 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
1300
1301 auto block_is = getDMSubData(dm_block)->getSmartRowIs();
1302 auto ao_schur = getDMSubData(dm_schur)->getSmartRowMap();
1303
1304 // Indices has to be map fro very to level, while assembling Schur
1305 // complement.
1306 schur_ptr =
1307 SetUpSchur::createSetUpSchur(mField, dm_schur, block_is, ao_schur);
1308 CHKERR schur_ptr->setUp(solver);
1309 }
1310
1312 };
1313
1314 auto dm = simple->getDM();
1315 auto D = createDMVector(dm);
1316 auto DD = vectorDuplicate(D);
1317 CHKERR VecSetDM(D, PETSC_NULLPTR);
1318 CHKERR VecSetDM(DD, PETSC_NULLPTR);
1319 uXScatter = scatter_create(D, 0);
1320 uYScatter = scatter_create(D, 1);
1321 if constexpr (SPACE_DIM == 3)
1322 uZScatter = scatter_create(D, 2);
1323
1324 auto create_solver = [pip_mng]() {
1325 if (is_quasi_static == PETSC_TRUE)
1326 return pip_mng->createTSIM();
1327 else
1328 return pip_mng->createTSIM2();
1329 };
1330
1331 auto solver = create_solver();
1332
1333 auto active_pre_lhs = []() {
1335 std::fill(PlasticOps::CommonData::activityData.begin(),
1338 };
1339
1340 auto active_post_lhs = [&]() {
1342 auto get_iter = [&]() {
1343 SNES snes;
1344 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
1345 int iter;
1346 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
1347 "Can not get iter");
1348 return iter;
1349 };
1350
1351 auto iter = get_iter();
1352 if (iter >= 0) {
1353
1354 std::array<int, 5> activity_data;
1355 std::fill(activity_data.begin(), activity_data.end(), 0);
1356 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
1357 activity_data.data(), activity_data.size(), MPI_INT,
1358 MPI_SUM, mField.get_comm());
1359
1360 int &active_points = activity_data[0];
1361 int &avtive_full_elems = activity_data[1];
1362 int &avtive_elems = activity_data[2];
1363 int &nb_points = activity_data[3];
1364 int &nb_elements = activity_data[4];
1365
1366 if (nb_points) {
1367
1368 double proc_nb_points =
1369 100 * static_cast<double>(active_points) / nb_points;
1370 double proc_nb_active =
1371 100 * static_cast<double>(avtive_elems) / nb_elements;
1372 double proc_nb_full_active = 100;
1373 if (avtive_elems)
1374 proc_nb_full_active =
1375 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
1376
1377 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1378 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
1379 "elements %d "
1380 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1381 iter, nb_points, active_points, proc_nb_points,
1382 avtive_elems, proc_nb_active, avtive_full_elems,
1383 proc_nb_full_active, iter);
1384 }
1385 }
1386
1388 };
1389
1390 auto add_active_dofs_elem = [&](auto dm) {
1392 auto fe_pre_proc = boost::make_shared<FEMethod>();
1393 fe_pre_proc->preProcessHook = active_pre_lhs;
1394 auto fe_post_proc = boost::make_shared<FEMethod>();
1395 fe_post_proc->postProcessHook = active_post_lhs;
1396 auto ts_ctx_ptr = getDMTsCtx(dm);
1397 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1398 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1400 };
1401
1402 auto set_essential_bc = [&](auto dm, auto solver) {
1404 // This is low level pushing finite elements (pipelines) to solver
1405
1406 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1407 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1408 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1409 auto ts_ctx_ptr = getDMTsCtx(dm);
1410 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1411 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1412 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1413 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1414
1415 // Add boundary condition scaling
1416 auto disp_time_scale = boost::make_shared<TimeScale>();
1417
1418 auto get_bc_hook_rhs = [&]() {
1420 mField, pre_proc_ptr, {disp_time_scale}, false);
1421 };
1422 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1423
1424 auto waak_post_proc_rhs_ptr = boost::weak_ptr<FEMethod>(
1425 post_proc_rhs_ptr); // fe method passed to lambda, have to be weak ptr to avoid circular shared ptr reference
1426 auto get_post_proc_hook_rhs = [this, waak_post_proc_rhs_ptr]() {
1429 mField, waak_post_proc_rhs_ptr.lock(), nullptr, Sev::verbose)();
1431 mField, waak_post_proc_rhs_ptr.lock(), 1.)();
1433 };
1434 auto get_post_proc_hook_lhs = [&]() {
1436 mField, post_proc_lhs_ptr, 1.);
1437 };
1438
1439 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1440 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1441
1443 };
1444
1445 auto B = createDMMatrix(dm);
1446 if (is_quasi_static == PETSC_FALSE) {
1447 CHKERR TSSetIJacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
1448 } else {
1449 CHKERR TSSetI2Jacobian(solver, B, B, PETSC_NULLPTR, PETSC_NULLPTR);
1450 }
1451 if (is_quasi_static == PETSC_TRUE) {
1452 CHKERR TSSetSolution(solver, D);
1453 } else {
1454 CHKERR TS2SetSolution(solver, D, DD);
1455 }
1456 CHKERR set_section_monitor(solver);
1457 CHKERR set_time_monitor(dm, solver);
1458 CHKERR TSSetFromOptions(solver);
1459
1460 CHKERR add_active_dofs_elem(dm);
1461 boost::shared_ptr<SetUpSchur> schur_ptr;
1462 CHKERR set_schur_pc(solver, schur_ptr);
1463 CHKERR set_essential_bc(dm, solver);
1464
1465 MOFEM_LOG_CHANNEL("TIMER");
1466 MOFEM_LOG_TAG("TIMER", "timer");
1467 if (set_timer)
1468 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
1469 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
1470 CHKERR TSSetUp(solver);
1471 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
1472 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
1473 CHKERR TSSolve(solver, NULL);
1474 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
1475
1476 if (mField.get_comm_rank() == 0) {
1477 auto ts_ctx_ptr = getDMTsCtx(dm);
1479 "ts_manager_graph.dot");
1480 }
1481
1483}
1484//! [Solve]
1485
1486//! [TestOperators]
1489
1490 // get operators tester
1491 auto simple = mField.getInterface<Simple>();
1492 auto opt = mField.getInterface<OperatorsTester>(); // get interface to
1493 // OperatorsTester
1494 auto pip = mField.getInterface<PipelineManager>(); // get interface to
1495 // pipeline manager
1496
1497 constexpr double eps = 1e-9;
1498
1499 auto x = opt->setRandomFields(simple->getDM(), {
1500
1501 {"U", {-1e-4, 1e-4}},
1502
1503 {"EP", {-1e-4, 1e-4}},
1504
1505 {"TAU", {0, 1e-4}}
1506
1507 });
1508
1509 auto dot_x_plastic_active =
1510 opt->setRandomFields(simple->getDM(), {
1511
1512 {"U", {-1, 1}},
1513
1514 {"EP", {-1, 1}},
1515
1516 {"TAU", {0.1, 0.5}}
1517
1518 });
1519 auto diff_x_plastic_active =
1520 opt->setRandomFields(simple->getDM(), {
1521
1522 {"U", {-1, 1}},
1523
1524 {"EP", {-1, 1}},
1525
1526 {"TAU", {-1, 1}}
1527
1528 });
1529
1530 auto dot_x_elastic =
1531 opt->setRandomFields(simple->getDM(), {
1532
1533 {"U", {-1, 1}},
1534
1535 {"EP", {-1, 1}},
1536
1537 {"TAU", {-1, -0.1}}
1538
1539 });
1540 auto diff_x_elastic =
1541 opt->setRandomFields(simple->getDM(), {
1542
1543 {"U", {-1, 1}},
1544
1545 {"EP", {-1, 1}},
1546
1547 {"TAU", {-1, 1}}
1548
1549 });
1550
1551 auto test_domain_ops = [&](auto fe_name, auto lhs_pipeline, auto rhs_pipeline,
1552 auto dot_x, auto diff_x) {
1554
1555 auto diff_res = opt->checkCentralFiniteDifference(
1556 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1557 SmartPetscObj<Vec>(), diff_x, 0, 0.5, eps);
1558
1559 // Calculate norm of difference between directional derivative calculated
1560 // from finite difference, and tangent matrix.
1561 double fnorm;
1562 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1563 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1564 "Test consistency of tangent matrix %3.4e", fnorm);
1565
1566 constexpr double err = 1e-5;
1567 if (fnorm > err)
1568 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1569 "Norm of directional derivative too large err = %3.4e", fnorm);
1570
1572 };
1573
1574 MOFEM_LOG("PLASTICITY", Sev::inform) << "Elastic active";
1575 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1576 pip->getDomainRhsFE(), dot_x_elastic, diff_x_elastic);
1577
1578 MOFEM_LOG("PLASTICITY", Sev::inform) << "Plastic active";
1579 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1580 pip->getDomainRhsFE(), dot_x_plastic_active,
1581 diff_x_plastic_active);
1582
1584};
1585
1586//! [TestOperators]
1587
1588static char help[] = "...\n\n";
1589
1590int main(int argc, char *argv[]) {
1591
1592#ifdef ADD_CONTACT
1593 #ifdef ENABLE_PYTHON_BINDING
1594 Py_Initialize();
1595 np::initialize();
1596 #endif
1597#endif // ADD_CONTACT
1598
1599 // Initialisation of MoFEM/PETSc and MOAB data structures
1600 const char param_file[] = "param_file.petsc";
1601 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1602
1603 // Add logging channel for example
1604 auto core_log = logging::core::get();
1605 core_log->add_sink(
1607 core_log->add_sink(
1609 LogManager::setLog("PLASTICITY");
1610 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
1611
1612#ifdef ADD_CONTACT
1613 core_log->add_sink(
1615 LogManager::setLog("CONTACT");
1616 MOFEM_LOG_TAG("CONTACT", "Contact");
1617#endif // ADD_CONTACT
1618
1619 core_log->add_sink(
1621 LogManager::setLog("PlasticSync");
1622 MOFEM_LOG_TAG("PlasticSync", "PlasticSync");
1623
1624 try {
1625
1626 //! [Register MoFEM discrete manager in PETSc]
1627 DMType dm_name = "DMMOFEM";
1628 CHKERR DMRegister_MoFEM(dm_name);
1629 //! [Register MoFEM discrete manager in PETSc
1630
1631 //! [Create MoAB]
1632 moab::Core mb_instance; ///< mesh database
1633 moab::Interface &moab = mb_instance; ///< mesh database interface
1634 //! [Create MoAB]
1635
1636 //! [Create MoFEM]
1637 MoFEM::Core core(moab); ///< finite element database
1638 MoFEM::Interface &m_field = core; ///< finite element database interface
1639 //! [Create MoFEM]
1640
1641 //! [Load mesh]
1642 Simple *simple = m_field.getInterface<Simple>();
1644 CHKERR simple->loadFile();
1645 //! [Load mesh]
1646
1647 //! [Example]
1648 Example ex(m_field);
1649 CHKERR ex.runProblem();
1650 //! [Example]
1651 }
1653
1655
1656#ifdef ADD_CONTACT
1657 #ifdef ENABLE_PYTHON_BINDING
1658 if (Py_FinalizeEx() < 0) {
1659 exit(120);
1660 }
1661 #endif
1662#endif // ADD_CONTACT
1663
1664 return 0;
1665}
1666
1667struct SetUpSchurImpl : public SetUpSchur {
1668
1670 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
1671 : SetUpSchur(), mField(m_field), subDM(sub_dm),
1672 fieldSplitIS(field_split_is), aoSchur(ao_up) {
1673 if (S) {
1675 "Is expected that schur matrix is not "
1676 "allocated. This is "
1677 "possible only is if PC is set up twice");
1678 }
1679 }
1680 virtual ~SetUpSchurImpl() { S.reset(); }
1681
1682 MoFEMErrorCode setUp(TS solver);
1685
1686private:
1688
1690 SmartPetscObj<DM> subDM; ///< field split sub dm
1691 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
1692 SmartPetscObj<AO> aoSchur; ///> main DM to subDM
1693};
1694
1697 auto simple = mField.getInterface<Simple>();
1698 auto pip_mng = mField.getInterface<PipelineManager>();
1699
1700 SNES snes;
1701 CHKERR TSGetSNES(solver, &snes);
1702 KSP ksp;
1703 CHKERR SNESGetKSP(snes, &ksp);
1704 CHKERR KSPSetFromOptions(ksp);
1705
1706 PC pc;
1707 CHKERR KSPGetPC(ksp, &pc);
1708 PetscBool is_pcfs = PETSC_FALSE;
1709 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1710 if (is_pcfs) {
1711 if (S) {
1713 "Is expected that schur matrix is not "
1714 "allocated. This is "
1715 "possible only is if PC is set up twice");
1716 }
1717
1719 CHKERR MatSetBlockSize(S, SPACE_DIM);
1720
1721 // Set DM to use shell block matrix
1722 DM solver_dm;
1723 CHKERR TSGetDM(solver, &solver_dm);
1724 CHKERR DMSetMatType(solver_dm, MATSHELL);
1725
1726 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1727 auto A = createDMBlockMat(simple->getDM());
1728 auto P = createDMNestSchurMat(simple->getDM());
1729
1730 if (is_quasi_static == PETSC_TRUE) {
1731 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1732 Mat A, Mat B, void *ctx) {
1733 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1734 };
1735 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1736 } else {
1737 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1738 PetscReal a, PetscReal aa, Mat A, Mat B,
1739 void *ctx) {
1740 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1741 };
1742 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1743 }
1744 CHKERR KSPSetOperators(ksp, A, P);
1745
1746 auto set_ops = [&]() {
1748 auto pip_mng = mField.getInterface<PipelineManager>();
1749
1750#ifndef ADD_CONTACT
1751 // Boundary
1752 pip_mng->getOpBoundaryLhsPipeline().push_front(
1754 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1755
1756 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1757
1758 ));
1759 // Domain
1760 pip_mng->getOpDomainLhsPipeline().push_front(
1762 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1763
1764 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1765
1766 ));
1767#else
1768
1769 double eps_stab = 1e-4;
1770 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
1771 PETSC_NULLPTR);
1772
1775 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1776
1777 // Boundary
1778 pip_mng->getOpBoundaryLhsPipeline().push_front(
1780 pip_mng->getOpBoundaryLhsPipeline().push_back(
1781 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
1782 return eps_stab;
1783 }));
1784 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1785
1786 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1787 false, false
1788
1789 ));
1790 // Domain
1791 pip_mng->getOpDomainLhsPipeline().push_front(
1793 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1794
1795 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1796 false, false
1797
1798 ));
1799#endif // ADD_CONTACT
1801 };
1802
1803 auto set_assemble_elems = [&]() {
1805 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1806 schur_asmb_pre_proc->preProcessHook = [this]() {
1808 CHKERR MatZeroEntries(S);
1809 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
1811 };
1812 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1813 auto weak_schur_asmb_post_proc = boost::weak_ptr<FEMethod>(
1814 schur_asmb_post_proc); // fe method passed to lambda, have to be weak ptr to avoid circular shared ptr reference
1815
1816 schur_asmb_post_proc->postProcessHook = [this,
1817 weak_schur_asmb_post_proc]() {
1819 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
1820
1821 // Apply essential constrains to Schur complement
1822 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1823 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1825 mField, weak_schur_asmb_post_proc.lock(), 1, S, aoSchur)();
1826
1828 };
1829 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1830 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1831 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1833 };
1834
1835 auto set_pc = [&]() {
1837 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
1838 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1840 };
1841
1842 auto set_diagonal_pc = [&]() {
1844 KSP *subksp;
1845 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
1846 auto get_pc = [](auto ksp) {
1847 PC pc_raw;
1848 CHKERR KSPGetPC(ksp, &pc_raw);
1849 return SmartPetscObj<PC>(pc_raw,
1850 true); // bump reference
1851 };
1852 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1853 CHKERR PetscFree(subksp);
1855 };
1856
1857 CHKERR set_ops();
1858 CHKERR set_pc();
1859 CHKERR set_assemble_elems();
1860
1861 CHKERR TSSetUp(solver);
1862 CHKERR KSPSetUp(ksp);
1863 CHKERR set_diagonal_pc();
1864
1865 } else {
1866 pip_mng->getOpBoundaryLhsPipeline().push_front(
1868 pip_mng->getOpBoundaryLhsPipeline().push_back(
1869 createOpSchurAssembleEnd({}, {}));
1870 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1871 pip_mng->getOpDomainLhsPipeline().push_back(
1872 createOpSchurAssembleEnd({}, {}));
1873 }
1874
1875 // fieldSplitIS.reset();
1876 // aoSchur.reset();
1878}
1879
1880boost::shared_ptr<SetUpSchur>
1882 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
1883 SmartPetscObj<AO> ao_up) {
1884 return boost::shared_ptr<SetUpSchur>(
1885 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
1886}
1887
1888namespace PlasticOps {
1889
1891 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1892 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1894 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
1896}
1897
1899 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1900 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1902 CHKERR MoFEM::AddHOOps<1, 2, 2>::add(pipeline, spaces, geom_field_name);
1904}
1905
1906template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM>
1908scaleL2(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1909 std::string geom_field_name) {
1911
1912 auto jac_ptr = boost::make_shared<MatrixDouble>();
1913 auto det_ptr = boost::make_shared<VectorDouble>();
1915 geom_field_name, jac_ptr));
1916 pipeline.push_back(new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, nullptr));
1917
1918 auto scale_ptr = boost::make_shared<double>(1.);
1920 Example::meshVolumeAndCount[1]; // average volume of elements
1922 auto op_scale = new OP(NOSPACE, OP::OPSPACE);
1923 op_scale->doWorkRhsHook = [scale_ptr, det_ptr,
1924 scale](DataOperator *base_op_ptr, int, EntityType,
1926 *scale_ptr = scale / det_ptr->size(); // distribute average element size
1927 // over integration points
1928 return 0;
1929 };
1930 pipeline.push_back(op_scale);
1931
1934 pipeline.push_back(
1935 new OpScaleBaseBySpaceInverseOfMeasure(L2, base, det_ptr, scale_ptr));
1936 }
1937
1939}
1940
1942 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1943 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1945 constexpr bool scale_l2 = false;
1946 if (scale_l2) {
1947 CHKERR scaleL2<3, 3, 3>(pipeline, geom_field_name);
1948 }
1949 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
1950 nullptr, nullptr, nullptr);
1952}
1953
1955 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1956 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1958 constexpr bool scale_l2 = false;
1959 if (scale_l2) {
1960 CHKERR scaleL2<2, 2, 2>(pipeline, geom_field_name);
1961 }
1962 CHKERR MoFEM::AddHOOps<2, 2, 2>::add(pipeline, spaces, geom_field_name,
1963 nullptr, nullptr, nullptr);
1965}
1966
1967} // 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
const double eps
Definition HenckyOps.hpp:13
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:2675
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:2717
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:2433
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:2670
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1214
MoFEMErrorCode scaleL2(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string geom_field_name)
Definition plastic.cpp:1908
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
double getScale(const double time)
Get scaling at given time.
Definition plastic.cpp:244
[Example]
Definition plastic.cpp:217
static std::array< double, 2 > meshVolumeAndCount
Definition plastic.cpp:224
boost::shared_ptr< DomainEle > reactionFe
Definition plastic.cpp:236
MoFEMErrorCode testOperators()
[Solve]
Definition plastic.cpp:1487
MoFEMErrorCode tsSolve()
Definition plastic.cpp:835
FieldApproximationBase base
Choice of finite element basis functions.
Definition plot_base.cpp:68
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition plastic.cpp:239
MoFEMErrorCode createCommonData()
[Set up problem]
Definition plastic.cpp:481
Example(MoFEM::Interface &m_field)
Definition plastic.cpp:219
MoFEMErrorCode OPs()
[Boundary condition]
Definition plastic.cpp:651
MoFEMErrorCode runProblem()
[Run problem]
Definition plastic.cpp:257
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:227
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition plastic.cpp:240
MoFEMErrorCode setupProblem()
[Run problem]
Definition plastic.cpp:276
MoFEMErrorCode bC()
[Create common data]
Definition plastic.cpp:607
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition plastic.cpp:238
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 getOptions()
get options
Definition Simple.cpp:180
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:1690
SmartPetscObj< Mat > S
SmartPetscObj< AO > aoSchur
Definition plastic.cpp:1692
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition plastic.cpp:1691
SetUpSchurImpl(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
Definition plastic.cpp:1669
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
virtual ~SetUpSchurImpl()
Definition plastic.cpp:1680
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:126
constexpr AssemblyType AT
Definition plastic.cpp:44
double C1_k
Kinematic hardening.
Definition plastic.cpp:134
double Qinf
Saturation yield stress.
Definition plastic.cpp:132
constexpr IntegrationType IT
Definition plastic.cpp:47
static char help[]
[TestOperators]
Definition plastic.cpp:1588
double rho
Definition plastic.cpp:145
int atom_test
Atom test.
Definition plastic.cpp:122
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:120
PetscBool is_quasi_static
Definition plastic.cpp:144
double alpha_damping
Definition plastic.cpp:146
constexpr int SPACE_DIM
Definition plastic.cpp:40
double visH
Viscous hardening.
Definition plastic.cpp:130
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:127
auto kinematic_hardening(FTensor::Tensor2_symmetric< T, DIM > &t_plastic_strain, double C1_k)
Definition plastic.cpp:93
PetscBool set_timer
Set timer.
Definition plastic.cpp:119
double iso_hardening_dtau(double tau, double H, double Qinf, double b_iso)
Definition plastic.cpp:79
double scale
Definition plastic.cpp:124
constexpr auto size_symm
Definition plastic.cpp:42
double zeta
Viscous hardening.
Definition plastic.cpp:131
double H
Hardening.
Definition plastic.cpp:129
int tau_order
Order of tau files.
Definition plastic.cpp:140
double iso_hardening_exp(double tau, double b_iso)
Definition plastic.cpp:65
double cn0
Definition plastic.cpp:136
int order
Order displacement.
Definition plastic.cpp:139
double b_iso
Saturation exponent.
Definition plastic.cpp:133
PetscBool is_large_strains
Large strains.
Definition plastic.cpp:118
int geom_order
Order if fixed.
Definition plastic.cpp:142
double sigmaY
Yield stress.
Definition plastic.cpp:128
double iso_hardening(double tau, double H, double Qinf, double b_iso, double sigmaY)
Definition plastic.cpp:74
auto kinematic_hardening_dplastic_strain(double C1_k)
Definition plastic.cpp:107
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62
int ep_order
Order of ep files.
Definition plastic.cpp:141
double cn1
Definition plastic.cpp:137
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