v0.15.4
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 = 10*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;
257double qual_thresh = 0.1;
260
270
277
278auto Gaussian_distribution = [](double init_temp, double peak_temp, double x,
279 double y, double z) {
280 double s =
281 width /
282 std::sqrt(-2. * std::log(0.01 * peak_temp / (peak_temp - init_temp)));
283 return (peak_temp - init_temp) * exp(-pow(y, 2) / (2. * pow(s, 2))) +
284 init_temp;
285};
286
287auto linear_distribution = [](double init_temp, double peak_temp, double x,
288 double y, double z) {
289 return ((peak_temp - init_temp) / width) * y + (peak_temp + init_temp) / 2.0;
290};
291
292auto uniform_distribution = [](double init_temp, double peak_temp, double x,
293 double y, double z) { return init_temp; };
294
295/**
296 * @brief Initialisation function for temperature field
297 */
298auto init_T = [](double init_temp, double peak_temp, double x, double y,
299 double z) {
300 switch (ic_type) {
301 case IC_GAUSSIAN:
302 return -Gaussian_distribution(init_temp, peak_temp, x, y, z);
303 case IC_LINEAR:
304 return -linear_distribution(init_temp, peak_temp, x, y, z);
305 case IC_UNIFORM:
306 default:
307 return -uniform_distribution(init_temp, peak_temp, x, y, z);
308 }
309};
310
311#include <HenckyOps.hpp>
312#include <PlasticOps.hpp>
313#include <PlasticNaturalBCs.hpp>
314#include <ThermoElasticOps.hpp>
315#include <FiniteThermalOps.hpp>
316#include <ThermoPlasticOps.hpp>
317#include <ThermalOps.hpp>
318
319#include <EdgeFlippingOps.hpp>
320#include <SolutionMapping.hpp>
321
322#include <ThermalConvection.hpp>
323#include <ThermalRadiation.hpp>
324
325#ifdef ADD_CONTACT
326 #ifdef ENABLE_PYTHON_BINDING
327 #include <boost/python.hpp>
328 #include <boost/python/def.hpp>
329 #include <boost/python/numpy.hpp>
330namespace bp = boost::python;
331namespace np = boost::python::numpy;
332 #endif
333
334namespace ContactOps {
335
336double cn_contact = 0.1;
337
338}; // namespace ContactOps
339
340 #include <ContactOps.hpp>
341#endif // ADD_CONTACT
342
343using namespace PlasticOps;
344using namespace HenckyOps;
345using namespace ThermoElasticOps;
346using namespace FiniteThermalOps;
347using namespace ThermalOps;
348
350
352 std::string output_name, int &counter = *(new int(0))) {
354
355 auto create_post_process_elements = [&]() {
357 auto pp_fe = boost::make_shared<PostProcEle>(m_field);
358
359 auto push_vol_post_proc_ops = [&](auto &pp_fe) {
361
362 auto &pip = pp_fe->getOpPtrVector();
363
364 auto TAU_ptr = boost::make_shared<VectorDouble>();
365 pip.push_back(new OpCalculateScalarFieldValues("TAU", TAU_ptr));
366 auto T_ptr = boost::make_shared<VectorDouble>();
367 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
368
369 auto T_grad_ptr = boost::make_shared<MatrixDouble>();
370 pip.push_back(
371 new OpCalculateScalarFieldGradient<SPACE_DIM>("T", T_grad_ptr));
372 auto U_ptr = boost::make_shared<MatrixDouble>();
373 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", U_ptr));
374 auto FLUX_ptr = boost::make_shared<MatrixDouble>();
375 pip.push_back(
376 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", FLUX_ptr));
377
378 auto EP_ptr = boost::make_shared<MatrixDouble>();
379 pip.push_back(
381
383
384 pip.push_back(
385
386 new OpPPMap(
387
388 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
389
390 {{"TAU", TAU_ptr}, {"T", T_ptr}},
391
392 {{"U", U_ptr}, {"FLUX", FLUX_ptr}, {"T_GRAD", T_grad_ptr}},
393
394 {},
395
396 {{"EP", EP_ptr}}
397
398 )
399
400 );
401
403 };
404
405 CHKERR push_vol_post_proc_ops(pp_fe);
406
407 if (m_field.get_comm_size() == 1) {
408
409 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", pp_fe);
410 CHKERR pp_fe->writeFile("out_" + std::to_string(counter) + "_" +
411 output_name + ".h5m");
412 } else {
413
415 m_field.get_comm_size());
416 auto &post_proc_moab = pp_fe->getPostProcMesh();
417 auto file_name = "out_" + std::to_string(counter) + "_" + output_name +
418 "_" + std::to_string(m_field.get_comm_rank()) + ".vtk";
419 MOFEM_LOG("WORLD", Sev::inform)
420 << "Writing file " << file_name << std::endl;
421 CHKERR post_proc_moab.write_file(file_name.c_str(), "VTK");
422 }
423 counter++;
424
426 };
427
428 CHKERR create_post_process_elements();
429
431}
432
434 Vec sol, std::string output_name) {
436
437 auto smart_sol = SmartPetscObj<Vec>(sol, true);
438
439 auto create_post_process_elements = [&]() {
441 auto pp_fe = boost::make_shared<PostProcEle>(m_field);
442
443 auto push_vol_post_proc_ops = [&](auto &pp_fe) {
445
446 auto &pip = pp_fe->getOpPtrVector();
447
448 auto TAU_ptr = boost::make_shared<VectorDouble>();
449 pip.push_back(
450 new OpCalculateScalarFieldValues("TAU", TAU_ptr, smart_sol));
451 auto T_ptr = boost::make_shared<VectorDouble>();
452 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr, smart_sol));
453
454 auto U_ptr = boost::make_shared<MatrixDouble>();
455 pip.push_back(
456 new OpCalculateVectorFieldValues<SPACE_DIM>("U", U_ptr, smart_sol));
457 auto FLUX_ptr = boost::make_shared<MatrixDouble>();
459 "FLUX", FLUX_ptr, smart_sol));
460
461 auto EP_ptr = boost::make_shared<MatrixDouble>();
463 "EP", EP_ptr, smart_sol));
464
466
467 pip.push_back(
468
469 new OpPPMap(
470
471 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
472
473 {{"TAU", TAU_ptr}, {"T", T_ptr}},
474
475 {{"U", U_ptr}, {"FLUX", FLUX_ptr}},
476
477 {},
478
479 {{"EP", EP_ptr}}
480
481 )
482
483 );
484
486 };
487
488 CHKERR push_vol_post_proc_ops(pp_fe);
489
490 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", pp_fe);
491 CHKERR pp_fe->writeFile("out_" + output_name + ".h5m");
492
494 };
495
496 CHKERR create_post_process_elements();
497
499}
500
502 const std::string &out_put_string,
503 const auto &out_put_quantity) {
505 auto rank = m_field.get_comm_rank();
506 auto size = m_field.get_comm_size();
507
508 // Loop through all processes and print one by one
509 for (int i = 0; i < size; ++i) {
510 // If it is this process's turn, print the data
511 if (i == rank) {
512 std::cout << "Proc " << rank << " " + out_put_string + " "
513 << out_put_quantity << std::endl;
514 }
515 // All processes wait here until the current one has finished
516 // printing
517 CHKERR PetscBarrier(NULL);
518 }
520};
521
531
532//! [Body and heat source]
540//! [Body and heat source]
541
542//! [Natural boundary conditions]
548//! [Natural boundary conditions]
549
550//! [Essential boundary conditions (Least square approach)]
552 IT>::OpEssentialRhs<HeatFluxCubitBcData, 3, SPACE_DIM>;
555//! [Essential boundary conditions (Least square approach)]
556
561
562auto save_range = [](moab::Interface &moab, const std::string name,
563 const Range r) {
565 auto out_meshset = get_temp_meshset_ptr(moab);
566 CHKERR moab.add_entities(*out_meshset, r);
567 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
569};
570
571auto get_string_from_vector = [](auto vec) {
572 std::string output_string = "";
573 for (auto el : vec) {
574 output_string += std::to_string(el) + " ";
575 }
576 return output_string;
577};
578
579struct Example;
580
581/**
582 * @brief Set of functions called by PETSc solver used to refine and update
583 * mesh.
584 *
585 * @note Currently theta method is only handled by this code.
586 *
587 */
588struct TSPrePostProc {
589
590 TSPrePostProc() = default;
591 virtual ~TSPrePostProc() = default;
592
593 /**
594 * @brief Used to setup TS solver
595 *
596 * @param ts
597 * @return MoFEMErrorCode
598 */
600
602
603private:
604 /**
605 * @brief Pre process time step
606 *
607 * Refine mesh and update fields
608 *
609 * @param ts
610 * @return MoFEMErrorCode
611 */
613
614 /**
615 * @brief Post process time step.
616 *
617 * Currently that function do not make anything major
618 *
619 * @param ts
620 * @return MoFEMErrorCode
621 */
623
625};
626
627static boost::weak_ptr<TSPrePostProc> tsPrePostProc;
628
629struct ResizeCtx {
631 // any flags / lists indicating which elements flipped or were added
632 PetscBool mesh_changed; // set by your code that flips elements
633 std::multimap<double, EntityHandle> el_q_map;
635 std::vector<EntityHandle> new_connectivity;
637 boost::weak_ptr<TSPrePostProc> ptr;
638 // store whatever mapping info you need
639};
640
641static std::unordered_map<TS, ResizeCtx *> ts_to_rctx;
642
644
647 int order_row, int order_col,
648 int order_data) {
650
651 constexpr int numNodes = 3;
652 constexpr int numEdges = 3;
653
654 auto &m_field = fe_raw_ptr->mField;
655 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
656 auto fe_handle = fe_ptr->getFEEntityHandle();
657
658 auto set_base_quadrature = [&]() {
660 int rule = 2 * (order_data + 1);
661 if (rule < QUAD_2D_TABLE_SIZE) {
662 if (QUAD_2D_TABLE[rule]->dim != 2) {
663 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
664 }
665 if (QUAD_2D_TABLE[rule]->order < rule) {
666 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
667 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
668 }
669 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
670 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
671 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
672 &fe_ptr->gaussPts(0, 0), 1);
673 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
674 &fe_ptr->gaussPts(1, 0), 1);
675 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
676 &fe_ptr->gaussPts(2, 0), 1);
677 auto &data = fe_ptr->dataOnElement[H1];
678 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
679 false);
680 double *shape_ptr =
681 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
682 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
683 1);
684 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
685 std::copy(
687 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
688
689 } else {
690 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
691 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
692 }
694 };
695
696 CHKERR set_base_quadrature();
697
698 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
700 fe_ptr->gaussPts.swap(ref_gauss_pts);
701 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
702 auto &data = fe_ptr->dataOnElement[H1];
703 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3);
704 double *shape_ptr =
705 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
706 CHKERR ShapeMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
707 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
709 };
710
711 auto refine_quadrature = [&]() {
713
714 moab::Core moab_ref;
715 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
716 EntityHandle nodes[numNodes];
717 for (int nn = 0; nn != numNodes; nn++)
718 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
719 EntityHandle tri;
720 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
721 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
722 MoFEM::Interface &m_field_ref = mofem_ref_core;
723
724 Range ref_tri(tri, tri);
725 Range edges;
726 CHKERR m_field_ref.get_moab().get_adjacencies(ref_tri, 1, true, edges,
727 moab::Interface::UNION);
728 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
729 ref_tri, BitRefLevel().set(0), false, VERBOSE);
730
731 Range nodes_at_front;
732 for (int nn = 0; nn != numNodes; nn++) {
733 EntityHandle ent;
734 CHKERR moab_ref.side_element(tri, 0, nn, ent);
735 nodes_at_front.insert(ent);
736 }
737
738 EntityHandle meshset;
739 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
740 for (int ee = 0; ee != numEdges; ee++) {
741 EntityHandle ent;
742 CHKERR moab_ref.side_element(tri, 1, ee, ent);
743 CHKERR moab_ref.add_entities(meshset, &ent, 1);
744 }
745
746 // refine mesh
747 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
748 Range ref_edges;
749 CHKERR m_field_ref.getInterface<BitRefManager>()
750 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(0),
751 BitRefLevel().set(), MBEDGE, ref_edges);
752
753 // Range tris_to_refine;
754 // CHKERR m_field_ref.getInterface<BitRefManager>()
755 // ->getEntitiesByTypeAndRefLevel(
756 // BitRefLevel().set(0), BitRefLevel().set(), MBTRI,
757 // tris_to_refine);
758 CHKERR m_ref->addVerticesInTheMiddleOfEdges(ref_edges,
759 BitRefLevel().set(1));
760 CHKERR m_ref->addVerticesInTheMiddleOfFaces(ref_tri, BitRefLevel().set(1));
761 CHKERR m_ref->refineTris(ref_tri, BitRefLevel().set(1));
762 CHKERR m_field_ref.getInterface<BitRefManager>()
763 ->updateMeshsetByEntitiesChildren(meshset, BitRefLevel().set(1),
764 meshset, MBEDGE, true);
765 CHKERR m_field_ref.getInterface<BitRefManager>()
766 ->updateMeshsetByEntitiesChildren(meshset, BitRefLevel().set(1),
767 meshset, MBTRI, true);
768
769 // get ref coords
770 Range output_ref_tris;
771 CHKERR m_field_ref.getInterface<BitRefManager>()
772 ->getEntitiesByTypeAndRefLevel(
773 BitRefLevel().set(1), BitRefLevel().set(), MBTRI, output_ref_tris);
774
775#ifndef NDEBUG
776 CHKERR save_range(moab_ref, "ref_tris.vtk", output_ref_tris);
777#endif
778
779 MatrixDouble ref_coords(output_ref_tris.size(), 9, false);
780 int tt = 0;
781 for (Range::iterator tit = output_ref_tris.begin();
782 tit != output_ref_tris.end(); tit++, tt++) {
783 int num_nodes;
784 const EntityHandle *conn;
785 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
786 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
787 }
788
789 auto &data = fe_ptr->dataOnElement[H1];
790 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
791 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
792 MatrixDouble &shape_n = data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
793 int gg = 0;
794 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
795 double *tri_coords = &ref_coords(tt, 0);
797 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
798 auto det = t_normal.l2();
799 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
800 for (int dd = 0; dd != 2; dd++) {
801 ref_gauss_pts(dd, gg) = shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
802 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
803 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
804 }
805 MOFEM_LOG("REMESHING", Sev::noisy)
806 << ref_gauss_pts(0, gg) << ", " << ref_gauss_pts(1, gg);
807 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
808 }
809 }
810
811 int num_nodes;
812 const EntityHandle *conn;
813 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
814 true);
815 std::bitset<numNodes> all_nodes;
816 for (auto nn = 0; nn != numNodes; ++nn) {
817 all_nodes.set(nn);
818 }
819
820 mapRefCoords[all_nodes.to_ulong()].swap(ref_gauss_pts);
821 CHKERR set_gauss_pts(mapRefCoords[all_nodes.to_ulong()]);
822
824 };
825
826 CHKERR refine_quadrature();
827
829}
830
831extern PetscErrorCode MyTSResizeTransfer(TS, PetscInt, Vec[], Vec[], void *);
832
833struct Example {
834
835 Example(MoFEM::Interface &m_field) : mField(m_field) {}
836
838
840
841private:
842 friend PetscErrorCode ::MyTSResizeTransfer(TS, PetscInt, Vec[], Vec[],
843 void *);
850 getElementQuality(std::multimap<double, EntityHandle> &el_q_map,
851 Range &flipped_els,
852 std::vector<EntityHandle> &new_connectivity,
853 bool &do_refine, Tag &th_spatial_coords);
855 MoFEMErrorCode doEdgeFlips(std::multimap<double, EntityHandle> &el_q_map,
856 Range &flipped_els, Tag &th_spatial_coords,
857 std::vector<EntityHandle> &new_connectivity);
858 MoFEMErrorCode doEdgeSplits(bool &refine, bool add_ents);
861
862 boost::shared_ptr<DomainEle> reactionFe;
863
864 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uXScatter;
865 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uYScatter;
866 std::tuple<SmartPetscObj<Vec>, SmartPetscObj<VecScatter>> uZScatter;
867
868 boost::shared_ptr<VectorDouble> tempFieldPtr =
869 boost::make_shared<VectorDouble>();
870 boost::shared_ptr<MatrixDouble> fluxFieldPtr =
871 boost::make_shared<MatrixDouble>();
872 boost::shared_ptr<MatrixDouble> dispFieldPtr =
873 boost::make_shared<MatrixDouble>();
874 boost::shared_ptr<MatrixDouble> dispGradPtr =
875 boost::make_shared<MatrixDouble>();
876 boost::shared_ptr<MatrixDouble> strainFieldPtr =
877 boost::make_shared<MatrixDouble>();
878 boost::shared_ptr<MatrixDouble> stressFieldPtr =
879 boost::make_shared<MatrixDouble>();
880 boost::shared_ptr<VectorDouble> plasticMultiplierFieldPtr =
881 boost::make_shared<VectorDouble>();
882 boost::shared_ptr<MatrixDouble> plasticStrainFieldPtr =
883 boost::make_shared<MatrixDouble>();
884
885 struct ScaledTimeScale : public MoFEM::TimeScale {
887 double getScale(const double time) {
888 return scale * MoFEM::TimeScale::getScale(time);
889 };
890 };
891
892#ifdef ADD_CONTACT
893 #ifdef ENABLE_PYTHON_BINDING
894 boost::shared_ptr<ContactOps::SDFPython> sdfPythonPtr;
895 #endif
896#endif // ADD_CONTACT
897
898 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
900 MoFEM::Interface &m_field, std::string block_name,
901 std::string thermal_block_name, std::string thermoelastic_block_name,
902 std::string thermoplastic_block_name, Pip &pip, std::string u,
903 std::string ep, std::string tau, std::string temperature) {
905
906 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
907 A>::template LinearForm<I>;
909 typename B::template OpGradTimesSymTensor<1, DIM, DIM>;
911 typename B::template OpGradTimesTensor<1, DIM, DIM>;
912
914
916
917 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
918 common_thermoelastic_ptr, common_thermoplastic_ptr] =
919 createCommonThermoPlasticOps<DIM, I, DomainEleOp>(
920 m_field, block_name, thermal_block_name, thermoelastic_block_name,
921 thermoplastic_block_name, pip, u, ep, tau, temperature, scale,
924
925 auto m_D_ptr = common_hencky_ptr->matDPtr;
926
928 ep, common_plastic_ptr->getPlasticStrainDotPtr()));
929 pip.push_back(new OpCalculateScalarFieldValuesDot(
930 tau, common_plastic_ptr->getPlasticTauDotPtr()));
931 pip.push_back(new OpCalculateScalarFieldValues(
932 temperature, common_thermoplastic_ptr->getTempPtr()));
934 "FLUX", common_thermoplastic_ptr->getHeatFluxPtr()));
935 pip.push_back(new typename P::template OpCalculatePlasticity<DIM, I>(
936 u, common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
937
938 pip.push_back(
939 new
940 typename H::template OpCalculateHenckyThermoPlasticStress<DIM, I, 0>(
941 u, common_thermoplastic_ptr->getTempPtr(), common_hencky_ptr,
942 common_thermoelastic_ptr->getCoeffExpansionPtr(),
943 common_thermoelastic_ptr->getRefTempPtr()));
944
945 // Calculate internal forces
946 if (common_hencky_ptr) {
947 pip.push_back(new OpInternalForcePiola(
948 u, common_hencky_ptr->getMatFirstPiolaStress()));
949 } else {
950 pip.push_back(
951 new OpInternalForceCauchy(u, common_plastic_ptr->mStressPtr));
952 }
953
954 auto inelastic_heat_frac_ptr =
955 common_thermoplastic_ptr->getInelasticHeatFractionPtr();
957 [inelastic_heat_frac_ptr](const double, const double, const double) {
958 return (*inelastic_heat_frac_ptr);
959 };
960
961 // TODO: add scenario for when not using Hencky material
964 temperature, common_hencky_ptr->getMatHenckyStress(),
965 common_plastic_ptr->getPlasticStrainDotPtr(), inelastic_heat_fraction));
966
967 pip.push_back(
968 new
969 typename P::template Assembly<A>::template OpCalculateConstraintsRhs<I>(
970 tau, common_plastic_ptr, m_D_ptr));
971 pip.push_back(
972 new
973 typename P::template Assembly<A>::template OpCalculatePlasticFlowRhs<
974 DIM, I>(ep, common_plastic_ptr, m_D_ptr));
975
977 }
978
979 template <int DIM, AssemblyType A, IntegrationType I, typename DomainEleOp>
981 MoFEM::Interface &m_field, std::string block_name,
982 std::string thermal_block_name, std::string thermoelastic_block_name,
983 std::string thermoplastic_block_name, Pip &pip, std::string u,
984 std::string ep, std::string tau, std::string temperature) {
986
987 using namespace HenckyOps;
989
990 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
991 A>::template BiLinearForm<I>;
992 using OpKPiola = typename B::template OpGradTensorGrad<1, DIM, DIM, 1>;
993 using OpKCauchy = typename B::template OpGradSymTensorGrad<1, DIM, DIM, 0>;
994
996
997 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
998 common_thermoelastic_ptr, common_thermoplastic_ptr] =
999 createCommonThermoPlasticOps<DIM, I, DomainEleOp>(
1000 m_field, block_name, thermal_block_name, thermoelastic_block_name,
1001 thermoplastic_block_name, pip, u, ep, tau, temperature, scale,
1003 inelastic_heat_fraction_scaling, Sev::inform);
1004
1005 auto m_D_ptr = common_hencky_ptr->matDPtr;
1006
1008 ep, common_plastic_ptr->getPlasticStrainDotPtr()));
1009 pip.push_back(new OpCalculateScalarFieldValuesDot(
1010 tau, common_plastic_ptr->getPlasticTauDotPtr()));
1011 pip.push_back(new typename P::template OpCalculatePlasticity<DIM, I>(
1012 u, common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
1013
1014 if (common_hencky_ptr) {
1015 pip.push_back(new typename H::template OpHenckyTangent<DIM, I, 0>(
1016 u, common_hencky_ptr, m_D_ptr));
1017 pip.push_back(new OpKPiola(u, u, common_hencky_ptr->getMatTangent()));
1018 pip.push_back(
1019 new typename P::template Assembly<A>::
1020 template OpCalculatePlasticInternalForceLhs_LogStrain_dEP<DIM, I>(
1021 u, ep, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
1022 } else {
1023 pip.push_back(new OpKCauchy(u, u, m_D_ptr));
1024 pip.push_back(new typename P::template Assembly<A>::
1025 template OpCalculatePlasticInternalForceLhs_dEP<DIM, I>(
1026 u, ep, common_plastic_ptr, m_D_ptr));
1027 }
1028
1029 if (common_hencky_ptr) {
1030 pip.push_back(
1031 new typename P::template Assembly<A>::
1032 template OpCalculateConstraintsLhs_LogStrain_dU<DIM, I>(
1033 tau, u, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
1034 pip.push_back(
1035 new typename P::template Assembly<A>::
1036 template OpCalculatePlasticFlowLhs_LogStrain_dU<DIM, I>(
1037 ep, u, common_plastic_ptr, common_hencky_ptr, m_D_ptr));
1038 } else {
1039 pip.push_back(new typename P::template Assembly<A>::
1040 template OpCalculateConstraintsLhs_dU<DIM, I>(
1041 tau, u, common_plastic_ptr, m_D_ptr));
1042 pip.push_back(new typename P::template Assembly<A>::
1043 template OpCalculatePlasticFlowLhs_dU<DIM, I>(
1044 ep, u, common_plastic_ptr, m_D_ptr));
1045 }
1046
1047 pip.push_back(new typename P::template Assembly<A>::
1048 template OpCalculatePlasticFlowLhs_dEP<DIM, I>(
1049 ep, ep, common_plastic_ptr, m_D_ptr));
1050 pip.push_back(new typename P::template Assembly<A>::
1051 template OpCalculatePlasticFlowLhs_dTAU<DIM, I>(
1052 ep, tau, common_plastic_ptr, m_D_ptr));
1053 pip.push_back(
1055 ep, temperature, common_thermoplastic_ptr));
1056 pip.push_back(new typename P::template Assembly<A>::
1057 template OpCalculateConstraintsLhs_dEP<DIM, I>(
1058 tau, ep, common_plastic_ptr, m_D_ptr));
1059 pip.push_back(
1060 new typename P::template Assembly<
1061 A>::template OpCalculateConstraintsLhs_dTAU<I>(tau, tau,
1062 common_plastic_ptr));
1063
1064 // TODO: add scenario for when not using Hencky material
1065 pip.push_back(new typename H::template OpCalculateHenckyThermalStressdT<
1066 DIM, I, AssemblyDomainEleOp, 0>(
1067 u, temperature, common_hencky_ptr,
1068 common_thermoelastic_ptr->getCoeffExpansionPtr()));
1069
1070 auto inelastic_heat_frac_ptr =
1071 common_thermoplastic_ptr->getInelasticHeatFractionPtr();
1073 [inelastic_heat_frac_ptr](const double, const double, const double) {
1074 return (*inelastic_heat_frac_ptr);
1075 };
1076
1077 // TODO: add scenario for when not using Hencky material
1080 temperature, temperature, common_hencky_ptr, common_plastic_ptr,
1082 common_thermoelastic_ptr->getCoeffExpansionPtr()));
1083
1084 // TODO: add scenario for when not using Hencky material
1087 temperature, ep, common_hencky_ptr, common_plastic_ptr,
1089
1090 // TODO: add scenario for when not using Hencky material
1093 temperature, u, common_hencky_ptr, common_plastic_ptr,
1095
1097 tau, temperature, common_thermoplastic_ptr));
1098
1100 }
1101
1102 template <int DIM, IntegrationType I, typename DomainEleOp>
1104 MoFEM::Interface &m_field, std::string plastic_block_name,
1105 std::string thermal_block_name, std::string thermoelastic_block_name,
1106 std::string thermoplastic_block_name,
1107 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1108 std::string u, std::string ep, std::string tau, std::string temperature,
1112 bool with_rates = true) {
1113
1115
1116 auto common_plastic_ptr = boost::make_shared<PlasticOps::CommonData>();
1117 auto common_thermal_ptr =
1118 boost::make_shared<ThermoElasticOps::BlockedThermalParameters>();
1119 auto common_thermoelastic_ptr =
1120 boost::make_shared<ThermoElasticOps::BlockedThermoElasticParameters>();
1121 auto common_thermoplastic_ptr =
1122 boost::make_shared<ThermoPlasticOps::ThermoPlasticBlockedParameters>();
1123
1124 constexpr auto size_symm = (DIM * (DIM + 1)) / 2;
1125 auto make_d_mat = []() {
1126 return boost::make_shared<MatrixDouble>(size_symm * size_symm, 1);
1127 };
1128
1129 common_plastic_ptr->mDPtr = boost::make_shared<MatrixDouble>();
1130 common_plastic_ptr->mGradPtr = boost::make_shared<MatrixDouble>();
1131 common_plastic_ptr->mStrainPtr = boost::make_shared<MatrixDouble>();
1132 common_plastic_ptr->mStressPtr = boost::make_shared<MatrixDouble>();
1133
1134 auto m_D_ptr = common_plastic_ptr->mDPtr;
1135
1136 CHK_THROW_MESSAGE(PlasticOps::addMatBlockOps<DIM>(
1137 m_field, plastic_block_name, pip, m_D_ptr,
1138 common_plastic_ptr->getParamsPtr(), scale, sev),
1139 "add mat block plastic ops");
1141 m_field, pip, thermal_block_name, common_thermal_ptr,
1146 "add mat block thermal ops");
1148 m_field, pip, thermoelastic_block_name,
1149 common_thermoelastic_ptr, default_coeff_expansion,
1150 default_ref_temp, sev),
1151 "add mat block thermal ops");
1153 m_field, pip, thermoplastic_block_name,
1154 common_thermoplastic_ptr, common_thermal_ptr, sev,
1156 "add mat block thermoplastic ops");
1157 auto common_hencky_ptr =
1158 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
1159 mField, pip, "U", "MAT_ELASTIC", Sev::inform, scale);
1160
1161 common_plastic_ptr->mDPtr = common_hencky_ptr->matDPtr;
1162
1163 pip.push_back(new OpCalculateScalarFieldValues(
1164 tau, common_plastic_ptr->getPlasticTauPtr()));
1166 ep, common_plastic_ptr->getPlasticStrainPtr()));
1168 u, common_plastic_ptr->mGradPtr));
1169
1170 pip.push_back(new OpCalculateScalarFieldValues(
1171 temperature, common_thermoplastic_ptr->getTempPtr()));
1173 "FLUX", common_thermoplastic_ptr->getHeatFluxPtr()));
1174
1175 common_plastic_ptr->mGradPtr = common_hencky_ptr->matGradPtr;
1176 common_plastic_ptr->mDPtr = common_hencky_ptr->matDPtr;
1177 common_hencky_ptr->matLogCPlastic =
1178 common_plastic_ptr->getPlasticStrainPtr();
1179 common_plastic_ptr->mStrainPtr = common_hencky_ptr->getMatLogC();
1180 common_plastic_ptr->mStressPtr = common_hencky_ptr->getMatHenckyStress();
1181
1183
1184 pip.push_back(new typename H::template OpCalculateEigenVals<DIM, I>(
1185 u, common_hencky_ptr));
1186 pip.push_back(
1187 new typename H::template OpCalculateLogC<DIM, I>(u, common_hencky_ptr));
1188 pip.push_back(new typename H::template OpCalculateLogC_dC<DIM, I>(
1189 u, common_hencky_ptr));
1190
1191 pip.push_back(
1192 new
1193 typename H::template OpCalculateHenckyThermoPlasticStress<DIM, I, 0>(
1194 u, common_thermoplastic_ptr->getTempPtr(), common_hencky_ptr,
1195 common_thermoelastic_ptr->getCoeffExpansionPtr(),
1196 common_thermoelastic_ptr->getRefTempPtr()));
1197 pip.push_back(new typename H::template OpCalculatePiolaStress<DIM, I, 0>(
1198 u, common_hencky_ptr));
1199
1200 pip.push_back(new typename P::template OpCalculatePlasticSurface<DIM, I>(
1201 u, common_plastic_ptr));
1202
1203 pip.push_back(new typename P::template OpCalculatePlasticHardening<DIM, I>(
1204 u, common_plastic_ptr, common_thermoplastic_ptr));
1205
1206 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
1207 common_thermal_ptr, common_thermoelastic_ptr,
1208 common_thermoplastic_ptr);
1209 }
1210
1211 friend struct TSPrePostProc;
1212};
1213
1216
1217 if (auto ptr = tsPrePostProc.lock()) {
1218 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Run step pre proc";
1219
1220 auto &m_field = ptr->ExRawPtr->mField;
1221 auto simple = m_field.getInterface<Simple>();
1222
1223 ResizeCtx *ctx = nullptr;
1224 CHKERR TSGetApplicationContext(ts, (void **)&ctx);
1225 if (!ctx)
1226 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "ResizeCtx missing");
1227
1228 if (ctx->mesh_changed == PETSC_TRUE) { // need to be set for new meshsets
1229 ptr->ExRawPtr->mechanicalBC(comp_mesh_bit, BitRefLevel().set()); // if remeshed
1230 ptr->ExRawPtr->thermalBC(comp_mesh_bit, BitRefLevel().set());
1231 // #ifdef ADD_CONTACT
1232 // auto pip_mng = m_field.getInterface<PipelineManager>();
1233 // pip_mng->getOpDomainLhsPipeline().clear();
1234 // pip_mng->getOpDomainRhsPipeline().clear();
1235 // pip_mng->getOpBoundaryLhsPipeline().clear();
1236 // pip_mng->getOpBoundaryRhsPipeline().clear();
1237 // CHKERR ptr->ExRawPtr->OPs();
1238 // #endif // ADD_CONTACT
1239 }
1240
1241 // get vector norm
1242 auto get_norm = [&](auto x) {
1243 double nrm;
1244 CHKERR VecNorm(x, NORM_2, &nrm);
1245 return nrm;
1246 };
1247
1248 auto save_range = [](moab::Interface &moab, const std::string name,
1249 const Range r) {
1251 auto out_meshset = get_temp_meshset_ptr(moab);
1252 CHKERR moab.add_entities(*out_meshset, r);
1253 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(),
1254 1);
1256 };
1257
1258 auto dm = simple->getDM();
1259 auto d_vector = createDMVector(dm);
1260 CHKERR DMoFEMMeshToLocalVector(dm, d_vector, INSERT_VALUES,
1261 SCATTER_FORWARD);
1262 CHKERR VecGhostUpdateBegin(d_vector, INSERT_VALUES, SCATTER_FORWARD);
1263 CHKERR VecGhostUpdateEnd(d_vector, INSERT_VALUES, SCATTER_FORWARD);
1264 CHKERR DMoFEMMeshToGlobalVector(dm, d_vector, INSERT_VALUES,
1265 SCATTER_REVERSE);
1266
1267 Tag th_spatial_coords;
1268 std::multimap<double, EntityHandle> el_q_map;
1269 std::vector<EntityHandle> new_connectivity;
1270 Range flipped_els;
1271 bool do_refine = false;
1272
1273 auto check_element_quality = [&]() {
1275
1276 // Get Range of all elements not to be flipped in the mesh
1277 Range virgin_entities;
1278 CHKERR m_field.getInterface<BitRefManager>()->getEntitiesByRefLevel(
1279 virgin_mesh_bit, BitRefLevel().set(), virgin_entities);
1280
1281 // Calculates the element quality
1282 CHKERR ptr->ExRawPtr->getElementQuality(el_q_map, flipped_els,
1283 new_connectivity, do_refine,
1284 th_spatial_coords);
1285
1287 };
1288
1289 auto solve_equil_sub_problem = [&]() {
1291 if (el_q_map.size() == 0) {
1293 }
1294
1295 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
1296
1297 auto simple = m_field.getInterface<Simple>();
1298
1300
1301 auto U_ptr = boost::make_shared<MatrixDouble>();
1302 auto EP_ptr = boost::make_shared<MatrixDouble>();
1303 auto TAU_ptr = boost::make_shared<VectorDouble>();
1304 auto T_ptr = boost::make_shared<VectorDouble>();
1305 // auto FLUX_ptr = boost::make_shared<MatrixDouble>();
1306 // auto T_grad_ptr = boost::make_shared<MatrixDouble>();
1307
1308 auto post_proc = [&](auto dm) {
1310
1311 auto post_proc_fe = boost::make_shared<PostProcEle>(m_field);
1312
1314 post_proc_fe->getOpPtrVector(), {H1, L2, HDIV});
1315
1317
1318 // post_proc_fe->getOpPtrVector().push_back(
1319 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX",
1320 // FLUX_ptr));
1321 post_proc_fe->getOpPtrVector().push_back(
1322 new OpCalculateScalarFieldValues("T", T_ptr));
1323 // post_proc_fe->getOpPtrVector().push_back(
1324 // new OpCalculateScalarFieldGradient<SPACE_DIM>("T",
1325 // T_grad_ptr));
1326 post_proc_fe->getOpPtrVector().push_back(
1328 post_proc_fe->getOpPtrVector().push_back(
1329 new OpCalculateScalarFieldValues("TAU", TAU_ptr));
1330 post_proc_fe->getOpPtrVector().push_back(
1332 EP_ptr));
1333 post_proc_fe->getOpPtrVector().push_back(
1334
1335 new OpPPMap(post_proc_fe->getPostProcMesh(),
1336 post_proc_fe->getMapGaussPts(),
1337
1338 {
1339 {"TAU", TAU_ptr},
1340 {"T", T_ptr},
1341 },
1342
1343 {{"U", U_ptr}},
1344
1345 {},
1346
1347 {{"EP", EP_ptr}}
1348
1349 )
1350
1351 );
1352
1353 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", post_proc_fe);
1354 CHKERR post_proc_fe->writeFile("out_equilibrate.h5m");
1355
1357 };
1358
1359 auto solve_equilibrate_solution = [&]() {
1361
1362 auto set_domain_rhs = [&](auto &pip) {
1364
1366 {H1, HDIV});
1367
1368 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1369 AT>::template LinearForm<IT>;
1370 using OpInternalForceCauchy =
1371 typename B::template OpGradTimesSymTensor<1, SPACE_DIM,
1372 SPACE_DIM>;
1373 using OpInternalForcePiola =
1374 typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
1375
1377
1378 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
1379 common_thermoelastic_ptr, common_thermoplastic_ptr] =
1380 ptr->ExRawPtr
1381 ->createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1382 m_field, "MAT_PLASTIC", "MAT_THERMAL",
1383 "MAT_THERMOELASTIC", "MAT_THERMOPLASTIC", pip, "U", "EP",
1386 Sev::inform);
1387
1388 auto m_D_ptr = common_plastic_ptr->mDPtr;
1389
1390 pip.push_back(new OpCalculateScalarFieldValues(
1391 "T", common_thermoplastic_ptr->getTempPtr()));
1392 pip.push_back(
1393 new
1394 typename P::template OpCalculatePlasticityWithoutRates<SPACE_DIM,
1395 IT>(
1396 "U", common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
1397
1398 // Calculate internal forces
1399 if (common_hencky_ptr) {
1400 pip.push_back(new OpInternalForcePiola(
1401 "U", common_hencky_ptr->getMatFirstPiolaStress()));
1402 } else {
1403 pip.push_back(
1404 new OpInternalForceCauchy("U", common_plastic_ptr->mStressPtr));
1405 }
1406
1408 };
1409
1410 auto set_domain_lhs = [&](auto &pip) {
1412
1414 {H1, L2, HDIV});
1415
1416 using namespace HenckyOps;
1417
1418 using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
1419 AT>::template BiLinearForm<IT>;
1420 using OpKPiola =
1421 typename B::template OpGradTensorGrad<1, SPACE_DIM, SPACE_DIM, 1>;
1422 using OpKCauchy =
1423 typename B::template OpGradSymTensorGrad<1, SPACE_DIM, SPACE_DIM,
1424 0>;
1425
1427
1428 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
1429 common_thermoelastic_ptr, common_thermoplastic_ptr] =
1430 ptr->ExRawPtr
1431 ->createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
1432 m_field, "MAT_PLASTIC", "MAT_THERMAL",
1433 "MAT_THERMOELASTIC", "MAT_THERMOPLASTIC", pip, "U", "EP",
1436 Sev::inform);
1437
1438 auto m_D_ptr = common_plastic_ptr->mDPtr;
1439
1440 pip.push_back(
1441 new
1442 typename P::template OpCalculatePlasticityWithoutRates<SPACE_DIM,
1443 IT>(
1444 "U", common_plastic_ptr, m_D_ptr, common_thermoplastic_ptr));
1445
1446 if (common_hencky_ptr) {
1448 pip.push_back(
1449 new typename H::template OpHenckyTangent<SPACE_DIM, IT, 0>(
1450 "U", common_hencky_ptr, m_D_ptr));
1451 pip.push_back(
1452 new OpKPiola("U", "U", common_hencky_ptr->getMatTangent()));
1453 // pip.push_back(
1454 // new typename P::template Assembly<AT>::
1455 // template
1456 // OpCalculatePlasticInternalForceLhs_LogStrain_dEP<
1457 // SPACE_DIM, IT>("U", "EP", common_plastic_ptr,
1458 // common_hencky_ptr, m_D_ptr));
1459 } else {
1460 pip.push_back(new OpKCauchy("U", "U", m_D_ptr));
1461 // pip.push_back(
1462 // new typename P::template Assembly<AT>::
1463 // template
1464 // OpCalculatePlasticInternalForceLhs_dEP<SPACE_DIM,
1465 // IT>(
1466 // "U", "EP", common_plastic_ptr, m_D_ptr));
1467 }
1468
1469 // TODO: add scenario for when not using Hencky material
1470 // pip.push_back(new
1471 // HenckyOps::OpCalculateHenckyThermalStressdT<
1472 // SPACE_DIM, IT, AssemblyDomainEleOp>(
1473 // "U", "T", common_hencky_ptr,
1474 // common_thermal_ptr->getCoeffExpansionPtr()));
1475
1477 };
1478
1479 auto create_sub_dm = [&](SmartPetscObj<DM> base_dm) {
1480 auto dm_sub = createDM(m_field.get_comm(), "DMMOFEM");
1481 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "EQUIL_DM");
1482 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
1483 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
1484 for (auto f : {"U", "EP", "TAU", "T"}) {
1487 }
1488 CHKERR DMSetUp(dm_sub);
1489 return dm_sub;
1490 };
1491
1492 auto sub_dm = create_sub_dm(simple->getDM());
1493
1494 auto fe_rhs = boost::make_shared<DomainEle>(m_field);
1495 auto fe_lhs = boost::make_shared<DomainEle>(m_field);
1496
1497 fe_rhs->getRuleHook = vol_rule;
1498 fe_lhs->getRuleHook = vol_rule;
1499 CHKERR set_domain_rhs(fe_rhs->getOpPtrVector());
1500 CHKERR set_domain_lhs(fe_lhs->getOpPtrVector());
1501
1502 auto bc_mng = m_field.getInterface<BcManager>();
1503
1505 "EQUIL_DM", "U");
1506
1507 auto &bc_map = bc_mng->getBcMapByBlockName();
1508 for (auto bc : bc_map)
1509 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
1510
1511 auto time_scale = boost::make_shared<TimeScale>(
1512 "", false, [](const double) { return 1; });
1513 auto def_time_scale = [time_scale](const double time) {
1514 return (!time_scale->argFileScale) ? time : 1;
1515 };
1516 auto def_file_name = [time_scale](const std::string &&name) {
1517 return (!time_scale->argFileScale) ? name : "";
1518 };
1519 auto time_displacement_scaling = boost::make_shared<TimeScale>(
1520 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
1521
1522 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1523 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1524 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1525
1526 PetscReal current_time;
1527 TSGetTime(ts, &current_time);
1528 pre_proc_ptr->ts_t = current_time;
1529
1530 // Set BCs by eliminating degrees of freedom
1531 auto get_bc_hook_rhs = [&]() {
1533 ptr->ExRawPtr->mField, pre_proc_ptr,
1534 {time_scale, time_displacement_scaling});
1535 return hook;
1536 };
1537 auto get_bc_hook_lhs = [&]() {
1539 ptr->ExRawPtr->mField, pre_proc_ptr,
1540 {time_scale, time_displacement_scaling});
1541 return hook;
1542 };
1543
1544 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1545 pre_proc_ptr->preProcessHook = get_bc_hook_lhs();
1546
1547 auto get_post_proc_hook_rhs = [&]() {
1550 ptr->ExRawPtr->mField, post_proc_rhs_ptr, nullptr,
1551 Sev::verbose)();
1553 ptr->ExRawPtr->mField, post_proc_rhs_ptr, 1.)();
1555 };
1556 auto get_post_proc_hook_lhs = [&]() {
1558 ptr->ExRawPtr->mField, post_proc_lhs_ptr, 1.);
1559 };
1560 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1561 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1562
1563 auto snes_ctx_ptr = getDMSnesCtx(sub_dm);
1564 snes_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_ptr);
1565 snes_ctx_ptr->getPreProcSetOperators().push_front(pre_proc_ptr);
1566 snes_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs_ptr);
1567 snes_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs_ptr);
1568
1569 auto null_fe = boost::shared_ptr<FEMethod>();
1570 // CHKERR DMMoFEMKSPSetComputeOperators(
1571 // sub_dm, simple->getDomainFEName(), fe_lhs, null_fe,
1572 // null_fe);
1573 // CHKERR DMMoFEMKSPSetComputeRHS(sub_dm,
1574 // simple->getDomainFEName(),
1575 // fe_rhs, null_fe, null_fe);
1576 CHKERR DMMoFEMSNESSetFunction(sub_dm, simple->getDomainFEName(), fe_rhs,
1577 null_fe, null_fe);
1578 CHKERR DMMoFEMSNESSetJacobian(sub_dm, simple->getDomainFEName(), fe_lhs,
1579 null_fe, null_fe);
1580
1581 // auto ksp = MoFEM::createKSP(m_field.get_comm());
1582 // CHKERR KSPSetDM(ksp, sub_dm);
1583 // CHKERR KSPSetFromOptions(ksp);
1584
1585 auto D = createDMVector(sub_dm);
1586
1587 auto snes = MoFEM::createSNES(m_field.get_comm());
1588 CHKERR SNESSetDM(snes, sub_dm);
1589 CHKERR SNESSetFromOptions(snes);
1590 CHKERR SNESSetUp(snes);
1591
1592 CHKERR DMoFEMMeshToLocalVector(sub_dm, D, INSERT_VALUES,
1593 SCATTER_FORWARD);
1594 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1595 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1596 // SmartPetscObj<Vec> global_rhs;
1597 // CHKERR DMCreateGlobalVector_MoFEM(
1598 // sub_dm, global_rhs);
1599 // CHKERR KSPSolve(ksp, PETSC_NULLPTR, D);
1600 CHKERR SNESSolve(snes, PETSC_NULLPTR, D);
1601
1602 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1603 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1604 CHKERR DMoFEMMeshToLocalVector(sub_dm, D, INSERT_VALUES,
1605 SCATTER_REVERSE);
1606
1608 };
1609
1610 CHKERR solve_equilibrate_solution();
1611 CHKERR post_proc(simple->getDM());
1612
1613 MOFEM_LOG("REMESHING", Sev::inform)
1614 << "Equilibrated solution after mapping";
1615
1617 };
1618
1619 if (ctx->mesh_changed == PETSC_FALSE) // protects for rollback
1620 CHKERR check_element_quality(); // improve element quality
1621 ctx->mesh_changed = PETSC_FALSE; // needs reset if true
1622 if (el_q_map.size() > 0 || do_refine) {
1623 // Now you can safely update the context fields
1624 ctx->ptr = ptr;
1625 ctx->el_q_map = el_q_map;
1626 ctx->flipped_els = flipped_els;
1627 ctx->new_connectivity = new_connectivity;
1628 ctx->th_spatial_coords = th_spatial_coords;
1629 ctx->mesh_changed = PETSC_TRUE;
1630
1631 // Then trigger the resize process
1632 // CHKERR TSResize(ts);
1633 }
1634
1635 // Need barriers, some functions in TS solver need are called
1636 // collectively and requite the same state of variables
1637 CHKERR PetscBarrier((PetscObject)ts);
1638
1639 MOFEM_LOG_CHANNEL("SYNC");
1640 MOFEM_TAG_AND_LOG("SYNC", Sev::verbose, "REMESHING") << "PreProc done";
1641 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
1642 }
1643
1645}
1646
1648 if (auto ptr = tsPrePostProc.lock()) {
1649 auto &m_field = ptr->ExRawPtr->mField;
1650 MOFEM_LOG_CHANNEL("SYNC");
1651 MOFEM_TAG_AND_LOG("SYNC", Sev::verbose, "THERMOPLASTICITY")
1652 << "PostProc done";
1653 MOFEM_LOG_SEVERITY_SYNC(m_field.get_comm(), Sev::verbose);
1654 }
1655 return 0;
1656}
1657
1659
1661
1662 CHKERR TSSetPreStep(ts, tsPreProc);
1663 CHKERR TSSetPostStep(ts, tsPostProc);
1664
1666}
1667
1669 MoFEM::Interface &m_field,
1670 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
1671 std::string thermoplastic_block_name,
1672 boost::shared_ptr<ThermoPlasticOps::ThermoPlasticBlockedParameters>
1673 blockedParamsPtr,
1674 boost::shared_ptr<ThermoElasticOps::BlockedThermalParameters>
1675 &blockedThermalParamsPtr,
1676 Sev sev, ScalerFunThreeArgs inelastic_heat_fraction_scaling_func) {
1678
1679 struct OpMatThermoPlasticBlocks : public DomainEleOp {
1680 OpMatThermoPlasticBlocks(
1681 boost::shared_ptr<double> omega_0_ptr,
1682 boost::shared_ptr<double> omega_h_ptr,
1683 boost::shared_ptr<double> inelastic_heat_fraction_ptr,
1684 boost::shared_ptr<double> temp_0_ptr,
1685 boost::shared_ptr<double> heat_conductivity,
1686 boost::shared_ptr<double> heat_capacity,
1687 boost::shared_ptr<double> heat_conductivity_scaling,
1688 boost::shared_ptr<double> heat_capacity_scaling,
1690 MoFEM::Interface &m_field, Sev sev,
1691 std::vector<const CubitMeshSets *> meshset_vec_ptr)
1692 : DomainEleOp(NOSPACE, DomainEleOp::OPSPACE), omega0Ptr(omega_0_ptr),
1693 omegaHPtr(omega_h_ptr),
1694 inelasticHeatFractionPtr(inelastic_heat_fraction_ptr),
1695 temp0Ptr(temp_0_ptr), heatConductivityPtr(heat_conductivity),
1696 heatCapacityPtr(heat_capacity),
1697 heatConductivityScalingPtr(heat_conductivity_scaling),
1698 heatCapacityScalingPtr(heat_capacity_scaling),
1699 inelasticHeatFractionScaling(inelastic_heat_fraction_scaling) {
1701 extractThermoPlasticBlockData(m_field, meshset_vec_ptr, sev),
1702 "Can not get data from block");
1703 }
1704
1705 MoFEMErrorCode doWork(int side, EntityType type,
1708
1709 auto scale_param = [this](auto parameter, double scaling) {
1710 return parameter * scaling;
1711 };
1712
1713 for (auto &b : blockData) {
1714
1715 if (b.blockEnts.find(getFEEntityHandle()) != b.blockEnts.end()) {
1716 *omega0Ptr = b.omega_0;
1717 *omegaHPtr = b.omega_h;
1718 *inelasticHeatFractionPtr = scale_param(
1719 b.inelastic_heat_fraction,
1720 inelasticHeatFractionScaling(
1722 *heatConductivityPtr / (*heatConductivityScalingPtr),
1723 *heatCapacityPtr / (*heatCapacityScalingPtr)));
1724 *temp0Ptr = b.temp_0;
1726 }
1727 }
1728
1729 *omega0Ptr = omega_0;
1730 *omegaHPtr = omega_h;
1731 *inelasticHeatFractionPtr =
1732 scale_param(inelastic_heat_fraction,
1733 inelasticHeatFractionScaling(
1735 *heatConductivityPtr / (*heatConductivityScalingPtr),
1736 *heatCapacityPtr / (*heatCapacityScalingPtr)));
1737 *temp0Ptr = temp_0;
1738
1740 }
1741
1742 private:
1743 ScalerFunThreeArgs inelasticHeatFractionScaling;
1744 boost::shared_ptr<double> heatConductivityPtr;
1745 boost::shared_ptr<double> heatCapacityPtr;
1746 boost::shared_ptr<double> heatConductivityScalingPtr;
1747 boost::shared_ptr<double> heatCapacityScalingPtr;
1748 struct BlockData {
1749 double omega_0;
1750 double omega_h;
1752 double temp_0;
1753 Range blockEnts;
1754 };
1755
1756 std::vector<BlockData> blockData;
1757
1758 MoFEMErrorCode extractThermoPlasticBlockData(
1759 MoFEM::Interface &m_field,
1760 std::vector<const CubitMeshSets *> meshset_vec_ptr, Sev sev) {
1762
1763 for (auto m : meshset_vec_ptr) {
1764 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat ThermoPlastic Block") << *m;
1765 std::vector<double> block_data;
1766 CHKERR m->getAttributes(block_data);
1767 if (block_data.size() < 3) {
1768 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1769 "Expected that block has four attributes");
1770 }
1771 auto get_block_ents = [&]() {
1772 Range ents;
1773 CHKERR
1774 m_field.get_moab().get_entities_by_handle(m->meshset, ents, true);
1775 return ents;
1776 };
1777
1778 MOFEM_TAG_AND_LOG("WORLD", sev, "Mat ThermoPlastic Block")
1779 << m->getName() << ": omega_0 = " << block_data[0]
1780 << " omega_h = " << block_data[1]
1781 << " inelastic_heat_fraction = " << block_data[2] << " temp_0 "
1782 << block_data[3];
1783
1784 blockData.push_back({block_data[0], block_data[1], block_data[2],
1785 block_data[3], get_block_ents()});
1786 }
1787 MOFEM_LOG_CHANNEL("WORLD");
1789 }
1790
1791 boost::shared_ptr<double> omega0Ptr;
1792 boost::shared_ptr<double> omegaHPtr;
1793 boost::shared_ptr<double> inelasticHeatFractionPtr;
1794 boost::shared_ptr<double> temp0Ptr;
1795 };
1796
1797 pipeline.push_back(new OpMatThermoPlasticBlocks(
1798 blockedParamsPtr->getOmega0Ptr(), blockedParamsPtr->getOmegaHPtr(),
1799 blockedParamsPtr->getInelasticHeatFractionPtr(),
1800 blockedParamsPtr->getTemp0Ptr(),
1801 blockedThermalParamsPtr->getHeatConductivityPtr(),
1802 blockedThermalParamsPtr->getHeatCapacityPtr(),
1803 blockedThermalParamsPtr->getHeatConductivityScalingPtr(),
1804 blockedThermalParamsPtr->getHeatCapacityScalingPtr(),
1805 inelastic_heat_fraction_scaling_func, m_field, sev,
1806
1807 // Get blockset using regular expression
1808 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
1809
1810 (boost::format("%s(.*)") % thermoplastic_block_name).str()
1811
1812 ))
1813
1814 ));
1815
1817}
1818
1819//! [Get element quality]
1821Example::getElementQuality(std::multimap<double, EntityHandle> &el_q_map,
1822 Range &flipped_els,
1823 std::vector<EntityHandle> &new_connectivity,
1824 bool &do_refine, Tag &th_spatial_coords) {
1826
1827 Range verts;
1828 CHKERR mField.get_moab().get_entities_by_type(0, MBVERTEX, verts);
1829 std::vector<double> coords(verts.size() * 3);
1830 CHKERR mField.get_moab().get_coords(verts, coords.data());
1831 auto t_x = getFTensor1FromPtr<3>(coords.data());
1832
1833 auto save_tag = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
1835 FTENSOR_INDEX(3, i)
1836 auto field_data = ent_ptr->getEntFieldData();
1838 if (SPACE_DIM == 2) {
1839 t_u = {field_data[0], field_data[1], 0.0};
1840 } else {
1841 t_u = {field_data[0], field_data[1], field_data[2]};
1842 }
1843
1844 t_x(i) += t_u(i);
1845 ++t_x;
1847 };
1848
1849 mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(save_tag, "U",
1850 &verts);
1851 double def_coord[3] = {0.0, 0.0, 0.0};
1852 CHKERR mField.get_moab().tag_get_handle(
1853 "SpatialCoord", 3, MB_TYPE_DOUBLE, th_spatial_coords,
1854 MB_TAG_DENSE | MB_TAG_CREAT, def_coord);
1855 CHKERR mField.get_moab().tag_set_data(th_spatial_coords, verts,
1856 coords.data());
1857
1858 // get a map which has the element quality for each tag
1859
1860 Range all_els;
1861 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, all_els,
1862 true);
1863 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1864 virgin_mesh_bit, BitRefLevel().set(), all_els);
1865
1866 std::multimap<double, EntityHandle> candidate_el_q_map;
1867 double spatial_coords[9], material_coords[9];
1868 const EntityHandle *conn;
1869 int num_nodes;
1870 Range::iterator nit = all_els.begin();
1871 for (int gg = 0; nit != all_els.end(); nit++, gg++) {
1872 CHKERR mField.get_moab().get_connectivity(*nit, conn, num_nodes, true);
1873
1874 CHKERR mField.get_moab().get_coords(conn, num_nodes, material_coords);
1875 CHKERR mField.get_moab().tag_get_data(th_spatial_coords, conn, num_nodes,
1876 spatial_coords);
1877
1878 double q = Tools::areaLengthQuality(spatial_coords);
1879 if (!std::isnormal(q))
1880 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1881 "Calculated quality of element is not "
1882 "as expected: %f",
1883 q);
1884
1885 if (q < qual_tol && q > 0.)
1886 candidate_el_q_map.insert(std::pair<double, EntityHandle>(q, *nit));
1887 }
1888
1889 double min_q = 1;
1890 CHKERR mField.getInterface<Tools>()->minElQuality<SPACE_DIM>(
1891 all_els, min_q, th_spatial_coords);
1892 MOFEM_LOG("REMESHING", Sev::inform)
1893 << "Old minimum element quality: " << min_q;
1894 // Get the first element using begin()
1895 auto pair = candidate_el_q_map.begin();
1896 MOFEM_LOG("REMESHING", Sev::inform)
1897 << "New minimum element quality: " << pair->first;
1898
1899 for (auto pair = candidate_el_q_map.begin(); pair != candidate_el_q_map.end();
1900 ++pair) {
1901 double quality = pair->first;
1902 Range element;
1903 element.insert(pair->second);
1904 if (!flipped_els.contains(element)) {
1905 // Get edges of element
1906 Range edges;
1907 CHKERR mField.get_moab().get_adjacencies(element, 1, false, edges);
1908
1909 // Get the longest edge
1910 EntityHandle longest_edge;
1911 double longest_edge_length = 0;
1912 std::vector<std::pair<double, EntityHandle>> edge_lengths;
1913 edge_lengths.reserve(edges.size());
1914 for (auto edge : edges) {
1915 edge_lengths.emplace_back(
1916 mField.getInterface<Tools>()->getEdgeLength(edge), edge);
1917 }
1918 if (!edge_lengths.empty()) {
1919 const auto it = std::max_element(
1920 edge_lengths.begin(), edge_lengths.end(),
1921 [](const auto &a, const auto &b) { return a.first < b.first; });
1922 longest_edge_length = it->first;
1923 longest_edge = it->second;
1924 } else {
1925 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1926 "Unable to calculate edge lengths to find longest edge.");
1927 }
1928
1929 MOFEM_LOG("REMESHING", Sev::verbose)
1930 << "Edge flip longest edge length: " << longest_edge_length
1931 << " for edge: " << longest_edge;
1932
1933 auto get_skin = [&]() {
1934 Range body_ents;
1935 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
1936 body_ents);
1937 Skinner skin(&mField.get_moab());
1938 Range skin_ents;
1939 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
1940 return skin_ents;
1941 };
1942
1943 auto filter_true_skin = [&](auto skin) {
1944 Range boundary_ents;
1945 ParallelComm *pcomm =
1946 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1947 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1948 PSTATUS_NOT, -1, &boundary_ents);
1949 return boundary_ents;
1950 };
1951
1952 Range boundary_ents = get_skin();
1953
1954 MOFEM_LOG("REMESHING", Sev::verbose)
1955 << "Boundary entities: " << boundary_ents;
1956
1957 // Get neighbouring element with the longest edge
1958 Range flip_candidate_els;
1959 CHKERR mField.get_moab().get_adjacencies(&longest_edge, 1, SPACE_DIM,
1960 false, flip_candidate_els);
1961 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1962 virgin_mesh_bit, BitRefLevel().set(), flip_candidate_els);
1963
1964 Range neighbouring_el = subtract(flip_candidate_els, element);
1965 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1966 virgin_mesh_bit, BitRefLevel().set(), neighbouring_el);
1967
1968 if (boundary_ents.contains(Range(longest_edge, longest_edge))) {
1969 continue;
1970 }
1971
1972 if (flipped_els.contains(neighbouring_el))
1973 continue; // Already flipped
1974
1975#ifndef NDEBUG
1976 if (neighbouring_el.size() != 1) {
1977 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1978 "Should be 1 neighbouring element to bad element for edge "
1979 "flip. Instead, there are %d",
1980 neighbouring_el.size());
1981 }
1982#endif
1983
1984 MOFEM_LOG("REMESHING", Sev::verbose)
1985 << "flip_candidate_els: " << flip_candidate_els;
1986 MOFEM_LOG("REMESHING", Sev::verbose)
1987 << "Neighbouring element: " << neighbouring_el;
1988
1989 // Check the quality of the neighbouring element
1990 std::vector<EntityHandle> neighbouring_nodes;
1991 CHKERR mField.get_moab().get_connectivity(&neighbouring_el.front(), 1,
1992 neighbouring_nodes, true);
1993
1994 std::vector<EntityHandle> element_nodes;
1995 CHKERR mField.get_moab().get_connectivity(&element.front(), 1,
1996 element_nodes, true);
1997
1998 CHKERR mField.get_moab().tag_get_data(
1999 th_spatial_coords, &neighbouring_nodes.front(), 3, spatial_coords);
2000
2001 double neighbour_qual = Tools::areaLengthQuality(spatial_coords);
2002 if (!std::isnormal(neighbour_qual))
2003 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
2004 "Calculated quality of neighbouring element is not as "
2005 "expected: %f",
2006 neighbour_qual);
2007
2008 // Get the nodes of flip_candidate_els as well as the nodes of
2009 // longest_edge
2010
2011 MOFEM_LOG("REMESHING", Sev::verbose)
2012 << "Element nodes before swap: "
2013 << get_string_from_vector(element_nodes);
2014 MOFEM_LOG("REMESHING", Sev::verbose)
2015 << "Neighbouring nodes before swap: "
2016 << get_string_from_vector(neighbouring_nodes);
2017
2018 CHKERR save_range(mField.get_moab(), "bad_element.vtk", element);
2019 CHKERR save_range(mField.get_moab(), "bad_element_neighbour.vtk",
2020 neighbouring_el);
2021
2022 // Get new canonical ordering of new nodes and new neighbouring
2023 // nodes
2024 std::vector<EntityHandle> reversed_neighbouring_nodes =
2025 neighbouring_nodes;
2026 std::reverse(reversed_neighbouring_nodes.begin(),
2027 reversed_neighbouring_nodes.end());
2028
2029 int num_matches = 0;
2030 std::vector<bool> mismatch_mask(element_nodes.size());
2031 int loop_counter = 0; // To prevent infinite loop
2032 while (num_matches != 2) {
2033 // Permute first element to the end
2034 std::rotate(reversed_neighbouring_nodes.begin(),
2035 reversed_neighbouring_nodes.begin() + 1,
2036 reversed_neighbouring_nodes.end());
2037 // Create a boolean mask
2038 std::transform(element_nodes.begin(), element_nodes.end(),
2039 reversed_neighbouring_nodes.begin(),
2040 mismatch_mask.begin(), std::equal_to<EntityHandle>());
2041 // Check if common edge is found
2042 num_matches =
2043 std::count(mismatch_mask.begin(), mismatch_mask.end(), true);
2044
2045 ++loop_counter;
2046 if (loop_counter > 3) {
2047 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
2048 "Not found matching nodes for edge flipping");
2049 }
2050 }
2051
2052 // Get matching nodes
2053 std::vector<EntityHandle> matched_elements(element_nodes.size());
2054 std::transform(element_nodes.begin(), element_nodes.end(),
2055 mismatch_mask.begin(), matched_elements.begin(),
2056 [](EntityHandle el, bool match) {
2057 return match ? el : -1; // Or some other "null" value
2058 });
2059
2060 // Remove zero (or "null") elements
2061 matched_elements.erase(
2062 std::remove(matched_elements.begin(), matched_elements.end(), -1),
2063 matched_elements.end());
2064
2065 // Get mismatching nodes
2066 std::vector<EntityHandle> mismatched_elements(element_nodes.size()),
2067 neighbouring_mismatched_elements(neighbouring_nodes.size());
2068 std::transform(element_nodes.begin(), element_nodes.end(),
2069 mismatch_mask.begin(), mismatched_elements.begin(),
2070 [](EntityHandle el, bool match) {
2071 return match ? -1 : el; // Or some other "null" value
2072 });
2073 std::transform(reversed_neighbouring_nodes.begin(),
2074 reversed_neighbouring_nodes.end(), mismatch_mask.begin(),
2075 neighbouring_mismatched_elements.begin(),
2076 [](EntityHandle el, bool match) {
2077 return match ? -1 : el; // Or some other "null" value
2078 });
2079
2080 // Remove zero (or "null") elements
2081 mismatched_elements.erase(std::remove(mismatched_elements.begin(),
2082 mismatched_elements.end(), -1),
2083 mismatched_elements.end());
2084 neighbouring_mismatched_elements.erase(
2085 std::remove(neighbouring_mismatched_elements.begin(),
2086 neighbouring_mismatched_elements.end(), -1),
2087 neighbouring_mismatched_elements.end());
2088
2089 mismatched_elements.insert(mismatched_elements.end(),
2090 neighbouring_mismatched_elements.begin(),
2091 neighbouring_mismatched_elements.end());
2092
2093 MOFEM_LOG("REMESHING", Sev::verbose)
2094 << "Reversed neighbouring nodes: "
2095 << get_string_from_vector(reversed_neighbouring_nodes);
2096
2097 MOFEM_LOG("REMESHING", Sev::verbose)
2098 << "mismatch mask: " << get_string_from_vector(mismatch_mask);
2099
2100 MOFEM_LOG("REMESHING", Sev::verbose)
2101 << "Old nodes are: " << get_string_from_vector(matched_elements);
2102
2103 MOFEM_LOG("REMESHING", Sev::verbose)
2104 << "New nodes are: " << get_string_from_vector(mismatched_elements);
2105
2106 auto replace_correct_nodes = [](std::vector<EntityHandle> &ABC,
2107 std::vector<EntityHandle> &DBA,
2108 const std::vector<EntityHandle> &AB,
2109 const std::vector<EntityHandle> &CD) {
2111 std::vector<std::vector<EntityHandle>> results;
2112 // Assume AB.size() == 2, CD.size() == 2 for tris
2113 for (int i = 0; i < 2; ++i) { // i: 0 for A, 1 for B
2114 for (int j = 0; j < 2; ++j) { // j: 0 for C, 1 for D
2115 // Only try to replace if CD[j] is not already in ABC
2116 if (std::find(ABC.begin(), ABC.end(), CD[j]) == ABC.end()) {
2117 std::vector<EntityHandle> tmp = ABC;
2118 // Find AB[i] in ABC and replace with CD[j]
2119 auto it = std::find(tmp.begin(), tmp.end(), AB[i]);
2120 if (it != tmp.end()) {
2121 *it = CD[j];
2122 results.push_back(tmp);
2123 }
2124 }
2125 }
2126 }
2127
2128 if (results.size() != 2) {
2129 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
2130 "Failed to find two valid vertex replacements for edge "
2131 "flip");
2132 }
2133
2134 ABC = results[0];
2135 DBA = results[1];
2136
2138 };
2139
2140 CHKERR replace_correct_nodes(element_nodes, neighbouring_nodes,
2141 matched_elements, mismatched_elements);
2142
2143 MOFEM_LOG("REMESHING", Sev::verbose)
2144 << "Element nodes after swap: "
2145 << get_string_from_vector(element_nodes);
2146 MOFEM_LOG("REMESHING", Sev::verbose)
2147 << "Neighbouring nodes after swap: "
2148 << get_string_from_vector(neighbouring_nodes);
2149
2150 // Calculate the quality of the new elements
2151 CHKERR mField.get_moab().tag_get_data(
2152 th_spatial_coords, &element_nodes.front(), 3, spatial_coords);
2153
2154 double new_qual = Tools::areaLengthQuality(spatial_coords);
2155 if (new_qual < 0.0 || !std::isfinite(new_qual))
2156 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
2157 "Calculated quality of new element is not as expected: %f",
2158 new_qual);
2159
2160#ifndef NDEBUG
2161 auto check_normal_direction = [&](double qual_val) {
2163 FTensor::Index<'i', 3> i;
2164 auto t_correct_normal = FTensor::Tensor1<double, 3>(0.0, 0.0, 1.0);
2165 auto [new_area, t_new_normal] = Tools::triAreaAndNormal(spatial_coords);
2166 auto t_diff = FTensor::Tensor1<double, 3>();
2167 t_diff(i) = t_new_normal(i) - t_correct_normal(i);
2168 if (qual_val > 1e-6 && t_diff(i) * t_diff(i) > 1e-6) {
2169 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
2170 "Direction of element to be created is wrong orientation");
2171 }
2173 };
2174
2175 CHKERR check_normal_direction(new_qual);
2176#endif
2177
2178 CHKERR mField.get_moab().tag_get_data(
2179 th_spatial_coords, &neighbouring_nodes.front(), 3, spatial_coords);
2180
2181 double new_neighbour_qual = Tools::areaLengthQuality(spatial_coords);
2182 if (new_neighbour_qual < 0.0 || !std::isfinite(new_neighbour_qual))
2183 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
2184 "Calculated quality of new neighbouring element is not "
2185 "as expected: %f",
2186 new_neighbour_qual);
2187
2188#ifndef NDEBUG
2189 CHKERR check_normal_direction(new_neighbour_qual);
2190#endif
2191
2192 // If the minimum element quality has improved, do the flip
2193 if (std::min(new_qual, new_neighbour_qual) >
2194 (1. + qual_thresh) * std::min(quality, neighbour_qual)) {
2195 MOFEM_LOG("REMESHING", Sev::inform)
2196 << "Element quality improved from " << quality << " and "
2197 << neighbour_qual << " to " << new_qual << " and "
2198 << new_neighbour_qual << " for elements" << element << " and "
2199 << neighbouring_el;
2200
2201 // then push to creation "pipeline".
2202 flipped_els.merge(flip_candidate_els);
2203 el_q_map.insert(
2204 std::pair<double, EntityHandle>(pair->first, pair->second));
2205 new_connectivity.insert(new_connectivity.end(), element_nodes.begin(),
2206 element_nodes.end());
2207 new_connectivity.insert(new_connectivity.end(),
2208 neighbouring_nodes.begin(),
2209 neighbouring_nodes.end());
2210 }
2211 }
2212 }
2213
2214 if (el_q_map.size() > 0) {
2215 MOFEM_LOG("REMESHING", Sev::verbose) << "Flipped elements: " << flipped_els;
2216 MOFEM_LOG("REMESHING", Sev::verbose)
2217 << "New connectivity: " << get_string_from_vector(new_connectivity);
2218 }
2219
2220 Range edges;
2221 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByDimAndRefLevel(
2222 virgin_mesh_bit, BitRefLevel().set(), SPACE_DIM - 1, edges);
2223 CHKERR mField.get_moab().tag_get_handle(
2224 "SpatialCoord", 3, MB_TYPE_DOUBLE, th_spatial_coords,
2225 MB_TAG_DENSE | MB_TAG_CREAT, def_coord);
2226
2227 Range prev_ref_ents;
2228 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2229 BitRefLevel().set(REFINED_EDGES_BIT), BitRefLevel().set(), MBEDGE,
2230 prev_ref_ents);
2231
2232 for (auto e : edges) {
2233 const EntityHandle *conn;
2234 int num_nodes;
2235 CHKERR mField.get_moab().get_connectivity(e, conn, num_nodes, true);
2236 std::array<double, 6> ref_coords, spatial_coords;
2237 CHKERR mField.get_moab().get_coords(conn, num_nodes, ref_coords.data());
2238 CHKERR mField.get_moab().tag_get_data(th_spatial_coords, conn, num_nodes,
2239 spatial_coords.data());
2240 auto get_length = [](auto &a) {
2242 FTensor::Tensor1<double, 3> p0{a[0], a[1], a[2]};
2243 FTensor::Tensor1<double, 3> p1{a[3], a[4], a[5]};
2244 p1(i) = p1(i) - p0(i);
2245 return p1.l2();
2246 };
2247 auto ref_edge_length = get_length(ref_coords);
2248 auto spatial_edge_length = get_length(spatial_coords);
2249 auto change = spatial_edge_length / ref_edge_length;
2250 if ((change >= 1. + edge_growth_thresh) && (num_refinement_levels > 0) &&
2251 !prev_ref_ents.contains(Range(e, e))) {
2252 do_refine = true;
2253 }
2254 }
2255
2257};
2258//! [Get element quality]
2259
2260//! [Edge flips]
2262 BitRefLevel child_bit) {
2264
2265 moab::Interface &moab = mField.get_moab();
2266
2267 auto make_edge_flip = [&](auto edge, auto adj_faces, Range &new_tris) {
2269
2270 auto get_conn = [&](EntityHandle e, EntityHandle *conn_cpy) {
2272 const EntityHandle *conn;
2273 int num_nodes;
2274 CHKERR moab.get_connectivity(e, conn, num_nodes, true);
2275 std::copy(conn, conn + num_nodes, conn_cpy);
2277 };
2278
2279 auto get_tri_normals = [&](auto &conn) {
2280 std::array<double, 18> coords;
2281 CHKERR moab.get_coords(conn.data(), 6, coords.data());
2282 std::array<FTensor::Tensor1<double, 3>, 2> tri_normals;
2283 for (int t = 0; t != 2; ++t) {
2284 CHKERR Tools::getTriNormal(&coords[9 * t], &tri_normals[t](0));
2285 }
2286 return tri_normals;
2287 };
2288
2289 auto test_flip = [&](auto &&t_normals) {
2290 FTENSOR_INDEX(3, i);
2291 if (t_normals[0](i) * t_normals[1](i) <
2292 std::numeric_limits<float>::epsilon())
2293 return false;
2294 return true;
2295 };
2296
2297 std::array<EntityHandle, 6> adj_conn;
2298 CHKERR get_conn(adj_faces[0], &adj_conn[0]);
2299 CHKERR get_conn(adj_faces[1], &adj_conn[3]);
2300 std::array<EntityHandle, 2> edge_conn;
2301 CHKERR get_conn(edge, edge_conn.data());
2302 std::array<EntityHandle, 2> new_edge_conn;
2303
2304 int j = 1;
2305 for (int i = 0; i != 6; ++i) {
2306 if (adj_conn[i] != edge_conn[0] && adj_conn[i] != edge_conn[1]) {
2307 new_edge_conn[j] = adj_conn[i];
2308 --j;
2309 }
2310 }
2311
2312 auto &new_conn = adj_conn; //< just alias this
2313 for (int t = 0; t != 2; ++t) {
2314 for (int i = 0; i != 3; ++i) {
2315 if (
2316
2317 (adj_conn[3 * t + i % 3] == edge_conn[0] &&
2318 adj_conn[3 * t + (i + 1) % 3] == edge_conn[1])
2319
2320 ||
2321
2322 (adj_conn[3 * t + i % 3] == edge_conn[1] &&
2323 adj_conn[3 * t + (i + 1) % 3] == edge_conn[0])
2324
2325 ) {
2326 new_conn[3 * t + (i + 1) % 3] = new_edge_conn[t];
2327 break;
2328 }
2329 }
2330 }
2331
2332 if (test_flip(get_tri_normals(new_conn))) {
2333 for (int t = 0; t != 2; ++t) {
2334 Range rtri;
2335 CHKERR moab.get_adjacencies(&new_conn[3 * t], SPACE_DIM + 1, SPACE_DIM,
2336 false, rtri);
2337 if (!rtri.size()) {
2338 EntityHandle tri;
2339 CHKERR moab.create_element(MBTRI, &new_conn[3 * t], SPACE_DIM + 1,
2340 tri);
2341 new_tris.insert(tri);
2342 } else {
2343#ifndef NDEBUG
2344 if (rtri.size() != 1) {
2345 MOFEM_LOG("SELF", Sev::error)
2346 << "Multiple tries created during edge flip for edge " << edge
2347 << " adjacent faces " << std::endl
2348 << rtri;
2349 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
2350 "Multiple tries created during edge flip");
2351 }
2352#endif // NDEBUG
2353 new_tris.merge(rtri);
2354 }
2355 }
2356
2357 Range new_edges;
2358 CHKERR moab.get_adjacencies(new_tris, SPACE_DIM - 1, true, new_edges,
2359 moab::Interface::UNION);
2360 } else {
2361
2362 MOFEM_LOG_CHANNEL("SELF");
2363 MOFEM_LOG("SELF", Sev::warning) << "Edge flip rejected for edge " << edge
2364 << " adjacent faces " << adj_faces;
2365 }
2366
2368 };
2369
2370 Range tris;
2371 CHKERR moab.get_entities_by_dimension(0, SPACE_DIM, tris);
2372 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
2373 parent_bit, BitRefLevel().set(), tris);
2374 Skinner skin(&moab);
2375 Range skin_edges;
2376 CHKERR skin.find_skin(0, tris, false, skin_edges);
2377
2378 Range edges;
2379 CHKERR moab.get_entities_by_dimension(0, SPACE_DIM - 1, edges);
2380 edges = subtract(edges, skin_edges);
2381 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
2382 parent_bit, BitRefLevel().set(), edges);
2383
2384 Range new_tris, flipped_tris, forbidden_tris;
2385 int flip_count = 0;
2386 for (auto edge : edges) {
2387 Range adjacent_tris;
2388 CHKERR moab.get_adjacencies(&edge, 1, SPACE_DIM, true, adjacent_tris);
2389
2390 adjacent_tris = intersect(adjacent_tris, tris);
2391 adjacent_tris = subtract(adjacent_tris, forbidden_tris);
2392 if (adjacent_tris.size() == 2) {
2393
2394#ifndef NDEBUG
2395 int side_number0, sense0, offset0;
2396 CHKERR mField.get_moab().side_number(adjacent_tris[0], edge, side_number0,
2397 sense0, offset0);
2398 int side_number1, sense1, offset1;
2399 CHKERR mField.get_moab().side_number(adjacent_tris[1], edge, side_number1,
2400 sense1, offset1);
2401 if (sense0 * sense1 > 0)
2402 SETERRQ(
2403 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
2404 "Cannot flip edge with same orientation in both adjacent faces");
2405#endif // NDEBUG
2406
2407 Range new_flipped_tris;
2408 CHKERR make_edge_flip(edge, adjacent_tris, new_flipped_tris);
2409 if (new_flipped_tris.size()) {
2410 flipped_tris.merge(adjacent_tris);
2411 forbidden_tris.merge(adjacent_tris);
2412 new_tris.merge(new_flipped_tris);
2413
2414#ifndef NDEBUG
2415 CHKERR save_range(moab,
2416 "flipped_tris_" + std::to_string(flip_count) + ".vtk",
2417 adjacent_tris);
2419 moab, "new_flipped_tris_" + std::to_string(flip_count) + ".vtk",
2420 new_flipped_tris);
2421
2422#endif // NDEBUG
2423
2424 ++flip_count;
2425 }
2426 }
2427 }
2428
2429 Range all_tris;
2430 CHKERR moab.get_entities_by_dimension(0, SPACE_DIM, all_tris);
2431 Range not_flipped_tris = subtract(all_tris, flipped_tris);
2432
2433 MOFEM_LOG("SELF", Sev::noisy)
2434 << "Flipped " << flip_count << " edges with two adjacent faces.";
2435 CHKERR mField.getInterface<BitRefManager>()->setBitRefLevel(not_flipped_tris,
2436 child_bit);
2437 CHKERR mField.getInterface<BitRefManager>()->setBitRefLevel(new_tris,
2438 child_bit);
2439 CHKERR mField.getInterface<BitRefManager>()->writeBitLevel(
2440 child_bit, BitRefLevel().set(), "edge_flips_before_refinement.vtk", "VTK",
2441 "");
2442
2444}
2445//! [Edge flips]
2446
2447//! [Do Edge Flips]
2449Example::doEdgeFlips(std::multimap<double, EntityHandle> &el_q_map,
2450 Range &flipped_els, Tag &th_spatial_coords,
2451 std::vector<EntityHandle> &new_connectivity) {
2453
2454 ReadUtilIface *read_util;
2455 CHKERR mField.get_moab().query_interface(read_util);
2456
2457 const int num_ele = el_q_map.size() * 2; // each flip creates 2 elements
2458 int num_nod_per_ele;
2459 EntityType ent_type;
2460
2461 if (SPACE_DIM == 2) {
2462 num_nod_per_ele = 3;
2463 ent_type = MBTRI;
2464 } else {
2465 num_nod_per_ele = 4;
2466 ent_type = MBTET;
2467 }
2468
2469 Range new_elements;
2470 auto new_conn = new_connectivity.begin();
2471 for (auto e = 0; e != num_ele; ++e) {
2472 EntityHandle conn[num_nod_per_ele];
2473 for (int n = 0; n < num_nod_per_ele; ++n) {
2474 conn[n] = *new_conn;
2475 ++new_conn;
2476 }
2477 EntityHandle new_ele;
2478 Range adj_ele;
2479 CHKERR mField.get_moab().get_adjacencies(conn, num_nod_per_ele, SPACE_DIM,
2480 false, adj_ele);
2481 if (adj_ele.size()) {
2482 if (adj_ele.size() != 1) {
2483 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
2484 "Element duplication");
2485 } else {
2486 new_ele = adj_ele.front();
2487 }
2488 } else {
2489 CHKERR mField.get_moab().create_element(ent_type, conn, num_nod_per_ele,
2490 new_ele);
2491 }
2492 new_elements.insert(new_ele);
2493 }
2494
2495 MOFEM_LOG("REMESHING", Sev::verbose)
2496 << "New elements from edge flipping: " << new_elements;
2497
2498 auto reset_flip_bit = [](EntityHandle ent, BitRefLevel &bit) {
2499 bit.set(STORAGE_BIT, true);
2500 bit.set(FLIPPED_BIT, false);
2501 };
2502 CHKERR mField.getInterface<BitRefManager>()->lambdaBitRefLevel(
2503 reset_flip_bit);
2504
2505 auto get_adj = [&](auto ents) {
2506 Range adj;
2507 for (auto d = 0; d != SPACE_DIM; ++d) {
2509 mField.get_moab().get_adjacencies(ents, d, true, adj,
2510 moab::Interface::UNION),
2511 "Getting adjacencies of dimension " + std::to_string(d) + " failed");
2512 }
2513 return adj;
2514 };
2515
2516 Range non_flipped_range;
2517 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByDimAndRefLevel(
2518 virgin_mesh_bit, BitRefLevel().set(), SPACE_DIM, non_flipped_range);
2519
2520 non_flipped_range = subtract(non_flipped_range, flipped_els);
2521 auto flip_bit_ents = new_elements;
2522 flip_bit_ents.merge(non_flipped_range);
2523 auto adj = get_adj(new_elements);
2524 // flip_bit_ents.merge(get_adj(new_elements));
2525
2526 CHKERR mField.getInterface<BitRefManager>()->setBitRefLevel(
2527 flip_bit_ents, flipped_bit, false);
2528
2529 CHKERR mField.getInterface<BitRefManager>()->writeBitLevelByDim(
2530 BitRefLevel().set(FLIPPED_BIT), BitRefLevel().set(), 2,
2531 "new_elements_after_edge_flips.vtk", "VTK", "");
2532
2534};
2535//! [Do Edge Flips]
2536
2537//! [Refine edges]
2538MoFEMErrorCode Example::doEdgeSplits(bool &refined, bool add_ents) {
2540
2541 Tag th_spatial_coords;
2542 double def_coord[3] = {0.0, 0.0, 0.0};
2543
2544 auto refined_mesh = [&](auto level) {
2546 auto bit = BitRefLevel().set(FLIPPED_BIT + level);
2547 Range edges;
2548 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByDimAndRefLevel(
2549 bit, BitRefLevel().set(), SPACE_DIM - 1, edges);
2550 CHKERR mField.get_moab().tag_get_handle(
2551 "SpatialCoord", 3, MB_TYPE_DOUBLE, th_spatial_coords,
2552 MB_TAG_DENSE | MB_TAG_CREAT, def_coord);
2553
2554 Range refine_edges;
2555 if (add_ents)
2556 for (auto e : edges) {
2557 const EntityHandle *conn;
2558 int num_nodes;
2559 CHKERR mField.get_moab().get_connectivity(e, conn, num_nodes, true);
2560 std::array<double, 6> ref_coords, spatial_coords;
2561 CHKERR mField.get_moab().get_coords(conn, num_nodes, ref_coords.data());
2562 CHKERR mField.get_moab().tag_get_data(th_spatial_coords, conn,
2563 num_nodes, spatial_coords.data());
2564 auto get_length = [](auto &a) {
2566 FTensor::Tensor1<double, 3> p0{a[0], a[1], a[2]};
2567 FTensor::Tensor1<double, 3> p1{a[3], a[4], a[5]};
2568 p1(i) = p1(i) - p0(i);
2569 return p1.l2();
2570 };
2571 auto ref_edge_length = get_length(ref_coords);
2572 auto spatial_edge_length = get_length(spatial_coords);
2573 auto change = spatial_edge_length / ref_edge_length;
2574 if (change >= 1. + edge_growth_thresh) {
2575 refine_edges.insert(e);
2576 }
2577 }
2578
2579 if (refine_edges.size())
2580 refined = true;
2581
2582 Range prev_level_ents;
2583 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2584 bit, BitRefLevel().set(), MBEDGE, prev_level_ents);
2585
2586 Range prev_ref_ents;
2587 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2588 BitRefLevel().set(REFINED_EDGES_BIT), BitRefLevel().set(), MBEDGE,
2589 prev_ref_ents);
2590
2591 refine_edges.merge(intersect(prev_ref_ents, prev_level_ents));
2592 CHKERR mField.getInterface<BitRefManager>()->setNthBitRefLevel(
2593 refine_edges, REFINED_EDGES_BIT, true);
2594
2595 auto refine = mField.getInterface<MeshRefinement>();
2596 auto refined_bit = BitRefLevel().set(FIRST_REF_BIT + level);
2597 CHKERR refine->addVerticesInTheMiddleOfEdges(refine_edges, refined_bit);
2598 Range tris_to_refine;
2599 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByDimAndRefLevel(
2600 bit, BitRefLevel().set(), SPACE_DIM, tris_to_refine);
2601 CHKERR refine->refineTris(tris_to_refine, refined_bit, QUIET, false);
2602
2603 auto set_spatial_coords = [&]() {
2605 Range new_vertices;
2606 CHKERR mField.getInterface<BitRefManager>()->getEntitiesByTypeAndRefLevel(
2607 refined_bit, refined_bit, MBVERTEX, new_vertices);
2608 auto th_parent_handle =
2609 mField.getInterface<BitRefManager>()->get_th_RefParentHandle();
2610 for (auto v : new_vertices) {
2611 EntityHandle parent;
2612 CHKERR mField.get_moab().tag_get_data(th_parent_handle, &v, 1, &parent);
2613 const EntityHandle *conn;
2614 int num_nodes;
2615 CHKERR mField.get_moab().get_connectivity(parent, conn, num_nodes,
2616 true);
2617 std::array<double, 6> spatial_coords;
2618 CHKERR mField.get_moab().tag_get_data(th_spatial_coords, conn,
2619 num_nodes, spatial_coords.data());
2620 for (auto d = 0; d < 3; ++d) {
2621 spatial_coords[d] += spatial_coords[3 + d];
2622 }
2623 for (auto d = 0; d < 3; ++d) {
2624 spatial_coords[d] /= 2.0;
2625 }
2626 CHKERR mField.get_moab().tag_set_data(th_spatial_coords, &v, 1,
2627 spatial_coords.data());
2628 }
2630 };
2631
2632 CHKERR set_spatial_coords();
2633
2634 CHKERR mField.getInterface<BitRefManager>()->writeBitLevelByDim(
2635 BitRefLevel().set(FIRST_REF_BIT + level), BitRefLevel().set(), 2,
2636 ("A_refined_" + boost::lexical_cast<std::string>(level) + ".vtk")
2637 .c_str(),
2638 "VTK", "");
2639
2641 };
2642
2643 auto reset_ref_bits = [](EntityHandle ent, BitRefLevel &bit) {
2644 bit.set(STORAGE_BIT, true);
2645 for (int l = 0; l < num_refinement_levels; ++l) {
2646 bit.set(FIRST_REF_BIT + l, false);
2647 }
2648 };
2649 CHKERR mField.getInterface<BitRefManager>()->lambdaBitRefLevel(
2650 reset_ref_bits);
2651
2652 for (auto l = 0; l < num_refinement_levels; ++l) {
2653 CHKERR refined_mesh(l);
2654 };
2655
2656 CHKERR mField.getInterface<BitRefManager>()->writeBitLevelByDim(
2658 BitRefLevel().set(), 2, "new_elements_after_edge_splits.vtk", "VTK", "");
2659
2661};
2662//! [Refine edges]
2663
2664//! [Run problem]
2669 if (!restart_flg)
2673 CHKERR OPs();
2674 CHKERR tsSolve();
2676}
2677//! [Run problem]
2678
2679//! [Set up problem]
2683
2684 Range domain_ents;
2685 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
2686 true);
2687 auto get_ents_by_dim = [&](const auto dim) {
2688 if (dim == SPACE_DIM) {
2689 return domain_ents;
2690 } else {
2691 Range ents;
2692 if (dim == 0)
2693 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
2694 else
2695 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
2696 return ents;
2697 }
2698 };
2699
2700 auto get_base = [&]() {
2701 auto domain_ents = get_ents_by_dim(SPACE_DIM);
2702 if (domain_ents.empty())
2703 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Empty mesh");
2704 const auto type = type_from_handle(domain_ents[0]);
2705 switch (type) {
2706 case MBQUAD:
2707 return DEMKOWICZ_JACOBI_BASE;
2708 case MBHEX:
2709 return DEMKOWICZ_JACOBI_BASE;
2710 case MBTRI:
2712 case MBTET:
2714 default:
2715 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type not handled");
2716 }
2717 return NOBASE;
2718 };
2719
2720 const auto base = get_base();
2721 MOFEM_LOG("PLASTICITY", Sev::inform)
2722 << "Base " << ApproximationBaseNames[base];
2723
2724 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
2725 CHKERR simple->addDomainField("EP", L2, base, size_symm);
2726 CHKERR simple->addDomainField("TAU", L2, base, 1);
2727 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
2728
2729 constexpr auto flux_space = (SPACE_DIM == 2) ? HCURL : HDIV;
2730 CHKERR simple->addDomainField("T", L2, base, 1);
2731 CHKERR simple->addDomainField("FLUX", flux_space, DEMKOWICZ_JACOBI_BASE, 1);
2732 CHKERR simple->addBoundaryField("FLUX", flux_space, DEMKOWICZ_JACOBI_BASE, 1);
2733 CHKERR simple->addBoundaryField("TBC", L2, base, 1);
2734
2735 // CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
2736
2737 CHKERR simple->setFieldOrder("U", order);
2738 CHKERR simple->setFieldOrder("EP", ep_order);
2739 CHKERR simple->setFieldOrder("TAU", tau_order);
2740 CHKERR simple->setFieldOrder("FLUX", flux_order);
2741 CHKERR simple->setFieldOrder("T", T_order);
2742 CHKERR simple->setFieldOrder("TBC", T_order);
2743
2744 // CHKERR simple->setFieldOrder("GEOMETRY", geom_order);
2745
2746#ifdef ADD_CONTACT
2747 CHKERR simple->addDomainField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
2748 SPACE_DIM);
2749 CHKERR simple->addBoundaryField("SIGMA", CONTACT_SPACE, DEMKOWICZ_JACOBI_BASE,
2750 SPACE_DIM);
2751
2752 auto get_skin = [&]() {
2753 Range body_ents;
2754 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
2755 Skinner skin(&mField.get_moab());
2756 Range skin_ents;
2757 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2758 return skin_ents;
2759 };
2760
2761 auto filter_blocks = [&](auto skin) {
2762 bool is_contact_block = false;
2763 Range contact_range;
2764 for (auto m :
2765 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2766
2767 (boost::format("%s(.*)") % "CONTACT").str()
2768
2769 ))
2770
2771 ) {
2772 is_contact_block =
2773 true; ///< blocs interation is collective, so that is set irrespective
2774 ///< if there are entities in given rank or not in the block
2775 MOFEM_LOG("CONTACT", Sev::inform)
2776 << "Find contact block set: " << m->getName();
2777 auto meshset = m->getMeshset();
2778 Range contact_meshset_range;
2779 CHKERR mField.get_moab().get_entities_by_dimension(
2780 meshset, SPACE_DIM - 1, contact_meshset_range, true);
2781
2782 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
2783 contact_meshset_range);
2784 contact_range.merge(contact_meshset_range);
2785 }
2786 if (is_contact_block) {
2787 MOFEM_LOG("SYNC", Sev::inform)
2788 << "Nb entities in contact surface: " << contact_range.size();
2790 skin = intersect(skin, contact_range);
2791 }
2792 return skin;
2793 };
2794
2795 auto filter_true_skin = [&](auto skin) {
2796 Range boundary_ents;
2797 ParallelComm *pcomm =
2798 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2799 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2800 PSTATUS_NOT, -1, &boundary_ents);
2801 return boundary_ents;
2802 };
2803
2804 auto boundary_ents = filter_true_skin(filter_blocks(get_skin()));
2805 CHKERR simple->setFieldOrder("SIGMA", 0);
2806 CHKERR simple->setFieldOrder("SIGMA", order - 1, &boundary_ents);
2807#endif
2808
2810 // Cannot resetup after this block has been defined
2811 // as empty when remeshing
2812 if (qual_tol < std::numeric_limits<double>::epsilon() &&
2814 CHKERR simple->addFieldToEmptyFieldBlocks("U", "TAU");
2815
2816 // auto project_ho_geometry = [&]() {
2817 // Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
2818 // return mField.loop_dofs("GEOMETRY", ent_method);
2819 // };
2820 // PetscBool project_geometry = PETSC_TRUE;
2821 // CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-project_geometry",
2822 // &project_geometry, PETSC_NULLPTR);
2823 // if (project_geometry) {
2824 // CHKERR project_ho_geometry();
2825 // }
2826
2828}
2829//! [Set up problem]
2830
2831//! [Create common data]
2834
2835 auto get_command_line_parameters = [&]() {
2837
2838 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-quasi_static",
2839 &is_quasi_static, PETSC_NULLPTR);
2840 MOFEM_LOG("PLASTICITY", Sev::inform)
2841 << "Is quasi static: " << (is_quasi_static ? "true" : "false");
2842
2843 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ts_dt", &init_dt,
2844 PETSC_NULLPTR);
2845 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Initial dt: " << init_dt;
2846
2847 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ts_adapt_dt_min", &min_dt,
2848 PETSC_NULLPTR);
2849 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Minimum dt: " << min_dt;
2850
2851 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-min_quality", &qual_tol,
2852 PETSC_NULLPTR);
2853 MOFEM_LOG("REMESHING", Sev::inform)
2854 << "Minumum quality for edge flipping: " << qual_tol;
2855 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "",
2856 "-quality_improvement_threshold", &qual_thresh,
2857 PETSC_NULLPTR);
2858 MOFEM_LOG("REMESHING", Sev::inform)
2859 << "Quality improvement threshold for edge flipping: " << qual_thresh;
2860 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-edge_growth_threshold",
2861 &edge_growth_thresh, PETSC_NULLPTR);
2862 MOFEM_LOG("REMESHING", Sev::inform)
2863 << "Edge growth threshold for edge splitting: " << edge_growth_thresh;
2864 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-num_refinement_levels",
2865 &num_refinement_levels, PETSC_NULLPTR);
2866 MOFEM_LOG("REMESHING", Sev::inform)
2867 << "Number of refinement levels for edge splitting: "
2869
2870 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-scale", &scale,
2871 PETSC_NULLPTR);
2872 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-young_modulus",
2873 &young_modulus, PETSC_NULLPTR);
2874 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-poisson_ratio",
2875 &poisson_ratio, PETSC_NULLPTR);
2876 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening", &H,
2877 PETSC_NULLPTR);
2878 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-hardening_viscous", &visH,
2879 PETSC_NULLPTR);
2880 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-yield_stress", &sigmaY,
2881 PETSC_NULLPTR);
2882 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn0", &cn0,
2883 PETSC_NULLPTR);
2884 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn1", &cn1,
2885 PETSC_NULLPTR);
2886 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-zeta", &zeta,
2887 PETSC_NULLPTR);
2888 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-Qinf", &Qinf,
2889 PETSC_NULLPTR);
2890 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-b_iso", &b_iso,
2891 PETSC_NULLPTR);
2892 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-C1_k", &C1_k,
2893 PETSC_NULLPTR);
2894 // CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-large_strains",
2895 // &is_large_strains, PETSC_NULLPTR);
2896 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-set_timer", &set_timer,
2897 PETSC_NULLPTR);
2898
2899 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-coeff_expansion",
2900 &default_coeff_expansion, PETSC_NULLPTR);
2901 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-ref_temp",
2902 &default_ref_temp, PETSC_NULLPTR);
2903 CHKERR PetscOptionsGetEList("", "-IC_type", ICTypes, 3,
2904 (PetscInt *)&ic_type, PETSC_NULLPTR);
2905 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-init_temp", &init_temp,
2906 PETSC_NULLPTR);
2907 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-peak_temp", &peak_temp,
2908 PETSC_NULLPTR);
2909 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-width", &width,
2910 PETSC_NULLPTR);
2911
2912 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-capacity",
2913 &default_heat_capacity, PETSC_NULLPTR);
2914 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-conductivity",
2915 &default_heat_conductivity, PETSC_NULLPTR);
2916
2917 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-omega_0", &omega_0,
2918 PETSC_NULLPTR);
2919 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-omega_h", &omega_h,
2920 PETSC_NULLPTR);
2921 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-inelastic_heat_fraction",
2922 &inelastic_heat_fraction, PETSC_NULLPTR);
2923 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-temp_0", &temp_0,
2924 PETSC_NULLPTR);
2925
2926 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &order,
2927 PETSC_NULLPTR);
2928 PetscBool tau_order_is_set; ///< true if tau order is set
2929 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-tau_order", &tau_order,
2930 &tau_order_is_set);
2931 PetscBool ep_order_is_set; ///< true if tau order is set
2932 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-ep_order", &ep_order,
2933 &ep_order_is_set);
2934 PetscBool flux_order_is_set; ///< true if flux order is set
2935 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-flux_order", &flux_order,
2936 &flux_order_is_set);
2937 PetscBool T_order_is_set; ///< true if T order is set
2938 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-T_order", &T_order,
2939 &T_order_is_set);
2940 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geom_order,
2941 PETSC_NULLPTR);
2942
2943 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
2944 PETSC_NULLPTR);
2945
2946 CHKERR PetscOptionsGetString(PETSC_NULLPTR, "", "-restart", restart_file,
2947 255, &restart_flg);
2948 sscanf(restart_file, "restart_%d.dat", &restart_step);
2949 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-restart_time",
2950 &restart_time, PETSC_NULLPTR);
2951
2952 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-rho", &rho,
2953 PETSC_NULLPTR);
2954 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-alpha_damping",
2955 &alpha_damping, PETSC_NULLPTR);
2956
2957 MOFEM_LOG("PLASTICITY", Sev::inform) << "Young modulus " << young_modulus;
2958 MOFEM_LOG("PLASTICITY", Sev::inform) << "Poisson ratio " << poisson_ratio;
2959 MOFEM_LOG("PLASTICITY", Sev::inform) << "Yield stress " << sigmaY;
2960 MOFEM_LOG("PLASTICITY", Sev::inform) << "Hardening " << H;
2961 MOFEM_LOG("PLASTICITY", Sev::inform) << "Viscous hardening " << visH;
2962 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation yield stress " << Qinf;
2963 MOFEM_LOG("PLASTICITY", Sev::inform) << "Saturation exponent " << b_iso;
2964 MOFEM_LOG("PLASTICITY", Sev::inform) << "Kinematic hardening " << C1_k;
2965 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn0 " << cn0;
2966 MOFEM_LOG("PLASTICITY", Sev::inform) << "cn1 " << cn1;
2967 MOFEM_LOG("PLASTICITY", Sev::inform) << "zeta " << zeta;
2968
2969 MOFEM_LOG("THERMAL", Sev::inform)
2970 << "default_ref_temp " << default_ref_temp;
2971 MOFEM_LOG("THERMAL", Sev::inform) << "init_temp " << init_temp;
2972 MOFEM_LOG("THERMAL", Sev::inform) << "peak_temp " << peak_temp;
2973 MOFEM_LOG("THERMAL", Sev::inform) << "width " << width;
2974 MOFEM_LOG("THERMAL", Sev::inform)
2975 << "default_coeff_expansion " << default_coeff_expansion;
2976 MOFEM_LOG("THERMAL", Sev::inform)
2977 << "heat_conductivity " << default_heat_conductivity;
2978 MOFEM_LOG("THERMAL", Sev::inform)
2979 << "heat_capacity " << default_heat_capacity;
2980
2981 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
2982 << "inelastic_heat_fraction " << inelastic_heat_fraction;
2983 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "omega_0 " << omega_0;
2984 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "omega_h " << omega_h;
2985
2986 if (tau_order_is_set == PETSC_FALSE)
2987 tau_order = order - 2;
2988 if (ep_order_is_set == PETSC_FALSE)
2989 ep_order = order - 1;
2990
2991 if (flux_order_is_set == PETSC_FALSE)
2992 flux_order = order;
2993 if (T_order_is_set == PETSC_FALSE)
2994 T_order = order - 1;
2995
2996 MOFEM_LOG("PLASTICITY", Sev::inform) << "Approximation order " << order;
2997 MOFEM_LOG("PLASTICITY", Sev::inform)
2998 << "Ep approximation order " << ep_order;
2999 MOFEM_LOG("PLASTICITY", Sev::inform)
3000 << "Tau approximation order " << tau_order;
3001 MOFEM_LOG("THERMAL", Sev::inform)
3002 << "FLUX approximation order " << flux_order;
3003 MOFEM_LOG("THERMAL", Sev::inform) << "T approximation order " << T_order;
3004 // MOFEM_LOG("PLASTICITY", Sev::inform)
3005 // << "Geometry approximation order " << geom_order;
3006
3007 MOFEM_LOG("PLASTICITY", Sev::inform) << "Density " << rho;
3008 MOFEM_LOG("PLASTICITY", Sev::inform) << "alpha_damping " << alpha_damping;
3009
3010 PetscBool is_scale = PETSC_TRUE;
3011 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_scale", &is_scale,
3012 PETSC_NULLPTR);
3013 MOFEM_LOG("THERMOPLASTICITY", Sev::inform) << "Scaling used? " << is_scale;
3014
3015 switch (is_scale) {
3016 case PETSC_TRUE:
3017 MOFEM_LOG("THERMOPLASTICITY", Sev::warning)
3018 << "Scaling does not yet work with radiation and convection BCs";
3019 // FIXME: Need to properly sort scaling as well as when using convection
3020 // and radiation BCs
3022 thermal_conductivity_scaling = [&](double thermal_cond, double heat_cap) {
3023 if (heat_cap != 0.0 && thermal_cond != 0.0)
3024 return 1. / (thermal_cond * heat_cap);
3025 else
3026 return 1. / thermal_cond;
3027 };
3028 heat_capacity_scaling = [&](double thermal_cond, double heat_cap) {
3029 if (heat_cap != 0.0)
3030 return 1. / (thermal_cond * heat_cap);
3031 else
3032 return 1.0;
3033 };
3035 [&](double young_modulus, double thermal_cond, double heat_cap) {
3036 if (heat_cap != 0.0)
3037 return young_modulus / (thermal_cond * heat_cap);
3038 else
3039 return young_modulus / thermal_cond;
3040 };
3041 break;
3042 default:
3043 thermal_conductivity_scaling = [&](double thermal_cond, double heat_cap) {
3044 return 1.0;
3045 };
3046 heat_capacity_scaling = [&](double thermal_cond, double heat_cap) {
3047 return 1.0;
3048 };
3050 double thermal_cond,
3051 double heat_cap) { return 1.0; };
3052 break;
3053 }
3054
3055 MOFEM_LOG("PLASTICITY", Sev::inform) << "Scale " << scale;
3056 MOFEM_LOG("THERMAL", Sev::inform)
3057 << "Thermal conductivity scale "
3060 MOFEM_LOG("THERMAL", Sev::inform)
3061 << "Thermal capacity scale "
3064 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
3065 << "Inelastic heat fraction scale "
3068
3069#ifdef ADD_CONTACT
3070 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-cn_contact",
3071 &ContactOps::cn_contact, PETSC_NULLPTR);
3072 MOFEM_LOG("CONTACT", Sev::inform)
3073 << "cn_contact " << ContactOps::cn_contact;
3074#endif // ADD_CONTACT
3075
3077 };
3078
3079 CHKERR get_command_line_parameters();
3080
3081#ifdef ADD_CONTACT
3082 #ifdef ENABLE_PYTHON_BINDING
3083 sdfPythonPtr = boost::make_shared<ContactOps::SDFPython>();
3084 CHKERR sdfPythonPtr->sdfInit("sdf.py");
3085 ContactOps::sdfPythonWeakPtr = sdfPythonPtr;
3086 #endif
3087#endif // ADD_CONTACT
3088
3090}
3091//! [Create common data]
3092
3093//! [Initial conditions]
3096
3097 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
3098
3099 // #ifdef PYTHON_INIT_SURFACE
3100 // auto get_py_surface_init = []() {
3101 // auto py_surf_init = boost::make_shared<SurfacePython>();
3102 // CHKERR py_surf_init->surfaceInit("surface.py");
3103 // surfacePythonWeakPtr = py_surf_init;
3104 // return py_surf_init;
3105 // };
3106 // auto py_surf_init = get_py_surface_init();
3107 // #endif
3108
3109 auto simple = mField.getInterface<Simple>();
3110
3111 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3112 // "REMOVE_X",
3113 // "U", 0, 0);
3114 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3115 // "REMOVE_Y",
3116 // "U", 1, 1);
3117 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3118 // "REMOVE_Z",
3119 // "U", 2, 2);
3120 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3121 // "REMOVE_ALL", "U", 0, 3);
3122
3123 // #ifdef ADD_CONTACT
3124 // for (auto b : {"FIX_X", "REMOVE_X"})
3125 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
3126 // "SIGMA", 0, 0, false, true);
3127 // for (auto b : {"FIX_Y", "REMOVE_Y"})
3128 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
3129 // "SIGMA", 1, 1, false, true);
3130 // for (auto b : {"FIX_Z", "REMOVE_Z"})
3131 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
3132 // "SIGMA", 2, 2, false, true);
3133 // for (auto b : {"FIX_ALL", "REMOVE_ALL"})
3134 // CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), b,
3135 // "SIGMA", 0, 3, false, true);
3136 // CHKERR bc_mng->removeBlockDOFsOnEntities(
3137 // simple->getProblemName(), "NO_CONTACT", "SIGMA", 0, 3, false, true);
3138 // #endif
3139
3140 // CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
3141 // simple->getProblemName(), "U");
3142
3144
3145 auto T_ptr = boost::make_shared<VectorDouble>();
3146
3147 auto post_proc = [&](auto dm) {
3149
3150 auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
3151
3153
3154 post_proc_fe->getOpPtrVector().push_back(
3155 new OpCalculateScalarFieldValues("T", T_ptr));
3156 // post_proc_fe->getOpPtrVector().push_back(
3157 // new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
3158 if (atom_test == 8) {
3159
3160 auto TAU_ptr = boost::make_shared<VectorDouble>();
3161 auto EP_ptr = boost::make_shared<MatrixDouble>();
3162
3163 post_proc_fe->getOpPtrVector().push_back(
3164 new OpCalculateScalarFieldValues("TAU", TAU_ptr));
3165 post_proc_fe->getOpPtrVector().push_back(
3167
3168 post_proc_fe->getOpPtrVector().push_back(
3169
3170 new OpPPMap(post_proc_fe->getPostProcMesh(),
3171 post_proc_fe->getMapGaussPts(),
3172
3173 {{"T", T_ptr}, {"TAU", TAU_ptr}},
3174
3175 {},
3176
3177 {},
3178
3179 {{"EP", EP_ptr}}
3180
3181 )
3182
3183 );
3184 } else {
3185 post_proc_fe->getOpPtrVector().push_back(
3186
3187 new OpPPMap(post_proc_fe->getPostProcMesh(),
3188 post_proc_fe->getMapGaussPts(),
3189
3190 {{"T", T_ptr}},
3191
3192 {},
3193
3194 {},
3195
3196 {}
3197
3198 )
3199
3200 );
3201 }
3202
3203 CHKERR DMoFEMLoopFiniteElements(dm, "dFE", post_proc_fe);
3204 CHKERR post_proc_fe->writeFile("out_init.h5m");
3205
3207 };
3208
3209 auto solve_init = [&]() {
3211
3212 auto set_domain_rhs = [&](auto &pip) {
3214
3216
3217 pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
3218 pip.push_back(new OpRhsSetInitT<AT, IT>(
3219 "T", nullptr, T_ptr, nullptr, boost::make_shared<double>(init_temp),
3220 boost::make_shared<double>(peak_temp)));
3221
3222 if (atom_test == 8) {
3223 auto TAU_ptr = boost::make_shared<VectorDouble>();
3224 auto EP_ptr = boost::make_shared<MatrixDouble>();
3225
3226 pip.push_back(new OpCalculateScalarFieldValues("TAU", TAU_ptr));
3227 auto min_tau = boost::make_shared<double>(1.0);
3228 auto max_tau = boost::make_shared<double>(2.0);
3229 pip.push_back(new OpRhsSetInitT<AT, IT>("TAU", nullptr, TAU_ptr,
3230 nullptr, min_tau, max_tau));
3231
3233 "EP", EP_ptr));
3234 auto min_EP = boost::make_shared<double>(0.0);
3235 auto max_EP = boost::make_shared<double>(0.01);
3237 "EP", nullptr, EP_ptr, nullptr, min_EP, max_EP));
3238 }
3239
3240 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
3241 // AT>::template LinearForm<IT>;
3242 // using OpInternalForceCauchy =
3243 // typename B::template OpGradTimesSymTensor<1, SPACE_DIM, SPACE_DIM>;
3244 // using OpInternalForcePiola =
3245 // typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
3246
3247 // using P = PlasticityIntegrators<DomainEleOp>;
3248
3249 // auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
3250 // common_thermoelastic_ptr, common_thermoplastic_ptr] =
3251 // createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
3252 // mField, "MAT_ELASTIC", "MAT_THERMAL", "MAT_THERMOPLASTIC", pip,
3253 // "U", "EP", "TAU", "T", scale, thermal_conductivity_scale,
3254 // heat_capacity_scale, inelastic_heat_fraction_scale,
3255 // Sev::inform);
3256 // auto m_D_ptr = common_hencky_ptr->matDPtr;
3257
3258 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
3259 // AT>::template LinearForm<IT>;
3260 // using H = HenckyOps::HenckyIntegrators<DomainEleOp>;
3261 // auto coeff_expansion_ptr = common_thermal_ptr->getCoeffExpansionPtr();
3262 // auto ref_temp_ptr = common_thermal_ptr->getRefTempPtr();
3263 // pip.push_back(new
3264 // typename H::template
3265 // OpCalculateHenckyThermalStress<SPACE_DIM, IT>(
3266 // "U", T_ptr, common_hencky_ptr,
3267 // coeff_expansion_ptr, ref_temp_ptr));
3268 // pip.push_back(new typename H::template
3269 // OpCalculatePiolaStress<SPACE_DIM, IT>(
3270 // "U", common_hencky_ptr));
3271 // using OpInternalForcePiola =
3272 // typename B::template OpGradTimesTensor<1, SPACE_DIM, SPACE_DIM>;
3273 // pip.push_back(new OpInternalForcePiola(
3274 // "U", common_hencky_ptr->getMatFirstPiolaStress()));
3275
3277 };
3278
3279 auto set_domain_lhs = [&](auto &pip) {
3281
3283
3284 using OpLhsScalarLeastSquaresProj = FormsIntegrators<
3285 DomainEleOp>::Assembly<AT>::BiLinearForm<IT>::OpMass<1, 1>;
3286 pip.push_back(new OpLhsScalarLeastSquaresProj("T", "T"));
3287 if (atom_test == 8) {
3288 pip.push_back(new OpLhsScalarLeastSquaresProj("TAU", "TAU"));
3289 pip.push_back(
3291 "EP", "EP"));
3292 }
3293
3294 // auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
3295 // common_thermoelastic_ptr, common_thermoplastic_ptr] =
3296 // createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
3297 // mField, "MAT_ELASTIC", "MAT_THERMAL", "MAT_THERMOPLASTIC", pip,
3298 // "U", "EP", "TAU", "T", scale, thermal_conductivity_scale,
3299 // heat_capacity_scale, inelastic_heat_fraction_scale,
3300 // Sev::inform);
3301
3302 // auto m_D_ptr = common_hencky_ptr->matDPtr;
3303
3304 // using B = typename FormsIntegrators<DomainEleOp>::template Assembly<
3305 // AT>::template BiLinearForm<IT>;
3306 // using OpKPiola = typename B::template OpGradTensorGrad<1, SPACE_DIM,
3307 // SPACE_DIM, 1>;
3308
3309 // using H = HenckyIntegrators<DomainEleOp>;
3310 // pip.push_back(new OpCalculateScalarFieldValues("T", T_ptr));
3311 // auto coeff_expansion_ptr = common_thermal_ptr->getCoeffExpansionPtr();
3312 // auto ref_temp_ptr = common_thermal_ptr->getRefTempPtr();
3313 // pip.push_back(new
3314 // typename H::template
3315 // OpCalculateHenckyThermalStress<SPACE_DIM, IT>(
3316 // "U", T_ptr, common_hencky_ptr,
3317 // coeff_expansion_ptr, ref_temp_ptr));
3318 // pip.push_back(new typename H::template
3319 // OpCalculatePiolaStress<SPACE_DIM, IT>(
3320 // "U", common_hencky_ptr));
3321 // pip.push_back(new typename H::template OpHenckyTangent<SPACE_DIM, IT>(
3322 // "U", common_hencky_ptr));
3323 // pip.push_back(new OpKPiola("U", "U",
3324 // common_hencky_ptr->getMatTangent()));
3325 // pip.push_back(new typename HenckyOps::OpCalculateHenckyThermalStressdT<
3326 // SPACE_DIM, IT, AssemblyDomainEleOp>("U", "T",
3327 // common_hencky_ptr,
3328 // coeff_expansion_ptr));
3329
3331 };
3332
3333 auto create_sub_dm = [&](SmartPetscObj<DM> base_dm) {
3334 auto dm_sub = createDM(mField.get_comm(), "DMMOFEM");
3335 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "INIT_DM");
3336 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
3337 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
3338 for (auto f : {"T"}) {
3341 }
3342 if (atom_test == 8) {
3343 for (auto f : {"TAU", "EP"}) {
3346 }
3347 }
3348 CHKERR DMSetUp(dm_sub);
3349 return dm_sub;
3350 };
3351
3352 auto fe_rhs = boost::make_shared<DomainEle>(mField);
3353 auto fe_lhs = boost::make_shared<DomainEle>(mField);
3354 fe_rhs->getRuleHook = vol_rule;
3355 fe_lhs->getRuleHook = vol_rule;
3356 CHKERR set_domain_rhs(fe_rhs->getOpPtrVector());
3357 CHKERR set_domain_lhs(fe_lhs->getOpPtrVector());
3358
3359 auto sub_dm = create_sub_dm(simple->getDM());
3360
3361 auto null_fe = boost::shared_ptr<FEMethod>();
3362 CHKERR DMMoFEMKSPSetComputeOperators(sub_dm, simple->getDomainFEName(),
3363 fe_lhs, null_fe, null_fe);
3364 CHKERR DMMoFEMKSPSetComputeRHS(sub_dm, simple->getDomainFEName(), fe_rhs,
3365 null_fe, null_fe);
3366
3367 auto ksp = MoFEM::createKSP(mField.get_comm());
3368 CHKERR KSPSetDM(ksp, sub_dm);
3369 CHKERR KSPSetFromOptions(ksp);
3370
3371 auto D = createDMVector(sub_dm);
3372
3373 CHKERR KSPSolve(ksp, PETSC_NULLPTR, D);
3374
3375 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
3376 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
3377 CHKERR DMoFEMMeshToGlobalVector(sub_dm, D, INSERT_VALUES, SCATTER_REVERSE);
3378
3380 };
3381
3382 CHKERR solve_init();
3383 CHKERR post_proc(simple->getDM());
3384
3385 MOFEM_LOG("THERMAL", Sev::inform) << "Set thermoelastic initial conditions";
3386
3388}
3389//! [Initial conditions]
3390
3391//! [Mechanical boundary conditions]
3394
3395 auto simple = mField.getInterface<Simple>();
3396 auto bc_mng = mField.getInterface<BcManager>();
3397
3398 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
3399 "U", 0, 0, true,
3401 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
3402 "U", 1, 1, true,
3404 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
3405 "U", 2, 2, true,
3407 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3408 "REMOVE_ALL", "U", 0, 3, true,
3410
3411#ifdef ADD_CONTACT
3412 for (auto b : {"FIX_X", "REMOVE_X"})
3413 CHKERR bc_mng->removeBlockDOFsOnEntities(
3414 simple->getProblemName(), b, "SIGMA", 0, 0, false, is_distributed_mesh);
3415 for (auto b : {"FIX_Y", "REMOVE_Y"})
3416 CHKERR bc_mng->removeBlockDOFsOnEntities(
3417 simple->getProblemName(), b, "SIGMA", 1, 1, false, is_distributed_mesh);
3418 for (auto b : {"FIX_Z", "REMOVE_Z"})
3419 CHKERR bc_mng->removeBlockDOFsOnEntities(
3420 simple->getProblemName(), b, "SIGMA", 2, 2, false, is_distributed_mesh);
3421 for (auto b : {"FIX_ALL", "REMOVE_ALL"})
3422 CHKERR bc_mng->removeBlockDOFsOnEntities(
3423 simple->getProblemName(), b, "SIGMA", 0, 3, false, is_distributed_mesh);
3424 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
3425 "NO_CONTACT", "SIGMA", 0, 3, false,
3427#endif
3428
3429 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
3430 simple->getProblemName(), "U");
3431
3432 auto &bc_map = bc_mng->getBcMapByBlockName();
3433 for (auto bc : bc_map)
3434 MOFEM_LOG("PLASTICITY", Sev::verbose) << "Marker " << bc.first;
3435
3437}
3438//! [Mechanical boundary conditions]
3439
3440//! [Thermal boundary conditions]
3443
3444 MOFEM_LOG("SYNC", Sev::noisy) << "bC";
3446
3447 auto simple = mField.getInterface<Simple>();
3448 auto bc_mng = mField.getInterface<BcManager>();
3449
3450 auto get_skin = [&]() {
3451 Range body_ents;
3452 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents);
3453 CHKERR mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
3454 bit, BitRefLevel().set(), body_ents);
3455 Skinner skin(&mField.get_moab());
3456 Range skin_ents;
3457 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
3458 return skin_ents;
3459 };
3460
3461 auto filter_flux_blocks = [&](auto skin, bool temp_bc = false) {
3462 auto remove_cubit_blocks = [&](auto c) {
3464 for (auto m :
3465
3466 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(c)
3467
3468 ) {
3469 Range ents;
3470 CHKERR mField.get_moab().get_entities_by_dimension(
3471 m->getMeshset(), SPACE_DIM - 1, ents, true);
3472 skin = subtract(skin, ents);
3473 }
3475 };
3476
3477 auto remove_named_blocks = [&](auto n) {
3479 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
3480 std::regex(
3481
3482 (boost::format("%s(.*)") % n).str()
3483
3484 ))
3485
3486 ) {
3487 Range ents;
3488 CHKERR mField.get_moab().get_entities_by_dimension(
3489 m->getMeshset(), SPACE_DIM - 1, ents, true);
3490 skin = subtract(skin, ents);
3491 }
3493 };
3494 if (!temp_bc) {
3495 CHK_THROW_MESSAGE(remove_cubit_blocks(NODESET | TEMPERATURESET),
3496 "remove_cubit_blocks");
3497 CHK_THROW_MESSAGE(remove_named_blocks("TEMPERATURE"),
3498 "remove_named_blocks");
3499 }
3500 CHK_THROW_MESSAGE(remove_cubit_blocks(SIDESET | HEATFLUXSET),
3501 "remove_cubit_blocks");
3502 CHK_THROW_MESSAGE(remove_named_blocks("HEATFLUX"), "remove_named_blocks");
3503 CHK_THROW_MESSAGE(remove_named_blocks("CONVECTION"), "remove_named_blocks");
3504 CHK_THROW_MESSAGE(remove_named_blocks("RADIATION"), "remove_named_blocks");
3505 return skin;
3506 };
3507
3508 auto filter_true_skin = [&](auto skin) {
3509 Range boundary_ents;
3510 ParallelComm *pcomm =
3511 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
3512 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
3513 PSTATUS_NOT, -1, &boundary_ents);
3514 return boundary_ents;
3515 };
3516
3517 auto remove_flux_ents = filter_true_skin(filter_flux_blocks(get_skin()));
3518 auto remove_temp_bc_ents =
3519 filter_true_skin(filter_flux_blocks(get_skin(), true));
3520
3521 // CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
3522 // remove_flux_ents);
3523 // CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
3524 // remove_temp_bc_ents);
3525
3526 MOFEM_LOG("SYNC", Sev::noisy) << remove_flux_ents << endl;
3528
3529 MOFEM_LOG("SYNC", Sev::noisy) << remove_temp_bc_ents << endl;
3531
3532#ifndef NDEBUG
3533
3535 mField.get_moab(),
3536 (boost::format("flux_remove_%d.vtk") % mField.get_comm_rank()).str(),
3537 remove_flux_ents);
3538
3539#endif
3540
3541 if (is_distributed_mesh == PETSC_TRUE) {
3542 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
3543 simple->getProblemName(), "FLUX", remove_flux_ents);
3544 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
3545 simple->getProblemName(), "TBC", remove_temp_bc_ents);
3546 } else {
3548 ->removeDofsOnEntitiesNotDistributed(simple->getProblemName(), "FLUX",
3549 remove_flux_ents);
3551 ->removeDofsOnEntitiesNotDistributed(simple->getProblemName(), "TBC",
3552 remove_temp_bc_ents);
3553 }
3554
3555 // auto set_init_temp = [](boost::shared_ptr<FieldEntity> field_entity_ptr) {
3556 // field_entity_ptr->getEntFieldData()[0] = init_temp;
3557 // return 0;
3558 // };
3559 // CHKERR
3560 // mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(set_init_temp,
3561 // "T");
3562
3563 CHKERR bc_mng->pushMarkDOFsOnEntities<HeatFluxCubitBcData>(
3564 simple->getProblemName(), "FLUX", false);
3565
3567}
3568//! [Thermal Boundary conditions]
3569
3570//! [Push operators to pipeline]
3573 auto pip_mng = mField.getInterface<PipelineManager>();
3574 auto simple = mField.getInterface<Simple>();
3575 auto bc_mng = mField.getInterface<BcManager>();
3576
3577 auto boundary_marker =
3578 bc_mng->getMergedBlocksMarker(vector<string>{"HEATFLUX"});
3579
3580 auto integration_rule_bc = [](int, int, int ao) { return 2 * ao; };
3581
3582 auto vol_rule = [](int, int, int ao) { return 2 * ao + geom_order; };
3583
3584 CHKERR pip_mng->setDomainRhsIntegrationRule(vol_rule);
3585 CHKERR pip_mng->setDomainLhsIntegrationRule(vol_rule);
3586
3587 CHKERR pip_mng->setBoundaryLhsIntegrationRule(integration_rule_bc);
3588 CHKERR pip_mng->setBoundaryRhsIntegrationRule(integration_rule_bc);
3589
3590 auto thermal_block_params =
3591 boost::make_shared<ThermoElasticOps::BlockedThermalParameters>();
3592 auto heat_conductivity_ptr = thermal_block_params->getHeatConductivityPtr();
3593 auto heat_capacity_ptr = thermal_block_params->getHeatCapacityPtr();
3594
3595 auto thermoelastic_block_params =
3596 boost::make_shared<ThermoElasticOps::BlockedThermoElasticParameters>();
3597 auto coeff_expansion_ptr = thermoelastic_block_params->getCoeffExpansionPtr();
3598 auto ref_temp_ptr = thermoelastic_block_params->getRefTempPtr();
3599
3600 // Default time scaling of BCs and sources, from command line arguments
3601 auto time_scale =
3602 boost::make_shared<TimeScale>("", false, [](const double) { return 1; });
3603 auto def_time_scale = [time_scale](const double time) {
3604 return (!time_scale->argFileScale) ? time : 1;
3605 };
3606 auto def_file_name = [time_scale](const std::string &&name) {
3607 return (!time_scale->argFileScale) ? name : "";
3608 };
3609
3610 // Files which define scaling for separate variables, if provided
3611 auto time_bodyforce_scaling = boost::make_shared<TimeScale>(
3612 def_file_name("bodyforce_scale.txt"), false, def_time_scale);
3613 auto time_heatsource_scaling = boost::make_shared<TimeScale>(
3614 def_file_name("heatsource_scale.txt"), false, def_time_scale);
3615 auto time_temperature_scaling = boost::make_shared<TimeScale>(
3616 def_file_name("temperature_bc_scale.txt"), false, def_time_scale);
3617 auto time_displacement_scaling = boost::make_shared<TimeScale>(
3618 def_file_name("displacement_bc_scale.txt"), false, def_time_scale);
3619 auto time_flux_scaling = boost::make_shared<TimeScale>(
3620 def_file_name("flux_bc_scale.txt"), false, def_time_scale);
3621 auto time_force_scaling = boost::make_shared<TimeScale>(
3622 def_file_name("force_bc_scale.txt"), false, def_time_scale);
3623
3624 auto add_boundary_ops_lhs = [&](auto &pip) {
3626
3627 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3628
3630 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
3631
3632 // Add Natural BCs to LHS
3634 pip, mField, "U", Sev::inform);
3635
3636#ifdef ADD_CONTACT
3637 CHKERR
3638 ContactOps::opFactoryBoundaryLhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
3639 pip, "SIGMA", "U");
3640 CHKERR
3641 ContactOps::opFactoryBoundaryToDomainLhs<SPACE_DIM, AT, IT, DomainEle>(
3642 mField, pip, simple->getDomainFEName(), "SIGMA", "U", "", vol_rule);
3643#endif // ADD_CONTACT
3644
3645 using T =
3646 NaturalBC<BoundaryEleOp>::template Assembly<PETSC>::BiLinearForm<GAUSS>;
3647 using OpConvectionLhsBC =
3648 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
3649 using OpRadiationLhsBC =
3650 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
3651 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
3652 pip.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
3653 T::AddFluxToPipeline<OpConvectionLhsBC>::add(pip, mField, "TBC", "TBC",
3654 "CONVECTION", Sev::verbose);
3655 T::AddFluxToPipeline<OpRadiationLhsBC>::add(
3656 pip, mField, "TBC", "TBC", temp_bc_ptr, "RADIATION", Sev::verbose);
3657
3658 // This is temporary implementation. It be moved to LinearFormsIntegrators,
3659 // however for hybridised case, what is goal of this changes, such function
3660 // is implemented for fluxes in broken space. Thus ultimately this operator
3661 // would be not needed.
3662
3663 struct OpTBCTimesNormalFlux
3665
3667
3668 OpTBCTimesNormalFlux(const std::string row_field_name,
3669 const std::string col_field_name,
3670 boost::shared_ptr<Range> ents_ptr = nullptr)
3671 : OP(row_field_name, col_field_name, OP::OPROWCOL, ents_ptr) {
3672 this->sYmm = false;
3673 this->assembleTranspose = true;
3674 this->onlyTranspose = false;
3675 }
3676
3677 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data,
3678 EntitiesFieldData::EntData &col_data) {
3680
3682
3683 // get integration weights
3684 auto t_w = OP::getFTensor0IntegrationWeight();
3685 // get base function values on rows
3686 auto t_row_base = row_data.getFTensor0N();
3687 // get normal vector
3688 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3689 // loop over integration points
3690 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3691 // loop over rows base functions
3692 auto a_mat_ptr = &*OP::locMat.data().begin();
3693 int rr = 0;
3694 for (; rr != OP::nbRows; rr++) {
3695 // take into account Jacobian
3696 const double alpha = t_w * t_row_base;
3697 // get column base functions values at gauss point gg
3698 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
3699 // loop over columns
3700 for (int cc = 0; cc != OP::nbCols; cc++) {
3701 // calculate element of local matrix
3702 // using L2 norm of normal vector for convenient area calculation
3703 // for quads, tris etc.
3704 *a_mat_ptr += alpha * (t_col_base(i) * t_normal(i));
3705 ++t_col_base;
3706 ++a_mat_ptr;
3707 }
3708 ++t_row_base;
3709 }
3710 for (; rr < OP::nbRowBaseFunctions; ++rr)
3711 ++t_row_base;
3712 ++t_normal;
3713 ++t_w; // move to another integration weight
3714 }
3715 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3716 if (fe_type == MBTRI) {
3717 OP::locMat /= 2;
3718 }
3720 }
3721 };
3722
3723 pip.push_back(new OpTBCTimesNormalFlux("TBC", "FLUX"));
3724
3726 };
3727
3728 auto add_boundary_ops_rhs = [&](auto &pip) {
3730
3732 pip.push_back(new OpSetHOWeightsOnSubDim<SPACE_DIM>());
3733
3735 pip, mField, "U", {time_scale, time_force_scaling}, "FORCE",
3736 Sev::inform);
3737
3738 // Temperature BC
3739
3740 using OpTemperatureBC =
3743 pip, mField, "FLUX", {time_scale, time_temperature_scaling},
3744 "TEMPERATURE", Sev::inform);
3745
3746 // Note: fluxes for temperature should be aggregated. Here separate is
3747 // NaturalMeshsetType<HEATFLUXSET>, we should add version with BLOCKSET,
3748 // convection, see example tutorials/vec-0/src/NaturalBoundaryBC.hpp.
3749 // and vec-0/elastic.cpp
3750
3751 using OpFluxBC =
3754 pip, mField, "TBC", {time_scale, time_flux_scaling}, "FLUX",
3755 Sev::inform);
3756
3758 using OpConvectionRhsBC =
3759 T::OpFlux<ThermoElasticOps::ConvectionBcType<BLOCKSET>, 1, 1>;
3760 using OpRadiationRhsBC =
3761 T::OpFlux<ThermoElasticOps::RadiationBcType<BLOCKSET>, 1, 1>;
3762 auto temp_bc_ptr = boost::make_shared<VectorDouble>();
3763 pip.push_back(new OpCalculateScalarFieldValues("TBC", temp_bc_ptr));
3764 T::AddFluxToPipeline<OpConvectionRhsBC>::add(
3765 pip, mField, "TBC", temp_bc_ptr, "CONVECTION", Sev::inform);
3766 T::AddFluxToPipeline<OpRadiationRhsBC>::add(pip, mField, "TBC", temp_bc_ptr,
3767 "RADIATION", Sev::inform);
3768
3769 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3770 pip.push_back(
3771 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3772
3773 // This is temporary implementation. It be moved to LinearFormsIntegrators,
3774 // however for hybridised case, what is goal of this changes, such function
3775 // is implemented for fluxes in broken space. Thus ultimately this operator
3776 // would be not needed.
3777
3778 struct OpTBCTimesNormalFlux
3780
3782
3783 OpTBCTimesNormalFlux(const std::string field_name,
3784 boost::shared_ptr<MatrixDouble> vec,
3785 boost::shared_ptr<Range> ents_ptr = nullptr)
3786 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
3787
3788 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
3791 // get integration weights
3792 auto t_w = OP::getFTensor0IntegrationWeight();
3793 // get base function values on rows
3794 auto t_row_base = row_data.getFTensor0N();
3795 // get normal vector
3796 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3797 // get vector values
3798 auto t_vec = getFTensor1FromMat<SPACE_DIM, 1>(*sourceVec);
3799 // loop over integration points
3800 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3801 // take into account Jacobian
3802 const double alpha = t_w * (t_vec(i) * t_normal(i));
3803 // loop over rows base functions
3804 int rr = 0;
3805 for (; rr != OP::nbRows; ++rr) {
3806 OP::locF[rr] += alpha * t_row_base;
3807 ++t_row_base;
3808 }
3809 for (; rr < OP::nbRowBaseFunctions; ++rr)
3810 ++t_row_base;
3811 ++t_w; // move to another integration weight
3812 ++t_vec;
3813 ++t_normal;
3814 }
3815 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3816 if (fe_type == MBTRI) {
3817 OP::locF /= 2;
3818 }
3820 }
3821
3822 protected:
3823 boost::shared_ptr<MatrixDouble> sourceVec;
3824 };
3825 pip.push_back(new OpTBCTimesNormalFlux("TBC", mat_flux_ptr));
3826
3827 struct OpBaseNormalTimesTBC
3829
3831
3832 OpBaseNormalTimesTBC(const std::string field_name,
3833 boost::shared_ptr<VectorDouble> vec,
3834 boost::shared_ptr<Range> ents_ptr = nullptr)
3835 : OP(field_name, field_name, OP::OPROW, ents_ptr), sourceVec(vec) {}
3836
3837 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data) {
3840 // get integration weights
3841 auto t_w = OP::getFTensor0IntegrationWeight();
3842 // get base function values on rows
3843 auto t_row_base = row_data.getFTensor1N<3>();
3844 // get normal vector
3845 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
3846 // get vector values
3847 auto t_vec = getFTensor0FromVec(*sourceVec);
3848 // loop over integration points
3849 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
3850 // take into account Jacobian
3851 const double alpha = t_w * t_vec;
3852 // loop over rows base functions
3853 int rr = 0;
3854 for (; rr != OP::nbRows; ++rr) {
3855 OP::locF[rr] += alpha * (t_row_base(i) * t_normal(i));
3856 ++t_row_base;
3857 }
3858 for (; rr < OP::nbRowBaseFunctions; ++rr)
3859 ++t_row_base;
3860 ++t_w; // move to another integration weight
3861 ++t_vec;
3862 ++t_normal;
3863 }
3864 EntityType fe_type = OP::getNumeredEntFiniteElementPtr()->getEntType();
3865 if (fe_type == MBTRI) {
3866 OP::locF /= 2;
3867 }
3869 }
3870
3871 protected:
3872 boost::shared_ptr<VectorDouble> sourceVec;
3873 };
3874
3875 pip.push_back(new OpBaseNormalTimesTBC("FLUX", temp_bc_ptr));
3876
3877#ifdef ADD_CONTACT
3878 CHKERR ContactOps::opFactoryBoundaryRhs<SPACE_DIM, AT, IT, BoundaryEleOp>(
3879 pip, "SIGMA", "U");
3880#endif // ADD_CONTACT
3881
3883 };
3884
3885 auto add_domain_ops_lhs = [&](auto &pip) {
3887
3888 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3889
3891 mField, pip, "MAT_THERMAL", thermal_block_params,
3895
3897
3898 if (is_quasi_static == PETSC_FALSE) {
3899
3900 //! [Only used for dynamics]
3903 //! [Only used for dynamics]
3904
3905 auto get_inertia_and_mass_damping = [this](const double, const double,
3906 const double) {
3907 auto *pip = mField.getInterface<PipelineManager>();
3908 auto &fe_domain_lhs = pip->getDomainLhsFE();
3909 return (rho / scale) * fe_domain_lhs->ts_aa +
3910 (alpha_damping / scale) * fe_domain_lhs->ts_a;
3911 };
3912 pip.push_back(new OpMass("U", "U", get_inertia_and_mass_damping));
3913 }
3914
3915 CHKERR opThermoPlasticFactoryDomainLhs<SPACE_DIM, AT, IT, DomainEleOp>(
3916 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
3917 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T");
3918
3919 auto hencky_common_data_ptr =
3920 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
3921 mField, pip, "U", "MAT_PLASTIC", Sev::inform, scale);
3922 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
3923 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
3924
3925 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3926
3927 auto resistance = [heat_conductivity_ptr](const double, const double,
3928 const double) {
3929 return (1. / (*heat_conductivity_ptr));
3930 };
3931 auto capacity = [heat_capacity_ptr](const double, const double,
3932 const double) {
3933 return -(*heat_capacity_ptr);
3934 };
3935
3936 pip.push_back(new OpHdivHdiv("FLUX", "FLUX", resistance, mat_grad_ptr));
3937 pip.push_back(
3938 new OpHdivT("FLUX", "T", []() constexpr { return -1; }, true));
3939
3940 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3941 pip.push_back(
3942 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3943
3944 pip.push_back(
3945 new OpHdivU("FLUX", "U", mat_flux_ptr, resistance, mat_grad_ptr));
3946
3947 auto op_capacity = new OpCapacity("T", "T", capacity);
3948 op_capacity->feScalingFun = [](const FEMethod *fe_ptr) {
3949 return fe_ptr->ts_a;
3950 };
3951 pip.push_back(op_capacity);
3952
3953 pip.push_back(new OpUnSetBc("FLUX"));
3954
3955 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
3956 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
3958 pip, mField, "T", vec_temp_ptr, "SETTEMP", Sev::verbose);
3959
3960 pip.push_back(new OpUnSetBc("FLUX"));
3961
3963 };
3964
3965 auto add_domain_ops_rhs = [&](auto &pip) {
3967
3968 pip.push_back(new OpSetBc("FLUX", true, boundary_marker));
3969
3971 mField, pip, "MAT_THERMAL", thermal_block_params,
3975
3977
3978 auto hencky_common_data_ptr =
3979 HenckyOps::commonDataFactory<SPACE_DIM, IT, DomainEleOp>(
3980 mField, pip, "U", "MAT_PLASTIC", Sev::inform, scale);
3981 auto mat_D_ptr = hencky_common_data_ptr->matDPtr;
3982 auto mat_grad_ptr = hencky_common_data_ptr->matGradPtr;
3983 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
3984 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
3985
3986 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
3987 auto vec_temp_dot_ptr = boost::make_shared<VectorDouble>();
3988 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
3989 auto vec_temp_div_ptr = boost::make_shared<VectorDouble>();
3990
3991 pip.push_back(new OpCalculateScalarFieldValues("T", vec_temp_ptr));
3992 pip.push_back(new OpCalculateScalarFieldValuesDot("T", vec_temp_dot_ptr));
3994 "FLUX", vec_temp_div_ptr));
3995 pip.push_back(
3996 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", mat_flux_ptr));
3997
3998 auto resistance = [heat_conductivity_ptr](const double, const double,
3999 const double) {
4000 return (1. / (*heat_conductivity_ptr));
4001 };
4002 // negative value is consequence of symmetric system
4003 auto capacity = [heat_capacity_ptr](const double, const double,
4004 const double) {
4005 return -(*heat_capacity_ptr);
4006 };
4007 auto unity = [](const double, const double, const double) constexpr {
4008 return -1.;
4009 };
4010 pip.push_back(
4011 new OpHdivFlux("FLUX", mat_flux_ptr, resistance, mat_grad_ptr));
4012 pip.push_back(new OpHDivTemp("FLUX", vec_temp_ptr, unity));
4013 pip.push_back(new OpBaseDivFlux("T", vec_temp_div_ptr, unity));
4014 pip.push_back(new OpBaseDotT("T", vec_temp_dot_ptr, capacity));
4015
4017 pip, mField, "U",
4018 {boost::make_shared<ScaledTimeScale>("body_force_hist.txt")},
4019 Sev::inform);
4020
4021 // only in case of dynamics
4022 if (is_quasi_static == PETSC_FALSE) {
4023
4024 //! [Only used for dynamics]
4027 //! [Only used for dynamics]
4028
4029 auto mat_acceleration = boost::make_shared<MatrixDouble>();
4031 "U", mat_acceleration));
4032 pip.push_back(
4033 new OpInertiaForce("U", mat_acceleration, [](double, double, double) {
4034 return rho / scale;
4035 }));
4036 if (alpha_damping > 0) {
4037 auto mat_velocity = boost::make_shared<MatrixDouble>();
4038 pip.push_back(
4039 new OpCalculateVectorFieldValuesDot<SPACE_DIM>("U", mat_velocity));
4040 pip.push_back(
4041 new OpInertiaForce("U", mat_velocity, [](double, double, double) {
4042 return alpha_damping / scale;
4043 }));
4044 }
4045 }
4046
4047 CHKERR opThermoPlasticFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
4048 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4049 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T");
4050
4051#ifdef ADD_CONTACT
4052 CHKERR ContactOps::opFactoryDomainRhs<SPACE_DIM, AT, IT, DomainEleOp>(
4053 pip, "SIGMA", "U");
4054#endif // ADD_CONTACT
4055
4056 pip.push_back(new OpUnSetBc("FLUX"));
4057
4059 };
4060
4061 auto create_reaction_pipeline = [&](auto &pip) {
4064 CHKERR PlasticOps::opFactoryDomainReactions<SPACE_DIM, AT, IT, DomainEleOp>(
4065 mField, "MAT_PLASTIC", pip, "U", "EP", "TAU");
4067 };
4068
4069 reactionFe = boost::make_shared<DomainEle>(mField);
4070 reactionFe->getRuleHook = vol_rule;
4071 CHKERR create_reaction_pipeline(reactionFe->getOpPtrVector());
4072 reactionFe->postProcessHook =
4074
4075 // Set BCs by eliminating degrees of freedom
4076 auto get_bc_hook_rhs = [&]() {
4078 mField, pip_mng->getDomainRhsFE(),
4079 {time_scale, time_displacement_scaling});
4080 return hook;
4081 };
4082 auto get_bc_hook_lhs = [&]() {
4084 mField, pip_mng->getDomainLhsFE(),
4085 {time_scale, time_displacement_scaling});
4086 return hook;
4087 };
4088
4089 pip_mng->getDomainRhsFE()->preProcessHook = get_bc_hook_rhs();
4090 pip_mng->getDomainLhsFE()->preProcessHook = get_bc_hook_lhs();
4091
4092 CHKERR add_domain_ops_lhs(pip_mng->getOpDomainLhsPipeline());
4093 CHKERR add_domain_ops_rhs(pip_mng->getOpDomainRhsPipeline());
4094
4095 // Boundary
4096 CHKERR add_boundary_ops_lhs(pip_mng->getOpBoundaryLhsPipeline());
4097 CHKERR add_boundary_ops_rhs(pip_mng->getOpBoundaryRhsPipeline());
4098
4100}
4101//! [Push operators to pipeline]
4102
4103//! [Solve]
4104struct SetUpSchur {
4105
4106 /**
4107 * @brief Create data structure for handling Schur complement
4108 *
4109 * @param m_field
4110 * @param sub_dm Schur complement sub dm
4111 * @param field_split_it IS of Schur block
4112 * @param ao_map AO map from sub dm to main problem
4113 * @return boost::shared_ptr<SetUpSchur>
4114 */
4115 static boost::shared_ptr<SetUpSchur> createSetUpSchur(
4116
4117 MoFEM::Interface &m_field, SmartPetscObj<DM> sub_dm,
4118 SmartPetscObj<IS> field_split_it, SmartPetscObj<AO> ao_map
4119
4120 );
4121 virtual MoFEMErrorCode setUp(TS solver) = 0;
4122
4123protected:
4124 SetUpSchur() = default;
4125};
4126
4127struct MyTsCtx {
4128 boost::shared_ptr<MoFEM::TsCtx> dmts_ctx;
4129 PetscInt snes_iter_counter = 0;
4130};
4131
4132static std::unordered_map<TS, MyTsCtx *> ts_to_ctx;
4133
4134MoFEMErrorCode TSIterationPreStage(TS ts, PetscReal stagetime) {
4136 MyTsCtx *my_ctx = ts_to_ctx[ts];
4137 my_ctx->snes_iter_counter = 0;
4139}
4140
4141// Monitor function
4142MoFEMErrorCode SNESIterationMonitor(SNES snes, PetscInt its, PetscReal norm,
4143 void *ctx) {
4145 MyTsCtx *my_ctx = static_cast<MyTsCtx *>(ctx);
4146 my_ctx->snes_iter_counter++;
4148}
4149
4150PetscErrorCode MyTSResizeSetup(TS ts, PetscInt nstep, PetscReal time, Vec sol,
4151 PetscBool *resize, void *ctx) {
4152 PetscFunctionBegin;
4153 ResizeCtx *rctx = static_cast<ResizeCtx *>(ctx);
4154 *resize = rctx->mesh_changed;
4155 PetscFunctionReturn(0);
4156}
4157
4158PetscErrorCode MyTSResizeTransfer(TS ts, PetscInt nv, Vec ts_vecsin[],
4159 Vec ts_vecsout[], void *ctx) {
4160 PetscFunctionBegin;
4161 ResizeCtx *rctx = static_cast<ResizeCtx *>(ctx);
4162
4163 if (auto ptr = rctx->ptr.lock()) {
4164
4165 MoFEM::Interface &m_field = *(rctx->m_field);
4166
4167 auto bit_mng = m_field.getInterface<BitRefManager>();
4168
4169 auto set_prev_mesh_bit = [](EntityHandle ent, BitRefLevel &bit) {
4170 if (bit[COMPUTATION_BIT]) {
4171 bit.set(COMPUTATION_BIT, false);
4172 bit.set(PREVIOUS_BIT, true);
4173 }
4174 };
4175
4176 CHKERR bit_mng->lambdaBitRefLevel(set_prev_mesh_bit);
4177
4178 std::string improved_reasons = "";
4179
4180 Range edges_to_not_refine;
4181
4182 CHKERR ptr->ExRawPtr->doEdgeFlips(rctx->el_q_map, rctx->flipped_els,
4183 rctx->th_spatial_coords,
4184 rctx->new_connectivity);
4185 if (rctx->el_q_map.size() > 0) {
4186 improved_reasons += ", Edge flipping";
4187 }
4188
4189 bool refined = false;
4190 int step;
4191 CHKERR TSGetStepNumber(ts, &step);
4192 CHKERR ptr->ExRawPtr->doEdgeSplits(refined, (step) ? true : false);
4193 if (refined) {
4194 improved_reasons += ", Edge splitting";
4195 }
4196
4197 // Erase leading ", " from improved_reasons
4198 improved_reasons.erase(0, 2);
4199
4200 if (improved_reasons != "")
4201 MOFEM_LOG("REMESHING", Sev::inform)
4202 << "Improved mesh quality by: " << improved_reasons;
4203
4204#ifndef NDEBUG
4205
4206 // comp_mesh_bit = BitRefLevel().set(COMPUTATION_BIT);
4207 // flipped_bit = BitRefLevel().set(FLIPPED_BIT);
4208 // refined_bit = BitRefLevel().set(FIRST_REF_BIT);
4209 // prev_mesh_bit = BitRefLevel().set(PREVIOUS_BIT);
4210 // virgin_mesh_bit = BitRefLevel().set(VIRGIN_BIT);
4211 // storage_bit = BitRefLevel().set(STORAGE_BIT);
4212
4213 if (m_field.get_comm_rank() == 0) {
4214 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4215 comp_mesh_bit, BitRefLevel().set(), 2,
4216 "before_mapping_comp_mesh_bit.vtk", "VTK", "");
4217 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4218 flipped_bit, BitRefLevel().set(), 2, "before_mapping_flipped_bit.vtk",
4219 "VTK", "");
4220 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4221 refined_bit, BitRefLevel().set(), 2, "before_mapping_refined_bit.vtk",
4222 "VTK", "");
4223 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4224 prev_mesh_bit, BitRefLevel().set(), 2,
4225 "before_mapping_prev_mesh_bit.vtk", "VTK", "");
4226 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4227 virgin_mesh_bit, BitRefLevel().set(), 2,
4228 "before_mapping_virgin_mesh_bit.vtk", "VTK", "");
4229 }
4230#endif // NDEBUG
4231
4232 MOFEM_LOG("REMESHING", Sev::verbose) << "number of vectors to map = " << nv;
4233
4234 for (PetscInt i = 0; i < nv; ++i) {
4235 double nrm;
4236 CHKERR VecNorm(ts_vecsin[i], NORM_2, &nrm);
4237 MOFEM_LOG("REMESHING", Sev::warning)
4238 << "Before remeshing: ts_vecsin[" << i << "] norm = " << nrm;
4239 }
4240
4241 auto scatter_mng = m_field.getInterface<VecManager>();
4242 auto simple = m_field.getInterface<Simple>();
4243
4244 // CHKERR m_field.getInterface<BitRefManager>()->writeBitLevel(
4245 // BitRefLevel().set(1), BitRefLevel().set(), "before_resettingup.vtk",
4246 // "VTK", "");
4247
4248 // Rebuilding DM with old and new mesh entities
4249 auto bit = BitRefLevel().set();
4251 {"TAU", "EP", "T"}, {tau_order, ep_order, T_order}, {"U"},
4252 {order}, {"FLUX"}, {flux_order}, bit);
4253
4254 // CHKERR m_field.getInterface<BitRefManager>()->writeBitLevel(
4255 // BitRefLevel().set(1), BitRefLevel().set(), "after_resettingup.vtk",
4256 // "VTK", "");
4257
4258 auto intermediate_dm = createDM(m_field.get_comm(), "DMMOFEM");
4260 intermediate_dm, &m_field, "INTERMEDIATE_DM",
4262 BitRefLevel().set());
4263 CHKERR DMMoFEMSetDestroyProblem(intermediate_dm, PETSC_TRUE);
4264 CHKERR DMSetFromOptions(intermediate_dm);
4265 CHKERR DMMoFEMAddElement(intermediate_dm, simple->getDomainFEName());
4266 CHKERR DMMoFEMSetSquareProblem(intermediate_dm, PETSC_TRUE);
4268 CHKERR DMSetUp(intermediate_dm);
4269
4270 Vec vec_in[nv], vec_out[nv];
4271 for (PetscInt i = 0; i < nv; ++i) {
4272 CHKERR DMCreateGlobalVector(intermediate_dm, &vec_in[i]);
4273 CHKERR VecDuplicate(vec_in[i], &vec_out[i]);
4274 }
4275
4276 VecScatter scatter_to_intermediate;
4277
4278 for (PetscInt i = 0; i < nv; ++i) {
4279 CHKERR scatter_mng->vecScatterCreate(
4280 ts_vecsin[i], simple->getProblemName(), RowColData::ROW, vec_in[i],
4281 "INTERMEDIATE_DM", RowColData::ROW, &scatter_to_intermediate);
4282 CHKERR VecScatterBegin(scatter_to_intermediate, ts_vecsin[i], vec_in[i],
4283 INSERT_VALUES, SCATTER_FORWARD);
4284 CHKERR VecScatterEnd(scatter_to_intermediate, ts_vecsin[i], vec_in[i],
4285 INSERT_VALUES, SCATTER_FORWARD);
4286 }
4287
4288 CHKERR VecScatterDestroy(&scatter_to_intermediate);
4289
4291 intermediate_dm, prev_mesh_bit,
4292 BitRefLevel().set(FLIPPED_BIT + num_refinement_levels), nv, vec_in,
4293 vec_out);
4294
4295 // Build problem on new bit ref level
4296 auto ts_problem_name = simple->getProblemName();
4298 ts_problem_name,
4300 CHKERR m_field.modify_problem_mask_ref_level_set_bit(ts_problem_name,
4301 BitRefLevel().set());
4303 PetscBarrier(nullptr);
4304 CHKERR DMSetUp_MoFEM(simple->getDM());
4305
4306 // Update meshsets for correct BCs
4307 MeshsetsManager *meshsets_manager_ptr;
4308 CHKERR m_field.getInterface(meshsets_manager_ptr);
4309 CHKERR meshsets_manager_ptr->updateAllMeshsetsByEntitiesChildren(
4310 BitRefLevel().set());
4311
4312 CHKERR ptr->ExRawPtr->mechanicalBC(
4314 BitRefLevel().set());
4315 CHKERR ptr->ExRawPtr->thermalBC(
4317 BitRefLevel().set());
4318
4319 VecScatter scatter_to_final;
4320
4321 for (PetscInt i = 0; i < nv; ++i) {
4322 CHKERR DMCreateGlobalVector(simple->getDM(), &ts_vecsout[i]);
4323 CHKERR scatter_mng->vecScatterCreate(
4324 ts_vecsout[i], simple->getProblemName(), RowColData::ROW, vec_out[i],
4325 "INTERMEDIATE_DM", RowColData::ROW, &scatter_to_final);
4326 CHKERR VecScatterBegin(scatter_to_final, vec_out[i], ts_vecsout[i],
4327 INSERT_VALUES, SCATTER_REVERSE);
4328 CHKERR VecScatterEnd(scatter_to_final, vec_out[i], ts_vecsout[i],
4329 INSERT_VALUES, SCATTER_REVERSE);
4330 CHKERR VecScatterDestroy(&scatter_to_final);
4331 }
4332
4333 for (PetscInt i = 0; i < nv; ++i) {
4334 CHKERR VecDestroy(&vec_in[i]);
4335 CHKERR VecDestroy(&vec_out[i]);
4336 }
4337
4338 auto set_all_bit = [&](EntityHandle ent, BitRefLevel &bit) {
4339 for (auto l = 0; l <= FLIPPED_BIT + num_refinement_levels; ++l) {
4340 bit.set(STORAGE_BIT, true);
4341 }
4342 if (bit[VIRGIN_BIT]) {
4343 bit.set(VIRGIN_BIT, false);
4344 }
4345 if (bit[FLIPPED_BIT]) {
4346 bit.set(VIRGIN_BIT, true);
4347 }
4348 if (bit[PREVIOUS_BIT]) {
4349 bit.set(PREVIOUS_BIT, false);
4350 }
4352 bit.set(COMPUTATION_BIT, true);
4353 }
4354 };
4355 CHKERR bit_mng->lambdaBitRefLevel(set_all_bit);
4356
4357#ifndef NDEBUG
4358
4359 // comp_mesh_bit = BitRefLevel().set(COMPUTATION_BIT);
4360 // flipped_bit = BitRefLevel().set(FLIPPED_BIT);
4361 // refined_bit = BitRefLevel().set(FIRST_REF_BIT);
4362 // prev_mesh_bit = BitRefLevel().set(PREVIOUS_BIT);
4363 // virgin_mesh_bit = BitRefLevel().set(VIRGIN_BIT);
4364 // storage_bit = BitRefLevel().set(STORAGE_BIT);
4365
4366 if (m_field.get_comm_rank() == 0) {
4367 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4368 comp_mesh_bit, BitRefLevel().set(), 2,
4369 "after_mapping_comp_mesh_bit.vtk", "VTK", "");
4370 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4371 flipped_bit, BitRefLevel().set(), 2, "after_mapping_flipped_bit.vtk",
4372 "VTK", "");
4373 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4374 refined_bit, BitRefLevel().set(), 2, "after_mapping_refined_bit.vtk",
4375 "VTK", "");
4376 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4377 prev_mesh_bit, BitRefLevel().set(), 2,
4378 "after_mapping_prev_mesh_bit.vtk", "VTK", "");
4379 CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByDim(
4380 virgin_mesh_bit, BitRefLevel().set(), 2,
4381 "after_mapping_virgin_mesh_bit.vtk", "VTK", "");
4382 }
4383#endif // NDEBUG
4384
4385 CHKERR m_field.modify_problem_ref_level_set_bit(ts_problem_name,
4387 CHKERR m_field.modify_problem_mask_ref_level_set_bit(ts_problem_name,
4388 BitRefLevel().set());
4389
4390 CHKERR TSSetDM(ts, simple->getDM());
4391
4392 auto B = createDMMatrix(simple->getDM());
4393 CHKERR TSSetIJacobian(ts, B, B, nullptr, nullptr);
4394 }
4395
4396 for (PetscInt i = 0; i < nv; ++i) {
4397 double nrm;
4398 CHKERR VecNorm(ts_vecsout[i], NORM_2, &nrm);
4399 MOFEM_LOG("REMESHING", Sev::warning)
4400 << "After remeshing: ts_vecsout[" << i << "] norm = " << nrm;
4401 }
4402
4403 PetscFunctionReturn(0);
4404}
4405
4407
4410
4413 ISManager *is_manager = mField.getInterface<ISManager>();
4414
4415 auto snes_ctx_ptr = getDMSnesCtx(simple->getDM());
4416
4417 auto set_section_monitor = [&](auto solver) {
4419 SNES snes;
4420 CHKERR TSGetSNES(solver, &snes);
4421 CHKERR SNESMonitorSet(snes,
4422 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
4423 void *))MoFEMSNESMonitorFields,
4424 (void *)(snes_ctx_ptr.get()), nullptr);
4426 };
4427
4428 auto create_post_process_elements = [&]() {
4429 auto pp_fe = boost::make_shared<PostProcEle>(mField);
4430
4431 auto push_vol_ops = [this](auto &pip) {
4433
4434 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4435 return 1.;
4436 };
4437 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4438 const double) { return 1.; };
4439
4440 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4441 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4442 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4443 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4444 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T", 1., unity_2_args,
4445 unity_2_args, unity_3_args, Sev::inform);
4446
4447 if (common_hencky_ptr) {
4448 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
4449 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Wrong pointer for grad");
4450 }
4451
4452 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
4453 common_thermoplastic_ptr);
4454 };
4455
4456 auto push_vol_post_proc_ops = [this](auto &pp_fe, auto &&p) {
4458
4459 auto &pip = pp_fe->getOpPtrVector();
4460
4461 auto [common_plastic_ptr, common_hencky_ptr, common_thermoplastic_ptr] =
4462 p;
4463
4464 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
4465 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
4466
4467 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
4468 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
4469
4470 auto u_ptr = boost::make_shared<MatrixDouble>();
4471 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
4472
4474
4475 if (is_large_strains) {
4476
4477 pip.push_back(
4478
4479 new OpPPMap(
4480
4481 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
4482
4483 {{"ISOTROPIC_HARDENING",
4484 common_plastic_ptr->getPlasticIsoHardeningPtr()},
4485 {"PLASTIC_SURFACE",
4486 common_plastic_ptr->getPlasticSurfacePtr()},
4487 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()},
4488 {"T", common_thermoplastic_ptr->getTempPtr()}},
4489
4490 {{"U", u_ptr},
4491 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
4492
4493 {{"GRAD", common_hencky_ptr->matGradPtr},
4494 {"FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()}},
4495
4496 {{"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
4497 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()},
4498 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
4499 {"HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()}}
4500
4501 )
4502
4503 );
4504
4505 } else {
4506
4507 pip.push_back(
4508
4509 new OpPPMap(
4510
4511 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
4512
4513 {{"PLASTIC_SURFACE",
4514 common_plastic_ptr->getPlasticSurfacePtr()},
4515 {"PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()},
4516 {"T", common_thermoplastic_ptr->getTempPtr()}},
4517
4518 {{"U", u_ptr},
4519 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
4520
4521 {},
4522
4523 {{"STRAIN", common_plastic_ptr->mStrainPtr},
4524 {"STRESS", common_plastic_ptr->mStressPtr},
4525 {"PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()},
4526 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
4527
4528 )
4529
4530 );
4531 }
4532
4534 };
4535
4536 // Defaults to outputting volume for 2D and skin for 3D
4537 PetscBool post_proc_vol = PETSC_FALSE;
4538 PetscBool post_proc_skin = PETSC_TRUE;
4539 switch (SPACE_DIM) {
4540 case 2:
4541 post_proc_vol = PETSC_TRUE;
4542 post_proc_skin = PETSC_FALSE;
4543 break;
4544 case 3:
4545 post_proc_vol = PETSC_FALSE;
4546 post_proc_skin = PETSC_TRUE;
4547 break;
4548 default:
4549 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "SPACE_DIM neither 2 nor 3");
4550 break;
4551 }
4552 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_vol",
4553 &post_proc_vol, PETSC_NULLPTR);
4554 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin",
4555 &post_proc_skin, PETSC_NULLPTR);
4556
4557 auto vol_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
4558 &post_proc_vol]() {
4559 if (post_proc_vol == PETSC_FALSE)
4560 return boost::shared_ptr<PostProcEle>();
4561 auto pp_fe = boost::make_shared<PostProcEle>(mField);
4563 push_vol_post_proc_ops(pp_fe, push_vol_ops(pp_fe->getOpPtrVector())),
4564 "push_vol_post_proc_ops");
4565 return pp_fe;
4566 };
4567
4568 auto skin_post_proc = [this, push_vol_post_proc_ops, push_vol_ops,
4569 &post_proc_skin]() {
4570 if (post_proc_skin == PETSC_FALSE)
4571 return boost::shared_ptr<SkinPostProcEle>();
4572
4573 auto simple = mField.getInterface<Simple>();
4574 auto pp_fe = boost::make_shared<SkinPostProcEle>(mField);
4575 auto op_side = new OpLoopSide<SideEle>(mField, simple->getDomainFEName(),
4576 SPACE_DIM, Sev::verbose);
4577 pp_fe->getOpPtrVector().push_back(op_side);
4578 CHK_MOAB_THROW(push_vol_post_proc_ops(
4579 pp_fe, push_vol_ops(op_side->getOpPtrVector())),
4580 "push_vol_post_proc_ops");
4581 return pp_fe;
4582 };
4583
4584 return std::make_pair(vol_post_proc(), skin_post_proc());
4585 };
4586
4587 auto scatter_create = [&](auto D, auto coeff) {
4589 CHKERR is_manager->isCreateProblemFieldAndRank(simple->getProblemName(),
4590 ROW, "U", coeff, coeff, is);
4591 int loc_size;
4592 CHKERR ISGetLocalSize(is, &loc_size);
4593 Vec v;
4594 CHKERR VecCreateMPI(mField.get_comm(), loc_size, PETSC_DETERMINE, &v);
4595 VecScatter scatter;
4596 CHKERR VecScatterCreate(D, is, v, PETSC_NULLPTR, &scatter);
4597 return std::make_tuple(SmartPetscObj<Vec>(v),
4598 SmartPetscObj<VecScatter>(scatter));
4599 };
4600
4601 boost::shared_ptr<SetPtsData> field_eval_data;
4602 boost::shared_ptr<MatrixDouble> u_field_ptr;
4603
4604 std::array<double, 3> field_eval_coords = {0., 0., 0.};
4605 int coords_dim = 3;
4606 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
4607 field_eval_coords.data(), &coords_dim,
4608 &do_eval_field);
4609
4610 boost::shared_ptr<std::map<std::string, boost::shared_ptr<VectorDouble>>>
4611 scalar_field_ptrs = boost::make_shared<
4612 std::map<std::string, boost::shared_ptr<VectorDouble>>>();
4613 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4614 vector_field_ptrs = boost::make_shared<
4615 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4616 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4617 sym_tensor_field_ptrs = boost::make_shared<
4618 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4619 boost::shared_ptr<std::map<std::string, boost::shared_ptr<MatrixDouble>>>
4620 tensor_field_ptrs = boost::make_shared<
4621 std::map<std::string, boost::shared_ptr<MatrixDouble>>>();
4622
4623 auto test_monitor_ptr = boost::make_shared<FEMethod>();
4624
4625 if (do_eval_field && atom_test == 0) {
4626 field_eval_data =
4627 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
4628 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
4629 field_eval_data, simple->getDomainFEName());
4630
4631 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
4632 auto no_rule = [](int, int, int) { return -1; };
4633 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
4634 field_eval_fe_ptr->getRuleHook = no_rule;
4635
4637 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV});
4638
4639 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4640 return 1.;
4641 };
4642 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4643 const double) { return 1.; };
4644
4645 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4646 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4647 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4648 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4649 "MAT_THERMOPLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U", "EP",
4650 "TAU", "T", 1., unity_2_args, unity_2_args, unity_3_args,
4651 Sev::inform);
4652
4653 auto u_field_ptr = boost::make_shared<MatrixDouble>();
4654 field_eval_fe_ptr->getOpPtrVector().push_back(
4655 new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_field_ptr));
4656 auto T_field_ptr = boost::make_shared<VectorDouble>();
4657 field_eval_fe_ptr->getOpPtrVector().push_back(
4658 new OpCalculateScalarFieldValues("T", T_field_ptr));
4659 auto FLUX_field_ptr = boost::make_shared<MatrixDouble>();
4660 field_eval_fe_ptr->getOpPtrVector().push_back(
4661 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", FLUX_field_ptr));
4662
4663 if ((common_plastic_ptr) && (common_hencky_ptr) && (scalar_field_ptrs)) {
4664 if (is_large_strains) {
4665 scalar_field_ptrs->insert(std::make_pair("TEMPERATURE", T_field_ptr));
4666 scalar_field_ptrs->insert(std::make_pair(
4667 "PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()));
4668 scalar_field_ptrs->insert(std::make_pair(
4669 "PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()));
4670 vector_field_ptrs->insert(std::make_pair("U", u_field_ptr));
4671 vector_field_ptrs->insert(std::make_pair("FLUX", FLUX_field_ptr));
4672 sym_tensor_field_ptrs->insert(std::make_pair(
4673 "PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()));
4674 sym_tensor_field_ptrs->insert(std::make_pair(
4675 "PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()));
4676 sym_tensor_field_ptrs->insert(std::make_pair(
4677 "HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()));
4678 sym_tensor_field_ptrs->insert(
4679 std::make_pair("HENCKY_STRAIN", common_hencky_ptr->getMatLogC()));
4680 tensor_field_ptrs->insert(
4681 std::make_pair("GRAD", common_hencky_ptr->matGradPtr));
4682 tensor_field_ptrs->insert(std::make_pair(
4683 "FIRST_PIOLA", common_hencky_ptr->getMatFirstPiolaStress()));
4684 } else {
4685 scalar_field_ptrs->insert(std::make_pair("TEMPERATURE", T_field_ptr));
4686 scalar_field_ptrs->insert(std::make_pair(
4687 "PLASTIC_SURFACE", common_plastic_ptr->getPlasticSurfacePtr()));
4688 scalar_field_ptrs->insert(std::make_pair(
4689 "PLASTIC_MULTIPLIER", common_plastic_ptr->getPlasticTauPtr()));
4690 vector_field_ptrs->insert(std::make_pair("U", u_field_ptr));
4691 vector_field_ptrs->insert(std::make_pair("FLUX", FLUX_field_ptr));
4692 sym_tensor_field_ptrs->insert(
4693 std::make_pair("STRAIN", common_plastic_ptr->mStrainPtr));
4694 sym_tensor_field_ptrs->insert(
4695 std::make_pair("STRESS", common_plastic_ptr->mStressPtr));
4696 sym_tensor_field_ptrs->insert(std::make_pair(
4697 "PLASTIC_STRAIN", common_plastic_ptr->getPlasticStrainPtr()));
4698 sym_tensor_field_ptrs->insert(std::make_pair(
4699 "PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()));
4700 }
4701 }
4702 } else if (atom_test > 0) {
4703 field_eval_data =
4704 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
4705
4706 CHKERR mField.getInterface<FieldEvaluatorInterface>()->buildTree<SPACE_DIM>(
4707 field_eval_data, simple->getDomainFEName());
4708
4709 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
4710 auto no_rule = [](int, int, int) { return -1; };
4711
4712 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
4713 field_eval_fe_ptr->getRuleHook = no_rule;
4714
4716 field_eval_fe_ptr->getOpPtrVector(), {H1, HDIV});
4717
4718 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
4719 return 1.;
4720 };
4721 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
4722 const double) { return 1.; };
4723
4724 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
4725 common_thermoelastic_ptr, common_thermoplastic_ptr] =
4726 createCommonThermoPlasticOps<SPACE_DIM, IT, DomainEleOp>(
4727 mField, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
4728 "MAT_THERMOPLASTIC", field_eval_fe_ptr->getOpPtrVector(), "U", "EP",
4729 "TAU", "T", 1, unity_2_args, unity_2_args, unity_3_args,
4730 Sev::inform);
4731
4732 auto dispGradPtr = common_hencky_ptr->matGradPtr;
4733 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
4734
4735 auto coeff_expansion_ptr = common_thermoelastic_ptr->getCoeffExpansionPtr();
4736 auto ref_temp_ptr = common_thermoelastic_ptr->getRefTempPtr();
4737
4738 field_eval_fe_ptr->getOpPtrVector().push_back(
4739 new OpCalculateScalarFieldValues("T", tempFieldPtr));
4740 field_eval_fe_ptr->getOpPtrVector().push_back(
4741 new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", fluxFieldPtr));
4742 field_eval_fe_ptr->getOpPtrVector().push_back(
4743 new OpCalculateVectorFieldValues<SPACE_DIM>("U", dispFieldPtr));
4744 field_eval_fe_ptr->getOpPtrVector().push_back(
4746 dispGradPtr));
4747 plasticMultiplierFieldPtr = common_plastic_ptr->getPlasticTauPtr();
4748 plasticStrainFieldPtr = common_plastic_ptr->getPlasticStrainPtr();
4749
4751
4752 field_eval_fe_ptr->getOpPtrVector().push_back(
4753 new typename H::template OpCalculateHenckyThermoPlasticStress<SPACE_DIM,
4754 IT, 0>(
4755 "U", tempFieldPtr, common_hencky_ptr, coeff_expansion_ptr,
4756 ref_temp_ptr));
4757 if (!IS_LARGE_STRAINS) {
4758 field_eval_fe_ptr->getOpPtrVector().push_back(
4760 common_hencky_ptr->getMatFirstPiolaStress(), stressFieldPtr));
4761 field_eval_fe_ptr->getOpPtrVector().push_back(
4762 new OpSymmetrizeTensor<SPACE_DIM>(dispGradPtr, strainFieldPtr));
4763 } else {
4764 field_eval_fe_ptr->getOpPtrVector().push_back(
4765 new typename H::template OpCalculateLogC<SPACE_DIM, IT>(
4766 "U", common_hencky_ptr));
4767 stressFieldPtr = common_hencky_ptr->getMatFirstPiolaStress();
4768 strainFieldPtr = common_hencky_ptr->getMatLogC();
4769 };
4770 }
4771
4772 auto set_time_monitor = [&](auto dm, auto solver) {
4774 if (atom_test == 0) {
4775 boost::shared_ptr<Monitor<SPACE_DIM>> monitor_ptr(new Monitor<SPACE_DIM>(
4776 dm, create_post_process_elements(), reactionFe, uXScatter, uYScatter,
4777 uZScatter, field_eval_coords, field_eval_data, scalar_field_ptrs,
4778 vector_field_ptrs, sym_tensor_field_ptrs, tensor_field_ptrs));
4779 boost::shared_ptr<ForcesAndSourcesCore> null;
4780 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(),
4781 monitor_ptr, null, null);
4782 } else {
4783
4784 test_monitor_ptr->preProcessHook = [&]() {
4786
4787 CHKERR mField.getInterface<FieldEvaluatorInterface>()
4788 ->evalFEAtThePoint<SPACE_DIM>(
4789 field_eval_coords.data(), 1e-12, simple->getProblemName(),
4790 simple->getDomainFEName(), field_eval_data,
4791 mField.get_comm_rank(), mField.get_comm_rank(), nullptr,
4792 MF_EXIST, QUIET);
4793
4794 auto eval_num_vec = createVectorMPI(mField.get_comm(), PETSC_DECIDE, 1);
4795 CHKERR VecZeroEntries(eval_num_vec);
4796 if (tempFieldPtr->size()) {
4797 CHKERR VecSetValue(eval_num_vec, 0, 1, ADD_VALUES);
4798 }
4799 CHKERR VecAssemblyBegin(eval_num_vec);
4800 CHKERR VecAssemblyEnd(eval_num_vec);
4801
4802 double eval_num;
4803 CHKERR VecSum(eval_num_vec, &eval_num);
4804 if (!(int)eval_num) {
4805 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4806 "atom test %d failed: did not find elements to evaluate "
4807 "the field, check the coordinates",
4808 atom_test);
4809 }
4810
4811 if (tempFieldPtr->size()) {
4812 auto t_temp = getFTensor0FromVec(*tempFieldPtr);
4813 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4814 << "Eval point T magnitude: " << t_temp;
4815 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4816 if (atom_test <= 3 && fabs(t_temp - 554.48) > 1e-2) {
4817 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4818 "atom test %d failed: wrong temperature value",
4819 atom_test);
4820 }
4821 if (atom_test == 4 && fabs(t_temp - 250) > 1e-2) {
4822 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4823 "atom test %d failed: wrong temperature value",
4824 atom_test);
4825 }
4826 if (atom_test == 5 && fabs(t_temp - 1) > 1e-2) {
4827 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4828 "atom test %d failed: wrong temperature value",
4829 atom_test);
4830 }
4831 }
4832 if (atom_test == 8 && fabs(t_temp - 0.5) > 1e-12) {
4833 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4834 "atom test %d failed: wrong temperature value", atom_test);
4835 }
4836 }
4837 if (fluxFieldPtr->size1()) {
4839 auto t_flux = getFTensor1FromMat<SPACE_DIM>(*fluxFieldPtr);
4840 auto flux_mag = sqrt(t_flux(i) * t_flux(i));
4841 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4842 << "Eval point FLUX magnitude: " << flux_mag;
4843 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4844 if (atom_test <= 3 && fabs(flux_mag - 27008.0) > 2e1) {
4845 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4846 "atom test %d failed: wrong flux value", atom_test);
4847 }
4848 if (atom_test == 4 && fabs(flux_mag - 150e3) > 1e-1) {
4849 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4850 "atom test %d failed: wrong flux value", atom_test);
4851 }
4852 if (atom_test == 5 && fabs(flux_mag) > 1e-6) {
4853 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4854 "atom test %d failed: wrong flux value", atom_test);
4855 }
4856 }
4857 }
4858 if (dispFieldPtr->size1()) {
4860 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*dispFieldPtr);
4861 auto disp_mag = sqrt(t_disp(i) * t_disp(i));
4862 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4863 << "Eval point U magnitude: " << disp_mag;
4864 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4865 if (atom_test == 1 && fabs(disp_mag - 0.00345) > 1e-5) {
4866 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4867 "atom test %d failed: wrong displacement value",
4868 atom_test);
4869 }
4870 if ((atom_test == 2 || atom_test == 3) &&
4871 fabs(disp_mag - 0.00265) > 1e-5) {
4872 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4873 "atom test %d failed: wrong displacement value",
4874 atom_test);
4875 }
4876 if ((atom_test == 5) &&
4877 fabs(t_disp(0) - (std::sqrt(std::exp(0.2)) - 1)) > 1e-5 &&
4878 fabs(t_disp(1) - (std::sqrt(std::exp(0.2)) - 1)) > 1e-5) {
4879 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4880 "atom test %d failed: wrong displacement value",
4881 atom_test);
4882 }
4883 }
4884 }
4885 if (strainFieldPtr->size1()) {
4887 auto t_strain =
4888 getFTensor2SymmetricFromMat<SPACE_DIM>(*strainFieldPtr);
4889 auto t_strain_trace = t_strain(i, i);
4890 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4891 if (atom_test == 1 && fabs(t_strain_trace - 0.00679) > 1e-5) {
4892 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4893 "atom test %d failed: wrong strain value", atom_test);
4894 }
4895 if ((atom_test == 2 || atom_test == 3) &&
4896 fabs(t_strain_trace - 0.00522) > 1e-5) {
4897 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4898 "atom test %d failed: wrong strain value", atom_test);
4899 }
4900 if ((atom_test == 5) && fabs(t_strain_trace - 0.2) > 1e-5) {
4901 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4902 "atom test %d failed: wrong strain value", atom_test);
4903 }
4904 }
4905 }
4906 if (stressFieldPtr->size1()) {
4907 double von_mises_stress;
4908 auto getVonMisesStress = [&](auto t_stress) {
4910 von_mises_stress = std::sqrt(
4911 0.5 *
4912 ((t_stress(0, 0) - t_stress(1, 1)) *
4913 (t_stress(0, 0) - t_stress(1, 1)) +
4914 (SPACE_DIM == 3 ? (t_stress(1, 1) - t_stress(2, 2)) *
4915 (t_stress(1, 1) - t_stress(2, 2))
4916 : 0) +
4917 (SPACE_DIM == 3 ? (t_stress(2, 2) - t_stress(0, 0)) *
4918 (t_stress(2, 2) - t_stress(0, 0))
4919 : 0) +
4920 6 * (t_stress(0, 1) * t_stress(0, 1) +
4921 (SPACE_DIM == 3 ? t_stress(1, 2) * t_stress(1, 2) : 0) +
4922 (SPACE_DIM == 3 ? t_stress(2, 0) * t_stress(2, 0) : 0))));
4924 };
4925 if (!IS_LARGE_STRAINS) {
4926 auto t_stress =
4927 getFTensor2SymmetricFromMat<SPACE_DIM>(*stressFieldPtr);
4928 CHKERR getVonMisesStress(t_stress);
4929 } else {
4930 auto t_stress =
4931 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*stressFieldPtr);
4932 CHKERR getVonMisesStress(t_stress);
4933 }
4934 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4935 << "Eval point von Mises Stress: " << von_mises_stress;
4936 if (atom_test && fabs(test_monitor_ptr->ts_t - 10) < 1e-12) {
4937 if (atom_test == 1 && fabs(von_mises_stress - 523.0) > 5e-1) {
4938 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4939 "atom test %d failed: wrong von Mises stress value",
4940 atom_test);
4941 }
4942 if (atom_test == 2 && fabs(von_mises_stress - 16.3) > 5e-2) {
4943 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4944 "atom test %d failed: wrong von Mises stress value",
4945 atom_test);
4946 }
4947 if (atom_test == 3 && fabs(von_mises_stress - 14.9) > 5e-2) {
4948 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4949 "atom test %d failed: wrong von Mises stress value",
4950 atom_test);
4951 }
4952 if (atom_test == 5 && fabs(von_mises_stress) > 5e-2) {
4953 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4954 "atom test %d failed: wrong von Mises stress value",
4955 atom_test);
4956 }
4957 }
4958 }
4959 if (plasticMultiplierFieldPtr->size()) {
4960 auto t_plastic_multiplier =
4961 getFTensor0FromVec(*plasticMultiplierFieldPtr);
4962 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4963 << "Eval point TAU magnitude: " << t_plastic_multiplier;
4964 if (atom_test == 8 && fabs(t_plastic_multiplier - 1.5) > 1e-12) {
4965 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4966 "atom test %d failed: wrong plastic multiplier value",
4967 atom_test);
4968 }
4969 }
4970 if (plasticStrainFieldPtr->size1()) {
4973 auto t_plastic_strain =
4974 getFTensor2SymmetricFromMat<SPACE_DIM>(*plasticStrainFieldPtr);
4975 MOFEM_LOG("THERMOPLASTICITY", Sev::inform)
4976 << "Eval point EP(0,0) = " << t_plastic_strain(0, 0)
4977 << ", EP(0,1) = " << t_plastic_strain(0, 1)
4978 << ", EP(1,1) = " << t_plastic_strain(1, 1);
4979 if (atom_test == 8) {
4980 if (fabs(t_plastic_strain(0, 0) - 0.005) > 1e-12) {
4981 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4982 "atom test %d failed: wrong EP(0,0) value", atom_test);
4983 }
4984 if (fabs(t_plastic_strain(0, 1) - 0.025) > 1e-12) {
4985 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4986 "atom test %d failed: wrong EP(0,1) value", atom_test);
4987 }
4988 if (fabs(t_plastic_strain(1, 1) - 0.015) > 1e-12) {
4989 SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
4990 "atom test %d failed: wrong EP(1,1) value", atom_test);
4991 }
4992 }
4993 }
4994
4995 MOFEM_LOG_SYNCHRONISE(mField.get_comm());
4997 };
4998 auto null = boost::shared_ptr<FEMethod>();
4999 CHKERR DMMoFEMTSSetMonitor(dm, solver, simple->getDomainFEName(), null,
5000 test_monitor_ptr, null);
5001 };
5002
5004 };
5005
5006 auto set_schur_pc = [&](auto solver,
5007 boost::shared_ptr<SetUpSchur> &schur_ptr) {
5009
5010 auto name_prb = simple->getProblemName();
5011
5012 // create sub dm for Schur complement
5013 auto create_schur_dm = [&](SmartPetscObj<DM> base_dm,
5014 SmartPetscObj<DM> &dm_sub) {
5016 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
5017 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "SCHUR");
5018 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
5019 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
5020 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
5021 for (auto f : {"U", "FLUX"}) {
5024 }
5025 CHKERR DMSetUp(dm_sub);
5026
5028 };
5029
5030 auto create_block_dm = [&](SmartPetscObj<DM> base_dm,
5031 SmartPetscObj<DM> &dm_sub) {
5033 dm_sub = createDM(mField.get_comm(), "DMMOFEM");
5034 CHKERR DMMoFEMCreateSubDM(dm_sub, base_dm, "BLOCK");
5035 CHKERR DMMoFEMSetSquareProblem(dm_sub, PETSC_TRUE);
5036 CHKERR DMMoFEMAddElement(dm_sub, simple->getDomainFEName());
5037 CHKERR DMMoFEMAddElement(dm_sub, simple->getBoundaryFEName());
5038#ifdef ADD_CONTACT
5039 for (auto f : {"SIGMA", "EP", "TAU", "T"}) {
5042 }
5043#else
5044 for (auto f : {"EP", "TAU", "T"}) {
5047 }
5048#endif
5049 CHKERR DMSetUp(dm_sub);
5051 };
5052
5053 // Create nested (sub BC) Schur DM
5054 if constexpr (AT == AssemblyType::BLOCK_SCHUR) {
5055
5056 SmartPetscObj<DM> dm_schur;
5057 CHKERR create_schur_dm(simple->getDM(), dm_schur);
5058 SmartPetscObj<DM> dm_block;
5059 CHKERR create_block_dm(simple->getDM(), dm_block);
5060
5061#ifdef ADD_CONTACT
5062
5063 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
5064 auto block_mat_data = createBlockMatStructure(
5065 simple->getDM(),
5066
5067 {
5068
5069 {simple->getDomainFEName(),
5070
5071 {{"U", "U"},
5072 {"SIGMA", "SIGMA"},
5073 {"U", "SIGMA"},
5074 {"SIGMA", "U"},
5075 {"EP", "EP"},
5076 {"TAU", "TAU"},
5077 {"U", "EP"},
5078 {"EP", "U"},
5079 {"EP", "TAU"},
5080 {"TAU", "EP"},
5081 {"TAU", "U"},
5082 {"T", "T"},
5083 {"U", "T"},
5084 {"T", "U"},
5085 {"EP", "T"},
5086 {"T", "EP"},
5087 {"TAU", "T"},
5088 {"T", "TAU"}
5089
5090 }},
5091
5092 {simple->getBoundaryFEName(),
5093
5094 {{"SIGMA", "SIGMA"}, {"U", "SIGMA"}, {"SIGMA", "U"}
5095
5096 }}
5097
5098 }
5099
5100 );
5101
5103
5104 {dm_schur, dm_block}, block_mat_data,
5105
5106 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
5107 true
5108
5109 );
5110 };
5111
5112#else
5113
5114 auto get_nested_mat_data = [&](auto schur_dm, auto block_dm) {
5115 auto block_mat_data =
5117
5118 {{simple->getDomainFEName(),
5119
5120 {{"U", "U"},
5121 {"EP", "EP"},
5122 {"TAU", "TAU"},
5123 {"U", "EP"},
5124 {"EP", "U"},
5125 {"EP", "TAU"},
5126 {"TAU", "U"},
5127 {"TAU", "EP"},
5128 {"T", "T"},
5129 {"T", "U"},
5130 {"T", "FLUX"},
5131 {"T", "EP"},
5132 {"FLUX", "T"},
5133 {"FLUX", "U"},
5134 {"U", "T"},
5135 {"EP", "T"},
5136 {"TAU", "T"}
5137
5138 }}}
5139
5140 );
5141
5143
5144 {dm_schur, dm_block}, block_mat_data,
5145
5146 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, false
5147
5148 );
5149 };
5150
5151#endif
5152
5153 auto nested_mat_data = get_nested_mat_data(dm_schur, dm_block);
5154 CHKERR DMMoFEMSetNestSchurData(simple->getDM(), nested_mat_data);
5155
5156 auto block_is = getDMSubData(dm_block)->getSmartRowIs();
5157 auto ao_schur = getDMSubData(dm_schur)->getSmartRowMap();
5158
5159 // Indices has to be map fro very to level, while assembling Schur
5160 // complement.
5161 schur_ptr =
5162 SetUpSchur::createSetUpSchur(mField, dm_schur, block_is, ao_schur);
5163 CHKERR schur_ptr->setUp(solver);
5164 }
5165
5167 };
5168
5169 auto dm = simple->getDM();
5170 auto D = createDMVector(dm);
5171 auto DD = vectorDuplicate(D);
5172 uXScatter = scatter_create(D, 0);
5173 uYScatter = scatter_create(D, 1);
5174 if constexpr (SPACE_DIM == 3)
5175 uZScatter = scatter_create(D, 2);
5176
5177 auto create_solver = [pip_mng]() {
5178 if (is_quasi_static == PETSC_TRUE)
5179 return pip_mng->createTSIM();
5180 else
5181 return pip_mng->createTSIM2();
5182 };
5183
5184 SmartPetscObj<Vec> solution_vector;
5185 CHKERR DMCreateGlobalVector_MoFEM(dm, solution_vector);
5186
5187 if (restart_flg) {
5188 PetscViewer viewer;
5189 CHKERR PetscViewerBinaryOpen(PETSC_COMM_WORLD, restart_file, FILE_MODE_READ,
5190 &viewer);
5191 CHKERR VecLoad(solution_vector, viewer);
5192 CHKERR PetscViewerDestroy(&viewer);
5193 CHKERR DMoFEMMeshToLocalVector(dm, solution_vector, INSERT_VALUES,
5194 SCATTER_REVERSE);
5195 }
5196
5197 auto solver = create_solver();
5198
5199 auto active_pre_lhs = []() {
5201 std::fill(PlasticOps::CommonData::activityData.begin(),
5204 };
5205
5206 auto active_post_lhs = [&]() {
5208 auto get_iter = [&]() {
5209 SNES snes;
5210 CHK_THROW_MESSAGE(TSGetSNES(solver, &snes), "Can not get SNES");
5211 int iter;
5212 CHK_THROW_MESSAGE(SNESGetIterationNumber(snes, &iter),
5213 "Can not get iter");
5214 return iter;
5215 };
5216
5217 auto iter = get_iter();
5218 if (iter >= 0) {
5219
5220 std::array<int, 5> activity_data;
5221 std::fill(activity_data.begin(), activity_data.end(), 0);
5222 MPI_Allreduce(PlasticOps::CommonData::activityData.data(),
5223 activity_data.data(), activity_data.size(), MPI_INT,
5224 MPI_SUM, mField.get_comm());
5225
5226 int &active_points = activity_data[0];
5227 int &avtive_full_elems = activity_data[1];
5228 int &avtive_elems = activity_data[2];
5229 int &nb_points = activity_data[3];
5230 int &nb_elements = activity_data[4];
5231
5232 if (nb_points) {
5233
5234 double proc_nb_points =
5235 100 * static_cast<double>(active_points) / nb_points;
5236 double proc_nb_active =
5237 100 * static_cast<double>(avtive_elems) / nb_elements;
5238 double proc_nb_full_active = 100;
5239 if (avtive_elems)
5240 proc_nb_full_active =
5241 100 * static_cast<double>(avtive_full_elems) / avtive_elems;
5242
5243 MOFEM_LOG_C("PLASTICITY", Sev::inform,
5244 "Iter %d nb pts %d nb active pts %d (%3.3f\%) nb active "
5245 "elements %d "
5246 "(%3.3f\%) nb full active elems %d (%3.3f\%)",
5247 iter, nb_points, active_points, proc_nb_points,
5248 avtive_elems, proc_nb_active, avtive_full_elems,
5249 proc_nb_full_active, iter);
5250 }
5251 }
5252
5254 };
5255
5256 auto add_active_dofs_elem = [&](auto dm) {
5258 auto fe_pre_proc = boost::make_shared<FEMethod>();
5259 fe_pre_proc->preProcessHook = active_pre_lhs;
5260 auto fe_post_proc = boost::make_shared<FEMethod>();
5261 fe_post_proc->postProcessHook = active_post_lhs;
5262 auto ts_ctx_ptr = getDMTsCtx(dm);
5263 ts_ctx_ptr->getPreProcessIJacobian().push_front(fe_pre_proc);
5264 ts_ctx_ptr->getPostProcessIJacobian().push_back(fe_post_proc);
5266 };
5267
5268 auto set_essential_bc = [&](auto dm, auto solver) {
5270 // This is low level pushing finite elements (pipelines) to solver
5271
5272 auto pre_proc_ptr = boost::make_shared<FEMethod>();
5273 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
5274 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
5275
5276 // Add boundary condition scaling
5277 auto disp_time_scale = boost::make_shared<TimeScale>();
5278
5279 auto get_bc_hook_rhs = [this, pre_proc_ptr, disp_time_scale]() {
5280 EssentialPreProc<DisplacementCubitBcData> hook(mField, pre_proc_ptr,
5281 {disp_time_scale}, false);
5282 return hook;
5283 };
5284 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
5285
5286 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
5289 mField, post_proc_rhs_ptr, nullptr, Sev::verbose)();
5291 mField, post_proc_rhs_ptr, 1.)();
5293 };
5294 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
5296 mField, post_proc_lhs_ptr, 1.);
5297 };
5298 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
5299
5300 auto ts_ctx_ptr = getDMTsCtx(dm);
5301 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
5302 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
5303 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
5304 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
5305 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
5306
5308 };
5309
5310 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_FORWARD);
5311
5312 if (is_quasi_static == PETSC_TRUE) {
5313 CHKERR TSSetSolution(solver, D);
5314 } else {
5315 CHKERR TS2SetSolution(solver, D, DD);
5316 }
5317
5318 auto set_up_adapt = [&](auto solver) {
5320 CHKERR TSAdaptRegister(TSADAPTMOFEM, TSAdaptCreateMoFEM);
5321 TSAdapt adapt;
5322 CHKERR TSGetAdapt(solver, &adapt);
5324 };
5325
5326 CHKERR set_section_monitor(solver);
5327 CHKERR set_time_monitor(dm, solver);
5328 CHKERR set_up_adapt(solver);
5329 CHKERR TSSetFromOptions(solver);
5330
5331 thermoplastic_raw_ptr = this;
5332
5333 if (restart_flg) {
5334 CHKERR TSSetTime(solver, restart_time);
5335 CHKERR TSSetStepNumber(solver, restart_step);
5336 }
5337
5338 CHKERR add_active_dofs_elem(dm);
5339 boost::shared_ptr<SetUpSchur> schur_ptr;
5340 CHKERR set_schur_pc(solver, schur_ptr);
5341 CHKERR set_essential_bc(dm, solver);
5342
5343 auto my_ctx = boost::make_shared<MyTsCtx>();
5344
5345 ts_to_ctx[solver] = my_ctx.get();
5346
5347 SNES snes;
5348 CHKERR TSGetSNES(solver, &snes);
5349
5350 CHKERR SNESMonitorSet(snes, SNESIterationMonitor, my_ctx.get(), NULL);
5351
5352 CHKERR TSSetPreStage(solver, TSIterationPreStage);
5353
5354 auto my_rhs = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec F, void *ctx) {
5355 MyTsCtx *my_ts_ctx = static_cast<MyTsCtx *>(ctx);
5356 auto ts_ctx = my_ts_ctx->dmts_ctx;
5357 auto &m_field = ts_ctx->mField;
5358 auto simple = m_field.getInterface<Simple>();
5359
5360 // Get the iteration number of the snes solver
5361 SNES snes;
5362 CHK_THROW_MESSAGE(TSGetSNES(ts, &snes), "Cannot get SNES");
5363
5364 double time_increment;
5365 CHK_THROW_MESSAGE(TSGetTimeStep(ts, &time_increment), "Cannot get iter");
5366 if (time_increment < min_dt) {
5367 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
5368 "Minimum time increment exceeded");
5369 }
5370
5371 if (my_ts_ctx->snes_iter_counter == 0) {
5372 int error = system("rm ./out_snes_residual_iter_*.h5m > /dev/null 2>&1");
5373 }
5374
5375 // Get the time step
5376 double ts_dt;
5377 CHK_THROW_MESSAGE(TSGetTimeStep(ts, &ts_dt),
5378 "Cannot get timestep from TS object");
5379
5380 if (ts_dt < min_dt) {
5381 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW,
5382 "Minimum timestep exceeded");
5383 }
5384
5385 // Post process the residuals
5386 auto post_proc = [&](auto dm, auto f_res, auto sol, auto sol_dot,
5387 auto out_name) {
5389
5390 auto smart_f_res = SmartPetscObj<Vec>(f_res, true);
5391 auto smart_sol = SmartPetscObj<Vec>(sol, true);
5392 auto smart_sol_dot = SmartPetscObj<Vec>(sol_dot, true);
5393
5394 auto post_proc_fe =
5395 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
5396 ts_ctx->mField);
5397 auto &pip = post_proc_fe->getOpPtrVector();
5399
5401
5402 // pointers for residuals
5403 auto disp_res_mat = boost::make_shared<MatrixDouble>();
5404 auto tau_res_vec = boost::make_shared<VectorDouble>();
5405 auto plastic_strain_res_mat = boost::make_shared<MatrixDouble>();
5406 auto flux_res_mat = boost::make_shared<MatrixDouble>();
5407 auto temp_res_vec = boost::make_shared<VectorDouble>();
5408
5410 "U", disp_res_mat, smart_f_res));
5411 pip.push_back(
5412 new OpCalculateScalarFieldValues("TAU", tau_res_vec, smart_f_res));
5414 "EP", plastic_strain_res_mat, smart_f_res));
5415 // pip.push_back(
5416 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", flux_res_mat,
5417 // smart_f_res));
5418 pip.push_back(
5419 new OpCalculateScalarFieldValues("T", temp_res_vec, smart_f_res));
5420
5421 // pointers for fields
5422 auto disp_mat = boost::make_shared<MatrixDouble>();
5423 auto tau_vec = boost::make_shared<VectorDouble>();
5424 auto plastic_strain_mat = boost::make_shared<MatrixDouble>();
5425 auto flux_mat = boost::make_shared<MatrixDouble>();
5426 auto temp_vec = boost::make_shared<VectorDouble>();
5427
5428 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", disp_mat));
5429 pip.push_back(new OpCalculateScalarFieldValues("TAU", tau_vec));
5431 "EP", plastic_strain_mat));
5432 // pip.push_back(
5433 // new OpCalculateVectorFieldValues<SPACE_DIM>("FLUX", flux_mat,
5434 // smart_sol));
5435 pip.push_back(new OpCalculateScalarFieldValues("T", temp_vec));
5436
5437 // pointers for rates of fields
5438 auto disp_dot_mat = boost::make_shared<MatrixDouble>();
5439 auto tau_dot_vec = boost::make_shared<VectorDouble>();
5440 auto plastic_strain_dot_mat = boost::make_shared<MatrixDouble>();
5441 auto flux_dot_mat = boost::make_shared<MatrixDouble>();
5442 auto temp_dot_vec = boost::make_shared<VectorDouble>();
5443
5445 "U", disp_dot_mat, smart_sol_dot));
5446 pip.push_back(
5447 new OpCalculateScalarFieldValues("TAU", tau_dot_vec, smart_sol_dot));
5449 "EP", plastic_strain_dot_mat, smart_sol_dot));
5450 // pip.push_back(
5451 // new OpCalculateHVecVectorField<3, SPACE_DIM>("FLUX", flux_dot_mat,
5452 // smart_sol_dot));
5453 pip.push_back(
5454 new OpCalculateScalarFieldValues("T", temp_dot_vec, smart_sol_dot));
5455
5456 constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
5457 auto make_d_mat = [&]() {
5458 return boost::make_shared<MatrixDouble>(size_symm * size_symm, 1);
5459 };
5460
5461 auto push_vol_ops = [&](auto &pip) {
5462 ScalerFunTwoArgs unity_2_args = [&](const double, const double) {
5463 return 1.;
5464 };
5465 ScalerFunThreeArgs unity_3_args = [&](const double, const double,
5466 const double) { return 1.; };
5467
5468 auto [common_plastic_ptr, common_hencky_ptr, common_thermal_ptr,
5469 common_thermoelastic_ptr, common_thermoplastic_ptr] =
5472 m_field, "MAT_PLASTIC", "MAT_THERMAL", "MAT_THERMOELASTIC",
5473 "MAT_THERMOPLASTIC", pip, "U", "EP", "TAU", "T", 1.,
5474 unity_2_args, unity_2_args, unity_3_args, Sev::inform);
5475
5476 if (common_hencky_ptr) {
5477 if (common_plastic_ptr->mGradPtr != common_hencky_ptr->matGradPtr)
5479 "Wrong pointer for grad");
5480 }
5481
5482 return std::make_tuple(common_plastic_ptr, common_hencky_ptr,
5483 common_thermoplastic_ptr);
5484 };
5485
5486 auto push_vol_post_proc_ops = [&](auto &pp_fe, auto &&p) {
5488
5489 auto &pip = pp_fe->getOpPtrVector();
5490
5491 auto [common_plastic_ptr, common_hencky_ptr, common_thermoplastic_ptr] =
5492 p;
5493
5494 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
5495 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
5496
5497 auto vec_temp_ptr = boost::make_shared<VectorDouble>();
5498 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
5499
5500 auto u_ptr = boost::make_shared<MatrixDouble>();
5501 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
5502
5504
5505 if (is_large_strains) {
5506
5507 pip.push_back(
5508
5509 new OpPPMap(
5510
5511 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
5512
5513 {{"RESIDUAL_TAU", tau_res_vec},
5514 {"RESIDUAL_T", temp_res_vec},
5515 {"TAU", tau_vec},
5516 {"T", temp_vec},
5517 {"RATE_TAU", tau_dot_vec},
5518 {"RATE_T", temp_dot_vec},
5519 {"ISOTROPIC_HARDENING",
5520 common_plastic_ptr->getPlasticIsoHardeningPtr()},
5521 {"PLASTIC_SURFACE",
5522 common_plastic_ptr->getPlasticSurfacePtr()},
5523 {"PLASTIC_MULTIPLIER",
5524 common_plastic_ptr->getPlasticTauPtr()},
5525 {"YIELD_FUNCTION",
5526 common_plastic_ptr->getPlasticSurfacePtr()},
5527 {"T", common_thermoplastic_ptr->getTempPtr()}},
5528
5529 {{"RESIDUAL_U", disp_res_mat},
5530 {"RATE_U", disp_dot_mat},
5531 {"U", u_ptr},
5532 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
5533
5534 {{"GRAD", common_hencky_ptr->matGradPtr},
5535 {"FIRST_PIOLA",
5536 common_hencky_ptr->getMatFirstPiolaStress()}},
5537
5538 {{"RESIDUAL_EP", plastic_strain_res_mat},
5539 {"RATE_EP", plastic_strain_dot_mat},
5540 {"PLASTIC_STRAIN",
5541 common_plastic_ptr->getPlasticStrainPtr()},
5542 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()},
5543 {"HENCKY_STRAIN", common_hencky_ptr->getMatLogC()},
5544 {"HENCKY_STRESS", common_hencky_ptr->getMatHenckyStress()}}
5545
5546 )
5547
5548 );
5549
5550 } else {
5551
5552 pip.push_back(
5553
5554 new OpPPMap(
5555
5556 pp_fe->getPostProcMesh(), pp_fe->getMapGaussPts(),
5557
5558 {{"RESIDUAL_TAU", tau_res_vec},
5559 {"RESIDUAL_T", temp_res_vec},
5560 {"TAU", tau_vec},
5561 {"T", temp_vec},
5562 {"RATE_TAU", tau_dot_vec},
5563 {"RATE_T", temp_dot_vec},
5564 {"ISOTROPIC_HARDENING",
5565 common_plastic_ptr->getPlasticIsoHardeningPtr()},
5566 {"PLASTIC_SURFACE",
5567 common_plastic_ptr->getPlasticSurfacePtr()},
5568 {"PLASTIC_MULTIPLIER",
5569 common_plastic_ptr->getPlasticTauPtr()},
5570 {"YIELD_FUNCTION",
5571 common_plastic_ptr->getPlasticSurfacePtr()},
5572 {"T", common_thermoplastic_ptr->getTempPtr()}},
5573
5574 {{"RESIDUAL_U", disp_res_mat},
5575 // {"RESIDUAL_FLUX", flux_res_mat},
5576 {"U", disp_mat},
5577 // {"FLUX", flux_mat},
5578 {"RATE_U", disp_dot_mat},
5579 {"U", u_ptr},
5580 {"FLUX", common_thermoplastic_ptr->getHeatFluxPtr()}},
5581
5582 {},
5583
5584 {{"RESIDUAL_PLASTIC_STRAIN", plastic_strain_res_mat},
5585 {"PLASTIC_STRAIN", plastic_strain_mat},
5586 {"RATE_PLASTIC_STRAIN", plastic_strain_dot_mat},
5587 {"STRAIN", common_plastic_ptr->mStrainPtr},
5588 {"STRESS", common_plastic_ptr->mStressPtr},
5589 {"PLASTIC_STRAIN",
5590 common_plastic_ptr->getPlasticStrainPtr()},
5591 {"PLASTIC_FLOW", common_plastic_ptr->getPlasticFlowPtr()}}
5592
5593 )
5594
5595 );
5596 }
5597
5599 };
5600
5601 CHK_MOAB_THROW(push_vol_post_proc_ops(post_proc_fe, push_vol_ops(pip)),
5602 "push_vol_post_proc_ops");
5603
5604 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
5605 post_proc_fe);
5606
5607 post_proc_fe->writeFile(out_name);
5609 };
5610
5611 // Output the RHS
5612
5613 auto set_RHS = TsSetIFunction(ts, t, u, u_t, F, ts_ctx.get());
5614 CHKERR post_proc(simple->getDM(),
5615 //
5616 F, u, u_t,
5617 //
5618 "out_snes_residual_iter_" +
5619 std::to_string(my_ts_ctx->snes_iter_counter) + ".h5m");
5620 return set_RHS;
5621 };
5622
5623 PetscBool is_output_residual_fields = PETSC_FALSE;
5624 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-output_residual_fields",
5625 &is_output_residual_fields, PETSC_NULLPTR);
5626
5627 if (is_output_residual_fields == PETSC_TRUE) {
5628 my_ctx->dmts_ctx = getDMTsCtx(simple->getDM());
5629 // auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
5630 CHKERR TSSetIFunction(solver, PETSC_NULLPTR, my_rhs, my_ctx.get());
5631 }
5632
5633 CHKERR TSSetDM(solver, dm);
5634
5635 auto ts_pre_post_proc = boost::make_shared<TSPrePostProc>();
5636 tsPrePostProc = ts_pre_post_proc;
5637
5638 if (auto ptr = tsPrePostProc.lock()) {
5639 ptr->ExRawPtr = this;
5640 std::multimap<double, EntityHandle> no_el_q_map;
5641 Range no_flipped_els;
5642 std::vector<EntityHandle> no_new_connectivity;
5643 Tag no_th_spatial_coords;
5644
5645 ResizeCtx *ctx = new ResizeCtx{
5646 &mField, PETSC_FALSE, no_el_q_map,
5647 no_flipped_els, no_new_connectivity, no_th_spatial_coords};
5648 PetscBool rollback =
5649 PETSC_TRUE; // choose true if you want to restart current step
5650 CHKERR TSSetResize(solver, rollback, MyTSResizeSetup, MyTSResizeTransfer,
5651 ctx);
5652 CHKERR TSSetApplicationContext(solver, (void *)ctx);
5653 // ptr->globSol = createDMVector(dm);
5654 // CHKERR DMoFEMMeshToLocalVector(dm, ptr->globSol, INSERT_VALUES,
5655 // SCATTER_FORWARD);
5656 // CHKERR VecAssemblyBegin(ptr->globSol);
5657 // CHKERR VecAssemblyEnd(ptr->globSol);
5658 MOFEM_LOG_CHANNEL("TIMER");
5659 MOFEM_LOG_TAG("TIMER", "timer");
5660 if (set_timer)
5661 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
5662 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp";
5663 CHKERR ptr->tsSetUp(solver);
5664 CHKERR TSSetUp(solver);
5665 MOFEM_LOG("TIMER", Sev::verbose) << "TSSetUp <= done";
5666 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve";
5667 CHKERR TSSolve(solver, PETSC_NULLPTR);
5668 MOFEM_LOG("TIMER", Sev::verbose) << "TSSolve <= done";
5669 }
5670
5672}
5673//! [Solve]
5674
5675static char help[] = "...\n\n";
5676
5677int main(int argc, char *argv[]) {
5678
5679#ifdef ADD_CONTACT
5680 #ifdef ENABLE_PYTHON_BINDING
5681 Py_Initialize();
5682 np::initialize();
5683 #endif
5684#endif // ADD_CONTACT
5685
5686 // Initialisation of MoFEM/PETSc and MOAB data structures
5687 const char param_file[] = "param_file.petsc";
5688 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
5689
5690 // Add logging channel for example
5691 auto core_log = logging::core::get();
5692 core_log->add_sink(
5694 core_log->add_sink(
5696 core_log->add_sink(
5697 LogManager::createSink(LogManager::getStrmWorld(), "THERMOPLASTICITY"));
5698 core_log->add_sink(
5700 core_log->add_sink(
5702 LogManager::setLog("PLASTICITY");
5703 LogManager::setLog("THERMAL");
5704 LogManager::setLog("THERMOPLASTICITY");
5705 LogManager::setLog("REMESHING");
5706 MOFEM_LOG_TAG("PLASTICITY", "Plasticity");
5707 MOFEM_LOG_TAG("THERMAL", "Thermal");
5708 MOFEM_LOG_TAG("THERMOPLASTICITY", "Thermoplasticity");
5709 MOFEM_LOG_TAG("REMESHING", "Remeshing");
5710
5711#ifdef ADD_CONTACT
5712 core_log->add_sink(
5714 LogManager::setLog("CONTACT");
5715 MOFEM_LOG_TAG("CONTACT", "Contact");
5716#endif // ADD_CONTACT
5717
5718 try {
5719
5720 //! [Register MoFEM discrete manager in PETSc]
5721 DMType dm_name = "DMMOFEM";
5722 CHKERR DMRegister_MoFEM(dm_name);
5723 //! [Register MoFEM discrete manager in PETSc
5724
5725 //! [Create MoAB]
5726 moab::Core mb_instance; ///< mesh database
5727 moab::Interface &moab = mb_instance; ///< mesh database interface
5728 //! [Create MoAB]
5729
5730 //! [Create MoFEM]
5731 MoFEM::Core core(moab); ///< finite element database
5732 MoFEM::Interface &m_field = core; ///< finite element database interface
5733 //! [Create MoFEM]
5734
5735 //! [Load mesh]
5736 Simple *simple = m_field.getInterface<Simple>();
5738
5739 simple->getBitRefLevel() = comp_mesh_bit;
5740 simple->getBitRefLevelMask() = BitRefLevel().set();
5741
5742 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_distributed_mesh",
5743 &is_distributed_mesh, PETSC_NULLPTR);
5744 if (is_distributed_mesh == PETSC_TRUE) {
5745 CHKERR simple->loadFile();
5746 } else {
5747 char meshFileName[255];
5748 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-file_name",
5749 meshFileName, 255, PETSC_NULLPTR);
5750 CHKERR simple->loadFile("", meshFileName);
5751 }
5752
5753 Range ents;
5754 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, ents,
5755 true);
5756 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevel(
5758 false);
5759 //! [Load mesh]
5760
5761 //! [Example]
5762 Example ex(m_field);
5763 CHKERR ex.runProblem();
5764 //! [Example]
5765 }
5767
5769
5770#ifdef ADD_CONTACT
5771 #ifdef ENABLE_PYTHON_BINDING
5772 if (Py_FinalizeEx() < 0) {
5773 exit(120);
5774 }
5775 #endif
5776#endif // ADD_CONTACT
5777
5778 return 0;
5779}
5780
5781struct SetUpSchurImpl : public SetUpSchur {
5782
5784 SmartPetscObj<IS> field_split_is, SmartPetscObj<AO> ao_up)
5785 : SetUpSchur(), mField(m_field), subDM(sub_dm),
5786 fieldSplitIS(field_split_is), aoSchur(ao_up) {
5787 if (S) {
5789 "Is expected that schur matrix is not "
5790 "allocated. This is "
5791 "possible only is PC is set up twice");
5792 }
5793 }
5794 virtual ~SetUpSchurImpl() { S.reset(); }
5795
5799
5800private:
5802
5803 MoFEM::Interface &mField;
5804 SmartPetscObj<DM> subDM; ///< field split sub dm
5805 SmartPetscObj<IS> fieldSplitIS; ///< IS for split Schur block
5806 SmartPetscObj<AO> aoSchur; ///> main DM to subDM
5807};
5808
5811 auto simple = mField.getInterface<Simple>();
5812 auto pip_mng = mField.getInterface<PipelineManager>();
5813
5814 SNES snes;
5815 CHKERR TSGetSNES(solver, &snes);
5816 KSP ksp;
5817 CHKERR SNESGetKSP(snes, &ksp);
5818 CHKERR KSPSetFromOptions(ksp);
5819
5820 PC pc;
5821 CHKERR KSPGetPC(ksp, &pc);
5822 PetscBool is_pcfs = PETSC_FALSE;
5823 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
5824 if (is_pcfs) {
5825 if (S) {
5827 "Is expected that schur matrix is not "
5828 "allocated. This is "
5829 "possible only is PC is set up twice");
5830 }
5831
5833 CHKERR MatSetBlockSize(S, SPACE_DIM);
5834
5835 // Set DM to use shell block matrix
5836 DM solver_dm;
5837 CHKERR TSGetDM(solver, &solver_dm);
5838 CHKERR DMSetMatType(solver_dm, MATSHELL);
5839
5840 auto ts_ctx_ptr = getDMTsCtx(solver_dm);
5841 auto A = createDMBlockMat(simple->getDM());
5842 auto P = createDMNestSchurMat(simple->getDM());
5843
5844 if (is_quasi_static == PETSC_TRUE) {
5845 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a,
5846 Mat A, Mat B, void *ctx) {
5847 return TsSetIJacobian(ts, t, u, u_t, a, B, A, ctx);
5848 };
5849 CHKERR TSSetIJacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
5850 } else {
5851 auto swap_assemble = [](TS ts, PetscReal t, Vec u, Vec u_t, Vec utt,
5852 PetscReal a, PetscReal aa, Mat A, Mat B,
5853 void *ctx) {
5854 return TsSetI2Jacobian(ts, t, u, u_t, utt, a, aa, B, A, ctx);
5855 };
5856 CHKERR TSSetI2Jacobian(solver, A, P, swap_assemble, ts_ctx_ptr.get());
5857 }
5858 CHKERR KSPSetOperators(ksp, A, P);
5859
5860 auto set_ops = [&]() {
5862 auto pip_mng = mField.getInterface<PipelineManager>();
5863
5864#ifndef ADD_CONTACT
5865 // Boundary
5866 pip_mng->getOpBoundaryLhsPipeline().push_front(
5868 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
5869
5870 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, aoSchur, S, false,
5871 false
5872
5873 ));
5874 // Domain
5875 pip_mng->getOpDomainLhsPipeline().push_front(
5877 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
5878
5879 {"EP", "TAU", "T"}, {nullptr, nullptr, nullptr}, aoSchur, S, false,
5880 false
5881
5882 ));
5883#else
5884
5885 double eps_stab = 1e-4;
5886 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "", "-eps_stab", &eps_stab,
5887 PETSC_NULLPTR);
5888
5891 using OpMassStab = B::OpMass<3, SPACE_DIM * SPACE_DIM>;
5892
5893 // Boundary
5894 pip_mng->getOpBoundaryLhsPipeline().push_front(
5896 pip_mng->getOpBoundaryLhsPipeline().push_back(
5897 new OpMassStab("SIGMA", "SIGMA", [eps_stab](double, double, double) {
5898 return eps_stab;
5899 }));
5900 pip_mng->getOpBoundaryLhsPipeline().push_back(createOpSchurAssembleEnd(
5901
5902 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
5903 aoSchur, S, false, false
5904
5905 ));
5906 // Domain
5907 pip_mng->getOpDomainLhsPipeline().push_front(
5909 pip_mng->getOpDomainLhsPipeline().push_back(createOpSchurAssembleEnd(
5910
5911 {"SIGMA", "EP", "TAU", "T"}, {nullptr, nullptr, nullptr, nullptr},
5912 aoSchur, S, false, false
5913
5914 ));
5915#endif // ADD_CONTACT
5917 };
5918
5919 auto set_assemble_elems = [&]() {
5921 auto schur_asmb_pre_proc = boost::make_shared<FEMethod>();
5922 schur_asmb_pre_proc->preProcessHook = [this]() {
5924 CHKERR MatZeroEntries(S);
5925 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble Begin";
5927 };
5928 auto schur_asmb_post_proc = boost::make_shared<FEMethod>();
5929
5930 schur_asmb_post_proc->postProcessHook = [this, schur_asmb_post_proc]() {
5932 MOFEM_LOG("TIMER", Sev::verbose) << "Lhs Assemble End";
5933
5934 // Apply essential constrains to Schur complement
5935 CHKERR MatAssemblyBegin(S, MAT_FINAL_ASSEMBLY);
5936 CHKERR MatAssemblyEnd(S, MAT_FINAL_ASSEMBLY);
5938 mField, schur_asmb_post_proc, 1, S, aoSchur)();
5939
5941 };
5942 auto ts_ctx_ptr = getDMTsCtx(simple->getDM());
5943 ts_ctx_ptr->getPreProcessIJacobian().push_front(schur_asmb_pre_proc);
5944 ts_ctx_ptr->getPostProcessIJacobian().push_front(schur_asmb_post_proc);
5946 };
5947
5948 auto set_pc = [&]() {
5950 CHKERR PCFieldSplitSetIS(pc, NULL, fieldSplitIS);
5951 CHKERR PCFieldSplitSetSchurPre(pc, PC_FIELDSPLIT_SCHUR_PRE_USER, S);
5953 };
5954
5955 auto set_diagonal_pc = [&]() {
5957 KSP *subksp;
5958 CHKERR PCFieldSplitSchurGetSubKSP(pc, PETSC_NULLPTR, &subksp);
5959 auto get_pc = [](auto ksp) {
5960 PC pc_raw;
5961 CHKERR KSPGetPC(ksp, &pc_raw);
5962 return SmartPetscObj<PC>(pc_raw,
5963 true); // bump reference
5964 };
5965 CHKERR setSchurA00MatSolvePC(get_pc(subksp[0]));
5966 CHKERR PetscFree(subksp);
5968 };
5969
5970 CHKERR set_ops();
5971 CHKERR set_pc();
5972 CHKERR set_assemble_elems();
5973
5974 CHKERR TSSetUp(solver);
5975 CHKERR KSPSetUp(ksp);
5976 CHKERR set_diagonal_pc();
5977
5978 } else {
5979 pip_mng->getOpBoundaryLhsPipeline().push_front(
5981 pip_mng->getOpBoundaryLhsPipeline().push_back(
5982 createOpSchurAssembleEnd({}, {}));
5983 pip_mng->getOpDomainLhsPipeline().push_front(createOpSchurAssembleBegin());
5984 pip_mng->getOpDomainLhsPipeline().push_back(
5985 createOpSchurAssembleEnd({}, {}));
5986 }
5987
5988 // fieldSplitIS.reset();
5989 // aoSchur.reset();
5991}
5992
5993boost::shared_ptr<SetUpSchur>
5995 SmartPetscObj<DM> sub_dm, SmartPetscObj<IS> is_sub,
5996 SmartPetscObj<AO> ao_up) {
5997 return boost::shared_ptr<SetUpSchur>(
5998 new SetUpSchurImpl(m_field, sub_dm, is_sub, ao_up));
5999}
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
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 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
MoFEMErrorCode lambdaBitRefLevel(boost::function< void(EntityHandle ent, BitRefLevel &bit)> fun) const
Process bit ref level by lambda function.
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.
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
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:205
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
constexpr IntegrationType I
constexpr AssemblyType A
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
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
MoFEMErrorCode edgeFlips(BitRefLevel parent_bit, BitRefLevel child_bit)
boost::shared_ptr< MatrixDouble > strainFieldPtr
MoFEMErrorCode doEdgeSplits(bool &refine, bool add_ents)
[Do Edge Flips]
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 createCommonData()
MoFEMErrorCode mechanicalBC(BitRefLevel bit, BitRefLevel mask)
[Initial conditions]
friend struct TSPrePostProc
MoFEMErrorCode getElementQuality(std::multimap< double, EntityHandle > &el_q_map, Range &flipped_els, std::vector< EntityHandle > &new_connectivity, bool &do_refine, Tag &th_spatial_coords)
[Get element quality]
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)
MoFEMErrorCode thermalBC(BitRefLevel bit, BitRefLevel mask)
[Mechanical boundary conditions]
std::tuple< SmartPetscObj< Vec >, SmartPetscObj< VecScatter > > uXScatter
Definition plastic.cpp:237
MoFEMErrorCode doEdgeFlips(std::multimap< double, EntityHandle > &el_q_map, Range &flipped_els, Tag &th_spatial_coords, std::vector< EntityHandle > &new_connectivity)
[Edge flips]
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.
MoFEMErrorCode addVerticesInTheMiddleOfEdges(const EntityHandle meshset, const BitRefLevel &bit, const bool recursive=false, int verb=QUIET, EntityHandle start_v=0)
make vertices in the middle of edges in meshset and add them to refinement levels defined by bit
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode updateAllMeshsetsByEntitiesChildren(const BitRefLevel &bit)
Update all blocksets, sidesets and node sets.
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.
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
static double getEdgeLength(const double *edge_coords)
Get edge length.
Definition Tools.cpp:418
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
boost::weak_ptr< TSPrePostProc > ptr
MoFEM::Interface * m_field
std::vector< EntityHandle > new_connectivity
std::multimap< double, EntityHandle > el_q_map
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
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 mapFields(SmartPetscObj< DM > &intermediateDM, BitRefLevel parentBit, BitRefLevel childBit, PetscInt numVecs=1, Vec vecsToMapFrom[]=PETSC_NULLPTR, Vec vecsToMapTo[]=PETSC_NULLPTR)
MoFEMErrorCode reSetUp(std::vector< std::string > L2Fields, std::vector< int > L2Oders, std::vector< std::string > H1Fields, std::vector< int > H1Orders, std::vector< std::string > HdivFields, std::vector< int > HdivOrders, BitRefLevel bIt)
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]
BitRefLevel flipped_bit
constexpr IntegrationType IT
static char help[]
[Solve]
ThermoPlasticityBits
@ FLIPPED_BIT
@ FIRST_REF_BIT
@ REFINED_EDGES_BIT
@ STORAGE_BIT
@ PREVIOUS_BIT
@ VIRGIN_BIT
@ COMPUTATION_BIT
auto init_T
Initialisation function for temperature field.
double default_thermal_conductivity_scale
BitRefLevel storage_bit
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)
BitRefLevel virgin_mesh_bit
int restart_step
double qual_tol
static std::unordered_map< TS, ResizeCtx * > ts_to_rctx
double default_ref_temp
PetscErrorCode MyTSResizeTransfer(TS, PetscInt, Vec[], Vec[], void *)
double qual_thresh
PetscBool order_edge
double Qinf_thermal(double Qinf, double omega_h, double temp_0, double temp)
BitRefLevel comp_mesh_bit
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
double edge_growth_thresh
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
BitRefLevel prev_mesh_bit
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 get_string_from_vector
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)
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
BitRefLevel refined_bit
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
int num_refinement_levels
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
int atom_test
Atom test.
Definition plastic.cpp:121
PetscBool is_quasi_static
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
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
int ep_order
Order of ep files.
Definition plastic.cpp:140
double cn1
Definition plastic.cpp:136
constexpr FieldSpace CONTACT_SPACE
Definition plastic.cpp:52
#define SCHUR_ASSEMBLE
Definition contact.cpp:18
#define FINITE_DEFORMATION_FLAG
constexpr bool IS_LARGE_STRAINS
double default_ref_temp
double default_heat_capacity
double default_coeff_expansion
auto save_range
double default_heat_conductivity
constexpr int SPACE_DIM
[Define dimension]
Definition elastic.cpp:18
constexpr AssemblyType A
[Define dimension]
Definition elastic.cpp:21
constexpr int SPACE_DIM