v0.16.0
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 <MoFEM.hpp>
14
15#ifdef INCLUDE_MBCOUPLER
16 #include <mbcoupler/Coupler.hpp>
17#endif
18using namespace MoFEM;
19
21
23#include <boost/math/constants/constants.hpp>
24
25#include <cholesky.hpp>
26#ifdef ENABLE_PYTHON_BINDING
27 #include <boost/python.hpp>
28 #include <boost/python/def.hpp>
29 #include <boost/python/numpy.hpp>
30namespace bp = boost::python;
31namespace np = boost::python::numpy;
32#endif
33
34#include <EshelbianAux.hpp>
35#include <EshelbianCohesive.hpp>
36#include <EshelbianContact.hpp>
38#include <TSElasticPostStep.hpp>
39
40extern "C" {
41#include <phg-quadrule/quad.h>
42}
43
44#include <queue>
45
46namespace EshelbianPlasticity {
55
56} // namespace EshelbianPlasticity
57
58static auto send_type(MoFEM::Interface &m_field, Range r,
59 const EntityType type) {
60 ParallelComm *pcomm =
61 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
62
63 auto dim = CN::Dimension(type);
64
65 std::vector<int> sendcounts(pcomm->size());
66 std::vector<int> displs(pcomm->size());
67 std::vector<int> sendbuf(r.size());
68 if (pcomm->rank() == 0) {
69 for (auto p = 1; p != pcomm->size(); p++) {
70 auto part_ents = m_field.getInterface<CommInterface>()
71 ->getPartEntities(m_field.get_moab(), p)
72 .subset_by_dimension(SPACE_DIM);
73 Range faces;
74 CHKERR m_field.get_moab().get_adjacencies(part_ents, dim, true, faces,
75 moab::Interface::UNION);
76 faces = intersect(faces, r);
77 sendcounts[p] = faces.size();
78 displs[p] = sendbuf.size();
79 for (auto f : faces) {
80 auto id = id_from_handle(f);
81 sendbuf.push_back(id);
82 }
83 }
84 }
85
86 int recv_data;
87 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
88 pcomm->comm());
89 std::vector<int> recvbuf(recv_data);
90 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
91 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
92
93 if (pcomm->rank() > 0) {
94 Range r;
95 for (auto &f : recvbuf) {
96 r.insert(ent_form_type_and_id(type, f));
97 }
98 return r;
99 }
100
101 return r;
102}
103
105 const std::string block_name) {
106 Range r;
107
108 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
109 auto bcs = mesh_mng->getCubitMeshsetPtr(
110
111 std::regex((boost::format("%s(.*)") % block_name).str())
112
113 );
114
115 for (auto bc : bcs) {
116 auto meshset = bc->getMeshset();
117 CHK_MOAB_THROW(m_field.get_moab().get_entities_by_handle(meshset, r, true),
118 "get meshset ents");
119 }
120
121 return r;
122};
123
125 const std::string block_name, int dim) {
126 Range r;
127
128 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
129 auto bcs = mesh_mng->getCubitMeshsetPtr(
130
131 std::regex((boost::format("%s(.*)") % block_name).str())
132
133 );
134
135 for (auto bc : bcs) {
136 Range faces;
137 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
138 faces, true),
139 "get meshset ents");
140 r.merge(faces);
141 }
142
143 return r;
144};
145
147 const std::string block_name, int dim) {
148 std::map<std::string, Range> r;
149
150 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
151 auto bcs = mesh_mng->getCubitMeshsetPtr(
152
153 std::regex((boost::format("%s(.*)") % block_name).str())
154
155 );
156
157 for (auto bc : bcs) {
158 Range faces;
159 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
160 faces, true),
161 "get meshset ents");
162 r[bc->getName()] = faces;
163 }
164
165 return r;
166}
167
168static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id,
169 const unsigned int cubit_bc_type) {
170 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
171 EntityHandle meshset;
172 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
173 return meshset;
174};
175
176static auto save_range(moab::Interface &moab, const std::string name,
177 const Range r, std::vector<Tag> tags = {}) {
179 auto out_meshset = get_temp_meshset_ptr(moab);
180 CHKERR moab.add_entities(*out_meshset, r);
181 if (r.size()) {
182 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
183 tags.data(), tags.size());
184 } else {
185 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
186 }
188};
189
190static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
191 Range boundary_ents;
192 ParallelComm *pcomm =
193 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
194 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
195 PSTATUS_SHARED | PSTATUS_MULTISHARED,
196 PSTATUS_NOT, -1, &boundary_ents),
197 "filter_pstatus");
198 return boundary_ents;
199};
200
201static auto filter_owners(MoFEM::Interface &m_field, Range skin) {
202 Range owner_ents;
203 ParallelComm *pcomm =
204 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
205 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
206 &owner_ents),
207 "filter_pstatus");
208 return owner_ents;
209};
210
211static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
212 Skinner skin(&m_field.get_moab());
213 Range skin_ents;
214 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
215 return skin_ents;
216};
217
219 Range crack_faces) {
220 ParallelComm *pcomm =
221 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
222 auto &moab = m_field.get_moab();
223 Range crack_skin_without_bdy;
224 if (pcomm->rank() == 0) {
225 Range crack_edges;
226 CHKERR moab.get_adjacencies(crack_faces, 1, true, crack_edges,
227 moab::Interface::UNION);
228 auto crack_skin = get_skin(m_field, crack_faces);
229 Range body_ents;
231 m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents),
232 "get_entities_by_dimension");
233 auto body_skin = get_skin(m_field, body_ents);
234 Range body_skin_edges;
235 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1, true, body_skin_edges,
236 moab::Interface::UNION),
237 "get_adjacencies");
238 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
239 auto front_edges_map = get_range_from_block_map(m_field, "FRONT", 1);
240 for (auto &m : front_edges_map) {
241 auto add_front = subtract(m.second, crack_edges);
242 auto i = intersect(m.second, crack_edges);
243 if (i.empty()) {
244 crack_skin_without_bdy.merge(add_front);
245 } else {
246 auto i_skin = get_skin(m_field, i);
247 Range adj_i_skin;
248 CHKERR moab.get_adjacencies(i_skin, 1, true, adj_i_skin,
249 moab::Interface::UNION);
250 adj_i_skin = subtract(intersect(adj_i_skin, m.second), crack_edges);
251 crack_skin_without_bdy.merge(adj_i_skin);
252 }
253 }
254 }
255 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
256}
257
259 Range crack_faces) {
260
261 ParallelComm *pcomm =
262 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
263
264 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface";
265
266 if (!pcomm->rank()) {
267
268 auto impl = [&](auto &saids) {
270
271 auto &moab = m_field.get_moab();
272
273 auto get_adj = [&](auto e, auto dim) {
274 Range adj;
275 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(
276 e, dim, true, adj, moab::Interface::UNION),
277 "get adj");
278 return adj;
279 };
280
281 auto get_conn = [&](auto e) {
282 Range conn;
283 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(e, conn, true),
284 "get connectivity");
285 return conn;
286 };
287
288 constexpr bool debug = false;
289 Range body_ents;
290 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
291 body_ents);
292 auto body_skin = get_skin(m_field, body_ents);
293 auto body_skin_edges = get_adj(body_skin, 1);
294
295 auto crack_skin =
296 subtract(get_skin(m_field, crack_faces), body_skin_edges);
297 auto crack_skin_conn = get_conn(crack_skin);
298 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
299 auto crack_edges = get_adj(crack_faces, 1);
300 crack_edges = subtract(crack_edges, crack_skin);
301 auto all_tets = get_adj(crack_edges, 3);
302 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
303 auto crack_conn = get_conn(crack_edges);
304 all_tets.merge(get_adj(crack_conn, 3));
305
306 if (debug) {
307 CHKERR save_range(m_field.get_moab(), "crack_faces.vtk", crack_faces);
308 CHKERR save_range(m_field.get_moab(), "all_crack_tets.vtk", all_tets);
309 CHKERR save_range(m_field.get_moab(), "crack_edges_all.vtk",
310 crack_edges);
311 }
312
313 if (crack_faces.size()) {
314 auto grow = [&](auto r) {
315 auto crack_faces_conn = get_conn(crack_faces);
316 Range v;
317 auto size_r = 0;
318 while (size_r != r.size() && r.size() > 0) {
319 size_r = r.size();
320 CHKERR moab.get_connectivity(r, v, true);
321 v = subtract(v, crack_faces_conn);
322 if (v.size()) {
323 CHKERR moab.get_adjacencies(v, SPACE_DIM, true, r,
324 moab::Interface::UNION);
325 r = intersect(r, all_tets);
326 }
327 if (r.empty()) {
328 break;
329 }
330 }
331 return r;
332 };
333
334 Range all_tets_ord = all_tets;
335 while (all_tets.size()) {
336 Range faces = get_adj(unite(saids.first, saids.second), 2);
337 faces = subtract(crack_faces, faces);
338 if (faces.size()) {
339 Range tets;
340 auto fit = faces.begin();
341 for (; fit != faces.end(); ++fit) {
342 tets = intersect(get_adj(Range(*fit, *fit), 3), all_tets);
343 if (tets.size() == 2) {
344 break;
345 }
346 }
347 if (tets.empty()) {
348 break;
349 } else {
350 saids.first.insert(tets[0]);
351 saids.first = grow(saids.first);
352 all_tets = subtract(all_tets, saids.first);
353 if (tets.size() == 2) {
354 saids.second.insert(tets[1]);
355 saids.second = grow(saids.second);
356 all_tets = subtract(all_tets, saids.second);
357 }
358 }
359 } else {
360 break;
361 }
362 }
363
364 saids.first = subtract(all_tets_ord, saids.second);
365 saids.second = subtract(all_tets_ord, saids.first);
366 }
367
369 };
370
371 std::pair<Range, Range> saids;
372 if (crack_faces.size())
373 CHK_THROW_MESSAGE(impl(saids), "get crack both sides");
374 return saids;
375 }
376
377 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface <- done";
378
379 return std::pair<Range, Range>();
380}
381
382namespace EshelbianPlasticity {
383
384auto vol_rule(int o) { return 2 * o; };
385auto face_rule(int o) { return 2 * o; };
386
388
389 using FunRule = boost::function<int(int)>;
391
393 boost::shared_ptr<Range> front_nodes,
394 boost::shared_ptr<Range> front_edges,
395 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
396 : frontNodes(front_nodes), frontEdges(front_edges), cachePhi(cache_phi){};
397
399 boost::shared_ptr<Range> front_nodes,
400 boost::shared_ptr<Range> front_edges, FunRule fun_rule,
401 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
402 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule),
403 cachePhi(cache_phi){};
404
406 int order_col, int order_data) {
408
409 constexpr bool debug = false;
410
411 constexpr int numNodes = 4;
412 constexpr int numEdges = 6;
413 constexpr int refinementLevels = 6;
414
415 auto &m_field = fe_raw_ptr->mField;
416 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
417 auto fe_handle = fe_ptr->getFEEntityHandle();
418
419 auto set_base_quadrature = [&]() {
421 int rule = funRule(order_data);
422 if (rule < QUAD_3D_TABLE_SIZE) {
423 if (QUAD_3D_TABLE[rule]->dim != 3) {
424 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
425 "wrong dimension");
426 }
427 if (QUAD_3D_TABLE[rule]->order < rule) {
428 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
429 "wrong order %d != %d", QUAD_3D_TABLE[rule]->order, rule);
430 }
431 const size_t nb_gauss_pts = QUAD_3D_TABLE[rule]->npoints;
432 auto &gauss_pts = fe_ptr->gaussPts;
433 gauss_pts.resize(4, nb_gauss_pts, false);
434 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[1], 4,
435 &gauss_pts(0, 0), 1);
436 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[2], 4,
437 &gauss_pts(1, 0), 1);
438 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[3], 4,
439 &gauss_pts(2, 0), 1);
440 cblas_dcopy(nb_gauss_pts, QUAD_3D_TABLE[rule]->weights, 1,
441 &gauss_pts(3, 0), 1);
442 auto &data = fe_ptr->dataOnElement[H1];
443 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4,
444 false);
445 double *shape_ptr =
446 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
447 cblas_dcopy(4 * nb_gauss_pts, QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
448 1);
449 } else {
450 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
451 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
452 }
454 };
455
456 CHKERR set_base_quadrature();
457
459
460 auto get_singular_nodes = [&]() {
461 int num_nodes;
462 const EntityHandle *conn;
463 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
464 true);
465 std::bitset<numNodes> singular_nodes;
466 for (auto nn = 0; nn != numNodes; ++nn) {
467 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
468 singular_nodes.set(nn);
469 } else {
470 singular_nodes.reset(nn);
471 }
472 }
473 return singular_nodes;
474 };
475
476 auto get_singular_edges = [&]() {
477 std::bitset<numEdges> singular_edges;
478 for (int ee = 0; ee != numEdges; ee++) {
479 EntityHandle edge;
480 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
481 if (frontEdges->find(edge) != frontEdges->end()) {
482 singular_edges.set(ee);
483 } else {
484 singular_edges.reset(ee);
485 }
486 }
487 return singular_edges;
488 };
489
490 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
492 fe_ptr->gaussPts.swap(ref_gauss_pts);
493 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
494 auto &data = fe_ptr->dataOnElement[H1];
495 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
496 double *shape_ptr =
497 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
498 CHKERR ShapeMBTET(shape_ptr, &fe_ptr->gaussPts(0, 0),
499 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
500 nb_gauss_pts);
502 };
503
504 auto singular_nodes = get_singular_nodes();
505 if (singular_nodes.count()) {
506 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
507 if (it_map_ref_coords != mapRefCoords.end()) {
508 CHKERR set_gauss_pts(it_map_ref_coords->second);
510 } else {
511
512 auto refine_quadrature = [&]() {
514
515 const int max_level = refinementLevels;
516 EntityHandle tet;
517
518 moab::Core moab_ref;
519 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
520 EntityHandle nodes[4];
521 for (int nn = 0; nn != 4; nn++)
522 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
523 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
524 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
525 MoFEM::Interface &m_field_ref = mofem_ref_core;
526 {
527 Range tets(tet, tet);
528 Range edges;
529 CHKERR m_field_ref.get_moab().get_adjacencies(
530 tets, 1, true, edges, moab::Interface::UNION);
531 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
532 tets, BitRefLevel().set(0), false, VERBOSE);
533 }
534
535 Range nodes_at_front;
536 for (int nn = 0; nn != numNodes; nn++) {
537 if (singular_nodes[nn]) {
538 EntityHandle ent;
539 CHKERR moab_ref.side_element(tet, 0, nn, ent);
540 nodes_at_front.insert(ent);
541 }
542 }
543
544 auto singular_edges = get_singular_edges();
545
546 EntityHandle meshset;
547 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
548 for (int ee = 0; ee != numEdges; ee++) {
549 if (singular_edges[ee]) {
550 EntityHandle ent;
551 CHKERR moab_ref.side_element(tet, 1, ee, ent);
552 CHKERR moab_ref.add_entities(meshset, &ent, 1);
553 }
554 }
555
556 // refine mesh
557 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
558 for (int ll = 0; ll != max_level; ll++) {
559 Range edges;
560 CHKERR m_field_ref.getInterface<BitRefManager>()
561 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
562 BitRefLevel().set(), MBEDGE,
563 edges);
564 Range ref_edges;
565 CHKERR moab_ref.get_adjacencies(
566 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
567 ref_edges = intersect(ref_edges, edges);
568 Range ents;
569 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
570 ref_edges = intersect(ref_edges, ents);
571 Range tets;
572 CHKERR m_field_ref.getInterface<BitRefManager>()
573 ->getEntitiesByTypeAndRefLevel(
574 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
575 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
576 ref_edges, BitRefLevel().set(ll + 1));
577 CHKERR m_ref->refineTets(tets, BitRefLevel().set(ll + 1));
578 CHKERR m_field_ref.getInterface<BitRefManager>()
579 ->updateMeshsetByEntitiesChildren(meshset,
580 BitRefLevel().set(ll + 1),
581 meshset, MBEDGE, true);
582 }
583
584 // get ref coords
585 Range tets;
586 CHKERR m_field_ref.getInterface<BitRefManager>()
587 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
588 BitRefLevel().set(), MBTET,
589 tets);
590
591 if (debug) {
592 CHKERR save_range(moab_ref, "ref_tets.vtk", tets);
593 }
594
595 MatrixDouble ref_coords(tets.size(), 12, false);
596 int tt = 0;
597 for (Range::iterator tit = tets.begin(); tit != tets.end();
598 tit++, tt++) {
599 int num_nodes;
600 const EntityHandle *conn;
601 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
602 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
603 }
604
605 auto &data = fe_ptr->dataOnElement[H1];
606 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
607 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
608 MatrixDouble &shape_n =
609 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
610 int gg = 0;
611 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
612 double *tet_coords = &ref_coords(tt, 0);
613 double det = Tools::tetVolume(tet_coords);
614 det *= 6;
615 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
616 for (int dd = 0; dd != 3; dd++) {
617 ref_gauss_pts(dd, gg) =
618 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
619 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
620 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
621 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
622 }
623 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
624 }
625 }
626
627 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
628 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
629
630 // clear cache bubble
631 cachePhi->get<0>() = 0;
632 cachePhi->get<1>() = 0;
633 // tet base cache
634 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
635 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
636
638 };
639
640 CHKERR refine_quadrature();
641 }
642 }
643 }
644
646 }
647
648private:
649 struct Fe : public ForcesAndSourcesCore {
650 using ForcesAndSourcesCore::dataOnElement;
651
652 private:
653 using ForcesAndSourcesCore::ForcesAndSourcesCore;
654 };
655
656 boost::shared_ptr<Range> frontNodes;
657 boost::shared_ptr<Range> frontEdges;
658
659 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cachePhi;
660
661 static inline std::map<long int, MatrixDouble> mapRefCoords;
662};
663
665
666 using FunRule = boost::function<int(int)>;
668
669 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
670 boost::shared_ptr<Range> front_edges)
671 : frontNodes(front_nodes), frontEdges(front_edges){};
672
673 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
674 boost::shared_ptr<Range> front_edges,
675 FunRule fun_rule)
676 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule){};
677
679 int order_col, int order_data) {
681
682 constexpr bool debug = false;
683
684 constexpr int numNodes = 3;
685 constexpr int numEdges = 3;
686 constexpr int refinementLevels = 6;
687
688 auto &m_field = fe_raw_ptr->mField;
689 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
690 auto fe_handle = fe_ptr->getFEEntityHandle();
691
692 auto set_base_quadrature = [&]() {
694 int rule = funRule(order_data);
695 if (rule < QUAD_2D_TABLE_SIZE) {
696 if (QUAD_2D_TABLE[rule]->dim != 2) {
697 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
698 }
699 if (QUAD_2D_TABLE[rule]->order < rule) {
700 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
701 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
702 }
703 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
704 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
705 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
706 &fe_ptr->gaussPts(0, 0), 1);
707 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
708 &fe_ptr->gaussPts(1, 0), 1);
709 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
710 &fe_ptr->gaussPts(2, 0), 1);
711 auto &data = fe_ptr->dataOnElement[H1];
712 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
713 false);
714 double *shape_ptr =
715 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
716 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
717 1);
718 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
719 std::copy(
721 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
722
723 } else {
724 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
725 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
726 }
728 };
729
730 CHKERR set_base_quadrature();
731
733
734 auto get_singular_nodes = [&]() {
735 int num_nodes;
736 const EntityHandle *conn;
737 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
738 true);
739 std::bitset<numNodes> singular_nodes;
740 for (auto nn = 0; nn != numNodes; ++nn) {
741 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
742 singular_nodes.set(nn);
743 } else {
744 singular_nodes.reset(nn);
745 }
746 }
747 return singular_nodes;
748 };
749
750 auto get_singular_edges = [&]() {
751 std::bitset<numEdges> singular_edges;
752 for (int ee = 0; ee != numEdges; ee++) {
753 EntityHandle edge;
754 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
755 if (frontEdges->find(edge) != frontEdges->end()) {
756 singular_edges.set(ee);
757 } else {
758 singular_edges.reset(ee);
759 }
760 }
761 return singular_edges;
762 };
763
764 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
766 fe_ptr->gaussPts.swap(ref_gauss_pts);
767 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
768 auto &data = fe_ptr->dataOnElement[H1];
769 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
770 double *shape_ptr =
771 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
772 CHKERR ShapeMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
773 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
775 };
776
777 auto singular_nodes = get_singular_nodes();
778 if (singular_nodes.count()) {
779 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
780 if (it_map_ref_coords != mapRefCoords.end()) {
781 CHKERR set_gauss_pts(it_map_ref_coords->second);
783 } else {
784
785 auto refine_quadrature = [&]() {
787
788 const int max_level = refinementLevels;
789
790 moab::Core moab_ref;
791 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
792 EntityHandle nodes[numNodes];
793 for (int nn = 0; nn != numNodes; nn++)
794 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
795 EntityHandle tri;
796 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
797 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
798 MoFEM::Interface &m_field_ref = mofem_ref_core;
799 {
800 Range tris(tri, tri);
801 Range edges;
802 CHKERR m_field_ref.get_moab().get_adjacencies(
803 tris, 1, true, edges, moab::Interface::UNION);
804 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
805 tris, BitRefLevel().set(0), false, VERBOSE);
806 }
807
808 Range nodes_at_front;
809 for (int nn = 0; nn != numNodes; nn++) {
810 if (singular_nodes[nn]) {
811 EntityHandle ent;
812 CHKERR moab_ref.side_element(tri, 0, nn, ent);
813 nodes_at_front.insert(ent);
814 }
815 }
816
817 auto singular_edges = get_singular_edges();
818
819 EntityHandle meshset;
820 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
821 for (int ee = 0; ee != numEdges; ee++) {
822 if (singular_edges[ee]) {
823 EntityHandle ent;
824 CHKERR moab_ref.side_element(tri, 1, ee, ent);
825 CHKERR moab_ref.add_entities(meshset, &ent, 1);
826 }
827 }
828
829 // refine mesh
830 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
831 for (int ll = 0; ll != max_level; ll++) {
832 Range edges;
833 CHKERR m_field_ref.getInterface<BitRefManager>()
834 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
835 BitRefLevel().set(), MBEDGE,
836 edges);
837 Range ref_edges;
838 CHKERR moab_ref.get_adjacencies(
839 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
840 ref_edges = intersect(ref_edges, edges);
841 Range ents;
842 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
843 ref_edges = intersect(ref_edges, ents);
844 Range tris;
845 CHKERR m_field_ref.getInterface<BitRefManager>()
846 ->getEntitiesByTypeAndRefLevel(
847 BitRefLevel().set(ll), BitRefLevel().set(), MBTRI, tris);
848 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
849 ref_edges, BitRefLevel().set(ll + 1));
850 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
851 CHKERR m_field_ref.getInterface<BitRefManager>()
852 ->updateMeshsetByEntitiesChildren(meshset,
853 BitRefLevel().set(ll + 1),
854 meshset, MBEDGE, true);
855 }
856
857 // get ref coords
858 Range tris;
859 CHKERR m_field_ref.getInterface<BitRefManager>()
860 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
861 BitRefLevel().set(), MBTRI,
862 tris);
863
864 if (debug) {
865 CHKERR save_range(moab_ref, "ref_tris.vtk", tris);
866 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
867 }
868
869 MatrixDouble ref_coords(tris.size(), 9, false);
870 int tt = 0;
871 for (Range::iterator tit = tris.begin(); tit != tris.end();
872 tit++, tt++) {
873 int num_nodes;
874 const EntityHandle *conn;
875 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
876 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
877 }
878
879 auto &data = fe_ptr->dataOnElement[H1];
880 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
881 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
882 MatrixDouble &shape_n =
883 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
884 int gg = 0;
885 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
886 double *tri_coords = &ref_coords(tt, 0);
888 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
889 auto det = t_normal.l2();
890 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
891 for (int dd = 0; dd != 2; dd++) {
892 ref_gauss_pts(dd, gg) =
893 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
894 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
895 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
896 }
897 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
898 }
899 }
900
901 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
902 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
903
905 };
906
907 CHKERR refine_quadrature();
908 }
909 }
910 }
911
913 }
914
915private:
916 struct Fe : public ForcesAndSourcesCore {
917 using ForcesAndSourcesCore::dataOnElement;
918
919 private:
920 using ForcesAndSourcesCore::ForcesAndSourcesCore;
921 };
922
923 boost::shared_ptr<Range> frontNodes;
924 boost::shared_ptr<Range> frontEdges;
925
926 static inline std::map<long int, MatrixDouble> mapRefCoords;
927};
928
929double EshelbianCore::exponentBase = exp(1);
930boost::function<double(const double)> EshelbianCore::f = EshelbianCore::f_log_e;
931boost::function<double(const double)> EshelbianCore::d_f =
933boost::function<double(const double)> EshelbianCore::dd_f =
935boost::function<double(const double)> EshelbianCore::inv_f =
937boost::function<double(const double)> EshelbianCore::inv_d_f =
939boost::function<double(const double)> EshelbianCore::inv_dd_f =
941
943EshelbianCore::query_interface(boost::typeindex::type_index type_index,
944 UnknownInterface **iface) const {
945 *iface = const_cast<EshelbianCore *>(this);
946 return 0;
947}
948
949MoFEMErrorCode OpJacobian::doWork(int side, EntityType type, EntData &data) {
951
952 if (evalRhs)
953 CHKERR evaluateRhs(data);
954
955 if (evalLhs)
956 CHKERR evaluateLhs(data);
957
959}
960
962 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
963}
964
966
969 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
970 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
971 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
972 const char *list_broken_hdiv_bases[] = {"demkowicz", "ainsworth"};
973 PetscInt choice_rot = EshelbianCore::rotSelector;
974 PetscInt choice_grad = EshelbianCore::gradApproximator;
975 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
976 PetscInt choice_stretch = StretchSelector::LOG;
977 PetscInt choice_solver = SolverType::TimeSolver;
978 PetscInt choice_broken_hdiv_base = 0;
979 PetscBool l2_user_base_scale_set = PETSC_FALSE;
982 choice_broken_hdiv_base = 0;
983 break;
985 choice_broken_hdiv_base = 1;
986 break;
987 default:
988 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
989 "Unsupported broken HDIV base %s",
991 }
992 char analytical_expr_file_name[255] = "analytical_expr.py";
993 PetscBool no_stretch =
994 stretchHandling == NO_STREACH ? PETSC_TRUE : PETSC_FALSE;
995
996 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
997 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
998 spaceOrder, &spaceOrder, PETSC_NULLPTR);
999 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
1000 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
1001 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
1002 "", materialH1Order, &materialH1Order, PETSC_NULLPTR);
1003 CHKERR PetscOptionsScalar("-viscosity_alpha_u", "viscosity", "", alphaU,
1004 &alphaU, PETSC_NULLPTR);
1005 CHKERR PetscOptionsScalar("-viscosity_alpha_w", "viscosity", "", alphaW,
1006 &alphaW, PETSC_NULLPTR);
1007 CHKERR PetscOptionsScalar("-viscosity_alpha_omega", "rot viscosity", "",
1008 alphaOmega, &alphaOmega, PETSC_NULLPTR);
1009 CHKERR PetscOptionsScalar("-density_alpha_rho", "density", "", alphaRho,
1010 &alphaRho, PETSC_NULLPTR);
1011 CHKERR PetscOptionsScalar("-alpha_tau", "tau", "", alphaTau, &alphaTau,
1012 PETSC_NULLPTR);
1013 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
1014 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
1015 PETSC_NULLPTR);
1016 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
1017 list_rots, NO_H1_CONFIGURATION + 1,
1018 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
1019
1020 CHKERR PetscOptionsScalar("-exponent_base", "exponent_base", "", exponentBase,
1021 &EshelbianCore::exponentBase, PETSC_NULLPTR);
1022 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
1023 StretchSelector::STRETCH_SELECTOR_LAST,
1024 list_stretches[choice_stretch], &choice_stretch,
1025 PETSC_NULLPTR);
1026
1027 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
1028 no_stretch, &no_stretch, PETSC_NULLPTR);
1029 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1030 setSingularity, &setSingularity, PETSC_NULLPTR);
1031 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1033 &l2_user_base_scale_set);
1034 CHKERR PetscOptionsEList(
1035 "-broken_hdiv_base", "broken HDIV stress approximation base", "",
1036 list_broken_hdiv_bases, 2,
1037 list_broken_hdiv_bases[choice_broken_hdiv_base],
1038 &choice_broken_hdiv_base, PETSC_NULLPTR);
1039
1040 // dynamic relaxation
1041
1042 // @deprecate this option
1043 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1044 physicalTimeFlg, &physicalTimeFlg, PETSC_NULLPTR);
1045 CHKERR PetscOptionsEList(
1046 "-solver_type", "solver type", "", EshelbianCore::listSolvers,
1048 EshelbianCore::listSolvers[choice_solver], &choice_solver, PETSC_NULLPTR);
1049
1050 if (choice_solver != SolverType::TimeSolver) {
1051 CHKERR PetscOptionsScalar("-physical_final_time", "physical final time", "",
1053 PETSC_NULLPTR);
1054 CHKERR PetscOptionsScalar("-physical_delta_time", "physical delta time", "",
1056 PETSC_NULLPTR);
1057 CHKERR PetscOptionsInt("-physical_max_steps", "physical max iterations", "",
1059 PETSC_NULLPTR);
1060 CHKERR PetscOptionsBool(
1061 "-physical_h1_update", "update each physicalsolver step", "",
1063 }
1064
1065 // contact parameters
1066 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1068 PETSC_NULLPTR);
1069 // cohesive interface
1070 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1071 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1072 CHKERR PetscOptionsInt(
1073 "-cohesive_interface_remove_level", "cohesive interface remove level", "",
1075
1076 // cracking parameters
1077 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1078 &crackingOn, PETSC_NULLPTR);
1079 CHKERR PetscOptionsScalar("-cracking_add_time", "cracking add time", "",
1080 crackingAddTime, &crackingAddTime, PETSC_NULLPTR);
1081 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1083 PETSC_NULLPTR);
1084 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1085 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1086
1087 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1088 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1089 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1090 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1091 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1092 "", list_release, 2, list_release[choice_release],
1093 &choice_release, PETSC_NULLPTR);
1094 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1096 PETSC_NULLPTR); // backward compatibility
1097 CHKERR PetscOptionsInt(
1098 "-nb_J_integral_contours", "Number of J integral contours", "",
1099 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1100
1101 // internal stress
1102 char tag_name[255] = "";
1103 CHKERR PetscOptionsString("-internal_stress_tag_name",
1104 "internal stress tag name", "", "", tag_name, 255,
1105 PETSC_NULLPTR);
1106 internalStressTagName = string(tag_name);
1107 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1109 PETSC_NULLPTR);
1110
1111 // Heterogenous Young's modulus
1112 char tag_heterogeneous_youngs_modulus_name[255] = "";
1113 CHKERR PetscOptionsString(
1114 "-heterogeneous_youngs_modulus", "heterogeneous Young's modulus tag name",
1115 "", "", tag_heterogeneous_youngs_modulus_name, 255, PETSC_NULLPTR);
1116 heterogeneousYoungModTagName = string(tag_heterogeneous_youngs_modulus_name);
1117
1118 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
1119 "-analytical_expr_file",
1120 analytical_expr_file_name, 255, PETSC_NULLPTR);
1121
1122 PetscOptionsEnd();
1123
1124 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1125 "none");
1126 char tag_mesh_transfer_source_file_name[255] = "";
1127 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1128 "source.h5m", tag_mesh_transfer_source_file_name,
1130 meshTransferSourceMeshFileName = string(tag_mesh_transfer_source_file_name);
1131 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1132 &meshTransferInterpOrder, PETSC_NULLPTR);
1133 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1135 PETSC_NULLPTR);
1136 PetscOptionsEnd();
1137
1139 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1140 "Unsupported mesh transfer interpolation order %d",
1142 }
1143 if (!internalStressTagName.empty())
1145 if (!heterogeneousYoungModTagName.empty())
1147
1148 if (setSingularity && !l2_user_base_scale_set) {
1149 l2UserBaseScale = PETSC_TRUE;
1150 }
1151
1153 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1154 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1155 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1157 static_cast<EnergyReleaseSelector>(choice_release);
1158 switch (choice_broken_hdiv_base) {
1159 case 0:
1161 break;
1162 case 1:
1164 break;
1165 default:
1166 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1167 "Unknown broken HDIV base option");
1168 }
1169
1171 case StretchSelector::LINEAR:
1178 break;
1179 case StretchSelector::LOG:
1180 if (std::fabs(EshelbianCore::exponentBase - exp(1)) >
1181 std::numeric_limits<float>::epsilon()) {
1188 } else {
1195 }
1196 break;
1197 case StretchSelector::LOG_QUADRATIC:
1201 EshelbianCore::inv_f = [](const double x) {
1203 "No logarithmic quadratic stretch for this case");
1204 return 0;
1205 };
1208 break; // no stretch, do not use stretch functions
1209 default:
1210 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1211 break;
1212 };
1213
1214 if (physicalTimeFlg) {
1215 MOFEM_LOG("EP", Sev::warning)
1216 << "-dynamic_relaxation option is deprecated, use -solver_type "
1217 "dynamic_relaxation instead.";
1218 choice_solver = SolverType::DynamicRelaxation;
1219 }
1220
1221 switch (choice_solver) {
1224 break;
1228 physicalTimeFlg = PETSC_TRUE;
1229 break;
1232 break;
1235 physicalTimeFlg = PETSC_TRUE;
1236 break;
1240 break;
1244 physicalTimeFlg = PETSC_TRUE;
1245 break;
1246 default:
1247 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1248 break;
1249 };
1250
1251 // start cracking after adding crack elements
1253
1254 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1255 MOFEM_LOG("EP", Sev::inform)
1256 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1257 MOFEM_LOG("EP", Sev::inform)
1258 << "materialH1Order: -material_order " << materialH1Order;
1259 MOFEM_LOG("EP", Sev::inform) << "alphaU: -viscosity_alpha_u " << alphaU;
1260 MOFEM_LOG("EP", Sev::inform) << "alphaW: -viscosity_alpha_w " << alphaW;
1261 MOFEM_LOG("EP", Sev::inform)
1262 << "alphaOmega: -viscosity_alpha_omega " << alphaOmega;
1263 MOFEM_LOG("EP", Sev::inform) << "alphaRho: -density_alpha_rho " << alphaRho;
1264 MOFEM_LOG("EP", Sev::inform) << "alphaTau: -alpha_tau " << alphaTau;
1265 MOFEM_LOG("EP", Sev::inform)
1266 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1267 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation "
1268 << list_rots[EshelbianCore::gradApproximator];
1269 if (exponentBase != exp(1))
1270 MOFEM_LOG("EP", Sev::inform)
1271 << "Base exponent: -exponent_base " << EshelbianCore::exponentBase;
1272 else
1273 MOFEM_LOG("EP", Sev::inform) << "Base exponent e";
1274 MOFEM_LOG("EP", Sev::inform)
1275 << "Stretch: -stretches " << list_stretches[choice_stretch];
1276 MOFEM_LOG("EP", Sev::inform)
1277 << "No stretch: -no_stretch "
1278 << (stretchHandling == NO_STREACH ? "yes" : "no");
1279
1280 MOFEM_LOG("EP", Sev::inform)
1281 << "Dynamic relaxation: -dynamic_relaxation " << (physicalTimeFlg)
1282 ? "yes"
1283 : "no";
1284 MOFEM_LOG("EP", Sev::inform) << "Solver type: -solver_type "
1285 << EshelbianCore::listSolvers[choice_solver];
1286 MOFEM_LOG("EP", Sev::inform)
1287 << "Singularity: -set_singularity " << (setSingularity)
1288 ? "yes"
1289 : "no";
1290 MOFEM_LOG("EP", Sev::inform)
1291 << "L2 user base scale: -l2_user_base_scale " << (l2UserBaseScale)
1292 ? "yes"
1293 : "no";
1294 MOFEM_LOG("EP", Sev::inform)
1295 << "Broken HDIV base: -broken_hdiv_base "
1296 << list_broken_hdiv_bases[choice_broken_hdiv_base];
1297
1298 MOFEM_LOG("EP", Sev::inform) << "Cracking on: -cracking_on " << (crackingOn)
1299 ? "yes"
1300 : "no";
1301 MOFEM_LOG("EP", Sev::inform)
1302 << "Cracking add time: -cracking_add_time " << crackingAddTime;
1303 MOFEM_LOG("EP", Sev::inform)
1304 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1305 MOFEM_LOG("EP", Sev::inform)
1306 << "Griffith energy: -griffith_energy " << griffithEnergy;
1307 MOFEM_LOG("EP", Sev::inform)
1308 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1309 MOFEM_LOG("EP", Sev::inform)
1310 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1311 MOFEM_LOG("EP", Sev::inform)
1312 << "Energy release variant: -energy_release_variant "
1313 << list_release[EshelbianCore::energyReleaseSelector];
1314 MOFEM_LOG("EP", Sev::inform)
1315 << "Number of J integral contours: -nb_J_integral_contours "
1317 MOFEM_LOG("EP", Sev::inform)
1318 << "Cohesive interface on: -cohesive_interface_on "
1319 << ((interfaceCrack == PETSC_TRUE) ? "yes" : "no");
1320 MOFEM_LOG("EP", Sev::inform)
1321 << "Cohesive interface remove level: -cohesive_interface_remove_level "
1323
1324#ifdef ENABLE_PYTHON_BINDING
1325 auto file_exists = [](std::string myfile) {
1326 std::ifstream file(myfile.c_str());
1327 if (file) {
1328 return true;
1329 }
1330 return false;
1331 };
1332
1333 if (file_exists(analytical_expr_file_name)) {
1334 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1335
1336 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1337 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1338 analytical_expr_file_name);
1339 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1340 } else {
1341 MOFEM_LOG("EP", Sev::warning)
1342 << analytical_expr_file_name << " file NOT found";
1343 }
1344#endif
1345
1346 if (spaceH1Order == -1)
1348
1350}
1351
1353 const bool add_bubble) {
1355
1356 auto get_tets = [&]() {
1357 Range tets;
1358 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1359 return tets;
1360 };
1361
1362 auto get_tets_skin = [&]() {
1363 Range tets_skin_part;
1364 Skinner skin(&mField.get_moab());
1365 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1366 ParallelComm *pcomm =
1367 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1368 Range tets_skin;
1369 CHKERR pcomm->filter_pstatus(tets_skin_part,
1370 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1371 PSTATUS_NOT, -1, &tets_skin);
1372 return tets_skin;
1373 };
1374
1375 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1376 // That mean, that hybrid field on all faces on which traction is applied,
1377 // on other faces, or enforcing displacements as
1378 // natural boundary condition.
1380 for (auto &v : *bcSpatialTractionVecPtr) {
1381 tets_skin = subtract(tets_skin, v.faces);
1382 }
1384 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1385 tets_skin = subtract(tets_skin, v.faces);
1386 }
1387
1389 for (auto &v : *bcSpatialPressureVecPtr) {
1390 tets_skin = subtract(tets_skin, v.faces);
1391 }
1392
1393 return tets_skin;
1394 };
1395
1396 auto add_blockset = [&](auto block_name, auto &&tets_skin) {
1397 auto crack_faces =
1398 get_range_from_block(mField, "block_name", SPACE_DIM - 1);
1399 tets_skin.merge(crack_faces);
1400 return tets_skin;
1401 };
1402
1403 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1404 auto contact_range =
1405 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1406 tets_skin = subtract(tets_skin, contact_range);
1407 return tets_skin;
1408 };
1409
1410 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1411 Range faces;
1412 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1413 faces, moab::Interface::UNION);
1414 Range trace_faces = subtract(faces, tets_skin);
1415 return trace_faces;
1416 };
1417
1418 auto tets = get_tets();
1419
1420 // remove also contact faces, i.e. that is also kind of hybrid field but
1421 // named but used to enforce contact conditions
1422 auto trace_faces = get_stress_trace_faces(
1423
1424 subtract_blockset("CONTACT",
1425 subtract_boundary_conditions(get_tets_skin()))
1426
1427 );
1428
1429 contactFaces = boost::make_shared<Range>(intersect(
1430 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1432 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1433
1434#ifndef NDEBUG
1435 if (contactFaces->size())
1437 "contact_faces_" +
1438 std::to_string(mField.get_comm_rank()) + ".vtk",
1439 *contactFaces);
1440 if (skeletonFaces->size())
1442 "skeleton_faces_" +
1443 std::to_string(mField.get_comm_rank()) + ".vtk",
1444 *skeletonFaces);
1445#endif
1446
1447 const FieldApproximationBase broken_hdiv_base =
1449
1450 auto add_broken_hdiv_field = [this, meshset, broken_hdiv_base](
1451 const std::string field_name,
1452 const int order) {
1454
1455 const FieldApproximationBase base = broken_hdiv_base;
1456
1457 auto get_side_map_hdiv = [&]() {
1458 return std::vector<
1459
1460 std::pair<EntityType,
1462
1463 >>{
1464
1465 {MBTET,
1466 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1467 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1468 dofs_side_map);
1469 }}
1470
1471 };
1472 };
1473
1475 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1477 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1479 };
1480
1481 auto add_l2_field = [this, meshset](const std::string field_name,
1482 const int order, const int dim) {
1485 MB_TAG_DENSE, MF_ZERO);
1487 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1489 };
1490
1491 auto add_h1_field = [this, meshset](const std::string field_name,
1492 const int order, const int dim) {
1495 MB_TAG_DENSE, MF_ZERO);
1497 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1498 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1499 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1500 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1502 };
1503
1504 auto add_l2_field_by_range = [this](const std::string field_name,
1505 const int order, const int dim,
1506 const int field_dim, Range &&r) {
1509 MB_TAG_DENSE, MF_ZERO);
1510 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1514 };
1515
1516 auto add_bubble_field = [this, meshset](const std::string field_name,
1517 const int order, const int dim) {
1519 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1520 MF_ZERO);
1521 // Modify field
1522 auto field_ptr = mField.get_field_structure(field_name);
1523 auto field_order_table =
1524 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1525 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1526 auto get_cgg_bubble_order_tet = [](int p) {
1527 return NBVOLUMETET_CCG_BUBBLE(p);
1528 };
1529 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1530 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1531 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1532 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1534 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1535 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1537 };
1538
1539 auto add_user_l2_field = [this, meshset](const std::string field_name,
1540 const int order, const int dim) {
1542 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1543 MF_ZERO);
1544 // Modify field
1545 auto field_ptr = mField.get_field_structure(field_name);
1546 auto field_order_table =
1547 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1548 auto zero_dofs = [](int p) { return 0; };
1549 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1550 field_order_table[MBVERTEX] = zero_dofs;
1551 field_order_table[MBEDGE] = zero_dofs;
1552 field_order_table[MBTRI] = zero_dofs;
1553 field_order_table[MBTET] = dof_l2_tet;
1555 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1557 };
1558
1559 if (!skeletonFaces)
1560 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1561 if (!contactFaces)
1562 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1563
1564 auto get_hybridised_disp = [&]() {
1565 auto faces = *skeletonFaces;
1566 auto skin = subtract_boundary_conditions(get_tets_skin());
1567 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1568 faces.merge(intersect(bc.faces, skin));
1569 }
1570 return faces;
1571 };
1572
1573 auto add_spatial_fields = [&]<FieldApproximationBase Base>() {
1575 using Orders = EshelbianCore::FieldOrders<Base>;
1576 CHKERR add_broken_hdiv_field(piolaStress, Orders::stress(spaceOrder));
1577 if (add_bubble) {
1578 CHKERR add_bubble_field(bubbleField, Orders::bubble(spaceOrder), 1);
1579 }
1580 CHKERR add_l2_field(spatialL2Disp, Orders::disp(spaceOrder), 3);
1581 CHKERR add_user_l2_field(rotAxis, Orders::rot(spaceOrder), 3);
1582 CHKERR add_user_l2_field(stretchTensor,
1584 ? Orders::stretch(spaceOrder)
1585 : -1,
1586 6);
1587 CHKERR add_l2_field_by_range(hybridSpatialDisp,
1588 Orders::hybrid(spaceOrder), 2, 3,
1589 get_hybridised_disp());
1590 CHKERR add_l2_field_by_range(contactDisp, Orders::hybrid(spaceOrder), 2, 3,
1593 };
1594
1595 CHKERR withFieldOrders(add_spatial_fields);
1596
1597 // spatial displacement
1598 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1599 // material positions
1600 CHKERR add_h1_field(materialH1Positions, materialH1Order, 3);
1601
1603
1605}
1606
1608 double time) {
1610
1611 Range meshset_ents;
1612 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1613
1614 auto project_ho_geometry = [&](auto field) {
1616 return mField.loop_dofs(field, ent_method);
1617 };
1618 CHKERR project_ho_geometry(materialH1Positions);
1619
1620 auto get_adj_front_edges = [&](auto &front_edges) {
1621 Range front_crack_nodes;
1622 Range crack_front_edges_with_both_nodes_not_at_front;
1623
1624 if (mField.get_comm_rank() == 0) {
1625 auto &moab = mField.get_moab();
1627 moab.get_connectivity(front_edges, front_crack_nodes, true),
1628 "get_connectivity failed");
1629 Range crack_front_edges;
1630 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1631 false, crack_front_edges,
1632 moab::Interface::UNION),
1633 "get_adjacencies failed");
1634 Range crack_front_edges_nodes;
1635 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1636 crack_front_edges_nodes, true),
1637 "get_connectivity failed");
1638 // those nodes are hannging nodes
1639 crack_front_edges_nodes =
1640 subtract(crack_front_edges_nodes, front_crack_nodes);
1641 Range crack_front_edges_with_both_nodes_not_at_front;
1643 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1644 crack_front_edges_with_both_nodes_not_at_front,
1645 moab::Interface::UNION),
1646 "get_adjacencies failed");
1647 // those edges are have one node not at the crack front
1648 crack_front_edges_with_both_nodes_not_at_front = intersect(
1649 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1650 }
1651
1652 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1653 crack_front_edges_with_both_nodes_not_at_front = send_type(
1654 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1655
1656 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1657 boost::make_shared<Range>(
1658 crack_front_edges_with_both_nodes_not_at_front));
1659 };
1660
1661 if ((time - crackingAddTime) > std::numeric_limits<double>::epsilon()) {
1662 crackFaces = boost::make_shared<Range>(
1663 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1664 } else {
1665 crackFaces = boost::make_shared<Range>();
1666 }
1667 frontEdges =
1668 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1669 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1670 frontVertices = front_vertices;
1671 frontAdjEdges = front_adj_edges;
1672
1673 MOFEM_LOG("EP", Sev::inform)
1674 << "Number of crack faces: " << crackFaces->size();
1675 MOFEM_LOG("EP", Sev::inform)
1676 << "Number of front edges: " << frontEdges->size();
1677 MOFEM_LOG("EP", Sev::inform)
1678 << "Number of front vertices: " << frontVertices->size();
1679 MOFEM_LOG("EP", Sev::inform)
1680 << "Number of front adjacent edges: " << frontAdjEdges->size();
1681
1682#ifndef NDEBUG
1683 if (crackingOn) {
1684 auto rank = mField.get_comm_rank();
1685 // CHKERR save_range(mField.get_moab(),
1686 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1687 // meshset_ents);
1689 (boost::format("crack_faces_%d.vtk") % rank).str(),
1690 *crackFaces);
1692 (boost::format("front_edges_%d.vtk") % rank).str(),
1693 *frontEdges);
1694 // CHKERR save_range(mField.get_moab(),
1695 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1696 // *frontVertices);
1697 // CHKERR save_range(mField.get_moab(),
1698 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1699 // *frontAdjEdges);
1700 }
1701#endif // NDEBUG
1702
1703 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1705 auto &moab = mField.get_moab();
1706
1707 double eps = 1;
1708 double beta = 0;
1709 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1710 PETSC_NULLPTR);
1711 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1712 eps -= beta;
1713
1714 auto field_blas = mField.getInterface<FieldBlas>();
1715 auto lambda =
1716 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1718 FTENSOR_INDEX(3, i);
1719 FTENSOR_INDEX(3, j);
1720
1721 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1722 if (nb_dofs == 0) {
1724 }
1725
1726#ifndef NDEBUG
1727 if (field_entity_ptr->getNbOfCoeffs() != 3)
1729 "Expected 3 coefficients per edge");
1730 if (nb_dofs % 3 != 0)
1732 "Expected multiple of 3 coefficients per edge");
1733#endif // NDEBUG
1734
1735 auto get_conn = [&]() {
1736 int num_nodes;
1737 const EntityHandle *conn;
1738 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1739 num_nodes, false);
1740 return std::make_pair(conn, num_nodes);
1741 };
1742
1743 auto get_dir = [&](auto &&conn_p) {
1744 auto [conn, num_nodes] = conn_p;
1745 double coords[6];
1746 CHKERR moab.get_coords(conn, num_nodes, coords);
1747 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
1748 coords[4] - coords[1],
1749 coords[5] - coords[2]};
1750 return t_edge_dir;
1751 };
1752
1753 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
1754 auto [conn, num_nodes] = conn_p;
1755 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
1756 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1757 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
1758 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1759 t_singularity_dof(i) = t_edge_dir(i) * eps;
1760 }
1761 return t_singularity_dof;
1762 };
1763
1764 auto t_singularity_dof =
1765 get_singularity_dof(get_conn(), get_dir(get_conn()));
1766
1767 auto field_data = field_entity_ptr->getEntFieldData();
1769 &field_data[0], &field_data[1], &field_data[2]};
1770
1771 t_dof(i) = t_singularity_dof(i);
1772 ++t_dof;
1773 for (auto n = 1; n < field_data.size() / 3; ++n) {
1774 t_dof(i) = 0;
1775 ++t_dof;
1776 }
1777
1779 };
1780
1781 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
1782 &front_adj_edges);
1783
1785 };
1786
1787 if (setSingularity)
1788 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
1789
1790 interfaceFaces = boost::make_shared<Range>(
1791 get_range_from_block(mField, "INTERFACE", SPACE_DIM - 1));
1792 MOFEM_LOG("EP", Sev::inform)
1793 << "Number of interface elements: " << interfaceFaces->size();
1794
1795 auto get_interface_from_block = [&](auto block_name) {
1796 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
1797 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
1798 Range faces;
1799 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
1800 faces, moab::Interface::UNION);
1801 faces = subtract(faces, skin);
1802 MOFEM_LOG("EP", Sev::inform)
1803 << "Number of vol interface elements: " << vol_eles.size()
1804 << " and faces: " << faces.size();
1805 return faces;
1806 };
1807
1808 interfaceFaces->merge(get_interface_from_block("VOLUME_INTERFACE"));
1809
1810 auto remove_interface_from_block = [&](auto block_name, auto level) {
1812 Range intreface_faces;
1813 if (mField.get_comm_rank() == 0) {
1814 auto ents = get_entities_by_handle(mField, block_name);
1815 for (auto l = 0; l < level; ++l) {
1816 Range adj_tets;
1817 CHKERR mField.get_moab().get_adjacencies(
1818 ents, SPACE_DIM, true, adj_tets, moab::Interface::UNION);
1819 Range adj_tets_faces;
1820 CHKERR mField.get_moab().get_adjacencies(adj_tets, SPACE_DIM - 1, true,
1821 adj_tets_faces,
1822 moab::Interface::UNION);
1823 ents.merge(adj_tets_faces);
1824 }
1825 auto faces = ents.subset_by_dimension(SPACE_DIM - 1);
1826 if (faces.size()) {
1827 MOFEM_LOG("EP", Sev::inform)
1828 << "Removed ents " << faces.size()
1829 << " interface faces: " << interfaceFaces->size();
1830 }
1831 intreface_faces = subtract(*interfaceFaces, faces);
1832 MOFEM_LOG("EP", Sev::noisy)
1833 << "Interface faces after remove " << intreface_faces;
1834 }
1835 auto intreface_faces_global = send_type(mField, intreface_faces, MBTRI);
1836 interfaceFaces->swap(intreface_faces_global);
1838 };
1839 CHKERR remove_interface_from_block("REMOVE_INTERFACE", interfaceRemoveLevel);
1840
1842}
1843
1846#ifdef INCLUDE_MBCOUPLER
1847
1848 double toler = 5.e-10;
1849 MOFEM_LOG_CHANNEL("WORLD");
1850 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
1852 MOFEM_LOG("WORLD", Sev::verbose)
1853 << "No source mesh specified. Skipping projection";
1855 }
1856 MOFEM_LOG("WORLD", Sev::inform)
1857 << "Projecting from source mesh: " << meshTransferSourceMeshFileName;
1858 MOFEM_LOG("WORLD", Sev::verbose)
1859 << "Interpolation Stress tag name: " << internalStressTagName;
1860 MOFEM_LOG("WORLD", Sev::verbose) << "Interpolation Young's modulus tag name: "
1862 MOFEM_LOG("WORLD", Sev::verbose)
1863 << "Interpolation order: " << meshTransferInterpOrder;
1864 MOFEM_LOG("WORLD", Sev::verbose) << "Using hybrid interpolation: "
1865 << (meshTransferHybridInterp ? "yes" : "no");
1866
1867 auto &moab = mField.get_moab();
1868
1869 // check if tag exists
1870 for (const auto &tag_name : listTagsToProject) {
1871 Tag old_interp_tag;
1872 auto rval_check_tag = moab.tag_get_handle(tag_name.c_str(), old_interp_tag);
1873 if (rval_check_tag == MB_SUCCESS) {
1874 MOFEM_LOG("WORLD", Sev::inform)
1875 << "Deleting existing tag on target mesh: " << tag_name;
1876 CHKERR moab.tag_delete(old_interp_tag);
1877 }
1878 }
1879 // make a size-1 communicator for the coupler (rank 0 only)
1880 int world_rank = -1, world_size = -1;
1881 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
1882 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
1883
1884 Range original_meshset_ents;
1885 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
1886
1887 MPI_Comm comm_coupler;
1888 if (world_rank == 0) {
1889 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
1890 } else {
1891 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
1892 }
1893
1894 // build a separate ParallelComm for the coupler (rank 0 only)
1895 ParallelComm *pcomm0 = nullptr;
1896 int pcomm0_id = -1;
1897 if (world_rank == 0) {
1898 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
1899 }
1900
1901 Coupler::Method method;
1902 switch (meshTransferInterpOrder) {
1903 case 0:
1904 method = Coupler::CONSTANT;
1905 break;
1906 case 1:
1907 method = Coupler::LINEAR_FE;
1908 break;
1909 default:
1910 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1911 "Unsupported interpolation order");
1912 }
1913
1914 int nprocs, rank;
1915 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
1916 CHKERRQ(ierr);
1917 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1918 CHKERRQ(ierr);
1919
1920 // std::string read_opts, write_opts;
1921 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
1922 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
1923 // if (world_size > 1)
1924 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
1925 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
1926
1927 // create target mesh from existing meshset
1928 EntityHandle target_root;
1929 CHKERR moab.create_meshset(MESHSET_SET, target_root);
1930 MOFEM_LOG("WORLD", Sev::inform)
1931 << "Creating target mesh from existing meshset";
1932 Range target_meshset_ents;
1933 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
1934 CHKERR moab.add_entities(target_root, target_meshset_ents);
1935
1936 // variables for tags to be broadcast later
1937 std::vector<Tag> interp_tags;
1938 std::vector<int> tag_length;
1939 std::vector<DataType> dtype;
1940 std::vector<TagType> storage;
1941
1942 // load source mesh
1943 Range targ_verts, targ_elems;
1944 if (world_rank == 0) {
1945 EntityHandle source_root;
1946 CHKERR moab.create_meshset(MESHSET_SET, source_root);
1947
1948 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
1949 auto rval_source_mesh = moab.load_file(
1950 meshTransferSourceMeshFileName.c_str(), &source_root, "");
1951 if (rval_source_mesh != MB_SUCCESS) {
1952 MOFEM_LOG("WORLD", Sev::warning) << "Error loading source mesh file: "
1954 }
1955 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
1956
1957 Range src_elems;
1958 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
1959
1960 EntityHandle part_set;
1961 CHKERR pcomm0->create_part(part_set);
1962 CHKERR moab.add_entities(part_set, src_elems);
1963
1964 Range src_elems_part;
1965 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
1966
1967 for (const auto &iterp_tag_name : listTagsToProject) {
1968 std::string tag_to_use = iterp_tag_name;
1969
1970 Tag interp_tag;
1971 CHKERR moab.tag_get_handle(tag_to_use.c_str(), interp_tag);
1972
1973 int interp_tag_len;
1974 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
1975
1976 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
1977 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1978 "Unsupported interpolation tag length: %d", interp_tag_len);
1979 }
1980
1981 // store tag info for later broadcast
1982 tag_length.push_back(interp_tag_len);
1983 dtype.push_back(DataType());
1984 storage.push_back(TagType());
1985 interp_tags.push_back(interp_tag);
1986 CHKERR moab.tag_get_data_type(interp_tag, dtype.back());
1987 CHKERR moab.tag_get_type(interp_tag, storage.back());
1988
1989 // coupler is collective
1990 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
1991
1992 std::vector<double> vpos; // the positions we are interested in
1993 int num_pts = 0;
1994
1995 Range tmp_verts;
1996
1997 // First get all vertices adj to partition entities in target mesh
1998 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
1999
2000 if (meshTransferInterpOrder == 0) {
2001 targ_verts = targ_elems;
2002 } else {
2003 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
2004 moab::Interface::UNION);
2005 }
2006
2007 // Then get non-owned verts and subtract
2008 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
2009 targ_verts = subtract(targ_verts, tmp_verts);
2010
2011 // get position of these entities; these are the target points
2012 num_pts = (int)targ_verts.size();
2013 vpos.resize(3 * targ_verts.size());
2014 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2015
2016 // Locate those points in the source mesh
2017 boost::shared_ptr<TupleList> tl_ptr;
2018 tl_ptr = boost::make_shared<TupleList>();
2019 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2020 false);
2021
2022 // If some points were not located, we need to process them
2023 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
2024 std::vector<double> &vpos,
2025 Range &missing_verts) {
2027 int missing_pts_num = 0;
2028 int i = 0;
2029 auto vit = targ_verts.begin();
2030 for (; vit != targ_verts.end(); i++) {
2031 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
2032 missing_verts.insert(*vit);
2033 vit = targ_verts.erase(vit);
2034 missing_pts_num++;
2035 } else {
2036 vit++;
2037 }
2038 }
2039
2040 int missing_pts_num_global = 0;
2041 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
2042 // MPI_SUM, pcomm0);
2043 if (missing_pts_num_global) {
2044 MOFEM_LOG("WORLD", Sev::warning)
2045 << missing_pts_num_global
2046 << " points in target mesh were not located in source mesh. ";
2047 }
2048
2049 if (missing_pts_num) {
2050 num_pts = (int)targ_verts.size();
2051 vpos.resize(3 * targ_verts.size());
2052 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2053 tl_ptr->reset();
2054 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2055 false);
2056 }
2058 };
2059
2060 Range missing_verts;
2061 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
2062
2063 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
2064 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
2065
2066 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
2067
2068 Tag scalar_tag, adj_count_tag;
2069 double def_scl = 0;
2070 string scalar_tag_name = string(tag_to_use) + "_COMP";
2071 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2072 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2073 &def_scl);
2074
2075 string adj_count_tag_name = "ADJ_COUNT";
2076 double def_adj = 0;
2077 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2078 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2079 &def_adj);
2080
2081 // MBCoupler functionality supports only scalar tags. For the case of
2082 // vector or tensor tags we need to save each component as a scalar tag
2083 auto create_scalar_tags = [&](const Range &src_elems,
2084 const std::vector<double> &source_data,
2085 int itag) {
2087
2088 std::vector<double> source_data_scalar(src_elems.size());
2089 // Populate source_data_scalar
2090 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
2091 source_data_scalar[ielem] =
2092 source_data[itag + ielem * interp_tag_len];
2093 }
2094
2095 // Set data on the scalar tag
2096 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
2097
2098 if (meshTransferInterpOrder == 1) {
2099 // Linear interpolation: compute average value of data on vertices
2100 Range src_verts;
2101 CHKERR moab.get_connectivity(src_elems, src_verts, true);
2102
2103 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
2104 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
2105
2106 for (auto &tet : src_elems) {
2107 double tet_data = 0;
2108 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
2109
2110 Range adj_verts;
2111 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
2112
2113 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
2114 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
2115
2116 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2117 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
2118 &adj_vert_count[0]);
2119
2120 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
2121 adj_vert_data[ivert] += tet_data;
2122 adj_vert_count[ivert] += 1;
2123 }
2124
2125 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2126 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
2127 &adj_vert_count[0]);
2128 }
2129
2130 // Reduce tags for the parallel case
2131 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
2132 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
2133
2134 std::vector<double> src_vert_data(src_verts.size(), 0.0);
2135 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
2136
2137 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
2138 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
2139 &src_vert_adj_count[0]);
2140
2141 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
2142 src_vert_data[ivert] /= src_vert_adj_count[ivert];
2143 }
2144 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
2145 }
2147 };
2148
2149 MOFEM_LOG("WORLD", Sev::inform)
2150 << "Performing interpolation for tag: " << tag_to_use;
2151 MOFEM_LOG("WORLD", Sev::inform)
2152 << "Number of target points to interpolate: " << num_pts;
2153 MOFEM_LOG("WORLD", Sev::inform)
2154 << "Interpolation method: "
2155 << (method == Coupler::CONSTANT ? "constant" : "linear FE");
2156 MOFEM_LOG("WORLD", Sev::inform)
2157 << "Number of components in tag: " << interp_tag_len;
2158
2159 MOFEM_LOG("WORLD", Sev::inform)
2160 << "Source tag data range: ["
2161 << *std::min_element(source_data.begin(), source_data.end()) << ", "
2162 << *std::max_element(source_data.begin(), source_data.end()) << "]";
2163
2164 for (int itag = 0; itag < interp_tag_len; itag++) {
2165
2166 CHKERR create_scalar_tags(src_elems, source_data, itag);
2167
2168 std::vector<double> target_data_scalar(num_pts, 0.0);
2169 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
2170 tl_ptr.get());
2171
2172 for (int ielem = 0; ielem < num_pts; ielem++) {
2173 target_data[itag + ielem * interp_tag_len] =
2174 target_data_scalar[ielem];
2175 }
2176 }
2177
2178 // Use original tag
2179 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2180
2181 if (missing_verts.size() && (meshTransferInterpOrder == 1) &&
2183 MOFEM_LOG("WORLD", Sev::warning)
2184 << "Using hybrid interpolation for "
2185 "missing points in the target mesh.";
2186 Range missing_adj_elems;
2187 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2188 moab::Interface::UNION);
2189
2190 int num_adj_elems = (int)missing_adj_elems.size();
2191 std::vector<double> vpos_adj_elems;
2192
2193 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2194 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2195
2196 // Locate those points in the source mesh
2197 tl_ptr->reset();
2198 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2199 tl_ptr.get(), false);
2200
2201 Range missing_tets;
2202 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2203 vpos_adj_elems, missing_tets);
2204 if (missing_tets.size()) {
2205 MOFEM_LOG("WORLD", Sev::warning)
2206 << missing_tets.size()
2207 << " points in target mesh were not located in source mesh. ";
2208 }
2209
2210 std::vector<double> target_data_adj_elems(
2211 interp_tag_len * num_adj_elems, 0.0);
2212
2213 for (int itag = 0; itag < interp_tag_len; itag++) {
2214 CHKERR create_scalar_tags(src_elems, source_data, itag);
2215
2216 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2217 CHKERR mbc.interpolate(method, scalar_tag_name,
2218 &target_data_adj_elems_scalar[0],
2219 tl_ptr.get());
2220
2221 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2222 target_data_adj_elems[itag + ielem * interp_tag_len] =
2223 target_data_adj_elems_scalar[ielem];
2224 }
2225 }
2226
2227 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2228 &target_data_adj_elems[0]);
2229
2230 // FIXME: add implementation for parallel case
2231 for (auto &vert : missing_verts) {
2232 Range adj_elems;
2233 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2234 moab::Interface::UNION);
2235
2236 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2237 0.0);
2238 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2239
2240 std::vector<double> vert_data(interp_tag_len, 0.0);
2241 for (int itag = 0; itag < interp_tag_len; itag++) {
2242 for (int i = 0; i < adj_elems.size(); i++) {
2243 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2244 }
2245 vert_data[itag] /= adj_elems.size();
2246 }
2247 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2248 }
2249 }
2250
2251 CHKERR moab.tag_delete(scalar_tag);
2252 CHKERR moab.tag_delete(adj_count_tag);
2253 }
2254
2255 // delete source mesh after projection but keep the tags info for broadcast
2256 Range src_mesh_ents;
2257 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2258 CHKERR moab.delete_entities(&source_root, 1);
2259 CHKERR moab.delete_entities(src_mesh_ents);
2260 CHKERR moab.delete_entities(&part_set, 1);
2261 }
2262
2263 // broadcast tag info to other processors
2264 int tag_size = tag_length.size();
2265 MPI_Bcast(&tag_size, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2266 if (rank != 0) {
2267 interp_tags.resize(tag_size);
2268 tag_length.resize(tag_size);
2269 dtype.resize(tag_size);
2270 storage.resize(tag_size);
2271 }
2272 MPI_Bcast(interp_tags.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2273 MPI_Bcast(tag_length.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2274 MPI_Bcast(dtype.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2275 MPI_Bcast(storage.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2276
2277 // create new tag on other processors
2278 // loop over tag index to support multiple tags projection in one run
2279
2280 for (size_t index = 0; index < interp_tags.size(); index++) {
2281 // check if tag exists first
2282 if (world_rank) {
2283 Tag old_interp_tag;
2284 auto rval_check_tag =
2285 moab.tag_get_handle(listTagsToProject[index].c_str(), old_interp_tag);
2286 if (rval_check_tag == MB_SUCCESS) {
2287 MOFEM_LOG("WORLD", Sev::verbose)
2288 << "Deleting existing tag on target mesh (post-projection): "
2289 << listTagsToProject[index];
2290 CHKERR moab.tag_delete(old_interp_tag);
2291 }
2292 }
2293 Tag interp_tag_all;
2294 unsigned flags =
2295 MB_TAG_CREAT | storage[index]; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2296 std::vector<double> def_val(tag_length[index], 0.);
2297 auto rval = moab.tag_get_handle(listTagsToProject[index].c_str(),
2298 tag_length[index], dtype[index],
2299 interp_tag_all, flags, def_val.data());
2300 if (rval != MB_SUCCESS && world_rank) {
2301 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2302 "Unable to create projection tag %s",
2303 listTagsToProject[index].c_str());
2304 }
2305
2306 MPI_Barrier(PETSC_COMM_WORLD);
2307
2308 // exchange data for all entity types across all processors
2309 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2310 mField.get_comm(), mField.get_moab(), 0, tag_length[index],
2311 Sev::inform);
2312 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2313 mField.get_comm(), mField.get_moab(), 3, tag_length[index],
2314 Sev::inform);
2315
2317 mField.get_moab(), vertex_exchange, interp_tag_all);
2319 mField.get_moab(), volume_exchange, interp_tag_all);
2320 }
2321
2322 // delete target meshset but not the entities
2323 CHKERR moab.delete_entities(&target_root, 1);
2324
2325#endif // INCLUDE_MBCOUPLER
2327}
2328
2331 const bool add_bubble) {
2333
2334 // set finite element fields
2335 auto add_field_to_fe = [this](const std::string fe,
2336 const std::string field_name) {
2342 };
2343
2348
2349 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2350 if (add_bubble) {
2351 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2352 }
2354 CHKERR add_field_to_fe(elementVolumeName, stretchTensor);
2355 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2356 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2357 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2358 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2360
2361 // build finite elements data structures
2363 }
2364
2366}
2367
2371
2372 Range meshset_ents;
2373 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2374
2375 auto set_fe_adjacency = [&](auto fe_name) {
2378 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2381 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2383 };
2384
2385 // set finite element fields
2386 auto add_field_to_fe = [this](const std::string fe,
2387 const std::string field_name) {
2396 };
2397
2399
2400 Range natural_bc_elements;
2401 if (bcSpatialDispVecPtr) {
2402 for (auto &v : *bcSpatialDispVecPtr) {
2403 natural_bc_elements.merge(v.faces);
2404 }
2405 }
2407 for (auto &v : *bcSpatialRotationVecPtr) {
2408 natural_bc_elements.merge(v.faces);
2409 }
2410 }
2412 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2413 natural_bc_elements.merge(v.faces);
2414 }
2415 }
2418 natural_bc_elements.merge(v.faces);
2419 }
2420 }
2422 for (auto &v : *bcSpatialTractionVecPtr) {
2423 natural_bc_elements.merge(v.faces);
2424 }
2425 }
2427 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2428 natural_bc_elements.merge(v.faces);
2429 }
2430 }
2432 for (auto &v : *bcSpatialPressureVecPtr) {
2433 natural_bc_elements.merge(v.faces);
2434 }
2435 }
2436 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2437
2439 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2441 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2442 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2443 CHKERR set_fe_adjacency(naturalBcElement);
2445 }
2446
2447 auto get_skin = [&](auto &body_ents) {
2448 Skinner skin(&mField.get_moab());
2449 Range skin_ents;
2450 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2451 return skin_ents;
2452 };
2453
2454 auto filter_true_skin = [&](auto &&skin) {
2455 Range boundary_ents;
2456 ParallelComm *pcomm =
2457 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2458 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2459 PSTATUS_NOT, -1, &boundary_ents);
2460 return boundary_ents;
2461 };
2462
2464
2465 Range body_ents;
2466 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2467 body_ents);
2468 auto skin = filter_true_skin(get_skin(body_ents));
2469
2477 contactDisp);
2480
2482 }
2483
2485 if (contactFaces) {
2486 MOFEM_LOG("EP", Sev::inform)
2487 << "Contact elements " << contactFaces->size();
2491 CHKERR add_field_to_fe(contactElement, piolaStress);
2492 CHKERR add_field_to_fe(contactElement, contactDisp);
2493 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2494 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2495 CHKERR set_fe_adjacency(contactElement);
2497 }
2498 }
2499
2501 if (!skeletonFaces)
2502 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2503 MOFEM_LOG("EP", Sev::inform)
2504 << "Skeleton elements " << skeletonFaces->size();
2508 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2509 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2510 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2511 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2512 CHKERR set_fe_adjacency(skeletonElement);
2514 }
2515
2517}
2518
2520 const EntityHandle meshset) {
2522
2523 // find adjacencies between finite elements and dofs
2525
2526 // Create coupled problem
2527 dM = createDM(mField.get_comm(), "DMMOFEM");
2528 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2529 BitRefLevel().set());
2530 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2531 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2537
2538 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2539 CHKERR DMSetUp(dM);
2540 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2541
2542 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2544 for (int d : {0, 1, 2}) {
2545 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2547 ->getSideDofsOnBrokenSpaceEntities(
2548 dofs_to_remove, prb_name, ROW, piolaStress,
2550 // remove piola dofs, i.e. traction free boundary
2551 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2552 dofs_to_remove);
2553 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2554 dofs_to_remove);
2555 }
2557 };
2558 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2559
2560 // Create elastic sub-problem
2561 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2562 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2568 if (stretchHandling != NO_STREACH) {
2570 }
2580 CHKERR DMSetUp(dmElastic);
2581
2582 dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2583 CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2592 if (stretchHandling != NO_STREACH) {
2594 }
2600 CHKERR DMSetUp(dmMaterial);
2601
2602 auto set_zero_block = [&]() {
2604 if (stretchHandling != NO_STREACH) {
2605 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2606 "ELASTIC_PROBLEM", spatialL2Disp, stretchTensor);
2607 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2608 "ELASTIC_PROBLEM", stretchTensor, spatialL2Disp);
2609 }
2610 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2611 "ELASTIC_PROBLEM", spatialL2Disp, rotAxis);
2612 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2613 "ELASTIC_PROBLEM", rotAxis, spatialL2Disp);
2614 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2615 "ELASTIC_PROBLEM", spatialL2Disp, bubbleField);
2616 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2617 "ELASTIC_PROBLEM", bubbleField, spatialL2Disp);
2618 if (stretchHandling != NO_STREACH) {
2619 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2620 "ELASTIC_PROBLEM", bubbleField, bubbleField);
2621 CHKERR
2622 mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2623 "ELASTIC_PROBLEM", piolaStress, piolaStress);
2624 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2625 "ELASTIC_PROBLEM", bubbleField, piolaStress);
2626 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2627 "ELASTIC_PROBLEM", piolaStress, bubbleField);
2628 }
2629
2630 auto zero_kinetic_constraints_block = [&]() {
2632 // we shoudl have sparet bloc names for this. TOPO_FIX_X, TOPO_FIX_Y,
2633 // TOPO_FIX_Z, TOPO_FIX_ALL
2634 auto bc_mng = mField.getInterface<BcManager>();
2635 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_X",
2636 materialH1Positions, 0, 0);
2637 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Y",
2638 materialH1Positions, 1, 1);
2639 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Z",
2640 materialH1Positions, 2, 2);
2641 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_ALL",
2642 materialH1Positions, 0, 3);
2643 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_X",
2644 materialH1Positions, 0, 0);
2645 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Y",
2646 materialH1Positions, 1, 1);
2647 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Z",
2648 materialH1Positions, 2, 2);
2649 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_ALL",
2650 materialH1Positions, 0, 3);
2652 };
2653
2654 // CHKERR zero_kinetic_constraints_block();
2655
2658 };
2659
2660 auto set_section = [&]() {
2662 PetscSection section;
2663 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2664 &section);
2665 CHKERR DMSetSection(dmElastic, section);
2666 CHKERR DMSetGlobalSection(dmElastic, section);
2667 CHKERR PetscSectionDestroy(&section);
2669 };
2670
2671 CHKERR set_zero_block();
2672 CHKERR set_section();
2673
2674 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2675 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2681 CHKERR DMSetUp(dmPrjSpatial);
2682
2683 // CHKERR mField.getInterface<BcManager>()
2684 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2685 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2686
2688}
2689
2690BcDisp::BcDisp(std::string name, std::vector<double> attr, Range faces)
2691 : blockName(name), faces(faces) {
2692 vals.resize(3, false);
2693 flags.resize(3, false);
2694 for (int ii = 0; ii != 3; ++ii) {
2695 vals[ii] = attr[ii];
2696 flags[ii] = static_cast<int>(attr[ii + 3]);
2697 }
2698
2699 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp " << name;
2700 MOFEM_LOG("EP", Sev::inform)
2701 << "Add BCDisp vals " << vals[0] << " " << vals[1] << " " << vals[2];
2702 MOFEM_LOG("EP", Sev::inform)
2703 << "Add BCDisp flags " << flags[0] << " " << flags[1] << " " << flags[2];
2704 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp nb. of faces " << faces.size();
2705}
2706
2707BcRot::BcRot(std::string name, std::vector<double> attr, Range faces)
2708 : blockName(name), faces(faces) {
2709 vals.resize(attr.size(), false);
2710 for (int ii = 0; ii != attr.size(); ++ii) {
2711 vals[ii] = attr[ii];
2712 }
2713 theta = attr[3];
2714}
2715
2716TractionBc::TractionBc(std::string name, std::vector<double> attr, Range faces)
2717 : blockName(name), faces(faces) {
2718 vals.resize(3, false);
2719 flags.resize(3, false);
2720 for (int ii = 0; ii != 3; ++ii) {
2721 vals[ii] = attr[ii];
2722 flags[ii] = static_cast<int>(attr[ii + 3]);
2723 }
2724
2725 MOFEM_LOG("EP", Sev::inform) << "Add BCForce " << name;
2726 MOFEM_LOG("EP", Sev::inform)
2727 << "Add BCForce vals " << vals[0] << " " << vals[1] << " " << vals[2];
2728 MOFEM_LOG("EP", Sev::inform)
2729 << "Add BCForce flags " << flags[0] << " " << flags[1] << " " << flags[2];
2730 MOFEM_LOG("EP", Sev::inform) << "Add BCForce nb. of faces " << faces.size();
2731}
2732
2734 std::vector<double> attr,
2735 Range faces)
2736 : blockName(name), faces(faces) {
2737
2738 blockName = name;
2739 if (attr.size() < 1) {
2741 "Wrong size of normal displacement BC");
2742 }
2743
2744 val = attr[0];
2745
2746 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc " << name;
2747 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc val " << val;
2748 MOFEM_LOG("EP", Sev::inform)
2749 << "Add NormalDisplacementBc nb. of faces " << faces.size();
2750}
2751
2752PressureBc::PressureBc(std::string name, std::vector<double> attr, Range faces)
2753 : blockName(name), faces(faces) {
2754
2755 blockName = name;
2756 if (attr.size() < 1) {
2758 "Wrong size of normal displacement BC");
2759 }
2760
2761 val = attr[0];
2762
2763 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc " << name;
2764 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc val " << val;
2765 MOFEM_LOG("EP", Sev::inform)
2766 << "Add PressureBc nb. of faces " << faces.size();
2767}
2768
2769ExternalStrain::ExternalStrain(std::string name, std::vector<double> attr,
2770 Range ents)
2771 : blockName(name), ents(ents) {
2772
2773 blockName = name;
2774 if (attr.size() < 2) {
2776 "Wrong size of external strain attribute");
2777 }
2778
2779 val = attr[0];
2780 bulkModulusK = attr[1];
2781
2782 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain " << name;
2783 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain val " << val;
2784 MOFEM_LOG("EP", Sev::inform)
2785 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2786 MOFEM_LOG("EP", Sev::inform)
2787 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2788 MOFEM_LOG("EP", Sev::inform)
2789 << "Add ExternalStrain nb. of tets " << ents.size();
2790}
2791
2793 std::vector<double> attr,
2794 Range faces)
2795 : blockName(name), faces(faces) {
2796
2797 blockName = name;
2798 if (attr.size() < 3) {
2800 "Wrong size of analytical displacement BC");
2801 }
2802
2803 flags.resize(3, false);
2804 for (int ii = 0; ii != 3; ++ii) {
2805 flags[ii] = attr[ii];
2806 }
2807
2808 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalDisplacementBc " << name;
2809 MOFEM_LOG("EP", Sev::inform)
2810 << "Add AnalyticalDisplacementBc flags " << flags[0] << " " << flags[1]
2811 << " " << flags[2];
2812 MOFEM_LOG("EP", Sev::inform)
2813 << "Add AnalyticalDisplacementBc nb. of faces " << faces.size();
2814}
2815
2817 std::vector<double> attr,
2818 Range faces)
2819 : blockName(name), faces(faces) {
2820
2821 blockName = name;
2822 if (attr.size() < 3) {
2824 "Wrong size of analytical traction BC");
2825 }
2826
2827 flags.resize(3, false);
2828 for (int ii = 0; ii != 3; ++ii) {
2829 flags[ii] = attr[ii];
2830 }
2831
2832 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc " << name;
2833 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc flags " << flags[0]
2834 << " " << flags[1] << " " << flags[2];
2835 MOFEM_LOG("EP", Sev::inform)
2836 << "Add AnalyticalTractionBc nb. of faces " << faces.size();
2837}
2838
2841 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2842 const std::string contact_set_name) {
2844
2845 // get skin from all tets
2846 Range tets;
2847 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2848 Range tets_skin_part;
2849 Skinner skin(&mField.get_moab());
2850 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
2851 ParallelComm *pcomm =
2852 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2853 Range tets_skin;
2854 CHKERR pcomm->filter_pstatus(tets_skin_part,
2855 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2856 PSTATUS_NOT, -1, &tets_skin);
2857
2858 bc_ptr->resize(3);
2859 for (int dd = 0; dd != 3; ++dd)
2860 (*bc_ptr)[dd] = tets_skin;
2861
2862 // Do not remove dofs on which traction is applied
2863 if (bcSpatialDispVecPtr)
2864 for (auto &v : *bcSpatialDispVecPtr) {
2865 if (v.flags[0])
2866 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2867 if (v.flags[1])
2868 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2869 if (v.flags[2])
2870 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2871 }
2872
2873 // Do not remove dofs on which rotation is applied
2874 if (bcSpatialRotationVecPtr)
2875 for (auto &v : *bcSpatialRotationVecPtr) {
2876 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2877 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2878 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2879 }
2880
2881 if (bcSpatialNormalDisplacementVecPtr)
2882 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2883 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2884 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2885 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2886 }
2887
2888 if (bcSpatialAnalyticalDisplacementVecPtr)
2889 for (auto &v : *bcSpatialAnalyticalDisplacementVecPtr) {
2890 if (v.flags[0])
2891 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2892 if (v.flags[1])
2893 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2894 if (v.flags[2])
2895 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2896 }
2897
2898 if (bcSpatialTractionVecPtr)
2899 for (auto &v : *bcSpatialTractionVecPtr) {
2900 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2901 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2902 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2903 }
2904
2905 if (bcSpatialAnalyticalTractionVecPtr)
2906 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2907 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2908 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2909 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2910 }
2911
2912 if (bcSpatialPressureVecPtr)
2913 for (auto &v : *bcSpatialPressureVecPtr) {
2914 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2915 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2916 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2917 }
2918
2919 // remove contact
2920 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
2921 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
2922 Range faces;
2923 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2924 true);
2925 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2926 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2927 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2928 }
2929
2931}
2932
2933/**
2934 * @brief Set integration rule on element
2935 * \param order on row
2936 * \param order on column
2937 * \param order on data
2938 *
2939 * Use maximal oder on data in order to determine integration rule
2940 *
2941 */
2942struct VolRule {
2943 int operator()(int p_row, int p_col, int p_data) const {
2944 return 2 * p_data + 1;
2945 }
2946};
2947
2948struct FaceRule {
2949 int operator()(int p_row, int p_col, int p_data) const {
2950 return 2 * (p_data + 1);
2951 }
2952};
2953
2955 const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates,
2956 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
2957 const bool add_bubble) {
2959
2960 auto bubble_cache =
2961 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
2962 fe->getUserPolynomialBase() =
2963 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2964 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2965 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2966
2967 // set integration rule
2968 fe->getRuleHook = [](int, int, int) { return -1; };
2969 // auto vol_rule = (SMALL_ROT > 0) ? vol_rule_lin : vol_rule_no_lin;
2970 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
2971 vol_rule, bubble_cache);
2972 // fe->getRuleHook = VolRule();
2973
2974 if (!dataAtPts) {
2975 dataAtPts =
2976 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
2977 dataAtPts->physicsPtr = physicalEquations;
2978 }
2979
2980 // calculate fields values
2981 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
2982 piolaStress, dataAtPts->getApproxPAtPts()));
2983 if (add_bubble) {
2984 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
2985 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2986 }
2987 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
2988 piolaStress, dataAtPts->getDivPAtPts()));
2989
2990 if (stretchHandling == NO_STREACH) {
2991 fe->getOpPtrVector().push_back(
2992 physicalEquations->returnOpCalculateStretchFromStress(
2993 dataAtPts, physicalEquations));
2994 } else {
2995 fe->getOpPtrVector().push_back(
2997 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2998 }
2999
3000 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3001 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3002 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
3003 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3004 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3005 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3006 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3007
3008 // H1 displacements
3009 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3010 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3011 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3012 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3013
3014 // velocities
3015 if (calc_rates) {
3016 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3017 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
3018 if (stretchHandling == NO_STREACH) {
3019 } else {
3020 fe->getOpPtrVector().push_back(
3022 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
3023 fe->getOpPtrVector().push_back(
3025 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
3026 MBTET));
3027 }
3028 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3029 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
3030 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
3031 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
3032
3033 // acceleration
3034 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3035 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
3036 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
3037 }
3038 }
3039
3040 // calculate other derived quantities
3041 fe->getOpPtrVector().push_back(new OpCalculateRotationAndSpatialGradient(
3042 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
3043
3044 // evaluate integration points
3045 if (stretchHandling == NO_STREACH) {
3046 } else {
3047 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3048 do_rhs, do_lhs, dataAtPts, physicalEquations));
3049 }
3050
3052}
3053
3055 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3057
3058 bool has_nonhomogeneous_mat_block =
3060 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_dP(
3061 piolaStress, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3062 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dP(
3063 bubbleField, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3064 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dBubble(
3065 bubbleField, bubbleField, dataAtPts, has_nonhomogeneous_mat_block));
3066
3067 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3068 spatialL2Disp, piolaStress, dataAtPts, true));
3069 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3070 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3071
3072 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3073 piolaStress, rotAxis, dataAtPts,
3074 symmetrySelector == SYMMETRIC ? true : false));
3075 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3076 bubbleField, rotAxis, dataAtPts,
3077 symmetrySelector == SYMMETRIC ? true : false));
3078
3079 if (symmetrySelector > SYMMETRIC) {
3080 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3081 rotAxis, piolaStress, dataAtPts, false));
3082 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3083 rotAxis, bubbleField, dataAtPts, false));
3084 }
3085 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3086 rotAxis, rotAxis, dataAtPts, alphaOmega));
3087
3089}
3090
3092 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3094
3095 fe_lhs->getOpPtrVector().push_back(
3096 physicalEquations->returnOpSpatialPhysical_du_du(
3097 stretchTensor, stretchTensor, dataAtPts, alphaU));
3098 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dP(
3099 stretchTensor, piolaStress, dataAtPts, true));
3100 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dBubble(
3101 stretchTensor, bubbleField, dataAtPts, true));
3102 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_domega(
3103 stretchTensor, rotAxis, dataAtPts,
3104 symmetrySelector == SYMMETRIC ? true : false));
3105
3106 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3107 spatialL2Disp, piolaStress, dataAtPts, true));
3108 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3109 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3110
3111 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3112 piolaStress, rotAxis, dataAtPts,
3113 symmetrySelector == SYMMETRIC ? true : false));
3114 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3115 bubbleField, rotAxis, dataAtPts,
3116 symmetrySelector == SYMMETRIC ? true : false));
3117
3118 if (symmetrySelector > SYMMETRIC) {
3119 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_du(
3120 rotAxis, stretchTensor, dataAtPts, false));
3121 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3122 rotAxis, piolaStress, dataAtPts, false));
3123 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3124 rotAxis, bubbleField, dataAtPts, false));
3125 }
3126 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3127 rotAxis, rotAxis, dataAtPts, alphaOmega));
3128
3130}
3131
3133 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3135 CHKERR pushPiolaStressGramOps(fe_lhs);
3136 fe_lhs->getOpPtrVector().push_back(
3137 new OpStressGram_dBubble_dP(bubbleField, piolaStress, dataAtPts));
3138 fe_lhs->getOpPtrVector().push_back(new OpStressGram_dBubble_dBubble(
3139 bubbleField, bubbleField));
3141}
3142
3144 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3146 fe_lhs->getOpPtrVector().push_back(
3147 new OpStressGram_dP_dP(piolaStress, piolaStress));
3149}
3150
3152 const int tag, const bool add_elastic, const bool add_material,
3153 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
3154 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
3156
3157 /** Contact requires that body is marked */
3158 auto get_body_range = [this](auto name, int dim) {
3159 std::map<int, Range> map;
3160
3161 for (auto m_ptr :
3162 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3163
3164 (boost::format("%s(.*)") % name).str()
3165
3166 ))
3167
3168 ) {
3169 Range ents;
3170 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3171 dim, ents, true),
3172 "by dim");
3173 map[m_ptr->getMeshsetId()] = ents;
3174 }
3175
3176 return map;
3177 };
3178
3179 auto local_tau_sacale = boost::make_shared<double>(1.0);
3180 using BoundaryEle =
3182 using BdyEleOp = BoundaryEle::UserDataOperator;
3183 struct OpSetTauScale : public BdyEleOp {
3184 OpSetTauScale(boost::shared_ptr<double> local_tau_sacale, double alphaTau)
3185 : BdyEleOp(NOSPACE, BdyEleOp::OPSPACE),
3186 localTauSacale(local_tau_sacale), alphaTau(alphaTau) {}
3187 MoFEMErrorCode doWork(int side, EntityType type,
3188 EntitiesFieldData::EntData &data) override {
3190 auto &coords = BdyEleOp::getCoords();
3191 auto [centre, barycenter, h] =
3192 Tools::getTricircumcenter3d(coords.data().data());
3193 *localTauSacale = (alphaTau / h);
3195 }
3196
3197 private:
3198 boost::shared_ptr<double> localTauSacale;
3199 double alphaTau;
3200 };
3201
3202 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
3203 auto ent = fe_method_ptr->getFEEntityHandle();
3204 if (
3205
3206 (interfaceFaces->find(ent) != interfaceFaces->end())
3207
3208 || (crackFaces->find(ent) != crackFaces->end())
3209
3210 ) {
3211 return false;
3212 };
3213 return true;
3214 };
3215
3216 // Right hand side
3217 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3218 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
3219
3220 // elastic
3221 if (add_elastic) {
3222
3223 fe_rhs->getOpPtrVector().push_back(
3224 new OpSpatialEquilibrium(spatialL2Disp, dataAtPts, alphaW, alphaRho));
3225 fe_rhs->getOpPtrVector().push_back(
3226 new OpSpatialRotation(rotAxis, dataAtPts, alphaOmega));
3227 if (stretchHandling == NO_STREACH) {
3228 // do nothing - no stretch approximation
3229 } else {
3230 if (!internalStressTagName.empty()) {
3231 switch (meshTransferInterpOrder) {
3232 case 0:
3233 fe_rhs->getOpPtrVector().push_back(
3234 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
3235 break;
3236 case 1:
3237 fe_rhs->getOpPtrVector().push_back(
3238 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
3239 break;
3240 default:
3241 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3242 "Unsupported mesh transfer interpolation order %d, for "
3243 "internal stress",
3244 meshTransferInterpOrder);
3245 }
3246 // set default time scaling for interal stresses to constant
3247 TimeScale::ScalingFun def_scaling_fun = [](double time) { return 1; };
3248 auto ts_internal_stress =
3249 boost::make_shared<DynamicRelaxationTimeScale>(
3250 "internal_stress_history.txt", false, def_scaling_fun);
3251 if (internalStressVoigt) {
3252 fe_rhs->getOpPtrVector().push_back(
3254 stretchTensor, dataAtPts, ts_internal_stress));
3255 } else {
3256 fe_rhs->getOpPtrVector().push_back(
3258 stretchTensor, dataAtPts, ts_internal_stress));
3259 }
3260 }
3261 if (auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
3262 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
3263 fe_rhs->getOpPtrVector().push_back(op);
3264 } else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
3265 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3266 "OpSpatialPhysicalExternalStrain not implemented for this "
3267 "material");
3268 }
3269
3270 fe_rhs->getOpPtrVector().push_back(
3271 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
3272 alphaU));
3273 }
3274 fe_rhs->getOpPtrVector().push_back(
3275 new OpSpatialConsistencyP(piolaStress, dataAtPts));
3276 fe_rhs->getOpPtrVector().push_back(
3277 new OpSpatialConsistencyBubble(bubbleField, dataAtPts));
3278 fe_rhs->getOpPtrVector().push_back(
3279 new OpSpatialConsistencyDivTerm(piolaStress, dataAtPts));
3280
3281 auto set_hybridisation_rhs = [&](auto &pip) {
3283
3284 using BoundaryEle =
3286 using EleOnSide =
3288 using SideEleOp = EleOnSide::UserDataOperator;
3289 using BdyEleOp = BoundaryEle::UserDataOperator;
3290
3291 // First: Iterate over skeleton FEs adjacent to Domain FEs
3292 // Note: BoundaryEle, i.e. uses skeleton interation rule
3293 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3294 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3295 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3296 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3297 return -1;
3298 };
3299 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3300 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3301
3302 CHKERR EshelbianPlasticity::
3303 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3304 op_loop_skeleton_side->getOpPtrVector(), {L2},
3305 materialH1Positions, frontAdjEdges);
3306
3307 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3308 // domain element.
3309 auto broken_data_ptr =
3310 boost::make_shared<std::vector<BrokenBaseSideData>>();
3311 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3312 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3313 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3314 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3315 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3316 CHKERR
3317 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3318 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3319 materialH1Positions, frontAdjEdges);
3320 op_loop_domain_side->getOpPtrVector().push_back(
3321 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3322 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3323 op_loop_domain_side->getOpPtrVector().push_back(
3325 flux_mat_ptr));
3326 op_loop_domain_side->getOpPtrVector().push_back(
3327 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3328
3329 // Assemble on skeleton
3330 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3332 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
3334 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3335 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
3336 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
3337 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3338 op_loop_skeleton_side->getOpPtrVector().push_back(
3339 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3340 hybrid_ptr));
3341 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3342 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3343
3344 // Add skeleton to domain pipeline
3345 pip.push_back(op_loop_skeleton_side);
3346
3348 };
3349
3350 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3351 auto hybrid_field) {
3353
3354 using BoundaryEle =
3356 using EleOnSide =
3358 using SideEleOp = EleOnSide::UserDataOperator;
3359 using BdyEleOp = BoundaryEle::UserDataOperator;
3360
3361 // First: Iterate over skeleton FEs adjacent to Domain FEs
3362 // Note: BoundaryEle, i.e. uses skeleton interation rule
3363 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3364 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3365 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3366 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3367 return -1;
3368 };
3369 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3370 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3371 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3372 CHKERR EshelbianPlasticity::
3373 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3374 op_loop_skeleton_side->getOpPtrVector(), {L2},
3375 materialH1Positions, frontAdjEdges);
3376
3377 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3378 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3379 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3380 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3381 CHKERR
3382 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3383 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3384 materialH1Positions, frontAdjEdges);
3385
3386 // Add stabilization operator
3387 auto broken_disp_data_ptr =
3388 boost::make_shared<std::vector<BrokenBaseSideData>>();
3389 op_loop_domain_side->getOpPtrVector().push_back(
3390 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3391 broken_disp_data_ptr));
3392 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3393 op_loop_domain_side->getOpPtrVector().push_back(
3395 disp_mat_ptr));
3396 // Set diag fluxes on skeleton side
3397 op_loop_domain_side->getOpPtrVector().push_back(
3398 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3399
3400 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3401 op_loop_skeleton_side->getOpPtrVector().push_back(
3402 new OpSetTauScale(local_tau_sacale, alphaTau));
3403
3404 // Add stabilization Ugamma Ugamma skeleton
3405 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3406 op_loop_skeleton_side->getOpPtrVector().push_back(
3408 hybrid_ptr));
3409
3410 // Diag u_gamma - u_gamma faces
3411 op_loop_skeleton_side->getOpPtrVector().push_back(
3413 hybrid_field, hybrid_ptr,
3414 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3415 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3416 }));
3417 // Diag L2 - L2 volumes
3418 op_loop_skeleton_side->getOpPtrVector().push_back(
3420 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3421 return (*local_tau_sacale);
3422 }));
3423 // Off-diag Ugamma - L2
3424 op_loop_skeleton_side->getOpPtrVector().push_back(
3426 hybrid_field, broken_disp_data_ptr,
3427 [local_tau_sacale](double, double, double) {
3428 return -(*local_tau_sacale);
3429 }));
3430 // Off-diag L2 - Ugamma
3431 op_loop_skeleton_side->getOpPtrVector().push_back(
3433 broken_disp_data_ptr, hybrid_ptr,
3434 [local_tau_sacale](double, double, double) {
3435 return -(*local_tau_sacale);
3436 }));
3437
3438 // Add skeleton to domain pipeline
3439 pip.push_back(op_loop_skeleton_side);
3440
3442 };
3443
3444 auto set_tau_stabilsation_disp_bc_rhs = [&](auto &pip, auto side_fe_name) {
3446
3447 using BoundaryEle =
3449 using EleOnSide =
3451 using SideEleOp = EleOnSide::UserDataOperator;
3452 using BdyEleOp = BoundaryEle::UserDataOperator;
3453
3454 // First: Iterate over skeleton FEs adjacent to Domain FEs
3455 // Note: BoundaryEle, i.e. uses skeleton interation rule
3456 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3457 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3458 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3459 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3460 return -1;
3461 };
3462 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3463 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3464 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3465 CHKERR EshelbianPlasticity::
3466 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3467 op_loop_skeleton_side->getOpPtrVector(), {L2},
3468 materialH1Positions, frontAdjEdges);
3469
3470 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3471 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3472 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3473 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3474 CHKERR
3475 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3476 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3477 materialH1Positions, frontAdjEdges);
3478
3479 // Add stabilization operator
3480 auto broken_disp_data_ptr =
3481 boost::make_shared<std::vector<BrokenBaseSideData>>();
3482 op_loop_domain_side->getOpPtrVector().push_back(
3483 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3484 broken_disp_data_ptr));
3485 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3486 op_loop_domain_side->getOpPtrVector().push_back(
3488 disp_mat_ptr));
3489 // Set diag fluxes on skeleton side
3490 op_loop_domain_side->getOpPtrVector().push_back(
3491 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3492
3493 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3494 op_loop_skeleton_side->getOpPtrVector().push_back(
3495 new OpSetTauScale(local_tau_sacale, alphaTau));
3496
3497 // Diag L2 - L2 volumes
3498 op_loop_skeleton_side->getOpPtrVector().push_back(
3500 broken_disp_data_ptr, bcSpatialDispVecPtr, timeScaleMap,
3501 [local_tau_sacale](double, double, double) {
3502 return (*local_tau_sacale);
3503 }));
3504 op_loop_skeleton_side->getOpPtrVector().push_back(
3506 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3507 timeScaleMap, [local_tau_sacale](double, double, double) {
3508 return (*local_tau_sacale);
3509 }));
3510 op_loop_skeleton_side->getOpPtrVector().push_back(
3512 broken_disp_data_ptr, bcSpatialRotationVecPtr, timeScaleMap,
3513 [local_tau_sacale](double, double, double) {
3514 return (*local_tau_sacale);
3515 }));
3516
3517 // Add skeleton to domain pipeline
3518 pip.push_back(op_loop_skeleton_side);
3519
3521 };
3522
3523 auto set_contact_rhs = [&](auto &pip) {
3524 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3525 };
3526
3527 auto set_cohesive_rhs = [&](auto &pip) {
3528 return pushCohesiveOpsRhs(
3529 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3530 interfaceFaces, pip);
3531 };
3532
3533 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3534 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3535 if (alphaTau > 0.0) {
3536 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3537 hybridSpatialDisp);
3538 CHKERR set_tau_stabilsation_disp_bc_rhs(fe_rhs->getOpPtrVector(),
3539 naturalBcElement);
3540 }
3541 if (interfaceCrack == PETSC_TRUE) {
3542 CHKERR set_cohesive_rhs(fe_rhs->getOpPtrVector());
3543 }
3544
3545 // Body forces
3546 using BodyNaturalBC =
3548 Assembly<PETSC>::LinearForm<GAUSS>;
3549 using OpBodyForce =
3550 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3551
3552 auto body_time_scale =
3553 boost::make_shared<DynamicRelaxationTimeScale>("body_force.txt");
3554 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3555 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3556 "BODY_FORCE", Sev::inform);
3557 }
3558
3559 // Left hand side
3560 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3561 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3562
3563 // elastic
3564 if (add_elastic) {
3565
3566 if (stretchHandling == NO_STREACH) {
3567 CHKERR pushNoStretchVolumeA00Ops(fe_lhs);
3568 } else {
3569 CHKERR pushStretchVolumeA00Ops(fe_lhs);
3570 }
3571
3572 auto set_hybridisation_lhs = [&](auto &pip) {
3574
3575 using BoundaryEle =
3577 using EleOnSide =
3579 using SideEleOp = EleOnSide::UserDataOperator;
3580 using BdyEleOp = BoundaryEle::UserDataOperator;
3581
3582 // First: Iterate over skeleton FEs adjacent to Domain FEs
3583 // Note: BoundaryEle, i.e. uses skeleton interation rule
3584 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3585 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3586 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3587 return -1;
3588 };
3589 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3590 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3591 CHKERR EshelbianPlasticity::
3592 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3593 op_loop_skeleton_side->getOpPtrVector(), {L2},
3594 materialH1Positions, frontAdjEdges);
3595
3596 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3597 // domain element.
3598 auto broken_data_ptr =
3599 boost::make_shared<std::vector<BrokenBaseSideData>>();
3600 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3601 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3602 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3603 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3604 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3605 CHKERR
3606 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3607 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3608 materialH1Positions, frontAdjEdges);
3609 op_loop_domain_side->getOpPtrVector().push_back(
3610 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3611
3612 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3614 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3615 op_loop_skeleton_side->getOpPtrVector().push_back(
3616 new OpC(hybridSpatialDisp, broken_data_ptr,
3617 boost::make_shared<double>(1.0), true, false));
3618
3619 pip.push_back(op_loop_skeleton_side);
3620
3622 };
3623
3624 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3625 auto hybrid_field) {
3627
3628 using BoundaryEle =
3630 using EleOnSide =
3632 using SideEleOp = EleOnSide::UserDataOperator;
3633 using BdyEleOp = BoundaryEle::UserDataOperator;
3634
3635 // First: Iterate over skeleton FEs adjacent to Domain FEs
3636 // Note: BoundaryEle, i.e. uses skeleton interation rule
3637 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3638 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3639 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3640 return -1;
3641 };
3642 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3643 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3644 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3645 CHKERR EshelbianPlasticity::
3646 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3647 op_loop_skeleton_side->getOpPtrVector(), {L2},
3648 materialH1Positions, frontAdjEdges);
3649
3650 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3651 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3652 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3653 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3654 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3655 CHKERR
3656 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3657 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3658 materialH1Positions, frontAdjEdges);
3659
3660 auto broken_disp_data_ptr =
3661 boost::make_shared<std::vector<BrokenBaseSideData>>();
3662 op_loop_domain_side->getOpPtrVector().push_back(
3663 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3664 broken_disp_data_ptr));
3665 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3666 op_loop_skeleton_side->getOpPtrVector().push_back(
3667 new OpSetTauScale(local_tau_sacale, alphaTau));
3668
3669 // Diag Ugamma-Ugamma skeleton
3670 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3671 hybrid_field, hybrid_field,
3672 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3673 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3674 }));
3675 // Diag L2-L2 volumes
3676 op_loop_skeleton_side->getOpPtrVector().push_back(
3678 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3679 return (*local_tau_sacale);
3680 }));
3681 // Off-diag Ugamma - L2
3682 op_loop_skeleton_side->getOpPtrVector().push_back(
3684 hybrid_field, broken_disp_data_ptr,
3685 [local_tau_sacale](double, double, double) {
3686 return -(*local_tau_sacale);
3687 },
3688 false, false));
3689 // Off-diag L2 - Ugamma
3690 op_loop_skeleton_side->getOpPtrVector().push_back(
3692 hybrid_field, broken_disp_data_ptr,
3693 [local_tau_sacale](double, double, double) {
3694 return -(*local_tau_sacale);
3695 },
3696 true, true));
3697
3698 pip.push_back(op_loop_skeleton_side);
3699
3701 };
3702
3703 auto set_tau_stabilsation_disp_bc_lhs = [&](auto &pip, auto side_fe_name) {
3705
3706 using BoundaryEle =
3708 using EleOnSide =
3710 using SideEleOp = EleOnSide::UserDataOperator;
3711 using BdyEleOp = BoundaryEle::UserDataOperator;
3712
3713 // First: Iterate over skeleton FEs adjacent to Domain FEs
3714 // Note: BoundaryEle, i.e. uses skeleton interation rule
3715 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3716 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3717 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3718 return -1;
3719 };
3720 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3721 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3722 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3723 CHKERR EshelbianPlasticity::
3724 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3725 op_loop_skeleton_side->getOpPtrVector(), {L2},
3726 materialH1Positions, frontAdjEdges);
3727
3728 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3729 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3730 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3731 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3732 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3733 CHKERR
3734 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3735 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3736 materialH1Positions, frontAdjEdges);
3737
3738 auto broken_disp_data_ptr =
3739 boost::make_shared<std::vector<BrokenBaseSideData>>();
3740 op_loop_domain_side->getOpPtrVector().push_back(
3741 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3742 broken_disp_data_ptr));
3743 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3744 op_loop_skeleton_side->getOpPtrVector().push_back(
3745 new OpSetTauScale(local_tau_sacale, alphaTau));
3746
3747 // Diag L2-L2 volumes
3748 op_loop_skeleton_side->getOpPtrVector().push_back(
3750 broken_disp_data_ptr, bcSpatialDispVecPtr,
3751 [local_tau_sacale](double, double, double) {
3752 return (*local_tau_sacale);
3753 }));
3754 op_loop_skeleton_side->getOpPtrVector().push_back(
3756 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3757 [local_tau_sacale](double, double, double) {
3758 return (*local_tau_sacale);
3759 }));
3760 op_loop_skeleton_side->getOpPtrVector().push_back(
3762 broken_disp_data_ptr, bcSpatialRotationVecPtr,
3763 [local_tau_sacale](double, double, double) {
3764 return (*local_tau_sacale);
3765 }));
3766
3767 pip.push_back(op_loop_skeleton_side);
3768
3770 };
3771
3772 auto set_contact_lhs = [&](auto &pip) {
3773 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3774 };
3775
3776 auto set_cohesive_lhs = [&](auto &pip) {
3777 return pushCohesiveOpsLhs(
3778 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3779 interfaceFaces, pip);
3780 };
3781
3782 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3783 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3784 if (alphaTau > 0.0) {
3785 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3786 hybridSpatialDisp);
3787 CHKERR set_tau_stabilsation_disp_bc_lhs(fe_lhs->getOpPtrVector(),
3788 naturalBcElement);
3789 }
3790 if (interfaceCrack == PETSC_TRUE) {
3791 CHKERR set_cohesive_lhs(fe_lhs->getOpPtrVector());
3792 }
3793 }
3794
3795 if (add_material) {
3796 }
3797
3799}
3800
3802 const bool add_elastic, const bool add_material,
3803 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3804 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3806
3807 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3808 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3809
3810 // set integration rule
3811 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3812 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3813 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
3814 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
3815 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3816 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3817
3818 CHKERR
3819 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3820 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3821 CHKERR
3822 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3823 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3824
3825 if (add_elastic) {
3826
3827 auto get_broken_op_side = [this](auto &pip) {
3828 using EleOnSide =
3830 using SideEleOp = EleOnSide::UserDataOperator;
3831 // Iterate over domain FEs adjacent to boundary.
3832 auto broken_data_ptr =
3833 boost::make_shared<std::vector<BrokenBaseSideData>>();
3834 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3835 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
3836 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3837 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3838 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3839 CHKERR
3840 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3841 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3842 materialH1Positions, frontAdjEdges);
3843 op_loop_domain_side->getOpPtrVector().push_back(
3844 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3845 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3846 op_loop_domain_side->getOpPtrVector().push_back(
3848 flux_mat_ptr));
3849 op_loop_domain_side->getOpPtrVector().push_back(
3850 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3851 pip.push_back(op_loop_domain_side);
3852 return broken_data_ptr;
3853 };
3854
3855 auto set_rhs = [&]() {
3857
3858 auto broken_data_ptr = get_broken_op_side(fe_rhs->getOpPtrVector());
3859
3860 fe_rhs->getOpPtrVector().push_back(
3861 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
3862 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
3863 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3864 timeScaleMap));
3865 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
3866 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
3867
3868 auto piola_scale_ptr = boost::make_shared<double>(1.0);
3869 fe_rhs->getOpPtrVector().push_back(
3870 new OpBrokenTractionBc(hybridSpatialDisp, bcSpatialTractionVecPtr,
3871 piola_scale_ptr, timeScaleMap));
3872 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3873 // if you push gradient of L2 base to physical element, it will not work.
3874 fe_rhs->getOpPtrVector().push_back(
3876 hybridSpatialDisp, hybrid_grad_ptr));
3877 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
3878 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
3879 hybrid_grad_ptr, timeScaleMap));
3880 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
3881 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
3882 timeScaleMap));
3883
3884 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3885 fe_rhs->getOpPtrVector().push_back(
3886 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3887 hybrid_ptr));
3888 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
3889 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
3890 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3891
3892 auto get_normal_disp_bc_faces = [&]() {
3893 auto faces =
3894 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3895 return boost::make_shared<Range>(faces);
3896 };
3897
3898 using BoundaryEle =
3900 using BdyEleOp = BoundaryEle::UserDataOperator;
3902 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3903 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
3904 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3905 get_normal_disp_bc_faces()));
3906
3908 };
3909
3910 auto set_lhs = [&]() {
3912
3913 auto broken_data_ptr = get_broken_op_side(fe_lhs->getOpPtrVector());
3914
3915 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
3916 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3917 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
3918 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
3919 timeScaleMap));
3920
3921 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3922 // if you push gradient of L2 base to physical element, it will not work.
3923 fe_lhs->getOpPtrVector().push_back(
3925 hybridSpatialDisp, hybrid_grad_ptr));
3926 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
3927 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
3928 timeScaleMap));
3929
3930 auto get_normal_disp_bc_faces = [&]() {
3931 auto faces =
3932 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3933 return boost::make_shared<Range>(faces);
3934 };
3935
3936 using BoundaryEle =
3938 using BdyEleOp = BoundaryEle::UserDataOperator;
3940 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3941 fe_lhs->getOpPtrVector().push_back(new OpC(
3942 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3943 true, true, get_normal_disp_bc_faces()));
3944
3946 };
3947
3948 CHKERR set_rhs();
3949 CHKERR set_lhs();
3950 }
3951
3953}
3954
3956 const bool add_elastic, const bool add_material,
3957 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3958 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3961}
3962
3964
3965 boost::shared_ptr<ForcesAndSourcesCore> &fe_contact_tree
3966
3967) {
3969 fe_contact_tree = createContactDetectionFiniteElement(*this);
3971}
3972
3975
3976 // Add contact operators. Note that only for rhs. THe lhs is assembled with
3977 // volume element, to enable schur complement evaluation.
3978 CHKERR setContactElementRhsOps(contactTreeRhs);
3979
3980 CHKERR setVolumeElementOps(tag, true, false, elasticFeRhs, elasticFeLhs);
3981 CHKERR setFaceElementOps(true, false, elasticBcRhs, elasticBcLhs);
3982
3983 auto adj_cache =
3984 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3985
3986 auto get_op_contact_bc = [&]() {
3988 auto op_loop_side = new OpLoopSide<SideEle>(
3989 mField, contactElement, SPACE_DIM - 1, Sev::noisy, adj_cache);
3990 return op_loop_side;
3991 };
3992
3994}
3995
3998 boost::shared_ptr<FEMethod> null;
3999
4000 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4001
4002 CHKERR DMMoFEMTSSetI2Function(dm, elementVolumeName, elasticFeRhs, null,
4003 null);
4004 CHKERR DMMoFEMTSSetI2Function(dm, naturalBcElement, elasticBcRhs, null,
4005 null);
4006 CHKERR DMMoFEMTSSetI2Jacobian(dm, elementVolumeName, elasticFeLhs, null,
4007 null);
4008 CHKERR DMMoFEMTSSetI2Jacobian(dm, naturalBcElement, elasticBcLhs, null,
4009 null);
4010
4011 } else {
4012 CHKERR DMMoFEMTSSetIFunction(dm, elementVolumeName, elasticFeRhs, null,
4013 null);
4014 CHKERR DMMoFEMTSSetIFunction(dm, naturalBcElement, elasticBcRhs, null,
4015 null);
4016 CHKERR DMMoFEMTSSetIJacobian(dm, elementVolumeName, elasticFeLhs, null,
4017 null);
4018 CHKERR DMMoFEMTSSetIJacobian(dm, naturalBcElement, elasticBcLhs, null,
4019 null);
4020 }
4021
4023}
4024
4028#include "impl/SetUpSchurImpl.cpp"
4029
4031
4032 inline static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x,
4033 bool set_ts_monitor) {
4034
4035#ifdef ENABLE_PYTHON_BINDING
4036 auto setup_sdf = [&]() { return setupContactSdf(); };
4037#endif
4038
4039 auto setup_ts_monitor = [&]() {
4040 boost::shared_ptr<TsCtx> ts_ctx;
4042 "get TS ctx");
4043 if (set_ts_monitor) {
4045 TSMonitorSet(ts, TsMonitorSet, ts_ctx.get(), PETSC_NULLPTR),
4046 "TS monitor set");
4047 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
4048 auto testing_monitor_ptr =
4049 boost::make_shared<EshelbianTestingMonitor>(*ep_ptr, monitor_ptr);
4050 ts_ctx->getLoopsMonitor().push_back(
4051 TsCtx::PairNameFEMethodPtr(ep_ptr->elementVolumeName, monitor_ptr));
4052
4053 PetscBool test_cook_flg = PETSC_FALSE;
4054 PetscBool test_cook_pts_flg = PETSC_FALSE;
4055 PetscInt atom_test = 0;
4056 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook",
4057 &test_cook_flg, PETSC_NULLPTR);
4058 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook_pts",
4059 &test_cook_pts_flg, PETSC_NULLPTR);
4060 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
4061 PETSC_NULLPTR);
4062 if (atom_test || test_cook_flg || test_cook_pts_flg) {
4064 ep_ptr->elementVolumeName, testing_monitor_ptr));
4065 }
4066 }
4067 MOFEM_LOG("EP", Sev::inform) << "TS monitor setup";
4068 return std::make_tuple(ts_ctx);
4069 };
4070
4071 auto setup_snes_monitor = [&]() {
4073 SNES snes;
4074 CHKERR TSGetSNES(ts, &snes);
4075 auto snes_ctx = getDMSnesCtx(ep_ptr->dmElastic);
4076 CHKERR SNESMonitorSet(snes,
4077 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
4078 void *))MoFEMSNESMonitorEnergy,
4079 (void *)(snes_ctx.get()), PETSC_NULLPTR);
4080 MOFEM_LOG("EP", Sev::inform) << "SNES monitor setup";
4082 };
4083
4084 auto setup_snes_conergence_test = [&]() {
4086
4087 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
4088 PetscReal snorm, PetscReal fnorm,
4089 SNESConvergedReason *reason, void *cctx) {
4091 // EshelbianCore *ep_ptr = (EshelbianCore *)cctx;
4092 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
4093 PETSC_NULLPTR);
4094
4095 Vec x_update, r;
4096 CHKERR SNESGetSolutionUpdate(snes, &x_update);
4097 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
4098
4100 };
4101
4102 // SNES snes;
4103 // CHKERR TSGetSNES(ts, &snes);
4104 // CHKERR SNESSetConvergenceTest(snes, snes_convergence_test, ep_ptr,
4105 // PETSC_NULLPTR);
4106 // MOFEM_LOG("EP", Sev::inform) << "SNES convergence test setup";
4108 };
4109
4110 auto setup_section = [&]() {
4111 PetscSection section_raw;
4112 CHK_THROW_MESSAGE(DMGetSection(ep_ptr->dmElastic, &section_raw),
4113 "get DM section");
4114 int num_fields;
4115 CHK_THROW_MESSAGE(PetscSectionGetNumFields(section_raw, &num_fields),
4116 "get num fields");
4117 for (int ff = 0; ff != num_fields; ff++) {
4118 const char *field_name;
4120 PetscSectionGetFieldName(section_raw, ff, &field_name),
4121 "get field name");
4122 MOFEM_LOG_C("EP", Sev::inform, "Field %d name %s", ff, field_name);
4123 }
4124 return SmartPetscObj<PetscSection>(section_raw, true);
4125 };
4126
4127 auto set_vector_on_mesh = [&]() {
4129 CHKERR DMoFEMMeshToLocalVector(ep_ptr->dmElastic, x, INSERT_VALUES,
4130 SCATTER_FORWARD);
4131 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4132 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4133 MOFEM_LOG("EP", Sev::inform) << "Vector set on mesh";
4135 };
4136
4137 auto setup_schur_block_solver = [&]() {
4138 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver";
4139 CHK_THROW_MESSAGE(TSAppendOptionsPrefix(ts, "elastic_"),
4140 "append options prefix");
4141 CHK_THROW_MESSAGE(TSSetFromOptions(ts), "set from options");
4142 CHK_THROW_MESSAGE(TSSetDM(ts, ep_ptr->dmElastic), "set DM");
4143 // Adding field split solver
4144 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
4145 if constexpr (A == AssemblyType::BLOCK_MAT) {
4146 schur_ptr =
4148 CHK_THROW_MESSAGE(schur_ptr->setUp(ts), "setup schur");
4149 }
4150 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver done";
4151 return schur_ptr;
4152 };
4153
4154 // Warning: sequence of construction is not guaranteed for tuple. You have
4155 // to enforce order by proper packaging.
4156
4157#ifdef ENABLE_PYTHON_BINDING
4158 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
4159 setup_snes_monitor(), setup_snes_conergence_test(),
4160 setup_section(), set_vector_on_mesh(),
4161 setup_schur_block_solver());
4162#else
4163 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
4164 setup_snes_conergence_test(), setup_section(),
4165 set_vector_on_mesh(), setup_schur_block_solver());
4166#endif
4167 }
4168};
4169
4172
4173 PetscBool debug_model = PETSC_FALSE;
4174 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
4175 PETSC_NULLPTR);
4176 MOFEM_LOG("EP", Sev::inform)
4177 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
4178
4179 if (debug_model == PETSC_TRUE) {
4180 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4181 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
4182 void *ctx) {
4184
4185 SNES snes;
4186 CHKERR TSGetSNES(ts, &snes);
4187 int it;
4188 CHKERR SNESGetIterationNumber(snes, &it);
4189 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
4190 CHKERR postProcessResults(1, file_name, F, u_t);
4191 std::string file_skel_name =
4192 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
4193
4194 auto get_material_force_tag = [&]() {
4195 auto &moab = mField.get_moab();
4196 Tag tag;
4197 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
4198 "can't get tag");
4199 return tag;
4200 };
4201
4202 CHKERR calculateFaceMaterialForce(1, ts);
4203 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
4204 {get_material_force_tag()});
4205
4207 };
4208 ts_ctx_ptr->tsDebugHook = post_proc;
4209 }
4210
4212}
4213
4216
4217 CHKERR addDebugModel(ts);
4218
4219 auto storage = solve_elastic_setup::setup(this, ts, x, true);
4220
4221 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4222 Vec xx;
4223 CHKERR VecDuplicate(x, &xx);
4224 CHKERR VecZeroEntries(xx);
4225 CHKERR TS2SetSolution(ts, x, xx);
4226 CHKERR VecDestroy(&xx);
4227 } else {
4228 CHKERR TSSetSolution(ts, x);
4229 }
4230
4231 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4232 {elasticFeLhs.get(), elasticFeRhs.get()});
4233 CHKERR TSSetUp(ts);
4234 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4235 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4237 CHKERR TSSolve(ts, PETSC_NULLPTR);
4239 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4240 {elasticFeLhs.get(), elasticFeRhs.get()});
4241
4242#ifndef NDEBUG
4243 // Make graph
4244 if (mField.get_comm_rank() == 0) {
4245 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4247 "solve_elastic_graph.dot");
4248 }
4249#endif
4250
4251 SNES snes;
4252 CHKERR TSGetSNES(ts, &snes);
4253 int lin_solver_iterations;
4254 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
4255 MOFEM_LOG("EP", Sev::inform)
4256 << "Number of linear solver iterations " << lin_solver_iterations;
4257
4258 PetscBool test_cook_flg = PETSC_FALSE;
4259 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
4260 PETSC_NULLPTR);
4261 if (test_cook_flg) {
4262 constexpr int expected_lin_solver_iterations = 11;
4263 if (lin_solver_iterations > expected_lin_solver_iterations)
4264 SETERRQ(
4265 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4266 "Expected number of iterations is different than expected %d > %d",
4267 lin_solver_iterations, expected_lin_solver_iterations);
4268 }
4269
4270 PetscBool test_sslv116_flag = PETSC_FALSE;
4271 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
4272 &test_sslv116_flag, PETSC_NULLPTR);
4273
4274 if (test_sslv116_flag) {
4275 double max_val = 0.0;
4276 double min_val = 0.0;
4277 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
4279 auto ent_type = ent_ptr->getEntType();
4280 if (ent_type == MBVERTEX) {
4281 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
4282 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
4283 }
4285 };
4286 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
4287 field_min_max, spatialH1Disp);
4288
4289 double global_max_val = 0.0;
4290 double global_min_val = 0.0;
4291 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
4292 mField.get_comm());
4293 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
4294 mField.get_comm());
4295 MOFEM_LOG("EP", Sev::inform)
4296 << "Max " << spatialH1Disp << " value: " << global_max_val;
4297 MOFEM_LOG("EP", Sev::inform)
4298 << "Min " << spatialH1Disp << " value: " << global_min_val;
4299
4300 double ref_max_val = 0.00767;
4301 double ref_min_val = -0.00329;
4302 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
4303 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4304 "Incorrect max value of the displacement field: %f != %f",
4305 global_max_val, ref_max_val);
4306 }
4307 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
4308 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4309 "Incorrect min value of the displacement field: %f != %f",
4310 global_min_val, ref_min_val);
4311 }
4312 }
4313
4314 CHKERR gettingNorms();
4315
4317}
4318
4320 int start_step,
4321 double start_time) {
4323
4324 auto storage = solve_elastic_setup::setup(this, ts, x, false);
4325
4326 // Deprecated options
4327 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
4328
4329 CHKERR PetscOptionsScalar("-dynamic_final_time",
4330 "dynamic relaxation final time", "",
4331 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
4332 CHKERR PetscOptionsScalar("-dynamic_delta_time",
4333 "dynamic relaxation final time", "", physicalDt,
4334 &physicalDt, PETSC_NULLPTR);
4335 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
4336 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
4337 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
4338 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
4339
4340 PetscOptionsEnd();
4341
4342 MOFEM_LOG("EP", Sev::warning)
4343 << "Following options are deprecated, use -physical prefix options "
4344 "instead";
4345 MOFEM_LOG("EP", Sev::inform)
4346 << "Dynamic relaxation final time -dynamic_final_time = "
4347 << finalPhysicalTime;
4348 MOFEM_LOG("EP", Sev::inform)
4349 << "Dynamic relaxation delta time -dynamic_delta_time = "
4350 << physicalDt;
4351 MOFEM_LOG("EP", Sev::inform)
4352 << "Dynamic relaxation max iterations -dynamic_max_it = " << physicalMaxSteps;
4353 MOFEM_LOG("EP", Sev::inform)
4354 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
4355 << (physicalH1Update ? "TRUE" : "FALSE");
4356
4357 CHKERR addDebugModel(ts);
4358
4359 auto setup_ts_monitor = [&]() {
4360 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
4361 return monitor_ptr;
4362 };
4363 auto monitor_ptr = setup_ts_monitor();
4364
4365 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4366 {elasticFeLhs.get(), elasticFeRhs.get()});
4367 CHKERR TSSetUp(ts);
4369
4370 double ts_delta_time;
4371 CHKERR TSGetTimeStep(ts, &ts_delta_time);
4372
4373 if (physicalH1Update) {
4374 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4375 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4376 }
4377
4380
4381 currentPhysicalTime = start_time;
4382 physicalStepNumber = start_step;
4383 monitor_ptr->ts = PETSC_NULLPTR;
4384 monitor_ptr->ts_u = PETSC_NULLPTR;
4385 monitor_ptr->ts_t = currentPhysicalTime;
4386 monitor_ptr->ts_step = physicalStepNumber;
4387 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4388
4389 if (physicalDt <= 0.) {
4390 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY,
4391 "physicalDt must be positive, got %g", physicalDt);
4392 }
4393 for (; currentPhysicalTime < finalPhysicalTime;) {
4394 MOFEM_LOG("EP", Sev::inform)
4395 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
4396 << " delta time " << physicalDt;
4397
4398 CHKERR TSSetStepNumber(ts, 0);
4399 CHKERR TSSetTime(ts, 0);
4400 CHKERR TSSetTimeStep(ts, ts_delta_time);
4401 if (!physicalH1Update) {
4403 }
4404 CHKERR TSSetSolution(ts, x);
4405 CHKERR TSSolve(ts, PETSC_NULLPTR);
4406 if (!physicalH1Update) {
4408 }
4409
4410 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
4411 SCATTER_FORWARD);
4412 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4413 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4414
4415 monitor_ptr->ts = PETSC_NULLPTR;
4416 monitor_ptr->ts_u = x;
4417 monitor_ptr->ts_t = currentPhysicalTime;
4418 monitor_ptr->ts_step = physicalStepNumber;
4419 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4420
4421 ++physicalStepNumber;
4422 if (physicalStepNumber > physicalMaxSteps)
4423 break;
4424
4425 const double remainingPhysicalTime =
4426 finalPhysicalTime - currentPhysicalTime;
4427 if (physicalDt >= remainingPhysicalTime) {
4428 currentPhysicalTime = finalPhysicalTime;
4429 } else {
4430 currentPhysicalTime += physicalDt;
4431 }
4432 }
4433
4435 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4436 {elasticFeLhs.get(), elasticFeRhs.get()});
4437
4439}
4440
4443
4444 auto set_block = [&](auto name, int dim) {
4445 std::map<int, Range> map;
4446 auto set_tag_impl = [&](auto name) {
4448 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4449 auto bcs = mesh_mng->getCubitMeshsetPtr(
4450
4451 std::regex((boost::format("%s(.*)") % name).str())
4452
4453 );
4454 for (auto bc : bcs) {
4455 Range r;
4456 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4457 true);
4458 map[bc->getMeshsetId()] = r;
4459 MOFEM_LOG("EP", Sev::inform)
4460 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4461 << r.size() << " entities";
4462 }
4464 };
4465
4466 CHKERR set_tag_impl(name);
4467
4468 return std::make_pair(name, map);
4469 };
4470
4471 auto set_skin = [&](auto &&map) {
4472 for (auto &m : map.second) {
4473 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4474 m.second.swap(s);
4475 MOFEM_LOG("EP", Sev::inform)
4476 << "Skin for block " << map.first << " id " << m.first << " has "
4477 << m.second.size() << " entities";
4478 }
4479 return map;
4480 };
4481
4482 auto set_tag = [&](auto &&map) {
4483 Tag th;
4484 auto name = map.first;
4485 int def_val[] = {-1};
4487 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4488 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4489 "create tag");
4490 for (auto &m : map.second) {
4491 int id = m.first;
4492 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4493 "clear tag");
4494 }
4495 return th;
4496 };
4497
4498 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4499 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4500 listTagsToTransfer.push_back(
4501 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4502 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4503
4505}
4506
4508EshelbianCore::postProcessRestartMesh(const int tag, const std::string file,
4509 std::vector<Tag> tags_to_transfer) {
4511 ParallelComm *pcomm =
4512 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
4513 // write file with only crack surfaces and full mesh
4514 if (crackingOn && !pcomm->rank()) {
4515 auto meshsets_mng = mField.getInterface<MeshsetsManager>();
4516
4517 std::vector<boost::shared_ptr<TempMeshset>> meshsets_tmp_list;
4518 auto &list = meshsets_mng->getMeshsetsMultindex();
4519 std::vector<Tag> tags_list;
4520
4521 auto meshset_ptr = get_temp_meshset_ptr(mField.get_moab());
4522
4523 for (auto &m : list) {
4524 meshsets_tmp_list.push_back(get_temp_meshset_ptr(mField.get_moab()));
4525 EntityHandle new_meshset = *meshsets_tmp_list.back();
4526 auto meshset = m.getMeshset();
4527 std::vector<Tag> tmp_tags_list;
4528 CHKERR mField.get_moab().tag_get_tags_on_entity(meshset, tmp_tags_list);
4529 Range ents;
4530 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
4531 CHKERR mField.get_moab().add_entities(new_meshset, ents);
4532 for (auto t : tmp_tags_list) {
4533 void *tag_vals[1];
4534 int tag_size[1];
4535 CHKERR mField.get_moab().tag_get_by_ptr(
4536 t, &meshset, 1, (const void **)tag_vals, tag_size);
4537 CHKERR mField.get_moab().tag_set_by_ptr(t, &new_meshset, 1, tag_vals,
4538 tag_size);
4539 }
4540 std::vector<std::string> remove_tags;
4541 remove_tags.push_back("AKDTree_coord_norm");
4542 remove_tags.push_back("__PARALLEL_");
4543 remove_tags.push_back("_RefBitLevel");
4544
4545 for (auto t : tmp_tags_list) {
4546 std::string tag_name;
4547 CHKERR mField.get_moab().tag_get_name(t, tag_name);
4548 bool add = true;
4549
4550 for (auto &p : remove_tags) {
4551 if (tag_name.compare(0, p.size(), p) == 0) {
4552 add = false;
4553 break;
4554 }
4555 }
4556
4557 if (add)
4558 tags_list.push_back(t);
4559 }
4560 }
4561
4562 for (auto &m_ptr : meshsets_tmp_list) {
4563 EntityHandle m = *m_ptr;
4564 CHKERR mField.get_moab().add_entities(*meshset_ptr, &m, 1);
4565 }
4566
4567 // meshsets_tmp_list has all meshsets to write
4568 std::sort(tags_list.begin(), tags_list.end());
4569 auto new_end = std::unique(tags_list.begin(), tags_list.end());
4570 tags_list.resize(std::distance(tags_list.begin(), new_end));
4571
4572 EntityHandle save_meshset = *meshset_ptr;
4573 CHKERR mField.get_moab().write_file(file.c_str(), "MOAB", "", &save_meshset,
4574 1, &tags_list[0], tags_list.size());
4575 }
4577}
4578
4580EshelbianCore::postProcessResults(const int tag, const std::string file,
4581 Vec f_residual, Vec var_vector, Vec gradient,
4582 std::vector<Tag> tags_to_transfer, TS ts) {
4584
4585 SmartPetscObj<Vec> f_r, v_v;
4586 if (f_residual != PETSC_NULLPTR || var_vector != PETSC_NULLPTR) {
4588 SmartPetscObj<Vec> xout;
4589 xout = createDMVector(dM);
4590 auto xin = f_residual != PETSC_NULLPTR ? f_residual : var_vector;
4591 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4592 xin, "ELASTIC_PROBLEM", RowColData::ROW, xout, "ESHELBY_PLASTICITY",
4593 RowColData::ROW, scatter);
4594 if (f_residual) {
4595 f_r = vectorDuplicate(xout);
4596 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
4597 SCATTER_FORWARD);
4598 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
4599 SCATTER_FORWARD);
4600 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
4601 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
4602 }
4603 if (var_vector) {
4604 v_v = createDMVector(dM);
4605 CHKERR VecScatterBegin(scatter, var_vector, v_v, INSERT_VALUES,
4606 SCATTER_FORWARD);
4607 CHKERR VecScatterEnd(scatter, var_vector, v_v, INSERT_VALUES,
4608 SCATTER_FORWARD);
4609 CHKERR VecGhostUpdateBegin(v_v, INSERT_VALUES, SCATTER_FORWARD);
4610 CHKERR VecGhostUpdateEnd(v_v, INSERT_VALUES, SCATTER_FORWARD);
4611 }
4612 }
4613
4615 if (gradient) {
4617 g = createDMVector(dM);
4618 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4619 gradient, "MATERIAL_PROBLEM", RowColData::ROW, g, "ESHELBY_PLASTICITY",
4620 RowColData::ROW, scatter);
4621 CHKERR VecScatterBegin(scatter, gradient, g, INSERT_VALUES,
4622 SCATTER_FORWARD);
4623 CHKERR VecScatterEnd(scatter, gradient, g, INSERT_VALUES, SCATTER_FORWARD);
4624 CHKERR VecGhostUpdateBegin(g, INSERT_VALUES, SCATTER_FORWARD);
4625 CHKERR VecGhostUpdateEnd(g, INSERT_VALUES, SCATTER_FORWARD);
4626 }
4627
4628 // mark crack surface
4629 if (crackingOn) {
4630 auto get_tag = [&](auto name, auto dim) {
4631 auto &mob = mField.get_moab();
4632 Tag tag;
4633 double def_val[] = {0., 0., 0.};
4634 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4635 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4636 "create tag");
4637 return tag;
4638 };
4639 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4640 }
4641
4642 {
4643 auto get_crack_tag = [&]() {
4644 Tag th;
4645 rval = mField.get_moab().tag_get_handle("CRACK", th);
4646 if (rval == MB_SUCCESS) {
4647 MOAB_THROW(mField.get_moab().tag_delete(th));
4648 }
4649 int def_val[] = {0};
4650 MOAB_THROW(mField.get_moab().tag_get_handle(
4651 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4652 def_val));
4653 return th;
4654 };
4655
4656 Tag th = get_crack_tag();
4657 tags_to_transfer.push_back(th);
4658 int mark[] = {1};
4659 Range mark_faces;
4660 if (crackFaces)
4661 mark_faces.merge(*crackFaces);
4662 if (interfaceFaces)
4663 mark_faces.merge(*interfaceFaces);
4664 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4665 }
4666
4667 // add tags to transfer
4668 for (auto t : listTagsToTransfer) {
4669 std::string name;
4670 CHKERR mField.get_moab().tag_get_name(t, name);
4671 MOFEM_LOG("EP", Sev::verbose)
4672 << "Adding tag " << name << " to transfer list for post-processing";
4673 tags_to_transfer.push_back(t);
4674 }
4675
4676 if (!dataAtPts) {
4677 dataAtPts =
4678 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
4679 }
4680
4681 CHKERR DMoFEMLoopFiniteElements(dM, contactElement, contactTreeRhs);
4682
4683 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
4685 auto post_proc_ptr =
4686 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4687 mField, post_proc_mesh);
4688 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4689 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4690 frontAdjEdges);
4691
4692 if (ts != PETSC_NULLPTR) {
4693 post_proc_ptr->data_ctx |= PetscData::CTX_SET_TIME;
4694 CHKERR TSGetTime(ts, &(post_proc_ptr->ts_t));
4695 CHKERR TSGetTimeStep(ts, &(post_proc_ptr->ts_dt));
4696 }
4697
4698 auto domain_ops = [&](auto &fe, int sense) {
4700
4701 auto bubble_cache = boost::make_shared<CGGUserPolynomialBase::CachePhi>(
4702 0, 0, MatrixDouble());
4703 fe.getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
4704 new CGGUserPolynomialBase(bubble_cache));
4705 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4706 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
4707 frontAdjEdges);
4708 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4709 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4710 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
4711 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4712 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
4713 SmartPetscObj<Vec>(), MBMAXTYPE));
4714 if (stretchHandling == NO_STREACH) {
4715 fe.getOpPtrVector().push_back(
4716 physicalEquations->returnOpCalculateStretchFromStress(
4717 dataAtPts, physicalEquations));
4718 } else {
4719 fe.getOpPtrVector().push_back(
4721 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4722 }
4723 if (var_vector) {
4724 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4725 piolaStress, dataAtPts->getVarPiolaPts(),
4726 boost::make_shared<double>(1), v_v));
4727 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4728 bubbleField, dataAtPts->getVarPiolaPts(),
4729 boost::make_shared<double>(1), v_v, MBMAXTYPE));
4730 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4731 rotAxis, dataAtPts->getVarRotAxisPts(), v_v, MBTET));
4732 if (stretchHandling == NO_STREACH) {
4733 fe.getOpPtrVector().push_back(
4734 physicalEquations->returnOpCalculateVarStretchFromStress(
4735 dataAtPts, physicalEquations));
4736 } else {
4737 fe.getOpPtrVector().push_back(
4739 stretchTensor, dataAtPts->getVarLogStreachPts(), v_v, MBTET));
4740 }
4741 }
4742 if (gradient) {
4743 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4744 materialH1Positions, dataAtPts->getGradientAtPts(), g));
4745 }
4746
4747 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4748 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4749 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4750 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
4751
4752 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4753 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4754 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4755 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
4756 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
4757 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
4758 // evaluate derived quantities
4759 fe.getOpPtrVector().push_back(
4761
4762 // evaluate integration points
4763 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
4764 true, false, dataAtPts, physicalEquations));
4765 if (auto op =
4766 physicalEquations->returnOpCalculateEnergy(dataAtPts, nullptr)) {
4767 fe.getOpPtrVector().push_back(op);
4768 fe.getOpPtrVector().push_back(new OpCalculateEshelbyStress(dataAtPts));
4769 }
4770
4771 // // post-proc
4775
4776 struct OpSidePPMap : public OpPPMap {
4777 OpSidePPMap(moab::Interface &post_proc_mesh,
4778 std::vector<EntityHandle> &map_gauss_pts,
4779 DataMapVec data_map_scalar, DataMapMat data_map_vec,
4780 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
4781 int sense)
4782 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
4783 data_map_vec, data_map_mat, data_symm_map_mat),
4784 tagSense(sense) {}
4785
4786 MoFEMErrorCode doWork(int side, EntityType type,
4789
4790 if (tagSense != 0) {
4791 if (tagSense != OpPPMap::getSkeletonSense())
4793 }
4794
4795 CHKERR OpPPMap::doWork(side, type, data);
4797 }
4798
4799 private:
4800 int tagSense;
4801 };
4802
4803 OpPPMap::DataMapMat vec_fields;
4804 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
4805 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
4806 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
4807 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
4808 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
4809 if (stretchHandling != NO_STREACH) {
4810 vec_fields["EiegnLogStreach"] = dataAtPts->getEigenVals();
4811 }
4812 if (var_vector) {
4813 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
4814 vec_fields["VarSpatialDisplacementL2"] =
4815 boost::make_shared<MatrixDouble>();
4816 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4817 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], v_v, MBTET));
4818 }
4819 if (f_residual) {
4820 vec_fields["ResSpatialDisplacementL2"] =
4821 boost::make_shared<MatrixDouble>();
4822 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4823 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], f_r, MBTET));
4824 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
4825 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4826 rotAxis, vec_fields["ResOmega"], f_r, MBTET));
4827 }
4828 if (gradient) {
4829 vec_fields["Gradient"] = dataAtPts->getGradientAtPts();
4830 }
4831
4832 OpPPMap::DataMapMat mat_fields;
4833 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
4834 if (var_vector) {
4835 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
4836 }
4837 if (f_residual) {
4838 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
4839 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4840 piolaStress, mat_fields["ResPiolaStress"],
4841 boost::make_shared<double>(1), f_r));
4842 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4843 bubbleField, mat_fields["ResPiolaStress"],
4844 boost::make_shared<double>(1), f_r, MBMAXTYPE));
4845 }
4846 if (!internalStressTagName.empty()) {
4847 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
4848 switch (meshTransferInterpOrder) {
4849 case 0:
4850 fe.getOpPtrVector().push_back(
4851 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
4852 break;
4853 case 1:
4854 fe.getOpPtrVector().push_back(
4855 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
4856 break;
4857 default:
4858 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4859 "Unsupported mesh transfer interpolation order %d, for "
4860 "internal stress",
4861 meshTransferInterpOrder);
4862 }
4863 }
4864
4865 OpPPMap::DataMapMat mat_fields_symm;
4866 mat_fields_symm["LogSpatialStretch"] =
4867 dataAtPts->getLogStretchTensorAtPts();
4868 mat_fields_symm["SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
4869 if (var_vector) {
4870 mat_fields_symm["VarLogSpatialStretch"] =
4871 dataAtPts->getVarLogStreachPts();
4872 }
4873 if (f_residual) {
4874 if (stretchHandling != NO_STREACH) {
4875 mat_fields_symm["ResLogSpatialStretch"] =
4876 boost::make_shared<MatrixDouble>();
4877 fe.getOpPtrVector().push_back(
4879 stretchTensor, mat_fields_symm["ResLogSpatialStretch"], f_r,
4880 MBTET));
4881 }
4882 }
4883
4884 fe.getOpPtrVector().push_back(
4885
4886 new OpSidePPMap(
4887
4888 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4889
4890 {},
4891
4892 vec_fields,
4893
4894 mat_fields,
4895
4896 mat_fields_symm,
4897
4898 sense
4899
4900 )
4901
4902 );
4903
4904 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
4905 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4906 dataAtPts, sense));
4907
4909 };
4910
4911 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
4912 // H1 material positions
4913 post_proc_ptr->getOpPtrVector().push_back(
4914 new OpCalculateVectorFieldValues<3>(materialH1Positions,
4915 dataAtPts->getLargeXH1AtPts()));
4916
4917 // domain
4919 mField, elementVolumeName, SPACE_DIM);
4920 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
4921 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
4922
4923 return post_proc_ptr;
4924 };
4925
4926 // contact
4927 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
4928 auto &pip) {
4930 // evaluate traction
4931 using EleOnSide =
4933 using SideEleOp = EleOnSide::UserDataOperator;
4934 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4935 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4936 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4937 boost::shared_ptr<BaseFunction>(
4938 new CGGUserPolynomialBase(nullptr, true));
4939 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4940 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4941 materialH1Positions, frontAdjEdges);
4942 auto traction_ptr = boost::make_shared<MatrixDouble>();
4943 op_loop_domain_side->getOpPtrVector().push_back(
4945 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
4946
4947 pip.push_back(new OpCalculateVectorFieldValues<3>(
4948 contactDisp, dataAtPts->getContactL2AtPts()));
4949 pip.push_back(op_loop_domain_side);
4950 // evaluate contact displacement and contact conditions
4951 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4952 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
4953 pip.push_back(getOpContactDetection(
4954 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
4955 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
4956 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4957
4959 using BoundaryEle =
4961 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
4962 pip.push_back(op_this);
4963
4964 op_this->getOpPtrVector().push_back(
4965
4966 new OpPPMap(
4967
4968 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4969
4970 {},
4971
4972 {{"ContactDisplacement", dataAtPts->getContactL2AtPts()}},
4973
4974 {},
4975
4976 {}
4977
4978 )
4979
4980 );
4981
4982 if (f_residual) {
4983
4984 auto contact_residual = boost::make_shared<MatrixDouble>();
4985 op_this->getOpPtrVector().push_back(
4987 contactDisp, contact_residual, f_r, MBTET));
4988 op_this->getOpPtrVector().push_back(
4989
4990 new OpPPMap(
4991
4992 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4993
4994 {},
4995
4996 {{"res_contact", contact_residual}},
4997
4998 {},
4999
5000 {}
5001
5002 )
5003
5004 );
5005 }
5006
5008 };
5009
5010 auto post_proc_mesh = boost::make_shared<moab::Core>();
5011 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5012 auto post_proc_negative_sense_ptr =
5013 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
5014 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5015 CHKERR calcs_side_traction_and_displacements(
5016 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
5017
5018 auto own_tets =
5019 CommInterface::getPartEntities(mField.get_moab(), mField.get_comm_rank())
5020 .subset_by_dimension(SPACE_DIM);
5021 Range own_faces;
5022 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
5023 own_faces, moab::Interface::UNION);
5024
5025 auto get_crack_faces = [&](auto crack_faces) {
5026 auto get_adj = [&](auto e, auto dim) {
5027 Range adj;
5028 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
5029 moab::Interface::UNION);
5030 return adj;
5031 };
5032 // this removes faces
5033 auto tets = get_adj(crack_faces, 3);
5034 // faces adjacent to tets not in crack_faces
5035 auto faces = subtract(get_adj(tets, 2), crack_faces);
5036 // what is left from below, are tets fully inside crack_faces
5037 tets = subtract(tets, get_adj(faces, 3));
5038 return subtract(crack_faces, get_adj(tets, 2));
5039 };
5040
5041 auto side_one_faces = [&](auto &faces) {
5042 std::pair<Range, Range> sides;
5043 for (auto f : faces) {
5044 Range adj;
5045 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
5046 adj = intersect(own_tets, adj);
5047 for (auto t : adj) {
5048 int side, sense, offset;
5049 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
5050 if (sense == 1) {
5051 sides.first.insert(f);
5052 } else {
5053 sides.second.insert(f);
5054 }
5055 }
5056 }
5057 return sides;
5058 };
5059
5060 auto get_interface_from_block = [&](auto block_name) {
5061 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
5062 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
5063 Range faces;
5064 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
5065 faces, moab::Interface::UNION);
5066 faces = subtract(faces, skin);
5067 return faces;
5068 };
5069
5070 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
5071 // VOLUME_INTERFACE faces were already merged into interfaceFaces in
5072 // projectGeometry(), after applying REMOVE_INTERFACE exclusions.
5073 auto crack_side_faces = side_one_faces(crack_faces);
5074 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5075 auto ent = fe_method_ptr->getFEEntityHandle();
5076 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
5077 return false;
5078 }
5079 return true;
5080 };
5081 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5082 auto ent = fe_method_ptr->getFEEntityHandle();
5083 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
5084 return false;
5085 }
5086 return true;
5087 };
5088
5089 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5090 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5091 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
5092
5093 auto post_proc_begin =
5094 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5095 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5096 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
5097 post_proc_ptr->exeTestHook = side_one_crack_faces;
5099 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5100 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
5101 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5102 post_proc_negative_sense_ptr, 0,
5103 mField.get_comm_size());
5104
5105 constexpr bool debug = false;
5106 if (debug) {
5107
5108 auto get_adj_front = [&]() {
5109 auto skeleton_faces = *skeletonFaces;
5110 Range adj_front;
5111 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
5112 moab::Interface::UNION);
5113
5114 adj_front = intersect(adj_front, skeleton_faces);
5115 adj_front = subtract(adj_front, *crackFaces);
5116 adj_front = intersect(own_faces, adj_front);
5117 return adj_front;
5118 };
5119
5120 auto adj_front = filter_owners(mField, get_adj_front());
5121 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
5122 auto ent = fe_method_ptr->getFEEntityHandle();
5123 if (adj_front.find(ent) == adj_front.end()) {
5124 return false;
5125 }
5126 return true;
5127 };
5128
5129 post_proc_ptr->exeTestHook = only_front_faces;
5131 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5132 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
5133 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5134 post_proc_negative_sense_ptr, 0,
5135 mField.get_comm_size());
5136 }
5137 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5138 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5139
5140 CHKERR post_proc_end.writeFile(file.c_str());
5142}
5143
5145EshelbianCore::postProcessSkeletonResults(const int tag, const std::string file,
5146 Vec f_residual,
5147 std::vector<Tag> tags_to_transfer) {
5149
5151 if (f_residual != PETSC_NULLPTR) {
5153 f_r = createDMVector(dM);
5154 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
5155 f_residual, "ELASTIC_PROBLEM", RowColData::ROW, f_r,
5156 "ESHELBY_PLASTICITY", RowColData::ROW, scatter);
5157 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
5158 SCATTER_FORWARD);
5159 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
5160 SCATTER_FORWARD);
5161 }
5162
5164
5165 auto post_proc_mesh = boost::make_shared<moab::Core>();
5166 auto post_proc_ptr =
5167 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5168 mField, post_proc_mesh);
5169 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
5170 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5172
5173 auto hybrid_disp = boost::make_shared<MatrixDouble>();
5174 post_proc_ptr->getOpPtrVector().push_back(
5176 post_proc_ptr->getOpPtrVector().push_back(
5178 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
5179
5180 auto op_loop_domain_side =
5182 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5183 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
5184
5185 // evaluated in side domain, that is op_loop_domain_side
5186 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5187 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
5188 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5189 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5191 op_loop_domain_side->getOpPtrVector().push_back(
5193 piolaStress, dataAtPts->getApproxPAtPts()));
5194 op_loop_domain_side->getOpPtrVector().push_back(
5196 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
5197 op_loop_domain_side->getOpPtrVector().push_back(
5199 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
5200
5201 if (stretchHandling == NO_STREACH) {
5202 op_loop_domain_side->getOpPtrVector().push_back(
5203 physicalEquations->returnOpCalculateStretchFromStress(
5205 } else {
5206 op_loop_domain_side->getOpPtrVector().push_back(
5208 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
5209 }
5210
5212
5213 OpPPMap::DataMapMat vec_fields;
5214 vec_fields["HybridDisplacement"] = hybrid_disp;
5215 // note that grad and omega have not trace, so this is only other side value
5216 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
5217 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5218 OpPPMap::DataMapMat mat_fields;
5219 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5220 mat_fields["HybridDisplacementGradient"] =
5221 dataAtPts->getGradHybridDispAtPts();
5222 OpPPMap::DataMapMat mat_fields_symm;
5223 mat_fields_symm["LogSpatialStretch"] = dataAtPts->getLogStretchTensorAtPts();
5224
5225 post_proc_ptr->getOpPtrVector().push_back(
5226
5227 new OpPPMap(
5228
5229 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5230
5231 {},
5232
5233 vec_fields,
5234
5235 mat_fields,
5236
5237 mat_fields_symm
5238
5239 )
5240
5241 );
5242
5243 if (f_residual) {
5244 auto hybrid_res = boost::make_shared<MatrixDouble>();
5245 post_proc_ptr->getOpPtrVector().push_back(
5247 f_r));
5249 post_proc_ptr->getOpPtrVector().push_back(
5250
5251 new OpPPMap(
5252
5253 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5254
5255 {},
5256
5257 {{"res_hybrid", hybrid_res}},
5258
5259 {},
5260
5261 {}
5262
5263 )
5264
5265 );
5266 }
5267
5268 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5269
5270 auto post_proc_begin =
5271 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5272 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5273 CHKERR DMoFEMLoopFiniteElements(dM, skeletonElement, post_proc_ptr);
5274 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5275 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5276
5277 CHKERR post_proc_end.writeFile(file.c_str());
5278
5280}
5281
5282//! [Getting norms]
5285
5286 auto post_proc_norm_fe =
5287 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
5288
5289 auto bubble_cache =
5290 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
5291 post_proc_norm_fe->getUserPolynomialBase() =
5292 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase(bubble_cache));
5293 post_proc_norm_fe->getRuleHook = [](int, int, int) { return -1; };
5294 post_proc_norm_fe->setRuleHook = SetIntegrationAtFrontVolume(
5295 frontVertices, frontAdjEdges, vol_rule, bubble_cache);
5296 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5297 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
5299
5300 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
5301 auto norms_vec =
5302 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
5303 CHKERR VecZeroEntries(norms_vec);
5304
5305 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
5306 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5307 post_proc_norm_fe->getOpPtrVector().push_back(
5309 post_proc_norm_fe->getOpPtrVector().push_back(
5311 post_proc_norm_fe->getOpPtrVector().push_back(
5312 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
5313 post_proc_norm_fe->getOpPtrVector().push_back(
5314 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
5315 post_proc_norm_fe->getOpPtrVector().push_back(
5316 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
5317 u_h1_ptr));
5318
5319 auto piola_ptr = boost::make_shared<MatrixDouble>();
5320 post_proc_norm_fe->getOpPtrVector().push_back(
5322 post_proc_norm_fe->getOpPtrVector().push_back(
5324 MBMAXTYPE));
5325
5326 post_proc_norm_fe->getOpPtrVector().push_back(
5327 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
5328
5329 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
5331 *post_proc_norm_fe);
5332 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
5333
5334 CHKERR VecAssemblyBegin(norms_vec);
5335 CHKERR VecAssemblyEnd(norms_vec);
5336 const double *norms;
5337 CHKERR VecGetArrayRead(norms_vec, &norms);
5338 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
5339 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
5340 MOFEM_LOG("EP", Sev::inform)
5341 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
5342 MOFEM_LOG("EP", Sev::inform)
5343 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
5344 CHKERR VecRestoreArrayRead(norms_vec, &norms);
5345
5347}
5348//! [Getting norms]
5349
5352
5353 auto bc_mng = mField.getInterface<BcManager>();
5355 "", piolaStress, false, false);
5356
5357 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
5358 for (auto bc : bc_mng->getBcMapByBlockName()) {
5359 if (auto disp_bc = bc.second->dispBcPtr) {
5360
5361 auto [field_name, block_name] =
5363 MOFEM_LOG("EP", Sev::inform)
5364 << "Field name: " << field_name << " Block name: " << block_name;
5365 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
5366
5367 std::vector<double> block_attributes(6, 0.);
5368 if (disp_bc->data.flag1 == 1) {
5369 block_attributes[0] = disp_bc->data.value1;
5370 block_attributes[3] = 1;
5371 }
5372 if (disp_bc->data.flag2 == 1) {
5373 block_attributes[1] = disp_bc->data.value2;
5374 block_attributes[4] = 1;
5375 }
5376 if (disp_bc->data.flag3 == 1) {
5377 block_attributes[2] = disp_bc->data.value3;
5378 block_attributes[5] = 1;
5379 }
5380 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5381 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces);
5382 }
5383 }
5384 // old way of naming blocksets for displacement BCs
5385 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
5386
5388 boost::make_shared<NormalDisplacementBcVec>();
5389 for (auto bc : bc_mng->getBcMapByBlockName()) {
5390 auto block_name = "(.*)NORMAL_DISPLACEMENT(.*)";
5391 std::regex reg_name(block_name);
5392 if (std::regex_match(bc.first, reg_name)) {
5393 auto [field_name, block_name] =
5395 MOFEM_LOG("EP", Sev::inform)
5396 << "Field name: " << field_name << " Block name: " << block_name;
5398 block_name, bc.second->bcAttributes,
5399 bc.second->bcEnts.subset_by_dimension(2));
5400 }
5401 }
5402
5404 boost::make_shared<AnalyticalDisplacementBcVec>();
5405
5406 for (auto bc : bc_mng->getBcMapByBlockName()) {
5407 auto block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
5408 std::regex reg_name(block_name);
5409 if (std::regex_match(bc.first, reg_name)) {
5410 auto [field_name, block_name] =
5412 MOFEM_LOG("EP", Sev::inform)
5413 << "Field name: " << field_name << " Block name: " << block_name;
5415 block_name, bc.second->bcAttributes,
5416 bc.second->bcEnts.subset_by_dimension(2));
5417 }
5418 }
5419
5420 auto ts_displacement =
5421 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
5422 for (auto &bc : *bcSpatialDispVecPtr) {
5423 MOFEM_LOG("EP", Sev::noisy)
5424 << "Add time scaling displacement BC: " << bc.blockName;
5425 timeScaleMap[bc.blockName] =
5427 ts_displacement, "disp_history", ".txt", bc.blockName);
5428 }
5429
5430 auto ts_normal_displacement =
5431 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
5432 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
5433 MOFEM_LOG("EP", Sev::noisy)
5434 << "Add time scaling normal displacement BC: " << bc.blockName;
5435 timeScaleMap[bc.blockName] =
5437 ts_normal_displacement, "normal_disp_history", ".txt",
5438 bc.blockName);
5439 }
5440
5442}
5443
5446
5447 auto bc_mng = mField.getInterface<BcManager>();
5449 false, false);
5450
5451 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
5452
5453 for (auto bc : bc_mng->getBcMapByBlockName()) {
5454 if (auto force_bc = bc.second->forceBcPtr) {
5455
5456 auto [field_name, block_name] =
5458 MOFEM_LOG("EP", Sev::inform)
5459 << "Field name: " << field_name << " Block name: " << block_name;
5460 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
5461
5462 std::vector<double> block_attributes(6, 0.);
5463 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
5464 block_attributes[3] = 1;
5465 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
5466 block_attributes[4] = 1;
5467 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
5468 block_attributes[5] = 1;
5469 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5470 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
5471 faces);
5472 }
5473 }
5474 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
5475
5476 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
5477 for (auto bc : bc_mng->getBcMapByBlockName()) {
5478 auto block_name = "(.*)PRESSURE(.*)";
5479 std::regex reg_name(block_name);
5480 if (std::regex_match(bc.first, reg_name)) {
5481
5482 auto [field_name, block_name] =
5484 MOFEM_LOG("EP", Sev::inform)
5485 << "Field name: " << field_name << " Block name: " << block_name;
5486 bcSpatialPressureVecPtr->emplace_back(
5487 block_name, bc.second->bcAttributes,
5488 bc.second->bcEnts.subset_by_dimension(2));
5489 }
5490 }
5491
5493 boost::make_shared<AnalyticalTractionBcVec>();
5494
5495 for (auto bc : bc_mng->getBcMapByBlockName()) {
5496 auto block_name = "(.*)ANALYTICAL_TRACTION(.*)";
5497 std::regex reg_name(block_name);
5498 if (std::regex_match(bc.first, reg_name)) {
5499 auto [field_name, block_name] =
5501 MOFEM_LOG("EP", Sev::inform)
5502 << "Field name: " << field_name << " Block name: " << block_name;
5504 block_name, bc.second->bcAttributes,
5505 bc.second->bcEnts.subset_by_dimension(2));
5506 }
5507 }
5508
5509 auto ts_traction =
5510 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
5511 for (auto &bc : *bcSpatialTractionVecPtr) {
5512 timeScaleMap[bc.blockName] =
5514 ts_traction, "traction_history", ".txt", bc.blockName);
5515 }
5516
5517 auto ts_pressure =
5518 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
5519 for (auto &bc : *bcSpatialPressureVecPtr) {
5520 timeScaleMap[bc.blockName] =
5522 ts_pressure, "pressure_history", ".txt", bc.blockName);
5523 }
5524
5526}
5527
5530
5531 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
5532 &ext_strain_vec_ptr,
5533 const std::string block_name,
5534 const int nb_attributes) {
5536 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5537 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
5538 std::vector<double> block_attributes;
5539 CHKERR it->getAttributes(block_attributes);
5540 if (block_attributes.size() < nb_attributes) {
5541 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5542 "In block %s expected %d attributes, but given %ld",
5543 it->getName().c_str(), nb_attributes, block_attributes.size());
5544 }
5545
5546 auto get_block_ents = [&]() {
5547 Range ents;
5548 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
5549 true);
5550 return ents;
5551 };
5552 auto Ents = get_block_ents();
5553 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
5554 get_block_ents());
5555 }
5557 };
5558
5559 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
5560
5561 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
5562
5563 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
5564 "externalstrain_history.txt");
5565 for (auto &ext_strain_block : *externalStrainVecPtr) {
5566 MOFEM_LOG("EP", Sev::noisy)
5567 << "Add time scaling external strain: " << ext_strain_block.blockName;
5568 timeScaleMap[ext_strain_block.blockName] =
5570 ts_pre_stretch, "externalstrain_history", ".txt",
5571 ext_strain_block.blockName);
5572 }
5573
5575}
5576
5579
5580 auto print_loc_size = [this](auto v, auto str, auto sev) {
5582 int size;
5583 CHKERR VecGetLocalSize(v.second, &size);
5584 int low, high;
5585 CHKERR VecGetOwnershipRange(v.second, &low, &high);
5586 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5587 << " " << high << " ) ";
5590 };
5591
5593 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5594 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5596 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5597 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5599 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5600 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5602 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5603 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5604
5606}
5607
5609 int start_step,
5610 double start_time) {
5612
5613 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5614
5615 auto cohesive_tao_ctx = createCohesiveTAOCtx(
5616 this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
5617 SmartPetscObj<TS>(ts, true));
5618
5619 // Deprecated options
5620 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5621
5622 CHKERR PetscOptionsScalar("-dynamic_final_time",
5623 "dynamic relaxation final time", "",
5624 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
5625 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5626 "dynamic relaxation final time", "", physicalDt,
5627 &physicalDt, PETSC_NULLPTR);
5628 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5629 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
5630 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5631 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
5632
5633 PetscOptionsEnd();
5634
5635 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
5636 MOFEM_LOG("EP", Sev::inform)
5637 << "Dynamic relaxation final time -dynamic_final_time = "
5639 MOFEM_LOG("EP", Sev::inform)
5640 << "Dynamic relaxation delta time -dynamic_delta_time = "
5641 << physicalDt;
5642 MOFEM_LOG("EP", Sev::inform)
5643 << "Dynamic relaxation max iterations -dynamic_max_it = " << physicalMaxSteps;
5644 MOFEM_LOG("EP", Sev::inform)
5645 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5646 << (physicalH1Update ? "TRUE" : "FALSE");
5647
5648 CHKERR initializeCohesiveKappaField(*this);
5650
5651 auto setup_ts_monitor = [&]() {
5652 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5653 return monitor_ptr;
5654 };
5655 auto monitor_ptr = setup_ts_monitor();
5656
5657 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5658 {elasticFeLhs.get(), elasticFeRhs.get()});
5659 CHKERR TSSetUp(ts);
5660 CHKERR TSElasticPostStep::postStepInitialise(this);
5661
5662 double ts_delta_time;
5663 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5664
5665 if (physicalH1Update) {
5666 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5667 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5668 }
5669
5670 auto tao = createTao(mField.get_comm());
5671 CHKERR TaoSetType(tao, TAOLMVM);
5672 auto g = cohesive_tao_ctx->duplicateGradientVec();
5674 cohesiveEvaluateObjectiveAndGradient,
5675 (void *)cohesive_tao_ctx.get());
5676
5677 currentPhysicalTime = start_time;
5678 physicalStepNumber = start_step;
5679 monitor_ptr->ts = PETSC_NULLPTR;
5680 monitor_ptr->ts_u = PETSC_NULLPTR;
5681 monitor_ptr->ts_t = currentPhysicalTime;
5682 monitor_ptr->ts_step = physicalStepNumber;
5684
5685 auto tao_sol0 = cohesive_tao_ctx->duplicateKappaVec();
5686 int tao_sol_size, tao_sol_loc_size;
5687 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
5688 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
5689 MOFEM_LOG("EP", Sev::inform)
5690 << "Cohesive crack growth initial kappa vector size " << tao_sol_size
5691 << " local size " << tao_sol_loc_size << " number of interface faces "
5692 << interfaceFaces->size();
5693
5694 CHKERR TaoSetFromOptions(tao);
5695
5696 auto xl = vectorDuplicate(tao_sol0);
5697 auto xu = vectorDuplicate(tao_sol0);
5698 CHKERR VecSet(xl, 0.0);
5699 CHKERR VecSet(xu, PETSC_INFINITY);
5700 CHKERR TaoSetVariableBounds(tao, xl, xu);
5701
5702 if (physicalDt <= 0.) {
5704 "physicalDt must be positive, got %g", physicalDt);
5705 }
5707 MOFEM_LOG("EP", Sev::inform)
5708 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
5709 << " delta time " << physicalDt;
5710
5711 CHKERR VecZeroEntries(tao_sol0);
5712 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5713 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5714 CHKERR TaoSetSolution(tao, tao_sol0);
5715
5716 if (!physicalH1Update && physicalStepNumber > start_step) {
5717 CHKERR TSElasticPostStep::preStepFun(ts);
5718 }
5719 CHKERR TaoSolve(tao);
5720
5721 Vec tao_sol;
5722 CHKERR TaoGetSolution(tao, &tao_sol);
5723
5724 // add solution increment to kappa vec/tags
5725 auto &kappa_vec = cohesive_tao_ctx->getKappaVec();
5727 get_kappa_tag(mField.get_moab()));
5728 CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
5729 CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
5730 SCATTER_FORWARD);
5731 CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
5733 get_kappa_tag(mField.get_moab()));
5734
5735 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5736 SCATTER_FORWARD);
5737 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5738 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5739 monitor_ptr->ts = PETSC_NULLPTR;
5740 monitor_ptr->ts_u = x;
5741 monitor_ptr->ts_t = currentPhysicalTime;
5742 monitor_ptr->ts_step = physicalStepNumber;
5744
5745 if (!physicalH1Update) {
5746 CHKERR TSElasticPostStep::postStepFun(ts);
5747 }
5748
5751 break;
5752
5753 const double remainingPhysicalTime =
5755 if (physicalDt >= remainingPhysicalTime) {
5757 } else {
5759 }
5760 }
5761
5762 CHKERR TSElasticPostStep::postStepDestroy();
5763 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5764 {elasticFeLhs.get(), elasticFeRhs.get()});
5765
5767}
5768
5770 double start_time) {
5772
5773 loadFactorTSSolveExecuted = PETSC_FALSE;
5774
5775 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5776
5778
5779 auto setup_ts_monitor = [&]() {
5780 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5781 return monitor_ptr;
5782 };
5783 auto monitor_ptr = setup_ts_monitor();
5784
5785 auto test_monitor_ptr =
5786 boost::make_shared<EshelbianTestingMonitor>(*this, monitor_ptr);
5787
5788 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5789 {elasticFeLhs.get(), elasticFeRhs.get()});
5790 CHKERR TSSetUp(ts);
5791 CHKERR TSElasticPostStep::postStepInitialise(this);
5792
5793 double ts_delta_time;
5794 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5795
5796 if (physicalH1Update) {
5797 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5798 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5799 }
5800
5801 CHKERR TSElasticPostStep::preStepFun(ts);
5802 CHKERR TSElasticPostStep::postStepFun(ts);
5803
5804 double load_factor_change_clip = 0.1;
5805
5806 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Load Factor Options", "none");
5807
5808 CHKERR PetscOptionsScalar("-initial_load_factor", "Initial load factor", "",
5809 loadFactor, &loadFactor, PETSC_NULLPTR);
5810 CHKERR PetscOptionsScalar("-max_crack_ext_area",
5811 "Maximum crack extension area", "",
5813 PETSC_NULLPTR);
5814 CHKERR PetscOptionsScalar("-clip_load_factor_percent",
5815 "Upper bound for load factor change", "",
5816 load_factor_change_clip,
5817 &load_factor_change_clip, PETSC_NULLPTR);
5818 PetscOptionsEnd();
5819
5820 currentPhysicalTime = start_time;
5821 physicalStepNumber = start_step;
5822 monitor_ptr->ts = ts;
5823 monitor_ptr->ts_u = PETSC_NULLPTR;
5824 monitor_ptr->ts_t = currentPhysicalTime;
5825 monitor_ptr->ts_step = physicalStepNumber;
5827
5828 PetscBool test_cook_flg = PETSC_FALSE;
5829 PetscInt atom_test = 0;
5830 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
5831 PETSC_NULLPTR);
5832 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
5833 PETSC_NULLPTR);
5834 if (atom_test || test_cook_flg) {
5835 test_monitor_ptr->ts = ts;
5836 test_monitor_ptr->ts_u = PETSC_NULLPTR;
5837 test_monitor_ptr->ts_t = currentPhysicalTime;
5838 test_monitor_ptr->ts_step = physicalStepNumber;
5839
5841 test_monitor_ptr);
5842 }
5843
5844 MOFEM_LOG("EP", Sev::inform)
5845 << "Initial crack area: " << *currentCrackAreaPtr;
5846 MOFEM_LOG("EP", Sev::inform) << "Initial load factor: " << loadFactor;
5847 MOFEM_LOG("EP", Sev::inform)
5848 << "Initial crack front energy: " << avgGriffithsEnergy;
5849
5851 MOFEM_LOG("EP", Sev::inform)
5852 << "Load step " << physicalStepNumber << " Load Factor "
5853 << currentPhysicalTime << " delta load factor " << physicalDt;
5854
5858
5859 CHKERR TSSetStepNumber(ts, 0);
5860 CHKERR TSSetTime(ts, 0);
5861 CHKERR TSSetTimeStep(ts, ts_delta_time);
5862 if (!physicalH1Update) {
5863 CHKERR TSElasticPostStep::preStepFun(ts);
5864 }
5865 CHKERR TSSetSolution(ts, x);
5866 CHKERR TSSolve(ts, PETSC_NULLPTR);
5867 loadFactorTSSolveExecuted = PETSC_TRUE;
5868 if (!physicalH1Update) {
5869 CHKERR TSElasticPostStep::postStepFun(ts);
5870 }
5871
5872 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5873 SCATTER_FORWARD);
5874 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5875 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5876
5877 monitor_ptr->ts = ts;
5878 monitor_ptr->ts_u = x;
5879 monitor_ptr->ts_t = currentPhysicalTime;
5880 monitor_ptr->ts_step = physicalStepNumber;
5882
5883 if (atom_test || test_cook_flg) {
5884 test_monitor_ptr->ts = ts;
5885 test_monitor_ptr->ts_u = x;
5886 test_monitor_ptr->ts_t = currentPhysicalTime;
5887 test_monitor_ptr->ts_step = physicalStepNumber;
5889 test_monitor_ptr);
5890 }
5891
5892 if (mField.get_comm_rank() == 0) {
5893 const double delta_area = *currentCrackAreaPtr - oldCrackArea;
5894 const bool has_crack_extension = delta_area > 0.0;
5895
5896 if (has_crack_extension) {
5897 const double denom = 0.5 * std::abs(avgGriffithsEnergy);
5898 if (denom > 0.0) {
5899 const double updated_load_factor =
5900 oldLoadFactor * std::sqrt(griffithEnergy / denom);
5901 loadFactor = std::max(updated_load_factor, 1.0e-6);
5902 }
5903 }
5904
5905 const bool is_first_step = physicalStepNumber == start_step;
5906 const double initial_step_range = 5;
5907 const double min_load_factor = 1.0e-6;
5908 const double max_load_factor =
5909 oldLoadFactor * (1.0 + load_factor_change_clip);
5910
5911 if (physicalStepNumber >= start_step + initial_step_range) {
5912 loadFactor = std::clamp(loadFactor, min_load_factor, max_load_factor);
5913 MOFEM_LOG("EP", Sev::inform)
5914 << "Allowable range for load factor [" << min_load_factor << ", "
5915 << max_load_factor << "]";
5916 }
5917
5918 const double previous_load_factor = is_first_step ? 0. : oldLoadFactor;
5919 physicalDt = loadFactor - previous_load_factor;
5920
5921 MOFEM_LOG("EP", Sev::inform)
5922 << "Setting new load factor to: " << loadFactor;
5923 }
5924 double load_control_data[] = {physicalDt, loadFactor};
5925 CHKERR MPI_Bcast(load_control_data, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
5926 physicalDt = load_control_data[0];
5927 loadFactor = load_control_data[1];
5928
5931 break;
5932
5933 const double remainingPhysicalTime =
5935 if (physicalDt >= remainingPhysicalTime) {
5937 } else {
5939 }
5940 }
5941
5942 CHKERR TSElasticPostStep::postStepDestroy();
5943 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5944 {elasticFeLhs.get(), elasticFeRhs.get()});
5945 MOFEM_LOG("EP", Sev::inform) << "Final load factor: " << loadFactor;
5946
5948}
5949
5951 int start_step,
5952 double start_time) {
5954
5955 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5956
5957 auto topological_tao_ctx = createTopologicalTAOCtx(
5958 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
5959 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
5960 SmartPetscObj<TS>(ts, true));
5961
5962 double final_time = 1;
5963 double delta_time = 0.1;
5964 int max_it = 10;
5965 PetscBool ts_h1_update = PETSC_FALSE;
5966
5967 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5968
5969 CHKERR PetscOptionsScalar("-dynamic_final_time",
5970 "dynamic relaxation final time", "", final_time,
5971 &final_time, PETSC_NULLPTR);
5972 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5973 "dynamic relaxation final time", "", delta_time,
5974 &delta_time, PETSC_NULLPTR);
5975 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5976 max_it, &max_it, PETSC_NULLPTR);
5977 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5978 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
5979
5980 PetscOptionsEnd();
5981
5982 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
5983 MOFEM_LOG("EP", Sev::inform)
5984 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
5985 MOFEM_LOG("EP", Sev::inform)
5986 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
5987 MOFEM_LOG("EP", Sev::inform)
5988 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
5989 MOFEM_LOG("EP", Sev::inform)
5990 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5991 << (ts_h1_update ? "TRUE" : "FALSE");
5992
5994
5995 auto setup_ts_monitor = [&]() {
5996 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5997 return monitor_ptr;
5998 };
5999 auto monitor_ptr = setup_ts_monitor();
6000
6001 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6002 {elasticFeLhs.get(), elasticFeRhs.get()});
6003 CHKERR TSSetUp(ts);
6004 CHKERR TSElasticPostStep::postStepInitialise(this);
6005
6006 double ts_delta_time;
6007 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6008
6009 if (ts_h1_update) {
6010 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6011 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6012 }
6013
6014 CHKERR TSElasticPostStep::preStepFun(ts);
6015 CHKERR TSElasticPostStep::postStepFun(ts);
6016
6017 auto tao = createTao(mField.get_comm());
6018 CHKERR TaoSetType(tao, TAOLMVM);
6021 topologicalEvaluateObjectiveAndGradient,
6022 (void *)topological_tao_ctx.get());
6023
6024 currentPhysicalTime = start_time;
6025 physicalStepNumber = start_step;
6026 monitor_ptr->ts = PETSC_NULLPTR;
6027 monitor_ptr->ts_u = PETSC_NULLPTR;
6028 monitor_ptr->ts_t = currentPhysicalTime;
6029 monitor_ptr->ts_step = physicalStepNumber;
6031
6032 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6033 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6034 SCATTER_FORWARD, RowColData::ROW);
6035 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6036 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6037
6038 int tao_sol_size, tao_sol_loc_size;
6039 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6040 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6041 MOFEM_LOG("EP", Sev::inform)
6042 << "Toplogical data vector size " << tao_sol_size << " local size "
6043 << tao_sol_loc_size << " number of interface faces "
6044 << interfaceFaces->size();
6045
6046 CHKERR TaoSetFromOptions(tao);
6047
6048 if (delta_time <= 0.) {
6050 "delta_time must be positive, got %g", delta_time);
6051 }
6052 for (; currentPhysicalTime < final_time;) {
6053 MOFEM_LOG("EP", Sev::inform)
6054 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
6055 << " delta time " << delta_time;
6056
6057 CHKERR VecZeroEntries(tao_sol0);
6058 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6059 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6060 CHKERR TaoSetSolution(tao, tao_sol0);
6061 CHKERR TaoSolve(tao);
6062 Vec tao_sol;
6063 CHKERR TaoGetSolution(tao, &tao_sol);
6064
6065 // // add solution increment to kappa vec/tags
6066 // auto &kappa_vec = topological_tao_ctx->getKappaVec();
6067 // CHKERR CommInterface::setVectorFromTag(mField.get_moab(), kappa_vec,
6068 // get_kappa_tag(mField.get_moab()));
6069 // CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
6070 // CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
6071 // SCATTER_FORWARD);
6072 // CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
6073 // CHKERR CommInterface::setTagFromVector(mField.get_moab(), kappa_vec,
6074 // get_kappa_tag(mField.get_moab()));
6075
6076
6077 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6078 SCATTER_FORWARD);
6079 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6080 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6081 monitor_ptr->ts = PETSC_NULLPTR;
6082 monitor_ptr->ts_u = x;
6083 monitor_ptr->ts_t = currentPhysicalTime;
6084 monitor_ptr->ts_step = physicalStepNumber;
6086
6088 if (physicalStepNumber > max_it)
6089 break;
6090
6091 const double remainingPhysicalTime = final_time - currentPhysicalTime;
6092 if (delta_time >= remainingPhysicalTime) {
6093 currentPhysicalTime = final_time;
6094 } else {
6095 currentPhysicalTime += delta_time;
6096 }
6097 }
6098
6099 CHKERR TSElasticPostStep::postStepDestroy();
6100 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6101 {elasticFeLhs.get(), elasticFeRhs.get()});
6102
6104}
6105
6107 int start_step,
6108 double start_time) {
6110
6111 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6112
6113 auto topological_tao_ctx = createTopologicalTAOCtx(
6114 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6115 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6116 SmartPetscObj<TS>(ts, true));
6117
6118 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6120
6121 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6122
6123 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6124 {elasticFeLhs.get(), elasticFeRhs.get()});
6125 CHKERR TSSetUp(ts);
6126 CHKERR TSElasticPostStep::postStepInitialise(this);
6127
6128 double ts_delta_time;
6129 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6130
6131 if (physicalH1Update) {
6132 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6133 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6134 }
6135
6136 CHKERR TSElasticPostStep::preStepFun(ts);
6137 CHKERR TSElasticPostStep::postStepFun(ts);
6138
6139 const bool restart_run =
6140 start_step != 0 ||
6141 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6142 const double test_time = restart_run ? start_time : finalPhysicalTime;
6143 if (!restart_run &&
6144 std::abs(test_time) < std::numeric_limits<double>::epsilon()) {
6146 "Set non-zero -physical_final_time for test_topological_derivative");
6147 }
6148
6149 currentPhysicalTime = test_time;
6150 physicalStepNumber = start_step;
6151 monitor_ptr->ts = PETSC_NULLPTR;
6152 monitor_ptr->ts_u = PETSC_NULLPTR;
6153 monitor_ptr->ts_t = currentPhysicalTime;
6154 monitor_ptr->ts_step = physicalStepNumber;
6156
6157 MOFEM_LOG("EP", Sev::inform)
6158 << "Solving load step before topological derivative test: "
6159 << physicalStepNumber << " Time " << currentPhysicalTime
6160 << " TS delta time " << ts_delta_time;
6161
6162 CHKERR TSSetStepNumber(ts, 0);
6163 CHKERR TSSetTime(ts, 0);
6164 CHKERR TSSetTimeStep(ts, ts_delta_time);
6165 if (!physicalH1Update) {
6166 CHKERR TSElasticPostStep::preStepFun(ts);
6167 }
6168 CHKERR TSSetSolution(ts, x);
6169 CHKERR TSSolve(ts, PETSC_NULLPTR);
6170 if (!physicalH1Update) {
6171 CHKERR TSElasticPostStep::postStepFun(ts);
6172 }
6173
6174 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6175 SCATTER_FORWARD);
6176 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6177 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6178
6179 monitor_ptr->ts = PETSC_NULLPTR;
6180 monitor_ptr->ts_u = x;
6181 monitor_ptr->ts_t = currentPhysicalTime;
6182 monitor_ptr->ts_step = physicalStepNumber;
6184
6185 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6186 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6187 SCATTER_FORWARD, RowColData::ROW);
6188 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6189 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6190
6191 int tao_sol_size, tao_sol_loc_size;
6192 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6193 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6194 MOFEM_LOG("EP", Sev::inform)
6195 << "Topological data vector size " << tao_sol_size << " local size "
6196 << tao_sol_loc_size << " number of interface faces "
6197 << interfaceFaces->size();
6198
6199 const char *list_objective_models[ObjectiveModelType::LAST_MODEL] = {
6200 "python_model", "hencky_model"};
6201#ifdef ENABLE_PYTHON_BINDING
6202 PetscInt choice_objective_model = ObjectiveModelType::PYTHON_MODEL;
6203#else
6204 PetscInt choice_objective_model = ObjectiveModelType::HENCKY_MODEL;
6205#endif
6207 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_model_type",
6208 list_objective_models, ObjectiveModelType::LAST_MODEL,
6209 &choice_objective_model, PETSC_NULLPTR);
6210 const auto objective_model_type =
6211 static_cast<ObjectiveModelType>(choice_objective_model);
6212 MOFEM_LOG("EP", Sev::inform)
6213 << "Objective model type: -objective_model_type "
6214 << list_objective_models[objective_model_type];
6215
6217 PetscReal obj_value;
6218 CHKERR testTopologicalDerivative(topological_tao_ctx.get(), tao_sol0,
6219 &obj_value, g, objective_model_type);
6220
6221 CHKERR TSElasticPostStep::postStepDestroy();
6222 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6223 {elasticFeLhs.get(), elasticFeRhs.get()});
6224
6226}
6227
6228} // namespace EshelbianPlasticity
6229
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_block_meshset(MoFEM::Interface &m_field, const int ms_id, const unsigned int cubit_bc_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.
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,...)
#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_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.
@ 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 removeBlockDOFsOnEntities(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, bool is_distributed_mesh=true)
Remove DOFs from problem based on block entities.
Definition BcManager.cpp:72
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
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
boost::shared_ptr< ContactSDFPython > setupContactSdf()
Read SDF file and setup contact SDF.
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
static Tag get_tag(moab::Interface &moab, std::string tag_name, int size)
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.
MoFEMErrorCode pushCohesiveOpsLhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
MoFEMErrorCode pushCohesiveOpsRhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
static auto get_body_range(MoFEM::Interface &m_field, const std::string name, int dim)
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
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.
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
#define QUAD_2D_TABLE_SIZE
Definition quad.h:174
#define QUAD_3D_TABLE_SIZE
Definition quad.h:186
static QUAD *const QUAD_2D_TABLE[]
Definition quad.h:175
static QUAD *const QUAD_3D_TABLE[]
Definition quad.h:187
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)
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_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 dd_f_log(const double v)
BitRefLevel bitAdjEnt
bit ref level for parent
static boost::function< double(const double)> inv_dd_f
MoFEM::Interface & mField
const std::string spatialL2Disp
static double inv_d_f_log(const double v)
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static enum SolverType solverType
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.
static enum StretchHandling stretchHandling
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
static const char * listSolvers[]
const std::string materialH1Positions
static int nbJIntegralContours
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.
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={})
const std::string elementVolumeName
static double dd_f_log_e(const double v)
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 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)
static double d_f_log(const double v)
boost::shared_ptr< NormalDisplacementBcVec > bcSpatialNormalDisplacementVecPtr
static double crackingStartTime
MoFEMErrorCode getOptions()
const std::string piolaStress
MoFEMErrorCode setElasticElementToTs(DM dm)
static double inv_d_f_log_e(const double v)
MoFEMErrorCode setFaceInterfaceOps(const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
static int physicalStepNumber
MoFEMErrorCode gettingNorms()
[Getting norms]
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
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
SmartPetscObj< DM > dmMaterial
Material problem.
static double inv_f_log(const double v)
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
static double crackingAddTime
static double exponentBase
static double dd_f_linear(const double v)
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)
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
static double currentPhysicalTime
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
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 double inv_d_f_linear(const double v)
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.
static double inv_dd_f_log(const double v)
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)
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
static double finalPhysicalTime
const std::string skinElement
static PetscBool internalStressVoigt
static double inv_dd_f_linear(const double v)
MoFEMErrorCode addVolumeFiniteElement(const EntityHandle meshset=0, const bool add_bubble=true)
static double inv_dd_f_log_e(const double v)
MoFEMErrorCode getExternalStrain()
MoFEMErrorCode getSpatialTractionBc()
MoFEMErrorCode pushNoStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
static PetscBool setSingularity
virtual ~EshelbianCore()
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
boost::shared_ptr< double > currentCrackAreaPtr
static PetscBool meshTransferSourceMeshFileSpecified
static double f_log_e_quadratic(const double v)
double avgGriffithsEnergy
static bool hasNonHomogeneousMaterialBlock
MoFEMErrorCode addDMs(const BitRefLevel bit=BitRefLevel().set(0), const EntityHandle meshset=0)
MoFEMErrorCode solveCohesiveCrackGrowth(TS ts, Vec x, int start_step, double start_time)
Solve cohesive crack growth problem.
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 double inv_f_log_e(const double v)
MoFEMErrorCode createExchangeVectors(Sev sev)
MoFEMErrorCode pushStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
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 double d_f_linear(const double v)
static int meshTransferInterpOrder
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
static double f_log(const double v)
CommInterface::EntitiesPetscVector faceExchange
SmartPetscObj< DM > dmElastic
Elastic problem.
static std::string meshTransferSourceMeshFileName
EshelbianCore(MoFEM::Interface &m_field)
boost::shared_ptr< Range > frontEdges
static boost::function< double(const double)> inv_f
const std::string stretchTensor
BitRefLevel bitAdjEntMask
bit ref level for parent parent
static double f_linear(const double v)
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)
AnalyticalTractionBc(std::string name, std::vector< double > attr, Range faces)
BcRot(std::string name, std::vector< double > attr, Range faces)
ExternalStrain(std::string name, std::vector< double > attr, Range ents)
int operator()(int p_row, int p_col, int p_data) const
NormalDisplacementBc(std::string name, std::vector< double > attr, Range faces)
PressureBc(std::string name, std::vector< double > attr, Range faces)
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges)
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, FunRule fun_rule)
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)
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)
Set integration rule on element.
int operator()(int p_row, int p_col, int p_data) const
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.
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.
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 MoFEMErrorCode setVectorFromTag(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Vector From Tag object.
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Tag From Vector object.
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.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
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
UserDataOperator(const FieldSpace space, const char type=OPSPACE, const bool symm=true)
Constructor for operators working on finite element spaces.
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.
Calculate symmetric tensor field rates ant integratio pts.
Calculate symmetric tensor field values at integration pts.
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, boost::shared_ptr< MatrixDouble > > DataMapMat
@ CTX_SET_TIME
Time value is set.
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
std::function< double(double)> ScalingFun
static constexpr std::array< double, 6 > diffShapeFunMBTRI
Definition Tools.hpp:104
static MoFEMErrorCode getTriNormal(const double *coords, double *normal, double *d_normal=nullptr)
Get the Tri Normal objectGet triangle normal.
Definition Tools.cpp:353
static double 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.
int order
Definition quad.h:28
int npoints
Definition quad.h:29
BoundaryEle::UserDataOperator BdyEleOp
int atom_test
Atom test.
Definition plastic.cpp:122
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62
auto save_range