v0.14.0
Loading...
Searching...
No Matches
plastic.cpp
Go to the documentation of this file.
1/**
2 * \file plastic.cpp
3 * \example 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;
62
63inline double iso_hardening_exp(double tau, double b_iso) {
64 return std::exp(
65 std::max(static_cast<double>(std::numeric_limits<float>::min_exponent10),
66 -b_iso * tau));
67}
68
69/**
70 * Isotropic hardening
71 */
72inline double iso_hardening(double tau, double H, double Qinf, double b_iso,
73 double sigmaY) {
74 return H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso)) + sigmaY;
75}
76
77inline double iso_hardening_dtau(double tau, double H, double Qinf,
78 double b_iso) {
79 auto r = [&](auto tau) {
80 return H + Qinf * b_iso * iso_hardening_exp(tau, b_iso);
81 };
82 constexpr double eps = 1e-12;
83 return std::max(r(tau), eps * r(0));
84}
85
86/**
87 * Kinematic hardening
88 */
89template <typename T, int DIM>
90inline auto
92 double C1_k) {
93 FTensor::Index<'i', DIM> i;
94 FTensor::Index<'j', DIM> j;
96 if (C1_k < std::numeric_limits<double>::epsilon()) {
97 t_alpha(i, j) = 0;
98 return t_alpha;
99 }
100 t_alpha(i, j) = C1_k * t_plastic_strain(i, j);
101 return t_alpha;
102}
103
104template <int DIM>
106 FTensor::Index<'i', DIM> i;
107 FTensor::Index<'j', DIM> j;
108 FTensor::Index<'k', DIM> k;
109 FTensor::Index<'l', DIM> l;
112 t_diff(i, j, k, l) = C1_k * (t_kd(i, k) ^ t_kd(j, l)) / 4.;
113 return t_diff;
114}
115
116PetscBool is_large_strains = PETSC_TRUE; ///< Large strains
117PetscBool set_timer = PETSC_FALSE; ///< Set timer
118
119double scale = 1.;
120
121double young_modulus = 206913; ///< Young modulus
122double poisson_ratio = 0.29; ///< Poisson ratio
123double sigmaY = 450; ///< Yield stress
124double H = 129; ///< Hardening
125double visH = 0; ///< Viscous hardening
126double zeta = 5e-2; ///< Viscous hardening
127double Qinf = 265; ///< Saturation yield stress
128double b_iso = 16.93; ///< Saturation exponent
129double C1_k = 0; ///< Kinematic hardening
130
131double cn0 = 1;
132double cn1 = 1;
133
134int order = 2; ///< Order displacement
135int tau_order = order - 2; ///< Order of tau files
136int ep_order = order - 1; ///< Order of ep files
137int geom_order = 2; ///< Order if fixed.
138
139PetscBool is_quasi_static = PETSC_TRUE;
140double rho = 0.0;
141double alpha_damping = 0;
142
143#include <HenckyOps.hpp>
144#include <PlasticOps.hpp>
145#include <PlasticNaturalBCs.hpp>
146
147#ifdef ADD_CONTACT
148 #ifdef PYTHON_SDF
149 #include <boost/python.hpp>
150 #include <boost/python/def.hpp>
151 #include <boost/python/numpy.hpp>
152namespace bp = boost::python;
153namespace np = boost::python::numpy;
154 #endif
155
156namespace ContactOps {
157
158double cn_contact = 0.1;
159
160}; // namespace ContactOps
161
162 #include <ContactOps.hpp>
163#endif // ADD_CONTACT
164
174
175using namespace PlasticOps;
176using namespace HenckyOps;
177
178namespace PlasticOps {
179
180template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM> struct AddHOOps;
181
182template <> struct AddHOOps<2, 3, 3> {
183 AddHOOps() = delete;
184 static MoFEMErrorCode
185 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
186 std::vector<FieldSpace> space, std::string geom_field_name);
187};
188
189template <> struct AddHOOps<1, 2, 2> {
190 AddHOOps() = delete;
191 static MoFEMErrorCode
192 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
193 std::vector<FieldSpace> space, std::string geom_field_name);
194};
195
196template <> struct AddHOOps<3, 3, 3> {
197 AddHOOps() = delete;
198 static MoFEMErrorCode
199 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
200 std::vector<FieldSpace> space, std::string geom_field_name);
201};
202
203template <> struct AddHOOps<2, 2, 2> {
204 AddHOOps() = delete;
205 static MoFEMErrorCode
206 add(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
207 std::vector<FieldSpace> space, std::string geom_field_name);
208};
209
210} // namespace PlasticOps
211
212
213struct Example {
214
215 Example(MoFEM::Interface &m_field) : mField(m_field) {}
216
218
219 enum { VOL, COUNT };
220 static inline std::array<double, 2> meshVolumeAndCount = {0, 0};
221
222private:
224
231
232 boost::shared_ptr<DomainEle> reactionFe;
233
234 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
235 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
236 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
237
240 double getScale(const double time) {
241 return scale * MoFEM::TimeScale::getScale(time);
242 };
243 };
244
245#ifdef ADD_CONTACT
246 #ifdef PYTHON_SDF
247 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
248 #endif
249#endif // ADD_CONTACT
250};
251
252//! [Run problem]
257 CHKERR bC();
258 CHKERR OPs();
259 PetscBool test_ops = PETSC_FALSE;
260 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-test_operators", &test_ops,
261 PETSC_NULL);
262 if (test_ops == PETSC_FALSE) {
263 CHKERR tsSolve();
264 } else {
266 }
268}
269//! [Run problem]
270
271//! [Set up problem]
275
276 Range domain_ents;
277 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
278 true);
279 auto get_ents_by_dim = [&](const auto dim) {
280 if (dim == SPACE_DIM) {
281 return domain_ents;
282 } else {
283 Range ents;
284 if (dim == 0)
285 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
286 else
287 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
288 return ents;
289 }
290 };
291
292 auto get_base = [&]() {
293 auto domain_ents = get_ents_by_dim(SPACE_DIM);
294 if (domain_ents.empty())
295 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
296 const auto type = type_from_handle(domain_ents[0]);
297 switch (type) {
298 case MBQUAD:
300 case MBHEX:
302 case MBTRI:
304 case MBTET:
306 default:
307 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
308 }
309 return NOBASE;
310 };
311
312 const auto base = get_base();
313 MOFEM_LOG("PLASTICITY", Sev::inform)
314 << "Base " << ApproximationBaseNames[base];
315
316 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
317 CHKERR simple->addDomainField("EP", L2, base, size_symm);
318 CHKERR simple->addDomainField("TAU", L2, base, 1);
319 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
320
321 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
322
323 PetscBool order_edge = PETSC_FALSE;
324 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_edge", &order_edge,
325 PETSC_NULL);
326 PetscBool order_face = PETSC_FALSE;
327 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_face", &order_face,
328 PETSC_NULL);
329 PetscBool order_volume = PETSC_FALSE;
330 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_volume", &order_volume,
331 PETSC_NULL);
332
333 if (order_edge || order_face || order_volume) {
334
335 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order edge " << order_edge
336 ? "true"
337 : "false";
338 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order face " << order_face
339 ? "true"
340 : "false";
341 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order volume " << order_volume
342 ? "true"
343 : "false";
344
345 auto ents = get_ents_by_dim(0);
346 if (order_edge)
347 ents.merge(get_ents_by_dim(1));
348 if (order_face)
349 ents.merge(get_ents_by_dim(2));
350 if (order_volume)
351 ents.merge(get_ents_by_dim(3));
352 CHKERR simple->setFieldOrder("U", order, &ents);
353 } else {
354 CHKERR simple->setFieldOrder("U", order);
355 }
356 CHKERR simple->setFieldOrder("EP", ep_order);
357 CHKERR simple->setFieldOrder("TAU", tau_order);
358
359 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
360
361#ifdef ADD_CONTACT
362 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
363 SPACE_DIM);
364 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
365 SPACE_DIM);
366
367 auto get_skin = [&]() {
368 Range body_ents;
369 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
370 Skinner skin(&mField.get_moab());
371 Range skin_ents;
372 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
373 return skin_ents;
374 };
375
376 auto filter_blocks = [&](auto skin) {
377 bool is_contact_block = true;
378 Range contact_range;
379 for (auto m :
381
382 (boost::format("%s(.*)") % "CONTACT").str()
383
384 ))
385
386 ) {
387 is_contact_block =
388 true; ///< blocs interation is collective, so that is set irrespective
389 ///< if there are entities in given rank or not in the block
390 MOFEM_LOG("CONTACT", Sev::inform)
391 << "Find contact block set: " << m->getName();
392 auto meshset = m->getMeshset();
393 Range contact_meshset_range;
394 CHKERR mField.get_moab().get_entities_by_dimension(
395 meshset, SPACE_DIM - 1, contact_meshset_range, true);
396
397 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
398 contact_meshset_range);
399 contact_range.merge(contact_meshset_range);
400 }
401 if (is_contact_block) {
402 MOFEM_LOG("SYNC", Sev::inform)
403 << "Nb entities in contact surface: " << contact_range.size();
405 skin = intersect(skin, contact_range);
406 }
407 return skin;
408 };
409
410 auto filter_true_skin = [&](auto skin) {
411 Range boundary_ents;
412 ParallelComm *pcomm =
413 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
414 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
415 PSTATUS_NOT, -1, &boundary_ents);
416 return boundary_ents;
417 };
418
419 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
420 CHKERR simple->setFieldOrder("SIGMA", 0);
421 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
422#endif
423
424 CHKERR simple->setUp();
425 CHKERR simple->addFieldToEmptyFieldBlocks("U", "TAU");
426
427 auto project_ho_geometry = [&]() {
428 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
429 return mField.loop_dofs("GEOMETRY", ent_method);
430 };
431 PetscBool project_geometry = PETSC_TRUE;
432 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-project_geometry",
433 &project_geometry, PETSC_NULL);
434 if (project_geometry) {
435 CHKERR project_ho_geometry();
436 }
437
438 auto get_volume = [&]() {
439 using VolOp = DomainEle::UserDataOperator;
440 auto *op_ptr = new VolOp(NOSPACE, VolOp::OPSPACE);
441 std::array<double, 2> volume_and_count;
442 op_ptr->doWorkRhsHook = [&](DataOperator *base_op_ptr, int side, EntityType type,
445 auto op_ptr = static_cast<VolOp *>(base_op_ptr);
446 volume_and_count[VOL] += op_ptr->getMeasure();
447 volume_and_count[COUNT] += 1;
448 // in necessary at integration over Gauss points.
450 };
451 volume_and_count = {0, 0};
452 auto fe = boost::make_shared<DomainEle>(mField);
453 fe->getOpPtrVector().push_back(op_ptr);
454
455 auto dm = simple->getDM();
457 DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(), fe),
458 "cac volume");
459 std::array<double, 2> tot_volume_and_count;
460 MPI_Allreduce(volume_and_count.data(), tot_volume_and_count.data(),
461 volume_and_count.size(), MPI_DOUBLE, MPI_SUM,
462 mField.get_comm());
463 return tot_volume_and_count;
464 };
465
466 meshVolumeAndCount = get_volume();
467 MOFEM_LOG("PLASTICITY", Sev::inform)
468 << "Mesh volume " << meshVolumeAndCount[VOL] << " nb. of elements "
470
472}
473//! [Set up problem]
474
475//! [Create common data]
478
479 auto get_command_line_parameters = [&]() {
481
482 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-scale", &scale, PETSC_NULL);
483 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-young_modulus",
484 &young_modulus, PETSC_NULL);
485 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-poisson_ratio",
486 &poisson_ratio, PETSC_NULL);
487 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-hardening", &H, PETSC_NULL);
488 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-hardening_viscous", &visH,
489 PETSC_NULL);
490 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-yield_stress", &sigmaY,
491 PETSC_NULL);
492 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn0", &cn0, PETSC_NULL);
493 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn1", &cn1, PETSC_NULL);
494 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-zeta", &zeta, PETSC_NULL);
495 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-Qinf", &Qinf, PETSC_NULL);
496 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-b_iso", &b_iso, PETSC_NULL);
497 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-C1_k", &C1_k, PETSC_NULL);
498 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-large_strains",
499 &is_large_strains, PETSC_NULL);
500 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-set_timer", &set_timer,
501 PETSC_NULL);
502
503 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &order, PETSC_NULL);
504 PetscBool tau_order_is_set; ///< true if tau order is set
505 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-tau_order", &tau_order,
506 &tau_order_is_set);
507 PetscBool ep_order_is_set; ///< true if tau order is set
508 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-ep_order", &ep_order,
509 &ep_order_is_set);
510 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-geom_order", &geom_order,
511 PETSC_NULL);
512
513 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-rho", &rho, PETSC_NULL);
514 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-alpha_damping",
515 &alpha_damping, PETSC_NULL);
516
517 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
518 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
519 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
520 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
521 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
522 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
523 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
524 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
525 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
526 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
527 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
528
529 if (tau_order_is_set == PETSC_FALSE)
530 tau_order = order - 2;
531 if (ep_order_is_set == PETSC_FALSE)
532 ep_order = order - 1;
533
534 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
535 MOFEM_LOG("PLASTICITY", Sev::inform)
536 << "Ep approximation order " << ep_order;
537 MOFEM_LOG("PLASTICITY", Sev::inform)
538 << "Tau approximation order " << tau_order;
539 MOFEM_LOG("PLASTICITY", Sev::inform)
540 << "Geometry approximation order " << geom_order;
541
542 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
543 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
544
545 PetscBool is_scale = PETSC_TRUE;
546 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-is_scale", &is_scale,
547 PETSC_NULL);
548 if (is_scale) {
550 }
551
552 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
553
554#ifdef ADD_CONTACT
555 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn_contact",
556 &ContactOps::cn_contact, PETSC_NULL);
557 MOFEM_LOG("CONTACT", Sev::inform)
558 << "cn_contact " << ContactOps::cn_contact;
559#endif // ADD_CONTACT
560
561 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-quasi_static",
562 &is_quasi_static, PETSC_NULL);
563 MOFEM_LOG("PLASTICITY", Sev::inform)
564 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
565
567 };
568
569 CHKERR get_command_line_parameters();
570
571#ifdef ADD_CONTACT
572 #ifdef PYTHON_SDF
573 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
574 CHKERR sdfPythonPtr->sdfInit("sdf.py");
575 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
576 #endif
577#endif // ADD_CONTACT
578
580}
581//! [Create common data]
582
583//! [Boundary condition]
586
588 auto bc_mng = mField.getInterface<BcManager>();
589
590 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
591 "U", 0, 0);
592 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
593 "U", 1, 1);
594 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
595 "U", 2, 2);
596 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
597 "REMOVE_ALL", "U", 0, 3);
598
599#ifdef ADD_CONTACT
600 for (auto b : {"FIX_X", "REMOVE_X"})
601 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
602 "SIGMA", 0, 0, false, true);
603 for (auto b : {"FIX_Y", "REMOVE_Y"})
604 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
605 "SIGMA", 1, 1, false, true);
606 for (auto b : {"FIX_Z", "REMOVE_Z"})
607 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
608 "SIGMA", 2, 2, false, true);
609 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
610 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
611 "SIGMA", 0, 3, false, true);
612 CHKERR bc_mng->removeBlockDOFsOnEntities(
613 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
614#endif
615
616 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
617 simple->getProblemName(), "U");
618
619 auto &bc_map = bc_mng->getBcMapByBlockName();
620 for (auto bc : bc_map)
621 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
622
624}
625//! [Boundary condition]
626
627//! [Push operators to pipeline]
630 auto pip_mng = mField.getInterface<PipelineManager>();
631
632 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
633
634 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order - 1; };
635
636 auto add_boundary_ops_lhs_mechanical = [&](auto &pip) {
638
640 pip, {HDIV}, "GEOMETRY");
641 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
642
643 // Add Natural BCs to LHS
645 pip, mField, "U", Sev::inform);
646
647#ifdef ADD_CONTACT
649 CHKERR
651 pip, "SIGMA", "U");
652 CHKERR
654 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
655 vol_rule);
656#endif // ADD_CONTACT
657
659 };
660
661 auto add_boundary_ops_rhs_mechanical = [&](auto &pip) {
663
665 pip, {HDIV}, "GEOMETRY");
666 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
667
668 // Add Natural BCs to RHS
670 pip, mField, "U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
671
672#ifdef ADD_CONTACT
674 pip, "SIGMA", "U");
675#endif // ADD_CONTACT
676
678 };
679
680 auto add_domain_ops_lhs = [this](auto &pip) {
683 pip, {H1, HDIV}, "GEOMETRY");
684
685 if (is_quasi_static == PETSC_FALSE) {
686
687 //! [Only used for dynamics]
690 //! [Only used for dynamics]
691
692 auto get_inertia_and_mass_damping = [this](const double, const double,
693 const double) {
694 auto *pip = mField.getInterface<PipelineManager>();
695 auto &fe_domain_lhs = pip->getDomainLhsFE();
696 return (rho / scale) * fe_domain_lhs->ts_aa +
697 (alpha_damping / scale) * fe_domain_lhs->ts_a;
698 };
699 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
700 }
701
703 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
704
706 };
707
708 auto add_domain_ops_rhs = [this](auto &pip) {
710
712 pip, {H1, HDIV}, "GEOMETRY");
713
715 pip, mField, "U",
716 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
717 Sev::inform);
718
719 // only in case of dynamics
720 if (is_quasi_static == PETSC_FALSE) {
721
722 //! [Only used for dynamics]
725 //! [Only used for dynamics]
726
727 auto mat_acceleration = boost::make_shared<MatrixDouble>();
729 "U", mat_acceleration));
730 pip.push_back(
731 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
732 return rho / scale;
733 }));
734 if (alpha_damping > 0) {
735 auto mat_velocity = boost::make_shared<MatrixDouble>();
736 pip.push_back(
737 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
738 pip.push_back(
739 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
740 return alpha_damping / scale;
741 }));
742 }
743 }
744
746 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
747
748#ifdef ADD_CONTACT
750 pip, "SIGMA", "U");
751#endif // ADD_CONTACT
752
754 };
755
756 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
757 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
758
759 // Boundary
760 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
761 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
762
763 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
764 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
765
766 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
767 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
768
769 auto create_reaction_pipeline = [&](auto &pip) {
772 pip, {H1}, "GEOMETRY");
774 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
776 };
777
778 reactionFe = boost::make_shared<DomainEle>(mField);
779 reactionFe->getRuleHook = vol_rule;
780 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
781 reactionFe->postProcessHook =
783
785}
786//! [Push operators to pipeline]
787
788//! [Solve]
789struct SetUpSchur {
790
791 /**
792 * @brief Create data structure for handling Schur complement
793 *
794 * @param m_field
795 * @param sub_dm Schur complement sub dm
796 * @param field_split_it IS of Schur block
797 * @param ao_map AO map from sub dm to main problem
798 * @return boost::shared_ptr<SetUpSchur>
799 */
800 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
801
802 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
803 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
804
805 );
806 virtual MoFEMErrorCode setUp(TS solver) = 0;
807
808protected:
809 SetUpSchur() = default;
810};
811
814
817 ISManager *is_manager = mField.getInterface<ISManager>();
818
819 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
820
821 auto set_section_monitor = [&](auto solver) {
823 SNES snes;
824 CHKERR TSGetSNES(solver, &snes);
825 CHKERR SNESMonitorSet(snes,
826 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
828 (void *)(snes_ctx_ptr.get()), nullptr);
830 };
831
832 auto create_post_process_elements = [&]() {
833
834 auto push_vol_ops = [this](auto &pip) {
836 pip, {H1, HDIV}, "GEOMETRY");
837
838 auto [common_plastic_ptr, common_hencky_ptr] =
840 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU", 1., Sev::inform);
841
842 if (common_hencky_ptr) {
843 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
844 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
845 }
846
847 return std::make_pair(common_plastic_ptr, common_hencky_ptr);
848 };
849
850 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
852
853 auto &pip = pp_fe->getOpPtrVector();
854
855 auto [common_plastic_ptr, common_hencky_ptr] = p;
856
858
859 auto x_ptr = boost::make_shared<MatrixDouble>();
860 pip.push_back(
861 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
862 auto u_ptr = boost::make_shared<MatrixDouble>();
863 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
864
865 if (is_large_strains) {
866
867 pip.push_back(
868
869 new OpPPMap(
870
871 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
872
873 {{"PLASTIC_SURFACE",
874 common_plastic_ptr->getPlasticSurfacePtr()},
875 {"PLASTIC_MULTIPLIER",
876 common_plastic_ptr->getPlasticTauPtr()}},
877
878 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
879
880 {{"GRAD", common_hencky_ptr->matGradPtr},
881 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
882
883 {{"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
884 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
885
886 )
887
888 );
889
890 } else {
891
892 pip.push_back(
893
894 new OpPPMap(
895
896 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
897
898 {{"PLASTIC_SURFACE",
899 common_plastic_ptr->getPlasticSurfacePtr()},
900 {"PLASTIC_MULTIPLIER",
901 common_plastic_ptr->getPlasticTauPtr()}},
902
903 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
904
905 {},
906
907 {{"STRAIN", common_plastic_ptr->mStrainPtr},
908 {"STRESS", common_plastic_ptr->mStressPtr},
909 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
910 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
911
912 )
913
914 );
915 }
916
918 };
919
920 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops]() {
921 PetscBool post_proc_vol = PETSC_FALSE;
922 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_vol",
923 &post_proc_vol, PETSC_NULL);
924 if (post_proc_vol == PETSC_FALSE)
925 return boost::shared_ptr<PostProcEle>();
926 auto pp_fe = boost::make_shared<PostProcEle>(mField);
928 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
929 "push_vol_post_proc_ops");
930 return pp_fe;
931 };
932
933 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops]() {
934 PetscBool post_proc_skin = PETSC_TRUE;
935 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_skin",
936 &post_proc_skin, PETSC_NULL);
937 if (post_proc_skin == PETSC_FALSE)
938 return boost::shared_ptr<SkinPostProcEle>();
939
940 auto simple = mField.getInterface<Simple>();
941 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
942 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
943 SPACE_DIM, Sev::verbose);
944 pp_fe->getOpPtrVector().push_back(op_side);
945 CHK_MOAB_THROW(push_vol_post_proc_ops(
946 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
947 "push_vol_post_proc_ops");
948 return pp_fe;
949 };
950
951 return std::make_pair(vol_post_proc(), skin_post_proc());
952 };
953
954 auto scatter_create = [&](auto D, auto coeff) {
956 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
957 ROW, "U", coeff, coeff, is);
958 int loc_size;
959 CHKERR ISGetLocalSize(is, &loc_size);
960 Vec v;
961 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
962 VecScatter scatter;
963 CHKERR VecScatterCreate(D, is, v, PETSC_NULL, &scatter);
964 return std::make_tuple(SmartPetscObj<Vec>(v),
966 };
967
968 auto set_time_monitor = [&](auto dm, auto solver) {
970 boost::shared_ptr<Monitor> monitor_ptr(
971 new Monitor(dm, create_post_process_elements(), reactionFe, uXScatter,
972 uYScatter, uZScatter));
973 boost::shared_ptr<ForcesAndSourcesCore> null;
974 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
975 monitor_ptr, null, null);
977 };
978
979 auto set_schur_pc = [&](auto solver,
980 boost::shared_ptr<SetUpSchur> &schur_ptr) {
982
983 auto name_prb = simple->getProblemName();
984
985 // create sub dm for Schur complement
986 auto create_schur_dm = [&](SmartPetscObj<DM> base_dm,
987 SmartPetscObj<DM> &dm_sub) {
989 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
990 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SCHUR");
991 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
992 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
993 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
994 for (auto f : {"U"}) {
997 }
998 CHKERR DMSetUp(dm_sub);
999
1001 };
1002
1003 auto create_block_dm = [&](SmartPetscObj<DM> base_dm,
1004 SmartPetscObj<DM> &dm_sub) {
1006 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
1007 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "BLOCK");
1008 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1009 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1010 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
1011#ifdef ADD_CONTACT
1012 for (auto f : {"SIGMA", "EP", "TAU"}) {
1015 }
1016#else
1017 for (auto f : {"EP", "TAU"}) {
1020 }
1021#endif
1022 CHKERR DMSetUp(dm_sub);
1024 };
1025
1026 // Create nested (sub BC) Schur DM
1027 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
1028
1029 SmartPetscObj<DM> dm_schur;
1030 CHKERR create_schur_dm(simple->getDM(), dm_schur);
1031 SmartPetscObj<DM> dm_block;
1032 CHKERR create_block_dm(simple->getDM(), dm_block);
1033
1034#ifdef ADD_CONTACT
1035
1036 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1037 auto block_mat_data = createBlockMatStructure(
1038 simple->getDM(),
1039
1040 {
1041
1042 {simple->getDomainFEName(),
1043
1044 {{"U", "U"},
1045 {"SIGMA", "SIGMA"},
1046 {"U", "SIGMA"},
1047 {"SIGMA", "U"},
1048 {"EP", "EP"},
1049 {"TAU", "TAU"},
1050 {"U", "EP"},
1051 {"EP", "U"},
1052 {"EP", "TAU"},
1053 {"TAU", "EP"},
1054 {"TAU", "U"}
1055
1056 }},
1057
1058 {simple->getBoundaryFEName(),
1059
1060 {{"SIGMA", "SIGMA"}, {"U", "SIGMA"}, {"SIGMA", "U"}
1061
1062 }}
1063
1064 }
1065
1066 );
1067
1069
1070 {dm_schur, dm_block}, block_mat_data,
1071
1072 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, true
1073
1074 );
1075 };
1076
1077#else
1078
1079 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
1080 auto block_mat_data =
1082
1083 {{simple->getDomainFEName(),
1084
1085 {{"U", "U"},
1086 {"EP", "EP"},
1087 {"TAU", "TAU"},
1088 {"U", "EP"},
1089 {"EP", "U"},
1090 {"EP", "TAU"},
1091 {"TAU", "U"},
1092 {"TAU", "EP"}
1093
1094 }}}
1095
1096 );
1097
1099
1100 {dm_schur, dm_block}, block_mat_data,
1101
1102 {"EP", "TAU"}, {nullptr, nullptr}, false
1103
1104 );
1105 };
1106
1107#endif
1108
1109 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
1110 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
1111
1112 auto block_is = getDMSubData(dm_block)->getSmartRowIs();
1113 auto ao_schur = getDMSubData(dm_schur)->getSmartRowMap();
1114
1115 // Indices has to be map fro very to level, while assembling Schur
1116 // complement.
1117 schur_ptr =
1118 SetUpSchur::createSetUpSchur(mField, dm_schur, block_is, ao_schur);
1119 CHKERR schur_ptr->setUp(solver);
1120 }
1121
1123 };
1124
1125 auto dm = simple->getDM();
1126 auto D = createDMVector(dm);
1127 auto DD = vectorDuplicate(D);
1128 uXScatter = scatter_create(D, 0);
1129 uYScatter = scatter_create(D, 1);
1130 if constexpr (SPACE_DIM == 3)
1131 uZScatter = scatter_create(D, 2);
1132
1133 auto create_solver = [pip_mng]() {
1134 if (is_quasi_static == PETSC_TRUE)
1135 return pip_mng->createTSIM();
1136 else
1137 return pip_mng->createTSIM2();
1138 };
1139
1140 auto solver = create_solver();
1141
1142 auto active_pre_lhs = []() {
1144 std::fill(PlasticOps::CommonData::activityData.begin(),
1147 };
1148
1149 auto active_post_lhs = [&]() {
1151 auto get_iter = [&]() {
1152 SNES snes;
1153 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
1154 int iter;
1155 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
1156 "Can not get iter");
1157 return iter;
1158 };
1159
1160 auto iter = get_iter();
1161 if (iter >= 0) {
1162
1163 std::array<int, 5> activity_data;
1164 std::fill(activity_data.begin(), activity_data.end(), 0);
1165 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
1166 activity_data.data(), activity_data.size(), MPI_INT,
1167 MPI_SUM, mField.get_comm());
1168
1169 int &active_points = activity_data[0];
1170 int &avtive_full_elems = activity_data[1];
1171 int &avtive_elems = activity_data[2];
1172 int &nb_points = activity_data[3];
1173 int &nb_elements = activity_data[4];
1174
1175 if (nb_points) {
1176
1177 double proc_nb_points =
1178 100 * static_cast<double>(active_points) / nb_points;
1179 double proc_nb_active =
1180 100 * static_cast<double>(avtive_elems) / nb_elements;
1181 double proc_nb_full_active = 100;
1182 if (avtive_elems)
1183 proc_nb_full_active =
1184 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
1185
1186 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1187 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
1188 "elements %d "
1189 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1190 iter, nb_points, active_points, proc_nb_points,
1191 avtive_elems, proc_nb_active, avtive_full_elems,
1192 proc_nb_full_active, iter);
1193 }
1194 }
1195
1197 };
1198
1199 auto add_active_dofs_elem = [&](auto dm) {
1201 auto fe_pre_proc = boost::make_shared<FEMethod>();
1202 fe_pre_proc->preProcessHook = active_pre_lhs;
1203 auto fe_post_proc = boost::make_shared<FEMethod>();
1204 fe_post_proc->postProcessHook = active_post_lhs;
1205 auto ts_ctx_ptr = getDMTsCtx(dm);
1206 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1207 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1209 };
1210
1211 auto set_essential_bc = [&](auto dm, auto solver) {
1213 // This is low level pushing finite elements (pipelines) to solver
1214
1215 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1216 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1217 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1218
1219 // Add boundary condition scaling
1220 auto disp_time_scale = boost::make_shared<TimeScale>();
1221
1222 auto get_bc_hook_rhs = [this, pre_proc_ptr, disp_time_scale]() {
1223 EssentialPreProc<DisplacementCubitBcData> hook(mField, pre_proc_ptr,
1224 {disp_time_scale}, false);
1225 return hook;
1226 };
1227 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1228
1229 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
1232 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
1234 mField, post_proc_rhs_ptr, 1.)();
1236 };
1237 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
1239 mField, post_proc_lhs_ptr, 1.);
1240 };
1241 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1242
1243 auto ts_ctx_ptr = getDMTsCtx(dm);
1244 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1245 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1246 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1247 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1248 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1249
1251 };
1252
1253 if (is_quasi_static == PETSC_TRUE) {
1254 CHKERR TSSetSolution(solver, D);
1255 } else {
1256 CHKERR TS2SetSolution(solver, D, DD);
1257 }
1258
1259 CHKERR set_section_monitor(solver);
1260 CHKERR set_time_monitor(dm, solver);
1261 CHKERR TSSetFromOptions(solver);
1262 CHKERR TSSetUp(solver);
1263
1264 CHKERR add_active_dofs_elem(dm);
1265 boost::shared_ptr<SetUpSchur> schur_ptr;
1266 CHKERR set_schur_pc(solver, schur_ptr);
1267 CHKERR set_essential_bc(dm, solver);
1268
1269 MOFEM_LOG_CHANNEL("TIMER");
1270 MOFEM_LOG_TAG("TIMER", "timer");
1271 if (set_timer)
1272 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
1273 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
1274 CHKERR TSSetUp(solver);
1275 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
1276 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
1277 CHKERR TSSolve(solver, NULL);
1278 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
1279
1281}
1282//! [Solve]
1283
1284//! [TestOperators]
1287
1288 // get operators tester
1289 auto simple = mField.getInterface<Simple>();
1290 auto opt = mField.getInterface<OperatorsTester>(); // get interface to
1291 // OperatorsTester
1292 auto pip = mField.getInterface<PipelineManager>(); // get interface to
1293 // pipeline manager
1294
1295 constexpr double eps = 1e-9;
1296
1297 auto x = opt->setRandomFields(simple->getDM(), {
1298
1299 {"U", {-1e-6, 1e-6}},
1300
1301 {"EP", {-1e-6, 1e-6}},
1302
1303 {"TAU", {0, 1e-4}}
1304
1305 });
1306
1307 auto dot_x_plastic_active =
1308 opt->setRandomFields(simple->getDM(), {
1309
1310 {"U", {-1, 1}},
1311
1312 {"EP", {-1, 1}},
1313
1314 {"TAU", {0.1, 1}}
1315
1316 });
1317 auto diff_x_plastic_active =
1318 opt->setRandomFields(simple->getDM(), {
1319
1320 {"U", {-1, 1}},
1321
1322 {"EP", {-1, 1}},
1323
1324 {"TAU", {-1, 1}}
1325
1326 });
1327
1328 auto dot_x_elastic =
1329 opt->setRandomFields(simple->getDM(), {
1330
1331 {"U", {-1, 1}},
1332
1333 {"EP", {-1, 1}},
1334
1335 {"TAU", {-1, -0.1}}
1336
1337 });
1338 auto diff_x_elastic =
1339 opt->setRandomFields(simple->getDM(), {
1340
1341 {"U", {-1, 1}},
1342
1343 {"EP", {-1, 1}},
1344
1345 {"TAU", {-1, 1}}
1346
1347 });
1348
1349 auto test_domain_ops = [&](auto fe_name, auto lhs_pipeline, auto rhs_pipeline,
1350 auto dot_x, auto diff_x) {
1352
1353 auto diff_res = opt->checkCentralFiniteDifference(
1354 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1355 SmartPetscObj<Vec>(), diff_x, 0, 0.5, eps);
1356
1357 // Calculate norm of difference between directional derivative calculated
1358 // from finite difference, and tangent matrix.
1359 double fnorm;
1360 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1361 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1362 "Test consistency of tangent matrix %3.4e", fnorm);
1363
1364 constexpr double err = 1e-5;
1365 if (fnorm > err)
1366 SETERRQ1(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1367 "Norm of directional derivative too large err = %3.4e", fnorm);
1368
1370 };
1371
1372 MOFEM_LOG("PLASTICITY", Sev::inform) << "Elastic active";
1373 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1374 pip->getDomainRhsFE(), dot_x_elastic, diff_x_elastic);
1375
1376 MOFEM_LOG("PLASTICITY", Sev::inform) << "Plastic active";
1377 CHKERR test_domain_ops(simple->getDomainFEName(), pip->getDomainLhsFE(),
1378 pip->getDomainRhsFE(), dot_x_plastic_active,
1379 diff_x_plastic_active);
1380
1381
1382
1384};
1385
1386//! [TestOperators]
1387
1388static char help[] = "...\n\n";
1389
1390int main(int argc, char *argv[]) {
1391
1392#ifdef ADD_CONTACT
1393 #ifdef PYTHON_SDF
1394 Py_Initialize();
1395 np::initialize();
1396 #endif
1397#endif // ADD_CONTACT
1398
1399 // Initialisation of MoFEM/PETSc and MOAB data structures
1400 const char param_file[] = "param_file.petsc";
1401 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1402
1403 // Add logging channel for example
1404 auto core_log = logging::core::get();
1405 core_log->add_sink(
1407 core_log->add_sink(
1409 LogManager::setLog("PLASTICITY");
1410 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
1411
1412#ifdef ADD_CONTACT
1413 core_log->add_sink(
1415 LogManager::setLog("CONTACT");
1416 MOFEM_LOG_TAG("CONTACT", "Contact");
1417#endif // ADD_CONTACT
1418
1419 try {
1420
1421 //! [Register MoFEM discrete manager in PETSc]
1422 DMType dm_name = "DMMOFEM";
1423 CHKERR DMRegister_MoFEM(dm_name);
1424 //! [Register MoFEM discrete manager in PETSc
1425
1426 //! [Create MoAB]
1427 moab::Core mb_instance; ///< mesh database
1428 moab::Interface &moab = mb_instance; ///< mesh database interface
1429 //! [Create MoAB]
1430
1431 //! [Create MoFEM]
1432 MoFEM::Core core(moab); ///< finite element database
1433 MoFEM::Interface &m_field = core; ///< finite element database interface
1434 //! [Create MoFEM]
1435
1436 //! [Load mesh]
1437 Simple *simple = m_field.getInterface<Simple>();
1438 CHKERR simple->getOptions();
1439 CHKERR simple->loadFile();
1440 //! [Load mesh]
1441
1442 //! [Example]
1443 Example ex(m_field);
1444 CHKERR ex.runProblem();
1445 //! [Example]
1446 }
1448
1450
1451#ifdef ADD_CONTACT
1452 #ifdef PYTHON_SDF
1453 if (Py_FinalizeEx() < 0) {
1454 exit(120);
1455 }
1456 #endif
1457#endif // ADD_CONTACT
1458
1459 return 0;
1460}
1461
1462struct SetUpSchurImpl : public SetUpSchur {
1463
1465 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
1466 : SetUpSchur(), mField(m_field), subDM(sub_dm),
1467 fieldSplitIS(field_split_is), aoSchur(ao_up) {
1468 if (S) {
1470 "Is expected that schur matrix is not "
1471 "allocated. This is "
1472 "possible only is PC is set up twice");
1473 }
1474 }
1475 virtual ~SetUpSchurImpl() { S.reset(); }
1476
1477 MoFEMErrorCode setUp(TS solver);
1480
1481private:
1483
1485 SmartPetscObj<DM> subDM; ///< field split sub dm
1486 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
1487 SmartPetscObj<AO> aoSchur; ///> main DM to subDM
1488};
1489
1492 auto simple = mField.getInterface<Simple>();
1493 auto pip_mng = mField.getInterface<PipelineManager>();
1494
1495 SNES snes;
1496 CHKERR TSGetSNES(solver, &snes);
1497 KSP ksp;
1498 CHKERR SNESGetKSP(snes, &ksp);
1499 CHKERR KSPSetFromOptions(ksp);
1500
1501 PC pc;
1502 CHKERR KSPGetPC(ksp, &pc);
1503 PetscBool is_pcfs = PETSC_FALSE;
1504 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1505 if (is_pcfs) {
1506 if (S) {
1508 "Is expected that schur matrix is not "
1509 "allocated. This is "
1510 "possible only is PC is set up twice");
1511 }
1512
1514 CHKERR MatSetBlockSize(S, SPACE_DIM);
1515
1516 // Set DM to use shell block matrix
1517 DM solver_dm;
1518 CHKERR TSGetDM(solver, &solver_dm);
1519 CHKERR DMSetMatType(solver_dm, MATSHELL);
1520
1521 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
1522 auto A = createDMBlockMat(simple->getDM());
1523 auto P = createDMNestSchurMat(simple->getDM());
1524
1525 if (is_quasi_static == PETSC_TRUE) {
1526 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
1527 Mat A, Mat B, void *ctx) {
1528 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
1529 };
1530 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1531 } else {
1532 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
1533 PetscReal a, PetscReal aa, Mat A, Mat B,
1534 void *ctx) {
1535 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
1536 };
1537 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
1538 }
1539 CHKERR KSPSetOperators(ksp, A, P);
1540
1541 auto set_ops = [&]() {
1543 auto pip_mng = mField.getInterface<PipelineManager>();
1544
1545#ifndef ADD_CONTACT
1546 // Boundary
1547 pip_mng->getOpBoundaryLhsPipeline().push_front(
1549 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1550
1551 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1552
1553 ));
1554 // Domain
1555 pip_mng->getOpDomainLhsPipeline().push_front(
1557 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1558
1559 {"EP", "TAU"}, {nullptr, nullptr}, aoSchur, S, false, false
1560
1561 ));
1562#else
1563
1564 double eps_stab = 1e-4;
1565 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-eps_stab", &eps_stab,
1566 PETSC_NULL);
1567
1570 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1571
1572 // Boundary
1573 pip_mng->getOpBoundaryLhsPipeline().push_front(
1575 pip_mng->getOpBoundaryLhsPipeline().push_back(
1576 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
1577 return eps_stab;
1578 }));
1579 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
1580
1581 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1582 false, false
1583
1584 ));
1585 // Domain
1586 pip_mng->getOpDomainLhsPipeline().push_front(
1588 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
1589
1590 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr}, aoSchur, S,
1591 false, false
1592
1593 ));
1594#endif // ADD_CONTACT
1596 };
1597
1598 auto set_assemble_elems = [&]() {
1600 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1601 schur_asmb_pre_proc->preProcessHook = [this]() {
1603 CHKERR MatZeroEntries(S);
1604 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
1606 };
1607 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1608
1609 schur_asmb_post_proc->postProcessHook = [this, schur_asmb_post_proc]() {
1611 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
1612
1613 // Apply essential constrains to Schur complement
1614 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1615 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1617 mField, schur_asmb_post_proc, 1, S, aoSchur)();
1618
1620 };
1621 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1622 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1623 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1625 };
1626
1627 auto set_pc = [&]() {
1629 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
1630 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1632 };
1633
1634 auto set_diagonal_pc = [&]() {
1636 KSP *subksp;
1637 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULL, &subksp);
1638 auto get_pc = [](auto ksp) {
1639 PC pc_raw;
1640 CHKERR KSPGetPC(ksp, &pc_raw);
1641 return SmartPetscObj<PC>(pc_raw,
1642 true); // bump reference
1643 };
1644 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
1645 CHKERR PetscFree(subksp);
1647 };
1648
1649 CHKERR set_ops();
1650 CHKERR set_pc();
1651 CHKERR set_assemble_elems();
1652
1653 CHKERR TSSetUp(solver);
1654 CHKERR KSPSetUp(ksp);
1655 CHKERR set_diagonal_pc();
1656
1657 } else {
1658 pip_mng->getOpBoundaryLhsPipeline().push_front(
1660 pip_mng->getOpBoundaryLhsPipeline().push_back(
1661 createOpSchurAssembleEnd({}, {}));
1662 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
1663 pip_mng->getOpDomainLhsPipeline().push_back(
1664 createOpSchurAssembleEnd({}, {}));
1665 }
1666
1667 // fieldSplitIS.reset();
1668 // aoSchur.reset();
1670}
1671
1672boost::shared_ptr<SetUpSchur>
1674 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
1675 SmartPetscObj<AO> ao_up) {
1676 return boost::shared_ptr<SetUpSchur>(
1677 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
1678}
1679
1680namespace PlasticOps {
1681
1683 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1684 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1686 CHKERR MoFEM::AddHOOps<2, 3, 3>::add(pipeline, spaces, geom_field_name);
1688}
1689
1691 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1692 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1694 CHKERR MoFEM::AddHOOps<1, 2, 2>::add(pipeline, spaces, geom_field_name);
1696}
1697
1698template <int FE_DIM, int PROBLEM_DIM, int SPACE_DIM>
1700scaleL2(boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1701 std::string geom_field_name) {
1703
1704 auto jac_ptr = boost::make_shared<MatrixDouble>();
1705 auto det_ptr = boost::make_shared<VectorDouble>();
1707 geom_field_name, jac_ptr));
1708 pipeline.push_back(new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, nullptr));
1709
1710 auto scale_ptr = boost::make_shared<double>(1.);
1712 Example::meshVolumeAndCount[1]; // average volume of elements
1713 using OP = ForcesAndSourcesCore::UserDataOperator;
1714 auto op_scale = new OP(NOSPACE, OP::OPSPACE);
1715 op_scale->doWorkRhsHook = [scale_ptr, det_ptr,
1716 scale](DataOperator *base_op_ptr, int, EntityType,
1718 *scale_ptr = scale / det_ptr->size(); // distribute average element size
1719 // over integrartion points
1720 return 0;
1721 };
1722 pipeline.push_back(op_scale);
1723
1724 pipeline.push_back(
1725 new OpScaleBaseBySpaceInverseOfMeasure(L2, det_ptr, scale_ptr));
1726
1728}
1729
1731 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1732 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1734
1735 constexpr bool scale_l2 = false;
1736 if (scale_l2) {
1737 CHKERR scaleL2<3, 3, 3>(pipeline, geom_field_name);
1738 }
1739 CHKERR MoFEM::AddHOOps<3, 3, 3>::add(pipeline, spaces, geom_field_name,
1740 nullptr, nullptr, nullptr);
1742}
1743
1745 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1746 std::vector<FieldSpace> spaces, std::string geom_field_name) {
1748 constexpr bool scale_l2 = false;
1749 if (scale_l2) {
1750 CHKERR scaleL2<2, 2, 2>(pipeline, geom_field_name);
1751 }
1752 CHKERR MoFEM::AddHOOps<2, 2, 2>::add(pipeline, spaces, geom_field_name,
1753 nullptr, nullptr, nullptr);
1755}
1756
1757} // namespace PlasticOps
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
constexpr double a
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
Kronecker Delta class symmetric.
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
@ ROW
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
Definition definitions.h:60
@ 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, 1 > 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:497
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:456
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:586
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1099
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1056
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
@ BLOCK_PRECONDITIONER_SCHUR
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
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
MoFEMErrorCode opFactoryDomainRhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
double cn_contact
Definition contact.cpp:100
MoFEMErrorCode opFactoryBoundaryToDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string fe_domain_name, std::string sigma, std::string u, std::string geom, ForcesAndSourcesCore::RuleHookFun rule, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryBoundaryRhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
MoFEMErrorCode opFactoryBoundaryLhs(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string sigma, std::string u, bool is_axisymmetric=false)
constexpr double eps
Definition HenckyOps.hpp:13
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
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:1056
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:165
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1141
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:2186
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *snes_ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:232
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:2223
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.
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1157
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:511
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create a Mat Diag Blocks object.
Definition Schur.cpp:1009
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:1944
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1562
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1127
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1083
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:2181
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1076
auto createCommonPlasticOps(MoFEM::Interface &m_field, std::string block_name, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string u, std::string ep, std::string tau, double scale, Sev sev)
MoFEMErrorCode opFactoryDomainReactions(MoFEM::Interface &m_field, std::string block_name, Pip &pip, std::string u, std::string ep, std::string tau)
MoFEMErrorCode opFactoryDomainRhs(MoFEM::Interface &m_field, std::string block_name, Pip &pip, std::string u, std::string ep, std::string tau)
MoFEMErrorCode scaleL2(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string geom_field_name)
Definition plastic.cpp:1700
MoFEMErrorCode opFactoryDomainLhs(MoFEM::Interface &m_field, std::string block_name, Pip &pip, std::string u, std::string ep, std::string tau)
constexpr AssemblyType A
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
double young_modulus
Young modulus.
Definition plastic.cpp:121
constexpr AssemblyType AT
Definition plastic.cpp:44
double C1_k
Kinematic hardening.
Definition plastic.cpp:129
double Qinf
Saturation yield stress.
Definition plastic.cpp:127
constexpr IntegrationType IT
Definition plastic.cpp:47
static char help[]
[TestOperators]
Definition plastic.cpp:1388
double rho
Definition plastic.cpp:140
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool is_quasi_static
Definition plastic.cpp:139
double alpha_damping
Definition plastic.cpp:141
constexpr int SPACE_DIM
Definition plastic.cpp:40
double visH
Viscous hardening.
Definition plastic.cpp:125
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:122
auto kinematic_hardening(FTensor::Tensor2_symmetric< T, DIM > &t_plastic_strain, double C1_k)
Definition plastic.cpp:91
PetscBool set_timer
Set timer.
Definition plastic.cpp:117
double iso_hardening_dtau(double tau, double H, double Qinf, double b_iso)
Definition plastic.cpp:77
double scale
Definition plastic.cpp:119
constexpr auto size_symm
Definition plastic.cpp:42
double zeta
Viscous hardening.
Definition plastic.cpp:126
double H
Hardening.
Definition plastic.cpp:124
int tau_order
Order of tau files.
Definition plastic.cpp:135
double iso_hardening_exp(double tau, double b_iso)
Definition plastic.cpp:63
double cn0
Definition plastic.cpp:131
int order
Order displacement.
Definition plastic.cpp:134
double b_iso
Saturation exponent.
Definition plastic.cpp:128
PetscBool is_large_strains
Large strains.
Definition plastic.cpp:116
int geom_order
Order if fixed.
Definition plastic.cpp:137
double sigmaY
Yield stress.
Definition plastic.cpp:123
double iso_hardening(double tau, double H, double Qinf, double b_iso, double sigmaY)
Definition plastic.cpp:72
auto kinematic_hardening_dplastic_strain(double C1_k)
Definition plastic.cpp:105
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
int ep_order
Order of ep files.
Definition plastic.cpp:136
double cn1
Definition plastic.cpp:132
constexpr FieldSpace CONTACT_SPACE
Definition plastic.cpp:52
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:240
[Example]
Definition plastic.cpp:213
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition plastic.cpp:236
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition plastic.cpp:234
MoFEMErrorCode testOperators()
[Solve]
Definition plastic.cpp:1285
MoFEMErrorCode tsSolve()
Definition plastic.cpp:812
FieldApproximationBase base
Definition plot_base.cpp:68
MoFEMErrorCode createCommonData()
[Set up problem]
Definition plastic.cpp:476
static std::array< double, 2 > meshVolumeAndCount
Definition plastic.cpp:220
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition plastic.cpp:235
Example(MoFEM::Interface &m_field)
Definition plastic.cpp:215
MoFEMErrorCode OPs()
[Boundary condition]
Definition plastic.cpp:628
MoFEMErrorCode runProblem()
[Run problem]
Definition plastic.cpp:253
MoFEM::Interface & mField
Definition plastic.cpp:223
MoFEMErrorCode setupProblem()
[Run problem]
Definition plastic.cpp:272
MoFEMErrorCode bC()
[Create common data]
Definition plastic.cpp:584
boost::shared_ptr< DomainEle > reactionFe
Definition plastic.cpp:232
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
Definition BcManager.hpp:25
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:112
base operator to do operations at Gauss Pt. level
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:76
Data on single entity (This is passed as argument to DataOperator::doWork)
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Class (Function) to calculate residual side diagonal.
Definition Essential.hpp:49
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.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Get field gradients at integration pts for scalar filed rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Get values at integration pts for tensor filed rank 1, i.e. vector field.
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...
PipelineManager interface.
MoFEM::VolumeElementForcesAndSourcesCore VolEle
boost::shared_ptr< FEMethod > & getDomainLhsFE()
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
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
[Push operators to pipeline]
SetUpSchur()=default
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
virtual MoFEMErrorCode setUp(TS solver)=0
SmartPetscObj< DM > subDM
field split sub dm
Definition plastic.cpp:1485
SmartPetscObj< Mat > S
SmartPetscObj< AO > aoSchur
Definition plastic.cpp:1487
SetUpSchurImpl(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
Definition plastic.cpp:1464
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition plastic.cpp:1486
virtual ~SetUpSchurImpl()
Definition plastic.cpp:1475
MoFEMErrorCode postProc()
MoFEMErrorCode preProc()
MoFEM::Interface & mField
constexpr AssemblyType AT
VolEle::UserDataOperator VolOp