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// #define 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::SCHUR
46 : AssemblyType::PETSC; //< selected assembly type
48 IntegrationType::GAUSS; //< selected integration type
49
53
62
63#ifdef ADD_CONTACT
64//! [Specialisation for assembly]
65
66// Assemble to A matrix, by default, however, some terms are assembled only to
67// preconditioning.
68
69template <>
73 const EntitiesFieldData::EntData &row_data,
74 const EntitiesFieldData::EntData &col_data, MatrixDouble &m) {
75 return MatSetValues<AssemblyTypeSelector<AT>>(
76 op_ptr->getKSPA(), row_data, col_data, m, ADD_VALUES);
77 };
78
79template <>
83 const EntitiesFieldData::EntData &row_data,
84 const EntitiesFieldData::EntData &col_data, MatrixDouble &m) {
85 return MatSetValues<AssemblyTypeSelector<AT>>(
86 op_ptr->getKSPA(), row_data, col_data, m, ADD_VALUES);
87 };
88
89/**
90 * @brief Element used to specialise assembly
91 *
92 */
93struct BoundaryEleOpStab : public BoundaryEleOp {
94 using BoundaryEleOp::BoundaryEleOp;
95};
96
97/**
98 * @brief Specialise assembly for Stabilised matrix
99 *
100 * @tparam
101 */
102template <>
106 const EntitiesFieldData::EntData &row_data,
107 const EntitiesFieldData::EntData &col_data, MatrixDouble &m) {
108 return MatSetValues<AssemblyTypeSelector<AT>>(
109 op_ptr->getKSPB(), row_data, col_data, m, ADD_VALUES);
110 };
111//! [Specialisation for assembly]
112#endif // ADD_CONTACT
113
114inline double iso_hardening_exp(double tau, double b_iso) {
115 return std::exp(
116 std::max(static_cast<double>(std::numeric_limits<float>::min_exponent10),
117 -b_iso * tau));
118}
119
120/**
121 * Isotropic hardening
122 */
123inline double iso_hardening(double tau, double H, double Qinf, double b_iso,
124 double sigmaY) {
125 return H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso)) + sigmaY;
126}
127
128inline double iso_hardening_dtau(double tau, double H, double Qinf,
129 double b_iso) {
130 auto r = [&](auto tau) {
131 return H + Qinf * b_iso * iso_hardening_exp(tau, b_iso);
132 };
133 constexpr double eps = 1e-12;
134 return std::max(r(tau), eps * r(0));
135}
136
137/**
138 * Kinematic hardening
139 */
140template <typename T, int DIM>
141inline auto
143 double C1_k) {
147 t_alpha(i, j) = C1_k * t_plastic_strain(i, j);
148 return t_alpha;
149}
150
151template <int DIM>
159 t_diff(i, j, k, l) = C1_k * (t_kd(i, k) ^ t_kd(j, l)) / 4.;
160 return t_diff;
161}
162
163PetscBool is_large_strains = PETSC_TRUE; ///< Large strains
164PetscBool set_timer = PETSC_FALSE; ///< Set timer
165
166double scale = 1.;
167
168double young_modulus = 206913; ///< Young modulus
169double poisson_ratio = 0.29; ///< Poisson ratio
170double sigmaY = 450; ///< Yield stress
171double H = 129; ///< Hardening
172double visH = 0; ///< Viscous hardening
173double zeta = 5e-2; ///< Viscous hardening
174double Qinf = 265; ///< Saturation yield stress
175double b_iso = 16.93; ///< Saturation exponent
176double C1_k = 0; ///< Kinematic hardening
177
178double cn0 = 1;
179double cn1 = 1;
180
181int order = 2; ///< Order displacement
182int tau_order = order - 2; ///< Order of tau files
183int ep_order = order - 1; ///< Order of ep files
184int geom_order = 2; ///< Order if fixed.
185
186PetscBool is_quasi_static = PETSC_TRUE;
187double rho = 0.0;
188double alpha_damping = 0;
189
190#include <HenckyOps.hpp>
191#include <PlasticOps.hpp>
192#include <PlasticNaturalBCs.hpp>
193
194#ifdef ADD_CONTACT
195#ifdef PYTHON_SFD
196#include <boost/python.hpp>
197#include <boost/python/def.hpp>
198namespace bp = boost::python;
199#endif
200
201namespace ContactOps {
202
203double cn_contact = 0.1;
204
205}; // namespace ContactOps
206
207#include <ContactOps.hpp>
208#endif // ADD_CONTACT
209
219
220using namespace PlasticOps;
221using namespace HenckyOps;
222struct Example {
223
224 Example(MoFEM::Interface &m_field) : mField(m_field) {}
225
227
228private:
230
236
237 boost::shared_ptr<DomainEle> reactionFe;
238
239 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
240 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
241 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
242
245 double getScale(const double time) {
246 return scale * MoFEM::TimeScale::getScale(time);
247 };
248 };
249
250#ifdef ADD_CONTACT
251#ifdef PYTHON_SFD
252 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
253#endif
254#endif // ADD_CONTACT
255};
256
257//! [Run problem]
262 CHKERR bC();
263 CHKERR OPs();
264 CHKERR tsSolve();
266}
267//! [Run problem]
268
269//! [Set up problem]
273
274 Range domain_ents;
275 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
276 true);
277 auto get_ents_by_dim = [&](const auto dim) {
278 if (dim == SPACE_DIM) {
279 return domain_ents;
280 } else {
281 Range ents;
282 if (dim == 0)
283 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
284 else
285 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
286 return ents;
287 }
288 };
289
290 auto get_base = [&]() {
291 auto domain_ents = get_ents_by_dim(SPACE_DIM);
292 if (domain_ents.empty())
293 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
294 const auto type = type_from_handle(domain_ents[0]);
295 switch (type) {
296 case MBQUAD:
298 case MBHEX:
300 case MBTRI:
302 case MBTET:
304 default:
305 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
306 }
307 return NOBASE;
308 };
309
310 const auto base = get_base();
311 MOFEM_LOG("PLASTICITY", Sev::inform)
312 << "Base " << ApproximationBaseNames[base];
313
314 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
315 CHKERR simple->addDomainField("EP", L2, base, size_symm);
316 CHKERR simple->addDomainField("TAU", L2, base, 1);
317 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
318
319 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
320
321 PetscBool order_edge = PETSC_FALSE;
322 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_edge", &order_edge,
323 PETSC_NULL);
324 PetscBool order_face = PETSC_FALSE;
325 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_face", &order_face,
326 PETSC_NULL);
327 PetscBool order_volume = PETSC_FALSE;
328 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-order_volume", &order_volume,
329 PETSC_NULL);
330
331 if (order_edge || order_face || order_volume) {
332
333 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order edge " << order_edge
334 ? "true"
335 : "false";
336 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order face " << order_face
337 ? "true"
338 : "false";
339 MOFEM_LOG("PLASTICITY", Sev::inform) << "Order volume " << order_volume
340 ? "true"
341 : "false";
342
343 auto ents = get_ents_by_dim(0);
344 if (order_edge)
345 ents.merge(get_ents_by_dim(1));
346 if (order_face)
347 ents.merge(get_ents_by_dim(2));
348 if (order_volume)
349 ents.merge(get_ents_by_dim(3));
350 CHKERR simple->setFieldOrder("U", order, &ents);
351 } else {
352 CHKERR simple->setFieldOrder("U", order);
353 }
354 CHKERR simple->setFieldOrder("EP", ep_order);
355 CHKERR simple->setFieldOrder("TAU", tau_order);
356
357 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
358
359#ifdef ADD_CONTACT
360 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
361 SPACE_DIM);
362 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
363 SPACE_DIM);
364
365 auto get_skin = [&]() {
366 Range body_ents;
367 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
368 Skinner skin(&mField.get_moab());
369 Range skin_ents;
370 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
371 return skin_ents;
372 };
373
374 auto filter_blocks = [&](auto skin) {
375 Range contact_range;
376 for (auto m :
378
379 (boost::format("%s(.*)") % "CONTACT").str()
380
381 ))
382
383 ) {
384 MOFEM_LOG("CONTACT", Sev::inform)
385 << "Find contact block set: " << m->getName();
386 auto meshset = m->getMeshset();
387 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM - 1,
388 contact_range, true);
389
390 MOFEM_LOG("SYNC", Sev::inform)
391 << "Nb entities in contact surface: " << contact_range.size();
393 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
394 contact_range);
395 skin = intersect(skin, contact_range);
396 }
397 return skin;
398 };
399
400 auto filter_true_skin = [&](auto skin) {
401 Range boundary_ents;
402 ParallelComm *pcomm =
403 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
404 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
405 PSTATUS_NOT, -1, &boundary_ents);
406 return boundary_ents;
407 };
408
409 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
410 CHKERR simple->setFieldOrder("SIGMA", 0);
411 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
412#endif
413
414 CHKERR simple->setUp();
415 CHKERR simple->addFieldToEmptyFieldBlocks("U", "TAU");
416
417 auto project_ho_geometry = [&]() {
418 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
419 return mField.loop_dofs("GEOMETRY", ent_method);
420 };
421 CHKERR project_ho_geometry();
422
424}
425//! [Set up problem]
426
427//! [Create common data]
430
431 auto get_command_line_parameters = [&]() {
433
434 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-scale", &scale, PETSC_NULL);
435 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-young_modulus",
436 &young_modulus, PETSC_NULL);
437 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-poisson_ratio",
438 &poisson_ratio, PETSC_NULL);
439 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-hardening", &H, PETSC_NULL);
440 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-hardening_viscous", &visH,
441 PETSC_NULL);
442 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-yield_stress", &sigmaY,
443 PETSC_NULL);
444 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn0", &cn0, PETSC_NULL);
445 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn1", &cn1, PETSC_NULL);
446 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-zeta", &zeta, PETSC_NULL);
447 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-Qinf", &Qinf, PETSC_NULL);
448 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-b_iso", &b_iso, PETSC_NULL);
449 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-C1_k", &C1_k, PETSC_NULL);
450 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-large_strains",
451 &is_large_strains, PETSC_NULL);
452 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-set_timer", &set_timer,
453 PETSC_NULL);
454
455 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &order, PETSC_NULL);
456 PetscBool tau_order_is_set; ///< true if tau order is set
457 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-tau_order", &tau_order,
458 &tau_order_is_set);
459 PetscBool ep_order_is_set; ///< true if tau order is set
460 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-ep_order", &ep_order,
461 &ep_order_is_set);
462 CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-geom_order", &geom_order,
463 PETSC_NULL);
464
465 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-rho", &rho, PETSC_NULL);
466 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-alpha_damping",
467 &alpha_damping, PETSC_NULL);
468
469 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
470 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
471 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
472 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
473 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
474 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
475 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
476 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
477 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
478 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
479 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
480
481 if (tau_order_is_set == PETSC_FALSE)
482 tau_order = order - 2;
483 if (ep_order_is_set == PETSC_FALSE)
484 ep_order = order - 1;
485
486 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
487 MOFEM_LOG("PLASTICITY", Sev::inform)
488 << "Ep approximation order " << ep_order;
489 MOFEM_LOG("PLASTICITY", Sev::inform)
490 << "Tau approximation order " << tau_order;
491 MOFEM_LOG("PLASTICITY", Sev::inform)
492 << "Geometry approximation order " << geom_order;
493
494 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
495 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
496
497 PetscBool is_scale = PETSC_TRUE;
498 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-is_scale", &is_scale,
499 PETSC_NULL);
500 if (is_scale) {
502 }
503
504 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
505
506#ifdef ADD_CONTACT
507 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-cn_contact",
508 &ContactOps::cn_contact, PETSC_NULL);
509 MOFEM_LOG("CONTACT", Sev::inform)
510 << "cn_contact " << ContactOps::cn_contact;
511#endif // ADD_CONTACT
512
513 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-quasi_static",
514 &is_quasi_static, PETSC_NULL);
515 MOFEM_LOG("PLASTICITY", Sev::inform)
516 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
517
519 };
520
521 CHKERR get_command_line_parameters();
522
523#ifdef ADD_CONTACT
524#ifdef PYTHON_SFD
525 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
526 CHKERR sdfPythonPtr->sdfInit("sdf.py");
527 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
528#endif
529#endif // ADD_CONTACT
530
532}
533//! [Create common data]
534
535//! [Boundary condition]
538
540 auto bc_mng = mField.getInterface<BcManager>();
541 auto prb_mng = mField.getInterface<ProblemsManager>();
542
543 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
544 "U", 0, 0);
545 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
546 "U", 1, 1);
547 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
548 "U", 2, 2);
549 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
550 "REMOVE_ALL", "U", 0, 3);
551
552#ifdef ADD_CONTACT
553 for (auto b : {"FIX_X", "REMOVE_X"})
554 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
555 "SIGMA", 0, 0, false, true);
556 for (auto b : {"FIX_Y", "REMOVE_Y"})
557 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
558 "SIGMA", 1, 1, false, true);
559 for (auto b : {"FIX_Z", "REMOVE_Z"})
560 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
561 "SIGMA", 2, 2, false, true);
562 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
563 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
564 "SIGMA", 0, 3, false, true);
565 CHKERR bc_mng->removeBlockDOFsOnEntities(
566 simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
567#endif
568
569 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
570 simple->getProblemName(), "U");
571
572 auto &bc_map = bc_mng->getBcMapByBlockName();
573 for (auto bc : bc_map)
574 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
575
577}
578//! [Boundary condition]
579
580//! [Push operators to pipeline]
583 auto pip_mng = mField.getInterface<PipelineManager>();
585 auto bc_mng = mField.getInterface<BcManager>();
586
587 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
588
589 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order - 1; };
590
591 auto add_boundary_ops_lhs_mechanical = [&](auto &pip) {
593
595 "GEOMETRY");
596 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
597
598 // Add Natural BCs to LHS
600 pip, mField, "U", Sev::inform);
601
602#ifdef ADD_CONTACT
603 CHKERR
604 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, GAUSS, BoundaryEleOp>(
605 pip, "SIGMA", "U");
606 CHKERR
607 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
608 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
609 vol_rule);
610#endif // ADD_CONTACT
611
613 };
614
615 auto add_boundary_ops_rhs_mechanical = [&](auto &pip) {
617
619 "GEOMETRY");
620 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
621
622 // Add Natural BCs to RHS
624 pip, mField, "U", {boost::make_shared<ScaledTimeScale>()}, Sev::inform);
625
626#ifdef ADD_CONTACT
627 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
628 pip, "SIGMA", "U");
629#endif // ADD_CONTACT
630
632 };
633
634 auto add_domain_ops_lhs = [this](auto &pip) {
637 "GEOMETRY");
638
639 if (is_quasi_static == PETSC_FALSE) {
640
641 //! [Only used for dynamics]
644 //! [Only used for dynamics]
645
646 auto get_inertia_and_mass_damping = [this](const double, const double,
647 const double) {
648 auto *pip = mField.getInterface<PipelineManager>();
649 auto &fe_domain_lhs = pip->getDomainLhsFE();
650 return (rho / scale) * fe_domain_lhs->ts_aa +
651 (alpha_damping / scale) * fe_domain_lhs->ts_a;
652 };
653 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
654 }
655
656 CHKERR PlasticOps::opFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
657 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
658
660 };
661
662 auto add_domain_ops_rhs = [this](auto &pip) {
664
666 "GEOMETRY");
667
669 pip, mField, "U",
670 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
671 Sev::inform);
672
673 // only in case of dynamics
674 if (is_quasi_static == PETSC_FALSE) {
675
676 //! [Only used for dynamics]
679 //! [Only used for dynamics]
680
681 auto mat_acceleration = boost::make_shared<MatrixDouble>();
683 "U", mat_acceleration));
684 pip.push_back(
685 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
686 return rho / scale;
687 }));
688 if (alpha_damping > 0) {
689 auto mat_velocity = boost::make_shared<MatrixDouble>();
690 pip.push_back(
691 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
692 pip.push_back(
693 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
694 return alpha_damping / scale;
695 }));
696 }
697 }
698
699 CHKERR PlasticOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
700 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
701
702#ifdef ADD_CONTACT
703 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
704 pip, "SIGMA", "U");
705#endif // ADD_CONTACT
706
708 };
709
710 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
711 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
712
713 // Boundary
714 CHKERR add_boundary_ops_lhs_mechanical(pip_mng->getOpBoundaryLhsPipeline());
715 CHKERR add_boundary_ops_rhs_mechanical(pip_mng->getOpBoundaryRhsPipeline());
716
717 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
718 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
719
720 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
721 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
722
723 auto create_reaction_pipeline = [&](auto &pip) {
726 "GEOMETRY");
727 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
728 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
730 };
731
732 reactionFe = boost::make_shared<DomainEle>(mField);
733 reactionFe->getRuleHook = vol_rule;
734 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
735 reactionFe->postProcessHook =
737
739}
740//! [Push operators to pipeline]
741
742//! [Solve]
744
745 /**
746 * @brief Create data structure for handling Schur complement
747 *
748 * @param m_field
749 * @param sub_dm Schur complement sub dm
750 * @param field_split_it IS of Schur block
751 * @param ao_map AO map from sub dm to main problem
752 * @return boost::shared_ptr<SetUpSchur>
753 */
754 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
755
756 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
757 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
758
759 );
760 virtual MoFEMErrorCode setUp(TS solver) = 0;
761
762protected:
763 SetUpSchur() = default;
764};
765
768
771 ISManager *is_manager = mField.getInterface<ISManager>();
772
773 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
774
775 auto set_section_monitor = [&](auto solver) {
777 SNES snes;
778 CHKERR TSGetSNES(solver, &snes);
779 CHKERR SNESMonitorSet(snes,
780 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
782 (void *)(snes_ctx_ptr.get()), nullptr);
784 };
785
786 auto create_post_process_elements = [&]() {
787 auto pp_fe = boost::make_shared<PostProcEle>(mField);
788 auto &pip = pp_fe->getOpPtrVector();
789
790 auto push_vol_ops = [this](auto &pip) {
792 "GEOMETRY");
793
794 auto [common_plastic_ptr, common_henky_ptr] =
795 PlasticOps::createCommonPlasticOps<SPACE_DIM, IT, DomainEleOp>(
796 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU", 1., Sev::inform);
797
798 if (common_henky_ptr) {
799 if (common_plastic_ptr->mGradPtr != common_henky_ptr->matGradPtr)
800 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
801 }
802
803 return std::make_pair(common_plastic_ptr, common_henky_ptr);
804 };
805
806 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
808
809 auto &pip = pp_fe->getOpPtrVector();
810
811 auto [common_plastic_ptr, common_henky_ptr] = p;
812
814
815 auto x_ptr = boost::make_shared<MatrixDouble>();
816 pip.push_back(
817 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
818 auto u_ptr = boost::make_shared<MatrixDouble>();
819 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
820
821 if (is_large_strains) {
822
823 pip.push_back(
824
825 new OpPPMap(
826
827 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
828
829 {{"PLASTIC_SURFACE",
830 common_plastic_ptr->getPlasticSurfacePtr()},
831 {"PLASTIC_MULTIPLIER",
832 common_plastic_ptr->getPlasticTauPtr()}},
833
834 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
835
836 {{"GRAD", common_henky_ptr->matGradPtr},
837 {"FIRST_PIOLA", common_henky_ptr->getMatFirstPiolaStress()}},
838
839 {{"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
840 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
841
842 )
843
844 );
845
846 } else {
847
848 pip.push_back(
849
850 new OpPPMap(
851
852 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
853
854 {{"PLASTIC_SURFACE",
855 common_plastic_ptr->getPlasticSurfacePtr()},
856 {"PLASTIC_MULTIPLIER",
857 common_plastic_ptr->getPlasticTauPtr()}},
858
859 {{"U", u_ptr}, {"GEOMETRY", x_ptr}},
860
861 {},
862
863 {{"STRAIN", common_plastic_ptr->mStrainPtr},
864 {"STRESS", common_plastic_ptr->mStressPtr},
865 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
866 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
867
868 )
869
870 );
871 }
872
874 };
875
876 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops]() {
877 PetscBool post_proc_vol = PETSC_FALSE;
878 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_vol",
879 &post_proc_vol, PETSC_NULL);
880 if (post_proc_vol == PETSC_FALSE)
881 return boost::shared_ptr<PostProcEle>();
882 auto pp_fe = boost::make_shared<PostProcEle>(mField);
884 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
885 "push_vol_post_proc_ops");
886 return pp_fe;
887 };
888
889 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops]() {
890 PetscBool post_proc_skin = PETSC_TRUE;
891 CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-post_proc_skin",
892 &post_proc_skin, PETSC_NULL);
893 if (post_proc_skin == PETSC_FALSE)
894 return boost::shared_ptr<SkinPostProcEle>();
895
896 auto simple = mField.getInterface<Simple>();
897 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
898 auto op_side = new OpLoopSide<SideEle>(
899 mField, simple->getDomainFEName(), SPACE_DIM, Sev::verbose);
900 pp_fe->getOpPtrVector().push_back(op_side);
901 CHK_MOAB_THROW(push_vol_post_proc_ops(
902 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
903 "push_vol_post_proc_ops");
904 return pp_fe;
905 };
906
907 return std::make_pair(vol_post_proc(), skin_post_proc());
908 };
909
910 auto scatter_create = [&](auto D, auto coeff) {
912 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
913 ROW, "U", coeff, coeff, is);
914 int loc_size;
915 CHKERR ISGetLocalSize(is, &loc_size);
916 Vec v;
917 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
918 VecScatter scatter;
919 CHKERR VecScatterCreate(D, is, v, PETSC_NULL, &scatter);
920 return std::make_tuple(SmartPetscObj<Vec>(v),
922 };
923
924 auto set_time_monitor = [&](auto dm, auto solver) {
926 boost::shared_ptr<Monitor> monitor_ptr(
927 new Monitor(dm, create_post_process_elements(), reactionFe, uXScatter,
928 uYScatter, uZScatter));
929 boost::shared_ptr<ForcesAndSourcesCore> null;
930 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
931 monitor_ptr, null, null);
933 };
934
935 auto set_schur_pc = [&](auto solver,
936 boost::shared_ptr<SetUpSchur> &schur_ptr) {
938
939 auto bc_mng = mField.getInterface<BcManager>();
940 auto name_prb = simple->getProblemName();
941
942 // create sub dm for Schur complement
943 auto create_sub_u_dm = [&](SmartPetscObj<DM> base_dm,
944 SmartPetscObj<DM> &dm_sub) {
946 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
947 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SUB_U");
948 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
949 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
950 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
951 for (auto f : {"U"}) {
954 }
955 CHKERR DMSetUp(dm_sub);
956
958 };
959
960 // Create nested (sub BC) Schur DM
961 if constexpr (AT == AssemblyType::SCHUR) {
962 SmartPetscObj<IS> is_epp;
963 CHKERR mField.getInterface<ISManager>()->isCreateProblemFieldAndRank(
964 simple->getProblemName(), ROW, "EP", 0, MAX_DOFS_ON_ENTITY, is_epp);
965 SmartPetscObj<IS> is_tau;
966 CHKERR mField.getInterface<ISManager>()->isCreateProblemFieldAndRank(
967 simple->getProblemName(), ROW, "TAU", 0, MAX_DOFS_ON_ENTITY, is_tau);
968
969 IS is_union_raw;
970 CHKERR ISExpand(is_epp, is_tau, &is_union_raw);
971 SmartPetscObj<IS> is_union(is_union_raw);
972
973#ifdef ADD_CONTACT
974 auto add_sigma_to_is = [&](auto is_union) {
975 SmartPetscObj<IS> is_union_sigma;
976 auto add_sigma_to_is_impl = [&]() {
978 SmartPetscObj<IS> is_sigma;
979 CHKERR mField.getInterface<ISManager>()->isCreateProblemFieldAndRank(
980 simple->getProblemName(), ROW, "SIGMA", 0, MAX_DOFS_ON_ENTITY,
981 is_sigma);
982 IS is_union_raw_sigma;
983 CHKERR ISExpand(is_union, is_sigma, &is_union_raw_sigma);
984 is_union_sigma = SmartPetscObj<IS>(is_union_raw_sigma);
986 };
987 CHK_THROW_MESSAGE(add_sigma_to_is_impl(), "Can not add sigma to IS");
988 return is_union_sigma;
989 };
990 is_union = add_sigma_to_is(is_union);
991#endif // ADD_CONTACT
992
993 SmartPetscObj<DM> dm_u_sub;
994 CHKERR create_sub_u_dm(simple->getDM(), dm_u_sub);
995
996 // Indices has to be map fro very to level, while assembling Schur
997 // complement.
998 auto is_up = getDMSubData(dm_u_sub)->getSmartRowIs();
999 auto ao_up = createAOMappingIS(is_up, PETSC_NULL);
1000 schur_ptr =
1001 SetUpSchur::createSetUpSchur(mField, dm_u_sub, is_union, ao_up);
1002 CHKERR schur_ptr->setUp(solver);
1003 }
1004
1006 };
1007
1008 auto dm = simple->getDM();
1009 auto D = createDMVector(dm);
1010 auto DD = vectorDuplicate(D);
1011 uXScatter = scatter_create(D, 0);
1012 uYScatter = scatter_create(D, 1);
1013 if constexpr (SPACE_DIM == 3)
1014 uZScatter = scatter_create(D, 2);
1015
1016 auto create_solver = [pip_mng]() {
1017 if (is_quasi_static == PETSC_TRUE)
1018 return pip_mng->createTSIM();
1019 else
1020 return pip_mng->createTSIM2();
1021 };
1022
1023 auto solver = create_solver();
1024
1025 auto active_pre_lhs = []() {
1027 std::fill(PlasticOps::CommonData::activityData.begin(),
1030 };
1031
1032 auto active_post_lhs = [&]() {
1034 auto get_iter = [&]() {
1035 SNES snes;
1036 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
1037 int iter;
1038 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
1039 "Can not get iter");
1040 return iter;
1041 };
1042
1043 auto iter = get_iter();
1044 if (iter >= 0) {
1045
1046 std::array<int, 5> activity_data;
1047 std::fill(activity_data.begin(), activity_data.end(), 0);
1048 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
1049 activity_data.data(), activity_data.size(), MPI_INT,
1050 MPI_SUM, mField.get_comm());
1051
1052 int &active_points = activity_data[0];
1053 int &avtive_full_elems = activity_data[1];
1054 int &avtive_elems = activity_data[2];
1055 int &nb_points = activity_data[3];
1056 int &nb_elements = activity_data[4];
1057
1058 if (nb_points) {
1059
1060 double proc_nb_points =
1061 100 * static_cast<double>(active_points) / nb_points;
1062 double proc_nb_active =
1063 100 * static_cast<double>(avtive_elems) / nb_elements;
1064 double proc_nb_full_active = 100;
1065 if (avtive_elems)
1066 proc_nb_full_active =
1067 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
1068
1069 MOFEM_LOG_C("PLASTICITY", Sev::inform,
1070 "Iter %d nb pts %d nb avtive pts %d (%3.3f\%) nb active "
1071 "elements %d "
1072 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
1073 iter, nb_points, active_points, proc_nb_points,
1074 avtive_elems, proc_nb_active, avtive_full_elems,
1075 proc_nb_full_active, iter);
1076 }
1077 }
1078
1080 };
1081
1082 auto add_active_dofs_elem = [&](auto dm) {
1084 auto fe_pre_proc = boost::make_shared<FEMethod>();
1085 fe_pre_proc->preProcessHook = active_pre_lhs;
1086 auto fe_post_proc = boost::make_shared<FEMethod>();
1087 fe_post_proc->postProcessHook = active_post_lhs;
1088 auto ts_ctx_ptr = getDMTsCtx(dm);
1089 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
1090 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
1092 };
1093
1094 auto set_essential_bc = [&](auto dm, auto solver) {
1096 // This is low level pushing finite elements (pipelines) to solver
1097
1098 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1099 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1100 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1101
1102 // Add boundary condition scaling
1103 auto disp_time_scale = boost::make_shared<TimeScale>();
1104
1105 auto get_bc_hook_rhs = [this, pre_proc_ptr, disp_time_scale]() {
1106 EssentialPreProc<DisplacementCubitBcData> hook(mField, pre_proc_ptr,
1107 {disp_time_scale}, false);
1108 return hook;
1109 };
1110 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1111
1112 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
1115 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
1117 mField, post_proc_rhs_ptr, 1.)();
1119 };
1120 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
1122 mField, post_proc_lhs_ptr, 1.);
1123 };
1124 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1125
1126 auto ts_ctx_ptr = getDMTsCtx(dm);
1127 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1128 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1129 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1130
1131 SNES snes;
1132 CHKERR TSGetSNES(solver, &snes);
1133 KSP ksp;
1134 CHKERR SNESGetKSP(snes, &ksp);
1135 PC pc;
1136 CHKERR KSPGetPC(ksp, &pc);
1137 PetscBool is_pcfs = PETSC_FALSE;
1138 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1139
1140 if (is_pcfs == PETSC_FALSE) {
1141 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1142 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1143 }
1145 };
1146
1147 if (is_quasi_static == PETSC_TRUE) {
1148 CHKERR TSSetSolution(solver, D);
1149 } else {
1150 CHKERR TS2SetSolution(solver, D, DD);
1151 }
1152
1153 CHKERR set_section_monitor(solver);
1154 CHKERR set_time_monitor(dm, solver);
1155 CHKERR TSSetFromOptions(solver);
1156 CHKERR TSSetUp(solver);
1157
1158 CHKERR add_active_dofs_elem(dm);
1159 boost::shared_ptr<SetUpSchur> schur_ptr;
1160 CHKERR set_schur_pc(solver, schur_ptr);
1161 CHKERR set_essential_bc(dm, solver);
1162
1163 MOFEM_LOG_CHANNEL("TIMER");
1164 MOFEM_LOG_TAG("TIMER", "timer");
1165 if (set_timer)
1166 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
1167 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
1168 CHKERR TSSetUp(solver);
1169 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
1170 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
1171 CHKERR TSSolve(solver, NULL);
1172 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
1173
1175}
1176//! [Solve]
1177
1178static char help[] = "...\n\n";
1179
1180int main(int argc, char *argv[]) {
1181
1182#ifdef ADD_CONTACT
1183#ifdef PYTHON_SFD
1184 Py_Initialize();
1185#endif
1186#endif // ADD_CONTACT
1187
1188 // Initialisation of MoFEM/PETSc and MOAB data structures
1189 const char param_file[] = "param_file.petsc";
1190 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
1191
1192 // Add logging channel for example
1193 auto core_log = logging::core::get();
1194 core_log->add_sink(
1196 core_log->add_sink(
1198 LogManager::setLog("PLASTICITY");
1199 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
1200
1201#ifdef ADD_CONTACT
1202 core_log->add_sink(
1204 LogManager::setLog("CONTACT");
1205 MOFEM_LOG_TAG("CONTACT", "Contact");
1206#endif // ADD_CONTACT
1207
1208 try {
1209
1210 //! [Register MoFEM discrete manager in PETSc]
1211 DMType dm_name = "DMMOFEM";
1212 CHKERR DMRegister_MoFEM(dm_name);
1213 //! [Register MoFEM discrete manager in PETSc
1214
1215 //! [Create MoAB]
1216 moab::Core mb_instance; ///< mesh database
1217 moab::Interface &moab = mb_instance; ///< mesh database interface
1218 //! [Create MoAB]
1219
1220 //! [Create MoFEM]
1221 MoFEM::Core core(moab); ///< finite element database
1222 MoFEM::Interface &m_field = core; ///< finite element database interface
1223 //! [Create MoFEM]
1224
1225 //! [Load mesh]
1226 Simple *simple = m_field.getInterface<Simple>();
1227 CHKERR simple->getOptions();
1228 CHKERR simple->loadFile();
1229 //! [Load mesh]
1230
1231 //! [Example]
1232 Example ex(m_field);
1233 CHKERR ex.runProblem();
1234 //! [Example]
1235 }
1237
1239
1240#ifdef ADD_CONTACT
1241#ifdef PYTHON_SFD
1242 if (Py_FinalizeEx() < 0) {
1243 exit(120);
1244 }
1245#endif
1246#endif // ADD_CONTACT
1247
1248 return 0;
1249}
1250
1251struct SetUpSchurImpl : public SetUpSchur {
1252
1254 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
1255 : SetUpSchur(), mField(m_field), subDM(sub_dm),
1256 fieldSplitIS(field_split_is), aoUp(ao_up) {
1257 if (S) {
1260 "Is expected that schur matrix is not allocated. This is "
1261 "possible only is PC is set up twice");
1262 }
1263 }
1265#ifdef ADD_CONTACT
1266 A.reset();
1267 P.reset();
1268#endif // ADD_CONTACT
1269 S.reset();
1270 }
1271
1272 MoFEMErrorCode setUp(TS solver);
1275
1276private:
1277#ifdef ADD_CONTACT
1280#endif // ADD_CONTACT
1282
1284 SmartPetscObj<DM> subDM; ///< field split sub dm
1285 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
1286 SmartPetscObj<AO> aoUp; ///> main DM to subDM
1287};
1288
1291 auto simple = mField.getInterface<Simple>();
1292 auto pip_mng = mField.getInterface<PipelineManager>();
1293
1294 SNES snes;
1295 CHKERR TSGetSNES(solver, &snes);
1296 KSP ksp;
1297 CHKERR SNESGetKSP(snes, &ksp);
1298 CHKERR KSPSetFromOptions(ksp);
1299
1300 PC pc;
1301 CHKERR KSPSetFromOptions(ksp);
1302 CHKERR KSPGetPC(ksp, &pc);
1303 PetscBool is_pcfs = PETSC_FALSE;
1304 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1305 if (is_pcfs) {
1306 if (S) {
1309 "Is expected that schur matrix is not allocated. This is "
1310 "possible only is PC is set up twice");
1311 }
1312
1313#ifdef ADD_CONTACT
1314 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1315 A = createDMMatrix(simple->getDM());
1316 P = matDuplicate(A, MAT_DO_NOT_COPY_VALUES);
1317 CHKERR TSSetIJacobian(solver, A, P, TsSetIJacobian, ts_ctx_ptr.get());
1318#endif // ADD_CONTACT
1320 CHKERR MatSetBlockSize(S, SPACE_DIM);
1321
1322 auto set_ops = [&]() {
1324 auto pip_mng = mField.getInterface<PipelineManager>();
1325
1326#ifndef ADD_CONTACT
1327 // Boundary
1328 pip_mng->getOpBoundaryLhsPipeline().push_front(
1329 new OpSchurAssembleBegin());
1330 pip_mng->getOpBoundaryLhsPipeline().push_back(
1332
1333 {"EP", "TAU"}, {nullptr, nullptr}, {SmartPetscObj<AO>(), aoUp},
1334 {SmartPetscObj<Mat>(), S}, {false, false}
1335
1336 ));
1337 // Domain
1338 pip_mng->getOpDomainLhsPipeline().push_front(new OpSchurAssembleBegin());
1339 pip_mng->getOpDomainLhsPipeline().push_back(
1341
1342 {"EP", "TAU"}, {nullptr, nullptr}, {SmartPetscObj<AO>(), aoUp},
1343 {SmartPetscObj<Mat>(), S}, {false, false}
1344
1345 ));
1346#else
1347
1348 double eps_stab = 1e-4;
1349 CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-eps_stab", &eps_stab,
1350 PETSC_NULL);
1351
1354 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
1355
1356 // Boundary
1357 pip_mng->getOpBoundaryLhsPipeline().push_front(
1358 new OpSchurAssembleBegin());
1359 pip_mng->getOpBoundaryLhsPipeline().push_back(
1360 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
1361 return eps_stab;
1362 }));
1363 pip_mng->getOpBoundaryLhsPipeline().push_back(
1365
1366 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr},
1369 {false, false, false}
1370
1371 ));
1372 // Domain
1373 pip_mng->getOpDomainLhsPipeline().push_front(new OpSchurAssembleBegin());
1374 pip_mng->getOpDomainLhsPipeline().push_back(
1376
1377 {"SIGMA", "EP", "TAU"}, {nullptr, nullptr, nullptr},
1380 {false, false, false}
1381
1382 ));
1383#endif // ADD_CONTACT
1385 };
1386
1387 auto set_assemble_elems = [&]() {
1389 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
1390 schur_asmb_pre_proc->preProcessHook = [this]() {
1392#ifdef ADD_CONTACT
1393 CHKERR MatZeroEntries(A);
1394 CHKERR MatZeroEntries(P);
1395#endif // ADD_CONTACT
1396 CHKERR MatZeroEntries(S);
1397 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
1399 };
1400 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
1401
1402 schur_asmb_post_proc->postProcessHook = [this, schur_asmb_post_proc]() {
1404 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
1405
1406#ifndef ADD_CONTACT
1408 mField, schur_asmb_post_proc, 1)();
1409#else // ADD_CONTACT
1410 CHKERR MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
1411 CHKERR MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
1412 // Apply essential constrains to A matrix
1414 mField, schur_asmb_post_proc, 1, A)();
1415 CHKERR MatAssemblyBegin(P, MAT_FINAL_ASSEMBLY);
1416 CHKERR MatAssemblyEnd(P, MAT_FINAL_ASSEMBLY);
1417 CHKERR MatAXPY(P, 1, A, SAME_NONZERO_PATTERN);
1418#endif // ADD_CONTACT
1419
1420 // Apply essential constrains to Schur complement
1421 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
1422 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
1424 mField, schur_asmb_post_proc, 1, S, aoUp)();
1425
1427 };
1428 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
1429 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
1430 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
1432 };
1433
1434 auto set_pc = [&]() {
1436 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
1437 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
1439 };
1440
1441 CHKERR set_ops();
1442 CHKERR set_pc();
1443 CHKERR set_assemble_elems();
1444
1445 } else {
1446 pip_mng->getOpBoundaryLhsPipeline().push_front(new OpSchurAssembleBegin());
1447 pip_mng->getOpBoundaryLhsPipeline().push_back(
1448 new OpSchurAssembleEnd<SCHUR_DGESV>({}, {}, {}, {}, {}));
1449 pip_mng->getOpDomainLhsPipeline().push_front(new OpSchurAssembleBegin());
1450 pip_mng->getOpDomainLhsPipeline().push_back(
1451 new OpSchurAssembleEnd<SCHUR_DGESV>({}, {}, {}, {}, {}));
1452 }
1453
1454 // we do not those anymore
1455 subDM.reset();
1456 fieldSplitIS.reset();
1457 // aoUp.reset();
1459}
1460
1461boost::shared_ptr<SetUpSchur>
1463 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
1464 SmartPetscObj<AO> ao_up) {
1465 return boost::shared_ptr<SetUpSchur>(
1466 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
1467}
static Index< 'p', 3 > p
std::string param_file
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Definition: LogManager.hpp:345
#define MOFEM_LOG_C(channel, severity, format,...)
Definition: LogManager.hpp:311
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition: acoustic.cpp:69
int main()
Definition: adol-c_atom.cpp:46
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Kronecker Delta class symmetric.
@ ROW
Definition: definitions.h:123
#define CATCH_ERRORS
Catch errors.
Definition: definitions.h:372
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
Definition: definitions.h:236
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
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.
Definition: definitions.h:595
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:447
FieldSpace
approximation spaces
Definition: definitions.h:82
@ L2
field with C-1 continuity
Definition: definitions.h:88
@ H1
continuous field
Definition: definitions.h:85
@ HCURL
field with continuous tangents
Definition: definitions.h:86
@ HDIV
field with continuous normal traction
Definition: definitions.h:87
#define MYPCOMM_INDEX
default communicator number PCOMM
Definition: definitions.h:215
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:346
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
Definition: definitions.h:576
@ MOFEM_NOT_FOUND
Definition: definitions.h:33
@ 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()
Definition: definitions.h:416
#define CHKERR
Inline error check.
Definition: definitions.h:535
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:440
constexpr int order
constexpr int SPACE_DIM
[Define dimension]
Definition: elastic.cpp:18
const int dim
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
FTensor::Index< 'm', SPACE_DIM > m
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:219
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition: DMMoFEM.cpp:483
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition: DMMoFEM.cpp:442
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition: DMMoFEM.cpp:242
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition: DMMoFEM.cpp:47
auto createDMVector(DM dm)
Get smart vector from DM.
Definition: DMMoFEM.hpp:1003
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition: DMMoFEM.cpp:275
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition: DMMoFEM.hpp:988
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
Definition: LogManager.cpp:389
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:308
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
Definition: LogManager.hpp:339
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
Definition: LogManager.hpp:284
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
FormsIntegrators< DomainEleOp >::Assembly< USER_ASSEMBLE >::LinearForm< GAUSS >::OpBaseTimesVector< 1, 3, 1 > OpInertiaForce
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
Definition: Templates.hpp:1779
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:1042
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobina in TS solver.
Definition: TsCtx.cpp:131
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition: DMMoFEM.hpp:1045
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:226
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:1061
auto createAOMappingIS(IS isapp, IS ispetsc)
Creates an application mapping using two index sets.
SmartPetscObj< Mat > matDuplicate(Mat mat, MatDuplicateOption op)
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition: DMMoFEM.hpp:1031
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
double young_modulus
Young modulus.
Definition: plastic.cpp:168
constexpr AssemblyType AT
Definition: plastic.cpp:44
double C1_k
Kinematic hardening.
Definition: plastic.cpp:176
double Qinf
Saturation yield stress.
Definition: plastic.cpp:174
constexpr IntegrationType IT
Definition: plastic.cpp:47
static char help[]
[Solve]
Definition: plastic.cpp:1178
double rho
Definition: plastic.cpp:187
#define EXECUTABLE_DIMENSION
Definition: plastic.cpp:13
PetscBool is_quasi_static
Definition: plastic.cpp:186
double alpha_damping
Definition: plastic.cpp:188
constexpr int SPACE_DIM
Definition: plastic.cpp:40
double visH
Viscous hardening.
Definition: plastic.cpp:172
double poisson_ratio
Poisson ratio.
Definition: plastic.cpp:169
auto kinematic_hardening(FTensor::Tensor2_symmetric< T, DIM > &t_plastic_strain, double C1_k)
Definition: plastic.cpp:142
PetscBool set_timer
Set timer.
Definition: plastic.cpp:164
double iso_hardening_dtau(double tau, double H, double Qinf, double b_iso)
Definition: plastic.cpp:128
double scale
Definition: plastic.cpp:166
constexpr auto size_symm
Definition: plastic.cpp:42
double zeta
Viscous hardening.
Definition: plastic.cpp:173
double H
Hardening.
Definition: plastic.cpp:171
int tau_order
Order of tau files.
Definition: plastic.cpp:182
double iso_hardening_exp(double tau, double b_iso)
Definition: plastic.cpp:114
double cn0
Definition: plastic.cpp:178
int order
Order displacement.
Definition: plastic.cpp:181
double b_iso
Saturation exponent.
Definition: plastic.cpp:175
PetscBool is_large_strains
Large strains.
Definition: plastic.cpp:163
int geom_order
Order if fixed.
Definition: plastic.cpp:184
double sigmaY
Yield stress.
Definition: plastic.cpp:170
double iso_hardening(double tau, double H, double Qinf, double b_iso, double sigmaY)
Definition: plastic.cpp:123
auto kinematic_hardening_dplastic_strain(double C1_k)
Definition: plastic.cpp:152
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition: plastic.cpp:61
int ep_order
Order of ep files.
Definition: plastic.cpp:183
double cn1
Definition: plastic.cpp:179
constexpr FieldSpace CONTACT_SPACE
Definition: plastic.cpp:52
FTensor::Index< 'm', 3 > m
Element used to specialise assembly.
Definition: contact.cpp:86
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 a given time.
Definition: plastic.cpp:245
[Example]
Definition: plastic.cpp:222
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition: plastic.cpp:241
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition: plastic.cpp:239
MoFEMErrorCode tsSolve()
Definition: plastic.cpp:766
FieldApproximationBase base
Definition: plot_base.cpp:68
MoFEMErrorCode createCommonData()
[Set up problem]
Definition: plastic.cpp:428
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition: plastic.cpp:240
Example(MoFEM::Interface &m_field)
Definition: plastic.cpp:224
MoFEMErrorCode OPs()
[Boundary condition]
Definition: plastic.cpp:581
MoFEMErrorCode runProblem()
[Run problem]
Definition: plastic.cpp:258
MoFEM::Interface & mField
Definition: plastic.cpp:229
MoFEMErrorCode setupProblem()
[Run problem]
Definition: plastic.cpp:270
MoFEMErrorCode bC()
[Create common data]
Definition: plastic.cpp:536
boost::shared_ptr< DomainEle > reactionFe
Definition: plastic.cpp:237
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
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:47
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition: Essential.hpp:55
Class (Function) to enforce essential constrains.
Definition: Essential.hpp:39
Class (Function) to calculate residual side diagonal.
Definition: Essential.hpp:63
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.
Definition: LogManager.cpp:298
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Definition: LogManager.cpp:344
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition: Natural.hpp:65
boost::function< MoFEMErrorCode(ForcesAndSourcesCore::UserDataOperator *op_ptr, const EntitiesFieldData::EntData &row_data, const EntitiesFieldData::EntData &col_data, MatrixDouble &m)> MatSetValuesHook
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.
Clear Schur complement internal data.
Definition: Schur.hpp:22
Assemble Schur complement.
Definition: Schur.hpp:104
PipelineManager interface.
MoFEM::VolumeElementForcesAndSourcesCore VolEle
boost::shared_ptr< FEMethod > & getDomainLhsFE()
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEM::EdgeElementForcesAndSourcesCore EdgeEle
Problem manager is used to build and partition problems.
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)
TimeScale constructor.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface refernce to pointer of interface.
static std::array< int, 5 > activityData
Definition: PlasticOps.hpp:107
[Push operators to pipeline]
Definition: plastic.cpp:743
SetUpSchur()=default
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_it, SmartPetscObj< AO > ao_map)
Create data structure for handling Schur complement.
Definition: plastic.cpp:1462
virtual MoFEMErrorCode setUp(TS solver)=0
SmartPetscObj< Mat > A
Definition: contact.cpp:844
SmartPetscObj< DM > subDM
field split sub dm
Definition: plastic.cpp:1284
MoFEMErrorCode setUp(KSP solver)
SmartPetscObj< Mat > S
SmartPetscObj< Mat > P
SetUpSchurImpl(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
Definition: plastic.cpp:1253
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition: plastic.cpp:1285
virtual ~SetUpSchurImpl()
Definition: plastic.cpp:1264
MoFEMErrorCode postProc()
SmartPetscObj< AO > aoUp
MoFEMErrorCode preProc()
MoFEM::Interface & mField