v0.15.0
Loading...
Searching...
No Matches
thermoplastic.cpp
Go to the documentation of this file.
1/**
2 * \file thermoplastic.cpp
3 * \example thermoplastic.cpp
4 *
5 * Thermoplasticity 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#include <cstdlib>
22extern "C" {
23#include <phg-quadrule/quad.h>
24}
25
26using namespace MoFEM;
27
28template <int DIM> struct ElementsAndOps;
29
30template <> struct ElementsAndOps<2> {
36 static constexpr FieldSpace CONTACT_SPACE = HCURL;
37};
38
39template <> struct ElementsAndOps<3> {
45 static constexpr FieldSpace CONTACT_SPACE = HDIV;
46};
47
48constexpr int SPACE_DIM =
49 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
50constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
51
52constexpr bool IS_LARGE_STRAINS =
53 FINITE_DEFORMATION_FLAG; //< Flag to turn off/on geometric nonlinearities
54
55constexpr AssemblyType AT =
56 (SCHUR_ASSEMBLE) ? AssemblyType::BLOCK_SCHUR
57 : AssemblyType::PETSC; //< selected assembly type
59 IntegrationType::GAUSS; //< selected integration type
60
64
68using DomainEleOp = DomainEle::UserDataOperator;
70using BoundaryEleOp = BoundaryEle::UserDataOperator;
75
77
78using ScalerFunTwoArgs = boost::function<double(const double, const double)>;
80 boost::function<double(const double, const double, const double)>;
81
82inline double H_thermal(double H, double omega_h, double temp_0, double temp) {
83 return H * (1. - omega_h * (temp - temp_0));
84}
85
86inline double dH_thermal_dtemp(double H, double omega_h) {
87 return -H * omega_h;
88}
89
90inline double y_0_thermal(double sigmaY, double omega_0, double temp_0,
91 double temp) {
92 return sigmaY * (1. - omega_0 * (temp - temp_0));
93}
94
95inline double dy_0_thermal_dtemp(double sigmaY, double omega_0) {
96 return -sigmaY * omega_0;
97}
98
99inline double Qinf_thermal(double Qinf, double omega_h, double temp_0,
100 double temp) {
101 return Qinf * (1. - omega_h * (temp - temp_0));
102}
103
104inline double dQinf_thermal_dtemp(double Qinf, double omega_h) {
105 return -Qinf * omega_h;
106}
107
108inline double iso_hardening_exp(double tau, double b_iso) {
109 return std::exp(-b_iso * tau);
110}
111
112double exp_C = -6.284;
113double exp_D = -1.024;
114
115inline double temp_hat(double temp) {
116 double JC_ref_temp = 0.;
117 double JC_melt_temp = 1650.;
118
119 return (temp - JC_ref_temp) / (JC_melt_temp - JC_ref_temp);
120}
121
122inline double exp_softening(double temp_hat) {
123 return std::exp(exp_C * pow(temp_hat, 2) + exp_D * temp_hat);
124}
125
126/**
127 * Isotropic hardening
128 */
129inline double iso_hardening(double tau, double H, double omega_0, double Qinf,
130 double omega_h, double b_iso, double sigmaY,
131 double temp_0, double temp) {
132 return (sigmaY + H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso))) *
134}
135
136inline double iso_hardening_dtau(double tau, double H, double omega_0,
137 double Qinf, double omega_h, double b_iso,
138 double sigmaY, double temp_0, double temp) {
139 return (H + Qinf * b_iso * iso_hardening_exp(tau, b_iso)) *
141}
142
143inline double iso_hardening_dtemp(double tau, double H, double omega_0,
144 double Qinf, double omega_h, double b_iso,
145 double sigmaY, double temp_0, double temp) {
146 double JC_ref_temp = 0.;
147 double JC_melt_temp = 1650.;
148 double T_hat = temp_hat(temp);
149
150 return (sigmaY + H * tau + Qinf * (1. - iso_hardening_exp(tau, b_iso))) *
151 (exp_D + 2 * T_hat * exp_C) *
152 std::exp(exp_D * T_hat + pow(T_hat, 2) * exp_C) /
153 (JC_melt_temp - JC_ref_temp);
154}
155
156/**
157 * Kinematic hardening
158 */
159template <typename T, int DIM>
160inline auto
162 double C1_k) {
163 FTensor::Index<'i', DIM> i;
164 FTensor::Index<'j', DIM> j;
166 if (C1_k < std::numeric_limits<double>::epsilon()) {
167 t_alpha(i, j) = 0;
168 return t_alpha;
169 }
170 t_alpha(i, j) = C1_k * t_plastic_strain(i, j);
171 return t_alpha;
172}
173
174template <int DIM>
176 FTensor::Index<'i', DIM> i;
177 FTensor::Index<'j', DIM> j;
178 FTensor::Index<'k', DIM> k;
179 FTensor::Index<'l', DIM> l;
182 t_diff(i, j, k, l) = C1_k * (t_kd(i, k) ^ t_kd(j, l)) / 4.;
183 return t_diff;
184}
185
187 IS_LARGE_STRAINS; // PETSC_TRUE; ///< Large strains
188PetscBool set_timer = PETSC_FALSE; ///< Set timer
189PetscBool do_eval_field = PETSC_FALSE; ///< Evaluate field
190char restart_file[255];
191PetscBool restart_flg = PETSC_TRUE;
192double restart_time = 0;
194PetscBool is_distributed_mesh = PETSC_TRUE;
195
196double scale = 1.;
202
203double young_modulus = 115000; ///< Young modulus
204double poisson_ratio = 0.31; ///< Poisson ratio
205double sigmaY = 936.2; ///< Yield stress
206double H = 584.3; ///< Hardening
207double visH = 0; ///< Viscous hardening
208double zeta = 5e-2; ///< regularisation parameter
209double Qinf = 174.2; ///< Saturation yield stress
210double b_iso = 63.69; ///< Saturation exponent
211double C1_k = 0; ///< Kinematic hardening
212
213double cn0 = 1;
214double cn1 = 1;
215
216double default_ref_temp = 20.0;
218const char *const ICTypes[] = {"uniform", "gaussian", "linear",
219 "ICType", "IC_", nullptr};
220// CHANGE this from PetscBool to ICType
222double init_temp = 20.0;
223double peak_temp = 1000.0;
224double width = 10.0; ///< Width of Gaussian distribution
227 11.4; // Force / (time temperature ) or Power /
228 // (length temperature) // Time unit is hour. force unit kN
229double default_heat_capacity = 2.332; // length^2/(time^2 temperature) //
230 // length is millimeter time is hour
231
232double omega_0 = 2e-3; ///< flow stress softening
233double omega_h = 2e-3; ///< hardening softening
235 0.9; ///< fraction of plastic dissipation converted to heat
236double temp_0 = 20; ///< reference temperature for thermal softening
237
238int order = 2; ///< Order displacement
239int tau_order = order - 2; ///< Order of tau field
240int ep_order = order - 1; ///< Order of ep field
241int flux_order = order; ///< Order of tau field
242int T_order = order - 1; ///< Order of ep field
243int geom_order = 2; ///< Order if fixed.
244
245int atom_test = 0;
246
247PetscBool order_edge = PETSC_FALSE;
248PetscBool order_face = PETSC_FALSE;
249PetscBool order_volume = PETSC_FALSE;
250
251PetscBool is_quasi_static = PETSC_TRUE;
252double rho = 0.0;
253double alpha_damping = 0;
254double init_dt = 0.05;
255double min_dt = 1e-12;
256double qual_tol = 0;
257
258auto Gaussian_distribution = [](double init_temp, double peak_temp, double x,
259 double y, double z) {
260 double s =
261 width /
262 std::sqrt(-2. * std::log(0.01 * peak_temp / (peak_temp - init_temp)));
263 return (peak_temp - init_temp) * exp(-pow(y, 2) / (2. * pow(s, 2))) +
264 init_temp;
265};
266
267auto linear_distribution = [](double init_temp, double peak_temp, double x,
268 double y, double z) {
269 return ((peak_temp - init_temp) / width) * y + (peak_temp + init_temp) / 2.0;
270};
271
272auto uniform_distribution = [](double init_temp, double peak_temp, double x,
273 double y, double z) { return init_temp; };
274
275/**
276 * @brief Initialisation function for temperature field
277 */
278auto init_T = [](double init_temp, double peak_temp, double x, double y,
279 double z) {
280 switch (ic_type) {
281 case IC_GAUSSIAN:
282 return -Gaussian_distribution(init_temp, peak_temp, x, y, z);
283 case IC_LINEAR:
284 return -linear_distribution(init_temp, peak_temp, x, y, z);
285 case IC_UNIFORM:
286 default:
287 return -uniform_distribution(init_temp, peak_temp, x, y, z);
288 }
289};
290
291#include <HenckyOps.hpp>
292#include <PlasticOps.hpp>
293#include <PlasticNaturalBCs.hpp>
294#include <ThermoElasticOps.hpp>
295#include <FiniteThermalOps.hpp>
296#include <ThermoPlasticOps.hpp>
297#include <ThermalOps.hpp>
298
299#include <EdgeFlippingOps.hpp>
300#include <SolutionMapping.hpp>
301
302#include <ThermalConvection.hpp>
303#include <ThermalRadiation.hpp>
304
305#ifdef ADD_CONTACT
306 #ifdef ENABLE_PYTHON_BINDING
307 #include <boost/python.hpp>
308 #include <boost/python/def.hpp>
309 #include <boost/python/numpy.hpp>
310namespace bp = boost::python;
311namespace np = boost::python::numpy;
312 #endif
313
314namespace ContactOps {
315
316double cn_contact = 0.1;
317
318}; // namespace ContactOps
319
320 #include <ContactOps.hpp>
321#endif // ADD_CONTACT
322
323using namespace PlasticOps;
324using namespace HenckyOps;
325using namespace ThermoElasticOps;
326using namespace FiniteThermalOps;
327using namespace ThermalOps;
328
330
332 std::string output_name, int &counter = *(new int(0))) {
334
335 auto create_post_process_elements = [&]() {
337 auto pp_fe = boost::make_shared<PostProcEle>(m_field);
338
339 auto push_vol_post_proc_ops = [&](auto &pp_fe) {
341
342 auto &pip = pp_fe->getOpPtrVector();
343
344 auto TAU_ptr = boost::make_shared<VectorDouble>();
345 pip.push_back(new OpCalculateScalarFieldValues("TAU", TAU_ptr));
346 auto T_ptr = boost::make_shared<VectorDouble>();
347 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
348
349 auto T_grad_ptr = boost::make_shared<MatrixDouble>();
350 pip.push_back(
351 new OpCalculateScalarFieldGradient<SPACE_DIM>("T", T_grad_ptr));
352 auto U_ptr = boost::make_shared<MatrixDouble>();
353 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", U_ptr));
354 auto FLUX_ptr = boost::make_shared<MatrixDouble>();
355 pip.push_back(
356 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", FLUX_ptr));
357
358 auto EP_ptr = boost::make_shared<MatrixDouble>();
359 pip.push_back(
361
363
364 pip.push_back(
365
366 new OpPPMap(
367
368 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
369
370 {{"TAU", TAU_ptr}, {"T", T_ptr}},
371
372 {{"U", U_ptr}, {"FLUX", FLUX_ptr}, {"T_GRAD", T_grad_ptr}},
373
374 {},
375
376 {{"EP", EP_ptr}}
377
378 )
379
380 );
381
383 };
384
385 CHKERR push_vol_post_proc_ops(pp_fe);
386
387 if (m_field.get_comm_size() == 1) {
388
389 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", pp_fe);
390 CHKERR pp_fe->writeFile("out_" + std::to_string(counter) + "_" +
391 output_name + ".h5m");
392 } else {
393
395 m_field.get_comm_size());
396 auto &post_proc_moab = pp_fe->getPostProcMesh();
397 auto file_name = "out_" + std::to_string(counter) + "_" + output_name +
398 "_" + std::to_string(m_field.get_comm_rank()) + ".vtk";
399 MOFEM_LOG("WORLD", Sev::inform)
400 << "Writing file " << file_name << std::endl;
401 CHKERR post_proc_moab.write_file(file_name.c_str(), "VTK");
402 }
403 counter++;
404
406 };
407
408 CHKERR create_post_process_elements();
409
411}
412
414 Vec sol, std::string output_name) {
416
417 auto smart_sol = SmartPetscObj<Vec>(sol, true);
418
419 auto create_post_process_elements = [&]() {
421 Simple *simple = m_field.getInterface<Simple>();
422 auto pp_fe = boost::make_shared<PostProcEle>(m_field);
423 auto &pip = pp_fe->getOpPtrVector();
424
425 auto push_vol_post_proc_ops = [&](auto &pp_fe) {
427
428 auto &pip = pp_fe->getOpPtrVector();
429
430 auto TAU_ptr = boost::make_shared<VectorDouble>();
431 pip.push_back(
432 new OpCalculateScalarFieldValues("TAU", TAU_ptr, smart_sol));
433 auto T_ptr = boost::make_shared<VectorDouble>();
434 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr, smart_sol));
435
436 auto U_ptr = boost::make_shared<MatrixDouble>();
437 pip.push_back(
438 new OpCalculateVectorFieldValues<SPACE_DIM>("U", U_ptr, smart_sol));
439 auto FLUX_ptr = boost::make_shared<MatrixDouble>();
441 "FLUX", FLUX_ptr, smart_sol));
442
443 auto EP_ptr = boost::make_shared<MatrixDouble>();
445 "EP", EP_ptr, smart_sol));
446
448
449 pip.push_back(
450
451 new OpPPMap(
452
453 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
454
455 {{"TAU", TAU_ptr}, {"T", T_ptr}},
456
457 {{"U", U_ptr}, {"FLUX", FLUX_ptr}},
458
459 {},
460
461 {{"EP", EP_ptr}}
462
463 )
464
465 );
466
468 };
469
470 CHKERR push_vol_post_proc_ops(pp_fe);
471
472 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", pp_fe);
473 CHKERR pp_fe->writeFile("out_" + output_name + ".h5m");
474
476 };
477
478 CHKERR create_post_process_elements();
479
481}
482
484 const std::string &out_put_string,
485 const auto &out_put_quantity) {
487 auto rank = m_field.get_comm_rank();
488 auto size = m_field.get_comm_size();
489
490 // Loop through all processes and print one by one
491 for (int i = 0; i < size; ++i) {
492 // If it is this process's turn, print the data
493 if (i == rank) {
494 std::cout << "Proc " << rank << " " + out_put_string + " "
495 << out_put_quantity << std::endl;
496 }
497 // All processes wait here until the current one has finished
498 // printing
499 CHKERR PetscBarrier(NULL);
500 }
502};
503
513
514//! [Body and heat source]
522//! [Body and heat source]
523
524//! [Natural boundary conditions]
530//! [Natural boundary conditions]
531
532//! [Essential boundary conditions (Least square approach)]
534 IT>::OpEssentialRhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
537//! [Essential boundary conditions (Least square approach)]
538
543
544auto save_range = [](moab::Interface &moab, const std::string name,
545 const Range r) {
547 auto out_meshset = get_temp_meshset_ptr(moab);
548 CHKERR moab.add_entities(*out_meshset, r);
549 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
551};
552
553struct Example;
554
555/**
556 * @brief Set of functions called by PETSc solver used to refine and update
557 * mesh.
558 *
559 * @note Currently theta method is only handled by this code.
560 *
561 */
562struct TSPrePostProc {
563
564 TSPrePostProc() = default;
565 virtual ~TSPrePostProc() = default;
566
567 /**
568 * @brief Used to setup TS solver
569 *
570 * @param ts
571 * @return MoFEMErrorCode
572 */
574
576
577private:
578 /**
579 * @brief Pre process time step
580 *
581 * Refine mesh and update fields
582 *
583 * @param ts
584 * @return MoFEMErrorCode
585 */
587
588 /**
589 * @brief Post process time step.
590 *
591 * Currently that function do not make anything major
592 *
593 * @param ts
594 * @return MoFEMErrorCode
595 */
597
599};
600
601static boost::weak_ptr<TSPrePostProc> tsPrePostProc;
602
603struct ResizeCtx {
605 // any flags / lists indicating which elements flipped or were added
606 PetscBool mesh_changed; // set by your code that flips elements
610 // store whatever mapping info you need
611};
612
613static std::unordered_map<TS, ResizeCtx *> ts_to_rctx;
614
615SetEnrichedIntegration::SetEnrichedIntegration(boost::shared_ptr<Range> new_els)
616 : newEls(new_els) {}
617
620 int order_row, int order_col,
621 int order_data) {
623
624 constexpr int numNodes = 3;
625 constexpr int numEdges = 3;
626
627 auto &m_field = fe_raw_ptr->mField;
628 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
629 auto fe_handle = fe_ptr->getFEEntityHandle();
630
631 auto set_base_quadrature = [&]() {
633 int rule = 2 * (order_data + 1);
634 if (rule < QUAD_2D_TABLE_SIZE) {
635 if (QUAD_2D_TABLE[rule]->dim != 2) {
636 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
637 }
638 if (QUAD_2D_TABLE[rule]->order < rule) {
639 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
640 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
641 }
642 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
643 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
644 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
645 &fe_ptr->gaussPts(0, 0), 1);
646 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
647 &fe_ptr->gaussPts(1, 0), 1);
648 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
649 &fe_ptr->gaussPts(2, 0), 1);
650 auto &data = fe_ptr->dataOnElement[H1];
651 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
652 false);
653 double *shape_ptr =
654 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
655 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
656 1);
657 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
658 std::copy(
660 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
661
662 } else {
663 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
664 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
665 }
667 };
668
669 CHKERR set_base_quadrature();
670
671 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
673 fe_ptr->gaussPts.swap(ref_gauss_pts);
674 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
675 auto &data = fe_ptr->dataOnElement[H1];
676 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3);
677 double *shape_ptr =
678 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
679 CHKERR ShapeMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
680 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
682 };
683
684 auto refine_quadrature = [&]() {
686
687 moab::Core moab_ref;
688 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
689 EntityHandle nodes[numNodes];
690 for (int nn = 0; nn != numNodes; nn++)
691 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
692 EntityHandle tri;
693 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
694 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
695 MoFEM::Interface &m_field_ref = mofem_ref_core;
696
697 Range ref_tri(tri, tri);
698 Range edges;
699 CHKERR m_field_ref.get_moab().get_adjacencies(ref_tri, 1, true, edges,
700 moab::Interface::UNION);
701 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
702 ref_tri, BitRefLevel().set(0), false, VERBOSE);
703
704 Range nodes_at_front;
705 for (int nn = 0; nn != numNodes; nn++) {
706 EntityHandle ent;
707 CHKERR moab_ref.side_element(tri, 0, nn, ent);
708 nodes_at_front.insert(ent);
709 }
710
711 EntityHandle meshset;
712 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
713 for (int ee = 0; ee != numEdges; ee++) {
714 EntityHandle ent;
715 CHKERR moab_ref.side_element(tri, 1, ee, ent);
716 CHKERR moab_ref.add_entities(meshset, &ent, 1);
717 }
718
719 // refine mesh
720 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
721 Range ref_edges;
722 CHKERR m_field_ref.getInterface<BitRefManager>()
723 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(0),
724 BitRefLevel().set(), MBEDGE, ref_edges);
725
726 // Range tris_to_refine;
727 // CHKERR m_field_ref.getInterface<BitRefManager>()
728 // ->getEntitiesByTypeAndRefLevel(
729 // BitRefLevel().set(0), BitRefLevel().set(), MBTRI,
730 // tris_to_refine);
731 CHKERR m_ref->addVerticesInTheMiddleOfEdges(ref_edges,
732 BitRefLevel().set(1));
733 CHKERR m_ref->addVerticesInTheMiddleOfFaces(ref_tri, BitRefLevel().set(1));
734 CHKERR m_ref->refineTris(ref_tri, BitRefLevel().set(1));
735 CHKERR m_field_ref.getInterface<BitRefManager>()
736 ->updateMeshsetByEntitiesChildren(meshset, BitRefLevel().set(1),
737 meshset, MBEDGE, true);
738 CHKERR m_field_ref.getInterface<BitRefManager>()
739 ->updateMeshsetByEntitiesChildren(meshset, BitRefLevel().set(1),
740 meshset, MBTRI, true);
741
742 // get ref coords
743 Range output_ref_tris;
744 CHKERR m_field_ref.getInterface<BitRefManager>()
745 ->getEntitiesByTypeAndRefLevel(
746 BitRefLevel().set(1), BitRefLevel().set(), MBTRI, output_ref_tris);
747
748#ifndef NDEBUG
749 CHKERR save_range(moab_ref, "ref_tris.vtk", output_ref_tris);
750#endif
751
752 MatrixDouble ref_coords(output_ref_tris.size(), 9, false);
753 int tt = 0;
754 for (Range::iterator tit = output_ref_tris.begin();
755 tit != output_ref_tris.end(); tit++, tt++) {
756 int num_nodes;
757 const EntityHandle *conn;
758 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
759 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
760 }
761
762 auto &data = fe_ptr->dataOnElement[H1];
763 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
764 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
765 MatrixDouble &shape_n = data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
766 int gg = 0;
767 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
768 double *tri_coords = &ref_coords(tt, 0);
770 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
771 auto det = t_normal.l2();
772 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
773 for (int dd = 0; dd != 2; dd++) {
774 ref_gauss_pts(dd, gg) = shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
775 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
776 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
777 }
778 MOFEM_LOG("REMESHING", Sev::noisy)
779 << ref_gauss_pts(0, gg) << ", " << ref_gauss_pts(1, gg);
780 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
781 }
782 }
783
784 int num_nodes;
785 const EntityHandle *conn;
786 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
787 true);
788 std::bitset<numNodes> all_nodes;
789 for (auto nn = 0; nn != numNodes; ++nn) {
790 all_nodes.set(nn);
791 }
792
793 mapRefCoords[all_nodes.to_ulong()].swap(ref_gauss_pts);
794 CHKERR set_gauss_pts(mapRefCoords[all_nodes.to_ulong()]);
795
797 };
798
799 CHKERR refine_quadrature();
800
802}
803
804struct Example {
805
806 Example(MoFEM::Interface &m_field) : mField(m_field) {}
807
809
811
812private:
820
821 boost::shared_ptr<DomainEle> reactionFe;
822
823 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
824 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
825 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
826
827 boost::shared_ptr<VectorDouble> tempFieldPtr =
828 boost::make_shared<VectorDouble>();
829 boost::shared_ptr<MatrixDouble> fluxFieldPtr =
830 boost::make_shared<MatrixDouble>();
831 boost::shared_ptr<MatrixDouble> dispFieldPtr =
832 boost::make_shared<MatrixDouble>();
833 boost::shared_ptr<MatrixDouble> dispGradPtr =
834 boost::make_shared<MatrixDouble>();
835 boost::shared_ptr<MatrixDouble> strainFieldPtr =
836 boost::make_shared<MatrixDouble>();
837 boost::shared_ptr<MatrixDouble> stressFieldPtr =
838 boost::make_shared<MatrixDouble>();
839 boost::shared_ptr<VectorDouble> plasticMultiplierFieldPtr =
840 boost::make_shared<VectorDouble>();
841 boost::shared_ptr<MatrixDouble> plasticStrainFieldPtr =
842 boost::make_shared<MatrixDouble>();
843
844 struct ScaledTimeScale : public MoFEM::TimeScale {
846 double getScale(const double time) {
847 return scale * MoFEM::TimeScale::getScale(time);
848 };
849 };
850
851#ifdef ADD_CONTACT
852 #ifdef ENABLE_PYTHON_BINDING
853 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
854 #endif
855#endif // ADD_CONTACT
856
857 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
859 MoFEM::Interface &m_field, std::string block_name,
860 std::string thermal_block_name, std::string thermoelastic_block_name,
861 std::string thermoplastic_block_name, Pip &pip, std::string u,
862 std::string ep, std::string tau, std::string temperature) {
864
865 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
866 A>::template LinearForm<I>;
868 typename B::template OpGradTimesSymTensor<1, DIM, DIM>;
870 typename B::template OpGradTimesTensor<1, DIM, DIM>;
871
873
875
876 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
877 common_thermoelastic_ptr, common_thermoplastic_ptr] =
878 createCommonThermoPlasticOps<DIM, I, DomainEleOp>(
879 m_field, block_name, thermal_block_name, thermoelastic_block_name,
880 thermoplastic_block_name, pip, u, ep, tau, temperature, scale,
883
884 auto m_D_ptr = common_hencky_ptr->matDPtr;
885
887 ep, common_plastic_ptr->getPlasticStrainDotPtr()));
888 pip.push_back(new OpCalculateScalarFieldValuesDot(
889 tau, common_plastic_ptr->getPlasticTauDotPtr()));
890 pip.push_back(new OpCalculateScalarFieldValues(
891 temperature, common_thermoplastic_ptr->getTempPtr()));
893 "FLUX", common_thermoplastic_ptr->getHeatFluxPtr()));
894 pip.push_back(new typename P::template OpCalculatePlasticity<DIM, I>(
895 u, common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
896
897 pip.push_back(
898 new
899 typename H::template OpCalculateHenckyThermoPlasticStress<DIM, I, 0>(
900 u, common_thermoplastic_ptr->getTempPtr(), common_hencky_ptr,
901 common_thermoelastic_ptr->getCoeffExpansionPtr(),
902 common_thermoelastic_ptr->getRefTempPtr()));
903
904 // Calculate internal forces
905 if (common_hencky_ptr) {
906 pip.push_back(new OpInternalForcePiola(
907 u, common_hencky_ptr->getMatFirstPiolaStress()));
908 } else {
909 pip.push_back(
910 new OpInternalForceCauchy(u, common_plastic_ptr->mStressPtr));
911 }
912
913 auto inelastic_heat_frac_ptr =
914 common_thermoplastic_ptr->getInelasticHeatFractionPtr();
916 [inelastic_heat_frac_ptr](const double, const double, const double) {
917 return (*inelastic_heat_frac_ptr);
918 };
919
920 // TODO: add scenario for when not using Hencky material
923 temperature, common_hencky_ptr->getMatHenckyStress(),
924 common_plastic_ptr->getPlasticStrainDotPtr(), inelastic_heat_fraction));
925
926 pip.push_back(
927 new
928 typename P::template Assembly<A>::template OpCalculateConstraintsRhs<I>(
929 tau, common_plastic_ptr, m_D_ptr));
930 pip.push_back(
931 new
932 typename P::template Assembly<A>::template OpCalculatePlasticFlowRhs<
933 DIM, I>(ep, common_plastic_ptr, m_D_ptr));
934
936 }
937
938 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
940 MoFEM::Interface &m_field, std::string block_name,
941 std::string thermal_block_name, std::string thermoelastic_block_name,
942 std::string thermoplastic_block_name, Pip &pip, std::string u,
943 std::string ep, std::string tau, std::string temperature) {
945
946 using namespace HenckyOps;
948
949 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
950 A>::template BiLinearForm<I>;
951 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, 1>;
952 using OpKCauchy = typename B::template OpGradSymTensorGrad<1, DIM, DIM, 0>;
953
955
956 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
957 common_thermoelastic_ptr, common_thermoplastic_ptr] =
958 createCommonThermoPlasticOps<DIM, I, DomainEleOp>(
959 m_field, block_name, thermal_block_name, thermoelastic_block_name,
960 thermoplastic_block_name, pip, u, ep, tau, temperature, scale,
963
964 auto m_D_ptr = common_hencky_ptr->matDPtr;
965
967 ep, common_plastic_ptr->getPlasticStrainDotPtr()));
968 pip.push_back(new OpCalculateScalarFieldValuesDot(
969 tau, common_plastic_ptr->getPlasticTauDotPtr()));
970 pip.push_back(new typename P::template OpCalculatePlasticity<DIM, I>(
971 u, common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
972
973 if (common_hencky_ptr) {
974 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
975 u, common_hencky_ptr, m_D_ptr));
976 pip.push_back(new OpKPiola(u, u, common_hencky_ptr->getMatTangent()));
977 pip.push_back(
978 new typename P::template Assembly<A>::
979 template OpCalculatePlasticInternalForceLhs_LogStrain_dEP<DIM, I>(
980 u, ep, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
981 } else {
982 pip.push_back(new OpKCauchy(u, u, m_D_ptr));
983 pip.push_back(new typename P::template Assembly<A>::
984 template OpCalculatePlasticInternalForceLhs_dEP<DIM, I>(
985 u, ep, common_plastic_ptr, m_D_ptr));
986 }
987
988 if (common_hencky_ptr) {
989 pip.push_back(
990 new typename P::template Assembly<A>::
991 template OpCalculateConstraintsLhs_LogStrain_dU<DIM, I>(
992 tau, u, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
993 pip.push_back(
994 new typename P::template Assembly<A>::
995 template OpCalculatePlasticFlowLhs_LogStrain_dU<DIM, I>(
996 ep, u, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
997 } else {
998 pip.push_back(new typename P::template Assembly<A>::
999 template OpCalculateConstraintsLhs_dU<DIM, I>(
1000 tau, u, common_plastic_ptr, m_D_ptr));
1001 pip.push_back(new typename P::template Assembly<A>::
1002 template OpCalculatePlasticFlowLhs_dU<DIM, I>(
1003 ep, u, common_plastic_ptr, m_D_ptr));
1004 }
1005
1006 pip.push_back(new typename P::template Assembly<A>::
1007 template OpCalculatePlasticFlowLhs_dEP<DIM, I>(
1008 ep, ep, common_plastic_ptr, m_D_ptr));
1009 pip.push_back(new typename P::template Assembly<A>::
1010 template OpCalculatePlasticFlowLhs_dTAU<DIM, I>(
1011 ep, tau, common_plastic_ptr, m_D_ptr));
1012 pip.push_back(
1014 ep, temperature, common_thermoplastic_ptr));
1015 pip.push_back(new typename P::template Assembly<A>::
1016 template OpCalculateConstraintsLhs_dEP<DIM, I>(
1017 tau, ep, common_plastic_ptr, m_D_ptr));
1018 pip.push_back(
1019 new typename P::template Assembly<
1020 A>::template OpCalculateConstraintsLhs_dTAU<I>(tau, tau,
1021 common_plastic_ptr));
1022
1023 // TODO: add scenario for when not using Hencky material
1024 pip.push_back(new typename H::template OpCalculateHenckyThermalStressdT<
1025 DIM, I, AssemblyDomainEleOp, 0>(
1026 u, temperature, common_hencky_ptr,
1027 common_thermoelastic_ptr->getCoeffExpansionPtr()));
1028
1029 auto inelastic_heat_frac_ptr =
1030 common_thermoplastic_ptr->getInelasticHeatFractionPtr();
1032 [inelastic_heat_frac_ptr](const double, const double, const double) {
1033 return (*inelastic_heat_frac_ptr);
1034 };
1035
1036 // TODO: add scenario for when not using Hencky material
1039 temperature, temperature, common_hencky_ptr, common_plastic_ptr,
1041 common_thermoelastic_ptr->getCoeffExpansionPtr()));
1042
1043 // TODO: add scenario for when not using Hencky material
1046 temperature, ep, common_hencky_ptr, common_plastic_ptr,
1048
1049 // TODO: add scenario for when not using Hencky material
1052 temperature, u, common_hencky_ptr, common_plastic_ptr,
1054
1056 tau, temperature, common_thermoplastic_ptr));
1057
1059 }
1060
1061 template <int DIM, IntegrationType I, typename DomainEleOp>
1063 MoFEM::Interface &m_field, std::string plastic_block_name,
1064 std::string thermal_block_name, std::string thermoelastic_block_name,
1065 std::string thermoplastic_block_name,
1066 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1067 std::string u, std::string ep, std::string tau, std::string temperature,
1071 bool with_rates = true) {
1072
1074
1075 auto common_plastic_ptr = boost::make_shared<PlasticOps::CommonData>();
1076 auto common_thermal_ptr =
1077 boost::make_shared<ThermoElasticOps::BlockedThermalParameters>();
1078 auto common_thermoelastic_ptr =
1079 boost::make_shared<ThermoElasticOps::BlockedThermoElasticParameters>();
1080 auto common_thermoplastic_ptr =
1081 boost::make_shared<ThermoPlasticOps::ThermoPlasticBlockedParameters>();
1082
1083 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
1084 auto make_d_mat = []() {
1085 return boost::make_shared<MatrixDouble>(size_symm * size_symm, 1);
1086 };
1087
1088 common_plastic_ptr->mDPtr = boost::make_shared<MatrixDouble>();
1089 common_plastic_ptr->mGradPtr = boost::make_shared<MatrixDouble>();
1090 common_plastic_ptr->mStrainPtr = boost::make_shared<MatrixDouble>();
1091 common_plastic_ptr->mStressPtr = boost::make_shared<MatrixDouble>();
1092
1093 auto m_D_ptr = common_plastic_ptr->mDPtr;
1094
1095 CHK_THROW_MESSAGE(PlasticOps::addMatBlockOps<DIM>(
1096 m_field, plastic_block_name, pip, m_D_ptr,
1097 common_plastic_ptr->getParamsPtr(), scale, sev),
1098 "add mat block plastic ops");
1100 m_field, pip, thermal_block_name, common_thermal_ptr,
1105 "add mat block thermal ops");
1107 m_field, pip, thermoelastic_block_name,
1108 common_thermoelastic_ptr, default_coeff_expansion,
1109 default_ref_temp, sev),
1110 "add mat block thermal ops");
1112 m_field, pip, thermoplastic_block_name,
1113 common_thermoplastic_ptr, common_thermal_ptr, sev,
1115 "add mat block thermoplastic ops");
1116 auto common_hencky_ptr =
1117 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
1118 mField, pip, "U", "MAT_ELASTIC", Sev::inform, scale);
1119
1120 common_plastic_ptr->mDPtr = common_hencky_ptr->matDPtr;
1121
1122 pip.push_back(new OpCalculateScalarFieldValues(
1123 tau, common_plastic_ptr->getPlasticTauPtr()));
1125 ep, common_plastic_ptr->getPlasticStrainPtr()));
1127 u, common_plastic_ptr->mGradPtr));
1128
1129 pip.push_back(new OpCalculateScalarFieldValues(
1130 temperature, common_thermoplastic_ptr->getTempPtr()));
1132 "FLUX", common_thermoplastic_ptr->getHeatFluxPtr()));
1133
1134 common_plastic_ptr->mGradPtr = common_hencky_ptr->matGradPtr;
1135 common_plastic_ptr->mDPtr = common_hencky_ptr->matDPtr;
1136 common_hencky_ptr->matLogCPlastic =
1137 common_plastic_ptr->getPlasticStrainPtr();
1138 common_plastic_ptr->mStrainPtr = common_hencky_ptr->getMatLogC();
1139 common_plastic_ptr->mStressPtr = common_hencky_ptr->getMatHenckyStress();
1140
1142
1143 pip.push_back(new typename H::template OpCalculateEigenVals<DIM, I>(
1144 u, common_hencky_ptr));
1145 pip.push_back(
1146 new typename H::template OpCalculateLogC<DIM, I>(u, common_hencky_ptr));
1147 pip.push_back(new typename H::template OpCalculateLogC_dC<DIM, I>(
1148 u, common_hencky_ptr));
1149
1150 pip.push_back(
1151 new
1152 typename H::template OpCalculateHenckyThermoPlasticStress<DIM, I, 0>(
1153 u, common_thermoplastic_ptr->getTempPtr(), common_hencky_ptr,
1154 common_thermoelastic_ptr->getCoeffExpansionPtr(),
1155 common_thermoelastic_ptr->getRefTempPtr()));
1156 pip.push_back(new typename H::template OpCalculatePiolaStress<DIM, I, 0>(
1157 u, common_hencky_ptr));
1158
1159 pip.push_back(new typename P::template OpCalculatePlasticSurface<DIM, I>(
1160 u, common_plastic_ptr));
1161
1162 pip.push_back(new typename P::template OpCalculatePlasticHardening<DIM, I>(
1163 u, common_plastic_ptr, common_thermoplastic_ptr));
1164
1165 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
1166 common_thermal_ptr, common_thermoelastic_ptr,
1167 common_thermoplastic_ptr);
1168 }
1169
1170 friend struct TSPrePostProc;
1171};
1172
1175
1176 if (auto ptr = tsPrePostProc.lock()) {
1177 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Run step pre proc";
1178
1179 auto &m_field = ptr->ExRawPtr->mField;
1180 auto simple = m_field.getInterface<Simple>();
1181 auto &moab = m_field.get_moab();
1182
1183 // get vector norm
1184 auto get_norm = [&](auto x) {
1185 double nrm;
1186 CHKERR VecNorm(x, NORM_2, &nrm);
1187 return nrm;
1188 };
1189
1190 auto save_range = [](moab::Interface &moab, const std::string name,
1191 const Range r) {
1193 auto out_meshset = get_temp_meshset_ptr(moab);
1194 CHKERR moab.add_entities(*out_meshset, r);
1195 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(),
1196 1);
1198 };
1199
1200 auto dm = simple->getDM();
1201 auto d_vector = createDMVector(dm);
1202 CHKERR DMoFEMMeshToLocalVector(dm, d_vector, INSERT_VALUES,
1203 SCATTER_FORWARD);
1204 CHKERR VecGhostUpdateBegin(d_vector, INSERT_VALUES, SCATTER_FORWARD);
1205 CHKERR VecGhostUpdateEnd(d_vector, INSERT_VALUES, SCATTER_FORWARD);
1206 CHKERR DMoFEMMeshToGlobalVector(dm, d_vector, INSERT_VALUES,
1207 SCATTER_REVERSE);
1208
1209 Range new_elements, all_old_els, flipped_els, adj_edges;
1210 // Set bitRefLevel for old and new mesh
1211 auto old_mesh_bitreflevel = BitRefLevel().set(0);
1212 // auto new_els_bitreflevel = BitRefLevel().set(1);
1213 auto new_mesh_bitreflevel = BitRefLevel().set(1);
1214
1215 auto improve_element_quality = [&]() {
1217
1218 Range all_els;
1219 CHKERR moab.get_entities_by_dimension(0, SPACE_DIM, all_els, true);
1220 CHKERR m_field.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1221 BitRefLevel().set(0), BitRefLevel().set(0), all_els);
1222
1223 double spatial_coords[9], material_coords[9];
1224 Tag th_spatial_coords;
1225 std::multimap<double, EntityHandle> el_q_map, el_J_increased_map,
1226 el_J_decreased_map;
1227
1228 auto get_element_quality_measures = [&]() {
1230
1231 Range verts;
1232 CHKERR moab.get_entities_by_type(0, MBVERTEX, verts);
1233 std::vector<double> coords(verts.size() * 3);
1234 CHKERR moab.get_coords(verts, coords.data());
1235 auto t_x = getFTensor1FromPtr<3>(coords.data());
1236
1237 auto save_tag = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
1239 FTENSOR_INDEX(3, i)
1240 auto field_data = ent_ptr->getEntFieldData();
1242 if (SPACE_DIM == 2) {
1243 t_u = {field_data[0], field_data[1], 0.0};
1244 } else {
1245 t_u = {field_data[0], field_data[1], field_data[2]};
1246 }
1247
1248 t_x(i) += t_u(i);
1249 ++t_x;
1251 };
1252
1253 m_field.getInterface<FieldBlas>()->fieldLambdaOnEntities(save_tag, "U",
1254 &verts);
1255 double def_coord[3] = {0.0, 0.0, 0.0};
1256 CHKERR moab.tag_get_handle("SpatialCoord", 3, MB_TYPE_DOUBLE,
1257 th_spatial_coords,
1258 MB_TAG_DENSE | MB_TAG_CREAT, def_coord);
1259 CHKERR moab.tag_set_data(th_spatial_coords, verts, coords.data());
1260
1261 // get a map which has the element quality for each tag
1262
1263 const EntityHandle *conn;
1264 int num_nodes;
1265 Range::iterator nit = all_els.begin();
1266 for (int gg = 0; nit != all_els.end(); nit++, gg++) {
1267 CHKERR m_field.get_moab().get_connectivity(*nit, conn, num_nodes,
1268 true);
1269
1270 CHKERR moab.get_coords(conn, num_nodes, material_coords);
1271 CHKERR moab.tag_get_data(th_spatial_coords, conn, num_nodes,
1272 spatial_coords);
1273
1274 double J =
1275 Tools::triArea(spatial_coords) / Tools::triArea(material_coords);
1276
1277 MOFEM_LOG("REMESHING", Sev::verbose)
1278 << "Element: " << *nit << " Jacobian: " << J;
1279
1280 double q = Tools::areaLengthQuality(spatial_coords);
1281 if (!std::isnormal(q))
1282 q = -2;
1283
1284 if (J < 0.1 && q < qual_tol && q > 0) {
1285 el_J_decreased_map.insert(std::pair<double, EntityHandle>(J, *nit));
1286 } else if (J > 3.0 && q < qual_tol && q > 0) {
1287 el_J_increased_map.insert(std::pair<double, EntityHandle>(J, *nit));
1288 } else if (q < qual_tol && q > 0) {
1289 el_q_map.insert(std::pair<double, EntityHandle>(q, *nit));
1290 }
1291 }
1292
1293 double min_q = 1;
1294 CHKERR m_field.getInterface<Tools>()->minElQuality<SPACE_DIM>(
1295 all_els, min_q, th_spatial_coords);
1296 MOFEM_LOG("REMESHING", Sev::inform)
1297 << "Old minimum element quality: " << min_q;
1298 // Get the first element using begin()
1299 auto pair = el_q_map.begin();
1300 MOFEM_LOG("REMESHING", Sev::inform)
1301 << "New minimum element quality: " << pair->first;
1302
1304 };
1305
1306 // Calculates the element quality as well as elements with excessively
1307 // increased and decreased Jacobians
1308 CHKERR get_element_quality_measures();
1309
1310 std::vector<EntityHandle> new_connectivity;
1311
1312 auto get_string_from_vector = [](auto vec) {
1313 std::string output_string = "";
1314 for (auto el : vec) {
1315 output_string += std::to_string(el) + " ";
1316 }
1317 return output_string;
1318 };
1319
1320 std::string improved_reasons = "";
1321
1322 // auto perform_edge_split = [&](auto bit0, auto bit) {
1323 // MoFEMFunctionBegin;
1324 // auto meshset_ptr = get_temp_meshset_ptr(moab);
1325 // CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
1326 // bit0, BitRefLevel().set(), *meshset_ptr);
1327
1328 // // random mesh refinement
1329 // auto meshset_ref_edges_ptr = get_temp_meshset_ptr(moab);
1330 // Range edges_to_refine;
1331 // CHKERR moab.get_entities_by_type(*meshset_ptr, MBEDGE,
1332 // edges_to_refine); int ii = 0; for (Range::iterator eit =
1333 // edges_to_refine.begin();
1334 // eit != edges_to_refine.end(); eit++, ii++) {
1335 // int numb = ii % 2;
1336 // if (numb == 0) {
1337 // CHKERR moab.add_entities(*meshset_ref_edges_ptr, &*eit, 1);
1338 // }
1339 // }
1340 // CHKERR refine->addVerticesInTheMiddleOfEdges(*meshset_ref_edges_ptr,
1341 // bit,
1342 // false, QUIET, 10000);
1343 // if (dim == 3) {
1344 // CHKERR refine->refineTets(*meshset_ptr, bit, QUIET, true);
1345 // } else if (dim == 2) {
1346 // CHKERR refine->refineTris(*meshset_ptr, bit, QUIET, true);
1347 // } else {
1348 // SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
1349 // "Dimension not handled by test");
1350 // }
1351
1352 // improved_reasons += ", Edge splitting";
1353 // MoFEMFunctionReturn(0);
1354 // };
1355
1356 auto perform_edge_flip = [&]() {
1358
1359 for (auto pair = el_q_map.begin(); pair != el_q_map.end(); ++pair) {
1360 double quality = pair->first;
1361 Range element;
1362 element.insert(pair->second);
1363 if (!flipped_els.contains(element)) {
1364 // Get edges of element
1365 Range edges;
1366 CHKERR m_field.get_moab().get_adjacencies(element, 1, false, edges);
1367
1368 // Get the longest edge
1369 double edge_length;
1370 EntityHandle longest_edge;
1371 double longest_edge_length = 0;
1372 for (auto edge : edges) {
1373 edge_length = m_field.getInterface<Tools>()->getEdgeLength(edge);
1374 if (edge_length > longest_edge_length) {
1375 longest_edge_length = edge_length;
1376 longest_edge = edge;
1377 }
1378 }
1379
1380 MOFEM_LOG("REMESHING", Sev::verbose)
1381 << "Edge flip longest edge length: " << longest_edge_length
1382 << " for edge: " << longest_edge;
1383
1384 auto get_skin = [&]() {
1385 Range body_ents;
1386 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
1387 body_ents);
1388 Skinner skin(&m_field.get_moab());
1389 Range skin_ents;
1390 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
1391 return skin_ents;
1392 };
1393
1394 auto filter_true_skin = [&](auto skin) {
1395 Range boundary_ents;
1396 ParallelComm *pcomm =
1397 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
1398 CHKERR pcomm->filter_pstatus(skin,
1399 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1400 PSTATUS_NOT, -1, &boundary_ents);
1401 return boundary_ents;
1402 };
1403
1404 Range boundary_ents = get_skin();
1405
1406 MOFEM_LOG("REMESHING", Sev::verbose)
1407 << "Boundary entities: " << boundary_ents;
1408
1409 if (boundary_ents.contains(Range(longest_edge, longest_edge)))
1410 continue;
1411
1412 // Get neighbouring element with the longest edge
1413 Range flip_candidate_els;
1414 CHKERR m_field.get_moab().get_adjacencies(
1415 &longest_edge, 1, SPACE_DIM, false, flip_candidate_els);
1416 CHKERR m_field.getInterface<BitRefManager>()
1417 ->filterEntitiesByRefLevel(BitRefLevel().set(0),
1418 BitRefLevel().set(),
1419 flip_candidate_els);
1420
1421 Range neighbouring_el = subtract(flip_candidate_els, element);
1422 CHKERR m_field.getInterface<BitRefManager>()
1423 ->filterEntitiesByRefLevel(
1424 BitRefLevel().set(0), BitRefLevel().set(), neighbouring_el);
1425
1426#ifndef NDEBUG
1427 if (neighbouring_el.size() != 1) {
1428 SETERRQ(
1429 PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1430 "Should be 1 neighbouring element to bad element for edge "
1431 "flip. Instead, there are %d",
1432 neighbouring_el.size());
1433 }
1434#endif
1435
1436 MOFEM_LOG("REMESHING", Sev::verbose)
1437 << "flip_candidate_els: " << flip_candidate_els;
1438 MOFEM_LOG("REMESHING", Sev::verbose)
1439 << "Neighbouring element: " << neighbouring_el;
1440
1441 if (flipped_els.contains(neighbouring_el))
1442 continue;
1443
1444 // Check the quality of the neighbouring element
1445 std::vector<EntityHandle> neighbouring_nodes;
1446 CHKERR m_field.get_moab().get_connectivity(
1447 &neighbouring_el.front(), 1, neighbouring_nodes, true);
1448
1449 std::vector<EntityHandle> element_nodes;
1450 CHKERR m_field.get_moab().get_connectivity(&element.front(), 1,
1451 element_nodes, true);
1452
1453 CHKERR moab.tag_get_data(th_spatial_coords,
1454 &neighbouring_nodes.front(), 3,
1455 spatial_coords);
1456
1457 double neighbour_qual = Tools::areaLengthQuality(spatial_coords);
1458 if (!std::isnormal(neighbour_qual))
1459 neighbour_qual = -2;
1460
1461 // Get the nodes of flip_candidate_els as well as the nodes of
1462 // longest_edge
1463
1464 MOFEM_LOG("REMESHING", Sev::verbose)
1465 << "Element nodes before swap: "
1466 << get_string_from_vector(element_nodes);
1467 MOFEM_LOG("REMESHING", Sev::verbose)
1468 << "Neighbouring nodes before swap: "
1469 << get_string_from_vector(neighbouring_nodes);
1470
1471 // Get new canonical ordering of new nodes and new neighbouring
1472 // nodes
1473 std::vector<EntityHandle> reversed_neighbouring_nodes =
1474 neighbouring_nodes;
1475 std::reverse(reversed_neighbouring_nodes.begin(),
1476 reversed_neighbouring_nodes.end());
1477
1478 int num_matches = 0;
1479 std::vector<bool> mismatch_mask(element_nodes.size());
1480 int loop_counter = 0; // To prevent infinite loop
1481 while (num_matches != 2) {
1482 // Permute first element to the end
1483 std::rotate(reversed_neighbouring_nodes.begin(),
1484 reversed_neighbouring_nodes.begin() + 1,
1485 reversed_neighbouring_nodes.end());
1486 // Create a boolean mask
1487 std::transform(element_nodes.begin(), element_nodes.end(),
1488 reversed_neighbouring_nodes.begin(),
1489 mismatch_mask.begin(),
1490 std::equal_to<EntityHandle>());
1491 // Check if common edge is found
1492 num_matches =
1493 std::count(mismatch_mask.begin(), mismatch_mask.end(), true);
1494
1495 ++loop_counter;
1496 if (loop_counter > 3) {
1497 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
1498 "Not found matching nodes for edge flipping");
1499 }
1500 }
1501
1502 // Get matching nodes
1503 std::vector<EntityHandle> matched_elements(element_nodes.size());
1504 std::transform(element_nodes.begin(), element_nodes.end(),
1505 mismatch_mask.begin(), matched_elements.begin(),
1506 [](EntityHandle el, bool match) {
1507 return match ? el
1508 : -1; // Or some other "null" value
1509 });
1510
1511 // Remove zero (or "null") elements
1512 matched_elements.erase(std::remove(matched_elements.begin(),
1513 matched_elements.end(), -1),
1514 matched_elements.end());
1515
1516 // Get mismatching nodes
1517 std::vector<EntityHandle> mismatched_elements(element_nodes.size()),
1518 neighbouring_mismatched_elements(neighbouring_nodes.size());
1519 std::transform(element_nodes.begin(), element_nodes.end(),
1520 mismatch_mask.begin(), mismatched_elements.begin(),
1521 [](EntityHandle el, bool match) {
1522 return match ? -1
1523 : el; // Or some other "null" value
1524 });
1525 std::transform(
1526 reversed_neighbouring_nodes.begin(),
1527 reversed_neighbouring_nodes.end(), mismatch_mask.begin(),
1528 neighbouring_mismatched_elements.begin(),
1529 [](EntityHandle el, bool match) {
1530 return match ? -1 : el; // Or some other "null" value
1531 });
1532
1533 // Remove zero (or "null") elements
1534 mismatched_elements.erase(std::remove(mismatched_elements.begin(),
1535 mismatched_elements.end(),
1536 -1),
1537 mismatched_elements.end());
1538 neighbouring_mismatched_elements.erase(
1539 std::remove(neighbouring_mismatched_elements.begin(),
1540 neighbouring_mismatched_elements.end(), -1),
1541 neighbouring_mismatched_elements.end());
1542
1543 mismatched_elements.insert(mismatched_elements.end(),
1544 neighbouring_mismatched_elements.begin(),
1545 neighbouring_mismatched_elements.end());
1546
1547 MOFEM_LOG("REMESHING", Sev::verbose)
1548 << "Reversed neighbouring nodes: "
1549 << get_string_from_vector(reversed_neighbouring_nodes);
1550
1551 MOFEM_LOG("REMESHING", Sev::verbose)
1552 << "mismatch mask: " << get_string_from_vector(mismatch_mask);
1553
1554 MOFEM_LOG("REMESHING", Sev::verbose)
1555 << "Old nodes are: "
1556 << get_string_from_vector(matched_elements);
1557
1558 MOFEM_LOG("REMESHING", Sev::verbose)
1559 << "New nodes are: "
1560 << get_string_from_vector(mismatched_elements);
1561
1562 auto replace_correct_nodes =
1563 [](std::vector<EntityHandle> &ABC,
1564 std::vector<EntityHandle> &DBA,
1565 const std::vector<EntityHandle> &AB,
1566 const std::vector<EntityHandle> &CD) {
1568 std::vector<std::vector<EntityHandle>> results;
1569 // Assume AB.size() == 2, CD.size() == 2 for tris
1570 for (int i = 0; i < 2; ++i) { // i: 0 for A, 1 for B
1571 for (int j = 0; j < 2; ++j) { // j: 0 for C, 1 for D
1572 // Only try to replace if CD[j] is not already in ABC
1573 if (std::find(ABC.begin(), ABC.end(), CD[j]) ==
1574 ABC.end()) {
1575 std::vector<EntityHandle> tmp = ABC;
1576 // Find AB[i] in ABC and replace with CD[j]
1577 auto it = std::find(tmp.begin(), tmp.end(), AB[i]);
1578 if (it != tmp.end()) {
1579 *it = CD[j];
1580 results.push_back(tmp);
1581 }
1582 }
1583 }
1584 }
1585
1586 if (results.size() != 2) {
1587 SETERRQ(
1588 PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
1589 "Failed to find two valid vertex replacements for edge "
1590 "flip");
1591 }
1592
1593 ABC = results[0];
1594 DBA = results[1];
1595
1597 };
1598
1599 CHKERR replace_correct_nodes(element_nodes, neighbouring_nodes,
1600 matched_elements, mismatched_elements);
1601
1602 MOFEM_LOG("REMESHING", Sev::verbose)
1603 << "Element nodes after swap: "
1604 << get_string_from_vector(element_nodes);
1605 MOFEM_LOG("REMESHING", Sev::verbose)
1606 << "Neighbouring nodes after swap: "
1607 << get_string_from_vector(neighbouring_nodes);
1608
1609 // Calculate the quality of the new elements
1610 CHKERR moab.tag_get_data(th_spatial_coords, &element_nodes.front(),
1611 3, spatial_coords);
1612
1613 double new_qual = Tools::areaLengthQuality(spatial_coords);
1614 if (!std::isnormal(new_qual))
1615 new_qual = -2;
1616
1617#ifndef NDEBUG
1618 auto check_normal_direction = [&]() {
1620 FTensor::Index<'i', 3> i;
1621 auto t_correct_normal =
1622 FTensor::Tensor1<double, 3>(0.0, 0.0, 1.0);
1623 auto [new_area, t_new_normal] =
1624 Tools::triAreaAndNormal(spatial_coords);
1625 auto t_diff = FTensor::Tensor1<double, 3>();
1626 t_diff(i) = t_new_normal(i) - t_correct_normal(i);
1627 if (t_diff(i) * t_diff(i) > 1e-6) {
1628 SETERRQ(
1629 PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
1630 "Direction of element to be created is wrong orientation");
1631 }
1633 };
1634
1635 CHKERR check_normal_direction();
1636#endif
1637
1638 CHKERR moab.tag_get_data(th_spatial_coords,
1639 &neighbouring_nodes.front(), 3,
1640 spatial_coords);
1641
1642 double new_neighbour_qual =
1643 Tools::areaLengthQuality(spatial_coords);
1644 if (!std::isnormal(new_neighbour_qual))
1645 new_neighbour_qual = -2;
1646
1647#ifndef NDEBUG
1648 CHKERR check_normal_direction();
1649#endif
1650
1651 // If the minimum element quality has improved, do the flip
1652 if (std::min(new_qual, new_neighbour_qual) >
1653 std::min(quality, neighbour_qual)) {
1654 MOFEM_LOG("REMESHING", Sev::inform)
1655 << "Element quality improved from " << quality << " and "
1656 << neighbour_qual << " to " << new_qual << " and "
1657 << new_neighbour_qual << " for elements" << element << " and "
1658 << neighbouring_el;
1659
1660 // then push to creation "pipeline".
1661 flipped_els.merge(flip_candidate_els);
1662 new_connectivity.insert(new_connectivity.end(),
1663 element_nodes.begin(),
1664 element_nodes.end());
1665 new_connectivity.insert(new_connectivity.end(),
1666 neighbouring_nodes.begin(),
1667 neighbouring_nodes.end());
1668 }
1669 }
1670 }
1671
1672 improved_reasons += ", Edge flipping";
1673
1675 };
1676
1677 // CHKERR perform_edge_split();
1678 CHKERR perform_edge_flip();
1679
1680 MOFEM_LOG("REMESHING", Sev::verbose)
1681 << "Flipped elements: " << flipped_els;
1682 MOFEM_LOG("REMESHING", Sev::verbose)
1683 << "New connectivity: " << get_string_from_vector(new_connectivity);
1684
1685 // Make new mesh with flipped edge
1686 // Get Range of all elements not to be flipped in the mesh
1687 CHKERR moab.get_entities_by_type(0, MBTRI, all_old_els, true);
1688 CHKERR m_field.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1689 BitRefLevel().set(0), BitRefLevel().set(), all_old_els);
1690
1691 // CHKERR save_range(m_field.get_moab(),
1692 // (boost::format("all_old_els.vtk")).str(),
1693 // all_old_els);
1694
1695 MOFEM_LOG("REMESHING", Sev::verbose)
1696 << "Elements added to old_mesh: " << all_old_els;
1697
1698 Range old_mesh_range;
1699 CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
1700 old_mesh_bitreflevel, BitRefLevel().set(), old_mesh_range, 1);
1701 MOFEM_LOG("REMESHING", Sev::verbose)
1702 << "Old mesh range: " << old_mesh_range;
1703#ifndef NDEBUG
1704 CHKERR save_range(m_field.get_moab(),
1705 (boost::format("old_mesh.vtk")).str(), old_mesh_range);
1706#endif
1707
1708 // Range evil_set;
1709 // CHKERR moab.get_entities_by_type(0, MBENTITYSET, evil_set, true);
1710
1711 // MOFEM_LOG("REMESHING", Sev::verbose) << "evil set: " <<
1712 // evil_set;
1713
1714 // CHKERR save_range(m_field.get_moab(),
1715 // (boost::format("evil_set.vtk")).str(), evil_set);
1716
1717 Range remaining_els_after_flip = subtract(all_old_els, flipped_els);
1718
1719 // Set new bitreflevel for all remaining elements after flipping
1720
1721 MOFEM_LOG("REMESHING", Sev::verbose)
1722 << "Non-flipped elements: " << remaining_els_after_flip;
1723
1724 ReadUtilIface *read_util;
1725 CHKERR m_field.get_moab().query_interface(read_util);
1726
1727 const int num_ele = flipped_els.size();
1728 int num_nod_per_ele;
1729 EntityType ent_type;
1730
1731 if (SPACE_DIM == 2) {
1732 num_nod_per_ele = 3;
1733 ent_type = MBTRI;
1734 } else {
1735 num_nod_per_ele = 4;
1736 ent_type = MBTET;
1737 }
1738
1739 EntityHandle *conn_moab;
1740 EntityHandle start_e = 0;
1741
1742 if (flipped_els.size() > 0) {
1743
1744 auto new_conn = new_connectivity.begin();
1745 for (auto e = 0; e != num_ele; ++e) {
1746 EntityHandle conn[num_nod_per_ele];
1747 for (int n = 0; n < num_nod_per_ele; ++n) {
1748 conn[n] = *new_conn;
1749 ++new_conn;
1750 }
1751 EntityHandle new_ele;
1752 Range adj_ele;
1753 CHKERR m_field.get_moab().get_adjacencies(conn, num_nod_per_ele,
1754 SPACE_DIM, false, adj_ele);
1755 if (adj_ele.size()) {
1756 if (adj_ele.size() != 1) {
1757 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
1758 "Element duplication");
1759 } else {
1760 new_ele = adj_ele.front();
1761 }
1762 } else {
1763 CHKERR m_field.get_moab().create_element(ent_type, conn,
1764 num_nod_per_ele, new_ele);
1765 }
1766 new_elements.insert(new_ele);
1767 }
1768
1769 // CHKERR read_util->get_element_connect(num_ele, num_nod_per_ele,
1770 // ent_type, 0, start_e,
1771 // conn_moab);
1772
1773 // std::copy(new_connectivity.begin(), new_connectivity.end(),
1774 // conn_moab);
1775
1776 // // Create adjacencies to this element
1777 // CHKERR read_util->update_adjacencies(start_e, num_ele,
1778 // num_nod_per_ele,
1779 // new_connectivity.data());
1780 // new_elements = Range(start_e, start_e + num_ele - 1);
1781
1782 MOFEM_LOG("REMESHING", Sev::verbose)
1783 << "New elements: " << new_elements;
1784
1785 // Set correct bitRefLevel for new elements
1786
1787 // CHKERR m_field.getInterface<BitRefManager>()->addBitRefLevel(
1788 // new_elements, new_els_bitreflevel, 1);
1789
1790 // #ifndef NDEBUG
1791 // Range new_els_range;
1792 // CHKERR
1793 // m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
1794 // new_els_bitreflevel, BitRefLevel().set(), new_els_range,
1795 // 1);
1796 // MOFEM_LOG("REMESHING", Sev::verbose)
1797 // << "New mesh range: " << new_els_range;
1798 // CHKERR save_range(m_field.get_moab(),
1799 // (boost::format("new_els.vtk")).str(),
1800 // new_els_range);
1801 // #endif
1802
1803 MOFEM_LOG("REMESHING", Sev::verbose)
1804 << "New elements from before: " << remaining_els_after_flip;
1805
1806 Range new_elements_nodes_vertices;
1807 new_elements_nodes_vertices.merge(new_elements);
1808 new_elements_nodes_vertices.merge(remaining_els_after_flip);
1809
1810 Range new_edges_range;
1811 CHKERR moab.get_adjacencies(new_elements_nodes_vertices, 1, true,
1812 new_edges_range, moab::Interface::UNION);
1813 Range new_vertices_range;
1814 CHKERR moab.get_adjacencies(new_elements_nodes_vertices, 0, true,
1815 new_vertices_range, moab::Interface::UNION);
1816
1817 new_elements_nodes_vertices.merge(new_edges_range);
1818 new_elements_nodes_vertices.merge(new_vertices_range);
1819
1820 MOFEM_LOG("REMESHING", Sev::verbose)
1821 << "New mesh after flip: " << new_elements_nodes_vertices;
1822
1823 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevel(
1824 new_elements_nodes_vertices, new_mesh_bitreflevel, false);
1825
1826#ifndef NDEBUG
1827 Range new_mesh_range;
1828 CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
1829 new_mesh_bitreflevel, BitRefLevel().set(), new_mesh_range, 1);
1830 MOFEM_LOG("REMESHING", Sev::verbose)
1831 << "New mesh range: " << new_mesh_range;
1832 CHKERR save_range(m_field.get_moab(),
1833 (boost::format("new_mesh.vtk")).str(),
1834 new_mesh_range);
1835#endif
1836
1837 // Erase leading ", " from improved_reasons
1838 improved_reasons.erase(0, 2);
1839
1840 MOFEM_LOG("REMESHING", Sev::inform)
1841 << "Improved mesh quality by: " << improved_reasons;
1842
1843 // CHKERR moab.write_file("remeshed_mesh.h5m", "MOAB", "");
1844 };
1845
1847 };
1848
1849 auto solve_equil_sub_problem = [&]() {
1851 if (flipped_els.size() == 0) {
1853 }
1854
1855 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
1856
1857 auto simple = m_field.getInterface<Simple>();
1858
1860
1861 auto U_ptr = boost::make_shared<MatrixDouble>();
1862 auto EP_ptr = boost::make_shared<MatrixDouble>();
1863 auto TAU_ptr = boost::make_shared<VectorDouble>();
1864 auto T_ptr = boost::make_shared<VectorDouble>();
1865 // auto FLUX_ptr = boost::make_shared<MatrixDouble>();
1866 // auto T_grad_ptr = boost::make_shared<MatrixDouble>();
1867
1868 auto post_proc = [&](auto dm) {
1870
1871 auto post_proc_fe = boost::make_shared<PostProcEle>(m_field);
1872
1874 post_proc_fe->getOpPtrVector(), {H1, L2, HDIV}, "GEOMETRY");
1875
1877
1878 // post_proc_fe->getOpPtrVector().push_back(
1879 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX",
1880 // FLUX_ptr));
1881 post_proc_fe->getOpPtrVector().push_back(
1882 new OpCalculateScalarFieldValues("T", T_ptr));
1883 // post_proc_fe->getOpPtrVector().push_back(
1884 // new OpCalculateScalarFieldGradient<SPACE_DIM>("T",
1885 // T_grad_ptr));
1886 post_proc_fe->getOpPtrVector().push_back(
1888 post_proc_fe->getOpPtrVector().push_back(
1889 new OpCalculateScalarFieldValues("TAU", TAU_ptr));
1890 post_proc_fe->getOpPtrVector().push_back(
1892 EP_ptr));
1893 post_proc_fe->getOpPtrVector().push_back(
1894
1895 new OpPPMap(post_proc_fe->getPostProcMesh(),
1896 post_proc_fe->getMapGaussPts(),
1897
1898 {
1899 {"TAU", TAU_ptr},
1900 {"T", T_ptr},
1901 },
1902
1903 {{"U", U_ptr}},
1904
1905 {},
1906
1907 {{"EP", EP_ptr}}
1908
1909 )
1910
1911 );
1912
1913 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", post_proc_fe);
1914 CHKERR post_proc_fe->writeFile("out_equilibrate.h5m");
1915
1917 };
1918
1919 auto solve_equilibrate_solution = [&]() {
1921
1922 auto set_domain_rhs = [&](auto &pip) {
1924
1926 "GEOMETRY");
1927
1928 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1929 AT>::template LinearForm<IT>;
1930 using OpInternalForceCauchy =
1931 typename B::template OpGradTimesSymTensor<1, SPACE_DIM,
1932 SPACE_DIM>;
1933 using OpInternalForcePiola =
1934 typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
1935
1937
1938 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
1939 common_thermoelastic_ptr, common_thermoplastic_ptr] =
1940 ptr->ExRawPtr
1941 ->createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1942 m_field, "MAT_PLASTIC", "MAT_THERMAL",
1943 "MAT_THERMOELASTIC", "MAT_THERMOPLASTIC", pip, "U", "EP",
1946 Sev::inform);
1947
1948 auto m_D_ptr = common_plastic_ptr->mDPtr;
1949
1950 pip.push_back(new OpCalculateScalarFieldValues(
1951 "T", common_thermoplastic_ptr->getTempPtr()));
1952 pip.push_back(
1953 new
1954 typename P::template OpCalculatePlasticityWithoutRates<SPACE_DIM,
1955 IT>(
1956 "U", common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
1957
1958 // Calculate internal forces
1959 if (common_hencky_ptr) {
1960 pip.push_back(new OpInternalForcePiola(
1961 "U", common_hencky_ptr->getMatFirstPiolaStress()));
1962 } else {
1963 pip.push_back(
1964 new OpInternalForceCauchy("U", common_plastic_ptr->mStressPtr));
1965 }
1966
1968 };
1969
1970 auto set_domain_lhs = [&](auto &pip) {
1972
1974 pip, {H1, L2, HDIV}, "GEOMETRY");
1975
1976 using namespace HenckyOps;
1977
1978 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1979 AT>::template BiLinearForm<IT>;
1980 using OpKPiola =
1981 typename B::template OpGradTensorGrad<1, SPACE_DIM, SPACE_DIM, 1>;
1982 using OpKCauchy =
1983 typename B::template OpGradSymTensorGrad<1, SPACE_DIM, SPACE_DIM,
1984 0>;
1985
1987
1988 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
1989 common_thermoelastic_ptr, common_thermoplastic_ptr] =
1990 ptr->ExRawPtr
1991 ->createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1992 m_field, "MAT_PLASTIC", "MAT_THERMAL",
1993 "MAT_THERMOELASTIC", "MAT_THERMOPLASTIC", pip, "U", "EP",
1996 Sev::inform);
1997
1998 auto m_D_ptr = common_plastic_ptr->mDPtr;
1999
2000 pip.push_back(
2001 new
2002 typename P::template OpCalculatePlasticityWithoutRates<SPACE_DIM,
2003 IT>(
2004 "U", common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
2005
2006 if (common_hencky_ptr) {
2008 pip.push_back(
2009 new typename H::template OpHenckyTangent<SPACE_DIM, IT, 0>(
2010 "U", common_hencky_ptr, m_D_ptr));
2011 pip.push_back(
2012 new OpKPiola("U", "U", common_hencky_ptr->getMatTangent()));
2013 // pip.push_back(
2014 // new typename P::template Assembly<AT>::
2015 // template
2016 // OpCalculatePlasticInternalForceLhs_LogStrain_dEP<
2017 // SPACE_DIM, IT>("U", "EP", common_plastic_ptr,
2018 // common_hencky_ptr, m_D_ptr));
2019 } else {
2020 pip.push_back(new OpKCauchy("U", "U", m_D_ptr));
2021 // pip.push_back(
2022 // new typename P::template Assembly<AT>::
2023 // template
2024 // OpCalculatePlasticInternalForceLhs_dEP<SPACE_DIM,
2025 // IT>(
2026 // "U", "EP", common_plastic_ptr, m_D_ptr));
2027 }
2028
2029 // TODO: add scenario for when not using Hencky material
2030 // pip.push_back(new
2031 // HenckyOps::OpCalculateHenckyThermalStressdT<
2032 // SPACE_DIM, IT, AssemblyDomainEleOp>(
2033 // "U", "T", common_hencky_ptr,
2034 // common_thermal_ptr->getCoeffExpansionPtr()));
2035
2037 };
2038
2039 auto create_sub_dm = [&](SmartPetscObj<DM> base_dm) {
2040 auto dm_sub = createDM(m_field.get_comm(), "DMMOFEM");
2041 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "EQUIL_DM");
2042 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
2043 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
2044 for (auto f : {"U", "EP", "TAU", "T"}) {
2047 }
2048 CHKERR DMSetUp(dm_sub);
2049 return dm_sub;
2050 };
2051
2052 auto sub_dm = create_sub_dm(simple->getDM());
2053
2054 auto fe_rhs = boost::make_shared<DomainEle>(m_field);
2055 auto fe_lhs = boost::make_shared<DomainEle>(m_field);
2056
2057 fe_rhs->getRuleHook = vol_rule;
2058 fe_lhs->getRuleHook = vol_rule;
2059 CHKERR set_domain_rhs(fe_rhs->getOpPtrVector());
2060 CHKERR set_domain_lhs(fe_lhs->getOpPtrVector());
2061
2062 auto bc_mng = m_field.getInterface<BcManager>();
2063
2065 "EQUIL_DM", "U");
2066
2067 auto &bc_map = bc_mng->getBcMapByBlockName();
2068 for (auto bc : bc_map)
2069 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
2070
2071 auto time_scale = boost::make_shared<TimeScale>(
2072 "", false, [](const double) { return 1; });
2073 auto def_time_scale = [time_scale](const double time) {
2074 return (!time_scale->argFileScale) ? time : 1;
2075 };
2076 auto def_file_name = [time_scale](const std::string &&name) {
2077 return (!time_scale->argFileScale) ? name : "";
2078 };
2079 auto time_displacement_scaling = boost::make_shared<TimeScale>(
2080 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
2081
2082 auto pre_proc_ptr = boost::make_shared<FEMethod>();
2083 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
2084 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
2085
2086 PetscReal current_time;
2087 TSGetTime(ts, &current_time);
2088 pre_proc_ptr->ts_t = current_time;
2089
2090 // Set BCs by eliminating degrees of freedom
2091 auto get_bc_hook_rhs = [&]() {
2093 ptr->ExRawPtr->mField, pre_proc_ptr,
2094 {time_scale, time_displacement_scaling});
2095 return hook;
2096 };
2097 auto get_bc_hook_lhs = [&]() {
2099 ptr->ExRawPtr->mField, pre_proc_ptr,
2100 {time_scale, time_displacement_scaling});
2101 return hook;
2102 };
2103
2104 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
2105 pre_proc_ptr->preProcessHook = get_bc_hook_lhs();
2106
2107 auto get_post_proc_hook_rhs = [&]() {
2110 ptr->ExRawPtr->mField, post_proc_rhs_ptr, nullptr,
2111 Sev::verbose)();
2113 ptr->ExRawPtr->mField, post_proc_rhs_ptr, 1.)();
2115 };
2116 auto get_post_proc_hook_lhs = [&]() {
2118 ptr->ExRawPtr->mField, post_proc_lhs_ptr, 1.);
2119 };
2120 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
2121 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
2122
2123 auto snes_ctx_ptr = getDMSnesCtx(sub_dm);
2124 snes_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_ptr);
2125 snes_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_ptr);
2126 snes_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs_ptr);
2127 snes_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs_ptr);
2128
2129 auto null_fe = boost::shared_ptr<FEMethod>();
2130 // CHKERR DMMoFEMKSPSetComputeOperators(
2131 // sub_dm, simple->getDomainFEName(), fe_lhs, null_fe,
2132 // null_fe);
2133 // CHKERR DMMoFEMKSPSetComputeRHS(sub_dm,
2134 // simple->getDomainFEName(),
2135 // fe_rhs, null_fe, null_fe);
2136 CHKERR DMMoFEMSNESSetFunction(sub_dm, simple->getDomainFEName(), fe_rhs,
2137 null_fe, null_fe);
2138 CHKERR DMMoFEMSNESSetJacobian(sub_dm, simple->getDomainFEName(), fe_lhs,
2139 null_fe, null_fe);
2140
2141 // auto ksp = MoFEM::createKSP(m_field.get_comm());
2142 // CHKERR KSPSetDM(ksp, sub_dm);
2143 // CHKERR KSPSetFromOptions(ksp);
2144
2145 auto D = createDMVector(sub_dm);
2146
2147 auto snes = MoFEM::createSNES(m_field.get_comm());
2148 CHKERR SNESSetDM(snes, sub_dm);
2149 CHKERR SNESSetFromOptions(snes);
2150 CHKERR SNESSetUp(snes);
2151
2152 CHKERR DMoFEMMeshToLocalVector(sub_dm, D, INSERT_VALUES,
2153 SCATTER_FORWARD);
2154 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
2155 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
2156 // SmartPetscObj<Vec> global_rhs;
2157 // CHKERR DMCreateGlobalVector_MoFEM(
2158 // sub_dm, global_rhs);
2159 // CHKERR KSPSolve(ksp, PETSC_NULLPTR, D);
2160 CHKERR SNESSolve(snes, PETSC_NULLPTR, D);
2161
2162 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
2163 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
2164 CHKERR DMoFEMMeshToLocalVector(sub_dm, D, INSERT_VALUES,
2165 SCATTER_REVERSE);
2166
2168 };
2169
2170 CHKERR solve_equilibrate_solution();
2171 CHKERR post_proc(simple->getDM());
2172
2173 MOFEM_LOG("REMESHING", Sev::inform)
2174 << "Equilibrated solution after mapping";
2175
2177 };
2178
2179 CHKERR improve_element_quality(); // improve element quality
2180 if (flipped_els.size() > 0) {
2181 // Now you can safely update the context fields
2182 ResizeCtx *ctx = nullptr;
2183 CHKERR TSGetApplicationContext(ts, (void **)&ctx);
2184 if (!ctx)
2185 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "ResizeCtx missing");
2186 ctx->all_old_els = all_old_els;
2187 ctx->new_elements = new_elements;
2188 ctx->flipped_els = flipped_els;
2189 ctx->mesh_changed = PETSC_TRUE;
2190
2191 // Then trigger the resize process
2192 // CHKERR TSResize(ts);
2193 }
2194
2195 // Need barriers, some functions in TS solver need are called
2196 // collectively and requite the same state of variables
2197 CHKERR PetscBarrier((PetscObject)ts);
2198
2199 MOFEM_LOG_CHANNEL("SYNC");
2200 MOFEM_TAG_AND_LOG("SYNC", Sev::verbose, "REMESHING") << "PreProc done";
2201 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
2202 }
2203
2205}
2206
2208 if (auto ptr = tsPrePostProc.lock()) {
2209 auto &m_field = ptr->ExRawPtr->mField;
2210 MOFEM_LOG_CHANNEL("SYNC");
2211 MOFEM_TAG_AND_LOG("SYNC", Sev::verbose, "THERMOPLASTICITY")
2212 << "PostProc done";
2213 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
2214 }
2215 return 0;
2216}
2217
2219
2221
2222 CHKERR TSSetPreStep(ts, tsPreProc);
2223 CHKERR TSSetPostStep(ts, tsPostProc);
2224
2226}
2227
2229 MoFEM::Interface &m_field,
2230 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
2231 std::string thermoplastic_block_name,
2232 boost::shared_ptr<ThermoPlasticOps::ThermoPlasticBlockedParameters>
2233 blockedParamsPtr,
2234 boost::shared_ptr<ThermoElasticOps::BlockedThermalParameters>
2235 &blockedThermalParamsPtr,
2236 Sev sev, ScalerFunThreeArgs inelastic_heat_fraction_scaling_func) {
2238
2239 struct OpMatThermoPlasticBlocks : public DomainEleOp {
2240 OpMatThermoPlasticBlocks(
2241 boost::shared_ptr<double> omega_0_ptr,
2242 boost::shared_ptr<double> omega_h_ptr,
2243 boost::shared_ptr<double> inelastic_heat_fraction_ptr,
2244 boost::shared_ptr<double> temp_0_ptr,
2245 boost::shared_ptr<double> heat_conductivity,
2246 boost::shared_ptr<double> heat_capacity,
2247 boost::shared_ptr<double> heat_conductivity_scaling,
2248 boost::shared_ptr<double> heat_capacity_scaling,
2250 MoFEM::Interface &m_field, Sev sev,
2251 std::vector<const CubitMeshSets *> meshset_vec_ptr)
2252 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), omega0Ptr(omega_0_ptr),
2253 omegaHPtr(omega_h_ptr),
2254 inelasticHeatFractionPtr(inelastic_heat_fraction_ptr),
2255 temp0Ptr(temp_0_ptr), heatConductivityPtr(heat_conductivity),
2256 heatCapacityPtr(heat_capacity),
2257 heatConductivityScalingPtr(heat_conductivity_scaling),
2258 heatCapacityScalingPtr(heat_capacity_scaling),
2259 inelasticHeatFractionScaling(inelastic_heat_fraction_scaling) {
2261 extractThermoPlasticBlockData(m_field, meshset_vec_ptr, sev),
2262 "Can not get data from block");
2263 }
2264
2265 MoFEMErrorCode doWork(int side, EntityType type,
2268
2269 auto scale_param = [this](auto parameter, double scaling) {
2270 return parameter * scaling;
2271 };
2272
2273 for (auto &b : blockData) {
2274
2275 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
2276 *omega0Ptr = b.omega_0;
2277 *omegaHPtr = b.omega_h;
2278 *inelasticHeatFractionPtr = scale_param(
2279 b.inelastic_heat_fraction,
2280 inelasticHeatFractionScaling(
2282 *heatConductivityPtr / (*heatConductivityScalingPtr),
2283 *heatCapacityPtr / (*heatCapacityScalingPtr)));
2284 *temp0Ptr = b.temp_0;
2286 }
2287 }
2288
2289 *omega0Ptr = omega_0;
2290 *omegaHPtr = omega_h;
2291 *inelasticHeatFractionPtr =
2292 scale_param(inelastic_heat_fraction,
2293 inelasticHeatFractionScaling(
2295 *heatConductivityPtr / (*heatConductivityScalingPtr),
2296 *heatCapacityPtr / (*heatCapacityScalingPtr)));
2297 *temp0Ptr = temp_0;
2298
2300 }
2301
2302 private:
2303 ScalerFunThreeArgs inelasticHeatFractionScaling;
2304 boost::shared_ptr<double> heatConductivityPtr;
2305 boost::shared_ptr<double> heatCapacityPtr;
2306 boost::shared_ptr<double> heatConductivityScalingPtr;
2307 boost::shared_ptr<double> heatCapacityScalingPtr;
2308 struct BlockData {
2309 double omega_0;
2310 double omega_h;
2312 double temp_0;
2313 Range blockEnts;
2314 };
2315
2316 std::vector<BlockData> blockData;
2317
2318 MoFEMErrorCode extractThermoPlasticBlockData(
2319 MoFEM::Interface &m_field,
2320 std::vector<const CubitMeshSets *> meshset_vec_ptr, Sev sev) {
2322
2323 for (auto m : meshset_vec_ptr) {
2324 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat ThermoPlastic Block") << *m;
2325 std::vector<double> block_data;
2326 CHKERR m->getAttributes(block_data);
2327 if (block_data.size() < 3) {
2328 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2329 "Expected that block has four attributes");
2330 }
2331 auto get_block_ents = [&]() {
2332 Range ents;
2333 CHKERR
2334 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
2335 return ents;
2336 };
2337
2338 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat ThermoPlastic Block")
2339 << m->getName() << ": omega_0 = " << block_data[0]
2340 << " omega_h = " << block_data[1]
2341 << " inelastic_heat_fraction = " << block_data[2] << " temp_0 "
2342 << block_data[3];
2343
2344 blockData.push_back({block_data[0], block_data[1], block_data[2],
2345 block_data[3], get_block_ents()});
2346 }
2347 MOFEM_LOG_CHANNEL("WORLD");
2349 }
2350
2351 boost::shared_ptr<double> omega0Ptr;
2352 boost::shared_ptr<double> omegaHPtr;
2353 boost::shared_ptr<double> inelasticHeatFractionPtr;
2354 boost::shared_ptr<double> temp0Ptr;
2355 };
2356
2357 pipeline.push_back(new OpMatThermoPlasticBlocks(
2358 blockedParamsPtr->getOmega0Ptr(), blockedParamsPtr->getOmegaHPtr(),
2359 blockedParamsPtr->getInelasticHeatFractionPtr(),
2360 blockedParamsPtr->getTemp0Ptr(),
2361 blockedThermalParamsPtr->getHeatConductivityPtr(),
2362 blockedThermalParamsPtr->getHeatCapacityPtr(),
2363 blockedThermalParamsPtr->getHeatConductivityScalingPtr(),
2364 blockedThermalParamsPtr->getHeatCapacityScalingPtr(),
2365 inelastic_heat_fraction_scaling_func, m_field, sev,
2366
2367 // Get blockset using regular expression
2368 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2369
2370 (boost::format("%s(.*)") % thermoplastic_block_name).str()
2371
2372 ))
2373
2374 ));
2375
2377}
2378
2379//! [Run problem]
2384 if (!restart_flg)
2387 CHKERR thermalBC();
2388 CHKERR OPs();
2389 CHKERR tsSolve();
2391}
2392//! [Run problem]
2393
2394//! [Set up problem]
2398
2399 Range domain_ents;
2400 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
2401 true);
2402 auto get_ents_by_dim = [&](const auto dim) {
2403 if (dim == SPACE_DIM) {
2404 return domain_ents;
2405 } else {
2406 Range ents;
2407 if (dim == 0)
2408 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
2409 else
2410 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
2411 return ents;
2412 }
2413 };
2414
2415 auto get_base = [&]() {
2416 auto domain_ents = get_ents_by_dim(SPACE_DIM);
2417 if (domain_ents.empty())
2418 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
2419 const auto type = type_from_handle(domain_ents[0]);
2420 switch (type) {
2421 case MBQUAD:
2422 return DEMKOWICZ_JACOBI_BASE;
2423 case MBHEX:
2424 return DEMKOWICZ_JACOBI_BASE;
2425 case MBTRI:
2427 case MBTET:
2429 default:
2430 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
2431 }
2432 return NOBASE;
2433 };
2434
2435 const auto base = get_base();
2436 MOFEM_LOG("PLASTICITY", Sev::inform)
2437 << "Base " << ApproximationBaseNames[base];
2438
2439 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
2440 CHKERR simple->addDomainField("EP", L2, base, size_symm);
2441 CHKERR simple->addDomainField("TAU", L2, base, 1);
2442 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
2443
2444 constexpr auto flux_space = (SPACE_DIM == 2) ? HCURL : HDIV;
2445 CHKERR simple->addDomainField("T", L2, base, 1);
2446 CHKERR simple->addDomainField("FLUX", flux_space, DEMKOWICZ_JACOBI_BASE, 1);
2447 CHKERR simple->addBoundaryField("FLUX", flux_space, DEMKOWICZ_JACOBI_BASE, 1);
2448 CHKERR simple->addBoundaryField("TBC", L2, base, 1);
2449
2450 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
2451
2452 CHKERR simple->setFieldOrder("U", order);
2453 CHKERR simple->setFieldOrder("EP", ep_order);
2454 CHKERR simple->setFieldOrder("TAU", tau_order);
2455 CHKERR simple->setFieldOrder("FLUX", flux_order);
2456 CHKERR simple->setFieldOrder("T", T_order);
2457 CHKERR simple->setFieldOrder("TBC", T_order);
2458
2459 CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
2460
2461#ifdef ADD_CONTACT
2462 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
2463 SPACE_DIM);
2464 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
2465 SPACE_DIM);
2466
2467 auto get_skin = [&]() {
2468 Range body_ents;
2469 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
2470 Skinner skin(&mField.get_moab());
2471 Range skin_ents;
2472 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2473 return skin_ents;
2474 };
2475
2476 auto filter_blocks = [&](auto skin) {
2477 bool is_contact_block = false;
2478 Range contact_range;
2479 for (auto m :
2480 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2481
2482 (boost::format("%s(.*)") % "CONTACT").str()
2483
2484 ))
2485
2486 ) {
2487 is_contact_block =
2488 true; ///< blocs interation is collective, so that is set irrespective
2489 ///< if there are entities in given rank or not in the block
2490 MOFEM_LOG("CONTACT", Sev::inform)
2491 << "Find contact block set: " << m->getName();
2492 auto meshset = m->getMeshset();
2493 Range contact_meshset_range;
2494 CHKERR mField.get_moab().get_entities_by_dimension(
2495 meshset, SPACE_DIM - 1, contact_meshset_range, true);
2496
2497 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
2498 contact_meshset_range);
2499 contact_range.merge(contact_meshset_range);
2500 }
2501 if (is_contact_block) {
2502 MOFEM_LOG("SYNC", Sev::inform)
2503 << "Nb entities in contact surface: " << contact_range.size();
2505 skin = intersect(skin, contact_range);
2506 }
2507 return skin;
2508 };
2509
2510 auto filter_true_skin = [&](auto skin) {
2511 Range boundary_ents;
2512 ParallelComm *pcomm =
2513 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2514 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2515 PSTATUS_NOT, -1, &boundary_ents);
2516 return boundary_ents;
2517 };
2518
2519 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
2520 CHKERR simple->setFieldOrder("SIGMA", 0);
2521 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
2522#endif
2523
2525 // Cannot resetup after this block has been defined
2526 // as empty when remeshing
2527 if (qual_tol < 1e-12)
2528 CHKERR simple->addFieldToEmptyFieldBlocks("U", "TAU");
2529
2530 auto project_ho_geometry = [&]() {
2531 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
2532 return mField.loop_dofs("GEOMETRY", ent_method);
2533 };
2534 PetscBool project_geometry = PETSC_TRUE;
2535 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
2536 &project_geometry, PETSC_NULLPTR);
2537 if (project_geometry) {
2538 CHKERR project_ho_geometry();
2539 }
2540
2542}
2543//! [Set up problem]
2544
2545//! [Create common data]
2548
2549 auto get_command_line_parameters = [&]() {
2551
2552 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-quasi_static",
2553 &is_quasi_static, PETSC_NULLPTR);
2554 MOFEM_LOG("PLASTICITY", Sev::inform)
2555 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
2556
2557 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ts_dt", &init_dt,
2558 PETSC_NULLPTR);
2559 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Initial dt: " << init_dt;
2560
2561 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ts_adapt_dt_min", &min_dt,
2562 PETSC_NULLPTR);
2563 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Minimum dt: " << min_dt;
2564
2565 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-min_quality", &qual_tol,
2566 PETSC_NULLPTR);
2567 MOFEM_LOG("REMESHING", Sev::inform)
2568 << "Minumum quality for edge flipping: " << qual_tol;
2569
2570 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale,
2571 PETSC_NULLPTR);
2572 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
2573 &young_modulus, PETSC_NULLPTR);
2574 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
2575 &poisson_ratio, PETSC_NULLPTR);
2576 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening", &H,
2577 PETSC_NULLPTR);
2578 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening_viscous", &visH,
2579 PETSC_NULLPTR);
2580 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-yield_stress", &sigmaY,
2581 PETSC_NULLPTR);
2582 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn0", &cn0,
2583 PETSC_NULLPTR);
2584 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn1", &cn1,
2585 PETSC_NULLPTR);
2586 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-zeta", &zeta,
2587 PETSC_NULLPTR);
2588 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-Qinf", &Qinf,
2589 PETSC_NULLPTR);
2590 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-b_iso", &b_iso,
2591 PETSC_NULLPTR);
2592 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-C1_k", &C1_k,
2593 PETSC_NULLPTR);
2594 // CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strains",
2595 // &is_large_strains, PETSC_NULLPTR);
2596 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-set_timer", &set_timer,
2597 PETSC_NULLPTR);
2598
2599 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-coeff_expansion",
2600 &default_coeff_expansion, PETSC_NULLPTR);
2601 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ref_temp",
2602 &default_ref_temp, PETSC_NULLPTR);
2603 CHKERR PetscOptionsGetEList("", "-IC_type", ICTypes, 3,
2604 (PetscInt *)&ic_type, PETSC_NULLPTR);
2605 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-init_temp", &init_temp,
2606 PETSC_NULLPTR);
2607 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-peak_temp", &peak_temp,
2608 PETSC_NULLPTR);
2609 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-width", &width,
2610 PETSC_NULLPTR);
2611
2612 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-capacity",
2613 &default_heat_capacity, PETSC_NULLPTR);
2614 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-conductivity",
2615 &default_heat_conductivity, PETSC_NULLPTR);
2616
2617 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-omega_0", &omega_0,
2618 PETSC_NULLPTR);
2619 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-omega_h", &omega_h,
2620 PETSC_NULLPTR);
2621 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-inelastic_heat_fraction",
2622 &inelastic_heat_fraction, PETSC_NULLPTR);
2623 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-temp_0", &temp_0,
2624 PETSC_NULLPTR);
2625
2626 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order,
2627 PETSC_NULLPTR);
2628 PetscBool tau_order_is_set; ///< true if tau order is set
2629 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-tau_order", &tau_order,
2630 &tau_order_is_set);
2631 PetscBool ep_order_is_set; ///< true if tau order is set
2632 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-ep_order", &ep_order,
2633 &ep_order_is_set);
2634 PetscBool flux_order_is_set; ///< true if flux order is set
2635 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-flux_order", &flux_order,
2636 &flux_order_is_set);
2637 PetscBool T_order_is_set; ///< true if T order is set
2638 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-T_order", &T_order,
2639 &T_order_is_set);
2640 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
2641 PETSC_NULLPTR);
2642
2643 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
2644 PETSC_NULLPTR);
2645
2646 CHKERR PetscOptionsGetString(PETSC_NULLPTR, "", "-restart", restart_file,
2647 255, &restart_flg);
2648 sscanf(restart_file, "restart_%d.dat", &restart_step);
2649 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-restart_time",
2650 &restart_time, PETSC_NULLPTR);
2651
2652 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho,
2653 PETSC_NULLPTR);
2654 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
2655 &alpha_damping, PETSC_NULLPTR);
2656
2657 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
2658 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
2659 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
2660 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
2661 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
2662 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
2663 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
2664 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
2665 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
2666 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
2667 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
2668 zeta *= init_dt;
2669 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta * dt " << zeta;
2670
2671 MOFEM_LOG("THERMAL", Sev::inform)
2672 << "default_ref_temp " << default_ref_temp;
2673 MOFEM_LOG("THERMAL", Sev::inform) << "init_temp " << init_temp;
2674 MOFEM_LOG("THERMAL", Sev::inform) << "peak_temp " << peak_temp;
2675 MOFEM_LOG("THERMAL", Sev::inform) << "width " << width;
2676 MOFEM_LOG("THERMAL", Sev::inform)
2677 << "default_coeff_expansion " << default_coeff_expansion;
2678 MOFEM_LOG("THERMAL", Sev::inform)
2679 << "heat_conductivity " << default_heat_conductivity;
2680 MOFEM_LOG("THERMAL", Sev::inform)
2681 << "heat_capacity " << default_heat_capacity;
2682
2683 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
2684 << "inelastic_heat_fraction " << inelastic_heat_fraction;
2685 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "omega_0 " << omega_0;
2686 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "omega_h " << omega_h;
2687
2688 if (tau_order_is_set == PETSC_FALSE)
2689 tau_order = order - 2;
2690 if (ep_order_is_set == PETSC_FALSE)
2691 ep_order = order - 1;
2692
2693 if (flux_order_is_set == PETSC_FALSE)
2694 flux_order = order;
2695 if (T_order_is_set == PETSC_FALSE)
2696 T_order = order - 1;
2697
2698 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
2699 MOFEM_LOG("PLASTICITY", Sev::inform)
2700 << "Ep approximation order " << ep_order;
2701 MOFEM_LOG("PLASTICITY", Sev::inform)
2702 << "Tau approximation order " << tau_order;
2703 MOFEM_LOG("THERMAL", Sev::inform)
2704 << "FLUX approximation order " << flux_order;
2705 MOFEM_LOG("THERMAL", Sev::inform) << "T approximation order " << T_order;
2706 MOFEM_LOG("PLASTICITY", Sev::inform)
2707 << "Geometry approximation order " << geom_order;
2708
2709 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
2710 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
2711
2712 PetscBool is_scale = PETSC_TRUE;
2713 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_scale", &is_scale,
2714 PETSC_NULLPTR);
2715 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Scaling used? " << is_scale;
2716
2717 switch (is_scale) {
2718 case PETSC_TRUE:
2719 MOFEM_LOG("THERMOPLASTICITY", Sev::warning)
2720 << "Scaling does not yet work with radiation and convection BCs";
2721 // FIXME: Need to properly sort scaling as well as when using convection
2722 // and radiation BCs
2724 thermal_conductivity_scaling = [&](double thermal_cond, double heat_cap) {
2725 if (heat_cap != 0.0 && thermal_cond != 0.0)
2726 return 1. / (thermal_cond * heat_cap);
2727 else
2728 return 1. / thermal_cond;
2729 };
2730 heat_capacity_scaling = [&](double thermal_cond, double heat_cap) {
2731 if (heat_cap != 0.0)
2732 return 1. / (thermal_cond * heat_cap);
2733 else
2734 return 1.0;
2735 };
2737 [&](double young_modulus, double thermal_cond, double heat_cap) {
2738 if (heat_cap != 0.0)
2739 return young_modulus / (thermal_cond * heat_cap);
2740 else
2741 return young_modulus / thermal_cond;
2742 };
2743 break;
2744 default:
2745 thermal_conductivity_scaling = [&](double thermal_cond, double heat_cap) {
2746 return 1.0;
2747 };
2748 heat_capacity_scaling = [&](double thermal_cond, double heat_cap) {
2749 return 1.0;
2750 };
2752 double thermal_cond,
2753 double heat_cap) { return 1.0; };
2754 break;
2755 }
2756
2757 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
2758 MOFEM_LOG("THERMAL", Sev::inform)
2759 << "Thermal conductivity scale "
2762 MOFEM_LOG("THERMAL", Sev::inform)
2763 << "Thermal capacity scale "
2766 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
2767 << "Inelastic heat fraction scale "
2770
2771#ifdef ADD_CONTACT
2772 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn_contact",
2773 &ContactOps::cn_contact, PETSC_NULLPTR);
2774 MOFEM_LOG("CONTACT", Sev::inform)
2775 << "cn_contact " << ContactOps::cn_contact;
2776#endif // ADD_CONTACT
2777
2779 };
2780
2781 CHKERR get_command_line_parameters();
2782
2783#ifdef ADD_CONTACT
2784 #ifdef ENABLE_PYTHON_BINDING
2785 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
2786 CHKERR sdfPythonPtr->sdfInit("sdf.py");
2787 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
2788 #endif
2789#endif // ADD_CONTACT
2790
2792}
2793//! [Create common data]
2794
2795//! [Initial conditions]
2798
2799 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
2800
2801 // #ifdef PYTHON_INIT_SURFACE
2802 // auto get_py_surface_init = []() {
2803 // auto py_surf_init = boost::make_shared<SurfacePython>();
2804 // CHKERR py_surf_init->surfaceInit("surface.py");
2805 // surfacePythonWeakPtr = py_surf_init;
2806 // return py_surf_init;
2807 // };
2808 // auto py_surf_init = get_py_surface_init();
2809 // #endif
2810
2811 auto simple = mField.getInterface<Simple>();
2812
2813 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
2814 // "REMOVE_X",
2815 // "U", 0, 0);
2816 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
2817 // "REMOVE_Y",
2818 // "U", 1, 1);
2819 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
2820 // "REMOVE_Z",
2821 // "U", 2, 2);
2822 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
2823 // "REMOVE_ALL", "U", 0, 3);
2824
2825 // #ifdef ADD_CONTACT
2826 // for (auto b : {"FIX_X", "REMOVE_X"})
2827 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
2828 // "SIGMA", 0, 0, false, true);
2829 // for (auto b : {"FIX_Y", "REMOVE_Y"})
2830 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
2831 // "SIGMA", 1, 1, false, true);
2832 // for (auto b : {"FIX_Z", "REMOVE_Z"})
2833 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
2834 // "SIGMA", 2, 2, false, true);
2835 // for (auto b : {"FIX_ALL", "REMOVE_ALL"})
2836 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
2837 // "SIGMA", 0, 3, false, true);
2838 // CHKERR bc_mng->removeBlockDOFsOnEntities(
2839 // simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
2840 // #endif
2841
2842 // CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2843 // simple->getProblemName(), "U");
2844
2846
2847 auto T_ptr = boost::make_shared<VectorDouble>();
2848
2849 auto post_proc = [&](auto dm) {
2851
2852 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
2853
2855
2856 post_proc_fe->getOpPtrVector().push_back(
2857 new OpCalculateScalarFieldValues("T", T_ptr));
2858 // post_proc_fe->getOpPtrVector().push_back(
2859 // new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
2860 if (atom_test == 8) {
2861
2862 auto TAU_ptr = boost::make_shared<VectorDouble>();
2863 auto EP_ptr = boost::make_shared<MatrixDouble>();
2864
2865 post_proc_fe->getOpPtrVector().push_back(
2866 new OpCalculateScalarFieldValues("TAU", TAU_ptr));
2867 post_proc_fe->getOpPtrVector().push_back(
2869
2870 post_proc_fe->getOpPtrVector().push_back(
2871
2872 new OpPPMap(post_proc_fe->getPostProcMesh(),
2873 post_proc_fe->getMapGaussPts(),
2874
2875 {{"T", T_ptr}, {"TAU", TAU_ptr}},
2876
2877 {},
2878
2879 {},
2880
2881 {{"EP", EP_ptr}}
2882
2883 )
2884
2885 );
2886 } else {
2887 post_proc_fe->getOpPtrVector().push_back(
2888
2889 new OpPPMap(post_proc_fe->getPostProcMesh(),
2890 post_proc_fe->getMapGaussPts(),
2891
2892 {{"T", T_ptr}},
2893
2894 {},
2895
2896 {},
2897
2898 {}
2899
2900 )
2901
2902 );
2903 }
2904
2905 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", post_proc_fe);
2906 CHKERR post_proc_fe->writeFile("out_init.h5m");
2907
2909 };
2910
2911 auto solve_init = [&]() {
2913
2914 auto set_domain_rhs = [&](auto &pip) {
2916
2918 "GEOMETRY");
2919
2920 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
2921 pip.push_back(new OpRhsSetInitT<AT, IT>(
2922 "T", nullptr, T_ptr, nullptr, boost::make_shared<double>(init_temp),
2923 boost::make_shared<double>(peak_temp)));
2924
2925 if (atom_test == 8) {
2926 auto TAU_ptr = boost::make_shared<VectorDouble>();
2927 auto EP_ptr = boost::make_shared<MatrixDouble>();
2928
2929 pip.push_back(new OpCalculateScalarFieldValues("TAU", TAU_ptr));
2930 auto min_tau = boost::make_shared<double>(1.0);
2931 auto max_tau = boost::make_shared<double>(2.0);
2932 pip.push_back(new OpRhsSetInitT<AT, IT>("TAU", nullptr, TAU_ptr,
2933 nullptr, min_tau, max_tau));
2934
2936 "EP", EP_ptr));
2937 auto min_EP = boost::make_shared<double>(0.0);
2938 auto max_EP = boost::make_shared<double>(0.01);
2940 "EP", nullptr, EP_ptr, nullptr, min_EP, max_EP));
2941 }
2942
2943 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
2944 // AT>::template LinearForm<IT>;
2945 // using OpInternalForceCauchy =
2946 // typename B::template OpGradTimesSymTensor<1, SPACE_DIM, SPACE_DIM>;
2947 // using OpInternalForcePiola =
2948 // typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
2949
2950 // using P = PlasticityIntegrators<DomainEleOp>;
2951
2952 // auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
2953 // common_thermoelastic_ptr, common_thermoplastic_ptr] =
2954 // createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
2955 // mField, "MAT_ELASTIC", "MAT_THERMAL", "MAT_THERMOPLASTIC", pip,
2956 // "U", "EP", "TAU", "T", scale, thermal_conductivity_scale,
2957 // heat_capacity_scale, inelastic_heat_fraction_scale,
2958 // Sev::inform);
2959 // auto m_D_ptr = common_hencky_ptr->matDPtr;
2960
2961 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
2962 // AT>::template LinearForm<IT>;
2963 // using H = HenckyOps::HenckyIntegrators<DomainEleOp>;
2964 // auto coeff_expansion_ptr = common_thermal_ptr->getCoeffExpansionPtr();
2965 // auto ref_temp_ptr = common_thermal_ptr->getRefTempPtr();
2966 // pip.push_back(new
2967 // typename H::template
2968 // OpCalculateHenckyThermalStress<SPACE_DIM, IT>(
2969 // "U", T_ptr, common_hencky_ptr,
2970 // coeff_expansion_ptr, ref_temp_ptr));
2971 // pip.push_back(new typename H::template
2972 // OpCalculatePiolaStress<SPACE_DIM, IT>(
2973 // "U", common_hencky_ptr));
2974 // using OpInternalForcePiola =
2975 // typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
2976 // pip.push_back(new OpInternalForcePiola(
2977 // "U", common_hencky_ptr->getMatFirstPiolaStress()));
2978
2980 };
2981
2982 auto set_domain_lhs = [&](auto &pip) {
2984
2986 "GEOMETRY");
2987
2988 using OpLhsScalarLeastSquaresProj = FormsIntegrators<
2989 DomainEleOp>::Assembly<AT>::BiLinearForm<IT>::OpMass<1, 1>;
2990 pip.push_back(new OpLhsScalarLeastSquaresProj("T", "T"));
2991 if (atom_test == 8) {
2992 pip.push_back(new OpLhsScalarLeastSquaresProj("TAU", "TAU"));
2993 pip.push_back(
2995 "EP", "EP"));
2996 }
2997
2998 // auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
2999 // common_thermoelastic_ptr, common_thermoplastic_ptr] =
3000 // createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
3001 // mField, "MAT_ELASTIC", "MAT_THERMAL", "MAT_THERMOPLASTIC", pip,
3002 // "U", "EP", "TAU", "T", scale, thermal_conductivity_scale,
3003 // heat_capacity_scale, inelastic_heat_fraction_scale,
3004 // Sev::inform);
3005
3006 // auto m_D_ptr = common_hencky_ptr->matDPtr;
3007
3008 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
3009 // AT>::template BiLinearForm<IT>;
3010 // using OpKPiola = typename B::template OpGradTensorGrad<1, SPACE_DIM,
3011 // SPACE_DIM, 1>;
3012
3013 // using H = HenckyIntegrators<DomainEleOp>;
3014 // pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
3015 // auto coeff_expansion_ptr = common_thermal_ptr->getCoeffExpansionPtr();
3016 // auto ref_temp_ptr = common_thermal_ptr->getRefTempPtr();
3017 // pip.push_back(new
3018 // typename H::template
3019 // OpCalculateHenckyThermalStress<SPACE_DIM, IT>(
3020 // "U", T_ptr, common_hencky_ptr,
3021 // coeff_expansion_ptr, ref_temp_ptr));
3022 // pip.push_back(new typename H::template
3023 // OpCalculatePiolaStress<SPACE_DIM, IT>(
3024 // "U", common_hencky_ptr));
3025 // pip.push_back(new typename H::template OpHenckyTangent<SPACE_DIM, IT>(
3026 // "U", common_hencky_ptr));
3027 // pip.push_back(new OpKPiola("U", "U",
3028 // common_hencky_ptr->getMatTangent()));
3029 // pip.push_back(new typename HenckyOps::OpCalculateHenckyThermalStressdT<
3030 // SPACE_DIM, IT, AssemblyDomainEleOp>("U", "T",
3031 // common_hencky_ptr,
3032 // coeff_expansion_ptr));
3033
3035 };
3036
3037 auto create_sub_dm = [&](SmartPetscObj<DM> base_dm) {
3038 auto dm_sub = createDM(mField.get_comm(), "DMMOFEM");
3039 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "INIT_DM");
3040 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
3041 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
3042 for (auto f : {"T"}) {
3045 }
3046 if (atom_test == 8) {
3047 for (auto f : {"TAU", "EP"}) {
3050 }
3051 }
3052 CHKERR DMSetUp(dm_sub);
3053 return dm_sub;
3054 };
3055
3056 auto fe_rhs = boost::make_shared<DomainEle>(mField);
3057 auto fe_lhs = boost::make_shared<DomainEle>(mField);
3058 fe_rhs->getRuleHook = vol_rule;
3059 fe_lhs->getRuleHook = vol_rule;
3060 CHKERR set_domain_rhs(fe_rhs->getOpPtrVector());
3061 CHKERR set_domain_lhs(fe_lhs->getOpPtrVector());
3062
3063 auto sub_dm = create_sub_dm(simple->getDM());
3064
3065 auto null_fe = boost::shared_ptr<FEMethod>();
3066 CHKERR DMMoFEMKSPSetComputeOperators(sub_dm, simple->getDomainFEName(),
3067 fe_lhs, null_fe, null_fe);
3068 CHKERR DMMoFEMKSPSetComputeRHS(sub_dm, simple->getDomainFEName(), fe_rhs,
3069 null_fe, null_fe);
3070
3071 auto ksp = MoFEM::createKSP(mField.get_comm());
3072 CHKERR KSPSetDM(ksp, sub_dm);
3073 CHKERR KSPSetFromOptions(ksp);
3074
3075 auto D = createDMVector(sub_dm);
3076
3077 CHKERR KSPSolve(ksp, PETSC_NULLPTR, D);
3078
3079 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
3080 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
3081 CHKERR DMoFEMMeshToGlobalVector(sub_dm, D, INSERT_VALUES, SCATTER_REVERSE);
3082
3084 };
3085
3086 CHKERR solve_init();
3087 CHKERR post_proc(simple->getDM());
3088
3089 MOFEM_LOG("THERMAL", Sev::inform) << "Set thermoelastic initial conditions";
3090
3092}
3093//! [Initial conditions]
3094
3095//! [Mechanical boundary conditions]
3098
3099 auto simple = mField.getInterface<Simple>();
3100 auto bc_mng = mField.getInterface<BcManager>();
3101
3102 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
3103 "U", 0, 0, true,
3105 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
3106 "U", 1, 1, true,
3108 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
3109 "U", 2, 2, true,
3111 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3112 "REMOVE_ALL", "U", 0, 3, true,
3114
3115#ifdef ADD_CONTACT
3116 for (auto b : {"FIX_X", "REMOVE_X"})
3117 CHKERR bc_mng->removeBlockDOFsOnEntities(
3118 simple->getProblemName(), b, "SIGMA", 0, 0, false, is_distributed_mesh);
3119 for (auto b : {"FIX_Y", "REMOVE_Y"})
3120 CHKERR bc_mng->removeBlockDOFsOnEntities(
3121 simple->getProblemName(), b, "SIGMA", 1, 1, false, is_distributed_mesh);
3122 for (auto b : {"FIX_Z", "REMOVE_Z"})
3123 CHKERR bc_mng->removeBlockDOFsOnEntities(
3124 simple->getProblemName(), b, "SIGMA", 2, 2, false, is_distributed_mesh);
3125 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
3126 CHKERR bc_mng->removeBlockDOFsOnEntities(
3127 simple->getProblemName(), b, "SIGMA", 0, 3, false, is_distributed_mesh);
3128 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3129 "NO_CONTACT", "SIGMA", 0, 3, false,
3131#endif
3132
3133 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
3134 simple->getProblemName(), "U");
3135
3136 auto &bc_map = bc_mng->getBcMapByBlockName();
3137 for (auto bc : bc_map)
3138 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
3139
3141}
3142//! [Mechanical boundary conditions]
3143
3144//! [Thermal boundary conditions]
3147
3148 MOFEM_LOG("SYNC", Sev::noisy) << "bC";
3150
3151 auto simple = mField.getInterface<Simple>();
3152 auto bc_mng = mField.getInterface<BcManager>();
3153
3154 auto get_skin = [&]() {
3155 Range body_ents;
3156 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
3157 Skinner skin(&mField.get_moab());
3158 Range skin_ents;
3159 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
3160 return skin_ents;
3161 };
3162
3163 auto filter_flux_blocks = [&](auto skin, bool temp_bc = false) {
3164 auto remove_cubit_blocks = [&](auto c) {
3166 for (auto m :
3167
3168 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(c)
3169
3170 ) {
3171 Range ents;
3172 CHKERR mField.get_moab().get_entities_by_dimension(
3173 m->getMeshset(), SPACE_DIM - 1, ents, true);
3174 skin = subtract(skin, ents);
3175 }
3177 };
3178
3179 auto remove_named_blocks = [&](auto n) {
3181 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
3182 std::regex(
3183
3184 (boost::format("%s(.*)") % n).str()
3185
3186 ))
3187
3188 ) {
3189 Range ents;
3190 CHKERR mField.get_moab().get_entities_by_dimension(
3191 m->getMeshset(), SPACE_DIM - 1, ents, true);
3192 skin = subtract(skin, ents);
3193 }
3195 };
3196 if (!temp_bc) {
3197 CHK_THROW_MESSAGE(remove_cubit_blocks(NODESET | TEMPERATURESET),
3198 "remove_cubit_blocks");
3199 CHK_THROW_MESSAGE(remove_named_blocks("TEMPERATURE"),
3200 "remove_named_blocks");
3201 }
3202 CHK_THROW_MESSAGE(remove_cubit_blocks(SIDESET | HEATFLUXSET),
3203 "remove_cubit_blocks");
3204 CHK_THROW_MESSAGE(remove_named_blocks("HEATFLUX"), "remove_named_blocks");
3205 CHK_THROW_MESSAGE(remove_named_blocks("CONVECTION"), "remove_named_blocks");
3206 CHK_THROW_MESSAGE(remove_named_blocks("RADIATION"), "remove_named_blocks");
3207 return skin;
3208 };
3209
3210 auto filter_true_skin = [&](auto skin) {
3211 Range boundary_ents;
3212 ParallelComm *pcomm =
3213 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
3214 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
3215 PSTATUS_NOT, -1, &boundary_ents);
3216 return boundary_ents;
3217 };
3218
3219 auto remove_flux_ents = filter_true_skin(filter_flux_blocks(get_skin()));
3220 auto remove_temp_bc_ents =
3221 filter_true_skin(filter_flux_blocks(get_skin(), true));
3222
3223 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
3224 remove_flux_ents);
3225 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
3226 remove_temp_bc_ents);
3227
3228 MOFEM_LOG("SYNC", Sev::noisy) << remove_flux_ents << endl;
3230
3231 MOFEM_LOG("SYNC", Sev::noisy) << remove_temp_bc_ents << endl;
3233
3234#ifndef NDEBUG
3235
3237 mField.get_moab(),
3238 (boost::format("flux_remove_%d.vtk") % mField.get_comm_rank()).str(),
3239 remove_flux_ents);
3240
3241#endif
3242
3243 if (is_distributed_mesh == PETSC_TRUE) {
3244 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
3245 simple->getProblemName(), "FLUX", remove_flux_ents);
3246 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
3247 simple->getProblemName(), "TBC", remove_temp_bc_ents);
3248 } else {
3250 ->removeDofsOnEntitiesNotDistributed(simple->getProblemName(), "FLUX",
3251 remove_flux_ents);
3253 ->removeDofsOnEntitiesNotDistributed(simple->getProblemName(), "TBC",
3254 remove_temp_bc_ents);
3255 }
3256
3257 // auto set_init_temp = [](boost::shared_ptr<FieldEntity> field_entity_ptr) {
3258 // field_entity_ptr->getEntFieldData()[0] = init_temp;
3259 // return 0;
3260 // };
3261 // CHKERR
3262 // mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(set_init_temp,
3263 // "T");
3264
3265 CHKERR bc_mng->pushMarkDOFsOnEntities<HeatFluxCubitBcData>(
3266 simple->getProblemName(), "FLUX", false);
3267
3269}
3270//! [Thermal Boundary conditions]
3271
3272//! [Push operators to pipeline]
3275 auto pip_mng = mField.getInterface<PipelineManager>();
3276 auto simple = mField.getInterface<Simple>();
3277 auto bc_mng = mField.getInterface<BcManager>();
3278
3279 auto boundary_marker =
3280 bc_mng->getMergedBlocksMarker(vector<string>{"HEATFLUX"});
3281
3282 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
3283
3284 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
3285
3286 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
3287 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
3288
3289 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
3290 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
3291
3292 auto thermal_block_params =
3293 boost::make_shared<ThermoElasticOps::BlockedThermalParameters>();
3294 auto heat_conductivity_ptr = thermal_block_params->getHeatConductivityPtr();
3295 auto heat_capacity_ptr = thermal_block_params->getHeatCapacityPtr();
3296
3297 auto thermoelastic_block_params =
3298 boost::make_shared<ThermoElasticOps::BlockedThermoElasticParameters>();
3299 auto coeff_expansion_ptr = thermoelastic_block_params->getCoeffExpansionPtr();
3300 auto ref_temp_ptr = thermoelastic_block_params->getRefTempPtr();
3301
3302 // Default time scaling of BCs and sources, from command line arguments
3303 auto time_scale =
3304 boost::make_shared<TimeScale>("", false, [](const double) { return 1; });
3305 auto def_time_scale = [time_scale](const double time) {
3306 return (!time_scale->argFileScale) ? time : 1;
3307 };
3308 auto def_file_name = [time_scale](const std::string &&name) {
3309 return (!time_scale->argFileScale) ? name : "";
3310 };
3311
3312 // Files which define scaling for separate variables, if provided
3313 auto time_bodyforce_scaling = boost::make_shared<TimeScale>(
3314 def_file_name("bodyforce_scale.txt"), false, def_time_scale);
3315 auto time_heatsource_scaling = boost::make_shared<TimeScale>(
3316 def_file_name("heatsource_scale.txt"), false, def_time_scale);
3317 auto time_temperature_scaling = boost::make_shared<TimeScale>(
3318 def_file_name("temperature_bc_scale.txt"), false, def_time_scale);
3319 auto time_displacement_scaling = boost::make_shared<TimeScale>(
3320 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
3321 auto time_flux_scaling = boost::make_shared<TimeScale>(
3322 def_file_name("flux_bc_scale.txt"), false, def_time_scale);
3323 auto time_force_scaling = boost::make_shared<TimeScale>(
3324 def_file_name("force_bc_scale.txt"), false, def_time_scale);
3325
3326 auto add_boundary_ops_lhs = [&](auto &pip) {
3328
3329 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3330
3332 "GEOMETRY");
3333 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
3334
3335 // Add Natural BCs to LHS
3337 pip, mField, "U", Sev::inform);
3338
3339#ifdef ADD_CONTACT
3340 CHKERR
3341 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
3342 pip, "SIGMA", "U");
3343 CHKERR
3344 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
3345 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "GEOMETRY",
3346 vol_rule);
3347#endif // ADD_CONTACT
3348
3349 using T =
3350 NaturalBC<BoundaryEleOp>::template Assembly<PETSC>::BiLinearForm<GAUSS>;
3351 using OpConvectionLhsBC =
3352 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
3353 using OpRadiationLhsBC =
3354 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
3355 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
3356 pip.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
3357 T::AddFluxToPipeline<OpConvectionLhsBC>::add(pip, mField, "TBC", "TBC",
3358 "CONVECTION", Sev::verbose);
3359 T::AddFluxToPipeline<OpRadiationLhsBC>::add(
3360 pip, mField, "TBC", "TBC", temp_bc_ptr, "RADIATION", Sev::verbose);
3361
3362 // This is temporary implementation. It be moved to LinearFormsIntegrators,
3363 // however for hybridised case, what is goal of this changes, such function
3364 // is implemented for fluxes in broken space. Thus ultimately this operator
3365 // would be not needed.
3366
3367 struct OpTBCTimesNormalFlux
3369
3371
3372 OpTBCTimesNormalFlux(const std::string row_field_name,
3373 const std::string col_field_name,
3374 boost::shared_ptr<Range> ents_ptr = nullptr)
3375 : OP(row_field_name, col_field_name, OP::OPROWCOL, ents_ptr) {
3376 this->sYmm = false;
3377 this->assembleTranspose = true;
3378 this->onlyTranspose = false;
3379 }
3380
3381 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
3382 EntitiesFieldData::EntData &col_data) {
3384
3386
3387 // get integration weights
3388 auto t_w = OP::getFTensor0IntegrationWeight();
3389 // get base function values on rows
3390 auto t_row_base = row_data.getFTensor0N();
3391 // get normal vector
3392 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3393 // loop over integration points
3394 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3395 // loop over rows base functions
3396 auto a_mat_ptr = &*OP::locMat.data().begin();
3397 int rr = 0;
3398 for (; rr != OP::nbRows; rr++) {
3399 // take into account Jacobian
3400 const double alpha = t_w * t_row_base;
3401 // get column base functions values at gauss point gg
3402 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
3403 // loop over columns
3404 for (int cc = 0; cc != OP::nbCols; cc++) {
3405 // calculate element of local matrix
3406 // using L2 norm of normal vector for convenient area calculation
3407 // for quads, tris etc.
3408 *a_mat_ptr += alpha * (t_col_base(i) * t_normal(i));
3409 ++t_col_base;
3410 ++a_mat_ptr;
3411 }
3412 ++t_row_base;
3413 }
3414 for (; rr < OP::nbRowBaseFunctions; ++rr)
3415 ++t_row_base;
3416 ++t_normal;
3417 ++t_w; // move to another integration weight
3418 }
3419 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3420 if (fe_type == MBTRI) {
3421 OP::locMat /= 2;
3422 }
3424 }
3425 };
3426
3427 pip.push_back(new OpTBCTimesNormalFlux("TBC", "FLUX"));
3428
3430 };
3431
3432 auto add_boundary_ops_rhs = [&](auto &pip) {
3434
3436 "GEOMETRY");
3437 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
3438
3440 pip, mField, "U", {time_scale, time_force_scaling}, "FORCE",
3441 Sev::inform);
3442
3443 // Temperature BC
3444
3445 using OpTemperatureBC =
3448 pip, mField, "FLUX", {time_scale, time_temperature_scaling},
3449 "TEMPERATURE", Sev::inform);
3450
3451 // Note: fluxes for temperature should be aggregated. Here separate is
3452 // NaturalMeshsetType<HEATFLUXSET>, we should add version with BLOCKSET,
3453 // convection, see example tutorials/vec-0/src/NaturalBoundaryBC.hpp.
3454 // and vec-0/elastic.cpp
3455
3456 using OpFluxBC =
3459 pip, mField, "TBC", {time_scale, time_flux_scaling}, "FLUX",
3460 Sev::inform);
3461
3463 using OpConvectionRhsBC =
3464 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
3465 using OpRadiationRhsBC =
3466 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
3467 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
3468 pip.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
3469 T::AddFluxToPipeline<OpConvectionRhsBC>::add(
3470 pip, mField, "TBC", temp_bc_ptr, "CONVECTION", Sev::inform);
3471 T::AddFluxToPipeline<OpRadiationRhsBC>::add(pip, mField, "TBC", temp_bc_ptr,
3472 "RADIATION", Sev::inform);
3473
3474 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3475 pip.push_back(
3476 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3477
3478 // This is temporary implementation. It be moved to LinearFormsIntegrators,
3479 // however for hybridised case, what is goal of this changes, such function
3480 // is implemented for fluxes in broken space. Thus ultimately this operator
3481 // would be not needed.
3482
3483 struct OpTBCTimesNormalFlux
3485
3487
3488 OpTBCTimesNormalFlux(const std::string field_name,
3489 boost::shared_ptr<MatrixDouble> vec,
3490 boost::shared_ptr<Range> ents_ptr = nullptr)
3491 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
3492
3493 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
3496 // get integration weights
3497 auto t_w = OP::getFTensor0IntegrationWeight();
3498 // get base function values on rows
3499 auto t_row_base = row_data.getFTensor0N();
3500 // get normal vector
3501 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3502 // get vector values
3503 auto t_vec = getFTensor1FromMat<SPACE_DIM, 1>(*sourceVec);
3504 // loop over integration points
3505 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3506 // take into account Jacobian
3507 const double alpha = t_w * (t_vec(i) * t_normal(i));
3508 // loop over rows base functions
3509 int rr = 0;
3510 for (; rr != OP::nbRows; ++rr) {
3511 OP::locF[rr] += alpha * t_row_base;
3512 ++t_row_base;
3513 }
3514 for (; rr < OP::nbRowBaseFunctions; ++rr)
3515 ++t_row_base;
3516 ++t_w; // move to another integration weight
3517 ++t_vec;
3518 ++t_normal;
3519 }
3520 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3521 if (fe_type == MBTRI) {
3522 OP::locF /= 2;
3523 }
3525 }
3526
3527 protected:
3528 boost::shared_ptr<MatrixDouble> sourceVec;
3529 };
3530 pip.push_back(new OpTBCTimesNormalFlux("TBC", mat_flux_ptr));
3531
3532 struct OpBaseNormalTimesTBC
3534
3536
3537 OpBaseNormalTimesTBC(const std::string field_name,
3538 boost::shared_ptr<VectorDouble> vec,
3539 boost::shared_ptr<Range> ents_ptr = nullptr)
3540 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
3541
3542 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
3545 // get integration weights
3546 auto t_w = OP::getFTensor0IntegrationWeight();
3547 // get base function values on rows
3548 auto t_row_base = row_data.getFTensor1N<3>();
3549 // get normal vector
3550 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3551 // get vector values
3552 auto t_vec = getFTensor0FromVec(*sourceVec);
3553 // loop over integration points
3554 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3555 // take into account Jacobian
3556 const double alpha = t_w * t_vec;
3557 // loop over rows base functions
3558 int rr = 0;
3559 for (; rr != OP::nbRows; ++rr) {
3560 OP::locF[rr] += alpha * (t_row_base(i) * t_normal(i));
3561 ++t_row_base;
3562 }
3563 for (; rr < OP::nbRowBaseFunctions; ++rr)
3564 ++t_row_base;
3565 ++t_w; // move to another integration weight
3566 ++t_vec;
3567 ++t_normal;
3568 }
3569 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3570 if (fe_type == MBTRI) {
3571 OP::locF /= 2;
3572 }
3574 }
3575
3576 protected:
3577 boost::shared_ptr<VectorDouble> sourceVec;
3578 };
3579
3580 pip.push_back(new OpBaseNormalTimesTBC("FLUX", temp_bc_ptr));
3581
3582#ifdef ADD_CONTACT
3583 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
3584 pip, "SIGMA", "U");
3585#endif // ADD_CONTACT
3586
3588 };
3589
3590 auto add_domain_ops_lhs = [&](auto &pip) {
3592
3593 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3594
3596 mField, pip, "MAT_THERMAL", thermal_block_params,
3600
3602 "GEOMETRY");
3603
3604 if (is_quasi_static == PETSC_FALSE) {
3605
3606 //! [Only used for dynamics]
3609 //! [Only used for dynamics]
3610
3611 auto get_inertia_and_mass_damping = [this](const double, const double,
3612 const double) {
3613 auto *pip = mField.getInterface<PipelineManager>();
3614 auto &fe_domain_lhs = pip->getDomainLhsFE();
3615 return (rho / scale) * fe_domain_lhs->ts_aa +
3616 (alpha_damping / scale) * fe_domain_lhs->ts_a;
3617 };
3618 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
3619 }
3620
3621 CHKERR opThermoPlasticFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
3622 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
3623 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T");
3624
3625 auto hencky_common_data_ptr =
3626 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
3627 mField, pip, "U", "MAT_PLASTIC", Sev::inform, scale);
3628 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
3629 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
3630
3631 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3632
3633 auto resistance = [heat_conductivity_ptr](const double, const double,
3634 const double) {
3635 return (1. / (*heat_conductivity_ptr));
3636 };
3637 auto capacity = [heat_capacity_ptr](const double, const double,
3638 const double) {
3639 return -(*heat_capacity_ptr);
3640 };
3641
3642 pip.push_back(new OpHdivHdiv("FLUX", "FLUX", resistance, mat_grad_ptr));
3643 pip.push_back(
3644 new OpHdivT("FLUX", "T", []() constexpr { return -1; }, true));
3645
3646 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3647 pip.push_back(
3648 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3649
3650 pip.push_back(
3651 new OpHdivU("FLUX", "U", mat_flux_ptr, resistance, mat_grad_ptr));
3652
3653 auto op_capacity = new OpCapacity("T", "T", capacity);
3654 op_capacity->feScalingFun = [](const FEMethod *fe_ptr) {
3655 return fe_ptr->ts_a;
3656 };
3657 pip.push_back(op_capacity);
3658
3659 pip.push_back(new OpUnSetBc("FLUX"));
3660
3661 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
3662 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
3664 pip, mField, "T", vec_temp_ptr, "SETTEMP", Sev::verbose);
3665
3666 pip.push_back(new OpUnSetBc("FLUX"));
3667
3669 };
3670
3671 auto add_domain_ops_rhs = [&](auto &pip) {
3673
3674 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3675
3677 mField, pip, "MAT_THERMAL", thermal_block_params,
3681
3683 "GEOMETRY");
3684
3685 auto hencky_common_data_ptr =
3686 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
3687 mField, pip, "U", "MAT_PLASTIC", Sev::inform, scale);
3688 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
3689 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
3690 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
3691 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
3692
3693 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
3694 auto vec_temp_dot_ptr = boost::make_shared<VectorDouble>();
3695 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3696 auto vec_temp_div_ptr = boost::make_shared<VectorDouble>();
3697
3698 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
3699 pip.push_back(new OpCalculateScalarFieldValuesDot("T", vec_temp_dot_ptr));
3701 "FLUX", vec_temp_div_ptr));
3702 pip.push_back(
3703 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3704
3705 auto resistance = [heat_conductivity_ptr](const double, const double,
3706 const double) {
3707 return (1. / (*heat_conductivity_ptr));
3708 };
3709 // negative value is consequence of symmetric system
3710 auto capacity = [heat_capacity_ptr](const double, const double,
3711 const double) {
3712 return -(*heat_capacity_ptr);
3713 };
3714 auto unity = [](const double, const double, const double) constexpr {
3715 return -1.;
3716 };
3717 pip.push_back(
3718 new OpHdivFlux("FLUX", mat_flux_ptr, resistance, mat_grad_ptr));
3719 pip.push_back(new OpHDivTemp("FLUX", vec_temp_ptr, unity));
3720 pip.push_back(new OpBaseDivFlux("T", vec_temp_div_ptr, unity));
3721 pip.push_back(new OpBaseDotT("T", vec_temp_dot_ptr, capacity));
3722
3724 pip, mField, "U",
3725 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
3726 Sev::inform);
3727
3728 // only in case of dynamics
3729 if (is_quasi_static == PETSC_FALSE) {
3730
3731 //! [Only used for dynamics]
3734 //! [Only used for dynamics]
3735
3736 auto mat_acceleration = boost::make_shared<MatrixDouble>();
3738 "U", mat_acceleration));
3739 pip.push_back(
3740 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
3741 return rho / scale;
3742 }));
3743 if (alpha_damping > 0) {
3744 auto mat_velocity = boost::make_shared<MatrixDouble>();
3745 pip.push_back(
3746 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
3747 pip.push_back(
3748 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
3749 return alpha_damping / scale;
3750 }));
3751 }
3752 }
3753
3754 CHKERR opThermoPlasticFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
3755 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
3756 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T");
3757
3758#ifdef ADD_CONTACT
3759 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
3760 pip, "SIGMA", "U");
3761#endif // ADD_CONTACT
3762
3763 pip.push_back(new OpUnSetBc("FLUX"));
3764
3766 };
3767
3768 auto create_reaction_pipeline = [&](auto &pip) {
3771 "GEOMETRY");
3772 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
3773 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
3775 };
3776
3777 reactionFe = boost::make_shared<DomainEle>(mField);
3778 reactionFe->getRuleHook = vol_rule;
3779 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
3780 reactionFe->postProcessHook =
3782
3783 // Set BCs by eliminating degrees of freedom
3784 auto get_bc_hook_rhs = [&]() {
3786 mField, pip_mng->getDomainRhsFE(),
3787 {time_scale, time_displacement_scaling});
3788 return hook;
3789 };
3790 auto get_bc_hook_lhs = [&]() {
3792 mField, pip_mng->getDomainLhsFE(),
3793 {time_scale, time_displacement_scaling});
3794 return hook;
3795 };
3796
3797 pip_mng->getDomainRhsFE()->preProcessHook = get_bc_hook_rhs();
3798 pip_mng->getDomainLhsFE()->preProcessHook = get_bc_hook_lhs();
3799
3800 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
3801 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
3802
3803 // Boundary
3804 CHKERR add_boundary_ops_lhs(pip_mng->getOpBoundaryLhsPipeline());
3805 CHKERR add_boundary_ops_rhs(pip_mng->getOpBoundaryRhsPipeline());
3806
3808}
3809//! [Push operators to pipeline]
3810
3811//! [Solve]
3812struct SetUpSchur {
3813
3814 /**
3815 * @brief Create data structure for handling Schur complement
3816 *
3817 * @param m_field
3818 * @param sub_dm Schur complement sub dm
3819 * @param field_split_it IS of Schur block
3820 * @param ao_map AO map from sub dm to main problem
3821 * @return boost::shared_ptr<SetUpSchur>
3822 */
3823 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
3824
3825 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
3826 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
3827
3828 );
3829 virtual MoFEMErrorCode setUp(TS solver) = 0;
3830
3831protected:
3832 SetUpSchur() = default;
3833};
3834
3835struct MyTsCtx {
3836 boost::shared_ptr<MoFEM::TsCtx> dmts_ctx;
3837 PetscInt snes_iter_counter = 0;
3838};
3839
3840static std::unordered_map<TS, MyTsCtx *> ts_to_ctx;
3841
3842MoFEMErrorCode TSIterationPreStage(TS ts, PetscReal stagetime) {
3844 MyTsCtx *my_ctx = ts_to_ctx[ts];
3845 my_ctx->snes_iter_counter = 0;
3847}
3848
3849// Monitor function
3850MoFEMErrorCode SNESIterationMonitor(SNES snes, PetscInt its, PetscReal norm,
3851 void *ctx) {
3853 MyTsCtx *my_ctx = static_cast<MyTsCtx *>(ctx);
3854 my_ctx->snes_iter_counter++;
3856}
3857
3858PetscErrorCode MyTSResizeSetup(TS ts, PetscInt nstep, PetscReal time, Vec sol,
3859 PetscBool *resize, void *ctx) {
3860 PetscFunctionBegin;
3861 ResizeCtx *rctx = static_cast<ResizeCtx *>(ctx);
3862 *resize = rctx->mesh_changed;
3863 PetscFunctionReturn(0);
3864}
3865
3866PetscErrorCode MyTSResizeTransfer(TS ts, PetscInt nv, Vec ts_vecsin[],
3867 Vec ts_vecsout[], void *ctx) {
3868 PetscFunctionBegin;
3869 ResizeCtx *rctx = static_cast<ResizeCtx *>(ctx);
3870
3871 MOFEM_LOG("REMESHING", Sev::verbose) << "number of vectors to map = " << nv;
3872
3873 for (PetscInt i = 0; i < nv; ++i) {
3874 double nrm;
3875 CHKERR VecNorm(ts_vecsin[i], NORM_2, &nrm);
3876 MOFEM_LOG("REMESHING", Sev::warning)
3877 << "Before remeshing: ts_vecsin[" << i << "] norm = " << nrm;
3878 }
3879
3880 if (auto ptr = tsPrePostProc.lock()) {
3881
3882 MoFEM::Interface &m_field = *(rctx->m_field);
3883
3884 MOFEM_LOG("REMESHING", Sev::verbose)
3885 << "rctx->all_old_els = " << rctx->all_old_els;
3886 MOFEM_LOG("REMESHING", Sev::verbose)
3887 << "rctx->new_elements = " << rctx->new_elements;
3888 MOFEM_LOG("REMESHING", Sev::verbose)
3889 << "rctx->flipped_els = " << rctx->flipped_els;
3890
3891 auto scatter_mng = m_field.getInterface<VecManager>();
3892 auto simple = m_field.getInterface<Simple>();
3893
3894 // Rebuilding DM with old and new mesh entities
3895 auto bit = BitRefLevel().set();
3897 {"T", "TAU", "EP"}, {T_order, tau_order, ep_order}, bit);
3898
3899 auto intermediate_dm = createDM(m_field.get_comm(), "DMMOFEM");
3900 CHKERR DMMoFEMCreateMoFEM(intermediate_dm, &m_field, "INTERMEDIATE_DM",
3901 BitRefLevel().set(),
3902 BitRefLevel().set(BITREFLEVEL_SIZE - 1).flip());
3903 CHKERR DMMoFEMSetDestroyProblem(intermediate_dm, PETSC_TRUE);
3904 CHKERR DMSetFromOptions(intermediate_dm);
3905 CHKERR DMMoFEMAddElement(intermediate_dm, simple->getDomainFEName());
3906 CHKERR DMMoFEMSetSquareProblem(intermediate_dm, PETSC_TRUE);
3908 CHKERR DMSetUp(intermediate_dm);
3909
3910 Vec vec_in[nv], vec_out[nv];
3911 for (PetscInt i = 0; i < nv; ++i) {
3912 CHKERR DMCreateGlobalVector(intermediate_dm, &vec_in[i]);
3913 CHKERR VecDuplicate(vec_in[i], &vec_out[i]);
3914 }
3915
3916 VecScatter scatter_to_intermediate;
3917
3918 for (PetscInt i = 0; i < nv; ++i) {
3919 CHKERR scatter_mng->vecScatterCreate(
3920 ts_vecsin[i], simple->getProblemName(), RowColData::ROW, vec_in[i],
3921 "INTERMEDIATE_DM", RowColData::ROW, &scatter_to_intermediate);
3922 CHKERR VecScatterBegin(scatter_to_intermediate, ts_vecsin[i], vec_in[i],
3923 INSERT_VALUES, SCATTER_FORWARD);
3924 CHKERR VecScatterEnd(scatter_to_intermediate, ts_vecsin[i], vec_in[i],
3925 INSERT_VALUES, SCATTER_FORWARD);
3926 }
3927
3928 CHKERR VecScatterDestroy(&scatter_to_intermediate);
3929
3931 CHKERR DMSetUp_MoFEM(intermediate_dm);
3932
3933 constexpr bool do_fake_mapping = false;
3934 if (do_fake_mapping) {
3935 auto tmp_D = createDMVector(intermediate_dm);
3936 CHKERR DMoFEMMeshToLocalVector(intermediate_dm, tmp_D, INSERT_VALUES,
3937 SCATTER_FORWARD);
3938 CHKERR VecCopy(vec_in[0], vec_out[0]);
3939
3940 auto sub_dm = createDM(m_field.get_comm(), "DMMOFEM");
3941 CHKERR DMSetType(sub_dm, "DMMOFEM");
3942 CHKERR DMMoFEMCreateSubDM(sub_dm, intermediate_dm, "SUB_MAPPING");
3943 CHKERR DMMoFEMAddElement(sub_dm, simple->getDomainFEName());
3944 CHKERR DMMoFEMSetSquareProblem(sub_dm, PETSC_TRUE);
3945 CHKERR DMMoFEMSetDestroyProblem(sub_dm, PETSC_TRUE);
3946
3947 MOFEM_LOG("REMESHING", Sev::inform) << "Created sub DpoM";
3948
3949 for (auto f : {"T", "TAU", "EP"}) {
3951 sub_dm, f, boost::make_shared<Range>(rctx->new_elements));
3953 sub_dm, f, boost::make_shared<Range>(rctx->new_elements));
3954 }
3955
3956 auto bit = BitRefLevel().set();
3957 CHKERR m_field.modify_problem_ref_level_set_bit("SUB_MAPPING", bit);
3958 CHKERR m_field.modify_problem_mask_ref_level_set_bit("SUB_MAPPING", bit);
3959
3961 CHKERR DMSubDMSetUp_MoFEM(sub_dm);
3962
3963 auto fe_method = boost::make_shared<DomainEle>(m_field);
3964 CHKERR DMoFEMLoopFiniteElements(sub_dm, simple->getDomainFEName(),
3965 fe_method);
3966
3967 CHKERR DMoFEMMeshToLocalVector(intermediate_dm, tmp_D, INSERT_VALUES,
3968 SCATTER_REVERSE);
3969 } else {
3971 intermediate_dm, rctx->all_old_els, rctx->new_elements,
3972 rctx->flipped_els, nv, vec_in, vec_out);
3973 }
3974
3975 // Build problem on new bit ref level
3976 auto ts_problem_name = simple->getProblemName();
3977 CHKERR m_field.modify_problem_ref_level_set_bit(ts_problem_name,
3978 BitRefLevel().set(1));
3980 ts_problem_name, BitRefLevel().set(BITREFLEVEL_SIZE - 1).flip());
3982 CHKERR DMSetUp_MoFEM(simple->getDM());
3983
3984#ifndef NDEBUG
3985
3986 // e10 -> e11 (old to new) no flipped
3987 // e10 -> e10 old flipped
3988 // -> e01 new flliped
3989 // e11, e01 -> bit01 mask 11 (all)
3990
3991 if (m_field.get_comm_rank() == 0) {
3992 MOFEM_LOG("REMESHING", Sev::verbose)
3993 << "Writing debug VTK files for remeshing verification";
3994 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
3995 BitRefLevel().set(0), BitRefLevel().set(0), 2, "bit_0_mask_0.vtk",
3996 "VTK", ""); // that are elements on old which are flipped
3997 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
3998 BitRefLevel().set(0), BitRefLevel().set(), 2, "bit_0_mask_all.vtk",
3999 "VTK", ""); // all old elements
4000 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4001 BitRefLevel().set(1), BitRefLevel().set(1), 2, "bit_1_mask_1.vtk",
4002 "VTK", ""); // that are new elements
4003 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4004 BitRefLevel().set(1), BitRefLevel().set(), 2, "bit_1_mask_all.vtk",
4005 "VTK", ""); // all new elements
4006 }
4007#endif // NDEBUG
4008
4009 VecScatter scatter_to_final;
4010
4011 for (PetscInt i = 0; i < nv; ++i) {
4012 CHKERR DMCreateGlobalVector(simple->getDM(), &ts_vecsout[i]);
4013 CHKERR scatter_mng->vecScatterCreate(
4014 ts_vecsout[i], simple->getProblemName(), RowColData::ROW, vec_out[i],
4015 "INTERMEDIATE_DM", RowColData::ROW, &scatter_to_final);
4016 CHKERR VecScatterBegin(scatter_to_final, vec_out[i], ts_vecsout[i],
4017 INSERT_VALUES, SCATTER_REVERSE);
4018 CHKERR VecScatterEnd(scatter_to_final, vec_out[i], ts_vecsout[i],
4019 INSERT_VALUES, SCATTER_REVERSE);
4020 CHKERR VecScatterDestroy(&scatter_to_final);
4021 }
4022
4023 for (PetscInt i = 0; i < nv; ++i) {
4024 CHKERR VecDestroy(&vec_in[i]);
4025 CHKERR VecDestroy(&vec_out[i]);
4026 }
4027
4028 // Squash and change bit ref level back
4029 auto bit_mng = m_field.getInterface<BitRefManager>();
4030
4031 Range flipped_ents;
4032 CHKERR bit_mng->getEntitiesByRefLevel(BitRefLevel().set(0),
4033 BitRefLevel().set(0), flipped_ents);
4034 CHKERR bit_mng->addBitRefLevel(flipped_ents,
4035 BitRefLevel().set(BITREFLEVEL_SIZE - 1));
4036 BitRefLevel shift_mask = BitRefLevel().set(BITREFLEVEL_SIZE - 1);
4037 shift_mask.flip();
4038 CHKERR bit_mng->shiftRightBitRef(1, shift_mask);
4039 CHKERR m_field.modify_problem_ref_level_set_bit(ts_problem_name,
4040 BitRefLevel().set(0));
4041 // CHKERR DMMoFEMSetIsPartitioned(simple->getDM(), is_distributed_mesh);
4042 // CHKERR DMSetUp_MoFEM(simple->getDM());
4043
4044 CHKERR TSSetDM(ts, simple->getDM());
4045 auto B = createDMMatrix(simple->getDM());
4046 CHKERR TSSetIJacobian(ts, B, B, nullptr, nullptr);
4047 rctx->mesh_changed = PETSC_FALSE;
4048 }
4049
4050 for (PetscInt i = 0; i < nv; ++i) {
4051 double nrm;
4052 CHKERR VecNorm(ts_vecsout[i], NORM_2, &nrm);
4053 MOFEM_LOG("REMESHING", Sev::warning)
4054 << "After remeshing: ts_vecsout[" << i << "] norm = " << nrm;
4055 }
4056
4057 PetscFunctionReturn(0);
4058}
4059
4061
4064
4067 ISManager *is_manager = mField.getInterface<ISManager>();
4068
4069 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
4070
4071 auto set_section_monitor = [&](auto solver) {
4073 SNES snes;
4074 CHKERR TSGetSNES(solver, &snes);
4075 CHKERR SNESMonitorSet(snes,
4076 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
4077 void *))MoFEMSNESMonitorFields,
4078 (void *)(snes_ctx_ptr.get()), nullptr);
4080 };
4081
4082 auto create_post_process_elements = [&]() {
4083 auto pp_fe = boost::make_shared<PostProcEle>(mField);
4084
4085 auto push_vol_ops = [this](auto &pip) {
4087 "GEOMETRY");
4088
4089 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4090 return 1.;
4091 };
4092 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4093 const double) { return 1.; };
4094
4095 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4096 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4097 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4098 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4099 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T", 1., unity_2_args,
4100 unity_2_args, unity_3_args, Sev::inform);
4101
4102 if (common_hencky_ptr) {
4103 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
4104 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
4105 }
4106
4107 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
4108 common_thermoplastic_ptr);
4109 };
4110
4111 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
4113
4114 auto &pip = pp_fe->getOpPtrVector();
4115
4116 auto [common_plastic_ptr, common_hencky_ptr, common_thermoplastic_ptr] =
4117 p;
4118
4119 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
4120 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
4121
4122 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
4123 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
4124
4125 auto u_ptr = boost::make_shared<MatrixDouble>();
4126 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
4127
4129
4130 auto x_ptr = boost::make_shared<MatrixDouble>();
4131 pip.push_back(
4132 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
4133
4134 if (is_large_strains) {
4135
4136 pip.push_back(
4137
4138 new OpPPMap(
4139
4140 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
4141
4142 {{"ISOTROPIC_HARDENING",
4143 common_plastic_ptr->getPlasticIsoHardeningPtr()},
4144 {"PLASTIC_SURFACE",
4145 common_plastic_ptr->getPlasticSurfacePtr()},
4146 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()},
4147 {"T", common_thermoplastic_ptr->getTempPtr()}},
4148
4149 {{"U", u_ptr},
4150 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()},
4151 {"GEOMETRY", x_ptr}},
4152
4153 {{"GRAD", common_hencky_ptr->matGradPtr},
4154 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
4155
4156 {{"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
4157 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()},
4158 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
4159 {"HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()}}
4160
4161 )
4162
4163 );
4164
4165 } else {
4166
4167 pip.push_back(
4168
4169 new OpPPMap(
4170
4171 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
4172
4173 {{"PLASTIC_SURFACE",
4174 common_plastic_ptr->getPlasticSurfacePtr()},
4175 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()},
4176 {"T", common_thermoplastic_ptr->getTempPtr()}},
4177
4178 {{"U", u_ptr},
4179 {"GEOMETRY", x_ptr},
4180 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
4181
4182 {},
4183
4184 {{"STRAIN", common_plastic_ptr->mStrainPtr},
4185 {"STRESS", common_plastic_ptr->mStressPtr},
4186 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
4187 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
4188
4189 )
4190
4191 );
4192 }
4193
4195 };
4196
4197 // Defaults to outputting volume for 2D and skin for 3D
4198 PetscBool post_proc_vol = PETSC_FALSE;
4199 PetscBool post_proc_skin = PETSC_TRUE;
4200 switch (SPACE_DIM) {
4201 case 2:
4202 post_proc_vol = PETSC_TRUE;
4203 post_proc_skin = PETSC_FALSE;
4204 break;
4205 case 3:
4206 post_proc_vol = PETSC_FALSE;
4207 post_proc_skin = PETSC_TRUE;
4208 break;
4209 default:
4210 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "SPACE_DIM neither 2 nor 3");
4211 break;
4212 }
4213 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol",
4214 &post_proc_vol, PETSC_NULLPTR);
4215 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
4216 &post_proc_skin, PETSC_NULLPTR);
4217
4218 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
4219 &post_proc_vol]() {
4220 if (post_proc_vol == PETSC_FALSE)
4221 return boost::shared_ptr<PostProcEle>();
4222 auto pp_fe = boost::make_shared<PostProcEle>(mField);
4224 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
4225 "push_vol_post_proc_ops");
4226 return pp_fe;
4227 };
4228
4229 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
4230 &post_proc_skin]() {
4231 if (post_proc_skin == PETSC_FALSE)
4232 return boost::shared_ptr<SkinPostProcEle>();
4233
4234 auto simple = mField.getInterface<Simple>();
4235 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
4236 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
4237 SPACE_DIM, Sev::verbose);
4238 pp_fe->getOpPtrVector().push_back(op_side);
4239 CHK_MOAB_THROW(push_vol_post_proc_ops(
4240 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
4241 "push_vol_post_proc_ops");
4242 return pp_fe;
4243 };
4244
4245 return std::make_pair(vol_post_proc(), skin_post_proc());
4246 };
4247
4248 auto scatter_create = [&](auto D, auto coeff) {
4250 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
4251 ROW, "U", coeff, coeff, is);
4252 int loc_size;
4253 CHKERR ISGetLocalSize(is, &loc_size);
4254 Vec v;
4255 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
4256 VecScatter scatter;
4257 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
4258 return std::make_tuple(SmartPetscObj<Vec>(v),
4259 SmartPetscObj<VecScatter>(scatter));
4260 };
4261
4262 boost::shared_ptr<SetPtsData> field_eval_data;
4263 boost::shared_ptr<MatrixDouble> u_field_ptr;
4264
4265 std::array<double, 3> field_eval_coords = {0., 0., 0.};
4266 int coords_dim = 3;
4267 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
4268 field_eval_coords.data(), &coords_dim,
4269 &do_eval_field);
4270
4271 boost::shared_ptr<std::map<std::string, boost::shared_ptr<VectorDouble>>>
4272 scalar_field_ptrs = boost::make_shared<
4273 std::map<std::string, boost::shared_ptr<VectorDouble>>>();
4274 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4275 vector_field_ptrs = boost::make_shared<
4276 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4277 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4278 sym_tensor_field_ptrs = boost::make_shared<
4279 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4280 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4281 tensor_field_ptrs = boost::make_shared<
4282 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4283
4284 auto test_monitor_ptr = boost::make_shared<FEMethod>();
4285
4286 if (do_eval_field && atom_test == 0) {
4287 field_eval_data =
4288 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
4289 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
4290 field_eval_data, simple->getDomainFEName());
4291
4292 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
4293 auto no_rule = [](int, int, int) { return -1; };
4294 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
4295 field_eval_fe_ptr->getRuleHook = no_rule;
4296
4298 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV}, "GEOMETRY");
4299
4300 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4301 return 1.;
4302 };
4303 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4304 const double) { return 1.; };
4305
4306 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4307 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4308 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4309 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4310 "MAT_THERMOPLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U", "EP",
4311 "TAU", "T", 1., unity_2_args, unity_2_args, unity_3_args,
4312 Sev::inform);
4313
4314 auto u_field_ptr = boost::make_shared<MatrixDouble>();
4315 field_eval_fe_ptr->getOpPtrVector().push_back(
4316 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_field_ptr));
4317 auto T_field_ptr = boost::make_shared<VectorDouble>();
4318 field_eval_fe_ptr->getOpPtrVector().push_back(
4319 new OpCalculateScalarFieldValues("T", T_field_ptr));
4320 auto FLUX_field_ptr = boost::make_shared<MatrixDouble>();
4321 field_eval_fe_ptr->getOpPtrVector().push_back(
4322 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", FLUX_field_ptr));
4323
4324 if ((common_plastic_ptr) && (common_hencky_ptr) && (scalar_field_ptrs)) {
4325 if (is_large_strains) {
4326 scalar_field_ptrs->insert(std::make_pair("TEMPERATURE", T_field_ptr));
4327 scalar_field_ptrs->insert(std::make_pair(
4328 "PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()));
4329 scalar_field_ptrs->insert(std::make_pair(
4330 "PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()));
4331 vector_field_ptrs->insert(std::make_pair("U", u_field_ptr));
4332 vector_field_ptrs->insert(std::make_pair("FLUX", FLUX_field_ptr));
4333 sym_tensor_field_ptrs->insert(std::make_pair(
4334 "PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()));
4335 sym_tensor_field_ptrs->insert(std::make_pair(
4336 "PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()));
4337 sym_tensor_field_ptrs->insert(std::make_pair(
4338 "HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()));
4339 sym_tensor_field_ptrs->insert(
4340 std::make_pair("HENCKY_STRAIN", common_hencky_ptr->getMatLogC()));
4341 tensor_field_ptrs->insert(
4342 std::make_pair("GRAD", common_hencky_ptr->matGradPtr));
4343 tensor_field_ptrs->insert(std::make_pair(
4344 "FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()));
4345 } else {
4346 scalar_field_ptrs->insert(std::make_pair("TEMPERATURE", T_field_ptr));
4347 scalar_field_ptrs->insert(std::make_pair(
4348 "PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()));
4349 scalar_field_ptrs->insert(std::make_pair(
4350 "PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()));
4351 vector_field_ptrs->insert(std::make_pair("U", u_field_ptr));
4352 vector_field_ptrs->insert(std::make_pair("FLUX", FLUX_field_ptr));
4353 sym_tensor_field_ptrs->insert(
4354 std::make_pair("STRAIN", common_plastic_ptr->mStrainPtr));
4355 sym_tensor_field_ptrs->insert(
4356 std::make_pair("STRESS", common_plastic_ptr->mStressPtr));
4357 sym_tensor_field_ptrs->insert(std::make_pair(
4358 "PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()));
4359 sym_tensor_field_ptrs->insert(std::make_pair(
4360 "PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()));
4361 }
4362 }
4363 } else if (atom_test > 0) {
4364 field_eval_data =
4365 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
4366
4367 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
4368 field_eval_data, simple->getDomainFEName());
4369
4370 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
4371 auto no_rule = [](int, int, int) { return -1; };
4372
4373 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
4374 field_eval_fe_ptr->getRuleHook = no_rule;
4375
4377 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV});
4378
4379 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4380 return 1.;
4381 };
4382 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4383 const double) { return 1.; };
4384
4385 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4386 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4387 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4388 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4389 "MAT_THERMOPLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U", "EP",
4390 "TAU", "T", 1, unity_2_args, unity_2_args, unity_3_args,
4391 Sev::inform);
4392
4393 auto dispGradPtr = common_hencky_ptr->matGradPtr;
4394 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
4395
4396 auto coeff_expansion_ptr = common_thermoelastic_ptr->getCoeffExpansionPtr();
4397 auto ref_temp_ptr = common_thermoelastic_ptr->getRefTempPtr();
4398
4399 field_eval_fe_ptr->getOpPtrVector().push_back(
4400 new OpCalculateScalarFieldValues("T", tempFieldPtr));
4401 field_eval_fe_ptr->getOpPtrVector().push_back(
4402 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", fluxFieldPtr));
4403 field_eval_fe_ptr->getOpPtrVector().push_back(
4404 new OpCalculateVectorFieldValues<SPACE_DIM>("U", dispFieldPtr));
4405 field_eval_fe_ptr->getOpPtrVector().push_back(
4407 dispGradPtr));
4408 plasticMultiplierFieldPtr = common_plastic_ptr->getPlasticTauPtr();
4409 plasticStrainFieldPtr = common_plastic_ptr->getPlasticStrainPtr();
4410
4412
4413 field_eval_fe_ptr->getOpPtrVector().push_back(
4414 new typename H::template OpCalculateHenckyThermoPlasticStress<SPACE_DIM,
4415 IT, 0>(
4416 "U", tempFieldPtr, common_hencky_ptr, coeff_expansion_ptr,
4417 ref_temp_ptr));
4418 if (!IS_LARGE_STRAINS) {
4419 field_eval_fe_ptr->getOpPtrVector().push_back(
4421 common_hencky_ptr->getMatFirstPiolaStress(), stressFieldPtr));
4422 field_eval_fe_ptr->getOpPtrVector().push_back(
4423 new OpSymmetrizeTensor<SPACE_DIM>(dispGradPtr, strainFieldPtr));
4424 } else {
4425 field_eval_fe_ptr->getOpPtrVector().push_back(
4426 new typename H::template OpCalculateLogC<SPACE_DIM, IT>(
4427 "U", common_hencky_ptr));
4428 stressFieldPtr = common_hencky_ptr->getMatFirstPiolaStress();
4429 strainFieldPtr = common_hencky_ptr->getMatLogC();
4430 };
4431 }
4432
4433 auto set_time_monitor = [&](auto dm, auto solver) {
4435 if (atom_test == 0) {
4436 boost::shared_ptr<Monitor<SPACE_DIM>> monitor_ptr(new Monitor<SPACE_DIM>(
4437 dm, create_post_process_elements(), reactionFe, uXScatter, uYScatter,
4438 uZScatter, field_eval_coords, field_eval_data, scalar_field_ptrs,
4439 vector_field_ptrs, sym_tensor_field_ptrs, tensor_field_ptrs));
4440 boost::shared_ptr<ForcesAndSourcesCore> null;
4441 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
4442 monitor_ptr, null, null);
4443 } else {
4444
4445 test_monitor_ptr->preProcessHook = [&]() {
4447
4448 CHKERR mField.getInterface<FieldEvaluatorInterface>()
4449 ->evalFEAtThePoint<SPACE_DIM>(
4450 field_eval_coords.data(), 1e-12, simple->getProblemName(),
4451 simple->getDomainFEName(), field_eval_data,
4452 mField.get_comm_rank(), mField.get_comm_rank(), nullptr,
4453 MF_EXIST, QUIET);
4454
4455 auto eval_num_vec = createVectorMPI(mField.get_comm(), PETSC_DECIDE, 1);
4456 CHKERR VecZeroEntries(eval_num_vec);
4457 if (tempFieldPtr->size()) {
4458 CHKERR VecSetValue(eval_num_vec, 0, 1, ADD_VALUES);
4459 }
4460 CHKERR VecAssemblyBegin(eval_num_vec);
4461 CHKERR VecAssemblyEnd(eval_num_vec);
4462
4463 double eval_num;
4464 CHKERR VecSum(eval_num_vec, &eval_num);
4465 if (!(int)eval_num) {
4466 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4467 "atom test %d failed: did not find elements to evaluate "
4468 "the field, check the coordinates",
4469 atom_test);
4470 }
4471
4472 if (tempFieldPtr->size()) {
4473 auto t_temp = getFTensor0FromVec(*tempFieldPtr);
4474 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4475 << "Eval point T magnitude: " << t_temp;
4476 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4477 if (atom_test <= 3 && fabs(t_temp - 554.48) > 1e-2) {
4478 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4479 "atom test %d failed: wrong temperature value",
4480 atom_test);
4481 }
4482 if (atom_test == 4 && fabs(t_temp - 250) > 1e-2) {
4483 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4484 "atom test %d failed: wrong temperature value",
4485 atom_test);
4486 }
4487 if (atom_test == 5 && fabs(t_temp - 1) > 1e-2) {
4488 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4489 "atom test %d failed: wrong temperature value",
4490 atom_test);
4491 }
4492 }
4493 if (atom_test == 8 && fabs(t_temp - 0.5) > 1e-12) {
4494 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4495 "atom test %d failed: wrong temperature value", atom_test);
4496 }
4497 }
4498 if (fluxFieldPtr->size1()) {
4500 auto t_flux = getFTensor1FromMat<SPACE_DIM>(*fluxFieldPtr);
4501 auto flux_mag = sqrt(t_flux(i) * t_flux(i));
4502 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4503 << "Eval point FLUX magnitude: " << flux_mag;
4504 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4505 if (atom_test <= 3 && fabs(flux_mag - 27008.0) > 2e1) {
4506 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4507 "atom test %d failed: wrong flux value", atom_test);
4508 }
4509 if (atom_test == 4 && fabs(flux_mag - 150e3) > 1e-1) {
4510 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4511 "atom test %d failed: wrong flux value", atom_test);
4512 }
4513 if (atom_test == 5 && fabs(flux_mag) > 1e-6) {
4514 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4515 "atom test %d failed: wrong flux value", atom_test);
4516 }
4517 }
4518 }
4519 if (dispFieldPtr->size1()) {
4521 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*dispFieldPtr);
4522 auto disp_mag = sqrt(t_disp(i) * t_disp(i));
4523 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4524 << "Eval point U magnitude: " << disp_mag;
4525 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4526 if (atom_test == 1 && fabs(disp_mag - 0.00345) > 1e-5) {
4527 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4528 "atom test %d failed: wrong displacement value",
4529 atom_test);
4530 }
4531 if ((atom_test == 2 || atom_test == 3) &&
4532 fabs(disp_mag - 0.00265) > 1e-5) {
4533 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4534 "atom test %d failed: wrong displacement value",
4535 atom_test);
4536 }
4537 if ((atom_test == 5) &&
4538 fabs(t_disp(0) - (std::sqrt(std::exp(0.2)) - 1)) > 1e-5 &&
4539 fabs(t_disp(1) - (std::sqrt(std::exp(0.2)) - 1)) > 1e-5) {
4540 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4541 "atom test %d failed: wrong displacement value",
4542 atom_test);
4543 }
4544 }
4545 }
4546 if (strainFieldPtr->size1()) {
4548 auto t_strain =
4549 getFTensor2SymmetricFromMat<SPACE_DIM>(*strainFieldPtr);
4550 auto t_strain_trace = t_strain(i, i);
4551 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4552 if (atom_test == 1 && fabs(t_strain_trace - 0.00679) > 1e-5) {
4553 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4554 "atom test %d failed: wrong strain value", atom_test);
4555 }
4556 if ((atom_test == 2 || atom_test == 3) &&
4557 fabs(t_strain_trace - 0.00522) > 1e-5) {
4558 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4559 "atom test %d failed: wrong strain value", atom_test);
4560 }
4561 if ((atom_test == 5) && fabs(t_strain_trace - 0.2) > 1e-5) {
4562 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4563 "atom test %d failed: wrong strain value", atom_test);
4564 }
4565 }
4566 }
4567 if (stressFieldPtr->size1()) {
4568 double von_mises_stress;
4569 auto getVonMisesStress = [&](auto t_stress) {
4571 von_mises_stress = std::sqrt(
4572 0.5 *
4573 ((t_stress(0, 0) - t_stress(1, 1)) *
4574 (t_stress(0, 0) - t_stress(1, 1)) +
4575 (SPACE_DIM == 3 ? (t_stress(1, 1) - t_stress(2, 2)) *
4576 (t_stress(1, 1) - t_stress(2, 2))
4577 : 0) +
4578 (SPACE_DIM == 3 ? (t_stress(2, 2) - t_stress(0, 0)) *
4579 (t_stress(2, 2) - t_stress(0, 0))
4580 : 0) +
4581 6 * (t_stress(0, 1) * t_stress(0, 1) +
4582 (SPACE_DIM == 3 ? t_stress(1, 2) * t_stress(1, 2) : 0) +
4583 (SPACE_DIM == 3 ? t_stress(2, 0) * t_stress(2, 0) : 0))));
4585 };
4586 if (!IS_LARGE_STRAINS) {
4587 auto t_stress =
4588 getFTensor2SymmetricFromMat<SPACE_DIM>(*stressFieldPtr);
4589 CHKERR getVonMisesStress(t_stress);
4590 } else {
4591 auto t_stress =
4592 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*stressFieldPtr);
4593 CHKERR getVonMisesStress(t_stress);
4594 }
4595 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4596 << "Eval point von Mises Stress: " << von_mises_stress;
4597 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4598 if (atom_test == 1 && fabs(von_mises_stress - 523.0) > 5e-1) {
4599 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4600 "atom test %d failed: wrong von Mises stress value",
4601 atom_test);
4602 }
4603 if (atom_test == 2 && fabs(von_mises_stress - 16.3) > 5e-2) {
4604 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4605 "atom test %d failed: wrong von Mises stress value",
4606 atom_test);
4607 }
4608 if (atom_test == 3 && fabs(von_mises_stress - 14.9) > 5e-2) {
4609 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4610 "atom test %d failed: wrong von Mises stress value",
4611 atom_test);
4612 }
4613 if (atom_test == 5 && fabs(von_mises_stress) > 5e-2) {
4614 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4615 "atom test %d failed: wrong von Mises stress value",
4616 atom_test);
4617 }
4618 }
4619 }
4620 if (plasticMultiplierFieldPtr->size()) {
4621 auto t_plastic_multiplier =
4622 getFTensor0FromVec(*plasticMultiplierFieldPtr);
4623 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4624 << "Eval point TAU magnitude: " << t_plastic_multiplier;
4625 if (atom_test == 8 && fabs(t_plastic_multiplier - 1.5) > 1e-12) {
4626 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4627 "atom test %d failed: wrong plastic multiplier value",
4628 atom_test);
4629 }
4630 }
4631 if (plasticStrainFieldPtr->size1()) {
4634 auto t_plastic_strain =
4635 getFTensor2SymmetricFromMat<SPACE_DIM>(*plasticStrainFieldPtr);
4636 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4637 << "Eval point EP(0,0) = " << t_plastic_strain(0, 0)
4638 << ", EP(0,1) = " << t_plastic_strain(0, 1)
4639 << ", EP(1,1) = " << t_plastic_strain(1, 1);
4640 if (atom_test == 8) {
4641 if (fabs(t_plastic_strain(0, 0) - 0.005) > 1e-12) {
4642 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4643 "atom test %d failed: wrong EP(0,0) value", atom_test);
4644 }
4645 if (fabs(t_plastic_strain(0, 1) - 0.025) > 1e-12) {
4646 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4647 "atom test %d failed: wrong EP(0,1) value", atom_test);
4648 }
4649 if (fabs(t_plastic_strain(1, 1) - 0.015) > 1e-12) {
4650 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4651 "atom test %d failed: wrong EP(1,1) value", atom_test);
4652 }
4653 }
4654 }
4655
4656 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
4658 };
4659 auto null = boost::shared_ptr<FEMethod>();
4660 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(), null,
4661 test_monitor_ptr, null);
4662 };
4663
4665 };
4666
4667 auto set_schur_pc = [&](auto solver,
4668 boost::shared_ptr<SetUpSchur> &schur_ptr) {
4670
4671 auto name_prb = simple->getProblemName();
4672
4673 // create sub dm for Schur complement
4674 auto create_schur_dm = [&](SmartPetscObj<DM> base_dm,
4675 SmartPetscObj<DM> &dm_sub) {
4677 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
4678 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SCHUR");
4679 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
4680 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
4681 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
4682 for (auto f : {"U", "FLUX"}) {
4685 }
4686 CHKERR DMSetUp(dm_sub);
4687
4689 };
4690
4691 auto create_block_dm = [&](SmartPetscObj<DM> base_dm,
4692 SmartPetscObj<DM> &dm_sub) {
4694 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
4695 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "BLOCK");
4696 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
4697 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
4698 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
4699#ifdef ADD_CONTACT
4700 for (auto f : {"SIGMA", "EP", "TAU", "T"}) {
4703 }
4704#else
4705 for (auto f : {"EP", "TAU", "T"}) {
4708 }
4709#endif
4710 CHKERR DMSetUp(dm_sub);
4712 };
4713
4714 // Create nested (sub BC) Schur DM
4715 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
4716
4717 SmartPetscObj<DM> dm_schur;
4718 CHKERR create_schur_dm(simple->getDM(), dm_schur);
4719 SmartPetscObj<DM> dm_block;
4720 CHKERR create_block_dm(simple->getDM(), dm_block);
4721
4722#ifdef ADD_CONTACT
4723
4724 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
4725 auto block_mat_data = createBlockMatStructure(
4726 simple->getDM(),
4727
4728 {
4729
4730 {simple->getDomainFEName(),
4731
4732 {{"U", "U"},
4733 {"SIGMA", "SIGMA"},
4734 {"U", "SIGMA"},
4735 {"SIGMA", "U"},
4736 {"EP", "EP"},
4737 {"TAU", "TAU"},
4738 {"U", "EP"},
4739 {"EP", "U"},
4740 {"EP", "TAU"},
4741 {"TAU", "EP"},
4742 {"TAU", "U"},
4743 {"T", "T"},
4744 {"U", "T"},
4745 {"T", "U"},
4746 {"EP", "T"},
4747 {"T", "EP"},
4748 {"TAU", "T"},
4749 {"T", "TAU"}
4750
4751 }},
4752
4753 {simple->getBoundaryFEName(),
4754
4755 {{"SIGMA", "SIGMA"}, {"U", "SIGMA"}, {"SIGMA", "U"}
4756
4757 }}
4758
4759 }
4760
4761 );
4762
4764
4765 {dm_schur, dm_block}, block_mat_data,
4766
4767 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
4768 true
4769
4770 );
4771 };
4772
4773#else
4774
4775 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
4776 auto block_mat_data =
4778
4779 {{simple->getDomainFEName(),
4780
4781 {{"U", "U"},
4782 {"EP", "EP"},
4783 {"TAU", "TAU"},
4784 {"U", "EP"},
4785 {"EP", "U"},
4786 {"EP", "TAU"},
4787 {"TAU", "U"},
4788 {"TAU", "EP"},
4789 {"T", "T"},
4790 {"T", "U"},
4791 {"T", "FLUX"},
4792 {"T", "EP"},
4793 {"FLUX", "T"},
4794 {"FLUX", "U"},
4795 {"U", "T"},
4796 {"EP", "T"},
4797 {"TAU", "T"}
4798
4799 }}}
4800
4801 );
4802
4804
4805 {dm_schur, dm_block}, block_mat_data,
4806
4807 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, false
4808
4809 );
4810 };
4811
4812#endif
4813
4814 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
4815 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
4816
4817 auto block_is = getDMSubData(dm_block)->getSmartRowIs();
4818 auto ao_schur = getDMSubData(dm_schur)->getSmartRowMap();
4819
4820 // Indices has to be map fro very to level, while assembling Schur
4821 // complement.
4822 schur_ptr =
4823 SetUpSchur::createSetUpSchur(mField, dm_schur, block_is, ao_schur);
4824 CHKERR schur_ptr->setUp(solver);
4825 }
4826
4828 };
4829
4830 auto dm = simple->getDM();
4831 auto D = createDMVector(dm);
4832 auto DD = vectorDuplicate(D);
4833 uXScatter = scatter_create(D, 0);
4834 uYScatter = scatter_create(D, 1);
4835 if constexpr (SPACE_DIM == 3)
4836 uZScatter = scatter_create(D, 2);
4837
4838 auto create_solver = [pip_mng]() {
4839 if (is_quasi_static == PETSC_TRUE)
4840 return pip_mng->createTSIM();
4841 else
4842 return pip_mng->createTSIM2();
4843 };
4844
4845 SmartPetscObj<Vec> solution_vector;
4846 CHKERR DMCreateGlobalVector_MoFEM(dm, solution_vector);
4847
4848 if (restart_flg) {
4849 PetscViewer viewer;
4850 CHKERR PetscViewerBinaryOpen(PETSC_COMM_WORLD, restart_file, FILE_MODE_READ,
4851 &viewer);
4852 CHKERR VecLoad(solution_vector, viewer);
4853 CHKERR PetscViewerDestroy(&viewer);
4854 CHKERR DMoFEMMeshToLocalVector(dm, solution_vector, INSERT_VALUES,
4855 SCATTER_REVERSE);
4856 }
4857
4858 auto solver = create_solver();
4859
4860 auto active_pre_lhs = []() {
4862 std::fill(PlasticOps::CommonData::activityData.begin(),
4865 };
4866
4867 auto active_post_lhs = [&]() {
4869 auto get_iter = [&]() {
4870 SNES snes;
4871 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
4872 int iter;
4873 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
4874 "Can not get iter");
4875 return iter;
4876 };
4877
4878 auto iter = get_iter();
4879 if (iter >= 0) {
4880
4881 std::array<int, 5> activity_data;
4882 std::fill(activity_data.begin(), activity_data.end(), 0);
4883 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
4884 activity_data.data(), activity_data.size(), MPI_INT,
4885 MPI_SUM, mField.get_comm());
4886
4887 int &active_points = activity_data[0];
4888 int &avtive_full_elems = activity_data[1];
4889 int &avtive_elems = activity_data[2];
4890 int &nb_points = activity_data[3];
4891 int &nb_elements = activity_data[4];
4892
4893 if (nb_points) {
4894
4895 double proc_nb_points =
4896 100 * static_cast<double>(active_points) / nb_points;
4897 double proc_nb_active =
4898 100 * static_cast<double>(avtive_elems) / nb_elements;
4899 double proc_nb_full_active = 100;
4900 if (avtive_elems)
4901 proc_nb_full_active =
4902 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
4903
4904 MOFEM_LOG_C("PLASTICITY", Sev::inform,
4905 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
4906 "elements %d "
4907 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
4908 iter, nb_points, active_points, proc_nb_points,
4909 avtive_elems, proc_nb_active, avtive_full_elems,
4910 proc_nb_full_active, iter);
4911 }
4912 }
4913
4915 };
4916
4917 auto add_active_dofs_elem = [&](auto dm) {
4919 auto fe_pre_proc = boost::make_shared<FEMethod>();
4920 fe_pre_proc->preProcessHook = active_pre_lhs;
4921 auto fe_post_proc = boost::make_shared<FEMethod>();
4922 fe_post_proc->postProcessHook = active_post_lhs;
4923 auto ts_ctx_ptr = getDMTsCtx(dm);
4924 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
4925 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
4927 };
4928
4929 auto set_essential_bc = [&](auto dm, auto solver) {
4931 // This is low level pushing finite elements (pipelines) to solver
4932
4933 auto pre_proc_ptr = boost::make_shared<FEMethod>();
4934 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
4935 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
4936
4937 // Add boundary condition scaling
4938 auto disp_time_scale = boost::make_shared<TimeScale>();
4939
4940 auto get_bc_hook_rhs = [this, pre_proc_ptr, disp_time_scale]() {
4941 EssentialPreProc<DisplacementCubitBcData> hook(mField, pre_proc_ptr,
4942 {disp_time_scale}, false);
4943 return hook;
4944 };
4945 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
4946
4947 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
4950 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
4952 mField, post_proc_rhs_ptr, 1.)();
4954 };
4955 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
4957 mField, post_proc_lhs_ptr, 1.);
4958 };
4959 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
4960
4961 auto ts_ctx_ptr = getDMTsCtx(dm);
4962 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
4963 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
4964 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
4965 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
4966 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
4967
4969 };
4970
4971 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_FORWARD);
4972
4973 if (is_quasi_static == PETSC_TRUE) {
4974 CHKERR TSSetSolution(solver, D);
4975 } else {
4976 CHKERR TS2SetSolution(solver, D, DD);
4977 }
4978
4979 auto set_up_adapt = [&](auto solver) {
4981 CHKERR TSAdaptRegister(TSADAPTMOFEM, TSAdaptCreateMoFEM);
4982 TSAdapt adapt;
4983 CHKERR TSGetAdapt(solver, &adapt);
4985 };
4986
4987 CHKERR set_section_monitor(solver);
4988 CHKERR set_time_monitor(dm, solver);
4989 CHKERR set_up_adapt(solver);
4990 CHKERR TSSetFromOptions(solver);
4991
4992 thermoplastic_raw_ptr = this;
4993
4994 CHKERR TSSetTime(solver, restart_time);
4995 CHKERR TSSetStepNumber(solver, restart_step);
4996
4997 CHKERR add_active_dofs_elem(dm);
4998 boost::shared_ptr<SetUpSchur> schur_ptr;
4999 CHKERR set_schur_pc(solver, schur_ptr);
5000 CHKERR set_essential_bc(dm, solver);
5001
5002 auto my_ctx = boost::make_shared<MyTsCtx>();
5003
5004 ts_to_ctx[solver] = my_ctx.get();
5005
5006 SNES snes;
5007 CHKERR TSGetSNES(solver, &snes);
5008
5009 CHKERR SNESMonitorSet(snes, SNESIterationMonitor, my_ctx.get(), NULL);
5010
5011 CHKERR TSSetPreStage(solver, TSIterationPreStage);
5012
5013 auto my_rhs = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec F, void *ctx) {
5014 MyTsCtx *my_ts_ctx = static_cast<MyTsCtx *>(ctx);
5015 auto ts_ctx = my_ts_ctx->dmts_ctx;
5016 auto &m_field = ts_ctx->mField;
5017 auto simple = m_field.getInterface<Simple>();
5018
5019 // Get the iteration number of the snes solver
5020 SNES snes;
5021 CHK_THROW_MESSAGE(TSGetSNES(ts, &snes), "Cannot get SNES");
5022
5023 double time_increment;
5024 CHK_THROW_MESSAGE(TSGetTimeStep(ts, &time_increment), "Cannot get iter");
5025 if (time_increment < min_dt) {
5026 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
5027 "Minimum time increment exceeded");
5028 }
5029
5030 if (my_ts_ctx->snes_iter_counter == 0) {
5031 int error = system("rm ./out_snes_residual_iter_*.h5m > /dev/null 2>&1");
5032 }
5033
5034 // Get the time step
5035 double ts_dt;
5036 CHK_THROW_MESSAGE(TSGetTimeStep(ts, &ts_dt),
5037 "Cannot get timestep from TS object");
5038
5039 if (ts_dt < min_dt) {
5040 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
5041 "Minimum timestep exceeded");
5042 }
5043
5044 // Post process the residuals
5045 auto post_proc = [&](auto dm, auto f_res, auto sol, auto sol_dot,
5046 auto out_name) {
5048
5049 auto smart_f_res = SmartPetscObj<Vec>(f_res, true);
5050 auto smart_sol = SmartPetscObj<Vec>(sol, true);
5051 auto smart_sol_dot = SmartPetscObj<Vec>(sol_dot, true);
5052
5053 auto post_proc_fe =
5054 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
5055 ts_ctx->mField);
5056 auto &pip = post_proc_fe->getOpPtrVector();
5058
5060 "GEOMETRY");
5061
5062 // pointers for residuals
5063 auto disp_res_mat = boost::make_shared<MatrixDouble>();
5064 auto tau_res_vec = boost::make_shared<VectorDouble>();
5065 auto plastic_strain_res_mat = boost::make_shared<MatrixDouble>();
5066 auto flux_res_mat = boost::make_shared<MatrixDouble>();
5067 auto temp_res_vec = boost::make_shared<VectorDouble>();
5068
5070 "U", disp_res_mat, smart_f_res));
5071 pip.push_back(
5072 new OpCalculateScalarFieldValues("TAU", tau_res_vec, smart_f_res));
5074 "EP", plastic_strain_res_mat, smart_f_res));
5075 // pip.push_back(
5076 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", flux_res_mat,
5077 // smart_f_res));
5078 pip.push_back(
5079 new OpCalculateScalarFieldValues("T", temp_res_vec, smart_f_res));
5080
5081 // pointers for fields
5082 auto disp_mat = boost::make_shared<MatrixDouble>();
5083 auto tau_vec = boost::make_shared<VectorDouble>();
5084 auto plastic_strain_mat = boost::make_shared<MatrixDouble>();
5085 auto flux_mat = boost::make_shared<MatrixDouble>();
5086 auto temp_vec = boost::make_shared<VectorDouble>();
5087
5088 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", disp_mat));
5089 pip.push_back(new OpCalculateScalarFieldValues("TAU", tau_vec));
5091 "EP", plastic_strain_mat));
5092 // pip.push_back(
5093 // new OpCalculateVectorFieldValues<SPACE_DIM>("FLUX", flux_mat,
5094 // smart_sol));
5095 pip.push_back(new OpCalculateScalarFieldValues("T", temp_vec));
5096
5097 // pointers for rates of fields
5098 auto disp_dot_mat = boost::make_shared<MatrixDouble>();
5099 auto tau_dot_vec = boost::make_shared<VectorDouble>();
5100 auto plastic_strain_dot_mat = boost::make_shared<MatrixDouble>();
5101 auto flux_dot_mat = boost::make_shared<MatrixDouble>();
5102 auto temp_dot_vec = boost::make_shared<VectorDouble>();
5103
5105 "U", disp_dot_mat, smart_sol_dot));
5106 pip.push_back(
5107 new OpCalculateScalarFieldValues("TAU", tau_dot_vec, smart_sol_dot));
5109 "EP", plastic_strain_dot_mat, smart_sol_dot));
5110 // pip.push_back(
5111 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", flux_dot_mat,
5112 // smart_sol_dot));
5113 pip.push_back(
5114 new OpCalculateScalarFieldValues("T", temp_dot_vec, smart_sol_dot));
5115
5116 constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
5117 auto make_d_mat = [&]() {
5118 return boost::make_shared<MatrixDouble>(size_symm * size_symm, 1);
5119 };
5120
5121 auto push_vol_ops = [&](auto &pip) {
5122 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
5123 return 1.;
5124 };
5125 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
5126 const double) { return 1.; };
5127
5128 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
5129 common_thermoelastic_ptr, common_thermoplastic_ptr] =
5132 m_field, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
5133 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T", 1.,
5134 unity_2_args, unity_2_args, unity_3_args, Sev::inform);
5135
5136 if (common_hencky_ptr) {
5137 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
5139 "Wrong pointer for grad");
5140 }
5141
5142 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
5143 common_thermoplastic_ptr);
5144 };
5145
5146 auto push_vol_post_proc_ops = [&](auto &pp_fe, auto &&p) {
5148
5149 auto &pip = pp_fe->getOpPtrVector();
5150
5151 auto [common_plastic_ptr, common_hencky_ptr, common_thermoplastic_ptr] =
5152 p;
5153
5154 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
5155 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
5156
5157 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
5158 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
5159
5160 auto u_ptr = boost::make_shared<MatrixDouble>();
5161 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
5162
5164
5165 auto x_ptr = boost::make_shared<MatrixDouble>();
5166 pip.push_back(
5167 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
5168
5169 if (is_large_strains) {
5170
5171 pip.push_back(
5172
5173 new OpPPMap(
5174
5175 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
5176
5177 {{"RESIDUAL_TAU", tau_res_vec},
5178 {"RESIDUAL_T", temp_res_vec},
5179 {"TAU", tau_vec},
5180 {"T", temp_vec},
5181 {"RATE_TAU", tau_dot_vec},
5182 {"RATE_T", temp_dot_vec},
5183 {"ISOTROPIC_HARDENING",
5184 common_plastic_ptr->getPlasticIsoHardeningPtr()},
5185 {"PLASTIC_SURFACE",
5186 common_plastic_ptr->getPlasticSurfacePtr()},
5187 {"PLASTIC_MULTIPLIER",
5188 common_plastic_ptr->getPlasticTauPtr()},
5189 {"YIELD_FUNCTION",
5190 common_plastic_ptr->getPlasticSurfacePtr()},
5191 {"T", common_thermoplastic_ptr->getTempPtr()}},
5192
5193 {{"RESIDUAL_U", disp_res_mat},
5194 {"RATE_U", disp_dot_mat},
5195 {"U", u_ptr},
5196 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()},
5197 {"GEOMETRY", x_ptr}},
5198
5199 {{"GRAD", common_hencky_ptr->matGradPtr},
5200 {"FIRST_PIOLA",
5201 common_hencky_ptr->getMatFirstPiolaStress()}},
5202
5203 {{"RESIDUAL_EP", plastic_strain_res_mat},
5204 {"RATE_EP", plastic_strain_dot_mat},
5205 {"PLASTIC_STRAIN",
5206 common_plastic_ptr->getPlasticStrainPtr()},
5207 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()},
5208 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
5209 {"HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()}}
5210
5211 )
5212
5213 );
5214
5215 } else {
5216
5217 pip.push_back(
5218
5219 new OpPPMap(
5220
5221 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
5222
5223 {{"RESIDUAL_TAU", tau_res_vec},
5224 {"RESIDUAL_T", temp_res_vec},
5225 {"TAU", tau_vec},
5226 {"T", temp_vec},
5227 {"RATE_TAU", tau_dot_vec},
5228 {"RATE_T", temp_dot_vec},
5229 {"ISOTROPIC_HARDENING",
5230 common_plastic_ptr->getPlasticIsoHardeningPtr()},
5231 {"PLASTIC_SURFACE",
5232 common_plastic_ptr->getPlasticSurfacePtr()},
5233 {"PLASTIC_MULTIPLIER",
5234 common_plastic_ptr->getPlasticTauPtr()},
5235 {"YIELD_FUNCTION",
5236 common_plastic_ptr->getPlasticSurfacePtr()},
5237 {"T", common_thermoplastic_ptr->getTempPtr()}},
5238
5239 {{"RESIDUAL_U", disp_res_mat},
5240 // {"RESIDUAL_FLUX", flux_res_mat},
5241 {"U", disp_mat},
5242 // {"FLUX", flux_mat},
5243 {"RATE_U", disp_dot_mat},
5244 {"U", u_ptr},
5245 {"GEOMETRY", x_ptr},
5246 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
5247
5248 {},
5249
5250 {{"RESIDUAL_PLASTIC_STRAIN", plastic_strain_res_mat},
5251 {"PLASTIC_STRAIN", plastic_strain_mat},
5252 {"RATE_PLASTIC_STRAIN", plastic_strain_dot_mat},
5253 {"STRAIN", common_plastic_ptr->mStrainPtr},
5254 {"STRESS", common_plastic_ptr->mStressPtr},
5255 {"PLASTIC_STRAIN",
5256 common_plastic_ptr->getPlasticStrainPtr()},
5257 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
5258
5259 )
5260
5261 );
5262 }
5263
5265 };
5266
5267 CHK_MOAB_THROW(push_vol_post_proc_ops(post_proc_fe, push_vol_ops(pip)),
5268 "push_vol_post_proc_ops");
5269
5270 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
5271 post_proc_fe);
5272
5273 post_proc_fe->writeFile(out_name);
5275 };
5276
5277 // Output the RHS
5278
5279 auto set_RHS = TsSetIFunction(ts, t, u, u_t, F, ts_ctx.get());
5280 CHKERR post_proc(simple->getDM(),
5281 //
5282 F, u, u_t,
5283 //
5284 "out_snes_residual_iter_" +
5285 std::to_string(my_ts_ctx->snes_iter_counter) + ".h5m");
5286 return set_RHS;
5287 };
5288
5289 PetscBool is_output_residual_fields = PETSC_FALSE;
5290 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-output_residual_fields",
5291 &is_output_residual_fields, PETSC_NULLPTR);
5292
5293 if (is_output_residual_fields == PETSC_TRUE) {
5294 my_ctx->dmts_ctx = getDMTsCtx(simple->getDM());
5295 // auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
5296 CHKERR TSSetIFunction(solver, PETSC_NULLPTR, my_rhs, my_ctx.get());
5297 }
5298
5299 CHKERR TSSetDM(solver, dm);
5300
5301 auto ts_pre_post_proc = boost::make_shared<TSPrePostProc>();
5302 tsPrePostProc = ts_pre_post_proc;
5303
5304 if (auto ptr = tsPrePostProc.lock()) {
5305 ptr->ExRawPtr = this;
5306
5307 Range no_all_old_els, no_new_els, no_flipped_els;
5308 ResizeCtx *ctx = new ResizeCtx{&mField, PETSC_FALSE, no_all_old_els,
5309 no_new_els, no_flipped_els};
5310 PetscBool rollback =
5311 PETSC_TRUE; // choose true if you want to restart current step
5312 CHKERR TSSetResize(solver, rollback, MyTSResizeSetup, MyTSResizeTransfer,
5313 ctx);
5314 CHKERR TSSetApplicationContext(solver, (void *)ctx);
5315 // ptr->globSol = createDMVector(dm);
5316 // CHKERR DMoFEMMeshToLocalVector(dm, ptr->globSol, INSERT_VALUES,
5317 // SCATTER_FORWARD);
5318 // CHKERR VecAssemblyBegin(ptr->globSol);
5319 // CHKERR VecAssemblyEnd(ptr->globSol);
5320 MOFEM_LOG_CHANNEL("TIMER");
5321 MOFEM_LOG_TAG("TIMER", "timer");
5322 if (set_timer)
5323 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
5324 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
5325 CHKERR ptr->tsSetUp(solver);
5326 CHKERR TSSetUp(solver);
5327 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
5328 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
5329 CHKERR TSSolve(solver, PETSC_NULLPTR);
5330 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
5331 }
5332
5334}
5335//! [Solve]
5336
5337static char help[] = "...\n\n";
5338
5339int main(int argc, char *argv[]) {
5340
5341#ifdef ADD_CONTACT
5342 #ifdef ENABLE_PYTHON_BINDING
5343 Py_Initialize();
5344 np::initialize();
5345 #endif
5346#endif // ADD_CONTACT
5347
5348 // Initialisation of MoFEM/PETSc and MOAB data structures
5349 const char param_file[] = "param_file.petsc";
5350 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
5351
5352 // Add logging channel for example
5353 auto core_log = logging::core::get();
5354 core_log->add_sink(
5356 core_log->add_sink(
5358 core_log->add_sink(
5359 LogManager::createSink(LogManager::getStrmWorld(), "THERMOPLASTICITY"));
5360 core_log->add_sink(
5362 core_log->add_sink(
5364 LogManager::setLog("PLASTICITY");
5365 LogManager::setLog("THERMAL");
5366 LogManager::setLog("THERMOPLASTICITY");
5367 LogManager::setLog("REMESHING");
5368 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
5369 MOFEM_LOG_TAG("THERMAL", "Thermal");
5370 MOFEM_LOG_TAG("THERMOPLASTICITY", "Thermoplasticity");
5371 MOFEM_LOG_TAG("REMESHING", "Remeshing");
5372
5373#ifdef ADD_CONTACT
5374 core_log->add_sink(
5376 LogManager::setLog("CONTACT");
5377 MOFEM_LOG_TAG("CONTACT", "Contact");
5378#endif // ADD_CONTACT
5379
5380 try {
5381
5382 //! [Register MoFEM discrete manager in PETSc]
5383 DMType dm_name = "DMMOFEM";
5384 CHKERR DMRegister_MoFEM(dm_name);
5385 //! [Register MoFEM discrete manager in PETSc
5386
5387 //! [Create MoAB]
5388 moab::Core mb_instance; ///< mesh database
5389 moab::Interface &moab = mb_instance; ///< mesh database interface
5390 //! [Create MoAB]
5391
5392 //! [Create MoFEM]
5393 MoFEM::Core core(moab); ///< finite element database
5394 MoFEM::Interface &m_field = core; ///< finite element database interface
5395 //! [Create MoFEM]
5396
5397 //! [Load mesh]
5398 Simple *simple = m_field.getInterface<Simple>();
5400 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_distributed_mesh",
5401 &is_distributed_mesh, PETSC_NULLPTR);
5402 if (is_distributed_mesh == PETSC_TRUE) {
5403 CHKERR simple->loadFile();
5404 } else {
5405 char meshFileName[255];
5406 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-file_name",
5407 meshFileName, 255, PETSC_NULLPTR);
5408 CHKERR simple->loadFile("", meshFileName);
5409 }
5410 //! [Load mesh]
5411
5412 //! [Example]
5413 Example ex(m_field);
5414 CHKERR ex.runProblem();
5415 //! [Example]
5416 }
5418
5420
5421#ifdef ADD_CONTACT
5422 #ifdef ENABLE_PYTHON_BINDING
5423 if (Py_FinalizeEx() < 0) {
5424 exit(120);
5425 }
5426 #endif
5427#endif // ADD_CONTACT
5428
5429 return 0;
5430}
5431
5432struct SetUpSchurImpl : public SetUpSchur {
5433
5435 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
5436 : SetUpSchur(), mField(m_field), subDM(sub_dm),
5437 fieldSplitIS(field_split_is), aoSchur(ao_up) {
5438 if (S) {
5440 "Is expected that schur matrix is not "
5441 "allocated. This is "
5442 "possible only is PC is set up twice");
5443 }
5444 }
5445 virtual ~SetUpSchurImpl() { S.reset(); }
5446
5450
5451private:
5453
5454 MoFEM::Interface &mField;
5455 SmartPetscObj<DM> subDM; ///< field split sub dm
5456 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
5457 SmartPetscObj<AO> aoSchur; ///> main DM to subDM
5458};
5459
5462 auto simple = mField.getInterface<Simple>();
5463 auto pip_mng = mField.getInterface<PipelineManager>();
5464
5465 SNES snes;
5466 CHKERR TSGetSNES(solver, &snes);
5467 KSP ksp;
5468 CHKERR SNESGetKSP(snes, &ksp);
5469 CHKERR KSPSetFromOptions(ksp);
5470
5471 PC pc;
5472 CHKERR KSPGetPC(ksp, &pc);
5473 PetscBool is_pcfs = PETSC_FALSE;
5474 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
5475 if (is_pcfs) {
5476 if (S) {
5478 "Is expected that schur matrix is not "
5479 "allocated. This is "
5480 "possible only is PC is set up twice");
5481 }
5482
5484 CHKERR MatSetBlockSize(S, SPACE_DIM);
5485
5486 // Set DM to use shell block matrix
5487 DM solver_dm;
5488 CHKERR TSGetDM(solver, &solver_dm);
5489 CHKERR DMSetMatType(solver_dm, MATSHELL);
5490
5491 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
5492 auto A = createDMBlockMat(simple->getDM());
5493 auto P = createDMNestSchurMat(simple->getDM());
5494
5495 if (is_quasi_static == PETSC_TRUE) {
5496 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
5497 Mat A, Mat B, void *ctx) {
5498 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
5499 };
5500 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
5501 } else {
5502 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
5503 PetscReal a, PetscReal aa, Mat A, Mat B,
5504 void *ctx) {
5505 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
5506 };
5507 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
5508 }
5509 CHKERR KSPSetOperators(ksp, A, P);
5510
5511 auto set_ops = [&]() {
5513 auto pip_mng = mField.getInterface<PipelineManager>();
5514
5515#ifndef ADD_CONTACT
5516 // Boundary
5517 pip_mng->getOpBoundaryLhsPipeline().push_front(
5519 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
5520
5521 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, aoSchur, S, false,
5522 false
5523
5524 ));
5525 // Domain
5526 pip_mng->getOpDomainLhsPipeline().push_front(
5528 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
5529
5530 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, aoSchur, S, false,
5531 false
5532
5533 ));
5534#else
5535
5536 double eps_stab = 1e-4;
5537 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
5538 PETSC_NULLPTR);
5539
5542 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
5543
5544 // Boundary
5545 pip_mng->getOpBoundaryLhsPipeline().push_front(
5547 pip_mng->getOpBoundaryLhsPipeline().push_back(
5548 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
5549 return eps_stab;
5550 }));
5551 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
5552
5553 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
5554 aoSchur, S, false, false
5555
5556 ));
5557 // Domain
5558 pip_mng->getOpDomainLhsPipeline().push_front(
5560 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
5561
5562 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
5563 aoSchur, S, false, false
5564
5565 ));
5566#endif // ADD_CONTACT
5568 };
5569
5570 auto set_assemble_elems = [&]() {
5572 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
5573 schur_asmb_pre_proc->preProcessHook = [this]() {
5575 CHKERR MatZeroEntries(S);
5576 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
5578 };
5579 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
5580
5581 schur_asmb_post_proc->postProcessHook = [this, schur_asmb_post_proc]() {
5583 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
5584
5585 // Apply essential constrains to Schur complement
5586 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
5587 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
5589 mField, schur_asmb_post_proc, 1, S, aoSchur)();
5590
5592 };
5593 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
5594 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
5595 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
5597 };
5598
5599 auto set_pc = [&]() {
5601 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
5602 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
5604 };
5605
5606 auto set_diagonal_pc = [&]() {
5608 KSP *subksp;
5609 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
5610 auto get_pc = [](auto ksp) {
5611 PC pc_raw;
5612 CHKERR KSPGetPC(ksp, &pc_raw);
5613 return SmartPetscObj<PC>(pc_raw,
5614 true); // bump reference
5615 };
5616 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
5617 CHKERR PetscFree(subksp);
5619 };
5620
5621 CHKERR set_ops();
5622 CHKERR set_pc();
5623 CHKERR set_assemble_elems();
5624
5625 CHKERR TSSetUp(solver);
5626 CHKERR KSPSetUp(ksp);
5627 CHKERR set_diagonal_pc();
5628
5629 } else {
5630 pip_mng->getOpBoundaryLhsPipeline().push_front(
5632 pip_mng->getOpBoundaryLhsPipeline().push_back(
5633 createOpSchurAssembleEnd({}, {}));
5634 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
5635 pip_mng->getOpDomainLhsPipeline().push_back(
5636 createOpSchurAssembleEnd({}, {}));
5637 }
5638
5639 // fieldSplitIS.reset();
5640 // aoSchur.reset();
5642}
5643
5644boost::shared_ptr<SetUpSchur>
5646 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
5647 SmartPetscObj<AO> ao_up) {
5648 return boost::shared_ptr<SetUpSchur>(
5649 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
5650}
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEX(DIM, I)
#define TSADAPTMOFEM
Definition TsCtx.hpp:10
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
constexpr double a
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Kronecker Delta class symmetric.
@ QUIET
@ VERBOSE
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
@ 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 BITREFLEVEL_SIZE
max number of refinements
#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.
@ TEMPERATURESET
@ HEATFLUXSET
@ NODESET
@ SIDESET
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_STD_EXCEPTION_THROW
Definition definitions.h:39
@ 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
Order displacement.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesVector< 1, SPACE_DIM, 1 > OpInertiaForce
PetscErrorCode ShapeMBTRI(double *N, const double *X, const double *Y, const int G_DIM)
calculate shape functions on triangle
Definition fem_tools.c:182
@ F
constexpr auto t_kd
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSNESSetFunction(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set SNES residual evaluation function
Definition DMMoFEM.cpp:708
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:114
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
PetscErrorCode DMMoFEMSNESSetJacobian(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set SNES Jacobian evaluation function
Definition DMMoFEM.cpp:749
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
PetscErrorCode DMMoFEMKSPSetComputeRHS(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set KSP right hand side evaluation function
Definition DMMoFEM.cpp:627
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1191
PetscErrorCode DMCreateGlobalVector_MoFEM(DM dm, Vec *g)
DMShellSetCreateGlobalVector.
Definition DMMoFEM.cpp:1157
PetscErrorCode DMoFEMMeshToGlobalVector(DM dm, Vec g, InsertMode mode, ScatterMode scatter_mode)
set ghosted vector values on all existing mesh entities
Definition DMMoFEM.cpp:525
PetscErrorCode DMSubDMSetUp_MoFEM(DM subdm)
Definition DMMoFEM.cpp:1344
PetscErrorCode DMMoFEMKSPSetComputeOperators(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
Set KSP operators and push mofem finite element methods.
Definition DMMoFEM.cpp:668
PetscErrorCode DMSetUp_MoFEM(DM dm)
Definition DMMoFEM.cpp:1297
PetscErrorCode DMoFEMLoopFiniteElementsUpAndLowRank(DM dm, const char fe_name[], MoFEM::FEMethod *method, int low_rank, int up_rank, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:557
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
@ BLOCK_PRECONDITIONER_SCHUR
Block preconditioner Schur assembly.
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#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
virtual MoFEMErrorCode modify_problem_mask_ref_level_set_bit(const std::string &name_problem, const BitRefLevel &bit)=0
set dof mask ref level for problem
virtual MoFEMErrorCode modify_problem_ref_level_set_bit(const std::string &name_problem, const BitRefLevel &bit)=0
set ref level for problem
MoFEMErrorCode pushMarkDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true)
Mark DOFs on block entities for boundary conditions.
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
double D
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
double cn_contact
Definition contact.cpp:97
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
auto createKSP(MPI_Comm comm)
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
Definition DMMoFEM.cpp:1046
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobian in TS solver.
Definition TsCtx.cpp:169
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1276
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:2585
auto createSNES(MPI_Comm comm)
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:434
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:596
MoFEMErrorCode setSchurA00MatSolvePC(SmartPetscObj< PC > pc)
Set PC for A00 block.
Definition Schur.cpp:2627
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)
PetscErrorCode TsSetIFunction(TS ts, PetscReal t, Vec u, Vec u_t, Vec F, void *ctx)
Set IFunction for TS solver.
Definition TsCtx.cpp:56
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
auto getDMSubData(DM dm)
Get sub problem data structure.
Definition DMMoFEM.hpp:1292
PetscErrorCode TsSetI2Jacobian(TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, PetscReal a, PetscReal aa, Mat A, Mat B, void *ctx)
Calculation Jacobian for second order PDE in time.
Definition TsCtx.cpp:519
boost::shared_ptr< BlockStructure > createBlockMatStructure(DM dm, SchurFEOpsFEandFields schur_fe_op_vec)
Create a Mat Diag Blocks object.
Definition Schur.cpp:1082
boost::shared_ptr< NestSchurData > createSchurNestedMatrixStruture(std::pair< SmartPetscObj< DM >, SmartPetscObj< DM > > dms, boost::shared_ptr< BlockStructure > block_mat_data_ptr, std::vector< std::string > fields_names, std::vector< boost::shared_ptr< Range > > field_ents, bool add_preconditioner_block)
Get the Schur Nest Mat Array object.
Definition Schur.cpp:2343
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
MoFEMErrorCode DMMoFEMSetNestSchurData(DM dm, boost::shared_ptr< NestSchurData >)
Definition DMMoFEM.cpp:1554
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1262
auto createDMNestSchurMat(DM dm)
Definition DMMoFEM.hpp:1218
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
PetscErrorCode TSAdaptCreateMoFEM(TSAdapt adapt)
Craete MOFEM adapt.
Definition TsCtx.cpp:829
OpSchurAssembleBase * createOpSchurAssembleBegin()
Definition Schur.cpp:2580
auto createDMBlockMat(DM dm)
Definition DMMoFEM.hpp:1211
boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > Pip
FTensor::Index< 'J', 3 > J
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMixDivTimesScalar< SPACE_DIM > OpHdivT
Integrate Lhs div of base of flux times base of temperature (FLUX x T) and transpose of it,...
OpHdivHdivImpl< SPACE_DIM, IS_LARGE_STRAINS > OpHdivHdiv
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, 1 > OpCapacity
Integrate Lhs base of temperature times (heat capacity) times base of temperature (T x T)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpBaseTimesScalar< 1 > OpBaseDotT
Integrate Rhs base of temperature time heat capacity times heat rate (T)
OpBaseDotT OpBaseDivFlux
Integrate Rhs base of temperature times divergence of flux (T)
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpMixDivTimesU< 3, 1, SPACE_DIM > OpHDivTemp
Integrate Rhs div flux base times temperature (T)
OpCalculateQdotQLhs_dU< SPACE_DIM, GAUSS, AssemblyDomainEleOp, IS_LARGE_STRAINS > OpHdivU
Integrate Lhs of flux term coupled to displacement field.
OpHdivFluxImpl< SPACE_DIM, IS_LARGE_STRAINS > OpHdivFlux
MoFEMErrorCode addMatThermalBlockOps(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_name, boost::shared_ptr< BlockedThermalParameters > blockedParamsPtr, double default_heat_conductivity, double default_heat_capacity, double default_thermal_conductivity_scale, double default_thermal_capacity_scale, Sev sev, ScalerFunTwoArgs thermal_conductivity_scaling_func, ScalerFunTwoArgs heat_capacity_scaling_func)
MoFEMErrorCode addMatThermoElasticBlockOps(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string block_name, boost::shared_ptr< BlockedThermoElasticParameters > blockedParamsPtr, double default_coeff_expansion, double default_ref_temp, Sev sev)
MoFEMErrorCode addMatThermoPlasticBlockOps(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, std::string thermoplastic_block_name, boost::shared_ptr< ThermoPlasticBlockedParameters > blockedParamsPtr, boost::shared_ptr< ThermoElasticOps::BlockedThermalParameters > &blockedThermalParamsPtr, Sev sev, ScalerFunThreeArgs inelastic_heat_fraction_scaling)
int r
Definition sdf.py:8
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr IntegrationType I
constexpr AssemblyType A
[Define dimension]
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
#define QUAD_2D_TABLE_SIZE
Definition quad.h:174
#define QUAD_3D_TABLE_SIZE
Definition quad.h:186
static QUAD *const QUAD_2D_TABLE[]
Definition quad.h:175
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Definition radiation.cpp:29
constexpr double heat_conductivity
Definition radiation.cpp:36
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForcePiola
Definition seepage.cpp:65
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradTensorGrad< 1, SPACE_DIM, SPACE_DIM, 1 > OpKPiola
[Only used for dynamics]
Definition seepage.cpp:63
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpGradTimesSymTensor< 1, SPACE_DIM, SPACE_DIM > OpInternalForceCauchy
Definition seepage.cpp:51
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradSymTensorGrad< 1, SPACE_DIM, SPACE_DIM, 0 > OpKCauchy
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:49
FTensor::Index< 'm', 3 > m
void temp(int x, int y=10)
Definition simple.cpp:4
Rhs for testing EP mapping with initial conditions.
PipelineManager::ElementsAndOpsByDim< 2 >::DomainEleOnRange DomainEleOnRange
PipelineManager::ElementsAndOpsByDim< 2 >::FaceSideEle SideEle
Definition plastic.cpp:29
PipelineManager::ElementsAndOpsByDim< 3 >::FaceSideEle SideEle
Definition plastic.cpp:36
PipelineManager::ElementsAndOpsByDim< 3 >::DomainEleOnRange DomainEleOnRange
double getScale(const double time)
Get scaling at given time.
[Example]
Definition plastic.cpp:216
MoFEMErrorCode thermalBC()
[Mechanical boundary conditions]
boost::shared_ptr< VectorDouble > tempFieldPtr
MoFEMErrorCode opThermoPlasticFactoryDomainLhs(MoFEM::Interface &m_field, std::string block_name, std::string thermal_block_name, std::string thermoelastic_block_name, std::string thermoplastic_block_name, Pip &pip, std::string u, std::string ep, std::string tau, std::string temperature)
boost::shared_ptr< DomainEle > reactionFe
Definition plastic.cpp:235
boost::shared_ptr< MatrixDouble > strainFieldPtr
boost::shared_ptr< MatrixDouble > dispGradPtr
MoFEMErrorCode tsSolve()
FieldApproximationBase base
Choice of finite element basis functions
Definition plot_base.cpp:68
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uYScatter
Definition plastic.cpp:238
MoFEMErrorCode mechanicalBC()
[Initial conditions]
MoFEMErrorCode createCommonData()
friend struct TSPrePostProc
boost::shared_ptr< VectorDouble > plasticMultiplierFieldPtr
Example(MoFEM::Interface &m_field)
MoFEMErrorCode OPs()
MoFEMErrorCode runProblem()
boost::shared_ptr< MatrixDouble > stressFieldPtr
MoFEM::Interface & mField
Reference to MoFEM interface.
Definition plastic.cpp:226
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uZScatter
Definition plastic.cpp:239
boost::shared_ptr< MatrixDouble > fluxFieldPtr
MoFEMErrorCode setupProblem()
boost::shared_ptr< MatrixDouble > dispFieldPtr
boost::shared_ptr< MatrixDouble > plasticStrainFieldPtr
MoFEMErrorCode opThermoPlasticFactoryDomainRhs(MoFEM::Interface &m_field, std::string block_name, std::string thermal_block_name, std::string thermoelastic_block_name, std::string thermoplastic_block_name, Pip &pip, std::string u, std::string ep, std::string tau, std::string temperature)
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition plastic.cpp:237
MoFEMErrorCode initialConditions()
[Create common data]
auto createCommonThermoPlasticOps(MoFEM::Interface &m_field, std::string plastic_block_name, std::string thermal_block_name, std::string thermoelastic_block_name, std::string thermoplastic_block_name, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string u, std::string ep, std::string tau, std::string temperature, double scale, ScalerFunTwoArgs thermal_conductivity_scaling, ScalerFunTwoArgs heat_capacity_scaling, ScalerFunThreeArgs inelastic_heat_fraction_scaling, Sev sev, bool with_rates=true)
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
Managing BitRefLevels.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:118
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)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to calculate residual side diagonal.
Definition Essential.hpp:49
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Structure for user loop methods on finite elements.
Basic algebra on fields.
Definition FieldBlas.hpp:21
Field evaluator interface.
SetIntegrationPtsMethodData SetPtsData
structure to get information from mofem into EntitiesFieldData
Definition of the heat flux bc data structure.
Definition BCData.hpp:423
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.
Mesh refinement interface.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Natural boundary conditions.
Definition Natural.hpp:57
Get vector field for H-div approximation.
Calculate divergence of vector field.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Calculate symmetric tensor field rates ant integratio pts.
Calculate symmetric tensor field values at integration pts.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Specialization for double precision vector field values calculation.
Enforce essential constrains on lhs.
Definition Essential.hpp:81
Enforce essential constrains on rhs.
Definition Essential.hpp:65
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
Set indices on entities on finite element.
Operator for symmetrizing tensor fields.
Unset indices on entities on finite element.
Template struct for dimension-specific finite element types.
PipelineManager interface.
MoFEM::VolumeElementForcesAndSourcesCore VolEle
boost::shared_ptr< FEMethod > & getDomainLhsFE()
Get domain left-hand side finite element.
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEM::EdgeElementForcesAndSourcesCore EdgeEle
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
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
intrusive_ptr for managing petsc objects
Force scale operator for reading two columns.
double getScale(const double time)
Get scaling at a given time.
TimeScale(std::string file_name="", bool error_if_file_not_given=false, ScalingFun def_scaling_fun=[](double time) { return time;})
TimeScale constructor.
Auxiliary tools.
Definition Tools.hpp:19
static constexpr std::array< double, 6 > diffShapeFunMBTRI
Definition Tools.hpp:104
static MoFEMErrorCode getTriNormal(const double *coords, double *normal, double *d_normal=nullptr)
Get the Tri Normal objectGet triangle normal.
Definition Tools.cpp:353
MoFEM::Interface & mField
Definition TsCtx.hpp:19
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
boost::shared_ptr< MoFEM::TsCtx > dmts_ctx
PetscInt snes_iter_counter
[Target temperature]
static std::array< int, 5 > activityData
int npoints
Definition quad.h:29
MoFEM::Interface * m_field
PetscBool mesh_changed
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
SetEnrichedIntegration(boost::shared_ptr< Range > new_els)
SmartPetscObj< DM > subDM
field split sub dm
Definition plastic.cpp:1680
SmartPetscObj< Mat > S
SmartPetscObj< AO > aoSchur
Definition plastic.cpp:1682
MoFEMErrorCode setUp(TS solver)
SmartPetscObj< IS > fieldSplitIS
IS for split Schur block.
Definition plastic.cpp:1681
SetUpSchurImpl(MoFEM::Interface &m_field, SmartPetscObj< DM > sub_dm, SmartPetscObj< IS > field_split_is, SmartPetscObj< AO > ao_up)
MoFEMErrorCode setUp(SmartPetscObj< KSP >)
virtual ~SetUpSchurImpl()
MoFEMErrorCode postProc()
MoFEMErrorCode preProc()
MoFEM::Interface & mField
[Push operators to pipeline]
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.
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field)
virtual MoFEMErrorCode setUp(TS solver)=0
MoFEMErrorCode reSetUp(std::vector< std::string > fIelds, std::vector< int > oRders, BitRefLevel bIt)
MoFEMErrorCode mapFields(SmartPetscObj< DM > &intermediateDM, Range elsToRemove=Range(), Range elsToAdd=Range(), Range elsToFlip=Range(), PetscInt numVecs=1, Vec vecsToMapFrom[]=PETSC_NULLPTR, Vec vecsToMapTo[]=PETSC_NULLPTR)
Set of functions called by PETSc solver used to refine and update mesh.
virtual ~TSPrePostProc()=default
static MoFEMErrorCode tsPreProc(TS ts)
Pre process time step.
static MoFEMErrorCode tsPostProc(TS ts)
Post process time step.
TSPrePostProc()=default
static MoFEMErrorCode tsPostProc(TS ts)
Post process time step.
static MoFEMErrorCode tsPreStage(TS ts)
static MoFEMErrorCode tsPreProc(TS ts)
Pre process time step.
MoFEMErrorCode tsSetUp(TS ts)
Used to setup TS solver.
constexpr AssemblyType AT
constexpr IntegrationType IT
double iso_hardening_dtemp(double tau, double H, double omega_0, double Qinf, double omega_h, double b_iso, double sigmaY, double temp_0, double temp)
double young_modulus
Young modulus.
@ IC_UNIFORM
@ IC_LINEAR
@ IC_GAUSSIAN
double default_heat_capacity_scale
auto save_range
constexpr AssemblyType AT
double exp_D
static boost::weak_ptr< TSPrePostProc > tsPrePostProc
double C1_k
Kinematic hardening.
int post_processing_counter
double peak_temp
double exp_softening(double temp_hat)
PetscBool order_face
double Qinf
Saturation yield stress.
char restart_file[255]
constexpr IntegrationType IT
static char help[]
[Solve]
auto init_T
Initialisation function for temperature field.
double default_thermal_conductivity_scale
ScalerFunTwoArgs heat_capacity_scaling
double dH_thermal_dtemp(double H, double omega_h)
constexpr bool IS_LARGE_STRAINS
double rho
ScalerFunThreeArgs inelastic_heat_fraction_scaling
int atom_test
PetscBool is_distributed_mesh
#define EXECUTABLE_DIMENSION
PetscBool do_eval_field
Evaluate field.
PetscBool is_quasi_static
double dy_0_thermal_dtemp(double sigmaY, double omega_0)
boost::function< double(const double, const double, const double)> ScalerFunThreeArgs
double alpha_damping
constexpr int SPACE_DIM
ICType ic_type
double visH
Viscous hardening.
double poisson_ratio
Poisson ratio.
boost::function< double(const double, const double)> ScalerFunTwoArgs
double iso_hardening(double tau, double H, double omega_0, double Qinf, double omega_h, double b_iso, double sigmaY, double temp_0, double temp)
double init_dt
Example * thermoplastic_raw_ptr
PetscErrorCode MyTSResizeSetup(TS ts, PetscInt nstep, PetscReal time, Vec sol, PetscBool *resize, void *ctx)
int restart_step
double qual_tol
static std::unordered_map< TS, ResizeCtx * > ts_to_rctx
double default_ref_temp
PetscBool order_edge
double Qinf_thermal(double Qinf, double omega_h, double temp_0, double temp)
auto kinematic_hardening(FTensor::Tensor2_symmetric< T, DIM > &t_plastic_strain, double C1_k)
double default_heat_capacity
PetscBool set_timer
Set timer.
const char *const ICTypes[]
double temp_hat(double temp)
const bool is_large_strains
PetscBool order_volume
double scale
constexpr auto size_symm
auto postProcessHere(MoFEM::Interface &m_field, SmartPetscObj< DM > &dm, std::string output_name, int &counter= *(new int(0)))
PetscBool restart_flg
int flux_order
Order of tau field.
MoFEMErrorCode TSIterationPreStage(TS ts, PetscReal stagetime)
double zeta
regularisation parameter
int T_order
Order of ep field.
ElementsAndOps< SPACE_DIM >::DomainEleOnRange DomainEleOnRange
double y_0_thermal(double sigmaY, double omega_0, double temp_0, double temp)
double init_temp
double H
Hardening.
double width
Width of Gaussian distribution.
auto linear_distribution
double default_coeff_expansion
int tau_order
Order of tau field.
double iso_hardening_dtau(double tau, double H, double omega_0, double Qinf, double omega_h, double b_iso, double sigmaY, double temp_0, double temp)
auto uniform_distribution
auto printOnAllCores(MoFEM::Interface &m_field, const std::string &out_put_string, const auto &out_put_quantity)
MoFEMErrorCode SNESIterationMonitor(SNES snes, PetscInt its, PetscReal norm, void *ctx)
double omega_0
flow stress softening
double iso_hardening_exp(double tau, double b_iso)
PetscErrorCode MyTSResizeTransfer(TS ts, PetscInt nv, Vec ts_vecsin[], Vec ts_vecsout[], void *ctx)
auto postProcessPETScHere(MoFEM::Interface &m_field, SmartPetscObj< DM > &dm, Vec sol, std::string output_name)
double H_thermal(double H, double omega_h, double temp_0, double temp)
double restart_time
double cn0
int order
Order displacement.
double b_iso
Saturation exponent.
auto Gaussian_distribution
int geom_order
Order if fixed.
double sigmaY
Yield stress.
ScalerFunTwoArgs thermal_conductivity_scaling
double default_heat_conductivity
auto kinematic_hardening_dplastic_strain(double C1_k)
double inelastic_heat_fraction
fraction of plastic dissipation converted to heat
double min_dt
double temp_0
reference temperature for thermal softening
static std::unordered_map< TS, MyTsCtx * > ts_to_ctx
int ep_order
Order of ep field.
double dQinf_thermal_dtemp(double Qinf, double omega_h)
double exp_C
double cn1
constexpr FieldSpace CONTACT_SPACE
double omega_h
hardening softening
double young_modulus
Young modulus.
Definition plastic.cpp:125
double C1_k
Kinematic hardening.
Definition plastic.cpp:133
double Qinf
Saturation yield stress.
Definition plastic.cpp:131
double rho
Definition plastic.cpp:144
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
int atom_test
Atom test.
Definition plastic.cpp:121
PetscBool is_quasi_static
[Operators used for contact]
Definition plastic.cpp:143
double alpha_damping
Definition plastic.cpp:145
double visH
Viscous hardening.
Definition plastic.cpp:129
double poisson_ratio
Poisson ratio.
Definition plastic.cpp:126
PetscBool set_timer
Set timer.
Definition plastic.cpp:118
double scale
Definition plastic.cpp:123
constexpr auto size_symm
Definition plastic.cpp:42
double zeta
Viscous hardening.
Definition plastic.cpp:130
double H
Hardening.
Definition plastic.cpp:128
int tau_order
Order of tau files.
Definition plastic.cpp:139
double cn0
Definition plastic.cpp:135
double b_iso
Saturation exponent.
Definition plastic.cpp:132
PetscBool is_large_strains
Large strains.
Definition plastic.cpp:117
int geom_order
Order if fixed.
Definition plastic.cpp:141
double sigmaY
Yield stress.
Definition plastic.cpp:127
int ep_order
Order of ep files.
Definition plastic.cpp:140
double cn1
Definition plastic.cpp:136
constexpr FieldSpace CONTACT_SPACE
[Specialisation for assembly]
Definition plastic.cpp:52
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
#define FINITE_DEFORMATION_FLAG
auto save_range
constexpr bool IS_LARGE_STRAINS
double default_ref_temp
double default_heat_capacity
double default_coeff_expansion
double default_heat_conductivity
constexpr int SPACE_DIM
[Define dimension]
Definition elastic.cpp:19
constexpr AssemblyType A
[Define dimension]
Definition elastic.cpp:22
constexpr int SPACE_DIM