v0.16.3
Loading...
Searching...
No Matches
EshelbianPlasticity.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianPlasticity.cpp
3 * \example
4 * mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp
5 *
6 * \brief Eshelbian plasticity implementation
7 *
8 * \copyright 2024. Various authors, some of them anonymous contributors under
9 * MiT core contributors license agreement.
10 */
11
12#define SINGULARITY
13#include <IntegrationRules.hpp>
14#include <MoFEM.hpp>
15
16#ifdef INCLUDE_MBCOUPLER
17 #include <mbcoupler/Coupler.hpp>
18#endif
19using namespace MoFEM;
20
22
24#include <EshelbianRestart.hpp>
25#include <boost/math/constants/constants.hpp>
26
27#include <cholesky.hpp>
28#ifdef ENABLE_PYTHON_BINDING
29 #include <boost/python.hpp>
30 #include <boost/python/def.hpp>
31 #include <boost/python/numpy.hpp>
32namespace bp = boost::python;
33namespace np = boost::python::numpy;
34#endif
35
36#include <EshelbianAux.hpp>
37#include <EshelbianContact.hpp>
41#include <TSElasticPostStep.hpp>
42
43extern "C" {
44#include <phg-quadrule/quad.h>
45}
46
47#include <queue>
48
49static auto send_type(MoFEM::Interface &m_field, Range r,
50 const EntityType type) {
51 ParallelComm *pcomm =
52 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
53
54 auto dim = CN::Dimension(type);
55
56 std::vector<int> sendcounts(pcomm->size());
57 std::vector<int> displs(pcomm->size());
58 std::vector<int> sendbuf(r.size());
59 if (pcomm->rank() == 0) {
60 for (auto p = 1; p != pcomm->size(); p++) {
61 auto part_ents = m_field.getInterface<CommInterface>()
62 ->getPartEntities(m_field.get_moab(), p)
63 .subset_by_dimension(SPACE_DIM);
64 Range faces;
65 CHKERR m_field.get_moab().get_adjacencies(part_ents, dim, true, faces,
66 moab::Interface::UNION);
67 faces = intersect(faces, r);
68 sendcounts[p] = faces.size();
69 displs[p] = sendbuf.size();
70 for (auto f : faces) {
71 auto id = id_from_handle(f);
72 sendbuf.push_back(id);
73 }
74 }
75 }
76
77 int recv_data;
78 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
79 pcomm->comm());
80 std::vector<int> recvbuf(recv_data);
81 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
82 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
83
84 if (pcomm->rank() > 0) {
85 Range r;
86 for (auto &f : recvbuf) {
87 r.insert(ent_form_type_and_id(type, f));
88 }
89 return r;
90 }
91
92 return r;
93}
94
96 const std::string block_name) {
97 Range r;
98
99 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
100 auto bcs = mesh_mng->getCubitMeshsetPtr(
101
102 std::regex((boost::format("%s(.*)") % block_name).str())
103
104 );
105
106 for (auto bc : bcs) {
107 auto meshset = bc->getMeshset();
108 CHK_MOAB_THROW(m_field.get_moab().get_entities_by_handle(meshset, r, true),
109 "get meshset ents");
110 }
111
112 return r;
113};
114
116 const std::string block_name, int dim) {
117 Range r;
118
119 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
120 auto bcs = mesh_mng->getCubitMeshsetPtr(
121
122 std::regex((boost::format("%s(.*)") % block_name).str())
123
124 );
125
126 for (auto bc : bcs) {
127 Range faces;
128 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
129 faces, true),
130 "get meshset ents");
131 r.merge(faces);
132 }
133
134 return r;
135};
136
138 const std::string block_name, int dim) {
139 std::map<std::string, Range> r;
140
141 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
142 auto bcs = mesh_mng->getCubitMeshsetPtr(
143
144 std::regex((boost::format("%s(.*)") % block_name).str())
145
146 );
147
148 for (auto bc : bcs) {
149 Range faces;
150 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
151 faces, true),
152 "get meshset ents");
153 r[bc->getName()] = faces;
154 }
155
156 return r;
157}
158
159static auto save_range(moab::Interface &moab, const std::string name,
160 const Range r, std::vector<Tag> tags = {}) {
162 auto out_meshset = get_temp_meshset_ptr(moab);
163 CHKERR moab.add_entities(*out_meshset, r);
164 if (r.size()) {
165 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
166 tags.data(), tags.size());
167 } else {
168 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
169 }
171};
172
173static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
174 Range boundary_ents;
175 ParallelComm *pcomm =
176 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
177 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
178 PSTATUS_SHARED | PSTATUS_MULTISHARED,
179 PSTATUS_NOT, -1, &boundary_ents),
180 "filter_pstatus");
181 return boundary_ents;
182};
183
184static auto filter_owners(MoFEM::Interface &m_field, Range skin) {
185 Range owner_ents;
186 ParallelComm *pcomm =
187 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
188 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
189 &owner_ents),
190 "filter_pstatus");
191 return owner_ents;
192};
193
194static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
195 Skinner skin(&m_field.get_moab());
196 Range skin_ents;
197 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
198 return skin_ents;
199};
200
202 Range crack_faces) {
203 ParallelComm *pcomm =
204 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
205 auto &moab = m_field.get_moab();
206 Range crack_skin_without_bdy;
207 if (pcomm->rank() == 0) {
208 Range crack_edges;
209 CHKERR moab.get_adjacencies(crack_faces, 1, true, crack_edges,
210 moab::Interface::UNION);
211 auto crack_skin = get_skin(m_field, crack_faces);
212 Range body_ents;
214 m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents),
215 "get_entities_by_dimension");
216 auto body_skin = get_skin(m_field, body_ents);
217 Range body_skin_edges;
218 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1, true, body_skin_edges,
219 moab::Interface::UNION),
220 "get_adjacencies");
221 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
222 auto front_edges_map = get_range_from_block_map(m_field, "FRONT", 1);
223 for (auto &m : front_edges_map) {
224 auto add_front = subtract(m.second, crack_edges);
225 auto i = intersect(m.second, crack_edges);
226 if (i.empty()) {
227 crack_skin_without_bdy.merge(add_front);
228 } else {
229 auto i_skin = get_skin(m_field, i);
230 Range adj_i_skin;
231 CHKERR moab.get_adjacencies(i_skin, 1, true, adj_i_skin,
232 moab::Interface::UNION);
233 adj_i_skin = subtract(intersect(adj_i_skin, m.second), crack_edges);
234 crack_skin_without_bdy.merge(adj_i_skin);
235 }
236 }
237 }
238 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
239}
240
242 Range crack_faces) {
243
244 ParallelComm *pcomm =
245 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
246
247 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface";
248
249 if (!pcomm->rank()) {
250
251 auto impl = [&](auto &saids) {
253
254 auto &moab = m_field.get_moab();
255
256 auto get_adj = [&](auto e, auto dim) {
257 Range adj;
258 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(
259 e, dim, true, adj, moab::Interface::UNION),
260 "get adj");
261 return adj;
262 };
263
264 auto get_conn = [&](auto e) {
265 Range conn;
266 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(e, conn, true),
267 "get connectivity");
268 return conn;
269 };
270
271 constexpr bool debug = false;
272 Range body_ents;
273 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
274 body_ents);
275 auto body_skin = get_skin(m_field, body_ents);
276 auto body_skin_edges = get_adj(body_skin, 1);
277
278 auto crack_skin =
279 subtract(get_skin(m_field, crack_faces), body_skin_edges);
280 auto crack_skin_conn = get_conn(crack_skin);
281 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
282 auto crack_edges = get_adj(crack_faces, 1);
283 crack_edges = subtract(crack_edges, crack_skin);
284 auto all_tets = get_adj(crack_edges, 3);
285 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
286 auto crack_conn = get_conn(crack_edges);
287 all_tets.merge(get_adj(crack_conn, 3));
288
289 if (debug) {
290 CHKERR save_range(m_field.get_moab(), "crack_faces.vtk", crack_faces);
291 CHKERR save_range(m_field.get_moab(), "all_crack_tets.vtk", all_tets);
292 CHKERR save_range(m_field.get_moab(), "crack_edges_all.vtk",
293 crack_edges);
294 }
295
296 if (crack_faces.size()) {
297 auto grow = [&](auto r) {
298 auto crack_faces_conn = get_conn(crack_faces);
299 Range v;
300 auto size_r = 0;
301 while (size_r != r.size() && r.size() > 0) {
302 size_r = r.size();
303 CHKERR moab.get_connectivity(r, v, true);
304 v = subtract(v, crack_faces_conn);
305 if (v.size()) {
306 CHKERR moab.get_adjacencies(v, SPACE_DIM, true, r,
307 moab::Interface::UNION);
308 r = intersect(r, all_tets);
309 }
310 if (r.empty()) {
311 break;
312 }
313 }
314 return r;
315 };
316
317 Range all_tets_ord = all_tets;
318 while (all_tets.size()) {
319 Range faces = get_adj(unite(saids.first, saids.second), 2);
320 faces = subtract(crack_faces, faces);
321 if (faces.size()) {
322 Range tets;
323 auto fit = faces.begin();
324 for (; fit != faces.end(); ++fit) {
325 tets = intersect(get_adj(Range(*fit, *fit), 3), all_tets);
326 if (tets.size() == 2) {
327 break;
328 }
329 }
330 if (tets.empty()) {
331 break;
332 } else {
333 saids.first.insert(tets[0]);
334 saids.first = grow(saids.first);
335 all_tets = subtract(all_tets, saids.first);
336 if (tets.size() == 2) {
337 saids.second.insert(tets[1]);
338 saids.second = grow(saids.second);
339 all_tets = subtract(all_tets, saids.second);
340 }
341 }
342 } else {
343 break;
344 }
345 }
346
347 saids.first = subtract(all_tets_ord, saids.second);
348 saids.second = subtract(all_tets_ord, saids.first);
349 }
350
352 };
353
354 std::pair<Range, Range> saids;
355 if (crack_faces.size())
356 CHK_THROW_MESSAGE(impl(saids), "get crack both sides");
357 return saids;
358 }
359
360 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface <- done";
361
362 return std::pair<Range, Range>();
363}
364
365namespace EshelbianPlasticity {
366
367auto vol_rule(int o) { return 2 * (o + 1); };
368auto face_rule(int o) { return 2 * (o + 1); };
369
371
372 using FunRule = boost::function<int(int)>;
374
376 boost::shared_ptr<Range> front_nodes,
377 boost::shared_ptr<Range> front_edges,
378 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
379 : funRule(vol_rule), frontNodes(front_nodes), frontEdges(front_edges),
380 cachePhi(cache_phi) {};
381
383 boost::shared_ptr<Range> front_nodes,
384 boost::shared_ptr<Range> front_edges, FunRule fun_rule,
385 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
386 : funRule(fun_rule), frontNodes(front_nodes), frontEdges(front_edges),
387 cachePhi(cache_phi) {};
388
390 int order_col, int order_data) {
392
393 constexpr bool debug = false;
394
395 constexpr int numNodes = 4;
396 constexpr int numEdges = 6;
397 constexpr int refinementLevels = 6;
398
399 auto &m_field = fe_raw_ptr->mField;
400 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
401 auto fe_handle = fe_ptr->getFEEntityHandle();
402
403 auto set_base_quadrature = [&]() {
405 if (!funRule) {
407 }
408 const int rule = funRule(order_data);
409 const auto xiao_rule = IntRules::XiaoGimbutas::getTetrahedronRule(rule);
410 if (!xiao_rule) {
411 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
412 "Xiao--Gimbutas tetrahedron rule is available for polynomial "
413 "orders 0 to %d; requested %d",
414 IntRules::XiaoGimbutas::tetrahedronRuleCount, rule);
415 }
416 if (xiao_rule->numBarycentricCoordinates != 4) {
417 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
418 "wrong number of tetrahedron barycentric coordinates");
419 }
420
421 const size_t nb_gauss_pts = xiao_rule->numPoints;
422 auto &gauss_pts = fe_ptr->gaussPts;
423 gauss_pts.resize(4, nb_gauss_pts, false);
424 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[1], 4, &gauss_pts(0, 0), 1);
425 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[2], 4, &gauss_pts(1, 0), 1);
426 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[3], 4, &gauss_pts(2, 0), 1);
427 cblas_dcopy(nb_gauss_pts, xiao_rule->weights, 1, &gauss_pts(3, 0), 1);
428 auto &data = fe_ptr->dataOnElement[H1];
429 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4,
430 false);
431 double *shape_ptr =
432 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
433 cblas_dcopy(4 * nb_gauss_pts, xiao_rule->points, 1, shape_ptr, 1);
435 };
436
437 CHKERR set_base_quadrature();
438
440
441 auto get_singular_nodes = [&]() {
442 int num_nodes;
443 const EntityHandle *conn;
444 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
445 true);
446 std::bitset<numNodes> singular_nodes;
447 for (auto nn = 0; nn != numNodes; ++nn) {
448 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
449 singular_nodes.set(nn);
450 } else {
451 singular_nodes.reset(nn);
452 }
453 }
454 return singular_nodes;
455 };
456
457 auto get_singular_edges = [&]() {
458 std::bitset<numEdges> singular_edges;
459 for (int ee = 0; ee != numEdges; ee++) {
460 EntityHandle edge;
461 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
462 if (frontEdges->find(edge) != frontEdges->end()) {
463 singular_edges.set(ee);
464 } else {
465 singular_edges.reset(ee);
466 }
467 }
468 return singular_edges;
469 };
470
471 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
473 fe_ptr->gaussPts.swap(ref_gauss_pts);
474 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
475 auto &data = fe_ptr->dataOnElement[H1];
476 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
477 double *shape_ptr =
478 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
479 CHKERR ShapeMBTET(shape_ptr, &fe_ptr->gaussPts(0, 0),
480 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
481 nb_gauss_pts);
483 };
484
485 auto singular_nodes = get_singular_nodes();
486 if (singular_nodes.count()) {
487 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
488 if (it_map_ref_coords != mapRefCoords.end()) {
489 CHKERR set_gauss_pts(it_map_ref_coords->second);
491 } else {
492
493 auto refine_quadrature = [&]() {
495
496 const int max_level = refinementLevels;
497 EntityHandle tet;
498
499 moab::Core moab_ref;
500 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
501 EntityHandle nodes[4];
502 for (int nn = 0; nn != 4; nn++)
503 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
504 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
505 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
506 MoFEM::Interface &m_field_ref = mofem_ref_core;
507 {
508 Range tets(tet, tet);
509 Range edges;
510 CHKERR m_field_ref.get_moab().get_adjacencies(
511 tets, 1, true, edges, moab::Interface::UNION);
512 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
513 tets, BitRefLevel().set(0), false, VERBOSE);
514 }
515
516 Range nodes_at_front;
517 for (int nn = 0; nn != numNodes; nn++) {
518 if (singular_nodes[nn]) {
519 EntityHandle ent;
520 CHKERR moab_ref.side_element(tet, 0, nn, ent);
521 nodes_at_front.insert(ent);
522 }
523 }
524
525 auto singular_edges = get_singular_edges();
526
527 EntityHandle meshset;
528 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
529 for (int ee = 0; ee != numEdges; ee++) {
530 if (singular_edges[ee]) {
531 EntityHandle ent;
532 CHKERR moab_ref.side_element(tet, 1, ee, ent);
533 CHKERR moab_ref.add_entities(meshset, &ent, 1);
534 }
535 }
536
537 // refine mesh
538 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
539 for (int ll = 0; ll != max_level; ll++) {
540 Range edges;
541 CHKERR m_field_ref.getInterface<BitRefManager>()
542 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
543 BitRefLevel().set(), MBEDGE,
544 edges);
545 Range ref_edges;
546 CHKERR moab_ref.get_adjacencies(
547 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
548 ref_edges = intersect(ref_edges, edges);
549 Range ents;
550 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
551 ref_edges = intersect(ref_edges, ents);
552 Range tets;
553 CHKERR m_field_ref.getInterface<BitRefManager>()
554 ->getEntitiesByTypeAndRefLevel(
555 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
556 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
557 ref_edges, BitRefLevel().set(ll + 1));
558 CHKERR m_ref->refineTets(tets, BitRefLevel().set(ll + 1));
559 CHKERR m_field_ref.getInterface<BitRefManager>()
560 ->updateMeshsetByEntitiesChildren(meshset,
561 BitRefLevel().set(ll + 1),
562 meshset, MBEDGE, true);
563 }
564
565 // get ref coords
566 Range tets;
567 CHKERR m_field_ref.getInterface<BitRefManager>()
568 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
569 BitRefLevel().set(), MBTET,
570 tets);
571
572 if (debug) {
573 CHKERR save_range(moab_ref, "ref_tets.vtk", tets);
574 }
575
576 MatrixDouble ref_coords(tets.size(), 12, false);
577 int tt = 0;
578 for (Range::iterator tit = tets.begin(); tit != tets.end();
579 tit++, tt++) {
580 int num_nodes;
581 const EntityHandle *conn;
582 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
583 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
584 }
585
586 auto &data = fe_ptr->dataOnElement[H1];
587 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
588 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
589 MatrixDouble &shape_n =
590 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
591 int gg = 0;
592 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
593 double *tet_coords = &ref_coords(tt, 0);
594 double det = Tools::tetVolume(tet_coords);
595 det *= 6;
596 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
597 for (int dd = 0; dd != 3; dd++) {
598 ref_gauss_pts(dd, gg) =
599 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
600 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
601 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
602 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
603 }
604 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
605 }
606 }
607
608 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
609 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
610
611 // clear cache bubble
612 cachePhi->get<0>() = 0;
613 cachePhi->get<1>() = 0;
614 // tet base cache
615 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
616 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
617
619 };
620
621 CHKERR refine_quadrature();
622 }
623 }
624 }
625
627 }
628
629private:
630 struct Fe : public ForcesAndSourcesCore {
631 using ForcesAndSourcesCore::dataOnElement;
632
633 private:
634 using ForcesAndSourcesCore::ForcesAndSourcesCore;
635 };
636
637 boost::shared_ptr<Range> frontNodes;
638 boost::shared_ptr<Range> frontEdges;
639
640 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cachePhi;
641
642 static inline std::map<long int, MatrixDouble> mapRefCoords;
643};
644
646
647 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
648 boost::shared_ptr<Range> front_edges)
649 : frontNodes(front_nodes), frontEdges(front_edges) {};
650
651 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
652 boost::shared_ptr<Range> front_edges, int (*)(int))
653 : frontNodes(front_nodes), frontEdges(front_edges) {};
654
656 int order_col, int order_data) {
658
659 constexpr bool debug = false;
660
661 constexpr int numNodes = 3;
662 constexpr int numEdges = 3;
663 constexpr int refinementLevels = 6;
664
665 auto &m_field = fe_raw_ptr->mField;
666 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
667 auto fe_handle = fe_ptr->getFEEntityHandle();
668
669 auto set_base_quadrature = [&]() {
671 const int rule = face_rule(order_data);
672 const auto xiao_rule = IntRules::XiaoGimbutas::getTriangleRule(rule);
673 if (!xiao_rule) {
674 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
675 "Xiao--Gimbutas triangle rule is available for polynomial "
676 "orders 0 to %d; requested %d",
677 IntRules::XiaoGimbutas::triangleRuleCount, rule);
678 }
679 if (xiao_rule->numBarycentricCoordinates != 3) {
680 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
681 "wrong number of triangle barycentric coordinates");
682 }
683
684 const size_t nb_gauss_pts = xiao_rule->numPoints;
685 auto &gauss_pts = fe_ptr->gaussPts;
686 gauss_pts.resize(3, nb_gauss_pts, false);
687 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[1], 3, &gauss_pts(0, 0), 1);
688 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[2], 3, &gauss_pts(1, 0), 1);
689 cblas_dcopy(nb_gauss_pts, xiao_rule->weights, 1, &gauss_pts(2, 0), 1);
691 };
692
693 CHKERR set_base_quadrature();
694
696
697 auto get_singular_nodes = [&]() {
698 int num_nodes;
699 const EntityHandle *conn;
700 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
701 true);
702 std::bitset<numNodes> singular_nodes;
703 for (auto nn = 0; nn != numNodes; ++nn) {
704 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
705 singular_nodes.set(nn);
706 } else {
707 singular_nodes.reset(nn);
708 }
709 }
710 return singular_nodes;
711 };
712
713 auto get_singular_edges = [&]() {
714 std::bitset<numEdges> singular_edges;
715 for (int ee = 0; ee != numEdges; ee++) {
716 EntityHandle edge;
717 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
718 if (frontEdges->find(edge) != frontEdges->end()) {
719 singular_edges.set(ee);
720 } else {
721 singular_edges.reset(ee);
722 }
723 }
724 return singular_edges;
725 };
726
727 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
729 fe_ptr->gaussPts.swap(ref_gauss_pts);
731 };
732
733 auto singular_nodes = get_singular_nodes();
734 if (singular_nodes.count()) {
735 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
736 if (it_map_ref_coords != mapRefCoords.end()) {
737 CHKERR set_gauss_pts(it_map_ref_coords->second);
739 } else {
740
741 auto refine_quadrature = [&]() {
743
744 const int max_level = refinementLevels;
745
746 moab::Core moab_ref;
747 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
748 EntityHandle nodes[numNodes];
749 for (int nn = 0; nn != numNodes; nn++)
750 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
751 EntityHandle tri;
752 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
753 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
754 MoFEM::Interface &m_field_ref = mofem_ref_core;
755 {
756 Range tris(tri, tri);
757 Range edges;
758 CHKERR m_field_ref.get_moab().get_adjacencies(
759 tris, 1, true, edges, moab::Interface::UNION);
760 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
761 tris, BitRefLevel().set(0), false, VERBOSE);
762 }
763
764 Range nodes_at_front;
765 for (int nn = 0; nn != numNodes; nn++) {
766 if (singular_nodes[nn]) {
767 EntityHandle ent;
768 CHKERR moab_ref.side_element(tri, 0, nn, ent);
769 nodes_at_front.insert(ent);
770 }
771 }
772
773 auto singular_edges = get_singular_edges();
774
775 EntityHandle meshset;
776 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
777 for (int ee = 0; ee != numEdges; ee++) {
778 if (singular_edges[ee]) {
779 EntityHandle ent;
780 CHKERR moab_ref.side_element(tri, 1, ee, ent);
781 CHKERR moab_ref.add_entities(meshset, &ent, 1);
782 }
783 }
784
785 // refine mesh
786 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
787 for (int ll = 0; ll != max_level; ll++) {
788 Range edges;
789 CHKERR m_field_ref.getInterface<BitRefManager>()
790 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
791 BitRefLevel().set(), MBEDGE,
792 edges);
793 Range ref_edges;
794 CHKERR moab_ref.get_adjacencies(
795 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
796 ref_edges = intersect(ref_edges, edges);
797 Range ents;
798 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
799 ref_edges = intersect(ref_edges, ents);
800 Range tris;
801 CHKERR m_field_ref.getInterface<BitRefManager>()
802 ->getEntitiesByTypeAndRefLevel(
803 BitRefLevel().set(ll), BitRefLevel().set(), MBTRI, tris);
804 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
805 ref_edges, BitRefLevel().set(ll + 1));
806 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
807 CHKERR m_field_ref.getInterface<BitRefManager>()
808 ->updateMeshsetByEntitiesChildren(meshset,
809 BitRefLevel().set(ll + 1),
810 meshset, MBEDGE, true);
811 }
812
813 // get ref coords
814 Range tris;
815 CHKERR m_field_ref.getInterface<BitRefManager>()
816 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
817 BitRefLevel().set(), MBTRI,
818 tris);
819
820 if (debug) {
821 CHKERR save_range(moab_ref, "ref_tris.vtk", tris);
822 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
823 }
824
825 MatrixDouble ref_coords(tris.size(), 9, false);
826 int tt = 0;
827 for (Range::iterator tit = tris.begin(); tit != tris.end();
828 tit++, tt++) {
829 int num_nodes;
830 const EntityHandle *conn;
831 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
832 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
833 }
834
835 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
836 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
837 MatrixDouble shape_n(nb_gauss_pts, 3, false);
838 CHKERR ShapeMBTRI(&shape_n(0, 0), &fe_ptr->gaussPts(0, 0),
839 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
840 int gg = 0;
841 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
842 double *tri_coords = &ref_coords(tt, 0);
844 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
845 auto det = t_normal.l2();
846 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
847 for (int dd = 0; dd != 2; dd++) {
848 ref_gauss_pts(dd, gg) =
849 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
850 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
851 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
852 }
853 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
854 }
855 }
856
857 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
858 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
859
861 };
862
863 CHKERR refine_quadrature();
864 }
865 }
866 }
867
869 }
870
871private:
872 struct Fe : public ForcesAndSourcesCore {
873 using ForcesAndSourcesCore::dataOnElement;
874
875 private:
876 using ForcesAndSourcesCore::ForcesAndSourcesCore;
877 };
878
879 boost::shared_ptr<Range> frontNodes;
880 boost::shared_ptr<Range> frontEdges;
881
882 static inline std::map<long int, MatrixDouble> mapRefCoords;
883};
884
885boost::function<double(const double)> EshelbianCore::f = EshelbianCore::f_log_e;
886boost::function<double(const double)> EshelbianCore::d_f =
888boost::function<double(const double)> EshelbianCore::dd_f =
890boost::function<double(const double)> EshelbianCore::inv_f =
892boost::function<double(const double)> EshelbianCore::inv_d_f =
894boost::function<double(const double)> EshelbianCore::inv_dd_f =
896
898EshelbianCore::query_interface(boost::typeindex::type_index type_index,
899 UnknownInterface **iface) const {
900 *iface = const_cast<EshelbianCore *>(this);
901 return 0;
902}
903
904MoFEMErrorCode OpJacobian::doWork(int side, EntityType type, EntData &data) {
906
907 if (evalRhs)
908 CHKERR evaluateRhs(data);
909
910 if (evalLhs)
911 CHKERR evaluateLhs(data);
912
914}
915
917 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
918}
919
921 auto destroy_dm = [](SmartPetscObj<DM> &dm) {
922 if (!dm)
923 return;
924
925 auto comm = PetscObjectComm(reinterpret_cast<PetscObject>(dm.get()));
926 CHKERRABORT(comm, DMMoFEMClearDMCtx(dm));
927 dm.reset();
928 };
929
930 // Sub-problems retain pointers into the parent problem. Clear their MoFEM
931 // contexts before releasing the coupled DM and before PETSc reference
932 // cycles can prevent the type-specific destroy callback from being reached.
934 destroy_dm(dmIncrementalOptimization);
935 destroy_dm(dmPrjSpatial);
936 destroy_dm(dmMaterial);
937 destroy_dm(dmElastic);
938 destroy_dm(dM);
939}
940
943
944 const char *ts_prefix = nullptr;
945 CHKERR TSGetOptionsPrefix(ts, &ts_prefix);
946 const std::string prefix = ts_prefix ? ts_prefix : "";
947 const auto make_ts_option = [&prefix](const char *name) {
948 return std::string("-") + prefix + name;
949 };
950 const auto has_ts_option = [&make_ts_option](const char *name,
951 PetscBool *found) {
952 const auto option = make_ts_option(name);
953 return PetscOptionsHasName(PETSC_NULLPTR, PETSC_NULLPTR, option.c_str(),
954 found);
955 };
956 const auto clear_ts_option = [&make_ts_option](const char *name) {
957 const auto option = make_ts_option(name);
958 return PetscOptionsClearValue(PETSC_NULLPTR, option.c_str());
959 };
960
961 PetscBool cancel_snes_monitor = PETSC_FALSE;
962 PetscBool cancel_ksp_monitor = PETSC_FALSE;
963 CHKERR has_ts_option("snes_monitor_cancel", &cancel_snes_monitor);
964 CHKERR has_ts_option("ksp_monitor_cancel", &cancel_ksp_monitor);
965
966 SNES snes;
967 CHKERR TSGetSNES(ts, &snes);
968
969 if (cancel_snes_monitor) {
970 CHKERR clear_ts_option("snes_monitor");
971 CHKERR clear_ts_option("snes_linesearch_monitor");
972 CHKERR SNESMonitorCancel(snes);
973 SNESLineSearch line_search;
974 CHKERR SNESGetLineSearch(snes, &line_search);
975 CHKERR SNESLineSearchMonitorCancel(line_search);
976 }
977
978 if (cancel_ksp_monitor) {
979 CHKERR clear_ts_option("ksp_monitor");
980 CHKERR clear_ts_option("ksp_monitor_short");
981 CHKERR clear_ts_option("ksp_monitor_true_residual");
982 KSP ksp;
983 CHKERR SNESGetKSP(snes, &ksp);
984 CHKERR KSPMonitorCancel(ksp);
985 }
986
988}
989
992
993 PetscBool cancel_projection_ksp_monitor = PETSC_FALSE;
994 CHKERR PetscOptionsHasName(PETSC_NULLPTR, PETSC_NULLPTR,
995 "-prjspatial_ksp_monitor_cancel",
996 &cancel_projection_ksp_monitor);
997
998 if (cancel_projection_ksp_monitor) {
999 CHKERR PetscOptionsClearValue(PETSC_NULLPTR, "-prjspatial_ksp_monitor");
1000 CHKERR PetscOptionsClearValue(PETSC_NULLPTR,
1001 "-prjspatial_ksp_monitor_short");
1002 CHKERR PetscOptionsClearValue(PETSC_NULLPTR,
1003 "-prjspatial_ksp_monitor_true_residual");
1004 }
1005
1007}
1008
1011 // Interface initialisation applies JSON options before selecting the layout.
1013 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
1014 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
1015 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
1016 const char *list_broken_hdiv_bases[] = {"demkowicz", "ainsworth"};
1017 PetscInt choice_rot = EshelbianCore::rotSelector;
1018 PetscInt choice_grad = EshelbianCore::gradApproximator;
1019 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
1020 PetscInt choice_stretch = StretchSelector::LOG;
1021 PetscInt choice_solver = SolverType::TimeSolver;
1022 PetscInt choice_broken_hdiv_base = 0;
1023 PetscBool l2_user_base_scale_set = PETSC_FALSE;
1026 choice_broken_hdiv_base = 0;
1027 break;
1029 choice_broken_hdiv_base = 1;
1030 break;
1031 default:
1032 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1033 "Unsupported broken HDIV base %s",
1035 }
1036 char analytical_expr_file_name[255] = "analytical_expr.py";
1037
1038 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
1039 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
1040 spaceOrder, &spaceOrder, PETSC_NULLPTR);
1041 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
1042 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
1043 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
1044 "", materialH1Order, &materialH1Order, PETSC_NULLPTR);
1045 CHKERR PetscOptionsScalar("-viscosity_alpha_u",
1046 "Logarithmic-stretch rate viscosity", "", alphaU,
1047 &alphaU, PETSC_NULLPTR);
1048 CHKERR PetscOptionsScalar("-viscosity_alpha_w",
1049 "Spatial-displacement rate viscosity", "", alphaW,
1050 &alphaW, PETSC_NULLPTR);
1051 CHKERR PetscOptionsScalar("-alpha_omega", "H1 rotation penalty coefficient",
1052 "", alphaOmega, &alphaOmega, PETSC_NULLPTR);
1053 CHKERR PetscOptionsScalar("-alpha_r", "L2 rotation penalty coefficient", "",
1054 alphaR, &alphaR, PETSC_NULLPTR);
1055 CHKERR PetscOptionsScalar("-viscosity_alpha_omega",
1056 "H1 rotation-rate viscosity", "",
1058 PETSC_NULLPTR);
1059 CHKERR PetscOptionsScalar("-viscosity_alpha_r", "L2 rotation-rate viscosity", "",
1060 alphaViscousR, &alphaViscousR, PETSC_NULLPTR);
1061 CHKERR PetscOptionsScalar("-density_alpha_rho",
1062 "Spatial-displacement inertia density", "",
1063 alphaRho, &alphaRho, PETSC_NULLPTR);
1064 CHKERR PetscOptionsScalar("-alpha_tau",
1065 "Interior displacement-stabilisation coefficient",
1066 "", alphaTau, &alphaTau, PETSC_NULLPTR);
1067 CHKERR PetscOptionsScalar(
1068 "-alpha_tau_lin",
1069 "Coefficient multiplying the face-averaged normal-traction contribution "
1070 "to displacement stabilisation",
1071 "", alphaTauLin, &alphaTauLin, PETSC_NULLPTR);
1072 CHKERR PetscOptionsScalar("-alpha_tau_bc_disp",
1073 "Displacement-BC stabilisation coefficient", "",
1074 alphaTauBcDisp, &alphaTauBcDisp, PETSC_NULLPTR);
1075 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
1076 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
1077 PETSC_NULLPTR);
1078 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
1079 list_rots, NO_H1_CONFIGURATION + 1,
1080 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
1081
1082 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
1083 StretchSelector::STRETCH_SELECTOR_LAST,
1084 list_stretches[choice_stretch], &choice_stretch,
1085 PETSC_NULLPTR);
1086
1087 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1088 setSingularity, &setSingularity, PETSC_NULLPTR);
1089 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1091 &l2_user_base_scale_set);
1092 CHKERR PetscOptionsEList("-broken_hdiv_base",
1093 "broken HDIV stress approximation base", "",
1094 list_broken_hdiv_bases, 2,
1095 list_broken_hdiv_bases[choice_broken_hdiv_base],
1096 &choice_broken_hdiv_base, PETSC_NULLPTR);
1097
1098 // dynamic relaxation
1099
1100 // @deprecate this option
1101 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1102 physicalTimeFlg, &physicalTimeFlg, PETSC_NULLPTR);
1103 CHKERR PetscOptionsEList(
1104 "-solver_type", "solver type", "", EshelbianCore::listSolvers,
1106 EshelbianCore::listSolvers[choice_solver], &choice_solver, PETSC_NULLPTR);
1107
1108 if (choice_solver != SolverType::TimeSolver) {
1109 CHKERR PetscOptionsScalar("-physical_final_time", "physical final time", "",
1111 &EshelbianCore::finalPhysicalTime, PETSC_NULLPTR);
1112 CHKERR PetscOptionsScalar("-physical_delta_time", "physical delta time", "",
1114 PETSC_NULLPTR);
1115 CHKERR PetscOptionsInt("-physical_max_steps", "physical max iterations", "",
1117 PETSC_NULLPTR);
1118 CHKERR PetscOptionsBool(
1119 "-physical_h1_update", "update each physicalsolver step", "",
1121 }
1122
1123 // contact parameters
1124 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1126 PETSC_NULLPTR);
1127 // cohesive interface
1128 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1129 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1130 CHKERR PetscOptionsInt(
1131 "-cohesive_interface_remove_level", "cohesive interface remove level", "",
1133 CHKERR PetscOptionsBool("-plastic_volume",
1134 "restrict plasticity to the PLATIC_VOLUME block", "",
1135 plasticVolume, &plasticVolume, PETSC_NULLPTR);
1136
1137 // cracking parameters
1138 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1139 &crackingOn, PETSC_NULLPTR);
1140 CHKERR PetscOptionsBool("-propagate_under_compression",
1141 "propagate crack under compression", "",
1143 &propagateUnderCompression, PETSC_NULLPTR);
1144 CHKERR PetscOptionsScalar("-cracking_add_time", "cracking add time", "",
1145 crackingAddTime, &crackingAddTime, PETSC_NULLPTR);
1146 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1148 PETSC_NULLPTR);
1149 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1150 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1151
1152 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1153 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1154 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1155 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1156 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1157 "", list_release, 2, list_release[choice_release],
1158 &choice_release, PETSC_NULLPTR);
1159 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1161 PETSC_NULLPTR); // backward compatibility
1162 CHKERR PetscOptionsInt(
1163 "-nb_J_integral_contours", "Number of J integral contours", "",
1164 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1165
1166 // internal stress
1167 char tag_name[255] = "";
1168 CHKERR PetscOptionsString("-internal_stress_tag_name",
1169 "internal stress tag name", "", "", tag_name, 255,
1170 PETSC_NULLPTR);
1171 internalStressTagName = string(tag_name);
1172 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1174 PETSC_NULLPTR);
1175
1176 // Heterogenous Young's modulus
1177 char tag_heterogeneous_youngs_modulus_name[255] = "";
1178 CHKERR PetscOptionsString(
1179 "-heterogeneous_youngs_modulus", "heterogeneous Young's modulus tag name",
1180 "", "", tag_heterogeneous_youngs_modulus_name, 255, PETSC_NULLPTR);
1181 heterogeneousYoungModTagName = string(tag_heterogeneous_youngs_modulus_name);
1182
1183 PetscBool has_analytical_expr_file_option = PETSC_FALSE;
1185 PETSC_NULLPTR, PETSC_NULLPTR, "-analytical_expr_file",
1186 analytical_expr_file_name, 255, &has_analytical_expr_file_option);
1187 if (!has_analytical_expr_file_option) {
1188 const auto analytical_expr_script =
1189 mField.getInterface<JsonConfigManager>()->getPythonScriptByKey(
1190 "analytical_expr");
1191 if (!analytical_expr_script.empty()) {
1192 CHKERR PetscStrncpy(analytical_expr_file_name,
1193 analytical_expr_script.c_str(),
1194 sizeof(analytical_expr_file_name));
1195 MOFEM_LOG("EP", Sev::inform)
1196 << "Using Python script 'analytical_expr' from JSON config: "
1197 << analytical_expr_file_name;
1198 }
1199 }
1200
1201 PetscOptionsEnd();
1202
1204
1205 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1206 "none");
1207 char tag_mesh_transfer_source_file_name[255] = "";
1208 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1209 "source.h5m", tag_mesh_transfer_source_file_name,
1211 meshTransferSourceMeshFileName = string(tag_mesh_transfer_source_file_name);
1212 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1213 &meshTransferInterpOrder, PETSC_NULLPTR);
1214 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1216 PETSC_NULLPTR);
1217 PetscOptionsEnd();
1218
1220 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1221 "Unsupported mesh transfer interpolation order %d",
1223 }
1224 if (!internalStressTagName.empty())
1226 if (!heterogeneousYoungModTagName.empty())
1228
1229 const PetscBool l2_user_base_scale_option = l2UserBaseScale;
1230 if (setSingularity && !l2_user_base_scale_set) {
1231 l2UserBaseScale = PETSC_TRUE;
1232 }
1233
1234 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1235 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1236 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1238 static_cast<EnergyReleaseSelector>(choice_release);
1239 switch (choice_broken_hdiv_base) {
1240 case 0:
1242 break;
1243 case 1:
1245 break;
1246 default:
1247 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1248 "Unknown broken HDIV base option");
1249 }
1250
1252 case StretchSelector::LINEAR:
1259 break;
1260 case StretchSelector::LOG:
1267 break;
1268 case StretchSelector::LOG_QUADRATIC:
1275 break;
1276 default:
1277 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1278 break;
1279 };
1280
1281 const PetscBool dynamic_relaxation_option = physicalTimeFlg;
1282 if (physicalTimeFlg) {
1283 MOFEM_LOG("EP", Sev::warning)
1284 << "-dynamic_relaxation option is deprecated, use -solver_type "
1285 "dynamic_relaxation instead.";
1286 choice_solver = SolverType::DynamicRelaxation;
1287 }
1288
1289 switch (choice_solver) {
1292 break;
1296 physicalTimeFlg = PETSC_TRUE;
1297 break;
1301 physicalTimeFlg = PETSC_TRUE;
1302 break;
1305 physicalTimeFlg = PETSC_TRUE;
1306 break;
1310 break;
1314 physicalTimeFlg = PETSC_TRUE;
1315 break;
1319 physicalTimeFlg = PETSC_TRUE;
1320 break;
1324 break;
1328 physicalTimeFlg = PETSC_TRUE;
1329 break;
1332 static_cast<SolverType>(
1334 physicalTimeFlg = PETSC_TRUE;
1335 break;
1338 static_cast<SolverType>(
1340 physicalTimeFlg = PETSC_TRUE;
1341 break;
1342 default:
1343 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1344 break;
1345 };
1346
1347 // start cracking time
1349 crackingStartTime = -1;
1350 crackingAddTime = -1;
1351 MOFEM_LOG("EP", Sev::warning)
1352 << "Cracking start/add time does not apply for load factor solver.";
1353 } else {
1355 }
1356
1357 const auto yes_no = [](auto flag) { return flag ? "yes" : "no"; };
1358
1359 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1360 MOFEM_LOG("EP", Sev::inform)
1361 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1362 MOFEM_LOG("EP", Sev::inform)
1363 << "materialH1Order: -material_order " << materialH1Order;
1364 MOFEM_LOG("EP", Sev::inform)
1365 << "alphaU (-viscosity_alpha_u), logarithmic-stretch rate viscosity: "
1366 << alphaU;
1367 MOFEM_LOG("EP", Sev::inform)
1368 << "alphaW (-viscosity_alpha_w), spatial-displacement rate viscosity: "
1369 << alphaW;
1370 MOFEM_LOG("EP", Sev::inform)
1371 << "alphaOmega (-alpha_omega), H1 rotation penalty coefficient: "
1372 << alphaOmega;
1373 MOFEM_LOG("EP", Sev::inform)
1374 << "alphaR (-alpha_r), L2 rotation penalty coefficient: " << alphaR;
1375 MOFEM_LOG("EP", Sev::inform)
1376 << "alphaViscousOmega (-viscosity_alpha_omega), H1 rotation-rate "
1377 "viscosity: "
1379 MOFEM_LOG("EP", Sev::inform)
1380 << "alphaViscousR (-viscosity_alpha_r), L2 rotation-rate viscosity: "
1381 << alphaViscousR;
1382 MOFEM_LOG("EP", Sev::inform)
1383 << "alphaRho (-density_alpha_rho), spatial-displacement inertia "
1384 "density: "
1385 << alphaRho;
1386 MOFEM_LOG("EP", Sev::inform)
1387 << "alphaTau (-alpha_tau), interior displacement-stabilisation "
1388 "coefficient: "
1389 << alphaTau;
1390 MOFEM_LOG("EP", Sev::inform)
1391 << "alphaTauLin (-alpha_tau_lin), face-averaged normal-traction "
1392 "stabilisation coefficient: "
1393 << alphaTauLin;
1394 MOFEM_LOG("EP", Sev::inform)
1395 << "alphaTauBcDisp (-alpha_tau_bc_disp), displacement-BC "
1396 "stabilisation coefficient: "
1397 << alphaTauBcDisp;
1398 MOFEM_LOG("EP", Sev::inform)
1399 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1400 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation: -grad "
1401 << list_rots[EshelbianCore::gradApproximator];
1402 MOFEM_LOG("EP", Sev::inform)
1403 << "Stretch: -stretches " << list_stretches[choice_stretch];
1404
1405 MOFEM_LOG("EP", Sev::inform) << "Dynamic relaxation: -dynamic_relaxation "
1406 << yes_no(dynamic_relaxation_option);
1407 MOFEM_LOG("EP", Sev::inform) << "Solver type: -solver_type "
1408 << EshelbianCore::listSolvers[choice_solver];
1409 if (choice_solver != SolverType::TimeSolver) {
1410 MOFEM_LOG("EP", Sev::inform)
1411 << "Physical final time: -physical_final_time " << finalPhysicalTime;
1412 MOFEM_LOG("EP", Sev::inform)
1413 << "Physical delta time: -physical_delta_time " << physicalDt;
1414 MOFEM_LOG("EP", Sev::inform)
1415 << "Physical max steps: -physical_max_steps " << physicalMaxSteps;
1416 MOFEM_LOG("EP", Sev::inform) << "Physical H1 update: -physical_h1_update "
1417 << yes_no(physicalH1Update);
1418 }
1419 MOFEM_LOG("EP", Sev::inform)
1420 << "Singularity: -set_singularity " << yes_no(setSingularity);
1421 MOFEM_LOG("EP", Sev::inform) << "L2 user base scale: -l2_user_base_scale "
1422 << yes_no(l2_user_base_scale_option);
1423 if (l2UserBaseScale != l2_user_base_scale_option) {
1424 MOFEM_LOG("EP", Sev::inform)
1425 << "Effective L2 user base scale after option processing "
1426 << yes_no(l2UserBaseScale) << " (auto-enabled by -set_singularity)";
1427 }
1428 MOFEM_LOG("EP", Sev::inform)
1429 << "Broken HDIV base: -broken_hdiv_base "
1430 << list_broken_hdiv_bases[choice_broken_hdiv_base];
1431 MOFEM_LOG("EP", Sev::inform)
1432 << "Contact max post-proc ref level: -contact_max_post_proc_ref_level "
1434
1435 MOFEM_LOG("EP", Sev::inform)
1436 << "Cracking on: -cracking_on " << yes_no(crackingOn);
1437 MOFEM_LOG("EP", Sev::inform)
1438 << "Cracking add time: -cracking_add_time " << crackingAddTime;
1439 MOFEM_LOG("EP", Sev::inform)
1440 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1441 MOFEM_LOG("EP", Sev::inform)
1442 << "Griffith energy: -griffith_energy " << griffithEnergy;
1443 MOFEM_LOG("EP", Sev::inform)
1444 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1445 MOFEM_LOG("EP", Sev::inform)
1446 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1447 MOFEM_LOG("EP", Sev::inform)
1448 << "Energy release variant: -energy_release_variant "
1449 << list_release[EshelbianCore::energyReleaseSelector];
1450 MOFEM_LOG("EP", Sev::inform)
1451 << "Number of J integral contours: -nb_J_integral_contours / "
1452 "-nb_J_integral_levels "
1454 MOFEM_LOG("EP", Sev::inform)
1455 << "Cohesive interface on: -cohesive_interface_on "
1456 << ((interfaceCrack == PETSC_TRUE) ? "yes" : "no");
1457 MOFEM_LOG("EP", Sev::inform)
1458 << "Cohesive interface remove level: -cohesive_interface_remove_level "
1460 MOFEM_LOG("EP", Sev::inform)
1461 << "Plastic volume: -plastic_volume " << yes_no(plasticVolume);
1462 MOFEM_LOG("EP", Sev::inform)
1463 << "Internal stress tag name: -internal_stress_tag_name "
1465 MOFEM_LOG("EP", Sev::inform)
1466 << "Internal stress Voigt notation: -internal_stress_voigt "
1467 << yes_no(internalStressVoigt);
1468 MOFEM_LOG("EP", Sev::inform)
1469 << "Heterogeneous Young's modulus: -heterogeneous_youngs_modulus "
1471 MOFEM_LOG("EP", Sev::inform)
1472 << "Analytical expression file: -analytical_expr_file "
1473 << analytical_expr_file_name;
1475 MOFEM_LOG("EP", Sev::inform)
1476 << "Mesh transfer source file: -mesh_transfer_source_file "
1478 } else {
1479 MOFEM_LOG("EP", Sev::inform)
1480 << "Mesh transfer source file: -mesh_transfer_source_file <not set>";
1481 }
1482 MOFEM_LOG("EP", Sev::inform)
1483 << "Mesh transfer interpolation order: -mesh_transfer_interp_order "
1485 MOFEM_LOG("EP", Sev::inform)
1486 << "Mesh transfer hybrid interpolation: -mesh_transfer_hybrid_interp "
1487 << yes_no(meshTransferHybridInterp);
1488
1489#ifdef ENABLE_PYTHON_BINDING
1490 auto file_exists = [](std::string myfile) {
1491 std::ifstream file(myfile.c_str());
1492 if (file) {
1493 return true;
1494 }
1495 return false;
1496 };
1497
1498 if (file_exists(analytical_expr_file_name)) {
1499 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1500
1501 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1502 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1503 analytical_expr_file_name);
1504 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1505 } else {
1506 MOFEM_LOG("EP", Sev::warning)
1507 << analytical_expr_file_name << " file NOT found";
1508 }
1509#endif
1510
1511 if (spaceH1Order == -1)
1513
1515}
1516
1520
1521 plasticVolumes = boost::make_shared<Range>();
1522 if (plasticVolume) {
1524 }
1525 if (plasticVolumes->empty()) {
1526 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
1528 }
1529 MOFEM_LOG("EP", Sev::inform)
1530 << "Number of plastic volume elements: " << plasticVolumes->size();
1531
1532 interfaceFaces = boost::make_shared<Range>(
1533 get_range_from_block(mField, "(INTERFACE|MAT_COHESIVE)", SPACE_DIM - 1));
1534
1535 auto get_internal_interface_faces = [&](const auto block_name) {
1536 auto volume_elements = get_range_from_block(mField, block_name, SPACE_DIM);
1537 auto skin = filter_true_skin(mField, get_skin(mField, volume_elements));
1538 Range faces;
1539 CHKERR mField.get_moab().get_adjacencies(
1540 volume_elements, SPACE_DIM - 1, true, faces, moab::Interface::UNION);
1541 faces = subtract(faces, skin);
1542 MOFEM_LOG("EP", Sev::inform)
1543 << "Number of volume interface elements: " << volume_elements.size()
1544 << " and internal faces: " << faces.size();
1545 return faces;
1546 };
1547
1548 interfaceFaces->merge(
1549 get_internal_interface_faces("(VOLUME_INTERFACE|MAT_COHESIVE)"));
1550
1551 auto remove_interface_faces = [&](const auto block_name, const auto level) {
1553 Range retained_faces;
1554 if (mField.get_comm_rank() == 0) {
1555 auto entities = get_entities_by_handle(mField, block_name);
1556 for (auto l = 0; l < level; ++l) {
1557 Range adjacent_tets;
1558 CHKERR mField.get_moab().get_adjacencies(
1559 entities, SPACE_DIM, true, adjacent_tets, moab::Interface::UNION);
1560 Range adjacent_tet_faces;
1561 CHKERR mField.get_moab().get_adjacencies(adjacent_tets, SPACE_DIM - 1,
1562 true, adjacent_tet_faces,
1563 moab::Interface::UNION);
1564 entities.merge(adjacent_tet_faces);
1565 }
1566 const auto faces = entities.subset_by_dimension(SPACE_DIM - 1);
1567 if (!faces.empty()) {
1568 MOFEM_LOG("EP", Sev::inform)
1569 << "Removing " << faces.size() << " of " << interfaceFaces->size()
1570 << " interface faces";
1571 }
1572 retained_faces = subtract(*interfaceFaces, faces);
1573 MOFEM_LOG("EP", Sev::noisy)
1574 << "Interface faces after removal " << retained_faces;
1575 }
1576 auto global_retained_faces = send_type(mField, retained_faces, MBTRI);
1577 interfaceFaces->swap(global_retained_faces);
1579 };
1580 CHKERR remove_interface_faces("REMOVE_INTERFACE", interfaceRemoveLevel);
1581
1582 MOFEM_LOG("EP", Sev::inform)
1583 << "Number of interface elements: " << interfaceFaces->size();
1584
1586}
1587
1588MoFEMErrorCode EshelbianCore::addFields(const EntityHandle meshset,
1589 const bool add_bubble) {
1591
1592 auto get_tets = [&]() {
1593 Range tets;
1594 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1595 return tets;
1596 };
1597
1598 auto get_tets_skin = [&]() {
1599 Range tets_skin_part;
1600 Skinner skin(&mField.get_moab());
1601 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1602 ParallelComm *pcomm =
1603 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1604 Range tets_skin;
1605 CHKERR pcomm->filter_pstatus(tets_skin_part,
1606 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1607 PSTATUS_NOT, -1, &tets_skin);
1608 return tets_skin;
1609 };
1610
1611 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1612 // That mean, that hybrid field on all faces on which traction is applied,
1613 // on other faces, or enforcing displacements as
1614 // natural boundary condition.
1616 for (auto &v : *bcSpatialTractionVecPtr) {
1617 tets_skin = subtract(tets_skin, v.faces);
1618 }
1619
1621 for (auto &v : *bcSpatialSpringVecPtr) {
1622 tets_skin = subtract(tets_skin, v.faces);
1623 }
1624
1626 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1627 tets_skin = subtract(tets_skin, v.faces);
1628 }
1629
1631 for (auto &v : *bcSpatialPressureVecPtr) {
1632 tets_skin = subtract(tets_skin, v.faces);
1633 }
1634
1635 return tets_skin;
1636 };
1637
1638 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1639 auto contact_range =
1640 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1641 tets_skin = subtract(tets_skin, contact_range);
1642 return tets_skin;
1643 };
1644
1645 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1646 Range faces;
1647 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1648 faces, moab::Interface::UNION);
1649 Range trace_faces = subtract(faces, tets_skin);
1650 return trace_faces;
1651 };
1652
1653 auto tets = get_tets();
1654
1655 // remove also contact faces, i.e. that is also kind of hybrid field but
1656 // named but used to enforce contact conditions
1657 auto trace_faces = get_stress_trace_faces(
1658
1659 subtract_blockset("CONTACT",
1660 subtract_boundary_conditions(get_tets_skin()))
1661
1662 );
1663
1664 contactFaces = boost::make_shared<Range>(intersect(
1665 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1667 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1668
1669#ifndef NDEBUG
1670 if (contactFaces->size())
1672 "contact_faces_" +
1673 std::to_string(mField.get_comm_rank()) + ".vtk",
1674 *contactFaces);
1675 if (skeletonFaces->size())
1677 "skeleton_faces_" +
1678 std::to_string(mField.get_comm_rank()) + ".vtk",
1679 *skeletonFaces);
1680#endif
1681
1683
1684 auto add_broken_hdiv_field = [this, meshset,
1685 broken_hdiv_base](const std::string field_name,
1686 const int order) {
1688
1689 const FieldApproximationBase base = broken_hdiv_base;
1690
1691 auto get_side_map_hdiv = [&]() {
1692 return std::vector<
1693
1694 std::pair<EntityType,
1696
1697 >>{
1698
1699 {MBTET,
1700 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1701 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1702 dofs_side_map);
1703 }}
1704
1705 };
1706 };
1707
1709 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1711 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1713 };
1714
1715 auto add_l2_field = [this, meshset](const std::string field_name,
1716 const int order, const int dim) {
1719 MB_TAG_DENSE, MF_ZERO);
1721 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1723 };
1724
1725 auto add_h1_field = [this, meshset](const std::string field_name,
1726 const int order, const int dim) {
1729 MB_TAG_DENSE, MF_ZERO);
1731 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1732 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1733 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1734 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1736 };
1737
1738 auto add_l2_field_by_range = [this](const std::string field_name,
1739 const int order, const int dim,
1740 const int field_dim, Range &&r) {
1743 MB_TAG_DENSE, MF_ZERO);
1744 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1748 };
1749
1750 auto add_bubble_field = [this, meshset](const std::string field_name,
1751 const int order, const int dim) {
1753 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1754 MF_ZERO);
1755 // Modify field
1756 auto field_ptr = mField.get_field_structure(field_name);
1757 auto field_order_table =
1758 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1759 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1760 auto get_cgg_bubble_order_tet = [](int p) {
1761 return NBVOLUMETET_CCG_BUBBLE(p);
1762 };
1763 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1764 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1765 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1766 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1768 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1769 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1771 };
1772
1773 auto add_user_l2_field = [this, meshset](const std::string field_name,
1774 const int order, const int dim) {
1776 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1777 MF_ZERO);
1778 // Modify field
1779 auto field_ptr = mField.get_field_structure(field_name);
1780 auto field_order_table =
1781 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1782 auto zero_dofs = [](int p) { return 0; };
1783 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1784 field_order_table[MBVERTEX] = zero_dofs;
1785 field_order_table[MBEDGE] = zero_dofs;
1786 field_order_table[MBTRI] = zero_dofs;
1787 field_order_table[MBTET] = dof_l2_tet;
1789 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1791 };
1792
1793 if (!skeletonFaces)
1794 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1795 if (!contactFaces)
1796 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1797
1798 auto get_hybridised_disp = [&]() {
1799 auto faces = *skeletonFaces;
1800 auto skin = subtract_boundary_conditions(get_tets_skin());
1801 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1802 faces.merge(intersect(bc.faces, skin));
1803 }
1805 for (auto &bc : *bcSpatialSpringVecPtr) {
1806 faces.merge(intersect(bc.faces, skin));
1807 }
1808 return faces;
1809 };
1810
1811 auto add_spatial_fields = [&]<FieldApproximationBase Base>() {
1813 using Orders = EshelbianCore::FieldOrders<Base>;
1814 CHKERR add_broken_hdiv_field(piolaStress, Orders::stress(spaceOrder));
1815 if (add_bubble) {
1816 CHKERR add_bubble_field(bubbleField, Orders::bubble(spaceOrder), 1);
1817 }
1818 CHKERR add_l2_field(spatialL2Disp, Orders::disp(spaceOrder), 3);
1819 CHKERR add_user_l2_field(rotAxis, Orders::rot(spaceOrder), 3);
1820 for (const auto &field :
1821 physicalEquations->getMaterialFieldDefinitions(*this))
1822 CHKERR add_user_l2_field(field.name, field.order, field.coefficients);
1823 CHKERR add_l2_field_by_range(hybridSpatialDisp, Orders::hybrid(spaceOrder),
1824 2, 3, get_hybridised_disp());
1825 CHKERR add_l2_field_by_range(contactDisp, Orders::hybrid(spaceOrder), 2, 3,
1828 };
1829
1830 CHKERR withFieldOrders(add_spatial_fields);
1831
1832 // spatial displacement
1833 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1834 // material positions
1835 CHKERR add_h1_field(materialH1Positions, materialH1Order, 3);
1836 // The five-coordinate trace-free approximation of H^p is initially zero
1837 // on every volume.
1838 CHKERR add_l2_field(plasticHField, 0,
1839 plasticLogarithmicStretchCoordinateSize);
1840
1841 if (plasticVolume) {
1842 if (!plasticVolumes)
1844 "Plastic volumes have not been resolved by "
1845 "resolveDissipationEntities");
1846 // Delta H^p uses the same basis, so adding the accepted increment
1847 // preserves the trace-free approximation of H^p.
1848 CHKERR add_l2_field_by_range(
1850 plasticLogarithmicStretchCoordinateSize, Range(*plasticVolumes));
1851 // One scalar P0 layout has two deliberately separate stores: mesh field
1852 // data hold committed kappa_n, while vectors on the incremental-control
1853 // DM hold the trial Delta kappa.
1854 CHKERR add_l2_field_by_range(plasticKappaField, 0, SPACE_DIM, 1,
1856 }
1857
1859
1861}
1862
1864 double time) {
1866
1867 Range meshset_ents;
1868 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1869
1870 auto project_ho_geometry = [&](auto field) {
1872 return mField.loop_dofs(field, ent_method);
1873 };
1874 CHKERR project_ho_geometry(materialH1Positions);
1875
1876 auto get_adj_front_edges = [&](auto &front_edges) {
1877 Range front_crack_nodes;
1878 Range crack_front_edges_with_both_nodes_not_at_front;
1879
1880 if (mField.get_comm_rank() == 0) {
1881 auto &moab = mField.get_moab();
1883 moab.get_connectivity(front_edges, front_crack_nodes, true),
1884 "get_connectivity failed");
1885 Range crack_front_edges;
1886 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1887 false, crack_front_edges,
1888 moab::Interface::UNION),
1889 "get_adjacencies failed");
1890 Range crack_front_edges_nodes;
1891 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1892 crack_front_edges_nodes, true),
1893 "get_connectivity failed");
1894 // those nodes are hannging nodes
1895 crack_front_edges_nodes =
1896 subtract(crack_front_edges_nodes, front_crack_nodes);
1897 Range crack_front_edges_with_both_nodes_not_at_front;
1899 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1900 crack_front_edges_with_both_nodes_not_at_front,
1901 moab::Interface::UNION),
1902 "get_adjacencies failed");
1903 // those edges are have one node not at the crack front
1904 crack_front_edges_with_both_nodes_not_at_front = intersect(
1905 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1906 }
1907
1908 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1909 crack_front_edges_with_both_nodes_not_at_front = send_type(
1910 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1911
1912 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1913 boost::make_shared<Range>(
1914 crack_front_edges_with_both_nodes_not_at_front));
1915 };
1916
1917 if ((time - crackingAddTime) > std::numeric_limits<double>::epsilon()) {
1918 crackFaces = boost::make_shared<Range>(
1919 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1920 } else {
1921 crackFaces = boost::make_shared<Range>();
1922 }
1923 frontEdges =
1924 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1925 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1926 frontVertices = front_vertices;
1927 frontAdjEdges = front_adj_edges;
1928
1929 MOFEM_LOG("EP", Sev::inform)
1930 << "Number of crack faces: " << crackFaces->size();
1931 MOFEM_LOG("EP", Sev::inform)
1932 << "Number of front edges: " << frontEdges->size();
1933 MOFEM_LOG("EP", Sev::inform)
1934 << "Number of front vertices: " << frontVertices->size();
1935 MOFEM_LOG("EP", Sev::inform)
1936 << "Number of front adjacent edges: " << frontAdjEdges->size();
1937
1938#ifndef NDEBUG
1939 if (crackingOn) {
1940 auto rank = mField.get_comm_rank();
1941 // CHKERR save_range(mField.get_moab(),
1942 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1943 // meshset_ents);
1945 (boost::format("crack_faces_%d.vtk") % rank).str(),
1946 *crackFaces);
1948 (boost::format("front_edges_%d.vtk") % rank).str(),
1949 *frontEdges);
1950 // CHKERR save_range(mField.get_moab(),
1951 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1952 // *frontVertices);
1953 // CHKERR save_range(mField.get_moab(),
1954 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1955 // *frontAdjEdges);
1956 }
1957#endif // NDEBUG
1958
1959 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1961 auto &moab = mField.get_moab();
1962
1963 double eps = 1;
1964 double beta = 0;
1965 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1966 PETSC_NULLPTR);
1967 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1968 eps -= beta;
1969
1970 auto field_blas = mField.getInterface<FieldBlas>();
1971 auto lambda =
1972 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1974 FTENSOR_INDEX(3, i);
1975 FTENSOR_INDEX(3, j);
1976
1977 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1978 if (nb_dofs == 0) {
1980 }
1981
1982#ifndef NDEBUG
1983 if (field_entity_ptr->getNbOfCoeffs() != 3)
1985 "Expected 3 coefficients per edge");
1986 if (nb_dofs % 3 != 0)
1988 "Expected multiple of 3 coefficients per edge");
1989#endif // NDEBUG
1990
1991 auto get_conn = [&]() {
1992 int num_nodes;
1993 const EntityHandle *conn;
1994 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1995 num_nodes, false);
1996 return std::make_pair(conn, num_nodes);
1997 };
1998
1999 auto get_dir = [&](auto &&conn_p) {
2000 auto [conn, num_nodes] = conn_p;
2001 double coords[6];
2002 CHKERR moab.get_coords(conn, num_nodes, coords);
2003 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
2004 coords[4] - coords[1],
2005 coords[5] - coords[2]};
2006 return t_edge_dir;
2007 };
2008
2009 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
2010 auto [conn, num_nodes] = conn_p;
2011 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
2012 if (front_vertices.find(conn[0]) != front_vertices.end()) {
2013 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
2014 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
2015 t_singularity_dof(i) = t_edge_dir(i) * eps;
2016 }
2017 return t_singularity_dof;
2018 };
2019
2020 auto t_singularity_dof =
2021 get_singularity_dof(get_conn(), get_dir(get_conn()));
2022
2023 auto field_data = field_entity_ptr->getEntFieldData();
2025 &field_data[0], &field_data[1], &field_data[2]};
2026
2027 t_dof(i) = t_singularity_dof(i);
2028 ++t_dof;
2029 for (auto n = 1; n < field_data.size() / 3; ++n) {
2030 t_dof(i) = 0;
2031 ++t_dof;
2032 }
2033
2035 };
2036
2037 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
2038 &front_adj_edges);
2039
2041 };
2042
2043 if (setSingularity)
2044 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
2045
2047}
2048
2051#ifdef INCLUDE_MBCOUPLER
2052
2053 double toler = 5.e-10;
2054 MOFEM_LOG_CHANNEL("WORLD");
2055 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
2057 MOFEM_LOG("WORLD", Sev::verbose)
2058 << "No source mesh specified. Skipping projection";
2060 }
2061 MOFEM_LOG("WORLD", Sev::inform)
2062 << "Projecting from source mesh: " << meshTransferSourceMeshFileName;
2063 MOFEM_LOG("WORLD", Sev::verbose)
2064 << "Interpolation Stress tag name: " << internalStressTagName;
2065 MOFEM_LOG("WORLD", Sev::verbose) << "Interpolation Young's modulus tag name: "
2067 MOFEM_LOG("WORLD", Sev::verbose)
2068 << "Interpolation order: " << meshTransferInterpOrder;
2069 MOFEM_LOG("WORLD", Sev::verbose) << "Using hybrid interpolation: "
2070 << (meshTransferHybridInterp ? "yes" : "no");
2071
2072 auto &moab = mField.get_moab();
2073
2074 // check if tag exists
2075 for (const auto &tag_name : listTagsToProject) {
2076 Tag old_interp_tag;
2077 auto rval_check_tag = moab.tag_get_handle(tag_name.c_str(), old_interp_tag);
2078 if (rval_check_tag == MB_SUCCESS) {
2079 MOFEM_LOG("WORLD", Sev::inform)
2080 << "Deleting existing tag on target mesh: " << tag_name;
2081 CHKERR moab.tag_delete(old_interp_tag);
2082 }
2083 }
2084 // make a size-1 communicator for the coupler (rank 0 only)
2085 int world_rank = -1, world_size = -1;
2086 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
2087 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
2088
2089 Range original_meshset_ents;
2090 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
2091
2092 MPI_Comm comm_coupler;
2093 if (world_rank == 0) {
2094 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
2095 } else {
2096 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
2097 }
2098
2099 // build a separate ParallelComm for the coupler (rank 0 only)
2100 ParallelComm *pcomm0 = nullptr;
2101 int pcomm0_id = -1;
2102 if (world_rank == 0) {
2103 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
2104 }
2105
2106 Coupler::Method method;
2107 switch (meshTransferInterpOrder) {
2108 case 0:
2109 method = Coupler::CONSTANT;
2110 break;
2111 case 1:
2112 method = Coupler::LINEAR_FE;
2113 break;
2114 default:
2115 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2116 "Unsupported interpolation order");
2117 }
2118
2119 int nprocs, rank;
2120 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
2121 CHKERRQ(ierr);
2122 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
2123 CHKERRQ(ierr);
2124
2125 // std::string read_opts, write_opts;
2126 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
2127 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
2128 // if (world_size > 1)
2129 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
2130 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
2131
2132 // create target mesh from existing meshset
2133 EntityHandle target_root;
2134 CHKERR moab.create_meshset(MESHSET_SET, target_root);
2135 MOFEM_LOG("WORLD", Sev::inform)
2136 << "Creating target mesh from existing meshset";
2137 Range target_meshset_ents;
2138 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
2139 CHKERR moab.add_entities(target_root, target_meshset_ents);
2140
2141 // variables for tags to be broadcast later
2142 std::vector<Tag> interp_tags;
2143 std::vector<int> tag_length;
2144 std::vector<DataType> dtype;
2145 std::vector<TagType> storage;
2146
2147 // load source mesh
2148 Range targ_verts, targ_elems;
2149 if (world_rank == 0) {
2150 EntityHandle source_root;
2151 CHKERR moab.create_meshset(MESHSET_SET, source_root);
2152
2153 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
2154 auto rval_source_mesh = moab.load_file(
2155 meshTransferSourceMeshFileName.c_str(), &source_root, "");
2156 if (rval_source_mesh != MB_SUCCESS) {
2157 MOFEM_LOG("WORLD", Sev::warning) << "Error loading source mesh file: "
2159 }
2160 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
2161
2162 Range src_elems;
2163 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
2164
2165 EntityHandle part_set;
2166 CHKERR pcomm0->create_part(part_set);
2167 CHKERR moab.add_entities(part_set, src_elems);
2168
2169 Range src_elems_part;
2170 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
2171
2172 for (const auto &iterp_tag_name : listTagsToProject) {
2173 std::string tag_to_use = iterp_tag_name;
2174
2175 Tag interp_tag;
2176 CHKERR moab.tag_get_handle(tag_to_use.c_str(), interp_tag);
2177
2178 int interp_tag_len;
2179 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
2180
2181 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
2182 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2183 "Unsupported interpolation tag length: %d", interp_tag_len);
2184 }
2185
2186 // store tag info for later broadcast
2187 tag_length.push_back(interp_tag_len);
2188 dtype.push_back(DataType());
2189 storage.push_back(TagType());
2190 interp_tags.push_back(interp_tag);
2191 CHKERR moab.tag_get_data_type(interp_tag, dtype.back());
2192 CHKERR moab.tag_get_type(interp_tag, storage.back());
2193
2194 // coupler is collective
2195 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
2196
2197 std::vector<double> vpos; // the positions we are interested in
2198 int num_pts = 0;
2199
2200 Range tmp_verts;
2201
2202 // First get all vertices adj to partition entities in target mesh
2203 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
2204
2205 if (meshTransferInterpOrder == 0) {
2206 targ_verts = targ_elems;
2207 } else {
2208 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
2209 moab::Interface::UNION);
2210 }
2211
2212 // Then get non-owned verts and subtract
2213 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
2214 targ_verts = subtract(targ_verts, tmp_verts);
2215
2216 // get position of these entities; these are the target points
2217 num_pts = (int)targ_verts.size();
2218 vpos.resize(3 * targ_verts.size());
2219 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2220
2221 // Locate those points in the source mesh
2222 boost::shared_ptr<TupleList> tl_ptr;
2223 tl_ptr = boost::make_shared<TupleList>();
2224 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2225 false);
2226
2227 // If some points were not located, we need to process them
2228 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
2229 std::vector<double> &vpos,
2230 Range &missing_verts) {
2232 int missing_pts_num = 0;
2233 int i = 0;
2234 auto vit = targ_verts.begin();
2235 for (; vit != targ_verts.end(); i++) {
2236 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
2237 missing_verts.insert(*vit);
2238 vit = targ_verts.erase(vit);
2239 missing_pts_num++;
2240 } else {
2241 vit++;
2242 }
2243 }
2244
2245 int missing_pts_num_global = 0;
2246 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
2247 // MPI_SUM, pcomm0);
2248 if (missing_pts_num_global) {
2249 MOFEM_LOG("WORLD", Sev::warning)
2250 << missing_pts_num_global
2251 << " points in target mesh were not located in source mesh. ";
2252 }
2253
2254 if (missing_pts_num) {
2255 num_pts = (int)targ_verts.size();
2256 vpos.resize(3 * targ_verts.size());
2257 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2258 tl_ptr->reset();
2259 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2260 false);
2261 }
2263 };
2264
2265 Range missing_verts;
2266 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
2267
2268 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
2269 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
2270
2271 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
2272
2273 Tag scalar_tag, adj_count_tag;
2274 double def_scl = 0;
2275 string scalar_tag_name = string(tag_to_use) + "_COMP";
2276 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2277 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2278 &def_scl);
2279
2280 string adj_count_tag_name = "ADJ_COUNT";
2281 double def_adj = 0;
2282 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2283 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2284 &def_adj);
2285
2286 // MBCoupler functionality supports only scalar tags. For the case of
2287 // vector or tensor tags we need to save each component as a scalar tag
2288 auto create_scalar_tags = [&](const Range &src_elems,
2289 const std::vector<double> &source_data,
2290 int itag) {
2292
2293 std::vector<double> source_data_scalar(src_elems.size());
2294 // Populate source_data_scalar
2295 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
2296 source_data_scalar[ielem] =
2297 source_data[itag + ielem * interp_tag_len];
2298 }
2299
2300 // Set data on the scalar tag
2301 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
2302
2303 if (meshTransferInterpOrder == 1) {
2304 // Linear interpolation: compute average value of data on vertices
2305 Range src_verts;
2306 CHKERR moab.get_connectivity(src_elems, src_verts, true);
2307
2308 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
2309 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
2310
2311 for (auto &tet : src_elems) {
2312 double tet_data = 0;
2313 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
2314
2315 Range adj_verts;
2316 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
2317
2318 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
2319 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
2320
2321 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2322 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
2323 &adj_vert_count[0]);
2324
2325 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
2326 adj_vert_data[ivert] += tet_data;
2327 adj_vert_count[ivert] += 1;
2328 }
2329
2330 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2331 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
2332 &adj_vert_count[0]);
2333 }
2334
2335 // Reduce tags for the parallel case
2336 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
2337 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
2338
2339 std::vector<double> src_vert_data(src_verts.size(), 0.0);
2340 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
2341
2342 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
2343 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
2344 &src_vert_adj_count[0]);
2345
2346 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
2347 src_vert_data[ivert] /= src_vert_adj_count[ivert];
2348 }
2349 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
2350 }
2352 };
2353
2354 MOFEM_LOG("WORLD", Sev::inform)
2355 << "Performing interpolation for tag: " << tag_to_use;
2356 MOFEM_LOG("WORLD", Sev::inform)
2357 << "Number of target points to interpolate: " << num_pts;
2358 MOFEM_LOG("WORLD", Sev::inform)
2359 << "Interpolation method: "
2360 << (method == Coupler::CONSTANT ? "constant" : "linear FE");
2361 MOFEM_LOG("WORLD", Sev::inform)
2362 << "Number of components in tag: " << interp_tag_len;
2363
2364 MOFEM_LOG("WORLD", Sev::inform)
2365 << "Source tag data range: ["
2366 << *std::min_element(source_data.begin(), source_data.end()) << ", "
2367 << *std::max_element(source_data.begin(), source_data.end()) << "]";
2368
2369 for (int itag = 0; itag < interp_tag_len; itag++) {
2370
2371 CHKERR create_scalar_tags(src_elems, source_data, itag);
2372
2373 std::vector<double> target_data_scalar(num_pts, 0.0);
2374 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
2375 tl_ptr.get());
2376
2377 for (int ielem = 0; ielem < num_pts; ielem++) {
2378 target_data[itag + ielem * interp_tag_len] =
2379 target_data_scalar[ielem];
2380 }
2381 }
2382
2383 // Use original tag
2384 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2385
2386 if (missing_verts.size() && (meshTransferInterpOrder == 1) &&
2388 MOFEM_LOG("WORLD", Sev::warning)
2389 << "Using hybrid interpolation for "
2390 "missing points in the target mesh.";
2391 Range missing_adj_elems;
2392 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2393 moab::Interface::UNION);
2394
2395 int num_adj_elems = (int)missing_adj_elems.size();
2396 std::vector<double> vpos_adj_elems;
2397
2398 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2399 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2400
2401 // Locate those points in the source mesh
2402 tl_ptr->reset();
2403 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2404 tl_ptr.get(), false);
2405
2406 Range missing_tets;
2407 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2408 vpos_adj_elems, missing_tets);
2409 if (missing_tets.size()) {
2410 MOFEM_LOG("WORLD", Sev::warning)
2411 << missing_tets.size()
2412 << " points in target mesh were not located in source mesh. ";
2413 }
2414
2415 std::vector<double> target_data_adj_elems(
2416 interp_tag_len * num_adj_elems, 0.0);
2417
2418 for (int itag = 0; itag < interp_tag_len; itag++) {
2419 CHKERR create_scalar_tags(src_elems, source_data, itag);
2420
2421 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2422 CHKERR mbc.interpolate(method, scalar_tag_name,
2423 &target_data_adj_elems_scalar[0],
2424 tl_ptr.get());
2425
2426 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2427 target_data_adj_elems[itag + ielem * interp_tag_len] =
2428 target_data_adj_elems_scalar[ielem];
2429 }
2430 }
2431
2432 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2433 &target_data_adj_elems[0]);
2434
2435 // FIXME: add implementation for parallel case
2436 for (auto &vert : missing_verts) {
2437 Range adj_elems;
2438 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2439 moab::Interface::UNION);
2440
2441 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2442 0.0);
2443 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2444
2445 std::vector<double> vert_data(interp_tag_len, 0.0);
2446 for (int itag = 0; itag < interp_tag_len; itag++) {
2447 for (int i = 0; i < adj_elems.size(); i++) {
2448 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2449 }
2450 vert_data[itag] /= adj_elems.size();
2451 }
2452 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2453 }
2454 }
2455
2456 CHKERR moab.tag_delete(scalar_tag);
2457 CHKERR moab.tag_delete(adj_count_tag);
2458 }
2459
2460 // delete source mesh after projection but keep the tags info for broadcast
2461 Range src_mesh_ents;
2462 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2463 CHKERR moab.delete_entities(&source_root, 1);
2464 CHKERR moab.delete_entities(src_mesh_ents);
2465 CHKERR moab.delete_entities(&part_set, 1);
2466 }
2467
2468 // broadcast tag info to other processors
2469 int tag_size = tag_length.size();
2470 MPI_Bcast(&tag_size, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2471 if (rank != 0) {
2472 interp_tags.resize(tag_size);
2473 tag_length.resize(tag_size);
2474 dtype.resize(tag_size);
2475 storage.resize(tag_size);
2476 }
2477 MPI_Bcast(interp_tags.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2478 MPI_Bcast(tag_length.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2479 MPI_Bcast(dtype.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2480 MPI_Bcast(storage.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2481
2482 // create new tag on other processors
2483 // loop over tag index to support multiple tags projection in one run
2484
2485 for (size_t index = 0; index < interp_tags.size(); index++) {
2486 // check if tag exists first
2487 if (world_rank) {
2488 Tag old_interp_tag;
2489 auto rval_check_tag =
2490 moab.tag_get_handle(listTagsToProject[index].c_str(), old_interp_tag);
2491 if (rval_check_tag == MB_SUCCESS) {
2492 MOFEM_LOG("WORLD", Sev::verbose)
2493 << "Deleting existing tag on target mesh (post-projection): "
2494 << listTagsToProject[index];
2495 CHKERR moab.tag_delete(old_interp_tag);
2496 }
2497 }
2498 Tag interp_tag_all;
2499 unsigned flags =
2500 MB_TAG_CREAT | storage[index]; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2501 std::vector<double> def_val(tag_length[index], 0.);
2502 auto rval = moab.tag_get_handle(listTagsToProject[index].c_str(),
2503 tag_length[index], dtype[index],
2504 interp_tag_all, flags, def_val.data());
2505 if (rval != MB_SUCCESS && world_rank) {
2506 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2507 "Unable to create projection tag %s",
2508 listTagsToProject[index].c_str());
2509 }
2510
2511 MPI_Barrier(PETSC_COMM_WORLD);
2512
2513 // exchange data for all entity types across all processors
2514 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2515 mField.get_comm(), mField.get_moab(), 0, tag_length[index],
2516 Sev::inform);
2517 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2518 mField.get_comm(), mField.get_moab(), 3, tag_length[index],
2519 Sev::inform);
2520
2522 mField.get_moab(), vertex_exchange, interp_tag_all);
2524 mField.get_moab(), volume_exchange, interp_tag_all);
2525 }
2526
2527 // delete target meshset but not the entities
2528 CHKERR moab.delete_entities(&target_root, 1);
2529
2530#endif // INCLUDE_MBCOUPLER
2532}
2533
2535 const bool add_bubble) {
2537
2538 // set finite element fields
2539 auto add_field_to_fe = [this](const std::string fe,
2540 const std::string field_name) {
2546 };
2547
2552
2553 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2554 if (add_bubble) {
2555 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2556 }
2557 for (const auto &field : physicalEquations->getMaterialFields(*this))
2558 CHKERR add_field_to_fe(elementVolumeName, field);
2559 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2560 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2561 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2562 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2566
2568 CHKERR add_field_to_fe(elementVolumeName, plasticFlowField);
2569 CHKERR add_field_to_fe(elementVolumeName, plasticKappaField);
2570 }
2571
2572 // build finite elements data structures
2574 }
2575
2577}
2578
2580EshelbianCore::addBoundaryFiniteElement(const EntityHandle meshset) {
2582
2583 Range meshset_ents;
2584 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2585
2586 auto set_fe_adjacency = [&](auto fe_name) {
2589 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2592 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2594 };
2595
2596 // set finite element fields
2597 auto add_field_to_fe = [this](const std::string fe,
2598 const std::string field_name) {
2607 };
2608
2610
2611 Range natural_bc_elements;
2612 if (bcSpatialDispVecPtr) {
2613 for (auto &v : *bcSpatialDispVecPtr) {
2614 natural_bc_elements.merge(v.faces);
2615 }
2616 }
2618 for (auto &v : *bcSpatialRotationVecPtr) {
2619 natural_bc_elements.merge(v.faces);
2620 }
2621 }
2623 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2624 natural_bc_elements.merge(v.faces);
2625 }
2626 }
2628 for (auto &v : *bcSpatialSpringVecPtr) {
2629 natural_bc_elements.merge(v.faces);
2630 }
2631 }
2634 natural_bc_elements.merge(v.faces);
2635 }
2636 }
2638 for (auto &v : *bcSpatialTractionVecPtr) {
2639 natural_bc_elements.merge(v.faces);
2640 }
2641 }
2643 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2644 natural_bc_elements.merge(v.faces);
2645 }
2646 }
2648 for (auto &v : *bcSpatialPressureVecPtr) {
2649 natural_bc_elements.merge(v.faces);
2650 }
2651 }
2652 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2653
2655 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2657 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2658 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2659 CHKERR set_fe_adjacency(naturalBcElement);
2661 }
2662
2663 auto get_skin = [&](auto &body_ents) {
2664 Skinner skin(&mField.get_moab());
2665 Range skin_ents;
2666 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2667 return skin_ents;
2668 };
2669
2670 auto filter_true_skin = [&](auto &&skin) {
2671 Range boundary_ents;
2672 ParallelComm *pcomm =
2673 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2674 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2675 PSTATUS_NOT, -1, &boundary_ents);
2676 return boundary_ents;
2677 };
2678
2680
2681 Range body_ents;
2682 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2683 body_ents);
2684 auto skin = filter_true_skin(get_skin(body_ents));
2685
2693 contactDisp);
2697 }
2698
2700 if (contactFaces) {
2701 MOFEM_LOG("EP", Sev::inform)
2702 << "Contact elements " << contactFaces->size();
2706 CHKERR add_field_to_fe(contactElement, piolaStress);
2707 CHKERR add_field_to_fe(contactElement, contactDisp);
2708 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2709 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2710 CHKERR set_fe_adjacency(contactElement);
2712 }
2713 }
2714
2716 if (!skeletonFaces)
2717 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2718 MOFEM_LOG("EP", Sev::inform)
2719 << "Skeleton elements " << skeletonFaces->size();
2723 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2724 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2725 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2726 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2727 CHKERR set_fe_adjacency(skeletonElement);
2729 }
2730
2732}
2733
2735 const EntityHandle meshset) {
2737
2738 // find adjacencies between finite elements and dofs
2740
2741 // Create coupled problem
2742 dM = createDM(mField.get_comm(), "DMMOFEM");
2743 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2744 BitRefLevel().set());
2745 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2746 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2752
2753 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2754 CHKERR DMSetUp(dM);
2755 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2756
2757 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2759 for (int d : {0, 1, 2}) {
2760 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2762 ->getSideDofsOnBrokenSpaceEntities(
2763 dofs_to_remove, prb_name, ROW, piolaStress,
2765 // remove piola dofs, i.e. traction free boundary
2766 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2767 dofs_to_remove);
2768 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2769 dofs_to_remove);
2770 }
2772 };
2773 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2774
2775 // Create elastic sub-problem
2776 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2777 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2784 for (const auto &field : physicalEquations->getMaterialFields(*this))
2795 CHKERR DMSetUp(dmElastic);
2796
2797 dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2798 CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2808 for (const auto &field : physicalEquations->getMaterialFields(*this))
2815 CHKERR DMSetUp(dmMaterial);
2816
2819 CHKERR DMMoFEMCreateSubDM(dmIncrementalOptimization, dM, "INCREMENTAL_OPTIMIZATION");
2835 CHKERR VecZeroEntries(incrementalTrialControl);
2836 }
2837
2838 auto set_zero_block = [&]() {
2840 const auto problems_manager = mField.getInterface<ProblemsManager>();
2841 auto add_empty_pair = [&](const std::string &row,
2842 const std::string &col) {
2844 if (mField.check_field(row) && mField.check_field(col)) {
2845 CHKERR problems_manager->addFieldToEmptyFieldBlocks("ELASTIC_PROBLEM",
2846 row, col);
2847 if (row != col)
2848 CHKERR problems_manager->addFieldToEmptyFieldBlocks(
2849 "ELASTIC_PROBLEM", col, row);
2850 }
2852 };
2853 for (const auto &[row, col] :
2854 physicalEquations->getMaterialEmptyBlocks(*this))
2855 CHKERR add_empty_pair(row, col);
2856 CHKERR add_empty_pair(spatialL2Disp, rotAxis);
2857 CHKERR add_empty_pair(spatialL2Disp, bubbleField);
2858
2861 };
2862
2863 auto set_section = [&]() {
2865 PetscSection section;
2866 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2867 &section);
2868 CHKERR DMSetSection(dmElastic, section);
2869 CHKERR DMSetGlobalSection(dmElastic, section);
2870 CHKERR PetscSectionDestroy(&section);
2872 };
2873
2874 CHKERR set_zero_block();
2875 CHKERR set_section();
2876
2877 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2878 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2884 CHKERR DMSetUp(dmPrjSpatial);
2885
2886 // CHKERR mField.getInterface<BcManager>()
2887 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2888 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2889
2891}
2892
2893BcDisp::BcDisp(std::string name, std::vector<double> attr, Range faces,
2894 std::string load_history_file)
2895 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2896 vals.resize(3, false);
2897 flags.resize(3, false);
2898 for (int ii = 0; ii != 3; ++ii) {
2899 vals[ii] = attr[ii];
2900 flags[ii] = static_cast<int>(attr[ii + 3]);
2901 }
2902
2903 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp " << name;
2904 MOFEM_LOG("EP", Sev::inform)
2905 << "Add BCDisp vals " << vals[0] << " " << vals[1] << " " << vals[2];
2906 MOFEM_LOG("EP", Sev::inform)
2907 << "Add BCDisp flags " << flags[0] << " " << flags[1] << " " << flags[2];
2908 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp nb. of faces " << faces.size();
2909}
2910
2911BcRot::BcRot(std::string name, std::vector<double> attr, Range faces,
2912 std::string load_history_file)
2913 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2914 vals.resize(attr.size(), false);
2915 for (int ii = 0; ii != attr.size(); ++ii) {
2916 vals[ii] = attr[ii];
2917 }
2918 theta = attr[3];
2919}
2920
2921TractionBc::TractionBc(std::string name, std::vector<double> attr, Range faces,
2922 std::string load_history_file)
2923 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2924 vals.resize(3, false);
2925 flags.resize(3, false);
2926 for (int ii = 0; ii != 3; ++ii) {
2927 vals[ii] = attr[ii];
2928 flags[ii] = static_cast<int>(attr[ii + 3]);
2929 }
2930
2931 MOFEM_LOG("EP", Sev::inform) << "Add BCForce " << name;
2932 MOFEM_LOG("EP", Sev::inform)
2933 << "Add BCForce vals " << vals[0] << " " << vals[1] << " " << vals[2];
2934 MOFEM_LOG("EP", Sev::inform)
2935 << "Add BCForce flags " << flags[0] << " " << flags[1] << " " << flags[2];
2936 MOFEM_LOG("EP", Sev::inform) << "Add BCForce nb. of faces " << faces.size();
2937}
2938
2940 std::vector<double> attr,
2941 Range faces,
2942 std::string load_history_file)
2943 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2944
2945 blockName = name;
2946 if (attr.size() < 1) {
2948 "Wrong size of normal displacement BC");
2949 }
2950
2951 val = attr[0];
2952
2953 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc " << name;
2954 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc val " << val;
2955 MOFEM_LOG("EP", Sev::inform)
2956 << "Add NormalDisplacementBc nb. of faces " << faces.size();
2957}
2958
2959SpringBc::SpringBc(std::string name, std::vector<double> attr, Range faces)
2960 : blockName(name), faces(faces) {
2961
2962 blockName = name;
2963 if (attr.size() < 2) {
2965 "Wrong size of spring BC attributes");
2966 }
2967
2968 normalStiffness = attr[0];
2969 tangentialStiffness = attr[1];
2970
2971 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc " << name;
2972 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc kn " << normalStiffness;
2973 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc kt " << tangentialStiffness;
2974 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc nb. of faces " << faces.size();
2975}
2976
2977PressureBc::PressureBc(std::string name, std::vector<double> attr, Range faces,
2978 std::string load_history_file)
2979 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2980
2981 blockName = name;
2982 if (attr.size() < 1) {
2984 "Wrong size of normal displacement BC");
2985 }
2986
2987 val = attr[0];
2988
2989 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc " << name;
2990 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc val " << val;
2991 MOFEM_LOG("EP", Sev::inform)
2992 << "Add PressureBc nb. of faces " << faces.size();
2993}
2994
2995ExternalStrain::ExternalStrain(std::string name, std::vector<double> attr,
2996 Range ents, std::string load_history_file)
2997 : blockName(name), loadHistoryFile(load_history_file), ents(ents) {
2998
2999 blockName = name;
3000 if (attr.size() < 2) {
3002 "Wrong size of external strain attribute");
3003 }
3004
3005 val = attr[0];
3006 bulkModulusK = attr[1];
3007
3008 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain " << name;
3009 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain val " << val;
3010 MOFEM_LOG("EP", Sev::inform)
3011 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
3012 MOFEM_LOG("EP", Sev::inform)
3013 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
3014 MOFEM_LOG("EP", Sev::inform)
3015 << "Add ExternalStrain nb. of tets " << ents.size();
3016}
3017
3019 std::string name, std::vector<double> attr, Range faces,
3020 std::string load_history_file)
3021 : blockName(name), faces(faces) {
3022 (void)load_history_file;
3023 if (attr.size() < 3) {
3025 "Wrong size of analytical displacement BC");
3026 }
3027
3028 flags.resize(3, false);
3029 for (int ii = 0; ii != 3; ++ii) {
3030 flags[ii] = attr[ii];
3031 }
3032
3033 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalDisplacementBc " << name;
3034 MOFEM_LOG("EP", Sev::inform)
3035 << "Add AnalyticalDisplacementBc flags " << flags[0] << " " << flags[1]
3036 << " " << flags[2];
3037 MOFEM_LOG("EP", Sev::inform)
3038 << "Add AnalyticalDisplacementBc nb. of faces " << faces.size();
3039}
3040
3042 std::vector<double> attr,
3043 Range faces,
3044 std::string load_history_file)
3045 : blockName(name), faces(faces) {
3046 (void)load_history_file;
3047 flags.resize(3, false);
3048 for (int ii = 0; ii != 3; ++ii) {
3049 flags[ii] = attr.size() < 3 ? 1 : attr[ii];
3050 }
3051
3052 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc " << name;
3053 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc flags " << flags[0]
3054 << " " << flags[1] << " " << flags[2];
3055 MOFEM_LOG("EP", Sev::inform)
3056 << "Add AnalyticalTractionBc nb. of faces " << faces.size();
3057}
3058
3060EshelbianCore::getTractionFreeBc(const EntityHandle meshset,
3061 boost::shared_ptr<TractionFreeBc> &bc_ptr,
3062 const std::string contact_set_name) {
3064
3065 // get skin from all tets
3066 Range tets;
3067 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
3068 Range tets_skin_part;
3069 Skinner skin(&mField.get_moab());
3070 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
3071 ParallelComm *pcomm =
3072 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
3073 Range tets_skin;
3074 CHKERR pcomm->filter_pstatus(tets_skin_part,
3075 PSTATUS_SHARED | PSTATUS_MULTISHARED,
3076 PSTATUS_NOT, -1, &tets_skin);
3077
3078 bc_ptr->resize(3);
3079 for (int dd = 0; dd != 3; ++dd)
3080 (*bc_ptr)[dd] = tets_skin;
3081
3082 // Do not remove dofs on which traction is applied
3083 if (bcSpatialDispVecPtr)
3084 for (auto &v : *bcSpatialDispVecPtr) {
3085 if (v.flags[0])
3086 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3087 if (v.flags[1])
3088 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3089 if (v.flags[2])
3090 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3091 }
3092
3093 // Do not remove dofs on which rotation is applied
3094 if (bcSpatialRotationVecPtr)
3095 for (auto &v : *bcSpatialRotationVecPtr) {
3096 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3097 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3098 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3099 }
3100
3101 if (bcSpatialNormalDisplacementVecPtr)
3102 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
3103 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3104 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3105 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3106 }
3107
3108 if (bcSpatialAnalyticalDisplacementVecPtr)
3109 for (auto &v : *bcSpatialAnalyticalDisplacementVecPtr) {
3110 if (v.flags[0])
3111 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3112 if (v.flags[1])
3113 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3114 if (v.flags[2])
3115 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3116 }
3117
3118 if (bcSpatialTractionVecPtr)
3119 for (auto &v : *bcSpatialTractionVecPtr) {
3120 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3121 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3122 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3123 }
3124
3125 if (bcSpatialSpringVecPtr)
3126 for (auto &v : *bcSpatialSpringVecPtr) {
3127 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3128 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3129 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3130 }
3131
3132 if (bcSpatialAnalyticalTractionVecPtr)
3133 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
3134 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3135 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3136 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3137 }
3138
3139 if (bcSpatialPressureVecPtr)
3140 for (auto &v : *bcSpatialPressureVecPtr) {
3141 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3142 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3143 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3144 }
3145
3146 // remove contact
3147 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
3148 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
3149 Range faces;
3150 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
3151 true);
3152 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
3153 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
3154 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
3155 }
3156
3158}
3159
3160/** Add the direct P0 plastic increment to the committed logarithmic stretch. */
3162 OpApplyPlasticFlowIncrement(boost::shared_ptr<DataAtIntegrationPts> data_ptr)
3163 : VolUserDataOperator(NOSPACE, OPSPACE), dataAtPts(std::move(data_ptr)) {
3164 if (!dataAtPts)
3167 "Plastic-flow increment operator has a null integration-point "
3168 "data pointer");
3169 }
3170
3171 MoFEMErrorCode doWork(int, EntityType, EntData &) override {
3173 const int nb_integration_pts = getGaussPts().size2();
3174 auto t_h_p = dataAtPts->getFTensorPlasticH(nb_integration_pts);
3176 auto get_flow = MatrixSizeHelper<
3178 *dataAtPts->getPlasticFlow(), nb_integration_pts);
3179 auto t_flow = get_flow();
3181 for (int gg = 0; gg != nb_integration_pts; ++gg) {
3182 t_h_p(i, j) += t_flow(i, j);
3183 ++t_h_p;
3184 ++t_flow;
3185 }
3187 }
3188
3189private:
3190 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
3191};
3192
3194 const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates,
3195 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
3196 const bool add_bubble) {
3198
3199 auto bubble_cache =
3200 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
3201 fe->getUserPolynomialBase() =
3202 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
3203 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3204 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
3205
3206 // set integration rule
3207 fe->getRuleHook = [](int, int, int) { return -1; };
3208 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
3209 vol_rule, bubble_cache);
3210
3211 if (!dataAtPts) {
3212 dataAtPts =
3213 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
3214 }
3215 dataAtPts->physicsPtr = physicalEquations;
3216
3217 // calculate fields values
3218 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3219 piolaStress, dataAtPts->getApproxPAtPts()));
3220 if (add_bubble) {
3221 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
3222 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
3223 }
3224 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
3225 piolaStress, dataAtPts->getDivPAtPts()));
3226 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3227 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3228
3229 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
3230 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3231 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
3232 CHKERR physicalEquations->pushMaterialFields(
3233 *this, fe->getOpPtrVector(), dataAtPts, PhysicalEquations::PREVIOUS);
3234
3235 // Stress-to-stretch recovery uses the shared constitutive scratch and
3236 // tangent storage in DataAtIntegrationPts. Recover the current state last so
3237 // the Jacobian operators consume the tangent evaluated at the current P.
3238 CHKERR physicalEquations->pushMaterialFields(*this, fe->getOpPtrVector(),
3239 dataAtPts);
3240
3241 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3242 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3243 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3244 rotAxis, dataAtPts->getRotAxisGradAtPts(), MBTET));
3245 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3246 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3247
3248 // H1 displacements
3249 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3250 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3251 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3252 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3253
3254 // velocities
3255 if (calc_rates) {
3256 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3257 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
3258 CHKERR physicalEquations->pushMaterialRates(*this, fe->getOpPtrVector(),
3259 dataAtPts);
3260 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3261 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
3262 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
3263 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
3264
3265 // acceleration
3266 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3267 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
3268 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
3269 }
3270 }
3271
3272 // calculate other derived quantities
3274 fe->getOpPtrVector(), plasticHField, dataAtPts->getPlasticH(), MBTET);
3275 if (plasticVolume && dmIncrementalOptimization && incrementalTrialControl) {
3277 fe->getOpPtrVector(), plasticFlowField, dataAtPts->getPlasticFlow(),
3278 MBTET, dmIncrementalOptimization, incrementalTrialControl);
3279 fe->getOpPtrVector().push_back(new OpApplyPlasticFlowIncrement(dataAtPts));
3280 }
3281 fe->getOpPtrVector().push_back(
3283
3284 // evaluate integration points
3285 CHKERR physicalEquations->pushMaterialEvaluation(*this, fe->getOpPtrVector(),
3286 dataAtPts, do_rhs, do_lhs);
3287
3289}
3290
3292 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3294
3295 CHKERR physicalEquations->pushMaterialTangent(*this, fe_lhs->getOpPtrVector(),
3296 dataAtPts);
3297
3298 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3299 spatialL2Disp, piolaStress, dataAtPts, true));
3300 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3301 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3302
3303 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3304 piolaStress, rotAxis, dataAtPts,
3305 symmetrySelector == SYMMETRIC ? true : false));
3306 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3307 bubbleField, rotAxis, dataAtPts,
3308 symmetrySelector == SYMMETRIC ? true : false));
3309
3310 if (symmetrySelector > SYMMETRIC) {
3311 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3312 rotAxis, piolaStress, dataAtPts, false));
3313 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3314 rotAxis, bubbleField, dataAtPts, false));
3315 }
3316 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3317 rotAxis, rotAxis, dataAtPts, alphaR, alphaOmega, alphaViscousR,
3318 alphaViscousOmega));
3319
3321}
3322
3324 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3326 CHKERR pushPiolaStressGramOps(fe_lhs);
3327 fe_lhs->getOpPtrVector().push_back(
3328 new OpStressGram_dBubble_dP(bubbleField, piolaStress, dataAtPts));
3329 fe_lhs->getOpPtrVector().push_back(
3330 new OpStressGram_dBubble_dBubble(bubbleField, bubbleField));
3332}
3333
3335 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3337 fe_lhs->getOpPtrVector().push_back(
3338 new OpStressGram_dP_dP(piolaStress, piolaStress));
3340}
3341
3343 const int tag, const bool add_elastic, const bool add_material,
3344 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
3345 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
3347
3348 CHKERR physicalEquations->checkSetup(*this);
3349
3350 auto local_tau_sacale = boost::make_shared<double>(1.0);
3351 using BoundaryEle =
3353 using BdyEleOp = BoundaryEle::UserDataOperator;
3354 struct OpSetTauScale : public BdyEleOp {
3355 OpSetTauScale(boost::shared_ptr<double> local_tau_sacale,
3356 boost::shared_ptr<MatrixDouble> piola_stress_at_pts,
3357 double alpha_tau, double alpha_tau_lin)
3358 : BdyEleOp(NOSPACE, BdyEleOp::OPSPACE),
3359 localTauSacale(local_tau_sacale),
3360 piolaStressAtPts(piola_stress_at_pts), alphaTau(alpha_tau),
3361 alphaTauLin(alpha_tau_lin) {}
3362 MoFEMErrorCode doWork(int side, EntityType type,
3363 EntitiesFieldData::EntData &data) override {
3365 auto &coords = BdyEleOp::getCoords();
3366 auto [centre, barycenter, h] =
3367 Tools::getTricircumcenter3d(coords.data().data());
3368
3369 if (PetscUnlikely(h <= 0))
3370 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3371 "Non-positive characteristic face size");
3372
3373 double mean_normal_traction = 0;
3374 if (alphaTauLin > 0) {
3375 if (PetscUnlikely(!piolaStressAtPts))
3376 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3377 "Piola stress is not available for tau scaling");
3378
3379 const auto nb_gauss_pts = BdyEleOp::getGaussPts().size2();
3381 auto get_piola =
3383 GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>, DL>::get(
3384 *piolaStressAtPts, nb_gauss_pts);
3385 auto t_piola = get_piola();
3386 auto t_normal = BdyEleOp::getFTensor1NormalsAtGaussPts();
3387 auto t_w = BdyEleOp::getFTensor0IntegrationWeight();
3389
3390 double face_measure = 0;
3391 double integrated_normal_traction = 0;
3392 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
3393 const double normal_norm = t_normal.l2();
3394 if (PetscUnlikely(normal_norm <= 0))
3395 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3396 "Face normal has non-positive length");
3397
3399 t_unit_normal(i) = t_normal(i) / normal_norm;
3400 const double dA = t_w * BdyEleOp::getMeasure();
3401 face_measure += dA;
3402 integrated_normal_traction +=
3403 dA * std::abs(t_unit_normal(i) * t_piola(i, J) *
3404 t_unit_normal(J));
3405
3406 ++t_piola;
3407 ++t_normal;
3408 ++t_w;
3409 }
3410
3411 if (PetscUnlikely(face_measure <= 0))
3412 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3413 "Face has non-positive measure");
3414 mean_normal_traction = integrated_normal_traction / face_measure;
3415 }
3416
3417 *localTauSacale = (alphaTau + alphaTauLin * mean_normal_traction) / h;
3418
3420 }
3421
3422 private:
3423 boost::shared_ptr<double> localTauSacale;
3424 boost::shared_ptr<MatrixDouble> piolaStressAtPts;
3425 double alphaTau;
3426 double alphaTauLin;
3427 };
3428
3429 auto add_tau_stress_producer = [&](auto &pip) {
3430 // Freeze traction-dependent stabilisation at the last converged state.
3431 auto piola_stress_at_pts = dataAtPts->getApproxP0AtPts();
3432 if (alphaTauLin > 0)
3434 piolaStress, piola_stress_at_pts, nullptr, solTSStep));
3435 return piola_stress_at_pts;
3436 };
3437
3438 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
3439 auto ent = fe_method_ptr->getFEEntityHandle();
3440 if (
3441
3442 (interfaceFaces->find(ent) != interfaceFaces->end())
3443
3444 || (crackFaces->find(ent) != crackFaces->end())
3445
3446 ) {
3447 return false;
3448 };
3449 return true;
3450 };
3451
3452 // Right hand side
3453 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3454 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
3455
3456 // elastic
3457 if (add_elastic) {
3458
3459 fe_rhs->getOpPtrVector().push_back(
3460 new OpSpatialEquilibrium(spatialL2Disp, dataAtPts, alphaW, alphaRho));
3461 fe_rhs->getOpPtrVector().push_back(new OpSpatialRotation(
3462 rotAxis, dataAtPts, alphaR, alphaOmega, alphaViscousR,
3463 alphaViscousOmega));
3464 CHKERR physicalEquations->pushMaterialResidual(
3465 *this, fe_rhs->getOpPtrVector(), dataAtPts);
3466 fe_rhs->getOpPtrVector().push_back(
3467 new OpSpatialConsistencyP(piolaStress, dataAtPts));
3468 fe_rhs->getOpPtrVector().push_back(
3469 new OpSpatialConsistencyBubble(bubbleField, dataAtPts));
3470 fe_rhs->getOpPtrVector().push_back(
3471 new OpSpatialConsistencyDivTerm(piolaStress, dataAtPts));
3472
3473 auto set_hybridisation_rhs = [&](auto &pip) {
3475
3476 using BoundaryEle =
3478 using EleOnSide =
3480 using SideEleOp = EleOnSide::UserDataOperator;
3481 using BdyEleOp = BoundaryEle::UserDataOperator;
3482
3483 // First: Iterate over skeleton FEs adjacent to Domain FEs
3484 // Note: BoundaryEle, i.e. uses skeleton interation rule
3485 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3486 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3487 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3488 return -1;
3489 };
3490 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3491 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3492
3493 CHKERR EshelbianPlasticity::
3494 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3495 op_loop_skeleton_side->getOpPtrVector(), {L2},
3496 materialH1Positions, frontAdjEdges);
3497
3498 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3499 // domain element.
3500 auto broken_data_ptr =
3501 boost::make_shared<std::vector<BrokenBaseSideData>>();
3502 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3503 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3504 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3505 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3506 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3507 CHKERR
3508 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3509 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3510 materialH1Positions, frontAdjEdges);
3511 op_loop_domain_side->getOpPtrVector().push_back(
3512 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3513 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3514 op_loop_domain_side->getOpPtrVector().push_back(
3516 flux_mat_ptr));
3517 op_loop_domain_side->getOpPtrVector().push_back(
3518 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3519
3520 // Assemble on skeleton
3521 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3523 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
3525 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3526 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
3527 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
3528 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3529 op_loop_skeleton_side->getOpPtrVector().push_back(
3530 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3531 hybrid_ptr));
3532 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3533 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3534
3535 // Add skeleton to domain pipeline
3536 pip.push_back(op_loop_skeleton_side);
3537
3539 };
3540
3541 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3542 auto hybrid_field) {
3544
3545 using BoundaryEle =
3547 using EleOnSide =
3549 using SideEleOp = EleOnSide::UserDataOperator;
3550 using BdyEleOp = BoundaryEle::UserDataOperator;
3551
3552 // First: Iterate over skeleton FEs adjacent to Domain FEs
3553 // Note: BoundaryEle, i.e. uses skeleton interation rule
3554 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3555 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3556 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3557 return -1;
3558 };
3559 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3560 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3561 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3562 CHKERR EshelbianPlasticity::
3563 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3564 op_loop_skeleton_side->getOpPtrVector(), {L2},
3565 materialH1Positions, frontAdjEdges);
3566
3567 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3568 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3569 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3570 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3571 CHKERR
3572 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3573 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3574 materialH1Positions, frontAdjEdges);
3575
3576 // Add stabilization operator
3577 auto broken_disp_data_ptr =
3578 boost::make_shared<std::vector<BrokenBaseSideData>>();
3579 op_loop_domain_side->getOpPtrVector().push_back(
3580 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3581 broken_disp_data_ptr));
3582 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3583 op_loop_domain_side->getOpPtrVector().push_back(
3585 disp_mat_ptr));
3586 // Set diag fluxes on skeleton side
3587 op_loop_domain_side->getOpPtrVector().push_back(
3588 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3589 auto piola_stress_at_pts =
3590 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3591 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3592 op_loop_skeleton_side->getOpPtrVector().push_back(
3593 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts, alphaTau,
3594 alphaTauLin));
3595
3596 // Add stabilization Ugamma Ugamma skeleton
3597 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3598 op_loop_skeleton_side->getOpPtrVector().push_back(
3600 hybrid_ptr));
3601
3602 // Diag u_gamma - u_gamma faces
3603 op_loop_skeleton_side->getOpPtrVector().push_back(
3605 hybrid_field, hybrid_ptr,
3606 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3607 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3608 }));
3609 // Diag L2 - L2 volumes
3610 op_loop_skeleton_side->getOpPtrVector().push_back(
3612 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3613 return (*local_tau_sacale);
3614 }));
3615 // Off-diag Ugamma - L2
3616 op_loop_skeleton_side->getOpPtrVector().push_back(
3618 hybrid_field, broken_disp_data_ptr,
3619 [local_tau_sacale](double, double, double) {
3620 return -(*local_tau_sacale);
3621 }));
3622 // Off-diag L2 - Ugamma
3623 op_loop_skeleton_side->getOpPtrVector().push_back(
3625 broken_disp_data_ptr, hybrid_ptr,
3626 [local_tau_sacale](double, double, double) {
3627 return -(*local_tau_sacale);
3628 }));
3629
3630 // Add skeleton to domain pipeline
3631 pip.push_back(op_loop_skeleton_side);
3632
3634 };
3635
3636 auto set_tau_stabilsation_disp_bc_rhs = [&](auto &pip, auto side_fe_name) {
3638
3639 using BoundaryEle =
3641 using EleOnSide =
3643 using SideEleOp = EleOnSide::UserDataOperator;
3644 using BdyEleOp = BoundaryEle::UserDataOperator;
3645
3646 // First: Iterate over skeleton FEs adjacent to Domain FEs
3647 // Note: BoundaryEle, i.e. uses skeleton interation rule
3648 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3649 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3650 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3651 return -1;
3652 };
3653 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3654 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3655 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3656 CHKERR EshelbianPlasticity::
3657 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3658 op_loop_skeleton_side->getOpPtrVector(), {L2},
3659 materialH1Positions, frontAdjEdges);
3660
3661 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3662 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3663 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3664 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3665 CHKERR
3666 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3667 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3668 materialH1Positions, frontAdjEdges);
3669
3670 // Add stabilization operator
3671 auto broken_disp_data_ptr =
3672 boost::make_shared<std::vector<BrokenBaseSideData>>();
3673 op_loop_domain_side->getOpPtrVector().push_back(
3674 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3675 broken_disp_data_ptr));
3676 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3677 op_loop_domain_side->getOpPtrVector().push_back(
3679 disp_mat_ptr));
3680 // Set diag fluxes on skeleton side
3681 op_loop_domain_side->getOpPtrVector().push_back(
3682 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3683
3684 auto piola_stress_at_pts =
3685 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3686
3687 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3688 op_loop_skeleton_side->getOpPtrVector().push_back(
3689 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts,
3690 alphaTauBcDisp, alphaTauLin));
3691
3692 // Diag L2 - L2 volumes
3693 op_loop_skeleton_side->getOpPtrVector().push_back(
3695 broken_disp_data_ptr, bcSpatialDispVecPtr, timeScaleMap,
3696 [local_tau_sacale](double, double, double) {
3697 return (*local_tau_sacale);
3698 }));
3699 op_loop_skeleton_side->getOpPtrVector().push_back(
3701 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3702 timeScaleMap, [local_tau_sacale](double, double, double) {
3703 return (*local_tau_sacale);
3704 }));
3705 op_loop_skeleton_side->getOpPtrVector().push_back(
3707 broken_disp_data_ptr, bcSpatialRotationVecPtr, timeScaleMap,
3708 [local_tau_sacale](double, double, double) {
3709 return (*local_tau_sacale);
3710 }));
3711
3712 // Add skeleton to domain pipeline
3713 pip.push_back(op_loop_skeleton_side);
3714
3716 };
3717
3718 auto set_contact_rhs = [&](auto &pip) {
3719 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3720 };
3721
3722 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3723 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3724 if (alphaTau > 0.0 || alphaTauLin > 0.0) {
3725 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3726 hybridSpatialDisp);
3727 }
3728 if (alphaTauBcDisp > 0.0 || alphaTauLin > 0.0) {
3729 CHKERR set_tau_stabilsation_disp_bc_rhs(fe_rhs->getOpPtrVector(),
3730 naturalBcElement);
3731 }
3732 // Body forces
3733 using BodyNaturalBC =
3735 Assembly<PETSC>::LinearForm<GAUSS>;
3736 using OpBodyForce =
3737 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3738
3739 std::string body_force_history;
3740 CHKERR getStringArgumentFromJsonBlocksets("BODY_FORCE", "load_history",
3741 body_force_history);
3742 if (body_force_history.empty()) {
3743 body_force_history = "body_force.txt";
3744 } else {
3745 MOFEM_LOG("EP", Sev::inform)
3746 << "Body force load history from JSON: " << body_force_history;
3747 }
3748 auto body_time_scale =
3749 boost::make_shared<DynamicRelaxationTimeScale>(body_force_history);
3750 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3751 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3752 "BODY_FORCE", Sev::inform);
3753 }
3754
3755 // Left hand side
3756 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3757 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3758
3759 // elastic
3760 if (add_elastic) {
3761
3762 CHKERR pushVolumeA00Ops(fe_lhs);
3763
3764 auto set_hybridisation_lhs = [&](auto &pip) {
3766
3767 using BoundaryEle =
3769 using EleOnSide =
3771 using SideEleOp = EleOnSide::UserDataOperator;
3772 using BdyEleOp = BoundaryEle::UserDataOperator;
3773
3774 // First: Iterate over skeleton FEs adjacent to Domain FEs
3775 // Note: BoundaryEle, i.e. uses skeleton interation rule
3776 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3777 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3778 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3779 return -1;
3780 };
3781 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3782 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3783 CHKERR EshelbianPlasticity::
3784 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3785 op_loop_skeleton_side->getOpPtrVector(), {L2},
3786 materialH1Positions, frontAdjEdges);
3787
3788 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3789 // domain element.
3790 auto broken_data_ptr =
3791 boost::make_shared<std::vector<BrokenBaseSideData>>();
3792 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3793 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3794 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3795 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3796 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3797 CHKERR
3798 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3799 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3800 materialH1Positions, frontAdjEdges);
3801 op_loop_domain_side->getOpPtrVector().push_back(
3802 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3803
3804 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3806 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3807 op_loop_skeleton_side->getOpPtrVector().push_back(
3808 new OpC(hybridSpatialDisp, broken_data_ptr,
3809 boost::make_shared<double>(1.0), true, false));
3810
3811 pip.push_back(op_loop_skeleton_side);
3812
3814 };
3815
3816 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3817 auto hybrid_field) {
3819
3820 using BoundaryEle =
3822 using EleOnSide =
3824 using SideEleOp = EleOnSide::UserDataOperator;
3825 using BdyEleOp = BoundaryEle::UserDataOperator;
3826
3827 // First: Iterate over skeleton FEs adjacent to Domain FEs
3828 // Note: BoundaryEle, i.e. uses skeleton interation rule
3829 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3830 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3831 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3832 return -1;
3833 };
3834 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3835 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3836 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3837 CHKERR EshelbianPlasticity::
3838 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3839 op_loop_skeleton_side->getOpPtrVector(), {L2},
3840 materialH1Positions, frontAdjEdges);
3841
3842 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3843 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3844 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3845 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3846 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3847 CHKERR
3848 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3849 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3850 materialH1Positions, frontAdjEdges);
3851
3852 auto broken_disp_data_ptr =
3853 boost::make_shared<std::vector<BrokenBaseSideData>>();
3854 op_loop_domain_side->getOpPtrVector().push_back(
3855 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3856 broken_disp_data_ptr));
3857 auto piola_stress_at_pts =
3858 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3859 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3860 op_loop_skeleton_side->getOpPtrVector().push_back(
3861 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts, alphaTau,
3862 alphaTauLin));
3863
3864 // Diag Ugamma-Ugamma skeleton
3865 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3866 hybrid_field, hybrid_field,
3867 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3868 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3869 }));
3870 // Diag L2-L2 volumes
3871 op_loop_skeleton_side->getOpPtrVector().push_back(
3873 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3874 return (*local_tau_sacale);
3875 }));
3876 // Off-diag Ugamma - L2
3877 op_loop_skeleton_side->getOpPtrVector().push_back(
3879 hybrid_field, broken_disp_data_ptr,
3880 [local_tau_sacale](double, double, double) {
3881 return -(*local_tau_sacale);
3882 },
3883 false, false));
3884 // Off-diag L2 - Ugamma
3885 op_loop_skeleton_side->getOpPtrVector().push_back(
3887 hybrid_field, broken_disp_data_ptr,
3888 [local_tau_sacale](double, double, double) {
3889 return -(*local_tau_sacale);
3890 },
3891 true, true));
3892
3893 pip.push_back(op_loop_skeleton_side);
3894
3896 };
3897
3898 auto set_tau_stabilsation_disp_bc_lhs = [&](auto &pip, auto side_fe_name) {
3900
3901 using BoundaryEle =
3903 using EleOnSide =
3905 using SideEleOp = EleOnSide::UserDataOperator;
3906 using BdyEleOp = BoundaryEle::UserDataOperator;
3907
3908 // First: Iterate over skeleton FEs adjacent to Domain FEs
3909 // Note: BoundaryEle, i.e. uses skeleton interation rule
3910 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3911 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3912 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3913 return -1;
3914 };
3915 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3916 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3917 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3918 CHKERR EshelbianPlasticity::
3919 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3920 op_loop_skeleton_side->getOpPtrVector(), {L2},
3921 materialH1Positions, frontAdjEdges);
3922
3923 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3924 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3925 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3926 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3927 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3928 CHKERR
3929 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3930 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3931 materialH1Positions, frontAdjEdges);
3932
3933 auto broken_disp_data_ptr =
3934 boost::make_shared<std::vector<BrokenBaseSideData>>();
3935 op_loop_domain_side->getOpPtrVector().push_back(
3936 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3937 broken_disp_data_ptr));
3938 auto piola_stress_at_pts =
3939 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3940 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3941 op_loop_skeleton_side->getOpPtrVector().push_back(
3942 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts,
3943 alphaTauBcDisp, alphaTauLin));
3944
3945 // Diag L2-L2 volumes
3946 op_loop_skeleton_side->getOpPtrVector().push_back(
3948 broken_disp_data_ptr, bcSpatialDispVecPtr,
3949 [local_tau_sacale](double, double, double) {
3950 return (*local_tau_sacale);
3951 }));
3952 op_loop_skeleton_side->getOpPtrVector().push_back(
3954 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3955 [local_tau_sacale](double, double, double) {
3956 return (*local_tau_sacale);
3957 }));
3958 op_loop_skeleton_side->getOpPtrVector().push_back(
3960 broken_disp_data_ptr, bcSpatialRotationVecPtr,
3961 [local_tau_sacale](double, double, double) {
3962 return (*local_tau_sacale);
3963 }));
3964
3965 pip.push_back(op_loop_skeleton_side);
3966
3968 };
3969
3970 auto set_contact_lhs = [&](auto &pip) {
3971 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3972 };
3973
3974 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3975 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3976 if (alphaTau > 0.0 || alphaTauLin > 0.0) {
3977 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3978 hybridSpatialDisp);
3979 }
3980 if (alphaTauBcDisp > 0.0 || alphaTauLin > 0.0) {
3981 CHKERR set_tau_stabilsation_disp_bc_lhs(fe_lhs->getOpPtrVector(),
3982 naturalBcElement);
3983 }
3984 }
3985
3986 if (add_material) {
3987 }
3988
3990}
3991
3993 const bool add_elastic, const bool add_material,
3994 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3995 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3997
3998 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3999 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
4000
4001 // set integration rule
4002 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
4003 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
4004 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
4005 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
4006 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
4007 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
4008
4009 CHKERR
4010 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4011 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
4012 CHKERR
4013 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4014 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
4015
4016 if (add_elastic) {
4017
4018 auto get_broken_op_side = [this](auto &pip) {
4019 using EleOnSide =
4021 using SideEleOp = EleOnSide::UserDataOperator;
4022 // Iterate over domain FEs adjacent to boundary.
4023 auto broken_data_ptr =
4024 boost::make_shared<std::vector<BrokenBaseSideData>>();
4025 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
4026 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4027 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4028 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4029 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
4030 CHKERR
4031 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4032 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4033 materialH1Positions, frontAdjEdges);
4034 op_loop_domain_side->getOpPtrVector().push_back(
4035 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
4036 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
4037 op_loop_domain_side->getOpPtrVector().push_back(
4039 flux_mat_ptr));
4040 op_loop_domain_side->getOpPtrVector().push_back(
4041 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
4042 pip.push_back(op_loop_domain_side);
4043 return broken_data_ptr;
4044 };
4045
4046 auto set_rhs = [&]() {
4048
4049 auto broken_data_ptr = get_broken_op_side(fe_rhs->getOpPtrVector());
4050
4051 fe_rhs->getOpPtrVector().push_back(
4052 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
4053 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
4054 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
4055 timeScaleMap));
4056 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
4057 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
4058
4059 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4060 fe_rhs->getOpPtrVector().push_back(
4061 new OpBrokenTractionBc(hybridSpatialDisp, bcSpatialTractionVecPtr,
4062 piola_scale_ptr, timeScaleMap));
4063 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4064 // if you push gradient of L2 base to physical element, it will not work.
4065 fe_rhs->getOpPtrVector().push_back(
4067 hybridSpatialDisp, hybrid_grad_ptr));
4068 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
4069 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
4070 hybrid_grad_ptr, timeScaleMap));
4071 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
4072 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
4073 timeScaleMap));
4074
4075 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
4076 fe_rhs->getOpPtrVector().push_back(
4077 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
4078 hybrid_ptr));
4079 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
4080 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4081 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
4082 fe_rhs->getOpPtrVector().push_back(
4083 new OpSpringRhsBc(hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4084 bcSpatialSpringVecPtr));
4085
4086 auto get_normal_disp_bc_faces = [&]() {
4087 auto faces =
4088 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4089 return boost::make_shared<Range>(faces);
4090 };
4091
4092 auto get_spring_bc_faces = [&]() {
4093 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4094 return boost::make_shared<Range>(faces);
4095 };
4096
4097 using BoundaryEle =
4099 using BdyEleOp = BoundaryEle::UserDataOperator;
4101 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
4102 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4103 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4104 get_normal_disp_bc_faces()));
4105 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4106 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4107 get_spring_bc_faces()));
4108
4110 };
4111
4112 auto set_lhs = [&]() {
4114
4115 auto broken_data_ptr = get_broken_op_side(fe_lhs->getOpPtrVector());
4116
4117 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
4118 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
4119 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
4120 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
4121 timeScaleMap));
4122 fe_lhs->getOpPtrVector().push_back(
4123 new OpSpringLhsBc_dU(hybridSpatialDisp, bcSpatialSpringVecPtr));
4124 fe_lhs->getOpPtrVector().push_back(new OpSpringLhsBc_dP(
4125 hybridSpatialDisp, broken_data_ptr, bcSpatialSpringVecPtr));
4126
4127 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4128 // if you push gradient of L2 base to physical element, it will not work.
4129 fe_lhs->getOpPtrVector().push_back(
4131 hybridSpatialDisp, hybrid_grad_ptr));
4132 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
4133 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
4134 timeScaleMap));
4135
4136 auto get_normal_disp_bc_faces = [&]() {
4137 auto faces =
4138 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4139 return boost::make_shared<Range>(faces);
4140 };
4141
4142 auto get_spring_bc_faces = [&]() {
4143 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4144 return boost::make_shared<Range>(faces);
4145 };
4146
4147 using BoundaryEle =
4149 using BdyEleOp = BoundaryEle::UserDataOperator;
4151 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
4152 fe_lhs->getOpPtrVector().push_back(new OpC(
4153 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4154 true, true, get_normal_disp_bc_faces()));
4155 fe_lhs->getOpPtrVector().push_back(new OpC(
4156 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4157 true, true, get_spring_bc_faces()));
4158
4160 };
4161
4162 CHKERR set_rhs();
4163 CHKERR set_lhs();
4164 }
4165
4167}
4168
4170
4171 boost::shared_ptr<ForcesAndSourcesCore> &fe_contact_tree
4172
4173) {
4175 fe_contact_tree = createContactDetectionFiniteElement(*this);
4177}
4178
4181
4182 // Add contact operators. Note that only for rhs. THe lhs is assembled with
4183 // volume element, to enable schur complement evaluation.
4184 CHKERR setContactElementRhsOps(contactTreeRhs);
4185
4186 CHKERR setVolumeElementOps(tag, true, false, elasticFeRhs, elasticFeLhs);
4187 CHKERR setFaceElementOps(true, false, elasticBcRhs, elasticBcLhs);
4188
4190}
4191
4194 boost::shared_ptr<FEMethod> null;
4195
4196 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4197
4198 CHKERR DMMoFEMTSSetI2Function(dm, elementVolumeName, elasticFeRhs, null,
4199 null);
4200 CHKERR DMMoFEMTSSetI2Function(dm, naturalBcElement, elasticBcRhs, null,
4201 null);
4202 CHKERR DMMoFEMTSSetI2Jacobian(dm, elementVolumeName, elasticFeLhs, null,
4203 null);
4204 CHKERR DMMoFEMTSSetI2Jacobian(dm, naturalBcElement, elasticBcLhs, null,
4205 null);
4206
4207 } else {
4208 CHKERR DMMoFEMTSSetIFunction(dm, elementVolumeName, elasticFeRhs, null,
4209 null);
4210 CHKERR DMMoFEMTSSetIFunction(dm, naturalBcElement, elasticBcRhs, null,
4211 null);
4212 CHKERR DMMoFEMTSSetIJacobian(dm, elementVolumeName, elasticFeLhs, null,
4213 null);
4214 CHKERR DMMoFEMTSSetIJacobian(dm, naturalBcElement, elasticBcLhs, null,
4215 null);
4216 }
4217
4219}
4220
4224#include "impl/SetUpSchurImpl.cpp"
4225
4227
4228 inline static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x,
4229 bool set_ts_monitor) {
4230
4231#ifdef ENABLE_PYTHON_BINDING
4232 auto setup_sdf = [&]() { return setupContactSdf(ep_ptr->mField); };
4233#endif
4234
4235 auto setup_ts_monitor = [&]() {
4236 boost::shared_ptr<TsCtx> ts_ctx;
4238 "get TS ctx");
4239 if (set_ts_monitor) {
4241 TSMonitorSet(ts, TsMonitorSet, ts_ctx.get(), PETSC_NULLPTR),
4242 "TS monitor set");
4243 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
4244 auto testing_monitor_ptr =
4245 boost::make_shared<EshelbianTestingMonitor>(*ep_ptr, monitor_ptr);
4246 ts_ctx->getLoopsMonitor().push_back(
4247 TsCtx::PairNameFEMethodPtr(ep_ptr->elementVolumeName, monitor_ptr));
4248
4249 PetscBool test_cook_flg = PETSC_FALSE;
4250 PetscBool test_cook_pts_flg = PETSC_FALSE;
4251 PetscInt atom_test = 0;
4252 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook",
4253 &test_cook_flg, PETSC_NULLPTR);
4254 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook_pts",
4255 &test_cook_pts_flg, PETSC_NULLPTR);
4256 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
4257 PETSC_NULLPTR);
4258 if (atom_test || test_cook_flg || test_cook_pts_flg) {
4260 ep_ptr->elementVolumeName, testing_monitor_ptr));
4261 }
4262 }
4263 MOFEM_LOG("EP", Sev::inform) << "TS monitor setup";
4264 return std::make_tuple(ts_ctx);
4265 };
4266
4267 auto setup_snes_monitor = [&]() {
4269 SNES snes;
4270 CHKERR TSGetSNES(ts, &snes);
4271 auto snes_ctx = getDMSnesCtx(ep_ptr->dmElastic);
4272 CHKERR SNESMonitorSet(snes,
4273 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
4274 void *))MoFEMSNESMonitorEnergy,
4275 (void *)(snes_ctx.get()), PETSC_NULLPTR);
4276 MOFEM_LOG("EP", Sev::inform) << "SNES monitor setup";
4278 };
4279
4280 auto setup_snes_convergence_test = [&]() {
4284 (ep_ptr->dynamicAtol > 0 || ep_ptr->dynamicRtol > 0)) {
4285 auto snes_convergence_test =
4286 [](SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm,
4287 PetscReal fnorm, SNESConvergedReason *reason, void *cctx) {
4289 auto ep_ptr = static_cast<EshelbianCore *>(cctx);
4290 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
4291 PETSC_NULLPTR);
4292
4293 if (it == 0) {
4294 if (ep_ptr->dynamicInitialResidual < 0)
4295 ep_ptr->dynamicInitialResidual = fnorm;
4296
4297 if (ep_ptr->dynamicAtol > 0 && fnorm < ep_ptr->dynamicAtol) {
4298 *reason = SNES_BREAKOUT_INNER_ITER;
4300 "EP", Sev::inform,
4301 "Stopping dynamic relaxation: SNES iteration 0 residual "
4302 "%3.4e < %3.4e",
4303 static_cast<double>(fnorm),
4304 static_cast<double>(ep_ptr->dynamicAtol));
4305 } else if (ep_ptr->dynamicRtol > 0 &&
4306 fnorm < ep_ptr->dynamicRtol *
4307 ep_ptr->dynamicInitialResidual) {
4308 *reason = SNES_BREAKOUT_INNER_ITER;
4310 "EP", Sev::inform,
4311 "Stopping dynamic relaxation: SNES iteration 0 residual "
4312 "%3.4e < %3.4e * initial residual %3.4e",
4313 static_cast<double>(fnorm),
4314 static_cast<double>(ep_ptr->dynamicRtol),
4315 static_cast<double>(ep_ptr->dynamicInitialResidual));
4316 }
4317
4318 if (*reason == SNES_BREAKOUT_INNER_ITER) {
4319 PetscObject ts_obj = PETSC_NULLPTR;
4320 CHKERR PetscObjectQuery((PetscObject)snes,
4321 "dynamic_relaxation_ts", &ts_obj);
4322 CHKERR TSSetConvergedReason((TS)ts_obj, TS_CONVERGED_USER);
4323 }
4324 }
4325
4327 };
4328
4329 SNES snes;
4330 CHKERR TSGetSNES(ts, &snes);
4331 CHKERR PetscObjectCompose((PetscObject)snes, "dynamic_relaxation_ts",
4332 (PetscObject)ts);
4333 CHKERR SNESSetConvergenceTest(snes, snes_convergence_test, ep_ptr,
4334 PETSC_NULLPTR);
4335 MOFEM_LOG("EP", Sev::inform) << "SNES convergence test setup";
4336 }
4338 };
4339
4340 auto setup_section = [&]() {
4341 PetscSection section_raw;
4342 CHK_THROW_MESSAGE(DMGetSection(ep_ptr->dmElastic, &section_raw),
4343 "get DM section");
4344 int num_fields;
4345 CHK_THROW_MESSAGE(PetscSectionGetNumFields(section_raw, &num_fields),
4346 "get num fields");
4347 for (int ff = 0; ff != num_fields; ff++) {
4348 const char *field_name;
4350 PetscSectionGetFieldName(section_raw, ff, &field_name),
4351 "get field name");
4352 MOFEM_LOG_C("EP", Sev::inform, "Field %d name %s", ff, field_name);
4353 }
4354 return SmartPetscObj<PetscSection>(section_raw, true);
4355 };
4356
4357 auto set_vector_on_mesh = [&]() {
4359 CHKERR DMoFEMMeshToLocalVector(ep_ptr->dmElastic, x, INSERT_VALUES,
4360 SCATTER_FORWARD);
4361 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4362 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4363 MOFEM_LOG("EP", Sev::inform) << "Vector set on mesh";
4365 };
4366
4367 auto setup_schur_block_solver = [&]() {
4368 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver";
4369 CHK_THROW_MESSAGE(TSAppendOptionsPrefix(ts, "elastic_"),
4370 "append options prefix");
4371 CHK_THROW_MESSAGE(TSSetFromOptions(ts), "set from options");
4372 CHK_THROW_MESSAGE(TSSetDM(ts, ep_ptr->dmElastic), "set DM");
4373 // Adding field split solver
4374 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
4375 if constexpr (A == AssemblyType::BLOCK_MAT) {
4376 schur_ptr =
4378 CHK_THROW_MESSAGE(schur_ptr->setUp(ts), "setup schur");
4379 }
4380 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver done";
4381 return schur_ptr;
4382 };
4383
4384 // Warning: sequence of construction is not guaranteed for tuple. You have
4385 // to enforce order by proper packaging.
4386
4387#ifdef ENABLE_PYTHON_BINDING
4388 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
4389 setup_snes_monitor(), setup_snes_convergence_test(),
4390 setup_section(), set_vector_on_mesh(),
4391 setup_schur_block_solver());
4392#else
4393 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
4394 setup_snes_convergence_test(), setup_section(),
4395 set_vector_on_mesh(), setup_schur_block_solver());
4396#endif
4397 }
4398};
4399
4402
4403 PetscBool debug_model = PETSC_FALSE;
4404 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
4405 PETSC_NULLPTR);
4406 MOFEM_LOG("EP", Sev::inform)
4407 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
4408
4409 if (debug_model == PETSC_TRUE) {
4410 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4411 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
4412 void *ctx) {
4414
4415 SNES snes;
4416 CHKERR TSGetSNES(ts, &snes);
4417 int it;
4418 CHKERR SNESGetIterationNumber(snes, &it);
4419 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
4420 CHKERR postProcessResults(1, file_name, F, u_t, PETSC_NULLPTR, {}, ts);
4421
4422 // Disabled until calculateFaceMaterialForce supports the active
4423 // Neo-Hookean material model. Its adjoint path currently assumes a
4424 // Hencky tangent and dereferences an empty matD tensor.
4425#if 0
4426 std::string file_skel_name =
4427 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
4428
4429 auto get_material_force_tag = [&]() {
4430 auto &moab = mField.get_moab();
4431 Tag tag;
4432 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
4433 "can't get tag");
4434 return tag;
4435 };
4436
4437 CHKERR calculateFaceMaterialForce(1, ts);
4438 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
4439 {get_material_force_tag()}, ts);
4440#endif
4441
4443 };
4444 ts_ctx_ptr->tsDebugHook = post_proc;
4445 }
4446
4448}
4449
4452
4453 CHKERR addDebugModel(ts);
4454
4455 auto storage = solve_elastic_setup::setup(this, ts, x, true);
4456
4457 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4458 Vec xx;
4459 CHKERR VecDuplicate(x, &xx);
4460 CHKERR VecZeroEntries(xx);
4461 CHKERR TS2SetSolution(ts, x, xx);
4462 CHKERR VecDestroy(&xx);
4463 } else {
4464 CHKERR TSSetSolution(ts, x);
4465 }
4466
4467 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4468 {elasticFeLhs.get(), elasticFeRhs.get()});
4469 CHKERR TSSetUp(ts);
4470 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4471 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4473 CHKERR TSSolve(ts, PETSC_NULLPTR);
4475 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4476 {elasticFeLhs.get(), elasticFeRhs.get()});
4477
4478#ifndef NDEBUG
4479 // Make graph
4480 if (mField.get_comm_rank() == 0) {
4481 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4483 "solve_elastic_graph.dot");
4484 }
4485#endif
4486
4487 SNES snes;
4488 CHKERR TSGetSNES(ts, &snes);
4489 int lin_solver_iterations;
4490 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
4491 MOFEM_LOG("EP", Sev::inform)
4492 << "Number of linear solver iterations " << lin_solver_iterations;
4493
4494 PetscBool test_cook_flg = PETSC_FALSE;
4495 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
4496 PETSC_NULLPTR);
4497 if (test_cook_flg) {
4498 PetscInt expected_lin_solver_iterations = 11;
4499 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "",
4500 "-test_cook_max_linear_iterations",
4501 &expected_lin_solver_iterations, PETSC_NULLPTR);
4502 if (lin_solver_iterations > expected_lin_solver_iterations)
4503 SETERRQ(
4504 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4505 "Expected number of iterations is different than expected %d > %d",
4506 lin_solver_iterations, expected_lin_solver_iterations);
4507 }
4508
4509 PetscBool test_sslv116_flag = PETSC_FALSE;
4510 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
4511 &test_sslv116_flag, PETSC_NULLPTR);
4512
4513 if (test_sslv116_flag) {
4514 double max_val = 0.0;
4515 double min_val = 0.0;
4516 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
4518 auto ent_type = ent_ptr->getEntType();
4519 if (ent_type == MBVERTEX) {
4520 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
4521 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
4522 }
4524 };
4525 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
4526 field_min_max, spatialH1Disp);
4527
4528 double global_max_val = 0.0;
4529 double global_min_val = 0.0;
4530 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
4531 mField.get_comm());
4532 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
4533 mField.get_comm());
4534 MOFEM_LOG("EP", Sev::inform)
4535 << "Max " << spatialH1Disp << " value: " << global_max_val;
4536 MOFEM_LOG("EP", Sev::inform)
4537 << "Min " << spatialH1Disp << " value: " << global_min_val;
4538
4539 double ref_max_val = 0.00767;
4540 double ref_min_val = -0.00329;
4541 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
4542 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4543 "Incorrect max value of the displacement field: %f != %f",
4544 global_max_val, ref_max_val);
4545 }
4546 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
4547 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4548 "Incorrect min value of the displacement field: %f != %f",
4549 global_min_val, ref_min_val);
4550 }
4551 }
4552
4553 CHKERR gettingNorms();
4554
4556}
4557
4558static MoFEMErrorCode RelaxationResidualMonitor(TS ts, PetscInt, PetscReal, Vec,
4559 void *) {
4561
4562 SNES snes;
4563 CHKERR TSGetSNES(ts, &snes);
4564 SNESConvergedReason snes_reason;
4565 CHKERR SNESGetConvergedReason(snes, &snes_reason);
4566 if (snes_reason == SNES_BREAKOUT_INNER_ITER) {
4567 MOFEM_LOG("EP", Sev::inform)
4568 << "Dynamic relaxation stopped due to SNES_BREAKOUT_INNER_ITER";
4569 CHKERR SNESSetConvergedReason(snes, SNES_CONVERGED_ITERATING);
4570 }
4571
4573}
4574
4577
4578 PetscBool is_beuler = PETSC_FALSE;
4579 PetscBool is_theta = PETSC_FALSE;
4580 CHKERR PetscObjectTypeCompare((PetscObject)ts, TSBEULER, &is_beuler);
4581 CHKERR PetscObjectTypeCompare((PetscObject)ts, TSTHETA, &is_theta);
4582
4583 PetscBool theta_extrapolate = PETSC_FALSE;
4584 PetscBool theta_extrapolate_set = PETSC_FALSE;
4585 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "",
4586 "-elastic_ts_theta_initial_guess_extrapolate",
4587 &theta_extrapolate, &theta_extrapolate_set);
4588 if (theta_extrapolate_set && theta_extrapolate) {
4589 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
4590 "-dynamic_atol and -dynamic_rtol assume the SNES iteration 0 "
4591 "residual is evaluated with zero rates. Disable "
4592 "-elastic_ts_theta_initial_guess_extrapolate.");
4593 }
4594
4595 PetscBool is_backward_euler_equivalent = is_beuler;
4596 if (is_theta) {
4597 PetscReal theta = 0;
4598 CHKERR TSThetaGetTheta(ts, &theta);
4599 is_backward_euler_equivalent =
4600 (std::abs(theta - 1.) <= 10. * std::numeric_limits<double>::epsilon())
4601 ? PETSC_TRUE
4602 : PETSC_FALSE;
4603 }
4604
4605 if (!is_backward_euler_equivalent) {
4606 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
4607 "-dynamic_atol and -dynamic_rtol require a "
4608 "backward-Euler-equivalent TS "
4609 "so that SNES iteration 0 has zero rates. Use "
4610 "-elastic_ts_type beuler or "
4611 "-elastic_ts_type theta -elastic_ts_theta_theta 1.");
4612 }
4613
4615}
4616
4618 int start_step,
4619 double start_time) {
4621
4622 // Deprecated options
4623 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
4624
4625 CHKERR PetscOptionsScalar(
4626 "-dynamic_final_time", "dynamic relaxation final time", "",
4627 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
4628 CHKERR PetscOptionsScalar("-dynamic_delta_time",
4629 "dynamic relaxation final time", "", physicalDt,
4630 &physicalDt, PETSC_NULLPTR);
4631 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
4632 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
4633 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
4634 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
4635 CHKERR PetscOptionsScalar("-dynamic_atol",
4636 "stop relaxation when the zero-rate residual is "
4637 "below this value; disabled for <= 0",
4638 "", dynamicAtol, &dynamicAtol, PETSC_NULLPTR);
4639 CHKERR PetscOptionsScalar("-dynamic_rtol",
4640 "stop relaxation when the zero-rate residual is "
4641 "below this fraction of its initial value; "
4642 "disabled for <= 0",
4643 "", dynamicRtol, &dynamicRtol, PETSC_NULLPTR);
4644
4645 PetscOptionsEnd();
4646
4647 auto storage = solve_elastic_setup::setup(this, ts, x, false);
4648
4649 if (dynamicAtol > 0 || dynamicRtol > 0) {
4651 }
4652
4653 MOFEM_LOG("EP", Sev::warning)
4654 << "Following options are deprecated, use -physical prefix options "
4655 "instead";
4656 MOFEM_LOG("EP", Sev::inform)
4657 << "Dynamic relaxation final time -dynamic_final_time = "
4658 << finalPhysicalTime;
4659 MOFEM_LOG("EP", Sev::inform)
4660 << "Dynamic relaxation delta time -dynamic_delta_time = " << physicalDt;
4661 MOFEM_LOG("EP", Sev::inform)
4662 << "Dynamic relaxation max iterations -dynamic_max_it = "
4663 << physicalMaxSteps;
4664 MOFEM_LOG("EP", Sev::inform)
4665 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
4666 << (physicalH1Update ? "TRUE" : "FALSE");
4667 MOFEM_LOG("EP", Sev::inform)
4668 << "Dynamic relaxation absolute tolerance -dynamic_atol = "
4669 << dynamicAtol;
4670 MOFEM_LOG("EP", Sev::inform)
4671 << "Dynamic relaxation relative tolerance -dynamic_rtol = "
4672 << dynamicRtol;
4673
4674 CHKERR addDebugModel(ts);
4675
4676 auto setup_ts_monitor = [&]() {
4677 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
4678 return monitor_ptr;
4679 };
4680 auto monitor_ptr = setup_ts_monitor();
4681
4682 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4683 {elasticFeLhs.get(), elasticFeRhs.get()});
4684 CHKERR TSSetUp(ts);
4686
4687 double ts_delta_time;
4688 CHKERR TSGetTimeStep(ts, &ts_delta_time);
4689 CHKERR TSSetSolution(ts, x);
4690
4691 if (physicalH1Update) {
4692 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4693 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4694 } else {
4695 CHKERR TSSetPreStep(ts, PETSC_NULLPTR);
4696 CHKERR TSSetPostStep(ts, PETSC_NULLPTR);
4697 }
4698 if (dynamicAtol > 0 || dynamicRtol > 0) {
4699 CHKERR TSMonitorSet(ts, RelaxationResidualMonitor, PETSC_NULLPTR,
4700 PETSC_NULLPTR);
4701 }
4702
4705
4706 currentPhysicalTime = start_time;
4707 physicalStepNumber = start_step;
4708 monitor_ptr->ts = PETSC_NULLPTR;
4709 monitor_ptr->ts_u = PETSC_NULLPTR;
4710 monitor_ptr->ts_t = currentPhysicalTime;
4711 monitor_ptr->ts_step = physicalStepNumber;
4712 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4713
4714 if (physicalDt <= 0.) {
4715 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY,
4716 "physicalDt must be positive, got %g", physicalDt);
4717 }
4718 for (; currentPhysicalTime <= finalPhysicalTime;) {
4719 MOFEM_LOG("EP", Sev::inform)
4720 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
4721 << " delta time " << physicalDt;
4722
4723 CHKERR TSSetStepNumber(ts, 0);
4724 CHKERR TSSetTime(ts, 0);
4725 CHKERR TSSetTimeStep(ts, ts_delta_time);
4726 CHKERR TSSetSolution(ts, x);
4727 if (!physicalH1Update) {
4729 }
4730 dynamicInitialResidual = -1;
4731 CHKERR TSSolve(ts, PETSC_NULLPTR);
4732 if (!physicalH1Update) {
4734 }
4735
4736 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
4737 SCATTER_FORWARD);
4738 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4739 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4740
4741 monitor_ptr->ts = PETSC_NULLPTR;
4742 monitor_ptr->ts_u = x;
4743 monitor_ptr->ts_t = currentPhysicalTime;
4744 monitor_ptr->ts_step = physicalStepNumber;
4745 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4746
4747 ++physicalStepNumber;
4748 if (physicalStepNumber > physicalMaxSteps)
4749 break;
4750 if (currentPhysicalTime >= finalPhysicalTime)
4751 break;
4752
4753 const double remainingPhysicalTime =
4754 finalPhysicalTime - currentPhysicalTime;
4755 if (physicalDt >= remainingPhysicalTime) {
4756 currentPhysicalTime = finalPhysicalTime;
4757 } else {
4758 currentPhysicalTime += physicalDt;
4759 }
4760 }
4761
4763 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4764 {elasticFeLhs.get(), elasticFeRhs.get()});
4765
4767}
4768
4771
4772 auto set_block = [&](auto name, int dim) {
4773 std::map<int, Range> map;
4774 auto set_tag_impl = [&](auto name) {
4776 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4777 auto bcs = mesh_mng->getCubitMeshsetPtr(
4778
4779 std::regex((boost::format("%s(.*)") % name).str())
4780
4781 );
4782 for (auto bc : bcs) {
4783 Range r;
4784 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4785 true);
4786 map[bc->getMeshsetId()] = r;
4787 MOFEM_LOG("EP", Sev::inform)
4788 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4789 << r.size() << " entities";
4790 }
4792 };
4793
4794 CHKERR set_tag_impl(name);
4795
4796 return std::make_pair(name, map);
4797 };
4798
4799 auto set_skin = [&](auto &&map) {
4800 for (auto &m : map.second) {
4801 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4802 m.second.swap(s);
4803 MOFEM_LOG("EP", Sev::inform)
4804 << "Skin for block " << map.first << " id " << m.first << " has "
4805 << m.second.size() << " entities";
4806 }
4807 return map;
4808 };
4809
4810 auto set_tag = [&](auto &&map) {
4811 Tag th;
4812 auto name = map.first;
4813 int def_val[] = {-1};
4815 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4816 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4817 "create tag");
4818 for (auto &m : map.second) {
4819 int id = m.first;
4820 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4821 "clear tag");
4822 }
4823 return th;
4824 };
4825
4826 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4827 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4828 listTagsToTransfer.push_back(
4829 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4830 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4831
4833}
4834
4836EshelbianCore::postProcessRestartMesh(const int tag, const std::string file,
4837 std::vector<Tag> tags_to_transfer) {
4839 ParallelComm *pcomm =
4840 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
4841 // write file with only crack surfaces and full mesh
4842 if (crackingOn && !pcomm->rank()) {
4843 auto meshsets_mng = mField.getInterface<MeshsetsManager>();
4844
4845 std::vector<boost::shared_ptr<TempMeshset>> meshsets_tmp_list;
4846 auto &list = meshsets_mng->getMeshsetsMultindex();
4847 std::vector<Tag> tags_list;
4848
4849 auto meshset_ptr = get_temp_meshset_ptr(mField.get_moab());
4850
4851 for (auto &m : list) {
4852 meshsets_tmp_list.push_back(get_temp_meshset_ptr(mField.get_moab()));
4853 EntityHandle new_meshset = *meshsets_tmp_list.back();
4854 auto meshset = m.getMeshset();
4855 std::vector<Tag> tmp_tags_list;
4856 CHKERR mField.get_moab().tag_get_tags_on_entity(meshset, tmp_tags_list);
4857 Range ents;
4858 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
4859 CHKERR mField.get_moab().add_entities(new_meshset, ents);
4860 for (auto t : tmp_tags_list) {
4861 void *tag_vals[1];
4862 int tag_size[1];
4863 CHKERR mField.get_moab().tag_get_by_ptr(
4864 t, &meshset, 1, (const void **)tag_vals, tag_size);
4865 CHKERR mField.get_moab().tag_set_by_ptr(t, &new_meshset, 1, tag_vals,
4866 tag_size);
4867 }
4868 std::vector<std::string> remove_tags;
4869 remove_tags.push_back("AKDTree_coord_norm");
4870 remove_tags.push_back("__PARALLEL_");
4871 remove_tags.push_back("_RefBitLevel");
4872
4873 for (auto t : tmp_tags_list) {
4874 std::string tag_name;
4875 CHKERR mField.get_moab().tag_get_name(t, tag_name);
4876 bool add = true;
4877
4878 for (auto &p : remove_tags) {
4879 if (tag_name.compare(0, p.size(), p) == 0) {
4880 add = false;
4881 break;
4882 }
4883 }
4884
4885 if (add)
4886 tags_list.push_back(t);
4887 }
4888 }
4889
4890 for (auto &m_ptr : meshsets_tmp_list) {
4891 EntityHandle m = *m_ptr;
4892 CHKERR mField.get_moab().add_entities(*meshset_ptr, &m, 1);
4893 }
4894
4895 // meshsets_tmp_list has all meshsets to write
4896 std::sort(tags_list.begin(), tags_list.end());
4897 auto new_end = std::unique(tags_list.begin(), tags_list.end());
4898 tags_list.resize(std::distance(tags_list.begin(), new_end));
4899
4900 EntityHandle save_meshset = *meshset_ptr;
4901 CHKERR mField.get_moab().write_file(file.c_str(), "MOAB", "", &save_meshset,
4902 1, &tags_list[0], tags_list.size());
4903 }
4905}
4906
4908EshelbianCore::postProcessResults(const int tag, const std::string file,
4909 Vec f_residual, Vec var_vector, Vec gradient,
4910 std::vector<Tag> tags_to_transfer, TS ts) {
4912
4913 SmartPetscObj<Vec> f_r, v_v;
4914 if (f_residual != PETSC_NULLPTR || var_vector != PETSC_NULLPTR) {
4916 SmartPetscObj<Vec> xout;
4917 xout = createDMVector(dM);
4918 auto xin = f_residual != PETSC_NULLPTR ? f_residual : var_vector;
4919 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4920 xin, "ELASTIC_PROBLEM", RowColData::ROW, xout, "ESHELBY_PLASTICITY",
4921 RowColData::ROW, scatter);
4922 if (f_residual) {
4923 f_r = vectorDuplicate(xout);
4924 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
4925 SCATTER_FORWARD);
4926 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
4927 SCATTER_FORWARD);
4928 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
4929 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
4930 }
4931 if (var_vector) {
4932 v_v = createDMVector(dM);
4933 CHKERR VecScatterBegin(scatter, var_vector, v_v, INSERT_VALUES,
4934 SCATTER_FORWARD);
4935 CHKERR VecScatterEnd(scatter, var_vector, v_v, INSERT_VALUES,
4936 SCATTER_FORWARD);
4937 CHKERR VecGhostUpdateBegin(v_v, INSERT_VALUES, SCATTER_FORWARD);
4938 CHKERR VecGhostUpdateEnd(v_v, INSERT_VALUES, SCATTER_FORWARD);
4939 }
4940 }
4941
4943 if (gradient) {
4945 g = createDMVector(dM);
4946 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4947 gradient, "MATERIAL_PROBLEM", RowColData::ROW, g, "ESHELBY_PLASTICITY",
4948 RowColData::ROW, scatter);
4949 CHKERR VecScatterBegin(scatter, gradient, g, INSERT_VALUES,
4950 SCATTER_FORWARD);
4951 CHKERR VecScatterEnd(scatter, gradient, g, INSERT_VALUES, SCATTER_FORWARD);
4952 CHKERR VecGhostUpdateBegin(g, INSERT_VALUES, SCATTER_FORWARD);
4953 CHKERR VecGhostUpdateEnd(g, INSERT_VALUES, SCATTER_FORWARD);
4954 }
4955
4956 // mark crack surface
4957 if (crackingOn) {
4958 auto get_tag = [&](auto name, auto dim) {
4959 auto &mob = mField.get_moab();
4960 Tag tag;
4961 double def_val[] = {0., 0., 0.};
4962 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4963 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4964 "create tag");
4965 return tag;
4966 };
4967 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4968 }
4969
4970 {
4971 auto get_crack_tag = [&]() {
4972 Tag th;
4973 rval = mField.get_moab().tag_get_handle("CRACK", th);
4974 if (rval == MB_SUCCESS) {
4975 MOAB_THROW(mField.get_moab().tag_delete(th));
4976 }
4977 int def_val[] = {0};
4978 MOAB_THROW(mField.get_moab().tag_get_handle(
4979 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4980 def_val));
4981 return th;
4982 };
4983
4984 Tag th = get_crack_tag();
4985 tags_to_transfer.push_back(th);
4986 int mark[] = {1};
4987 Range mark_faces;
4988 if (crackFaces)
4989 mark_faces.merge(*crackFaces);
4990 if (interfaceFaces)
4991 mark_faces.merge(*interfaceFaces);
4992 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4993 }
4994
4995 // add tags to transfer
4996 for (auto t : listTagsToTransfer) {
4997 std::string name;
4998 CHKERR mField.get_moab().tag_get_name(t, name);
4999 MOFEM_LOG("EP", Sev::verbose)
5000 << "Adding tag " << name << " to transfer list for post-processing";
5001 tags_to_transfer.push_back(t);
5002 }
5003
5004 if (!dataAtPts) {
5005 dataAtPts =
5006 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
5007 }
5008
5009 CHKERR DMoFEMLoopFiniteElements(dM, contactElement, contactTreeRhs);
5010
5011 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
5013 auto post_proc_ptr =
5014 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5015 mField, post_proc_mesh);
5016 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
5017 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5018 frontAdjEdges);
5019
5020 if (ts != PETSC_NULLPTR) {
5021 post_proc_ptr->data_ctx |= PetscData::CTX_SET_TIME;
5022 CHKERR TSGetTime(ts, &(post_proc_ptr->ts_t));
5023 CHKERR TSGetTimeStep(ts, &(post_proc_ptr->ts_dt));
5024 }
5025
5026 auto domain_ops = [&](auto &fe, int sense) {
5028 MaterialPostProcData material_output;
5029
5030 auto bubble_cache = boost::make_shared<CGGUserPolynomialBase::CachePhi>(
5031 0, 0, MatrixDouble());
5032 fe.getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
5033 new CGGUserPolynomialBase(bubble_cache));
5034 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5035 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
5036 frontAdjEdges);
5037 auto piola_scale_ptr = boost::make_shared<double>(1.0);
5038 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5039 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
5040 const bool add_bubble = mField.check_field(bubbleField);
5041 if (add_bubble) {
5042 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5043 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
5044 SmartPetscObj<Vec>(), MBMAXTYPE));
5045 }
5046 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5047 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
5048 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
5049 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5050 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
5051 if (add_bubble) {
5052 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5053 bubbleField, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep,
5054 MBMAXTYPE));
5055 }
5056 CHKERR physicalEquations->pushMaterialFields(
5057 *this, fe.getOpPtrVector(), dataAtPts, PhysicalEquations::PREVIOUS);
5058 CHKERR physicalEquations->pushMaterialFields(
5059 *this, fe.getOpPtrVector(), dataAtPts, PhysicalEquations::CURRENT);
5060 if (var_vector) {
5061 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5062 piolaStress, dataAtPts->getVarPiolaPts(),
5063 boost::make_shared<double>(1), v_v));
5064 if (add_bubble)
5065 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5066 bubbleField, dataAtPts->getVarPiolaPts(),
5067 boost::make_shared<double>(1), v_v, MBMAXTYPE));
5068 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5069 rotAxis, dataAtPts->getVarRotAxisPts(), v_v, MBTET));
5070 CHKERR physicalEquations->pushMaterialVariation(
5071 *this, fe.getOpPtrVector(), dataAtPts, v_v, &material_output);
5072 }
5073 if (gradient) {
5074 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5075 materialH1Positions, dataAtPts->getGradientAtPts(), g));
5076 }
5077
5078 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5079 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
5080
5081 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5082 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
5083 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5084 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
5085 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
5086 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
5087 // evaluate derived quantities
5089 fe.getOpPtrVector(), plasticHField, dataAtPts->getPlasticH(),
5090 MBTET);
5091 auto plastic_flow_ptr = boost::shared_ptr<MatrixDouble>();
5092 auto plastic_kappa_ptr = boost::shared_ptr<VectorDouble>();
5093 if (plasticVolume) {
5094 plastic_flow_ptr = boost::make_shared<MatrixDouble>();
5096 fe.getOpPtrVector(), plasticFlowField, plastic_flow_ptr, MBTET);
5097 plastic_kappa_ptr = boost::make_shared<VectorDouble>();
5098 fe.getOpPtrVector().push_back(new OpCalculateScalarFieldValues(
5099 plasticKappaField, plastic_kappa_ptr, MBTET));
5100 }
5101 fe.getOpPtrVector().push_back(
5103
5104 CHKERR physicalEquations->pushPostProc(*this, fe.getOpPtrVector(),
5105 dataAtPts, material_output);
5106
5107 // // post-proc
5111
5112 OpPPMap::DataMapVec scalar_fields;
5113 if (plasticVolume)
5114 scalar_fields["PlasticKappa"] = plastic_kappa_ptr;
5115
5116 struct OpSidePPMap : public OpPPMap {
5117 OpSidePPMap(moab::Interface &post_proc_mesh,
5118 std::vector<EntityHandle> &map_gauss_pts,
5119 DataMapVec data_map_scalar, DataMapMat data_map_vec,
5120 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
5121 int sense)
5122 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
5123 data_map_vec, data_map_mat, data_symm_map_mat),
5124 tagSense(sense) {}
5125
5126 MoFEMErrorCode doWork(int side, EntityType type,
5129
5130 if (tagSense != 0) {
5131 if (tagSense != OpPPMap::getSkeletonSense())
5133 }
5134
5135 CHKERR OpPPMap::doWork(side, type, data);
5137 }
5138
5139 private:
5140 int tagSense;
5141 };
5142
5143 OpPPMap::DataMapMat vec_fields;
5144 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
5145 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
5146 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5147 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
5148 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
5149 if (var_vector) {
5150 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
5151 vec_fields["VarSpatialDisplacementL2"] =
5152 boost::make_shared<MatrixDouble>();
5153 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5154 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], v_v, MBTET));
5155 }
5156 if (f_residual) {
5157 vec_fields["ResSpatialDisplacementL2"] =
5158 boost::make_shared<MatrixDouble>();
5159 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5160 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], f_r, MBTET));
5161 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
5162 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5163 rotAxis, vec_fields["ResOmega"], f_r, MBTET));
5164 }
5165 if (gradient) {
5166 vec_fields["Gradient"] = dataAtPts->getGradientAtPts();
5167 }
5168
5169 OpPPMap::DataMapMat mat_fields;
5170 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5171 if (var_vector) {
5172 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
5173 }
5174 if (f_residual) {
5175 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
5176 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5177 piolaStress, mat_fields["ResPiolaStress"],
5178 boost::make_shared<double>(1), f_r));
5179 if (add_bubble)
5180 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5181 bubbleField, mat_fields["ResPiolaStress"],
5182 boost::make_shared<double>(1), f_r, MBMAXTYPE));
5183 }
5184 if (!internalStressTagName.empty()) {
5185 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
5186 switch (meshTransferInterpOrder) {
5187 case 0:
5188 fe.getOpPtrVector().push_back(
5189 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
5190 break;
5191 case 1:
5192 fe.getOpPtrVector().push_back(
5193 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
5194 break;
5195 default:
5196 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
5197 "Unsupported mesh transfer interpolation order %d, for "
5198 "internal stress",
5199 meshTransferInterpOrder);
5200 }
5201 }
5202
5203 OpPPMap::DataMapMat mat_fields_symm;
5204 if (f_residual) {
5205 CHKERR physicalEquations->pushPostProcResidual(
5206 *this, fe.getOpPtrVector(), dataAtPts, f_r, material_output);
5207 }
5208 if (plasticVolume)
5209 mat_fields_symm["PlasticHp"] = dataAtPts->getPlasticH();
5210 if (plasticVolume)
5211 mat_fields_symm["PlasticFlow"] = plastic_flow_ptr;
5212 scalar_fields.insert(material_output.scalarFields.begin(),
5213 material_output.scalarFields.end());
5214 vec_fields.insert(material_output.vectorFields.begin(),
5215 material_output.vectorFields.end());
5216 mat_fields_symm.insert(material_output.symmetricFields.begin(),
5217 material_output.symmetricFields.end());
5218
5219 fe.getOpPtrVector().push_back(
5220
5221 new OpSidePPMap(
5222
5223 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5224
5225 scalar_fields,
5226
5227 vec_fields,
5228
5229 mat_fields,
5230
5231 mat_fields_symm,
5232
5233 sense
5234
5235 )
5236
5237 );
5238
5239 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
5240 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5241 dataAtPts, sense));
5242
5244 };
5245
5246 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
5247 // H1 material positions
5248 post_proc_ptr->getOpPtrVector().push_back(
5249 new OpCalculateVectorFieldValues<3>(materialH1Positions,
5250 dataAtPts->getLargeXH1AtPts()));
5251
5252 // domain
5254 mField, elementVolumeName, SPACE_DIM);
5255 CHK_THROW_MESSAGE(domain_ops(*(op_loop_side->getSideFEPtr()), sense),
5256 "Cannot construct material postprocessing pipeline");
5257 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
5258
5259 return post_proc_ptr;
5260 };
5261
5262 // contact
5263 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
5264 auto &pip) {
5266 // evaluate traction
5267 using EleOnSide =
5269 using SideEleOp = EleOnSide::UserDataOperator;
5270 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
5271 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5272 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5273 boost::shared_ptr<BaseFunction>(
5274 new CGGUserPolynomialBase(nullptr, true));
5275 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5276 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5277 materialH1Positions, frontAdjEdges);
5278 auto traction_ptr = boost::make_shared<MatrixDouble>();
5279 op_loop_domain_side->getOpPtrVector().push_back(
5281 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
5282
5283 pip.push_back(new OpCalculateVectorFieldValues<3>(
5284 contactDisp, dataAtPts->getContactL2AtPts()));
5285 pip.push_back(op_loop_domain_side);
5286 // evaluate contact displacement and contact conditions
5287 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5288 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
5289 pip.push_back(getOpContactDetection(
5290 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
5291 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
5292 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
5293
5295 using BoundaryEle =
5297 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
5298 pip.push_back(op_this);
5299
5300 OpPPMap::DataMapMat vec_fields;
5301 vec_fields["ContactDisplacement"] = dataAtPts->getContactL2AtPts();
5302
5303 op_this->getOpPtrVector().push_back(
5304
5305 new OpPPMap(
5306
5307 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5308
5309 {},
5310
5311 vec_fields,
5312
5313 {},
5314
5315 {}
5316
5317 )
5318
5319 );
5320
5321 if (f_residual) {
5322
5323 auto contact_residual = boost::make_shared<MatrixDouble>();
5324 op_this->getOpPtrVector().push_back(
5326 contactDisp, contact_residual, f_r, MBTET));
5327 op_this->getOpPtrVector().push_back(
5328
5329 new OpPPMap(
5330
5331 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5332
5333 {},
5334
5335 {{"res_contact", contact_residual}},
5336
5337 {},
5338
5339 {}
5340
5341 )
5342
5343 );
5344 }
5345
5347 };
5348
5349 auto post_proc_mesh = boost::make_shared<moab::Core>();
5350 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5351 auto post_proc_negative_sense_ptr =
5352 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
5353 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5354 CHKERR calcs_side_traction_and_displacements(
5355 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
5356
5357 auto own_tets =
5358 CommInterface::getPartEntities(mField.get_moab(), mField.get_comm_rank())
5359 .subset_by_dimension(SPACE_DIM);
5360 Range own_faces;
5361 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
5362 own_faces, moab::Interface::UNION);
5363
5364 auto get_crack_faces = [&](auto crack_faces) {
5365 auto get_adj = [&](auto e, auto dim) {
5366 Range adj;
5367 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
5368 moab::Interface::UNION);
5369 return adj;
5370 };
5371 // this removes faces
5372 auto tets = get_adj(crack_faces, 3);
5373 // faces adjacent to tets not in crack_faces
5374 auto faces = subtract(get_adj(tets, 2), crack_faces);
5375 // what is left from below, are tets fully inside crack_faces
5376 tets = subtract(tets, get_adj(faces, 3));
5377 return subtract(crack_faces, get_adj(tets, 2));
5378 };
5379
5380 auto side_one_faces = [&](auto &faces) {
5381 std::pair<Range, Range> sides;
5382 for (auto f : faces) {
5383 Range adj;
5384 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
5385 adj = intersect(own_tets, adj);
5386 for (auto t : adj) {
5387 int side, sense, offset;
5388 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
5389 if (sense == 1) {
5390 sides.first.insert(f);
5391 } else {
5392 sides.second.insert(f);
5393 }
5394 }
5395 }
5396 return sides;
5397 };
5398
5399 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
5400 // VOLUME_INTERFACE faces were already merged into interfaceFaces in
5401 // resolveDissipationEntities(), after applying REMOVE_INTERFACE exclusions.
5402 auto crack_side_faces = side_one_faces(crack_faces);
5403 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5404 auto ent = fe_method_ptr->getFEEntityHandle();
5405 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
5406 return false;
5407 }
5408 return true;
5409 };
5410 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5411 auto ent = fe_method_ptr->getFEEntityHandle();
5412 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
5413 return false;
5414 }
5415 return true;
5416 };
5417
5418 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5419 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5420 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
5421
5422 auto post_proc_begin =
5423 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5424 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5425 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
5426 post_proc_ptr->exeTestHook = side_one_crack_faces;
5428 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5429 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
5430 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5431 post_proc_negative_sense_ptr, 0,
5432 mField.get_comm_size());
5433
5434 constexpr bool debug = false;
5435 if (debug) {
5436
5437 auto get_adj_front = [&]() {
5438 auto skeleton_faces = *skeletonFaces;
5439 Range adj_front;
5440 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
5441 moab::Interface::UNION);
5442
5443 adj_front = intersect(adj_front, skeleton_faces);
5444 adj_front = subtract(adj_front, *crackFaces);
5445 adj_front = intersect(own_faces, adj_front);
5446 return adj_front;
5447 };
5448
5449 auto adj_front = filter_owners(mField, get_adj_front());
5450 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
5451 auto ent = fe_method_ptr->getFEEntityHandle();
5452 if (adj_front.find(ent) == adj_front.end()) {
5453 return false;
5454 }
5455 return true;
5456 };
5457
5458 post_proc_ptr->exeTestHook = only_front_faces;
5460 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5461 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
5462 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5463 post_proc_negative_sense_ptr, 0,
5464 mField.get_comm_size());
5465 }
5466 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5467 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5468
5469 CHKERR post_proc_end.writeFile(file.c_str());
5471}
5472
5474 const int tag, const std::string file, Vec f_residual,
5475 std::vector<Tag> tags_to_transfer, TS ts) {
5477
5479 if (f_residual != PETSC_NULLPTR) {
5481 f_r = createDMVector(dM);
5482 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
5483 f_residual, "ELASTIC_PROBLEM", RowColData::ROW, f_r,
5484 "ESHELBY_PLASTICITY", RowColData::ROW, scatter);
5485 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
5486 SCATTER_FORWARD);
5487 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
5488 SCATTER_FORWARD);
5489 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
5490 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
5491 }
5492
5494
5495 auto post_proc_mesh = boost::make_shared<moab::Core>();
5496 auto post_proc_ptr =
5497 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5498 mField, post_proc_mesh);
5499 if (ts != PETSC_NULLPTR) {
5500 post_proc_ptr->data_ctx |= PetscData::CtxSetTime;
5501 CHKERR TSGetTime(ts, &post_proc_ptr->ts_t);
5502 CHKERR TSGetTimeStep(ts, &post_proc_ptr->ts_dt);
5503 }
5504 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
5505 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5507
5508 auto hybrid_disp = boost::make_shared<MatrixDouble>();
5509 post_proc_ptr->getOpPtrVector().push_back(
5511 post_proc_ptr->getOpPtrVector().push_back(
5513 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
5514
5515 auto op_loop_domain_side =
5517 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5518 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
5519
5520 MaterialPostProcData material_output;
5521 CHKERR physicalEquations->pushSkeletonEvaluation(
5522 *this, *op_loop_domain_side->getSideFEPtr(), dataAtPts, f_r,
5523 material_output);
5524
5526
5527 OpPPMap::DataMapMat vec_fields = material_output.vectorFields;
5528 vec_fields["HybridDisplacement"] = hybrid_disp;
5529 // note that grad and omega have not trace, so this is only other side value
5530 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
5531 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5532 OpPPMap::DataMapMat mat_fields;
5533 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5534 mat_fields["HybridDisplacementGradient"] =
5535 dataAtPts->getGradHybridDispAtPts();
5536 OpPPMap::DataMapMat mat_fields_symm = material_output.symmetricFields;
5537
5538 post_proc_ptr->getOpPtrVector().push_back(
5539
5540 new OpPPMap(
5541
5542 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5543
5544 material_output.scalarFields,
5545
5546 vec_fields,
5547
5548 mat_fields,
5549
5550 mat_fields_symm
5551
5552 )
5553
5554 );
5555
5556 if (f_residual) {
5557 auto hybrid_res = boost::make_shared<MatrixDouble>();
5558 post_proc_ptr->getOpPtrVector().push_back(
5560 f_r));
5562 post_proc_ptr->getOpPtrVector().push_back(
5563
5564 new OpPPMap(
5565
5566 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5567
5568 {},
5569
5570 {{"res_hybrid", hybrid_res}},
5571
5572 {},
5573
5574 {}
5575
5576 )
5577
5578 );
5579 }
5580
5581 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5582
5583 auto post_proc_begin =
5584 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5585 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5586 CHKERR DMoFEMLoopFiniteElements(dM, skeletonElement, post_proc_ptr);
5587 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5588 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5589
5590 CHKERR post_proc_end.writeFile(file.c_str());
5591
5593}
5594
5595//! [Getting norms]
5598
5599 auto post_proc_norm_fe =
5600 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
5601
5602 auto bubble_cache =
5603 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
5604 post_proc_norm_fe->getUserPolynomialBase() =
5605 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase(bubble_cache));
5606 post_proc_norm_fe->getRuleHook = [](int, int, int) { return -1; };
5607 post_proc_norm_fe->setRuleHook = SetIntegrationAtFrontVolume(
5608 frontVertices, frontAdjEdges, vol_rule, bubble_cache);
5609 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5610 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
5612
5613 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
5614 auto norms_vec =
5615 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
5616 CHKERR VecZeroEntries(norms_vec);
5617
5618 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
5619 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5620 post_proc_norm_fe->getOpPtrVector().push_back(
5622 post_proc_norm_fe->getOpPtrVector().push_back(
5624 post_proc_norm_fe->getOpPtrVector().push_back(
5625 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
5626 post_proc_norm_fe->getOpPtrVector().push_back(
5627 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
5628 post_proc_norm_fe->getOpPtrVector().push_back(
5629 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
5630 u_h1_ptr));
5631
5632 auto piola_ptr = boost::make_shared<MatrixDouble>();
5633 post_proc_norm_fe->getOpPtrVector().push_back(
5635 post_proc_norm_fe->getOpPtrVector().push_back(
5637 MBMAXTYPE));
5638
5639 post_proc_norm_fe->getOpPtrVector().push_back(
5640 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
5641
5642 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
5644 *post_proc_norm_fe);
5645 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
5646
5647 CHKERR VecAssemblyBegin(norms_vec);
5648 CHKERR VecAssemblyEnd(norms_vec);
5649 const double *norms;
5650 CHKERR VecGetArrayRead(norms_vec, &norms);
5651 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
5652 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
5653 MOFEM_LOG("EP", Sev::inform)
5654 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
5655 MOFEM_LOG("EP", Sev::inform)
5656 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
5657 CHKERR VecRestoreArrayRead(norms_vec, &norms);
5658
5660}
5661//! [Getting norms]
5662
5665
5666 auto bc_mng = mField.getInterface<BcManager>();
5668 "", piolaStress, false, false);
5669 CHKERR bc_mng->pushMarkDOFsOnEntities<BcDisplacementMeshsetType<BLOCKSET>>(
5670 "", piolaStress, false, false);
5671
5672 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
5673 auto get_fix_load_history = [&](const std::string &block_name) {
5674 for (const auto type_name : {"FIX_X", "FIX_Y", "FIX_Z", "FIX_ALL"}) {
5675 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5676 std::regex(
5677
5678 (boost::format("%s(.*)") % type_name).str()
5679
5680 ))
5681
5682 ) {
5683 if (it->getName() == block_name) {
5685 type_name, it->getMeshsetId(), "load_history");
5686 }
5687 }
5688 }
5689 return std::string();
5690 };
5691
5692 for (auto bc : bc_mng->getBcMapByBlockName()) {
5693 if (auto disp_bc = bc.second->dispBcPtr) {
5694
5695 auto [field_name, block_name] =
5697 MOFEM_LOG("EP", Sev::inform)
5698 << "Field name: " << field_name << " Block name: " << block_name;
5699 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
5700
5701 std::vector<double> block_attributes(6, 0.);
5702 if (disp_bc->data.flag1 == 1) {
5703 block_attributes[0] = disp_bc->data.value1;
5704 block_attributes[3] = 1;
5705 }
5706 if (disp_bc->data.flag2 == 1) {
5707 block_attributes[1] = disp_bc->data.value2;
5708 block_attributes[4] = 1;
5709 }
5710 if (disp_bc->data.flag3 == 1) {
5711 block_attributes[2] = disp_bc->data.value3;
5712 block_attributes[5] = 1;
5713 }
5714 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5715 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces,
5716 get_fix_load_history(block_name));
5717 }
5718 }
5719 // old way of naming blocksets for displacement BCs
5720 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
5721
5723 boost::make_shared<NormalDisplacementBcVec>();
5724 CHKERR getBc(bcSpatialNormalDisplacementVecPtr, "NORMAL_DISPLACEMENT", 1);
5725
5726 bcSpatialSpringVecPtr = boost::make_shared<SpringBcVec>();
5727 auto mesh_mng = mField.getInterface<MeshsetsManager>();
5728 for (auto it : mesh_mng->getCubitMeshsetPtr(
5729 std::regex((boost::format("(.*)%s(.*)") % "SPRING_BC").str()))) {
5730 std::vector<double> block_attributes;
5731 CHKERR it->getAttributes(block_attributes);
5732 if (block_attributes.size() < 2) {
5733 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5734 "In block %s expected 2 attributes, but given %ld",
5735 it->getName().c_str(), block_attributes.size());
5736 }
5737 Range faces;
5738 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
5739 true);
5740 MOFEM_LOG("EP", Sev::inform)
5741 << "Found spring BC on block " << it->getName();
5742 MOFEM_LOG("EP", Sev::inform)
5743 << " kn = " << block_attributes[0] << ", kt = " << block_attributes[1];
5744 MOFEM_LOG("EP", Sev::inform) << " nb. of faces " << faces.size();
5745 bcSpatialSpringVecPtr->emplace_back(it->getName(), block_attributes, faces);
5746 }
5747
5749 boost::make_shared<AnalyticalDisplacementBcVec>();
5750 CHKERR getBc(bcSpatialAnalyticalDisplacementVecPtr, "ANALYTICAL_DISPLACEMENT",
5751 3);
5752
5753 auto ts_displacement =
5754 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
5755 for (auto &bc : *bcSpatialDispVecPtr) {
5756 MOFEM_LOG("EP", Sev::noisy)
5757 << "Add time scaling displacement BC: " << bc.blockName;
5758 if (!bc.loadHistoryFile.empty()) {
5759 MOFEM_LOG("EP", Sev::inform)
5760 << "Displacement load history from JSON for " << bc.blockName << ": "
5761 << bc.loadHistoryFile;
5762 timeScaleMap[bc.blockName] =
5763 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5764 } else {
5765 timeScaleMap[bc.blockName] =
5767 ts_displacement, "disp_history", ".txt", bc.blockName);
5768 }
5769 }
5770
5771 auto ts_normal_displacement =
5772 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
5773 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
5774 MOFEM_LOG("EP", Sev::noisy)
5775 << "Add time scaling normal displacement BC: " << bc.blockName;
5776 if (!bc.loadHistoryFile.empty()) {
5777 MOFEM_LOG("EP", Sev::inform)
5778 << "Normal displacement load history from JSON for " << bc.blockName
5779 << ": " << bc.loadHistoryFile;
5780 timeScaleMap[bc.blockName] =
5781 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5782 } else {
5783 timeScaleMap[bc.blockName] =
5785 ts_normal_displacement, "normal_disp_history", ".txt",
5786 bc.blockName);
5787 }
5788 }
5789
5791}
5792
5795
5796 auto bc_mng = mField.getInterface<BcManager>();
5798 false, false);
5799
5800 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
5801
5802 for (auto bc : bc_mng->getBcMapByBlockName()) {
5803 if (auto force_bc = bc.second->forceBcPtr) {
5804
5805 auto [field_name, block_name] =
5807 MOFEM_LOG("EP", Sev::inform)
5808 << "Field name: " << field_name << " Block name: " << block_name;
5809 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
5810
5811 std::vector<double> block_attributes(6, 0.);
5812 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
5813 block_attributes[3] = 1;
5814 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
5815 block_attributes[4] = 1;
5816 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
5817 block_attributes[5] = 1;
5818 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5819 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
5820 faces);
5821 }
5822 }
5823 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
5824
5825 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
5826 CHKERR getBc(bcSpatialPressureVecPtr, "PRESSURE", 1);
5827
5829 boost::make_shared<AnalyticalTractionBcVec>();
5830 CHKERR getBc(bcSpatialAnalyticalTractionVecPtr, "ANALYTICAL_TRACTION", 3);
5831
5832 auto ts_traction =
5833 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
5834 for (auto &bc : *bcSpatialTractionVecPtr) {
5835 if (!bc.loadHistoryFile.empty()) {
5836 MOFEM_LOG("EP", Sev::inform)
5837 << "Traction load history from JSON for " << bc.blockName << ": "
5838 << bc.loadHistoryFile;
5839 timeScaleMap[bc.blockName] =
5840 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5841 } else {
5842 timeScaleMap[bc.blockName] =
5844 ts_traction, "traction_history", ".txt", bc.blockName);
5845 }
5846 }
5847
5848 auto ts_pressure =
5849 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
5850 for (auto &bc : *bcSpatialPressureVecPtr) {
5851 if (!bc.loadHistoryFile.empty()) {
5852 MOFEM_LOG("EP", Sev::inform)
5853 << "Pressure load history from JSON for " << bc.blockName << ": "
5854 << bc.loadHistoryFile;
5855 timeScaleMap[bc.blockName] =
5856 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5857 } else {
5858 timeScaleMap[bc.blockName] =
5860 ts_pressure, "pressure_history", ".txt", bc.blockName);
5861 }
5862 }
5863
5865}
5866
5869
5870 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
5871 &ext_strain_vec_ptr,
5872 const std::string block_name,
5873 const int nb_attributes) {
5875 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5876 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
5877 std::vector<double> block_attributes;
5878 const bool analytical_external_strain = std::regex_match(
5879 it->getName(), std::regex("(.*)ANALYTICAL_EXTERNALSTRAIN(.*)"));
5880 const std::string json_block_name =
5881 analytical_external_strain ? "ANALYTICAL_EXTERNALSTRAIN" : block_name;
5882
5883 CHKERR it->getAttributes(block_attributes);
5884
5885 if (block_attributes.size() < nb_attributes) {
5886 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5887 "In block %s expected %d attributes, but given %ld",
5888 it->getName().c_str(), nb_attributes, block_attributes.size());
5889 }
5890
5891 auto get_block_ents = [&]() {
5892 Range ents;
5893 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
5894 true);
5895 return ents;
5896 };
5897
5898 std::string load_history;
5899 if (!analytical_external_strain) {
5900 load_history = getStringArgumentFromJsonBlockset(
5901 json_block_name, it->getMeshsetId(), "load_history");
5902 }
5903 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
5904 get_block_ents(), load_history);
5905 }
5907 };
5908
5909 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
5910
5911 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
5912
5913 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
5914 "externalstrain_history.txt");
5915 for (auto &ext_strain_block : *externalStrainVecPtr) {
5916 MOFEM_LOG("EP", Sev::noisy)
5917 << "Add time scaling external strain: " << ext_strain_block.blockName;
5918 if (!ext_strain_block.loadHistoryFile.empty()) {
5919 MOFEM_LOG("EP", Sev::inform)
5920 << "External strain load history from JSON for "
5921 << ext_strain_block.blockName << ": "
5922 << ext_strain_block.loadHistoryFile;
5923 timeScaleMap[ext_strain_block.blockName] =
5924 boost::make_shared<DynamicRelaxationTimeScale>(
5925 ext_strain_block.loadHistoryFile);
5926 } else {
5927 timeScaleMap[ext_strain_block.blockName] =
5929 ts_pre_stretch, "externalstrain_history", ".txt",
5930 ext_strain_block.blockName);
5931 }
5932 }
5933
5935}
5936
5939
5940 auto print_loc_size = [this](auto v, auto str, auto sev) {
5942 int size;
5943 CHKERR VecGetLocalSize(v.second, &size);
5944 int low, high;
5945 CHKERR VecGetOwnershipRange(v.second, &low, &high);
5946 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5947 << " " << high << " ) ";
5950 };
5951
5953 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5954 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5956 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5957 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5959 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5960 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5962 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5963 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5964
5966}
5967
5969 double start_time) {
5971
5972 loadFactorTSSolveExecuted = PETSC_FALSE;
5973
5974 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5975
5977
5978 auto setup_ts_monitor = [&]() {
5979 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5980 return monitor_ptr;
5981 };
5982 auto monitor_ptr = setup_ts_monitor();
5983
5984 auto test_monitor_ptr =
5985 boost::make_shared<EshelbianTestingMonitor>(*this, monitor_ptr);
5986
5987 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5988 {elasticFeLhs.get(), elasticFeRhs.get()});
5989 CHKERR TSSetUp(ts);
5990 CHKERR TSElasticPostStep::postStepInitialise(this);
5991
5992 double ts_delta_time;
5993 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5994
5995 if (physicalH1Update) {
5996 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5997 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5998 }
5999
6000 CHKERR TSElasticPostStep::preStepFun(ts);
6001 CHKERR TSElasticPostStep::postStepFun(ts);
6002
6003 double load_factor_change_clip = 0.1;
6004
6005 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Load Factor Options", "none");
6006
6007 CHKERR PetscOptionsScalar("-initial_load_factor", "Initial load factor", "",
6008 loadFactor, &loadFactor, PETSC_NULLPTR);
6009 CHKERR PetscOptionsScalar(
6010 "-max_crack_ext_area", "Maximum crack extension area", "",
6011 maxCrackExtension, &maxCrackExtension, PETSC_NULLPTR);
6012 CHKERR PetscOptionsScalar(
6013 "-clip_load_factor_percent", "Upper bound for load factor change", "",
6014 load_factor_change_clip, &load_factor_change_clip, PETSC_NULLPTR);
6015 PetscOptionsEnd();
6016
6018 physicalStepNumber = start_step;
6019 double initial_dt = physicalDt;
6020 monitor_ptr->ts = ts;
6021 monitor_ptr->ts_u = PETSC_NULLPTR;
6022 monitor_ptr->ts_t = currentPhysicalTime;
6023 monitor_ptr->ts_step = physicalStepNumber;
6025
6026 PetscBool test_cook_flg = PETSC_FALSE;
6027 PetscInt atom_test = 0;
6028 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
6029 PETSC_NULLPTR);
6030 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
6031 PETSC_NULLPTR);
6032 if (atom_test || test_cook_flg) {
6033 test_monitor_ptr->ts = ts;
6034 test_monitor_ptr->ts_u = PETSC_NULLPTR;
6035 test_monitor_ptr->ts_t = currentPhysicalTime;
6036 test_monitor_ptr->ts_step = physicalStepNumber;
6037
6039 test_monitor_ptr);
6040 }
6041
6042 MOFEM_LOG("EP", Sev::inform)
6043 << "Initial crack area: " << *currentCrackAreaPtr;
6044 MOFEM_LOG("EP", Sev::inform) << "Initial load factor: " << loadFactor;
6045 MOFEM_LOG("EP", Sev::inform)
6046 << "Initial crack front energy: " << avgGriffithsEnergy;
6047
6048 double load_factor_modifier = 1.0;
6049
6051 MOFEM_LOG("EP", Sev::inform)
6052 << "Load step " << physicalStepNumber << " Load Factor "
6053 << currentPhysicalTime << " delta load factor " << physicalDt;
6054
6058
6059 CHKERR TSSetStepNumber(ts, 0);
6060 CHKERR TSSetTime(ts, 0);
6061 CHKERR TSSetTimeStep(ts, ts_delta_time);
6062 if (!physicalH1Update) {
6063 CHKERR TSElasticPostStep::preStepFun(ts);
6064 }
6065 CHKERR TSSetSolution(ts, x);
6066 CHKERR TSSolve(ts, PETSC_NULLPTR);
6067 loadFactorTSSolveExecuted = PETSC_TRUE;
6068 if (!physicalH1Update) {
6069 CHKERR TSElasticPostStep::postStepFun(ts);
6070 }
6071
6072 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6073 SCATTER_FORWARD);
6074 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6075 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6076
6077 monitor_ptr->ts = ts;
6078 monitor_ptr->ts_u = x;
6079 monitor_ptr->ts_t = currentPhysicalTime;
6080 monitor_ptr->ts_step = physicalStepNumber;
6082
6083 if (atom_test || test_cook_flg) {
6084 test_monitor_ptr->ts = ts;
6085 test_monitor_ptr->ts_u = x;
6086 test_monitor_ptr->ts_t = currentPhysicalTime;
6087 test_monitor_ptr->ts_step = physicalStepNumber;
6089 test_monitor_ptr);
6090 }
6091
6092 if (mField.get_comm_rank() == 0) {
6093
6094 auto update_load_factor_modifier = [&](auto reason) {
6095 if (nbStepsNoCrackExtension > 1) {
6096 MOFEM_LOG("EP", Sev::warning)
6097 << reason << " for " << nbStepsNoCrackExtension
6098 << " consecutive steps. Increasing load factor range to allow "
6099 "for larger increments.";
6100 load_factor_modifier += 1.0;
6101 } else {
6102 load_factor_modifier = 1.0;
6103 }
6104 };
6105
6106 const bool crack_arrest_stops =
6108 update_load_factor_modifier(crack_arrest_stops
6109 ? "Potential crack arrest"
6110 : "No cracking occured");
6111
6112 if (crack_arrest_stops) {
6113 physicalDt = initial_dt * load_factor_modifier;
6115 MOFEM_LOG("EP", Sev::warning)
6116 << "Potential crack arrest detected. Increasing load factor by "
6117 << physicalDt << " to: " << loadFactor;
6118 } else {
6119 const double denom = 0.5 * std::abs(avgGriffithsEnergy);
6120 if (denom > 0.0) {
6121 const double updated_load_factor =
6122 oldLoadFactor * std::sqrt(griffithEnergy / denom);
6123 loadFactor = std::max(updated_load_factor, 1.0e-6);
6124 } else {
6125 MOFEM_LOG("EP", Sev::warning)
6126 << "Griffith energy is zero, cannot update load factor.";
6127 }
6128
6129 // Clip load factor.
6130 const bool is_first_step = physicalStepNumber == start_step;
6131 const double initial_step_range = 0;
6132 const double min_load_factor = 1.0e-6;
6133 const double max_load_factor =
6135 (1.0 + load_factor_change_clip * load_factor_modifier);
6136
6137 if (physicalStepNumber >= start_step + initial_step_range) {
6138 loadFactor = std::clamp(loadFactor, min_load_factor, max_load_factor);
6139 MOFEM_LOG("EP", Sev::inform)
6140 << "Allowable range for load factor [" << min_load_factor << ", "
6141 << max_load_factor << "]";
6142 }
6143
6144 // update load factor increment for next step
6146 }
6147
6148 MOFEM_LOG("EP", Sev::inform)
6149 << "Setting new load factor to: " << loadFactor;
6150 }
6151 double load_control_data[] = {physicalDt, loadFactor};
6152 CHKERR MPI_Bcast(load_control_data, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
6153 physicalDt = load_control_data[0];
6154 loadFactor = load_control_data[1];
6155
6158 break;
6159
6160 const double remainingPhysicalTime =
6162 if (physicalDt >= remainingPhysicalTime) {
6164 } else {
6166 }
6167 }
6168
6169 CHKERR TSElasticPostStep::postStepDestroy();
6170 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6171 {elasticFeLhs.get(), elasticFeRhs.get()});
6172 MOFEM_LOG("EP", Sev::inform) << "Final load factor: " << loadFactor;
6173
6175}
6176
6178 int start_step,
6179 double start_time) {
6181
6182 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6183
6184 auto topological_tao_ctx = createTopologicalTAOCtx(
6185 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6186 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6187 SmartPetscObj<TS>(ts, true));
6188
6189 double final_time = 1;
6190 double delta_time = 0.1;
6191 int max_it = 10;
6192 PetscBool ts_h1_update = PETSC_FALSE;
6193
6194 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
6195
6196 CHKERR PetscOptionsScalar("-dynamic_final_time",
6197 "dynamic relaxation final time", "", final_time,
6198 &final_time, PETSC_NULLPTR);
6199 CHKERR PetscOptionsScalar("-dynamic_delta_time",
6200 "dynamic relaxation final time", "", delta_time,
6201 &delta_time, PETSC_NULLPTR);
6202 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
6203 max_it, &max_it, PETSC_NULLPTR);
6204 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
6205 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
6206
6207 PetscOptionsEnd();
6208
6209 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6210 MOFEM_LOG("EP", Sev::inform)
6211 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
6212 MOFEM_LOG("EP", Sev::inform)
6213 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
6214 MOFEM_LOG("EP", Sev::inform)
6215 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
6216 MOFEM_LOG("EP", Sev::inform)
6217 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
6218 << (ts_h1_update ? "TRUE" : "FALSE");
6219
6221
6222 auto setup_ts_monitor = [&]() {
6223 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6224 return monitor_ptr;
6225 };
6226 auto monitor_ptr = setup_ts_monitor();
6227
6228 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6229 {elasticFeLhs.get(), elasticFeRhs.get()});
6230 CHKERR TSSetUp(ts);
6231 CHKERR TSElasticPostStep::postStepInitialise(this);
6232
6233 double ts_delta_time;
6234 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6235
6236 if (ts_h1_update) {
6237 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6238 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6239 }
6240
6241 CHKERR TSElasticPostStep::preStepFun(ts);
6242 CHKERR TSElasticPostStep::postStepFun(ts);
6243
6244 auto tao = createTao(mField.get_comm());
6245 CHKERR TaoSetType(tao, TAOLMVM);
6248 topologicalEvaluateObjectiveAndGradient,
6249 (void *)topological_tao_ctx.get());
6250
6251 currentPhysicalTime = start_time;
6252 physicalStepNumber = start_step;
6253 monitor_ptr->ts = PETSC_NULLPTR;
6254 monitor_ptr->ts_u = PETSC_NULLPTR;
6255 monitor_ptr->ts_t = currentPhysicalTime;
6256 monitor_ptr->ts_step = physicalStepNumber;
6258
6259 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6260 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6261 SCATTER_FORWARD, RowColData::ROW);
6262 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6263 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6264
6265 int tao_sol_size, tao_sol_loc_size;
6266 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6267 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6268 MOFEM_LOG("EP", Sev::inform)
6269 << "Toplogical data vector size " << tao_sol_size << " local size "
6270 << tao_sol_loc_size << " number of interface faces "
6271 << interfaceFaces->size();
6272
6273 CHKERR TaoSetFromOptions(tao);
6274
6275 if (delta_time <= 0.) {
6277 "delta_time must be positive, got %g", delta_time);
6278 }
6279 for (; currentPhysicalTime < final_time;) {
6280 MOFEM_LOG("EP", Sev::inform)
6281 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
6282 << " delta time " << delta_time;
6283
6284 CHKERR VecZeroEntries(tao_sol0);
6285 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6286 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6287 CHKERR TaoSetSolution(tao, tao_sol0);
6288 CHKERR TaoSolve(tao);
6289 Vec tao_sol;
6290 CHKERR TaoGetSolution(tao, &tao_sol);
6291
6292 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6293 SCATTER_FORWARD);
6294 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6295 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6296 monitor_ptr->ts = PETSC_NULLPTR;
6297 monitor_ptr->ts_u = x;
6298 monitor_ptr->ts_t = currentPhysicalTime;
6299 monitor_ptr->ts_step = physicalStepNumber;
6301
6303 if (physicalStepNumber > max_it)
6304 break;
6305
6306 const double remainingPhysicalTime = final_time - currentPhysicalTime;
6307 if (delta_time >= remainingPhysicalTime) {
6308 currentPhysicalTime = final_time;
6309 } else {
6310 currentPhysicalTime += delta_time;
6311 }
6312 }
6313
6314 CHKERR TSElasticPostStep::postStepDestroy();
6315 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6316 {elasticFeLhs.get(), elasticFeRhs.get()});
6317
6319}
6320
6323 double start_time) {
6325
6326 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6329
6330 auto topological_tao_ctx = createTopologicalTAOCtx(
6331 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6332 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6333 SmartPetscObj<TS>(ts, true));
6334
6335 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6337
6338 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6339
6340 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6341 {elasticFeLhs.get(), elasticFeRhs.get()});
6342 CHKERR TSSetUp(ts);
6343 CHKERR TSElasticPostStep::postStepInitialise(this);
6344
6345 double ts_delta_time;
6346 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6347
6348 if (physicalH1Update) {
6349 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6350 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6351 }
6352
6353 CHKERR TSElasticPostStep::preStepFun(ts);
6354 CHKERR TSElasticPostStep::postStepFun(ts);
6355
6356 const bool restart_run =
6357 start_step != 0 ||
6358 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6359 const double test_time = restart_run ? start_time : finalPhysicalTime;
6360 if (!restart_run &&
6361 std::abs(test_time) < std::numeric_limits<double>::epsilon()) {
6362 SETERRQ(
6364 "Set non-zero -physical_final_time for test_topological_derivative");
6365 }
6366
6367 currentPhysicalTime = test_time;
6368 physicalStepNumber = start_step;
6369 monitor_ptr->ts = PETSC_NULLPTR;
6370 monitor_ptr->ts_u = PETSC_NULLPTR;
6371 monitor_ptr->ts_t = currentPhysicalTime;
6372 monitor_ptr->ts_step = physicalStepNumber;
6374
6375 MOFEM_LOG("EP", Sev::inform)
6376 << "Solving load step before topological derivative test: "
6377 << physicalStepNumber << " Time " << currentPhysicalTime
6378 << " TS delta time " << ts_delta_time;
6379
6380 CHKERR TSSetStepNumber(ts, 0);
6381 CHKERR TSSetTime(ts, 0);
6382 CHKERR TSSetTimeStep(ts, ts_delta_time);
6383 if (!physicalH1Update) {
6384 CHKERR TSElasticPostStep::preStepFun(ts);
6385 }
6386 CHKERR TSSetSolution(ts, x);
6387 CHKERR TSSolve(ts, PETSC_NULLPTR);
6388 if (!physicalH1Update) {
6389 CHKERR TSElasticPostStep::postStepFun(ts);
6390 }
6391
6392 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES, SCATTER_FORWARD);
6393 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6394 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6395
6396 monitor_ptr->ts = PETSC_NULLPTR;
6397 monitor_ptr->ts_u = x;
6398 monitor_ptr->ts_t = currentPhysicalTime;
6399 monitor_ptr->ts_step = physicalStepNumber;
6401
6402 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6403 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6404 SCATTER_FORWARD, RowColData::ROW);
6405 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6406 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6407
6408 int tao_sol_size, tao_sol_loc_size;
6409 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6410 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6411 MOFEM_LOG("EP", Sev::inform)
6412 << "Topological data vector size " << tao_sol_size << " local size "
6413 << tao_sol_loc_size << " number of interface faces "
6414 << interfaceFaces->size();
6415
6416 const char *list_objective_models[ObjectiveModelType::LAST_MODEL] = {
6417 "python_model", "hencky_model"};
6418#ifdef ENABLE_PYTHON_BINDING
6419 PetscInt choice_objective_model = ObjectiveModelType::PYTHON_MODEL;
6420#else
6421 PetscInt choice_objective_model = ObjectiveModelType::HENCKY_MODEL;
6422#endif
6423 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, PETSC_NULLPTR,
6424 "-objective_model_type", list_objective_models,
6425 ObjectiveModelType::LAST_MODEL,
6426 &choice_objective_model, PETSC_NULLPTR);
6427 const auto objective_model_type =
6428 static_cast<ObjectiveModelType>(choice_objective_model);
6429 MOFEM_LOG("EP", Sev::inform) << "Objective model type: -objective_model_type "
6430 << list_objective_models[objective_model_type];
6431
6433 PetscReal obj_value;
6434 CHKERR testTopologicalDerivative(topological_tao_ctx.get(), tao_sol0,
6435 &obj_value, g, objective_model_type);
6436
6437 CHKERR TSElasticPostStep::postStepDestroy();
6438 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6439 {elasticFeLhs.get(), elasticFeRhs.get()});
6440
6442}
6443
6446 double start_time) {
6448
6451 "The equilibrated mechanical value test requires "
6452 "-plastic_volume 1 and -cohesive_interface_on 0");
6453 CHKERR validateEquilibratedMechanicalValueScope(*this);
6454
6455 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6459
6460 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6461 {elasticFeLhs.get(), elasticFeRhs.get()});
6462 CHKERR TSSetSolution(ts, x);
6463 CHKERR TSSetUp(ts);
6464 CHKERR TSElasticPostStep::postStepInitialise(this);
6465
6466 const bool restart_run =
6467 start_step != 0 ||
6468 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6469 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6470 if (std::abs(currentPhysicalTime) < std::numeric_limits<double>::epsilon())
6472 "Set non-zero -physical_final_time for "
6473 "test_equilibrated_mechanical_value");
6474 physicalStepNumber = start_step;
6475
6476 CHKERR testEquilibratedMechanicalValue(*this, ts, x);
6477
6478 CHKERR TSElasticPostStep::postStepDestroy();
6479 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6480 {elasticFeLhs.get(), elasticFeRhs.get()});
6481
6483}
6484
6487 double start_time) {
6489
6492 "The incremental-optimization transaction test currently requires "
6493 "-plastic_volume 1 and -cohesive_interface_on 0");
6494 CHKERR validateEquilibratedMechanicalValueScope(*this);
6495
6496 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6500
6501 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6502 {elasticFeLhs.get(), elasticFeRhs.get()});
6503 CHKERR TSSetSolution(ts, x);
6504 CHKERR TSSetUp(ts);
6505 CHKERR TSElasticPostStep::postStepInitialise(this);
6506
6507 const bool restart_run =
6508 start_step != 0 ||
6509 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6510 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6511 if (std::abs(currentPhysicalTime) < std::numeric_limits<double>::epsilon())
6513 "Set non-zero -physical_final_time for "
6514 "test_incremental_optimization_transaction");
6515 physicalStepNumber = start_step;
6516
6517 CHKERR testIncrementalOptimizationTransaction(*this, ts, x);
6518
6519 CHKERR TSElasticPostStep::postStepDestroy();
6520 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6521 {elasticFeLhs.get(), elasticFeRhs.get()});
6523}
6524
6527 TS ts, Vec x, int start_step, double start_time) {
6529
6532 "The incremental-optimization derivative test currently requires "
6533 "-plastic_volume 1 and -cohesive_interface_on 0");
6534 CHKERR validateEquilibratedMechanicalValueScope(*this);
6535
6536 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6540
6541 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6542 {elasticFeLhs.get(), elasticFeRhs.get()});
6543 CHKERR TSSetSolution(ts, x);
6544 CHKERR TSSetUp(ts);
6545 CHKERR TSElasticPostStep::postStepInitialise(this);
6546
6547 const bool restart_run =
6548 start_step != 0 ||
6549 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6550 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6551 if (std::abs(currentPhysicalTime) <
6552 std::numeric_limits<double>::epsilon())
6554 "Set non-zero -physical_final_time for "
6555 "test_incremental_optimization_objective_derivative");
6556 physicalStepNumber = start_step;
6557
6558 CHKERR testIncrementalOptimizationObjectiveDerivative(*this, ts, x);
6559
6560 CHKERR TSElasticPostStep::postStepDestroy();
6561 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6562 {elasticFeLhs.get(), elasticFeRhs.get()});
6564}
6565
6568 TS ts, Vec x, int start_step, double start_time) {
6570
6573 "The incremental-optimization constraint derivative test "
6574 "requires -plastic_volume 1 and -cohesive_interface_on 0");
6575 CHKERR validateEquilibratedMechanicalValueScope(*this);
6576
6577 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6581
6582 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6583 {elasticFeLhs.get(), elasticFeRhs.get()});
6584 CHKERR TSSetSolution(ts, x);
6585 CHKERR TSSetUp(ts);
6586 CHKERR TSElasticPostStep::postStepInitialise(this);
6587
6588 const bool restart_run =
6589 start_step != 0 ||
6590 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6591 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6592 if (std::abs(currentPhysicalTime) <
6593 std::numeric_limits<double>::epsilon())
6595 "Set non-zero -physical_final_time for "
6596 "test_incremental_optimization_constraint_derivative");
6597 physicalStepNumber = start_step;
6598
6599 CHKERR testIncrementalOptimizationConstraintDerivative(*this, ts, x);
6600
6601 CHKERR TSElasticPostStep::postStepDestroy();
6602 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6603 {elasticFeLhs.get(), elasticFeRhs.get()});
6605}
6606
6608 TS ts, Vec x, int start_step, double start_time) {
6610
6613 "-solver_type incremental_optimization currently supports "
6614 "-plastic_volume 1 and -cohesive_interface_on 0 only");
6615 CHKERR validateEquilibratedMechanicalValueScope(*this);
6616 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6620
6621 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6622 {elasticFeLhs.get(), elasticFeRhs.get()});
6623 CHKERR TSSetSolution(ts, x);
6624 CHKERR TSSetUp(ts);
6625 CHKERR TSElasticPostStep::postStepInitialise(this);
6626
6627 if (!(finalPhysicalTime > start_time))
6629 "Incremental-optimization final physical time %g must exceed "
6630 "the start time %g",
6631 finalPhysicalTime, start_time);
6632 if (!(physicalDt > 0.))
6634 "Incremental-optimization physical time step must be positive, "
6635 "got %g",
6636 physicalDt);
6637 if (physicalMaxSteps <= 0)
6639 "Incremental-optimization physical maximum steps must be "
6640 "positive, got %d",
6642
6643 PetscBool monitor_physical_steps = PETSC_TRUE;
6644 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "",
6645 "-incremental_optimization_step_monitor",
6646 &monitor_physical_steps, PETSC_NULLPTR);
6647 boost::shared_ptr<EshelbianMonitor> monitor_ptr;
6648 if (monitor_physical_steps)
6649 monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6650 auto monitor_committed_step = [&]() {
6652 if (!monitor_ptr)
6654 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6655 SCATTER_FORWARD);
6656 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6657 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6658 monitor_ptr->ts = PETSC_NULLPTR;
6659 monitor_ptr->ts_u = x;
6660 monitor_ptr->ts_t = currentPhysicalTime;
6661 monitor_ptr->ts_step = physicalStepNumber;
6664 };
6665 auto clear_incremental_control_fields = [&]() {
6667 // Preserve committed kappa in mesh storage. Only Delta H_p is a transient
6668 // post-processing field; Delta kappa exists solely in the TAO vector.
6669 CHKERR PlasticIncrementalOptimizationInternal::clearPlasticIncrementFields(
6670 *this);
6672 };
6673
6674 currentPhysicalTime = start_time;
6675 physicalStepNumber = start_step;
6676 // PlasticFlow is an increment-only post-processing field. A restart mesh
6677 // can contain the last accepted increment, which must not be reported as
6678 // the increment of the freshly initialized physical step.
6679 CHKERR clear_incremental_control_fields();
6680 CHKERR monitor_committed_step();
6681
6682 const double time_tolerance =
6683 10 * std::numeric_limits<double>::epsilon() *
6684 std::max({1., std::abs(start_time), std::abs(finalPhysicalTime)});
6685 int completed_steps = 0;
6686 while (currentPhysicalTime + time_tolerance < finalPhysicalTime &&
6687 completed_steps < physicalMaxSteps) {
6688 const double previous_time = currentPhysicalTime;
6690 std::min(previous_time + physicalDt, finalPhysicalTime);
6691 physicalStepNumber = start_step + completed_steps + 1;
6692
6693 MOFEM_LOG("EP", Sev::inform)
6694 << "Incremental-optimization load step " << physicalStepNumber
6695 << " time " << currentPhysicalTime << " delta time "
6696 << currentPhysicalTime - previous_time;
6697
6698 if (physicalH1Update) {
6699 CHKERR TSSetSolution(ts, x);
6700 CHKERR TSSetTime(ts, currentPhysicalTime);
6701 CHKERR TSElasticPostStep::preStepFun(ts);
6702 }
6703
6705
6706 if (physicalH1Update) {
6707 CHKERR TSSetSolution(ts, x);
6708 CHKERR TSSetTime(ts, currentPhysicalTime);
6709 CHKERR TSElasticPostStep::postStepFun(ts);
6710 }
6711
6712 const MoFEMErrorCode monitor_error = monitor_committed_step();
6713 const MoFEMErrorCode clear_control_error =
6714 clear_incremental_control_fields();
6715 CHKERR monitor_error;
6716 CHKERR clear_control_error;
6717 ++completed_steps;
6718 }
6719
6720 const bool reached_final_time =
6721 currentPhysicalTime + time_tolerance >= finalPhysicalTime;
6722
6723 CHKERR TSElasticPostStep::postStepDestroy();
6724 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6725 {elasticFeLhs.get(), elasticFeRhs.get()});
6726
6727 if (!reached_final_time)
6729 "Incremental optimization stopped at time %g after %d steps "
6730 "before final time %g; increase -physical_max_steps",
6731 currentPhysicalTime, completed_steps, finalPhysicalTime);
6732
6733 MOFEM_LOG("EP", Sev::inform)
6734 << "Incremental optimization completed " << completed_steps
6735 << " physical steps at time " << currentPhysicalTime;
6737}
6738
6739} // namespace EshelbianPlasticity
6740
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
Implementation of tonsorial bubble base div(v) = 0.
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
Implementation of CGGUserPolynomialBase class.
Auxilary functions for Eshelbian plasticity.
Contains definition of EshelbianMonitor class.
FormsIntegrators< FaceElementForcesAndSourcesCore::UserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMassVectorFace
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 9, 9 > OpStressGram_dBubble_dBubble
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 3, 9 > OpStressGram_dP_dP
static auto send_type(MoFEM::Interface &m_field, Range r, const EntityType type)
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto get_two_sides_of_crack_surface(MoFEM::Interface &m_field, Range crack_faces)
static auto get_range_from_block_map(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto filter_owners(MoFEM::Interface &m_field, Range skin)
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
static auto get_entities_by_handle(MoFEM::Interface &m_field, const std::string block_name)
static auto get_crack_front_edges(MoFEM::Interface &m_field, Range crack_faces)
Eshelbian plasticity interface.
Native restart vector layout validation.
Contains definition of EshelbianTestingMonitor class.
std::string type
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_C(channel, severity, format,...)
Shared implementation details for plastic incremental optimization.
Plasticity implementation of incremental optimization.
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
Definition adjoint.cpp:2291
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
cholesky decomposition
@ QUIET
@ VERBOSE
@ COL
@ ROW
@ MF_ZERO
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ NOBASE
Definition definitions.h:59
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define MOAB_THROW(err)
Check error code of MoAB function and throw MoFEM exception.
#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()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MYPCOMM_INDEX
default communicator number PCOMM
@ DISCONTINUOUS
Broken continuity (No effect on L2 space)
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
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
static const bool debug
PetscErrorCode ShapeMBTET(double *N, const double *G_X, const double *G_Y, const double *G_Z, int DIM)
calculate shape functions
Definition fem_tools.c:306
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
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 DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMTSSetIFunction(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set TS implicit function evaluation function
Definition DMMoFEM.cpp:790
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 DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
PetscErrorCode DMMoFEMGetTsCtx(DM dm, MoFEM::TsCtx **ts_ctx)
get MoFEM::TsCtx data structure
Definition DMMoFEM.cpp:1132
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMMoFEMTSSetIJacobian(DM dm, 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 TS Jacobian evaluation function
Definition DMMoFEM.cpp:843
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
PetscErrorCode DMMoFEMTSSetI2Jacobian(DM dm, 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 TS Jacobian evaluation function
Definition DMMoFEM.cpp:1007
PetscErrorCode DMMoFEMTSSetI2Function(DM dm, 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 TS implicit function evaluation function
Definition DMMoFEM.cpp:965
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
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_adjacency_table(const std::string &fe_name, const EntityType type, ElementAdjacencyFunct function)=0
modify finite element table, only for advanced user
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual bool check_field(const std::string &name) const =0
check if field is in database
@ GAUSS
Gaussian quadrature integration.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
virtual MoFEMErrorCode loop_finite_elements(const std::string problem_name, const std::string &fe_name, FEMethod &method, boost::shared_ptr< NumeredEntFiniteElement_multiIndex > fe_ptr=nullptr, MoFEMTypes bh=MF_EXIST, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr(), int verb=DEFAULT_VERBOSITY)=0
Make a loop over finite elements.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
MoFEMErrorCode addFieldToEmptyFieldBlocks(const std::string problem_name, const std::string row_field, const std::string col_field) const
Add empty field blocks to optimize matrix storage.
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.
#define NBVOLUMETET_L2(P)
Number of base functions on tetrahedron for L2 space.
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static MoFEMErrorCode checkDynamicToleranceCompatibility(TS ts)
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
ForcesAndSourcesCore::UserDataOperator * getOpContactDetection(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::shared_ptr< MatrixDouble > u_h1_ptr, boost::shared_ptr< MatrixDouble > contact_traction_ptr, Range r, moab::Interface *post_proc_mesh_ptr, std::vector< EntityHandle > *map_gauss_pts_ptr)
Push operator for contact detection.
boost::shared_ptr< ForcesAndSourcesCore > createContactDetectionFiniteElement(EshelbianCore &ep)
Create a Contact Tree finite element.
MoFEMErrorCode pushContactOpsRhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the right-hand side.
MoFEMErrorCode pushContactOpsLhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the left-hand side.
boost::shared_ptr< ContactSDFPython > setupContactSdf(MoFEM::Interface &m_field)
Read SDF file and setup contact SDF.
static MoFEMErrorCode RelaxationResidualMonitor(TS ts, PetscInt, PetscReal, Vec, void *)
MoFEMErrorCode addCalculatePlasticLogarithmicStretchFieldValues(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, const std::string &field_name, boost::shared_ptr< MatrixDouble > tensor_values, const EntityType zero_type, SmartPetscObj< DM > data_dm, SmartPetscObj< Vec > data_vector)
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
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
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
PetscErrorCode TsMonitorSet(TS ts, PetscInt step, PetscReal t, Vec u, void *ctx)
Set monitor for TS solver.
Definition TsCtx.cpp:263
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1279
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:434
MoFEMErrorCode MoFEMSNESMonitorEnergy(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:656
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
static const bool debug
auto id_from_handle(const EntityHandle h)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PostProcBrokenMeshInMoabBaseEndImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseEnd
Enable to run stack of post-processing elements. Use this to end stack.
PostProcBrokenMeshInMoabBaseBeginImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseBegin
Enable to run stack of post-processing elements. Use this to begin stack.
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.
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
Definition TaoCtx.cpp:178
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1265
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
auto createTao(MPI_Comm comm)
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
int r
Definition sdf.py:205
constexpr AssemblyType A
double h
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
constexpr double g
FTensor::Index< 'm', 3 > m
CGG User Polynomial Base.
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field, EshelbianCore *ep_core_ptr)
SmartPetscObj< Vec > incrementalTrialControl
MoFEMErrorCode setElasticElementOps(const int tag)
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
static PetscBool physicalH1Update
static enum StretchSelector stretchSelector
boost::shared_ptr< Range > frontAdjEdges
static int interfaceRemoveLevel
MoFEMErrorCode addBoundaryFiniteElement(const EntityHandle meshset=0)
const std::string skeletonElement
static double inv_dd_f_linear(const double)
static double inv_f_linear(const double v)
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
boost::shared_ptr< Range > contactFaces
static double dd_f_log_e_quadratic(const double v)
static double inv_d_f_linear(const double)
double dynamicInitialResidual
static double dd_f_linear(const double)
BitRefLevel bitAdjEnt
bit ref level for parent
static boost::function< double(const double)> inv_dd_f
MoFEM::Interface & mField
const std::string spatialL2Disp
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static enum SolverType solverType
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
static PetscBool l2UserBaseScale
SmartPetscObj< DM > dM
Coupled problem all fields.
MoFEMErrorCode solveSchapeOptimisation(TS ts, Vec x, int start_step, double start_time)
Solve shape optimisation problem.
boost::shared_ptr< Range > plasticVolumes
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
static const char * listSolvers[]
const std::string materialH1Positions
static int nbJIntegralContours
MoFEMErrorCode applyTestSolverMonitorOptions(TS ts)
MoFEMErrorCode setBlockTagsOnSkin()
static PetscBool crackingOn
MoFEMErrorCode getTractionFreeBc(const EntityHandle meshset, boost::shared_ptr< TractionFreeBc > &bc_ptr, const std::string contact_set_name)
Remove all, but entities where kinematic constrains are applied.
MoFEMErrorCode applyProjectionSolverMonitorOptions()
static double griffithEnergy
Griffith energy.
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
MoFEMErrorCode postProcessRestartMesh(const int tag, const std::string file, std::vector< Tag > tags_to_transfer={})
MoFEMErrorCode pushVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
const std::string elementVolumeName
static double dd_f_log_e(const double v)
static double d_f_linear(const double)
static enum RotSelector rotSelector
MoFEMErrorCode addDebugModel(TS ts)
Add debug to model.
static enum RotSelector gradApproximator
PetscBool loadFactorTSSolveExecuted
MoFEMErrorCode postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, Vec gradient=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
MoFEMErrorCode getBc(boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
static double inv_dd_f_log_e_quadratic(const double stretch)
static double physicalDt
CommInterface::EntitiesPetscVector vertexExchange
static std::vector< std::string > listTagsToProject
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
static std::string heterogeneousYoungModTagName
const std::string spatialH1Disp
static FieldApproximationBase brokenHdivBase
static double maxCrackExtension
static int physicalMaxSteps
MoFEMErrorCode solveElastic(TS ts, Vec x)
@ TestIncrementalOptimizationConstraintDerivative
@ TestIncrementalOptimizationLayout
@ TestIncrementalOptimizationTransaction
@ TestIncrementalOptimizationObjectiveDerivative
@ TestEquilibratedMechanicalValue
boost::shared_ptr< NormalDisplacementBcVec > bcSpatialNormalDisplacementVecPtr
MoFEMErrorCode solveTestIncrementalOptimizationTransaction(TS ts, Vec x, int start_step, double start_time)
static double crackingStartTime
MoFEMErrorCode getOptions()
const std::string plasticHField
const std::string piolaStress
MoFEMErrorCode setElasticElementToTs(DM dm)
static double inv_d_f_log_e(const double v)
std::string getStringArgumentFromJsonBlockset(const std::string &type_name, const int meshset_id, const std::string &param_name)
static int physicalStepNumber
MoFEMErrorCode gettingNorms()
[Getting norms]
MoFEMErrorCode solveTestEquilibratedMechanicalValue(TS ts, Vec x, int start_step, double start_time)
boost::shared_ptr< Range > interfaceFaces
MoFEMErrorCode setVolumeElementOps(const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
static PetscBool physicalTimeFlg
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Getting interface of core database.
const std::string bubbleField
MoFEMErrorCode solveIncrementalOptimizationTAO(TS ts, Vec x, int start_step, double start_time)
Solve the incremental constitutive optimization with TAO.
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
const std::string plasticFlowField
SmartPetscObj< DM > dmMaterial
Material problem.
MoFEMErrorCode runIncrementalOptimizationTAO(TS ts, Vec x)
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
MoFEMErrorCode solveTestIncrementalOptimizationObjectiveDerivative(TS ts, Vec x, int start_step, double start_time)
MoFEMErrorCode resolveDissipationEntities(const EntityHandle meshset=0)
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
static double crackingAddTime
MoFEMErrorCode setFaceElementOps(const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
MoFEMErrorCode projectGeometry(const EntityHandle meshset=0, double time=0)
static double currentPhysicalTime
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
boost::shared_ptr< SpringBcVec > bcSpatialSpringVecPtr
static double crackingAtol
Cracking absolute tolerance.
MoFEMErrorCode projectMaterialTags(const EntityHandle meshset=0)
boost::shared_ptr< Range > skeletonFaces
static double crackingRtol
Cracking relative tolerance.
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
static PetscBool meshTransferHybridInterp
BitRefLevel bitAdjParentMask
bit ref level for parent parent
MoFEMErrorCode solveDynamicRelaxation(TS ts, Vec x, int start_step, double start_time)
Solve problem using dynamic relaxation method.
const std::string contactDisp
static std::string internalStressTagName
CommInterface::EntitiesPetscVector edgeExchange
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
static boost::function< double(const double)> f
MoFEMErrorCode solveTestTopologicalDerivative(TS ts, Vec x, int start_step, double start_time)
static int nbStepsNoCrackExtension
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
static double finalPhysicalTime
const std::string skinElement
static PetscBool internalStressVoigt
MoFEMErrorCode addVolumeFiniteElement(const EntityHandle meshset=0, const bool add_bubble=true)
MoFEMErrorCode solveTestIncrementalOptimizationConstraintDerivative(TS ts, Vec x, int start_step, double start_time)
static double inv_dd_f_log_e(const double v)
MoFEMErrorCode getExternalStrain()
MoFEMErrorCode getSpatialTractionBc()
static PetscBool setSingularity
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, const bool add_bubble=true)
static double d_f_log_e(const double v)
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
static PetscBool plasticVolume
boost::shared_ptr< double > currentCrackAreaPtr
static PetscBool meshTransferSourceMeshFileSpecified
static double f_log_e_quadratic(const double v)
double avgGriffithsEnergy
static double inv_f_log_e_quadratic(const double stretch)
MoFEMErrorCode addDMs(const BitRefLevel bit=BitRefLevel().set(0), const EntityHandle meshset=0)
MoFEMErrorCode getSpatialDispBc()
[Getting norms]
BitRefLevel bitAdjParent
bit ref level for parent
MoFEMErrorCode setContactElementRhsOps(boost::shared_ptr< ForcesAndSourcesCore > &fe_contact_tree)
static PetscBool interfaceCrack
MoFEMErrorCode solveLoadFactor(TS ts, Vec x, int start_step, double start_time)
Solve load factor crack growth problem.
static double d_f_log_e_quadratic(const double v)
CommInterface::EntitiesPetscVector volumeExchange
const std::string naturalBcElement
static boost::function< double(const double)> dd_f
static double f_log_e(const double v)
static bool potentialCrackArrest
static PetscBool propagateUnderCompression
static double inv_f_log_e(const double v)
MoFEMErrorCode createExchangeVectors(Sev sev)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > crackFaces
static boost::function< double(const double)> d_f
boost::shared_ptr< Range > frontVertices
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_d_f
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
static int meshTransferInterpOrder
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
static double inv_d_f_log_e_quadratic(const double stretch)
CommInterface::EntitiesPetscVector faceExchange
SmartPetscObj< DM > dmElastic
Elastic problem.
static std::string meshTransferSourceMeshFileName
EshelbianCore(MoFEM::Interface &m_field)
const std::string plasticKappaField
boost::shared_ptr< Range > frontEdges
static boost::function< double(const double)> inv_f
BitRefLevel bitAdjEntMask
bit ref level for parent parent
static double f_linear(const double v)
SmartPetscObj< DM > dmIncrementalOptimization
Incremental-optimization control problem.
MoFEMErrorCode addFields(const EntityHandle meshset=0, const bool add_bubble=true)
MoFEMErrorCode withFieldOrders(Op &&op) const
MoFEMErrorCode pushStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
const std::string contactElement
MoFEMErrorCode pushPiolaStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
AnalyticalDisplacementBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
AnalyticalTractionBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
BcRot(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
ExternalStrain(std::string name, std::vector< double > attr, Range ents, std::string load_history_file="")
NormalDisplacementBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
OpApplyPlasticFlowIncrement(boost::shared_ptr< DataAtIntegrationPts > data_ptr)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
MoFEMErrorCode doWork(int, EntityType, EntData &) override
Operator for linear form, usually to calculate values on right hand side.
PressureBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, int(*)(int))
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges)
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cachePhi
SetIntegrationAtFrontVolume(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cache_phi=nullptr)
SetIntegrationAtFrontVolume(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, FunRule fun_rule, boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cache_phi=nullptr)
SpringBc(std::string name, std::vector< double > attr, Range faces)
static MoFEMErrorCode preStepFun(TS ts)
static MoFEMErrorCode postStepFun(TS ts)
static MoFEMErrorCode postStepInitialise(EshelbianCore *ep_ptr)
TractionBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x, bool set_ts_monitor)
multi_index_container< DofsSideMapData, indexed_by< ordered_non_unique< tag< TypeSide_mi_tag >, composite_key< DofsSideMapData, member< DofsSideMapData, EntityType, &DofsSideMapData::type >, member< DofsSideMapData, int, &DofsSideMapData::side > > >, ordered_unique< tag< EntDofIdx_mi_tag >, member< DofsSideMapData, int, &DofsSideMapData::dof > > > > DofsSideMap
Map entity stype and side to element/entity dof index.
Template specialization for displacement boundary conditions.
Boundary condition manager for finite element problem setup.
static std::pair< std::string, std::string > extractStringFromBlockId(const std::string block_id, const std::string prb_name)
Extract block name and block name from block id.
Template specialization system for type-safe boundary condition handling.
Managing BitRefLevels.
Managing BitRefLevels.
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
static Range getPartEntities(moab::Interface &moab, int part)
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode add_broken_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const std::vector< std::pair< EntityType, std::function< MoFEMErrorCode(BaseFunction::DofsSideMap &)> > > list_dof_side_map, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual bool check_finite_element(const std::string &name) const =0
Check if finite element is in database.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
Structure for user loop methods on finite elements.
EntityHandle getFEEntityHandle() const
Get the entity handle of the current finite element.
Basic algebra on fields.
Definition FieldBlas.hpp:21
Field data structure for finite element approximation.
Definition of the force bc data structure.
Definition BCData.hpp:135
@ OPSPACE
operator do Work is execute on space data
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
structure to get information from mofem into EntitiesFieldData
static boost::shared_ptr< ScalingMethod > get(boost::shared_ptr< ScalingMethod > ts, std::string file_prefix, std::string file_suffix, std::string block_name, Args &&...args)
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
Mesh refinement interface.
Interface for managing meshsets containing materials and boundary conditions.
CubitMeshSet_multiIndex & getMeshsetsMultindex()
Natural boundary conditions.
Definition Natural.hpp:57
Operator for broken loop side.
Get norm of input MatrixDouble for Tensor1.
Get norm of input MatrixDouble for Tensor2.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate divergence of tonsorial field using vectorial base.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Calculate trace of vector (Hdiv/Hcurl) space.
Specialization for double precision scalar field values calculation.
Get field gradients time derivative at integration pts for scalar field rank 0, i....
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
Element used to execute operators on side of the element.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
std::map< std::string, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
@ CTX_SET_TIME
Time value is set.
static constexpr Switches CtxSetTime
Time value switch.
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.
Template struct for dimension-specific finite element types.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
intrusive_ptr for managing petsc objects
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 tetVolume(const double *coords)
Calculate volume of tetrahedron.
Definition Tools.cpp:30
static std::tuple< std::array< double, 3 >, std::array< double, 2 >, double > getTricircumcenter3d(double *coords_ptr)
Calculate triangle circumcenter in 3d.
Definition Tools.cpp:878
FEMethodsSequence & getLoopsMonitor()
Get the loops to do Monitor object.
Definition TsCtx.hpp:102
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Apply rotation boundary condition.
BoundaryEle::UserDataOperator BdyEleOp
int atom_test
Atom test.
Definition plastic.cpp:121
auto save_range