v0.15.5
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 <EshelbianContact.hpp>
36#include <EshelbianCohesive.hpp>
37#include <TSElasticPostStep.hpp>
38
39extern "C" {
40#include <phg-quadrule/quad.h>
41}
42
43#include <queue>
44
45namespace EshelbianPlasticity {
54
55} // namespace EshelbianPlasticity
56
57static auto send_type(MoFEM::Interface &m_field, Range r,
58 const EntityType type) {
59 ParallelComm *pcomm =
60 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
61
62 auto dim = CN::Dimension(type);
63
64 std::vector<int> sendcounts(pcomm->size());
65 std::vector<int> displs(pcomm->size());
66 std::vector<int> sendbuf(r.size());
67 if (pcomm->rank() == 0) {
68 for (auto p = 1; p != pcomm->size(); p++) {
69 auto part_ents = m_field.getInterface<CommInterface>()
70 ->getPartEntities(m_field.get_moab(), p)
71 .subset_by_dimension(SPACE_DIM);
72 Range faces;
73 CHKERR m_field.get_moab().get_adjacencies(part_ents, dim, true, faces,
74 moab::Interface::UNION);
75 faces = intersect(faces, r);
76 sendcounts[p] = faces.size();
77 displs[p] = sendbuf.size();
78 for (auto f : faces) {
79 auto id = id_from_handle(f);
80 sendbuf.push_back(id);
81 }
82 }
83 }
84
85 int recv_data;
86 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
87 pcomm->comm());
88 std::vector<int> recvbuf(recv_data);
89 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
90 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
91
92 if (pcomm->rank() > 0) {
93 Range r;
94 for (auto &f : recvbuf) {
95 r.insert(ent_form_type_and_id(type, f));
96 }
97 return r;
98 }
99
100 return r;
101}
102
104 const std::string block_name, int dim) {
105 Range r;
106
107 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
108 auto bcs = mesh_mng->getCubitMeshsetPtr(
109
110 std::regex((boost::format("%s(.*)") % block_name).str())
111
112 );
113
114 for (auto bc : bcs) {
115 Range faces;
116 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
117 faces, true),
118 "get meshset ents");
119 r.merge(faces);
120 }
121
122 return r;
123};
124
126 const std::string block_name, int dim) {
127 std::map<std::string, Range> r;
128
129 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
130 auto bcs = mesh_mng->getCubitMeshsetPtr(
131
132 std::regex((boost::format("%s(.*)") % block_name).str())
133
134 );
135
136 for (auto bc : bcs) {
137 Range faces;
138 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
139 faces, true),
140 "get meshset ents");
141 r[bc->getName()] = faces;
142 }
143
144 return r;
145}
146
147static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id,
148 const unsigned int cubit_bc_type) {
149 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
150 EntityHandle meshset;
151 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
152 return meshset;
153};
154
155static auto save_range(moab::Interface &moab, const std::string name,
156 const Range r, std::vector<Tag> tags = {}) {
158 auto out_meshset = get_temp_meshset_ptr(moab);
159 CHKERR moab.add_entities(*out_meshset, r);
160 if (r.size()) {
161 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
162 tags.data(), tags.size());
163 } else {
164 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
165 }
167};
168
169static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
170 Range boundary_ents;
171 ParallelComm *pcomm =
172 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
173 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
174 PSTATUS_SHARED | PSTATUS_MULTISHARED,
175 PSTATUS_NOT, -1, &boundary_ents),
176 "filter_pstatus");
177 return boundary_ents;
178};
179
180static auto filter_owners(MoFEM::Interface &m_field, Range skin) {
181 Range owner_ents;
182 ParallelComm *pcomm =
183 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
184 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
185 &owner_ents),
186 "filter_pstatus");
187 return owner_ents;
188};
189
190static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
191 Skinner skin(&m_field.get_moab());
192 Range skin_ents;
193 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
194 return skin_ents;
195};
196
198 Range crack_faces) {
199 ParallelComm *pcomm =
200 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
201 auto &moab = m_field.get_moab();
202 Range crack_skin_without_bdy;
203 if (pcomm->rank() == 0) {
204 Range crack_edges;
205 CHKERR moab.get_adjacencies(crack_faces, 1, true, crack_edges,
206 moab::Interface::UNION);
207 auto crack_skin = get_skin(m_field, crack_faces);
208 Range body_ents;
210 m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents),
211 "get_entities_by_dimension");
212 auto body_skin = get_skin(m_field, body_ents);
213 Range body_skin_edges;
214 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1, true, body_skin_edges,
215 moab::Interface::UNION),
216 "get_adjacencies");
217 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
218 auto front_edges_map = get_range_from_block_map(m_field, "FRONT", 1);
219 for (auto &m : front_edges_map) {
220 auto add_front = subtract(m.second, crack_edges);
221 auto i = intersect(m.second, crack_edges);
222 if (i.empty()) {
223 crack_skin_without_bdy.merge(add_front);
224 } else {
225 auto i_skin = get_skin(m_field, i);
226 Range adj_i_skin;
227 CHKERR moab.get_adjacencies(i_skin, 1, true, adj_i_skin,
228 moab::Interface::UNION);
229 adj_i_skin = subtract(intersect(adj_i_skin, m.second), crack_edges);
230 crack_skin_without_bdy.merge(adj_i_skin);
231 }
232 }
233 }
234 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
235}
236
238 Range crack_faces) {
239
240 ParallelComm *pcomm =
241 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
242
243 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface";
244
245 if (!pcomm->rank()) {
246
247 auto impl = [&](auto &saids) {
249
250 auto &moab = m_field.get_moab();
251
252 auto get_adj = [&](auto e, auto dim) {
253 Range adj;
254 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(
255 e, dim, true, adj, moab::Interface::UNION),
256 "get adj");
257 return adj;
258 };
259
260 auto get_conn = [&](auto e) {
261 Range conn;
262 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(e, conn, true),
263 "get connectivity");
264 return conn;
265 };
266
267 constexpr bool debug = false;
268 Range body_ents;
269 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
270 body_ents);
271 auto body_skin = get_skin(m_field, body_ents);
272 auto body_skin_edges = get_adj(body_skin, 1);
273
274 auto crack_skin =
275 subtract(get_skin(m_field, crack_faces), body_skin_edges);
276 auto crack_skin_conn = get_conn(crack_skin);
277 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
278 auto crack_edges = get_adj(crack_faces, 1);
279 crack_edges = subtract(crack_edges, crack_skin);
280 auto all_tets = get_adj(crack_edges, 3);
281 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
282 auto crack_conn = get_conn(crack_edges);
283 all_tets.merge(get_adj(crack_conn, 3));
284
285 if (debug) {
286 CHKERR save_range(m_field.get_moab(), "crack_faces.vtk", crack_faces);
287 CHKERR save_range(m_field.get_moab(), "all_crack_tets.vtk", all_tets);
288 CHKERR save_range(m_field.get_moab(), "crack_edges_all.vtk",
289 crack_edges);
290 }
291
292 if (crack_faces.size()) {
293 auto grow = [&](auto r) {
294 auto crack_faces_conn = get_conn(crack_faces);
295 Range v;
296 auto size_r = 0;
297 while (size_r != r.size() && r.size() > 0) {
298 size_r = r.size();
299 CHKERR moab.get_connectivity(r, v, true);
300 v = subtract(v, crack_faces_conn);
301 if (v.size()) {
302 CHKERR moab.get_adjacencies(v, SPACE_DIM, true, r,
303 moab::Interface::UNION);
304 r = intersect(r, all_tets);
305 }
306 if (r.empty()) {
307 break;
308 }
309 }
310 return r;
311 };
312
313 Range all_tets_ord = all_tets;
314 while (all_tets.size()) {
315 Range faces = get_adj(unite(saids.first, saids.second), 2);
316 faces = subtract(crack_faces, faces);
317 if (faces.size()) {
318 Range tets;
319 auto fit = faces.begin();
320 for (; fit != faces.end(); ++fit) {
321 tets = intersect(get_adj(Range(*fit, *fit), 3), all_tets);
322 if (tets.size() == 2) {
323 break;
324 }
325 }
326 if (tets.empty()) {
327 break;
328 } else {
329 saids.first.insert(tets[0]);
330 saids.first = grow(saids.first);
331 all_tets = subtract(all_tets, saids.first);
332 if (tets.size() == 2) {
333 saids.second.insert(tets[1]);
334 saids.second = grow(saids.second);
335 all_tets = subtract(all_tets, saids.second);
336 }
337 }
338 } else {
339 break;
340 }
341 }
342
343 saids.first = subtract(all_tets_ord, saids.second);
344 saids.second = subtract(all_tets_ord, saids.first);
345 }
346
348 };
349
350 std::pair<Range, Range> saids;
351 if (crack_faces.size())
352 CHK_THROW_MESSAGE(impl(saids), "get crack both sides");
353 return saids;
354 }
355
356 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface <- done";
357
358 return std::pair<Range, Range>();
359}
360
361namespace EshelbianPlasticity {
362
364
365 using FunRule = boost::function<int(int)>;
366 FunRule funRule = [](int p) { return 2 * p + 1; };
367
369 boost::shared_ptr<Range> front_nodes,
370 boost::shared_ptr<Range> front_edges,
371 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
372 : frontNodes(front_nodes), frontEdges(front_edges), cachePhi(cache_phi){};
373
375 boost::shared_ptr<Range> front_nodes,
376 boost::shared_ptr<Range> front_edges, FunRule fun_rule,
377 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
378 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule),
379 cachePhi(cache_phi){};
380
382 int order_col, int order_data) {
384
385 constexpr bool debug = false;
386
387 constexpr int numNodes = 4;
388 constexpr int numEdges = 6;
389 constexpr int refinementLevels = 6;
390
391 auto &m_field = fe_raw_ptr->mField;
392 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
393 auto fe_handle = fe_ptr->getFEEntityHandle();
394
395 auto set_base_quadrature = [&]() {
397 int rule = funRule(order_data);
398 if (rule < QUAD_3D_TABLE_SIZE) {
399 if (QUAD_3D_TABLE[rule]->dim != 3) {
400 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
401 "wrong dimension");
402 }
403 if (QUAD_3D_TABLE[rule]->order < rule) {
404 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
405 "wrong order %d != %d", QUAD_3D_TABLE[rule]->order, rule);
406 }
407 const size_t nb_gauss_pts = QUAD_3D_TABLE[rule]->npoints;
408 auto &gauss_pts = fe_ptr->gaussPts;
409 gauss_pts.resize(4, nb_gauss_pts, false);
410 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[1], 4,
411 &gauss_pts(0, 0), 1);
412 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[2], 4,
413 &gauss_pts(1, 0), 1);
414 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[3], 4,
415 &gauss_pts(2, 0), 1);
416 cblas_dcopy(nb_gauss_pts, QUAD_3D_TABLE[rule]->weights, 1,
417 &gauss_pts(3, 0), 1);
418 auto &data = fe_ptr->dataOnElement[H1];
419 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4,
420 false);
421 double *shape_ptr =
422 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
423 cblas_dcopy(4 * nb_gauss_pts, QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
424 1);
425 } else {
426 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
427 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
428 }
430 };
431
432 CHKERR set_base_quadrature();
433
435
436 auto get_singular_nodes = [&]() {
437 int num_nodes;
438 const EntityHandle *conn;
439 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
440 true);
441 std::bitset<numNodes> singular_nodes;
442 for (auto nn = 0; nn != numNodes; ++nn) {
443 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
444 singular_nodes.set(nn);
445 } else {
446 singular_nodes.reset(nn);
447 }
448 }
449 return singular_nodes;
450 };
451
452 auto get_singular_edges = [&]() {
453 std::bitset<numEdges> singular_edges;
454 for (int ee = 0; ee != numEdges; ee++) {
455 EntityHandle edge;
456 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
457 if (frontEdges->find(edge) != frontEdges->end()) {
458 singular_edges.set(ee);
459 } else {
460 singular_edges.reset(ee);
461 }
462 }
463 return singular_edges;
464 };
465
466 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
468 fe_ptr->gaussPts.swap(ref_gauss_pts);
469 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
470 auto &data = fe_ptr->dataOnElement[H1];
471 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
472 double *shape_ptr =
473 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
474 CHKERR ShapeMBTET(shape_ptr, &fe_ptr->gaussPts(0, 0),
475 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
476 nb_gauss_pts);
478 };
479
480 auto singular_nodes = get_singular_nodes();
481 if (singular_nodes.count()) {
482 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
483 if (it_map_ref_coords != mapRefCoords.end()) {
484 CHKERR set_gauss_pts(it_map_ref_coords->second);
486 } else {
487
488 auto refine_quadrature = [&]() {
490
491 const int max_level = refinementLevels;
492 EntityHandle tet;
493
494 moab::Core moab_ref;
495 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
496 EntityHandle nodes[4];
497 for (int nn = 0; nn != 4; nn++)
498 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
499 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
500 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
501 MoFEM::Interface &m_field_ref = mofem_ref_core;
502 {
503 Range tets(tet, tet);
504 Range edges;
505 CHKERR m_field_ref.get_moab().get_adjacencies(
506 tets, 1, true, edges, moab::Interface::UNION);
507 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
508 tets, BitRefLevel().set(0), false, VERBOSE);
509 }
510
511 Range nodes_at_front;
512 for (int nn = 0; nn != numNodes; nn++) {
513 if (singular_nodes[nn]) {
514 EntityHandle ent;
515 CHKERR moab_ref.side_element(tet, 0, nn, ent);
516 nodes_at_front.insert(ent);
517 }
518 }
519
520 auto singular_edges = get_singular_edges();
521
522 EntityHandle meshset;
523 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
524 for (int ee = 0; ee != numEdges; ee++) {
525 if (singular_edges[ee]) {
526 EntityHandle ent;
527 CHKERR moab_ref.side_element(tet, 1, ee, ent);
528 CHKERR moab_ref.add_entities(meshset, &ent, 1);
529 }
530 }
531
532 // refine mesh
533 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
534 for (int ll = 0; ll != max_level; ll++) {
535 Range edges;
536 CHKERR m_field_ref.getInterface<BitRefManager>()
537 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
538 BitRefLevel().set(), MBEDGE,
539 edges);
540 Range ref_edges;
541 CHKERR moab_ref.get_adjacencies(
542 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
543 ref_edges = intersect(ref_edges, edges);
544 Range ents;
545 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
546 ref_edges = intersect(ref_edges, ents);
547 Range tets;
548 CHKERR m_field_ref.getInterface<BitRefManager>()
549 ->getEntitiesByTypeAndRefLevel(
550 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
551 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
552 ref_edges, BitRefLevel().set(ll + 1));
553 CHKERR m_ref->refineTets(tets, BitRefLevel().set(ll + 1));
554 CHKERR m_field_ref.getInterface<BitRefManager>()
555 ->updateMeshsetByEntitiesChildren(meshset,
556 BitRefLevel().set(ll + 1),
557 meshset, MBEDGE, true);
558 }
559
560 // get ref coords
561 Range tets;
562 CHKERR m_field_ref.getInterface<BitRefManager>()
563 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
564 BitRefLevel().set(), MBTET,
565 tets);
566
567 if (debug) {
568 CHKERR save_range(moab_ref, "ref_tets.vtk", tets);
569 }
570
571 MatrixDouble ref_coords(tets.size(), 12, false);
572 int tt = 0;
573 for (Range::iterator tit = tets.begin(); tit != tets.end();
574 tit++, tt++) {
575 int num_nodes;
576 const EntityHandle *conn;
577 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
578 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
579 }
580
581 auto &data = fe_ptr->dataOnElement[H1];
582 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
583 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
584 MatrixDouble &shape_n =
585 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
586 int gg = 0;
587 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
588 double *tet_coords = &ref_coords(tt, 0);
589 double det = Tools::tetVolume(tet_coords);
590 det *= 6;
591 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
592 for (int dd = 0; dd != 3; dd++) {
593 ref_gauss_pts(dd, gg) =
594 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
595 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
596 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
597 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
598 }
599 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
600 }
601 }
602
603 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
604 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
605
606 // clear cache bubble
607 cachePhi->get<0>() = 0;
608 cachePhi->get<1>() = 0;
609 // tet base cache
610 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
611 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
612
614 };
615
616 CHKERR refine_quadrature();
617 }
618 }
619 }
620
622 }
623
624private:
625 struct Fe : public ForcesAndSourcesCore {
626 using ForcesAndSourcesCore::dataOnElement;
627
628 private:
629 using ForcesAndSourcesCore::ForcesAndSourcesCore;
630 };
631
632 boost::shared_ptr<Range> frontNodes;
633 boost::shared_ptr<Range> frontEdges;
634
635 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cachePhi;
636
637 static inline std::map<long int, MatrixDouble> mapRefCoords;
638};
639
641
642 using FunRule = boost::function<int(int)>;
643 FunRule funRule = [](int p) { return 2 * (p + 1) + 1; };
644
645 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
646 boost::shared_ptr<Range> front_edges)
647 : frontNodes(front_nodes), frontEdges(front_edges){};
648
649 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
650 boost::shared_ptr<Range> front_edges,
651 FunRule fun_rule)
652 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule){};
653
655 int order_col, int order_data) {
657
658 constexpr bool debug = false;
659
660 constexpr int numNodes = 3;
661 constexpr int numEdges = 3;
662 constexpr int refinementLevels = 6;
663
664 auto &m_field = fe_raw_ptr->mField;
665 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
666 auto fe_handle = fe_ptr->getFEEntityHandle();
667
668 auto set_base_quadrature = [&]() {
670 int rule = funRule(order_data);
671 if (rule < QUAD_2D_TABLE_SIZE) {
672 if (QUAD_2D_TABLE[rule]->dim != 2) {
673 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
674 }
675 if (QUAD_2D_TABLE[rule]->order < rule) {
676 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
677 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
678 }
679 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
680 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
681 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
682 &fe_ptr->gaussPts(0, 0), 1);
683 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
684 &fe_ptr->gaussPts(1, 0), 1);
685 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
686 &fe_ptr->gaussPts(2, 0), 1);
687 auto &data = fe_ptr->dataOnElement[H1];
688 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
689 false);
690 double *shape_ptr =
691 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
692 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
693 1);
694 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
695 std::copy(
697 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
698
699 } else {
700 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
701 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
702 }
704 };
705
706 CHKERR set_base_quadrature();
707
709
710 auto get_singular_nodes = [&]() {
711 int num_nodes;
712 const EntityHandle *conn;
713 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
714 true);
715 std::bitset<numNodes> singular_nodes;
716 for (auto nn = 0; nn != numNodes; ++nn) {
717 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
718 singular_nodes.set(nn);
719 } else {
720 singular_nodes.reset(nn);
721 }
722 }
723 return singular_nodes;
724 };
725
726 auto get_singular_edges = [&]() {
727 std::bitset<numEdges> singular_edges;
728 for (int ee = 0; ee != numEdges; ee++) {
729 EntityHandle edge;
730 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
731 if (frontEdges->find(edge) != frontEdges->end()) {
732 singular_edges.set(ee);
733 } else {
734 singular_edges.reset(ee);
735 }
736 }
737 return singular_edges;
738 };
739
740 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
742 fe_ptr->gaussPts.swap(ref_gauss_pts);
743 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
744 auto &data = fe_ptr->dataOnElement[H1];
745 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
746 double *shape_ptr =
747 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
748 CHKERR ShapeMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
749 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
751 };
752
753 auto singular_nodes = get_singular_nodes();
754 if (singular_nodes.count()) {
755 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
756 if (it_map_ref_coords != mapRefCoords.end()) {
757 CHKERR set_gauss_pts(it_map_ref_coords->second);
759 } else {
760
761 auto refine_quadrature = [&]() {
763
764 const int max_level = refinementLevels;
765
766 moab::Core moab_ref;
767 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
768 EntityHandle nodes[numNodes];
769 for (int nn = 0; nn != numNodes; nn++)
770 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
771 EntityHandle tri;
772 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
773 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
774 MoFEM::Interface &m_field_ref = mofem_ref_core;
775 {
776 Range tris(tri, tri);
777 Range edges;
778 CHKERR m_field_ref.get_moab().get_adjacencies(
779 tris, 1, true, edges, moab::Interface::UNION);
780 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
781 tris, BitRefLevel().set(0), false, VERBOSE);
782 }
783
784 Range nodes_at_front;
785 for (int nn = 0; nn != numNodes; nn++) {
786 if (singular_nodes[nn]) {
787 EntityHandle ent;
788 CHKERR moab_ref.side_element(tri, 0, nn, ent);
789 nodes_at_front.insert(ent);
790 }
791 }
792
793 auto singular_edges = get_singular_edges();
794
795 EntityHandle meshset;
796 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
797 for (int ee = 0; ee != numEdges; ee++) {
798 if (singular_edges[ee]) {
799 EntityHandle ent;
800 CHKERR moab_ref.side_element(tri, 1, ee, ent);
801 CHKERR moab_ref.add_entities(meshset, &ent, 1);
802 }
803 }
804
805 // refine mesh
806 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
807 for (int ll = 0; ll != max_level; ll++) {
808 Range edges;
809 CHKERR m_field_ref.getInterface<BitRefManager>()
810 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
811 BitRefLevel().set(), MBEDGE,
812 edges);
813 Range ref_edges;
814 CHKERR moab_ref.get_adjacencies(
815 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
816 ref_edges = intersect(ref_edges, edges);
817 Range ents;
818 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
819 ref_edges = intersect(ref_edges, ents);
820 Range tris;
821 CHKERR m_field_ref.getInterface<BitRefManager>()
822 ->getEntitiesByTypeAndRefLevel(
823 BitRefLevel().set(ll), BitRefLevel().set(), MBTRI, tris);
824 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
825 ref_edges, BitRefLevel().set(ll + 1));
826 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
827 CHKERR m_field_ref.getInterface<BitRefManager>()
828 ->updateMeshsetByEntitiesChildren(meshset,
829 BitRefLevel().set(ll + 1),
830 meshset, MBEDGE, true);
831 }
832
833 // get ref coords
834 Range tris;
835 CHKERR m_field_ref.getInterface<BitRefManager>()
836 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
837 BitRefLevel().set(), MBTRI,
838 tris);
839
840 if (debug) {
841 CHKERR save_range(moab_ref, "ref_tris.vtk", tris);
842 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
843 }
844
845 MatrixDouble ref_coords(tris.size(), 9, false);
846 int tt = 0;
847 for (Range::iterator tit = tris.begin(); tit != tris.end();
848 tit++, tt++) {
849 int num_nodes;
850 const EntityHandle *conn;
851 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
852 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
853 }
854
855 auto &data = fe_ptr->dataOnElement[H1];
856 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
857 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
858 MatrixDouble &shape_n =
859 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
860 int gg = 0;
861 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
862 double *tri_coords = &ref_coords(tt, 0);
864 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
865 auto det = t_normal.l2();
866 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
867 for (int dd = 0; dd != 2; dd++) {
868 ref_gauss_pts(dd, gg) =
869 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
870 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
871 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
872 }
873 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
874 }
875 }
876
877 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
878 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
879
881 };
882
883 CHKERR refine_quadrature();
884 }
885 }
886 }
887
889 }
890
891private:
892 struct Fe : public ForcesAndSourcesCore {
893 using ForcesAndSourcesCore::dataOnElement;
894
895 private:
896 using ForcesAndSourcesCore::ForcesAndSourcesCore;
897 };
898
899 boost::shared_ptr<Range> frontNodes;
900 boost::shared_ptr<Range> frontEdges;
901
902 static inline std::map<long int, MatrixDouble> mapRefCoords;
903};
904
905double EshelbianCore::exponentBase = exp(1);
906boost::function<double(const double)> EshelbianCore::f = EshelbianCore::f_log_e;
907boost::function<double(const double)> EshelbianCore::d_f =
909boost::function<double(const double)> EshelbianCore::dd_f =
911boost::function<double(const double)> EshelbianCore::inv_f =
913boost::function<double(const double)> EshelbianCore::inv_d_f =
915boost::function<double(const double)> EshelbianCore::inv_dd_f =
917
919EshelbianCore::query_interface(boost::typeindex::type_index type_index,
920 UnknownInterface **iface) const {
921 *iface = const_cast<EshelbianCore *>(this);
922 return 0;
923}
924
925MoFEMErrorCode OpJacobian::doWork(int side, EntityType type, EntData &data) {
927
928 if (evalRhs)
929 CHKERR evaluateRhs(data);
930
931 if (evalLhs)
932 CHKERR evaluateLhs(data);
933
935}
936
938 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
939}
940
942
945 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
946 const char *list_symm[] = {"symm", "not_symm"};
947 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
948 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
949 const char *list_solvers[] = {"time_solver", "dynamic_relaxation",
950 "cohesive"};
951 PetscInt choice_rot = EshelbianCore::rotSelector;
952 PetscInt choice_grad = EshelbianCore::gradApproximator;
953 PetscInt choice_symm = EshelbianCore::symmetrySelector;
954 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
955 PetscInt choice_stretch = StretchSelector::LOG;
956 PetscInt choice_solver = SolverType::TimeSolver;
957 char analytical_expr_file_name[255] = "analytical_expr.py";
958
959 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
960 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
961 spaceOrder, &spaceOrder, PETSC_NULLPTR);
962 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
963 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
964 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
965 "", materialOrder, &materialOrder, PETSC_NULLPTR);
966 CHKERR PetscOptionsScalar("-viscosity_alpha_u", "viscosity", "", alphaU,
967 &alphaU, PETSC_NULLPTR);
968 CHKERR PetscOptionsScalar("-viscosity_alpha_w", "viscosity", "", alphaW,
969 &alphaW, PETSC_NULLPTR);
970 CHKERR PetscOptionsScalar("-viscosity_alpha_omega", "rot viscosity", "",
971 alphaOmega, &alphaOmega, PETSC_NULLPTR);
972 CHKERR PetscOptionsScalar("-density_alpha_rho", "density", "", alphaRho,
973 &alphaRho, PETSC_NULLPTR);
974 CHKERR PetscOptionsScalar("-alpha_tau", "tau", "", alphaTau, &alphaTau,
975 PETSC_NULLPTR);
976 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
977 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
978 PETSC_NULLPTR);
979 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
980 list_rots, NO_H1_CONFIGURATION + 1,
981 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
982 CHKERR PetscOptionsEList("-symm", "symmetric variant", "", list_symm, 2,
983 list_symm[choice_symm], &choice_symm, PETSC_NULLPTR);
984
985 CHKERR PetscOptionsScalar("-exponent_base", "exponent_base", "", exponentBase,
986 &EshelbianCore::exponentBase, PETSC_NULLPTR);
987 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
988 StretchSelector::STRETCH_SELECTOR_LAST,
989 list_stretches[choice_stretch], &choice_stretch,
990 PETSC_NULLPTR);
991
992 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
993 noStretch, &noStretch, PETSC_NULLPTR);
994 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
995 setSingularity, &setSingularity, PETSC_NULLPTR);
996 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
997 l2UserBaseScale, &l2UserBaseScale, PETSC_NULLPTR);
998
999 // dynamic relaxation
1000
1001 // @deprecate this option
1002 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1003 dynamicRelaxation, &dynamicRelaxation, PETSC_NULLPTR);
1004 CHKERR PetscOptionsEList("-solver_type", "solver type", "", list_solvers,
1005 SolverType::LastSolver, list_solvers[choice_solver],
1006 &choice_solver, PETSC_NULLPTR);
1007
1008 // contact parameters
1009 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1011 PETSC_NULLPTR);
1012 // cohesive interfae
1013 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1014 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1015
1016 // cracking parameters
1017 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1018 &crackingOn, PETSC_NULLPTR);
1019 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1021 PETSC_NULLPTR);
1022 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1023 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1024
1025 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1026 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1027 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1028 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1029 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1030 "", list_release, 2, list_release[choice_release],
1031 &choice_release, PETSC_NULLPTR);
1032 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1034 PETSC_NULLPTR); // backward compatibility
1035 CHKERR PetscOptionsInt(
1036 "-nb_J_integral_contours", "Number of J integral contours", "",
1037 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1038
1039 // internal stress
1040 char tag_name[255] = "";
1041 CHKERR PetscOptionsString("-internal_stress_tag_name",
1042 "internal stress tag name", "", "", tag_name, 255,
1043 PETSC_NULLPTR);
1044 internalStressTagName = string(tag_name);
1045 CHKERR PetscOptionsInt(
1046 "-internal_stress_interp_order", "internal stress interpolation order",
1048 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1050 PETSC_NULLPTR);
1051
1052 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
1053 "-analytical_expr_file",
1054 analytical_expr_file_name, 255, PETSC_NULLPTR);
1055
1056 PetscOptionsEnd();
1057
1059 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1060 "Unsupported internal stress interpolation order %d",
1062 }
1063
1064 if (setSingularity) {
1065 l2UserBaseScale = PETSC_TRUE;
1066 }
1067
1068 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1069 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1070 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1071 EshelbianCore::symmetrySelector = static_cast<SymmetrySelector>(choice_symm);
1073 static_cast<EnergyReleaseSelector>(choice_release);
1074
1076 case StretchSelector::LINEAR:
1083 break;
1084 case StretchSelector::LOG:
1085 if (std::fabs(EshelbianCore::exponentBase - exp(1)) >
1086 std::numeric_limits<float>::epsilon()) {
1093 } else {
1100 }
1101 break;
1102 case StretchSelector::LOG_QUADRATIC:
1106 EshelbianCore::inv_f = [](const double x) {
1108 "No logarithmic quadratic stretch for this case");
1109 return 0;
1110 };
1113 break; // no stretch, do not use stretch functions
1114 default:
1115 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1116 break;
1117 };
1118
1119 if (dynamicRelaxation) {
1120 MOFEM_LOG("EP", Sev::warning)
1121 << "-dynamic_relaxation option is deprecated, use -solver_type "
1122 "dynamic_relaxation instead.";
1123 choice_solver = SolverType::DynamicRelaxation;
1124 }
1125
1126 switch (choice_solver) {
1129 break;
1133 dynamicRelaxation = PETSC_TRUE;
1134 break;
1137 break;
1138 default:
1139 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1140 break;
1141 };
1142
1143 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1144 MOFEM_LOG("EP", Sev::inform)
1145 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1146 MOFEM_LOG("EP", Sev::inform)
1147 << "materialOrder: -material_order " << materialOrder;
1148 MOFEM_LOG("EP", Sev::inform) << "alphaU: -viscosity_alpha_u " << alphaU;
1149 MOFEM_LOG("EP", Sev::inform) << "alphaW: -viscosity_alpha_w " << alphaW;
1150 MOFEM_LOG("EP", Sev::inform)
1151 << "alphaOmega: -viscosity_alpha_omega " << alphaOmega;
1152 MOFEM_LOG("EP", Sev::inform) << "alphaRho: -density_alpha_rho " << alphaRho;
1153 MOFEM_LOG("EP", Sev::inform) << "alphaTau: -alpha_tau " << alphaTau;
1154 MOFEM_LOG("EP", Sev::inform)
1155 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1156 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation "
1157 << list_rots[EshelbianCore::gradApproximator];
1158 MOFEM_LOG("EP", Sev::inform)
1159 << "Symmetry: -symm " << list_symm[EshelbianCore::symmetrySelector];
1160 if (exponentBase != exp(1))
1161 MOFEM_LOG("EP", Sev::inform)
1162 << "Base exponent: -exponent_base " << EshelbianCore::exponentBase;
1163 else
1164 MOFEM_LOG("EP", Sev::inform) << "Base exponent e";
1165 MOFEM_LOG("EP", Sev::inform)
1166 << "Stretch: -stretches " << list_stretches[choice_stretch];
1167 MOFEM_LOG("EP", Sev::inform) << "No stretch: -no_stretch " << (noStretch)
1168 ? "yes"
1169 : "no";
1170
1171 MOFEM_LOG("EP", Sev::inform)
1172 << "Dynamic relaxation: -dynamic_relaxation " << (dynamicRelaxation)
1173 ? "yes"
1174 : "no";
1175 MOFEM_LOG("EP", Sev::inform)
1176 << "Solver type: -solver_type " << list_solvers[choice_solver];
1177 MOFEM_LOG("EP", Sev::inform)
1178 << "Singularity: -set_singularity " << (setSingularity)
1179 ? "yes"
1180 : "no";
1181 MOFEM_LOG("EP", Sev::inform)
1182 << "L2 user base scale: -l2_user_base_scale " << (l2UserBaseScale)
1183 ? "yes"
1184 : "no";
1185
1186 MOFEM_LOG("EP", Sev::inform) << "Cracking on: -cracking_on " << (crackingOn)
1187 ? "yes"
1188 : "no";
1189 MOFEM_LOG("EP", Sev::inform)
1190 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1191 MOFEM_LOG("EP", Sev::inform)
1192 << "Griffith energy: -griffith_energy " << griffithEnergy;
1193 MOFEM_LOG("EP", Sev::inform)
1194 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1195 MOFEM_LOG("EP", Sev::inform)
1196 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1197 MOFEM_LOG("EP", Sev::inform)
1198 << "Energy release variant: -energy_release_variant "
1199 << list_release[EshelbianCore::energyReleaseSelector];
1200 MOFEM_LOG("EP", Sev::inform)
1201 << "Number of J integral contours: -nb_J_integral_contours "
1203 MOFEM_LOG("EP", Sev::inform)
1204 << "Cohesive interface on: -cohesive_interface_on "
1205 << (interfaceCrack == PETSC_TRUE)
1206 ? "yes"
1207 : "no";
1208
1209#ifdef ENABLE_PYTHON_BINDING
1210 auto file_exists = [](std::string myfile) {
1211 std::ifstream file(myfile.c_str());
1212 if (file) {
1213 return true;
1214 }
1215 return false;
1216 };
1217
1218 if (file_exists(analytical_expr_file_name)) {
1219 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1220
1221 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1222 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1223 analytical_expr_file_name);
1224 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1225 } else {
1226 MOFEM_LOG("EP", Sev::warning)
1227 << analytical_expr_file_name << " file NOT found";
1228 }
1229#endif
1230
1231 if (spaceH1Order == -1)
1233
1235}
1236
1239
1240 auto get_tets = [&]() {
1241 Range tets;
1242 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1243 return tets;
1244 };
1245
1246 auto get_tets_skin = [&]() {
1247 Range tets_skin_part;
1248 Skinner skin(&mField.get_moab());
1249 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1250 ParallelComm *pcomm =
1251 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1252 Range tets_skin;
1253 CHKERR pcomm->filter_pstatus(tets_skin_part,
1254 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1255 PSTATUS_NOT, -1, &tets_skin);
1256 return tets_skin;
1257 };
1258
1259 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1260 // That mean, that hybrid field on all faces on which traction is applied,
1261 // on other faces, or enforcing displacements as
1262 // natural boundary condition.
1264 for (auto &v : *bcSpatialTractionVecPtr) {
1265 tets_skin = subtract(tets_skin, v.faces);
1266 }
1268 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1269 tets_skin = subtract(tets_skin, v.faces);
1270 }
1271
1273 for (auto &v : *bcSpatialPressureVecPtr) {
1274 tets_skin = subtract(tets_skin, v.faces);
1275 }
1276
1277 return tets_skin;
1278 };
1279
1280 auto add_blockset = [&](auto block_name, auto &&tets_skin) {
1281 auto crack_faces =
1282 get_range_from_block(mField, "block_name", SPACE_DIM - 1);
1283 tets_skin.merge(crack_faces);
1284 return tets_skin;
1285 };
1286
1287 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1288 auto contact_range =
1289 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1290 tets_skin = subtract(tets_skin, contact_range);
1291 return tets_skin;
1292 };
1293
1294 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1295 Range faces;
1296 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1297 faces, moab::Interface::UNION);
1298 Range trace_faces = subtract(faces, tets_skin);
1299 return trace_faces;
1300 };
1301
1302 auto tets = get_tets();
1303
1304 // remove also contact faces, i.e. that is also kind of hybrid field but
1305 // named but used to enforce contact conditions
1306 auto trace_faces = get_stress_trace_faces(
1307
1308 subtract_blockset("CONTACT",
1309 subtract_boundary_conditions(get_tets_skin()))
1310
1311 );
1312
1313 contactFaces = boost::make_shared<Range>(intersect(
1314 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1316 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1317
1318#ifndef NDEBUG
1319 if (contactFaces->size())
1321 "contact_faces_" +
1322 std::to_string(mField.get_comm_rank()) + ".vtk",
1323 *contactFaces);
1324 if (skeletonFaces->size())
1326 "skeleton_faces_" +
1327 std::to_string(mField.get_comm_rank()) + ".vtk",
1328 *skeletonFaces);
1329#endif
1330
1331 auto add_broken_hdiv_field = [this, meshset](const std::string field_name,
1332 const int order) {
1334
1336
1337 auto get_side_map_hdiv = [&]() {
1338 return std::vector<
1339
1340 std::pair<EntityType,
1342
1343 >>{
1344
1345 {MBTET,
1346 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1347 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1348 dofs_side_map);
1349 }}
1350
1351 };
1352 };
1353
1355 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1357 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1359 };
1360
1361 auto add_l2_field = [this, meshset](const std::string field_name,
1362 const int order, const int dim) {
1365 MB_TAG_DENSE, MF_ZERO);
1367 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1369 };
1370
1371 auto add_h1_field = [this, meshset](const std::string field_name,
1372 const int order, const int dim) {
1375 MB_TAG_DENSE, MF_ZERO);
1377 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1378 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1379 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1380 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1382 };
1383
1384 auto add_l2_field_by_range = [this](const std::string field_name,
1385 const int order, const int dim,
1386 const int field_dim, Range &&r) {
1389 MB_TAG_DENSE, MF_ZERO);
1390 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1394 };
1395
1396 auto add_bubble_field = [this, meshset](const std::string field_name,
1397 const int order, const int dim) {
1399 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1400 MF_ZERO);
1401 // Modify field
1402 auto field_ptr = mField.get_field_structure(field_name);
1403 auto field_order_table =
1404 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1405 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1406 auto get_cgg_bubble_order_tet = [](int p) {
1407 return NBVOLUMETET_CCG_BUBBLE(p);
1408 };
1409 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1410 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1411 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1412 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1414 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1415 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1417 };
1418
1419 auto add_user_l2_field = [this, meshset](const std::string field_name,
1420 const int order, const int dim) {
1422 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1423 MF_ZERO);
1424 // Modify field
1425 auto field_ptr = mField.get_field_structure(field_name);
1426 auto field_order_table =
1427 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1428 auto zero_dofs = [](int p) { return 0; };
1429 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1430 field_order_table[MBVERTEX] = zero_dofs;
1431 field_order_table[MBEDGE] = zero_dofs;
1432 field_order_table[MBTRI] = zero_dofs;
1433 field_order_table[MBTET] = dof_l2_tet;
1435 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1437 };
1438
1439 // spatial fields
1440 CHKERR add_broken_hdiv_field(piolaStress, spaceOrder);
1441 CHKERR add_bubble_field(bubbleField, spaceOrder, 1);
1442 CHKERR add_l2_field(spatialL2Disp, spaceOrder - 1, 3);
1443 CHKERR add_user_l2_field(rotAxis, spaceOrder - 1, 3);
1444 CHKERR add_user_l2_field(stretchTensor, noStretch ? -1 : spaceOrder, 6);
1445
1446 if (!skeletonFaces)
1447 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1448 if (!contactFaces)
1449 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1450
1451 auto get_hybridised_disp = [&]() {
1452 auto faces = *skeletonFaces;
1453 auto skin = subtract_boundary_conditions(get_tets_skin());
1454 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1455 faces.merge(intersect(bc.faces, skin));
1456 }
1457 return faces;
1458 };
1459
1460 CHKERR add_l2_field_by_range(hybridSpatialDisp, spaceOrder - 1, 2, 3,
1461 get_hybridised_disp());
1462 CHKERR add_l2_field_by_range(contactDisp, spaceOrder - 1, 2, 3,
1464
1465 // spatial displacement
1466 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1467 // material positions
1468 CHKERR add_h1_field(materialH1Positions, 2, 3);
1469
1470 // Eshelby stress
1471 // CHKERR add_broken_hdiv_field(eshelbyStress, spaceOrder);
1472 // CHKERR add_l2_field(materialL2Disp, spaceOrder - 1, 3);
1473 // CHKERR add_l2_field_by_range(hybridMaterialDisp, spaceOrder - 1, 2, 3,
1474 // Range(*materialSkeletonFaces));
1475
1477
1479}
1480
1483
1484 Range meshset_ents;
1485 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1486
1487 auto project_ho_geometry = [&](auto field) {
1489 return mField.loop_dofs(field, ent_method);
1490 };
1491 CHKERR project_ho_geometry(materialH1Positions);
1492
1493 auto get_adj_front_edges = [&](auto &front_edges) {
1494 Range front_crack_nodes;
1495 Range crack_front_edges_with_both_nodes_not_at_front;
1496
1497 if (mField.get_comm_rank() == 0) {
1498 auto &moab = mField.get_moab();
1500 moab.get_connectivity(front_edges, front_crack_nodes, true),
1501 "get_connectivity failed");
1502 Range crack_front_edges;
1503 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1504 false, crack_front_edges,
1505 moab::Interface::UNION),
1506 "get_adjacencies failed");
1507 Range crack_front_edges_nodes;
1508 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1509 crack_front_edges_nodes, true),
1510 "get_connectivity failed");
1511 // those nodes are hannging nodes
1512 crack_front_edges_nodes =
1513 subtract(crack_front_edges_nodes, front_crack_nodes);
1514 Range crack_front_edges_with_both_nodes_not_at_front;
1516 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1517 crack_front_edges_with_both_nodes_not_at_front,
1518 moab::Interface::UNION),
1519 "get_adjacencies failed");
1520 // those edges are have one node not at the crack front
1521 crack_front_edges_with_both_nodes_not_at_front = intersect(
1522 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1523 }
1524
1525 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1526 crack_front_edges_with_both_nodes_not_at_front = send_type(
1527 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1528
1529 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1530 boost::make_shared<Range>(
1531 crack_front_edges_with_both_nodes_not_at_front));
1532 };
1533
1534 crackFaces = boost::make_shared<Range>(
1535 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1536 frontEdges =
1537 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1538 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1539 frontVertices = front_vertices;
1540 frontAdjEdges = front_adj_edges;
1541
1542 MOFEM_LOG("EP", Sev::inform)
1543 << "Number of crack faces: " << crackFaces->size();
1544 MOFEM_LOG("EP", Sev::inform)
1545 << "Number of front edges: " << frontEdges->size();
1546 MOFEM_LOG("EP", Sev::inform)
1547 << "Number of front vertices: " << frontVertices->size();
1548 MOFEM_LOG("EP", Sev::inform)
1549 << "Number of front adjacent edges: " << frontAdjEdges->size();
1550
1551#ifndef NDEBUG
1552 if (crackingOn) {
1553 auto rank = mField.get_comm_rank();
1554 // CHKERR save_range(mField.get_moab(),
1555 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1556 // meshset_ents);
1558 (boost::format("crack_faces_%d.vtk") % rank).str(),
1559 *crackFaces);
1561 (boost::format("front_edges_%d.vtk") % rank).str(),
1562 *frontEdges);
1563 // CHKERR save_range(mField.get_moab(),
1564 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1565 // *frontVertices);
1566 // CHKERR save_range(mField.get_moab(),
1567 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1568 // *frontAdjEdges);
1569 }
1570#endif // NDEBUG
1571
1572 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1574 auto &moab = mField.get_moab();
1575
1576 double eps = 1;
1577 double beta = 0;
1578 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1579 PETSC_NULLPTR);
1580 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1581 eps -= beta;
1582
1583 auto field_blas = mField.getInterface<FieldBlas>();
1584 auto lambda =
1585 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1587 FTENSOR_INDEX(3, i);
1588 FTENSOR_INDEX(3, j);
1589
1590 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1591 if (nb_dofs == 0) {
1593 }
1594
1595#ifndef NDEBUG
1596 if (field_entity_ptr->getNbOfCoeffs() != 3)
1598 "Expected 3 coefficients per edge");
1599 if (nb_dofs % 3 != 0)
1601 "Expected multiple of 3 coefficients per edge");
1602#endif // NDEBUG
1603
1604 auto get_conn = [&]() {
1605 int num_nodes;
1606 const EntityHandle *conn;
1607 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1608 num_nodes, false);
1609 return std::make_pair(conn, num_nodes);
1610 };
1611
1612 auto get_dir = [&](auto &&conn_p) {
1613 auto [conn, num_nodes] = conn_p;
1614 double coords[6];
1615 CHKERR moab.get_coords(conn, num_nodes, coords);
1616 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
1617 coords[4] - coords[1],
1618 coords[5] - coords[2]};
1619 return t_edge_dir;
1620 };
1621
1622 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
1623 auto [conn, num_nodes] = conn_p;
1624 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
1625 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1626 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
1627 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1628 t_singularity_dof(i) = t_edge_dir(i) * eps;
1629 }
1630 return t_singularity_dof;
1631 };
1632
1633 auto t_singularity_dof =
1634 get_singularity_dof(get_conn(), get_dir(get_conn()));
1635
1636 auto field_data = field_entity_ptr->getEntFieldData();
1638 &field_data[0], &field_data[1], &field_data[2]};
1639
1640 t_dof(i) = t_singularity_dof(i);
1641 ++t_dof;
1642 for (auto n = 1; n < field_data.size() / 3; ++n) {
1643 t_dof(i) = 0;
1644 ++t_dof;
1645 }
1646
1648 };
1649
1650 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
1651 &front_adj_edges);
1652
1654 };
1655
1656 if (setSingularity)
1657 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
1658
1659 interfaceFaces = boost::make_shared<Range>(
1660 get_range_from_block(mField, "INTERFACE", SPACE_DIM - 1));
1661 MOFEM_LOG("EP", Sev::inform)
1662 << "Number of interface elements: " << interfaceFaces->size();
1663
1664 auto get_interface_from_block = [&](auto block_name) {
1665 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
1666 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
1667 Range faces;
1668 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
1669 faces, moab::Interface::UNION);
1670 faces = subtract(faces, skin);
1671 MOFEM_LOG("EP", Sev::inform)
1672 << "Number of vol interface elements: " << vol_eles.size()
1673 << " and faces: " << faces.size();
1674 return faces;
1675 };
1676
1677 interfaceFaces->merge(get_interface_from_block("VOLUME_INTERFACE"));
1678
1680}
1681
1685#ifdef INCLUDE_MBCOUPLER
1686
1687 char mesh_source_file[255] = "source.h5m";
1688 char iterp_tag_name[255] = "INTERNAL_STRESS";
1689
1690 int interp_order = 1;
1691 PetscBool hybrid_interp = PETSC_TRUE;
1692 PetscBool project_internal_stress = PETSC_FALSE;
1693
1694 double toler = 5.e-10;
1695 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1696 "none");
1697 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1698 "source.h5m", mesh_source_file, 255,
1699 &project_internal_stress);
1700 CHKERR PetscOptionsString("-interp_tag", "interpolation tag name", "",
1701 "INTERNAL_STRESS", iterp_tag_name, 255,
1702 PETSC_NULLPTR);
1703 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1704 &interp_order, PETSC_NULLPTR);
1705 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1706 hybrid_interp, &hybrid_interp, PETSC_NULLPTR);
1707 PetscOptionsEnd();
1708
1709 MOFEM_LOG_CHANNEL("WORLD");
1710 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
1711 if (!project_internal_stress) {
1712 MOFEM_LOG("WORLD", Sev::inform)
1713 << "No internal stress source mesh specified. Skipping projection of "
1714 "internal stress";
1716 }
1717 MOFEM_LOG("WORLD", Sev::inform)
1718 << "Projecting internal stress from source mesh: " << mesh_source_file;
1719
1720 auto &moab = mField.get_moab();
1721
1722 // check if tag exists
1723 Tag old_interp_tag;
1724 auto rval_check_tag = moab.tag_get_handle(iterp_tag_name, old_interp_tag);
1725 if (rval_check_tag == MB_SUCCESS) {
1726 MOFEM_LOG("WORLD", Sev::inform)
1727 << "Deleting existing tag on target mesh: " << iterp_tag_name;
1728 CHKERR moab.tag_delete(old_interp_tag);
1729 }
1730
1731 // make a size-1 communicator for the coupler (rank 0 only)
1732 int world_rank = -1, world_size = -1;
1733 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
1734 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
1735
1736 Range original_meshset_ents;
1737 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
1738
1739 MPI_Comm comm_coupler;
1740 if (world_rank == 0) {
1741 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
1742 } else {
1743 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
1744 }
1745
1746 // build a separate ParallelComm for the coupler (rank 0 only)
1747 ParallelComm *pcomm0 = nullptr;
1748 int pcomm0_id = -1;
1749 if (world_rank == 0) {
1750 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
1751 }
1752
1753 Coupler::Method method;
1754 switch (interp_order) {
1755 case 0:
1756 method = Coupler::CONSTANT;
1757 break;
1758 case 1:
1759 method = Coupler::LINEAR_FE;
1760 break;
1761 default:
1762 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1763 "Unsupported interpolation order");
1764 }
1765
1766 int nprocs, rank;
1767 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
1768 CHKERRQ(ierr);
1769 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1770 CHKERRQ(ierr);
1771
1772 // std::string read_opts, write_opts;
1773 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
1774 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
1775 // if (world_size > 1)
1776 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
1777 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
1778
1779 // create target mesh from existing meshset
1780 EntityHandle target_root;
1781 CHKERR moab.create_meshset(MESHSET_SET, target_root);
1782 MOFEM_LOG("WORLD", Sev::inform)
1783 << "Creating target mesh from existing meshset";
1784 Range target_meshset_ents;
1785 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
1786 CHKERR moab.add_entities(target_root, target_meshset_ents);
1787
1788 // variables for tags to be broadcast later
1789 int tag_length;
1790 DataType dtype;
1791 TagType storage;
1792
1793 // load source mesh
1794 Range targ_verts, targ_elems;
1795 if (world_rank == 0) {
1796
1797 EntityHandle source_root;
1798 CHKERR moab.create_meshset(MESHSET_SET, source_root);
1799
1800 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
1801 auto rval_source_mesh = moab.load_file(mesh_source_file, &source_root, "");
1802 if (rval_source_mesh != MB_SUCCESS) {
1803 MOFEM_LOG("WORLD", Sev::warning)
1804 << "Error loading source mesh file: " << mesh_source_file;
1805 }
1806 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
1807
1808 Range src_elems;
1809 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
1810
1811 EntityHandle part_set;
1812 CHKERR pcomm0->create_part(part_set);
1813 CHKERR moab.add_entities(part_set, src_elems);
1814
1815 Range src_elems_part;
1816 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
1817
1818 Tag interp_tag;
1819 CHKERR moab.tag_get_handle(iterp_tag_name, interp_tag);
1820
1821 int interp_tag_len;
1822 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
1823
1824 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
1825 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1826 "Unsupported interpolation tag length: %d", interp_tag_len);
1827 }
1828
1829 // store tag info for later broadcast
1830 tag_length = interp_tag_len;
1831 CHKERR moab.tag_get_data_type(interp_tag, dtype);
1832 CHKERR moab.tag_get_type(interp_tag, storage);
1833
1834 // coupler is collective
1835 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
1836
1837 std::vector<double> vpos; // the positions we are interested in
1838 int num_pts = 0;
1839
1840 Range tmp_verts;
1841
1842 // First get all vertices adj to partition entities in target mesh
1843 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
1844
1845 if (interp_order == 0) {
1846 targ_verts = targ_elems;
1847 } else {
1848 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
1849 moab::Interface::UNION);
1850 }
1851
1852 // Then get non-owned verts and subtract
1853 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
1854 targ_verts = subtract(targ_verts, tmp_verts);
1855
1856 // get position of these entities; these are the target points
1857 num_pts = (int)targ_verts.size();
1858 vpos.resize(3 * targ_verts.size());
1859 CHKERR moab.get_coords(targ_verts, &vpos[0]);
1860
1861 // Locate those points in the source mesh
1862 boost::shared_ptr<TupleList> tl_ptr;
1863 tl_ptr = boost::make_shared<TupleList>();
1864 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(), false);
1865
1866 // If some points were not located, we need to process them
1867 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
1868 std::vector<double> &vpos,
1869 Range &missing_verts) {
1871 int missing_pts_num = 0;
1872 int i = 0;
1873 auto vit = targ_verts.begin();
1874 for (; vit != targ_verts.end(); i++) {
1875 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
1876 missing_verts.insert(*vit);
1877 vit = targ_verts.erase(vit);
1878 missing_pts_num++;
1879 } else {
1880 vit++;
1881 }
1882 }
1883
1884 int missing_pts_num_global = 0;
1885 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
1886 // MPI_SUM, pcomm0);
1887 if (missing_pts_num_global) {
1888 MOFEM_LOG("WORLD", Sev::warning)
1889 << missing_pts_num_global
1890 << " points in target mesh were not located in source mesh. ";
1891 }
1892
1893 if (missing_pts_num) {
1894 num_pts = (int)targ_verts.size();
1895 vpos.resize(3 * targ_verts.size());
1896 CHKERR moab.get_coords(targ_verts, &vpos[0]);
1897 tl_ptr->reset();
1898 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
1899 false);
1900 }
1902 };
1903
1904 Range missing_verts;
1905 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
1906
1907 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
1908 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
1909
1910 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
1911
1912 Tag scalar_tag, adj_count_tag;
1913 double def_scl = 0;
1914 string scalar_tag_name = string(iterp_tag_name) + "_COMP";
1915 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
1916 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
1917 &def_scl);
1918
1919 string adj_count_tag_name = "ADJ_COUNT";
1920 double def_adj = 0;
1921 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
1922 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
1923 &def_adj);
1924
1925 // MBCoupler functionality supports only scalar tags. For the case of
1926 // vector or tensor tags we need to save each component as a scalar tag
1927 auto create_scalar_tags = [&](const Range &src_elems,
1928 const std::vector<double> &source_data,
1929 int itag) {
1931
1932 std::vector<double> source_data_scalar(src_elems.size());
1933 // Populate source_data_scalar
1934 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
1935 source_data_scalar[ielem] = source_data[itag + ielem * interp_tag_len];
1936 }
1937
1938 // Set data on the scalar tag
1939 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
1940
1941 if (interp_order == 1) {
1942 // Linear interpolation: compute average value of data on vertices
1943 Range src_verts;
1944 CHKERR moab.get_connectivity(src_elems, src_verts, true);
1945
1946 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
1947 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
1948
1949 for (auto &tet : src_elems) {
1950 double tet_data = 0;
1951 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
1952
1953 Range adj_verts;
1954 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
1955
1956 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
1957 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
1958
1959 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
1960 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
1961 &adj_vert_count[0]);
1962
1963 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
1964 adj_vert_data[ivert] += tet_data;
1965 adj_vert_count[ivert] += 1;
1966 }
1967
1968 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
1969 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
1970 &adj_vert_count[0]);
1971 }
1972
1973 // Reduce tags for the parallel case
1974 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
1975 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
1976
1977 std::vector<double> src_vert_data(src_verts.size(), 0.0);
1978 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
1979
1980 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
1981 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
1982 &src_vert_adj_count[0]);
1983
1984 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
1985 src_vert_data[ivert] /= src_vert_adj_count[ivert];
1986 }
1987 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
1988 }
1990 };
1991
1992 for (int itag = 0; itag < interp_tag_len; itag++) {
1993
1994 CHKERR create_scalar_tags(src_elems, source_data, itag);
1995
1996 std::vector<double> target_data_scalar(num_pts, 0.0);
1997 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
1998 tl_ptr.get());
1999
2000 for (int ielem = 0; ielem < num_pts; ielem++) {
2001 target_data[itag + ielem * interp_tag_len] = target_data_scalar[ielem];
2002 }
2003 }
2004
2005 // Use original tag
2006 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2007
2008 if (missing_verts.size() && (interp_order == 1) && hybrid_interp) {
2009 MOFEM_LOG("WORLD", Sev::warning) << "Using hybrid interpolation for "
2010 "missing points in the target mesh.";
2011 Range missing_adj_elems;
2012 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2013 moab::Interface::UNION);
2014
2015 int num_adj_elems = (int)missing_adj_elems.size();
2016 std::vector<double> vpos_adj_elems;
2017
2018 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2019 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2020
2021 // Locate those points in the source mesh
2022 tl_ptr->reset();
2023 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2024 tl_ptr.get(), false);
2025
2026 Range missing_tets;
2027 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2028 vpos_adj_elems, missing_tets);
2029 if (missing_tets.size()) {
2030 MOFEM_LOG("WORLD", Sev::warning)
2031 << missing_tets.size()
2032 << "points in target mesh were not located in source mesh. ";
2033 }
2034
2035 std::vector<double> target_data_adj_elems(interp_tag_len * num_adj_elems,
2036 0.0);
2037
2038 for (int itag = 0; itag < interp_tag_len; itag++) {
2039 CHKERR create_scalar_tags(src_elems, source_data, itag);
2040
2041 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2042 CHKERR mbc.interpolate(method, scalar_tag_name,
2043 &target_data_adj_elems_scalar[0], tl_ptr.get());
2044
2045 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2046 target_data_adj_elems[itag + ielem * interp_tag_len] =
2047 target_data_adj_elems_scalar[ielem];
2048 }
2049 }
2050
2051 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2052 &target_data_adj_elems[0]);
2053
2054 // FIXME: add implementation for parallel case
2055 for (auto &vert : missing_verts) {
2056 Range adj_elems;
2057 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2058 moab::Interface::UNION);
2059
2060 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2061 0.0);
2062 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2063
2064 std::vector<double> vert_data(interp_tag_len, 0.0);
2065 for (int itag = 0; itag < interp_tag_len; itag++) {
2066 for (int i = 0; i < adj_elems.size(); i++) {
2067 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2068 }
2069 vert_data[itag] /= adj_elems.size();
2070 }
2071 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2072 }
2073 }
2074
2075 CHKERR moab.tag_delete(scalar_tag);
2076 CHKERR moab.tag_delete(adj_count_tag);
2077 // delete source mesh
2078 Range src_mesh_ents;
2079 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2080 CHKERR moab.delete_entities(&source_root, 1);
2081 CHKERR moab.delete_entities(src_mesh_ents);
2082 CHKERR moab.delete_entities(&part_set, 1);
2083 }
2084
2085 // broadcast tag info to other processors
2086 MPI_Bcast(&tag_length, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2087 MPI_Bcast(&dtype, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2088 MPI_Bcast(&storage, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2089
2090 // create tag on other processors
2091 Tag interp_tag_all;
2092 unsigned flags =
2093 MB_TAG_CREAT | storage; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2094 std::vector<double> def_val(tag_length, 0.);
2095 CHKERR moab.tag_get_handle(iterp_tag_name, tag_length, dtype, interp_tag_all,
2096 flags, def_val.data());
2097 MPI_Barrier(PETSC_COMM_WORLD);
2098
2099 // exchange data for all entity types across all processors
2100 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2101 mField.get_comm(), mField.get_moab(), 0, tag_length, Sev::inform);
2102 auto edge_exchange = CommInterface::createEntitiesPetscVector(
2103 mField.get_comm(), mField.get_moab(), 1, tag_length, Sev::inform);
2104 auto face_exchange = CommInterface::createEntitiesPetscVector(
2105 mField.get_comm(), mField.get_moab(), 2, tag_length, Sev::inform);
2106 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2107 mField.get_comm(), mField.get_moab(), 3, tag_length, Sev::inform);
2108
2110 mField.get_moab(), vertex_exchange, interp_tag_all);
2112 mField.get_moab(), edge_exchange, interp_tag_all);
2114 mField.get_moab(), face_exchange, interp_tag_all);
2116 mField.get_moab(), volume_exchange, interp_tag_all);
2117
2118 // delete target meshset but not the entities
2119 CHKERR moab.delete_entities(&target_root, 1);
2120
2121#endif // INCLUDE_MBCOUPLER
2123}
2124
2128
2129 // set finite element fields
2130 auto add_field_to_fe = [this](const std::string fe,
2131 const std::string field_name) {
2137 };
2138
2143
2144 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2145 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2146 if (!noStretch)
2147 CHKERR add_field_to_fe(elementVolumeName, stretchTensor);
2148 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2149 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2150 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2151 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2154
2155 // build finite elements data structures
2157 }
2158
2160}
2161
2165
2166 Range meshset_ents;
2167 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2168
2169 auto set_fe_adjacency = [&](auto fe_name) {
2172 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2175 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2177 };
2178
2179 // set finite element fields
2180 auto add_field_to_fe = [this](const std::string fe,
2181 const std::string field_name) {
2188 };
2189
2191
2192 Range natural_bc_elements;
2193 if (bcSpatialDispVecPtr) {
2194 for (auto &v : *bcSpatialDispVecPtr) {
2195 natural_bc_elements.merge(v.faces);
2196 }
2197 }
2199 for (auto &v : *bcSpatialRotationVecPtr) {
2200 natural_bc_elements.merge(v.faces);
2201 }
2202 }
2204 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2205 natural_bc_elements.merge(v.faces);
2206 }
2207 }
2210 natural_bc_elements.merge(v.faces);
2211 }
2212 }
2214 for (auto &v : *bcSpatialTractionVecPtr) {
2215 natural_bc_elements.merge(v.faces);
2216 }
2217 }
2219 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2220 natural_bc_elements.merge(v.faces);
2221 }
2222 }
2224 for (auto &v : *bcSpatialPressureVecPtr) {
2225 natural_bc_elements.merge(v.faces);
2226 }
2227 }
2228 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2229
2231 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2233 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2234 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2235 CHKERR set_fe_adjacency(naturalBcElement);
2237 }
2238
2239 auto get_skin = [&](auto &body_ents) {
2240 Skinner skin(&mField.get_moab());
2241 Range skin_ents;
2242 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2243 return skin_ents;
2244 };
2245
2246 auto filter_true_skin = [&](auto &&skin) {
2247 Range boundary_ents;
2248 ParallelComm *pcomm =
2249 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2250 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2251 PSTATUS_NOT, -1, &boundary_ents);
2252 return boundary_ents;
2253 };
2254
2256
2257 Range body_ents;
2258 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2259 body_ents);
2260 auto skin = filter_true_skin(get_skin(body_ents));
2261
2269 contactDisp);
2272
2274 }
2275
2277 if (contactFaces) {
2278 MOFEM_LOG("EP", Sev::inform)
2279 << "Contact elements " << contactFaces->size();
2283 CHKERR add_field_to_fe(contactElement, piolaStress);
2284 CHKERR add_field_to_fe(contactElement, contactDisp);
2285 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2286 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2287 CHKERR set_fe_adjacency(contactElement);
2289 }
2290 }
2291
2293 if (!skeletonFaces)
2294 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2295 MOFEM_LOG("EP", Sev::inform)
2296 << "Skeleton elements " << skeletonFaces->size();
2300 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2301 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2302 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2303 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2304 CHKERR set_fe_adjacency(skeletonElement);
2306 }
2307
2309}
2310
2312 const EntityHandle meshset) {
2314
2315 // find adjacencies between finite elements and dofs
2317
2318 // Create coupled problem
2319 dM = createDM(mField.get_comm(), "DMMOFEM");
2320 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2321 BitRefLevel().set());
2322 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2323 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2329
2330 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2331 CHKERR DMSetUp(dM);
2332 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2333
2334 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2336 for (int d : {0, 1, 2}) {
2337 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2339 ->getSideDofsOnBrokenSpaceEntities(
2340 dofs_to_remove, prb_name, ROW, piolaStress,
2342 // remove piola dofs, i.e. traction free boundary
2343 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2344 dofs_to_remove);
2345 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2346 dofs_to_remove);
2347 }
2349 };
2350 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2351
2352 // Create elastic sub-problem
2353 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2354 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2360 if (!noStretch) {
2362 }
2372 CHKERR DMSetUp(dmElastic);
2373
2374 // dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2375 // CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2376 // CHKERR DMMoFEMSetDestroyProblem(dmMaterial, PETSC_TRUE);
2377 // CHKERR DMMoFEMAddSubFieldRow(dmMaterial, eshelbyStress);
2378 // CHKERR DMMoFEMAddSubFieldRow(dmMaterial, materialL2Disp);
2379 // CHKERR DMMoFEMAddElement(dmMaterh elementVolumeName);
2380 // CHKERR DMMoFEMAddElement(dmMaterial, naturalBcElement);
2381 // CHKERR DMMoFEMAddElement(dmMaterial, skinElement);
2382 // CHKERR DMMoFEMSetSquareProblem(dmMaterial, PETSC_TRUE);
2383 // CHKERR DMMoFEMSetIsPartitioned(dmMaterial, PETSC_TRUE);
2384 // CHKERR DMSetUp(dmMaterial);
2385
2386 auto set_zero_block = [&]() {
2388 if (!noStretch) {
2389 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2390 "ELASTIC_PROBLEM", spatialL2Disp, stretchTensor);
2391 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2392 "ELASTIC_PROBLEM", stretchTensor, spatialL2Disp);
2393 }
2394 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2395 "ELASTIC_PROBLEM", spatialL2Disp, rotAxis);
2396 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2397 "ELASTIC_PROBLEM", rotAxis, spatialL2Disp);
2398 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2399 "ELASTIC_PROBLEM", spatialL2Disp, bubbleField);
2400 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2401 "ELASTIC_PROBLEM", bubbleField, spatialL2Disp);
2402 if (!noStretch) {
2403 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2404 "ELASTIC_PROBLEM", bubbleField, bubbleField);
2405 CHKERR
2406 mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2407 "ELASTIC_PROBLEM", piolaStress, piolaStress);
2408 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2409 "ELASTIC_PROBLEM", bubbleField, piolaStress);
2410 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2411 "ELASTIC_PROBLEM", piolaStress, bubbleField);
2412 }
2413
2416 };
2417
2418 auto set_section = [&]() {
2420 PetscSection section;
2421 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2422 &section);
2423 CHKERR DMSetSection(dmElastic, section);
2424 CHKERR DMSetGlobalSection(dmElastic, section);
2425 CHKERR PetscSectionDestroy(&section);
2427 };
2428
2429 CHKERR set_zero_block();
2430 CHKERR set_section();
2431
2432 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2433 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2439 CHKERR DMSetUp(dmPrjSpatial);
2440
2441 // CHKERR mField.getInterface<BcManager>()
2442 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2443 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2444
2446}
2447
2448BcDisp::BcDisp(std::string name, std::vector<double> attr, Range faces)
2449 : blockName(name), faces(faces) {
2450 vals.resize(3, false);
2451 flags.resize(3, false);
2452 for (int ii = 0; ii != 3; ++ii) {
2453 vals[ii] = attr[ii];
2454 flags[ii] = static_cast<int>(attr[ii + 3]);
2455 }
2456
2457 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp " << name;
2458 MOFEM_LOG("EP", Sev::inform)
2459 << "Add BCDisp vals " << vals[0] << " " << vals[1] << " " << vals[2];
2460 MOFEM_LOG("EP", Sev::inform)
2461 << "Add BCDisp flags " << flags[0] << " " << flags[1] << " " << flags[2];
2462 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp nb. of faces " << faces.size();
2463}
2464
2465BcRot::BcRot(std::string name, std::vector<double> attr, Range faces)
2466 : blockName(name), faces(faces) {
2467 vals.resize(attr.size(), false);
2468 for (int ii = 0; ii != attr.size(); ++ii) {
2469 vals[ii] = attr[ii];
2470 }
2471 theta = attr[3];
2472}
2473
2474TractionBc::TractionBc(std::string name, std::vector<double> attr, Range faces)
2475 : blockName(name), faces(faces) {
2476 vals.resize(3, false);
2477 flags.resize(3, false);
2478 for (int ii = 0; ii != 3; ++ii) {
2479 vals[ii] = attr[ii];
2480 flags[ii] = static_cast<int>(attr[ii + 3]);
2481 }
2482
2483 MOFEM_LOG("EP", Sev::inform) << "Add BCForce " << name;
2484 MOFEM_LOG("EP", Sev::inform)
2485 << "Add BCForce vals " << vals[0] << " " << vals[1] << " " << vals[2];
2486 MOFEM_LOG("EP", Sev::inform)
2487 << "Add BCForce flags " << flags[0] << " " << flags[1] << " " << flags[2];
2488 MOFEM_LOG("EP", Sev::inform) << "Add BCForce nb. of faces " << faces.size();
2489}
2490
2492 std::vector<double> attr,
2493 Range faces)
2494 : blockName(name), faces(faces) {
2495
2496 blockName = name;
2497 if (attr.size() < 1) {
2499 "Wrong size of normal displacement BC");
2500 }
2501
2502 val = attr[0];
2503
2504 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc " << name;
2505 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc val " << val;
2506 MOFEM_LOG("EP", Sev::inform)
2507 << "Add NormalDisplacementBc nb. of faces " << faces.size();
2508}
2509
2510PressureBc::PressureBc(std::string name, std::vector<double> attr, Range faces)
2511 : blockName(name), faces(faces) {
2512
2513 blockName = name;
2514 if (attr.size() < 1) {
2516 "Wrong size of normal displacement BC");
2517 }
2518
2519 val = attr[0];
2520
2521 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc " << name;
2522 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc val " << val;
2523 MOFEM_LOG("EP", Sev::inform)
2524 << "Add PressureBc nb. of faces " << faces.size();
2525}
2526
2527ExternalStrain::ExternalStrain(std::string name, std::vector<double> attr,
2528 Range ents)
2529 : blockName(name), ents(ents) {
2530
2531 blockName = name;
2532 if (attr.size() < 2) {
2534 "Wrong size of external strain attribute");
2535 }
2536
2537 val = attr[0];
2538 bulkModulusK = attr[1];
2539
2540 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain " << name;
2541 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain val " << val;
2542 MOFEM_LOG("EP", Sev::inform)
2543 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2544 MOFEM_LOG("EP", Sev::inform)
2545 << "Add ExternalStrain nb. of tets " << ents.size();
2546}
2547
2549 std::vector<double> attr,
2550 Range faces)
2551 : blockName(name), faces(faces) {
2552
2553 blockName = name;
2554 if (attr.size() < 3) {
2556 "Wrong size of analytical displacement BC");
2557 }
2558
2559 flags.resize(3, false);
2560 for (int ii = 0; ii != 3; ++ii) {
2561 flags[ii] = attr[ii];
2562 }
2563
2564 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalDisplacementBc " << name;
2565 MOFEM_LOG("EP", Sev::inform)
2566 << "Add AnalyticalDisplacementBc flags " << flags[0] << " " << flags[1]
2567 << " " << flags[2];
2568 MOFEM_LOG("EP", Sev::inform)
2569 << "Add AnalyticalDisplacementBc nb. of faces " << faces.size();
2570}
2571
2573 std::vector<double> attr,
2574 Range faces)
2575 : blockName(name), faces(faces) {
2576
2577 blockName = name;
2578 if (attr.size() < 3) {
2580 "Wrong size of analytical traction BC");
2581 }
2582
2583 flags.resize(3, false);
2584 for (int ii = 0; ii != 3; ++ii) {
2585 flags[ii] = attr[ii];
2586 }
2587
2588 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc " << name;
2589 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc flags " << flags[0]
2590 << " " << flags[1] << " " << flags[2];
2591 MOFEM_LOG("EP", Sev::inform)
2592 << "Add AnalyticalTractionBc nb. of faces " << faces.size();
2593}
2594
2597 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2598 const std::string contact_set_name) {
2600
2601 // get skin from all tets
2602 Range tets;
2603 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2604 Range tets_skin_part;
2605 Skinner skin(&mField.get_moab());
2606 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
2607 ParallelComm *pcomm =
2608 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2609 Range tets_skin;
2610 CHKERR pcomm->filter_pstatus(tets_skin_part,
2611 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2612 PSTATUS_NOT, -1, &tets_skin);
2613
2614 bc_ptr->resize(3);
2615 for (int dd = 0; dd != 3; ++dd)
2616 (*bc_ptr)[dd] = tets_skin;
2617
2618 // Do not remove dofs on which traction is applied
2619 if (bcSpatialDispVecPtr)
2620 for (auto &v : *bcSpatialDispVecPtr) {
2621 if (v.flags[0])
2622 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2623 if (v.flags[1])
2624 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2625 if (v.flags[2])
2626 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2627 }
2628
2629 // Do not remove dofs on which rotation is applied
2630 if (bcSpatialRotationVecPtr)
2631 for (auto &v : *bcSpatialRotationVecPtr) {
2632 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2633 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2634 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2635 }
2636
2637 if (bcSpatialNormalDisplacementVecPtr)
2638 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2639 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2640 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2641 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2642 }
2643
2644 if (bcSpatialAnalyticalDisplacementVecPtr)
2645 for (auto &v : *bcSpatialAnalyticalDisplacementVecPtr) {
2646 if (v.flags[0])
2647 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2648 if (v.flags[1])
2649 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2650 if (v.flags[2])
2651 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2652 }
2653
2654 if (bcSpatialTractionVecPtr)
2655 for (auto &v : *bcSpatialTractionVecPtr) {
2656 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2657 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2658 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2659 }
2660
2661 if (bcSpatialAnalyticalTractionVecPtr)
2662 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2663 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2664 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2665 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2666 }
2667
2668 if (bcSpatialPressureVecPtr)
2669 for (auto &v : *bcSpatialPressureVecPtr) {
2670 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2671 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2672 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2673 }
2674
2675 // remove contact
2676 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
2677 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
2678 Range faces;
2679 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2680 true);
2681 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2682 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2683 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2684 }
2685
2687}
2688
2689/**
2690 * @brief Set integration rule on element
2691 * \param order on row
2692 * \param order on column
2693 * \param order on data
2694 *
2695 * Use maximal oder on data in order to determine integration rule
2696 *
2697 */
2698struct VolRule {
2699 int operator()(int p_row, int p_col, int p_data) const {
2700 return 2 * p_data + 1;
2701 }
2702};
2703
2704struct FaceRule {
2705 int operator()(int p_row, int p_col, int p_data) const {
2706 return 2 * (p_data + 1);
2707 }
2708};
2709
2711 const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates,
2712 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe) {
2714
2715 auto bubble_cache =
2716 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
2717 fe->getUserPolynomialBase() =
2718 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2719 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2720 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2721
2722 // set integration rule
2723 fe->getRuleHook = [](int, int, int) { return -1; };
2724 auto vol_rule_lin = [](int o) { return 2 * o + 1; };
2725 auto vol_rule_no_lin = [](int o) { return 2 * o + (o - 1) + 1; };
2726 auto vol_rule = (SMALL_ROT > 0) ? vol_rule_lin : vol_rule_no_lin;
2727 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
2728 vol_rule, bubble_cache);
2729 // fe->getRuleHook = VolRule();
2730
2731 if (!dataAtPts) {
2732 dataAtPts =
2733 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
2734 dataAtPts->physicsPtr = physicalEquations;
2735 }
2736
2737 // calculate fields values
2738 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
2739 piolaStress, dataAtPts->getApproxPAtPts()));
2740 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
2741 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2742 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
2743 piolaStress, dataAtPts->getDivPAtPts()));
2744
2745 if (noStretch) {
2746 fe->getOpPtrVector().push_back(
2747 physicalEquations->returnOpCalculateStretchFromStress(
2748 dataAtPts, physicalEquations));
2749 } else {
2750 fe->getOpPtrVector().push_back(
2752 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2753 }
2754
2755 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2756 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
2757 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2758 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
2759 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2760 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
2761
2762 // H1 displacements
2763 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2764 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
2765 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
2766 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
2767
2768 // velocities
2769 if (calc_rates) {
2770 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
2771 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
2772 if (noStretch) {
2773 } else {
2774 fe->getOpPtrVector().push_back(
2776 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
2777 fe->getOpPtrVector().push_back(
2779 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
2780 MBTET));
2781 }
2782 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
2783 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
2784 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
2785 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
2786
2787 // acceleration
2788 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
2789 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
2790 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
2791 }
2792 }
2793
2794 // calculate other derived quantities
2795 fe->getOpPtrVector().push_back(new OpCalculateRotationAndSpatialGradient(
2796 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
2797
2798 // evaluate integration points
2799 if (noStretch) {
2800 } else {
2801 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
2802 tag, do_rhs, do_lhs, dataAtPts, physicalEquations));
2803 }
2804
2806}
2807
2809 const int tag, const bool add_elastic, const bool add_material,
2810 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
2811 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
2813
2814 /** Contact requires that body is marked */
2815 auto get_body_range = [this](auto name, int dim) {
2816 std::map<int, Range> map;
2817
2818 for (auto m_ptr :
2819 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2820
2821 (boost::format("%s(.*)") % name).str()
2822
2823 ))
2824
2825 ) {
2826 Range ents;
2827 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
2828 dim, ents, true),
2829 "by dim");
2830 map[m_ptr->getMeshsetId()] = ents;
2831 }
2832
2833 return map;
2834 };
2835
2836 constexpr bool stab_tau_dot_variant = false;
2837
2838 auto local_tau_sacale = boost::make_shared<double>(1.0);
2839 using BoundaryEle =
2841 using BdyEleOp = BoundaryEle::UserDataOperator;
2842 auto set_scale_op = new BdyEleOp(NOSPACE, BdyEleOp::OPSPACE);
2843 set_scale_op->doWorkRhsHook =
2844 [this,
2845 local_tau_sacale](DataOperator *raw_op_ptr, int side, EntityType type,
2848 auto op_ptr = static_cast<BdyEleOp *>(raw_op_ptr);
2849 auto h = std::sqrt(op_ptr->getFTensor1Normal().l2());
2850 *local_tau_sacale = (alphaTau / h);
2852 };
2853
2854 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
2855 auto ent = fe_method_ptr->getFEEntityHandle();
2856 if (
2857
2858 (interfaceFaces->find(ent) != interfaceFaces->end())
2859
2860 || (crackFaces->find(ent) != crackFaces->end())
2861
2862 ) {
2863 return false;
2864 };
2865 return true;
2866 };
2867
2868 // Right hand side
2869 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2870 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
2871
2872 // elastic
2873 if (add_elastic) {
2874
2875 fe_rhs->getOpPtrVector().push_back(
2876 new OpSpatialEquilibrium(spatialL2Disp, dataAtPts, alphaW, alphaRho));
2877 fe_rhs->getOpPtrVector().push_back(
2878 new OpSpatialRotation(rotAxis, dataAtPts, alphaOmega));
2879 if (noStretch) {
2880 // do nothing - no stretch approximation
2881 } else {
2882 if (!internalStressTagName.empty()) {
2883 switch (internalStressInterpOrder) {
2884 case 0:
2885 fe_rhs->getOpPtrVector().push_back(
2886 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
2887 break;
2888 case 1:
2889 fe_rhs->getOpPtrVector().push_back(
2890 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
2891 break;
2892 default:
2893 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2894 "Unsupported internal stress interpolation order %d",
2895 internalStressInterpOrder);
2896 }
2897 // set default time scaling for interal stresses to constant
2898 TimeScale::ScalingFun def_scaling_fun = [](double time) { return 1; };
2899 auto ts_internal_stress =
2900 boost::make_shared<DynamicRelaxationTimeScale>(
2901 "internal_stress_history.txt", false, def_scaling_fun);
2902 if (internalStressVoigt) {
2903 fe_rhs->getOpPtrVector().push_back(
2905 stretchTensor, dataAtPts, ts_internal_stress));
2906 } else {
2907 fe_rhs->getOpPtrVector().push_back(
2909 stretchTensor, dataAtPts, ts_internal_stress));
2910 }
2911 }
2912 if (auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
2913 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
2914 fe_rhs->getOpPtrVector().push_back(op);
2915 } else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
2916 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2917 "OpSpatialPhysicalExternalStrain not implemented for this "
2918 "material");
2919 }
2920
2921 fe_rhs->getOpPtrVector().push_back(
2922 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
2923 alphaU));
2924 }
2925 fe_rhs->getOpPtrVector().push_back(
2926 new OpSpatialConsistencyP(piolaStress, dataAtPts));
2927 fe_rhs->getOpPtrVector().push_back(
2928 new OpSpatialConsistencyBubble(bubbleField, dataAtPts));
2929 fe_rhs->getOpPtrVector().push_back(
2930 new OpSpatialConsistencyDivTerm(piolaStress, dataAtPts));
2931
2932 auto set_hybridisation_rhs = [&](auto &pip) {
2934
2935 using BoundaryEle =
2937 using EleOnSide =
2939 using SideEleOp = EleOnSide::UserDataOperator;
2940 using BdyEleOp = BoundaryEle::UserDataOperator;
2941
2942 // First: Iterate over skeleton FEs adjacent to Domain FEs
2943 // Note: BoundaryEle, i.e. uses skeleton interation rule
2944 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2945 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
2946 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
2947 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2948 return -1;
2949 };
2950 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2951 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2952
2953 CHKERR EshelbianPlasticity::
2954 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2955 op_loop_skeleton_side->getOpPtrVector(), {L2},
2956 materialH1Positions, frontAdjEdges);
2957
2958 // Second: Iterate over domain FEs adjacent to skelton, particularly one
2959 // domain element.
2960 auto broken_data_ptr =
2961 boost::make_shared<std::vector<BrokenBaseSideData>>();
2962 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2963 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2964 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
2965 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2966 boost::make_shared<CGGUserPolynomialBase>();
2967 CHKERR
2968 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2969 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2970 materialH1Positions, frontAdjEdges);
2971 op_loop_domain_side->getOpPtrVector().push_back(
2972 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
2973 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
2974 op_loop_domain_side->getOpPtrVector().push_back(
2976 flux_mat_ptr));
2977 op_loop_domain_side->getOpPtrVector().push_back(
2978 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
2979
2980 // Assemble on skeleton
2981 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2983 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
2985 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2986 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
2987 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
2988 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2989 op_loop_skeleton_side->getOpPtrVector().push_back(
2990 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
2991 hybrid_ptr));
2992 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
2993 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
2994
2995 // Add skeleton to domain pipeline
2996 pip.push_back(op_loop_skeleton_side);
2997
2999 };
3000
3001 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3002 auto hybrid_field) {
3004
3005 using BoundaryEle =
3007 using EleOnSide =
3009 using SideEleOp = EleOnSide::UserDataOperator;
3010 using BdyEleOp = BoundaryEle::UserDataOperator;
3011
3012 // First: Iterate over skeleton FEs adjacent to Domain FEs
3013 // Note: BoundaryEle, i.e. uses skeleton interation rule
3014 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3015 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3016 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3017 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3018 return -1;
3019 };
3020 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3021 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3022 CHKERR EshelbianPlasticity::
3023 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3024 op_loop_skeleton_side->getOpPtrVector(), {L2},
3025 materialH1Positions, frontAdjEdges);
3026
3027 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3028 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3029 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3030 boost::make_shared<CGGUserPolynomialBase>();
3031 CHKERR
3032 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3033 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3034 materialH1Positions, frontAdjEdges);
3035
3036 // Add stabilization operator
3037 auto broken_disp_data_ptr =
3038 boost::make_shared<std::vector<BrokenBaseSideData>>();
3039 op_loop_domain_side->getOpPtrVector().push_back(
3040 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3041 broken_disp_data_ptr));
3042 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3043 if (stab_tau_dot_variant) {
3044 op_loop_domain_side->getOpPtrVector().push_back(
3046 disp_mat_ptr));
3047 } else {
3048 op_loop_domain_side->getOpPtrVector().push_back(
3050 disp_mat_ptr));
3051 }
3052 // Set diag fluxes on skeleton side
3053 op_loop_domain_side->getOpPtrVector().push_back(
3054 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3055
3056 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3057 op_loop_skeleton_side->getOpPtrVector().push_back(set_scale_op);
3058
3059 // Add stabilization Ugamma Ugamma skeleton
3060 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3061 if (stab_tau_dot_variant) {
3062 op_loop_skeleton_side->getOpPtrVector().push_back(
3064 hybrid_ptr));
3065 } else {
3066 op_loop_skeleton_side->getOpPtrVector().push_back(
3068 hybrid_ptr));
3069 }
3070
3071 // Diag u_gamma - u_gamma faces
3072 op_loop_skeleton_side->getOpPtrVector().push_back(
3074 hybrid_field, hybrid_ptr,
3075 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3076 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3077 }));
3078 // Diag L2 - L2 volumes
3079 op_loop_skeleton_side->getOpPtrVector().push_back(
3081 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3082 return (*local_tau_sacale);
3083 }));
3084 // Off-diag Ugamma - L2
3085 op_loop_skeleton_side->getOpPtrVector().push_back(
3087 hybrid_field, broken_disp_data_ptr,
3088 [local_tau_sacale](double, double, double) {
3089 return -(*local_tau_sacale);
3090 }));
3091 // Off-diag L2 - Ugamma
3092 op_loop_skeleton_side->getOpPtrVector().push_back(
3094 broken_disp_data_ptr, hybrid_ptr,
3095 [local_tau_sacale](double, double, double) {
3096 return -(*local_tau_sacale);
3097 }));
3098
3099 // Add skeleton to domain pipeline
3100 pip.push_back(op_loop_skeleton_side);
3101
3103 };
3104
3105 auto set_contact_rhs = [&](auto &pip) {
3106 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3107 };
3108
3109 auto set_cohesive_rhs = [&](auto &pip) {
3110 return pushCohesiveOpsRhs(
3111 *this,
3112 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges,
3113 [](int p) { return 2 * (p + 1) + 1; }),
3114 interfaceFaces, pip);
3115 };
3116
3117 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3118 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3119 if (alphaTau > 0.0) {
3120 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3121 hybridSpatialDisp);
3122 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), contactElement,
3123 contactDisp);
3124 }
3125 if (interfaceCrack == PETSC_TRUE) {
3126 CHKERR set_cohesive_rhs(fe_rhs->getOpPtrVector());
3127 }
3128
3129 // Body forces
3130 using BodyNaturalBC =
3132 Assembly<PETSC>::LinearForm<GAUSS>;
3133 using OpBodyForce =
3134 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3135
3136 auto body_time_scale =
3137 boost::make_shared<DynamicRelaxationTimeScale>("body_force.txt");
3138 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3139 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3140 "BODY_FORCE", Sev::inform);
3141 }
3142
3143 // Left hand side
3144 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3145 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3146
3147 // elastic
3148 if (add_elastic) {
3149
3150 if (noStretch) {
3151 fe_lhs->getOpPtrVector().push_back(
3152 new OpSpatialConsistency_dP_dP(piolaStress, piolaStress, dataAtPts));
3153 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dP(
3154 bubbleField, piolaStress, dataAtPts));
3155 fe_lhs->getOpPtrVector().push_back(
3156 new OpSpatialConsistency_dBubble_dBubble(bubbleField, bubbleField,
3157 dataAtPts));
3158 } else {
3159 fe_lhs->getOpPtrVector().push_back(
3160 physicalEquations->returnOpSpatialPhysical_du_du(
3161 stretchTensor, stretchTensor, dataAtPts, alphaU));
3162 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dP(
3163 stretchTensor, piolaStress, dataAtPts, true));
3164 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dBubble(
3165 stretchTensor, bubbleField, dataAtPts, true));
3166 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_domega(
3167 stretchTensor, rotAxis, dataAtPts,
3168 symmetrySelector == SYMMETRIC ? true : false));
3169 }
3170
3171 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3172 spatialL2Disp, piolaStress, dataAtPts, true));
3173 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3174 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3175
3176 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3177 piolaStress, rotAxis, dataAtPts,
3178 symmetrySelector == SYMMETRIC ? true : false));
3179 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3180 bubbleField, rotAxis, dataAtPts,
3181 symmetrySelector == SYMMETRIC ? true : false));
3182
3183 if (symmetrySelector > SYMMETRIC) {
3184 if (!noStretch) {
3185 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_du(
3186 rotAxis, stretchTensor, dataAtPts, false));
3187 }
3188 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3189 rotAxis, piolaStress, dataAtPts, false));
3190 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3191 rotAxis, bubbleField, dataAtPts, false));
3192 }
3193 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3194 rotAxis, rotAxis, dataAtPts, alphaOmega));
3195
3196 auto set_hybridisation_lhs = [&](auto &pip) {
3198
3199 using BoundaryEle =
3201 using EleOnSide =
3203 using SideEleOp = EleOnSide::UserDataOperator;
3204 using BdyEleOp = BoundaryEle::UserDataOperator;
3205
3206 // First: Iterate over skeleton FEs adjacent to Domain FEs
3207 // Note: BoundaryEle, i.e. uses skeleton interation rule
3208 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3209 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3210 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3211 return -1;
3212 };
3213 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3214 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3215 CHKERR EshelbianPlasticity::
3216 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3217 op_loop_skeleton_side->getOpPtrVector(), {L2},
3218 materialH1Positions, frontAdjEdges);
3219
3220 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3221 // domain element.
3222 auto broken_data_ptr =
3223 boost::make_shared<std::vector<BrokenBaseSideData>>();
3224 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3225 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3226 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3227 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3228 boost::make_shared<CGGUserPolynomialBase>();
3229 CHKERR
3230 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3231 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3232 materialH1Positions, frontAdjEdges);
3233 op_loop_domain_side->getOpPtrVector().push_back(
3234 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3235
3236 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3238 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3239 op_loop_skeleton_side->getOpPtrVector().push_back(
3240 new OpC(hybridSpatialDisp, broken_data_ptr,
3241 boost::make_shared<double>(1.0), true, false));
3242
3243 pip.push_back(op_loop_skeleton_side);
3244
3246 };
3247
3248 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3249 auto hybrid_field) {
3251
3252 using BoundaryEle =
3254 using EleOnSide =
3256 using SideEleOp = EleOnSide::UserDataOperator;
3257 using BdyEleOp = BoundaryEle::UserDataOperator;
3258
3259 // First: Iterate over skeleton FEs adjacent to Domain FEs
3260 // Note: BoundaryEle, i.e. uses skeleton interation rule
3261 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3262 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3263 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3264 return -1;
3265 };
3266 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3267 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3268 CHKERR EshelbianPlasticity::
3269 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3270 op_loop_skeleton_side->getOpPtrVector(), {L2},
3271 materialH1Positions, frontAdjEdges);
3272
3273 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3274 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3275 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3276 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3277 boost::make_shared<CGGUserPolynomialBase>();
3278 CHKERR
3279 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3280 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3281 materialH1Positions, frontAdjEdges);
3282
3283 auto broken_disp_data_ptr =
3284 boost::make_shared<std::vector<BrokenBaseSideData>>();
3285 op_loop_domain_side->getOpPtrVector().push_back(
3286 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3287 broken_disp_data_ptr));
3288 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3289 op_loop_skeleton_side->getOpPtrVector().push_back(set_scale_op);
3290
3291 auto time_shift = [](const FEMethod *fe_ptr) { return fe_ptr->ts_a; };
3292
3293 // Diag Ugamma-Ugamma skeleton
3294 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3295 hybrid_field, hybrid_field,
3296 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3297 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3298 }));
3299 if (stab_tau_dot_variant) {
3300 static_cast<OpMassVectorFace &>(
3301 op_loop_skeleton_side->getOpPtrVector().back())
3302 .feScalingFun = time_shift;
3303 }
3304 // Diag L2-L2 volumes
3305 op_loop_skeleton_side->getOpPtrVector().push_back(
3307 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3308 return (*local_tau_sacale);
3309 }));
3310 if (stab_tau_dot_variant) {
3311 static_cast<OpBrokenBaseBrokenBase &>(
3312 op_loop_skeleton_side->getOpPtrVector().back())
3313 .feScalingFun = time_shift;
3314 }
3315 // Off-diag Ugamma - L2
3316 op_loop_skeleton_side->getOpPtrVector().push_back(
3318 hybrid_field, broken_disp_data_ptr,
3319 [local_tau_sacale](double, double, double) {
3320 return -(*local_tau_sacale);
3321 },
3322 false, false));
3323 if (stab_tau_dot_variant) {
3324 static_cast<OpHyrbridBaseBrokenBase &>(
3325 op_loop_skeleton_side->getOpPtrVector().back())
3326 .feScalingFun = time_shift;
3327 }
3328
3329 // Off-diag L2 - Ugamma
3330 op_loop_skeleton_side->getOpPtrVector().push_back(
3332 hybrid_field, broken_disp_data_ptr,
3333 [local_tau_sacale](double, double, double) {
3334 return -(*local_tau_sacale);
3335 },
3336 true, true));
3337 if (stab_tau_dot_variant) {
3338 static_cast<OpHyrbridBaseBrokenBase &>(
3339 op_loop_skeleton_side->getOpPtrVector().back())
3340 .feScalingFun = time_shift;
3341 }
3342
3343 pip.push_back(op_loop_skeleton_side);
3344
3346 };
3347
3348 auto set_contact_lhs = [&](auto &pip) {
3349 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3350 };
3351
3352 auto set_cohesive_lhs = [&](auto &pip) {
3353 return pushCohesiveOpsLhs(
3354 *this,
3355 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges,
3356 [](int p) { return 2 * (p + 1) + 1; }),
3357 interfaceFaces, pip);
3358 };
3359
3360 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3361 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3362 if (alphaTau > 0.0) {
3363 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3364 hybridSpatialDisp);
3365 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), contactElement,
3366 contactDisp);
3367 }
3368 if (interfaceCrack == PETSC_TRUE) {
3369 CHKERR set_cohesive_lhs(fe_lhs->getOpPtrVector());
3370 }
3371 }
3372
3373 if (add_material) {
3374 }
3375
3377}
3378
3380 const bool add_elastic, const bool add_material,
3381 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3382 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3384
3385 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3386 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3387
3388 // set integration rule
3389 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3390 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3391 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
3392 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
3393 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3394 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3395
3396 CHKERR
3397 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3398 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3399 CHKERR
3400 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3401 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3402
3403 if (add_elastic) {
3404
3405 auto get_broken_op_side = [this](auto &pip) {
3406 using EleOnSide =
3408 using SideEleOp = EleOnSide::UserDataOperator;
3409 // Iterate over domain FEs adjacent to boundary.
3410 auto broken_data_ptr =
3411 boost::make_shared<std::vector<BrokenBaseSideData>>();
3412 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3413 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
3414 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3415 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3416 boost::make_shared<CGGUserPolynomialBase>();
3417 CHKERR
3418 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3419 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3420 materialH1Positions, frontAdjEdges);
3421 op_loop_domain_side->getOpPtrVector().push_back(
3422 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3423 boost::shared_ptr<double> piola_scale_ptr(new double);
3424 op_loop_domain_side->getOpPtrVector().push_back(
3425 physicalEquations->returnOpSetScale(piola_scale_ptr,
3426 physicalEquations));
3427 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3428 op_loop_domain_side->getOpPtrVector().push_back(
3430 flux_mat_ptr));
3431 op_loop_domain_side->getOpPtrVector().push_back(
3432 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3433 pip.push_back(op_loop_domain_side);
3434 return std::make_tuple(broken_data_ptr, piola_scale_ptr);
3435 };
3436
3437 auto set_rhs = [&]() {
3439
3440 auto [broken_data_ptr, piola_scale_ptr] =
3441 get_broken_op_side(fe_rhs->getOpPtrVector());
3442
3443 fe_rhs->getOpPtrVector().push_back(
3444 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
3445 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
3446 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3447 timeScaleMap));
3448 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
3449 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
3450
3451 fe_rhs->getOpPtrVector().push_back(
3452 new OpBrokenTractionBc(hybridSpatialDisp, bcSpatialTractionVecPtr,
3453 piola_scale_ptr, timeScaleMap));
3454 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3455 // if you push gradient of L2 base to physical element, it will not work.
3456 fe_rhs->getOpPtrVector().push_back(
3458 hybridSpatialDisp, hybrid_grad_ptr));
3459 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
3460 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
3461 hybrid_grad_ptr, timeScaleMap));
3462 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
3463 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
3464 timeScaleMap));
3465
3466 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3467 fe_rhs->getOpPtrVector().push_back(
3468 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3469 hybrid_ptr));
3470 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
3471 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
3472 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3473
3474 auto get_normal_disp_bc_faces = [&]() {
3475 auto faces =
3476 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3477 return boost::make_shared<Range>(faces);
3478 };
3479
3480 using BoundaryEle =
3482 using BdyEleOp = BoundaryEle::UserDataOperator;
3484 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3485 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
3486 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3487 get_normal_disp_bc_faces()));
3488
3490 };
3491
3492 auto set_lhs = [&]() {
3494
3495 auto [broken_data_ptr, piola_scale_ptr] =
3496 get_broken_op_side(fe_lhs->getOpPtrVector());
3497
3498 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
3499 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3500 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
3501 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
3502 timeScaleMap));
3503
3504 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3505 // if you push gradient of L2 base to physical element, it will not work.
3506 fe_lhs->getOpPtrVector().push_back(
3508 hybridSpatialDisp, hybrid_grad_ptr));
3509 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
3510 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
3511 timeScaleMap));
3512
3513 auto get_normal_disp_bc_faces = [&]() {
3514 auto faces =
3515 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3516 return boost::make_shared<Range>(faces);
3517 };
3518
3519 using BoundaryEle =
3521 using BdyEleOp = BoundaryEle::UserDataOperator;
3523 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3524 fe_lhs->getOpPtrVector().push_back(new OpC(
3525 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3526 true, true, get_normal_disp_bc_faces()));
3527
3529 };
3530
3531 CHKERR set_rhs();
3532 CHKERR set_lhs();
3533 }
3534
3536}
3537
3539 const bool add_elastic, const bool add_material,
3540 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3541 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3544}
3545
3547
3548 boost::shared_ptr<ForcesAndSourcesCore> &fe_contact_tree
3549
3550) {
3552 fe_contact_tree = createContactDetectionFiniteElement(*this);
3554}
3555
3558
3559 // Add contact operators. Note that only for rhs. THe lhs is assembled with
3560 // volume element, to enable schur complement evaluation.
3561 CHKERR setContactElementRhsOps(contactTreeRhs);
3562
3563 CHKERR setVolumeElementOps(tag, true, false, elasticFeRhs, elasticFeLhs);
3564 CHKERR setFaceElementOps(true, false, elasticBcRhs, elasticBcLhs);
3565
3566 auto adj_cache =
3567 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3568
3569 auto get_op_contact_bc = [&]() {
3571 auto op_loop_side = new OpLoopSide<SideEle>(
3572 mField, contactElement, SPACE_DIM - 1, Sev::noisy, adj_cache);
3573 return op_loop_side;
3574 };
3575
3577}
3578
3581 boost::shared_ptr<FEMethod> null;
3582
3583 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3584
3585 CHKERR DMMoFEMTSSetI2Function(dm, elementVolumeName, elasticFeRhs, null,
3586 null);
3587 CHKERR DMMoFEMTSSetI2Function(dm, naturalBcElement, elasticBcRhs, null,
3588 null);
3589 CHKERR DMMoFEMTSSetI2Jacobian(dm, elementVolumeName, elasticFeLhs, null,
3590 null);
3591 CHKERR DMMoFEMTSSetI2Jacobian(dm, naturalBcElement, elasticBcLhs, null,
3592 null);
3593
3594 } else {
3595 CHKERR DMMoFEMTSSetIFunction(dm, elementVolumeName, elasticFeRhs, null,
3596 null);
3597 CHKERR DMMoFEMTSSetIFunction(dm, naturalBcElement, elasticBcRhs, null,
3598 null);
3599 CHKERR DMMoFEMTSSetIJacobian(dm, elementVolumeName, elasticFeLhs, null,
3600 null);
3601 CHKERR DMMoFEMTSSetIJacobian(dm, naturalBcElement, elasticBcLhs, null,
3602 null);
3603 }
3604
3606}
3607
3610#include "impl/SetUpSchurImpl.cpp"
3611
3613
3614 inline static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x,
3615 bool set_ts_monitor) {
3616
3617#ifdef ENABLE_PYTHON_BINDING
3618 auto setup_sdf = [&]() { return setupContactSdf(); };
3619#endif
3620
3621 auto setup_ts_monitor = [&]() {
3622 boost::shared_ptr<TsCtx> ts_ctx;
3624 "get TS ctx");
3625 if (set_ts_monitor) {
3627 TSMonitorSet(ts, TsMonitorSet, ts_ctx.get(), PETSC_NULLPTR),
3628 "TS monitor set");
3629 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
3630 ts_ctx->getLoopsMonitor().push_back(
3631 TsCtx::PairNameFEMethodPtr(ep_ptr->elementVolumeName, monitor_ptr));
3632 }
3633 MOFEM_LOG("EP", Sev::inform) << "TS monitor setup";
3634 return std::make_tuple(ts_ctx);
3635 };
3636
3637 auto setup_snes_monitor = [&]() {
3639 SNES snes;
3640 CHKERR TSGetSNES(ts, &snes);
3641 auto snes_ctx = getDMSnesCtx(ep_ptr->dmElastic);
3642 CHKERR SNESMonitorSet(snes,
3643 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
3644 void *))MoFEMSNESMonitorEnergy,
3645 (void *)(snes_ctx.get()), PETSC_NULLPTR);
3646 MOFEM_LOG("EP", Sev::inform) << "SNES monitor setup";
3648 };
3649
3650 auto setup_snes_conergence_test = [&]() {
3652
3653 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
3654 PetscReal snorm, PetscReal fnorm,
3655 SNESConvergedReason *reason, void *cctx) {
3657 // EshelbianCore *ep_ptr = (EshelbianCore *)cctx;
3658 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
3659 PETSC_NULLPTR);
3660
3661 Vec x_update, r;
3662 CHKERR SNESGetSolutionUpdate(snes, &x_update);
3663 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
3664
3666 };
3667
3668 // SNES snes;
3669 // CHKERR TSGetSNES(ts, &snes);
3670 // CHKERR SNESSetConvergenceTest(snes, snes_convergence_test, ep_ptr,
3671 // PETSC_NULLPTR);
3672 // MOFEM_LOG("EP", Sev::inform) << "SNES convergence test setup";
3674 };
3675
3676 auto setup_section = [&]() {
3677 PetscSection section_raw;
3678 CHK_THROW_MESSAGE(DMGetSection(ep_ptr->dmElastic, &section_raw),
3679 "get DM section");
3680 int num_fields;
3681 CHK_THROW_MESSAGE(PetscSectionGetNumFields(section_raw, &num_fields),
3682 "get num fields");
3683 for (int ff = 0; ff != num_fields; ff++) {
3684 const char *field_name;
3686 PetscSectionGetFieldName(section_raw, ff, &field_name),
3687 "get field name");
3688 MOFEM_LOG_C("EP", Sev::inform, "Field %d name %s", ff, field_name);
3689 }
3690 return SmartPetscObj<PetscSection>(section_raw, true);
3691 };
3692
3693 auto set_vector_on_mesh = [&]() {
3695 CHKERR DMoFEMMeshToLocalVector(ep_ptr->dmElastic, x, INSERT_VALUES,
3696 SCATTER_FORWARD);
3697 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3698 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3699 MOFEM_LOG("EP", Sev::inform) << "Vector set on mesh";
3701 };
3702
3703 auto setup_schur_block_solver = [&]() {
3704 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver";
3705 CHK_THROW_MESSAGE(TSAppendOptionsPrefix(ts, "elastic_"),
3706 "append options prefix");
3707 CHK_THROW_MESSAGE(TSSetFromOptions(ts), "set from options");
3708 CHK_THROW_MESSAGE(TSSetDM(ts, ep_ptr->dmElastic), "set DM");
3709 // Adding field split solver
3710 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
3711 if constexpr (A == AssemblyType::BLOCK_MAT) {
3712 schur_ptr =
3714 CHK_THROW_MESSAGE(schur_ptr->setUp(ts), "setup schur");
3715 }
3716 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver done";
3717 return schur_ptr;
3718 };
3719
3720 // Warning: sequence of construction is not guaranteed for tuple. You have
3721 // to enforce order by proper packaging.
3722
3723#ifdef ENABLE_PYTHON_BINDING
3724 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
3725 setup_snes_monitor(), setup_snes_conergence_test(),
3726 setup_section(), set_vector_on_mesh(),
3727 setup_schur_block_solver());
3728#else
3729 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
3730 setup_snes_conergence_test(), setup_section(),
3731 set_vector_on_mesh(), setup_schur_block_solver());
3732#endif
3733 }
3734};
3735
3738
3739 PetscBool debug_model = PETSC_FALSE;
3740 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
3741 PETSC_NULLPTR);
3742 MOFEM_LOG("EP", Sev::inform)
3743 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
3744
3745 if (debug_model == PETSC_TRUE) {
3746 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
3747 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
3748 void *ctx) {
3750
3751 SNES snes;
3752 CHKERR TSGetSNES(ts, &snes);
3753 int it;
3754 CHKERR SNESGetIterationNumber(snes, &it);
3755 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
3756 CHKERR postProcessResults(1, file_name, F, u_t);
3757 std::string file_skel_name =
3758 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
3759
3760 auto get_material_force_tag = [&]() {
3761 auto &moab = mField.get_moab();
3762 Tag tag;
3763 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
3764 "can't get tag");
3765 return tag;
3766 };
3767
3768 CHKERR calculateFaceMaterialForce(1, ts);
3769 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
3770 {get_material_force_tag()});
3771
3773 };
3774 ts_ctx_ptr->tsDebugHook = post_proc;
3775 }
3776
3778}
3779
3782
3783 CHKERR addDebugModel(ts);
3784
3785 auto storage = solve_elastic_setup::setup(this, ts, x, true);
3786
3787 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3788 Vec xx;
3789 CHKERR VecDuplicate(x, &xx);
3790 CHKERR VecZeroEntries(xx);
3791 CHKERR TS2SetSolution(ts, x, xx);
3792 CHKERR VecDestroy(&xx);
3793 } else {
3794 CHKERR TSSetSolution(ts, x);
3795 }
3796
3797 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3798 {elasticFeLhs.get(), elasticFeRhs.get()});
3799 CHKERR TSSetUp(ts);
3800 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
3801 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
3803 CHKERR TSSolve(ts, PETSC_NULLPTR);
3805 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3806 {elasticFeLhs.get(), elasticFeRhs.get()});
3807
3808#ifndef NDEBUG
3809 // Make graph
3810 if (mField.get_comm_rank() == 0) {
3811 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
3813 "solve_elastic_graph.dot");
3814 }
3815#endif
3816
3817 SNES snes;
3818 CHKERR TSGetSNES(ts, &snes);
3819 int lin_solver_iterations;
3820 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
3821 MOFEM_LOG("EP", Sev::inform)
3822 << "Number of linear solver iterations " << lin_solver_iterations;
3823
3824 PetscBool test_cook_flg = PETSC_FALSE;
3825 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
3826 PETSC_NULLPTR);
3827 if (test_cook_flg) {
3828 constexpr int expected_lin_solver_iterations = 11;
3829 if (lin_solver_iterations > expected_lin_solver_iterations)
3830 SETERRQ(
3831 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3832 "Expected number of iterations is different than expected %d > %d",
3833 lin_solver_iterations, expected_lin_solver_iterations);
3834 }
3835
3836 PetscBool test_sslv116_flag = PETSC_FALSE;
3837 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
3838 &test_sslv116_flag, PETSC_NULLPTR);
3839
3840 if (test_sslv116_flag) {
3841 double max_val = 0.0;
3842 double min_val = 0.0;
3843 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
3845 auto ent_type = ent_ptr->getEntType();
3846 if (ent_type == MBVERTEX) {
3847 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
3848 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
3849 }
3851 };
3852 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
3853 field_min_max, spatialH1Disp);
3854
3855 double global_max_val = 0.0;
3856 double global_min_val = 0.0;
3857 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
3858 mField.get_comm());
3859 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
3860 mField.get_comm());
3861 MOFEM_LOG("EP", Sev::inform)
3862 << "Max " << spatialH1Disp << " value: " << global_max_val;
3863 MOFEM_LOG("EP", Sev::inform)
3864 << "Min " << spatialH1Disp << " value: " << global_min_val;
3865
3866 double ref_max_val = 0.00767;
3867 double ref_min_val = -0.00329;
3868 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
3869 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3870 "Incorrect max value of the displacement field: %f != %f",
3871 global_max_val, ref_max_val);
3872 }
3873 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
3874 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3875 "Incorrect min value of the displacement field: %f != %f",
3876 global_min_val, ref_min_val);
3877 }
3878 }
3879
3880 CHKERR gettingNorms();
3881
3883}
3884
3886 int start_step,
3887 double start_time) {
3889
3890 auto storage = solve_elastic_setup::setup(this, ts, x, false);
3891
3892 double final_time = 1;
3893 double delta_time = 0.1;
3894 int max_it = 10;
3895 PetscBool ts_h1_update = PETSC_FALSE;
3896
3897 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
3898
3899 CHKERR PetscOptionsScalar("-dynamic_final_time",
3900 "dynamic relaxation final time", "", final_time,
3901 &final_time, PETSC_NULLPTR);
3902 CHKERR PetscOptionsScalar("-dynamic_delta_time",
3903 "dynamic relaxation final time", "", delta_time,
3904 &delta_time, PETSC_NULLPTR);
3905 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
3906 max_it, &max_it, PETSC_NULLPTR);
3907 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
3908 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
3909
3910 PetscOptionsEnd();
3911
3912 MOFEM_LOG("EP", Sev::inform)
3913 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
3914 MOFEM_LOG("EP", Sev::inform)
3915 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
3916 MOFEM_LOG("EP", Sev::inform)
3917 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
3918 MOFEM_LOG("EP", Sev::inform)
3919 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
3920 << (ts_h1_update ? "TRUE" : "FALSE");
3921
3922 CHKERR addDebugModel(ts);
3923
3924 auto setup_ts_monitor = [&]() {
3925 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
3926 return monitor_ptr;
3927 };
3928 auto monitor_ptr = setup_ts_monitor();
3929
3930 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3931 {elasticFeLhs.get(), elasticFeRhs.get()});
3932 CHKERR TSSetUp(ts);
3934
3935 double ts_delta_time;
3936 CHKERR TSGetTimeStep(ts, &ts_delta_time);
3937
3938 if (ts_h1_update) {
3939 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
3940 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
3941 }
3942
3945
3946 dynamicTime = start_time;
3947 dynamicStep = start_step;
3948 monitor_ptr->ts_u = PETSC_NULLPTR;
3949 monitor_ptr->ts_t = dynamicTime;
3950 monitor_ptr->ts_step = dynamicStep;
3951 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
3952
3953 for (; dynamicTime < final_time; dynamicTime += delta_time) {
3954 MOFEM_LOG("EP", Sev::inform) << "Load step " << dynamicStep << " Time "
3955 << dynamicTime << " delta time " << delta_time;
3956
3957 CHKERR TSSetStepNumber(ts, 0);
3958 CHKERR TSSetTime(ts, 0);
3959 CHKERR TSSetTimeStep(ts, ts_delta_time);
3960 if (!ts_h1_update) {
3962 }
3963 CHKERR TSSetSolution(ts, x);
3964 CHKERR TSSolve(ts, PETSC_NULLPTR);
3965 if (!ts_h1_update) {
3967 }
3968
3969 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
3970 SCATTER_FORWARD);
3971 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3972 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3973
3974 monitor_ptr->ts_u = x;
3975 monitor_ptr->ts_t = dynamicTime;
3976 monitor_ptr->ts_step = dynamicStep;
3977 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
3978
3979 ++dynamicStep;
3980 if (dynamicStep > max_it)
3981 break;
3982 }
3983
3985 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3986 {elasticFeLhs.get(), elasticFeRhs.get()});
3987
3989}
3990
3993
3994 auto set_block = [&](auto name, int dim) {
3995 std::map<int, Range> map;
3996 auto set_tag_impl = [&](auto name) {
3998 auto mesh_mng = mField.getInterface<MeshsetsManager>();
3999 auto bcs = mesh_mng->getCubitMeshsetPtr(
4000
4001 std::regex((boost::format("%s(.*)") % name).str())
4002
4003 );
4004 for (auto bc : bcs) {
4005 Range r;
4006 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4007 true);
4008 map[bc->getMeshsetId()] = r;
4009 MOFEM_LOG("EP", Sev::inform)
4010 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4011 << r.size() << " entities";
4012 }
4014 };
4015
4016 CHKERR set_tag_impl(name);
4017
4018 return std::make_pair(name, map);
4019 };
4020
4021 auto set_skin = [&](auto &&map) {
4022 for (auto &m : map.second) {
4023 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4024 m.second.swap(s);
4025 MOFEM_LOG("EP", Sev::inform)
4026 << "Skin for block " << map.first << " id " << m.first << " has "
4027 << m.second.size() << " entities";
4028 }
4029 return map;
4030 };
4031
4032 auto set_tag = [&](auto &&map) {
4033 Tag th;
4034 auto name = map.first;
4035 int def_val[] = {-1};
4037 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4038 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4039 "create tag");
4040 for (auto &m : map.second) {
4041 int id = m.first;
4042 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4043 "clear tag");
4044 }
4045 return th;
4046 };
4047
4048 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4049 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4050 listTagsToTransfer.push_back(
4051 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4052 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4053
4055}
4056
4058EshelbianCore::postProcessResults(const int tag, const std::string file,
4059 Vec f_residual, Vec var_vector,
4060 std::vector<Tag> tags_to_transfer) {
4062
4063 // mark crack surface
4064 if (crackingOn) {
4065 auto get_tag = [&](auto name, auto dim) {
4066 auto &mob = mField.get_moab();
4067 Tag tag;
4068 double def_val[] = {0., 0., 0.};
4069 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4070 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4071 "create tag");
4072 return tag;
4073 };
4074 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4075 }
4076
4077 {
4078 auto get_crack_tag = [&]() {
4079 Tag th;
4080 rval = mField.get_moab().tag_get_handle("CRACK", th);
4081 if (rval == MB_SUCCESS) {
4082 MOAB_THROW(mField.get_moab().tag_delete(th));
4083 }
4084 int def_val[] = {0};
4085 MOAB_THROW(mField.get_moab().tag_get_handle(
4086 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4087 def_val));
4088 return th;
4089 };
4090
4091 Tag th = get_crack_tag();
4092 tags_to_transfer.push_back(th);
4093 int mark[] = {1};
4094 Range mark_faces;
4095 if (crackFaces)
4096 mark_faces.merge(*crackFaces);
4097 if (interfaceFaces)
4098 mark_faces.merge(*interfaceFaces);
4099 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4100 }
4101
4102 // add tags to transfer
4103 for (auto t : listTagsToTransfer) {
4104 tags_to_transfer.push_back(t);
4105 }
4106
4107 if (!dataAtPts) {
4108 dataAtPts =
4109 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
4110 }
4111
4112 CHKERR DMoFEMLoopFiniteElements(dM, contactElement, contactTreeRhs);
4113
4114 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
4116 auto post_proc_ptr =
4117 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4118 mField, post_proc_mesh);
4119 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4120 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4121 frontAdjEdges);
4122
4123 auto domain_ops = [&](auto &fe, int sense) {
4125 fe.getUserPolynomialBase() =
4126 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase());
4127 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4128 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
4129 frontAdjEdges);
4130 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4131 fe.getOpPtrVector().push_back(physicalEquations->returnOpSetScale(
4132 piola_scale_ptr, physicalEquations));
4133 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4134 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
4135 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4136 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
4137 SmartPetscObj<Vec>(), MBMAXTYPE));
4138 if (noStretch) {
4139 fe.getOpPtrVector().push_back(
4140 physicalEquations->returnOpCalculateStretchFromStress(
4141 dataAtPts, physicalEquations));
4142 } else {
4143 fe.getOpPtrVector().push_back(
4145 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4146 }
4147 if (var_vector) {
4148 auto vec = SmartPetscObj<Vec>(var_vector, true);
4149 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4150 piolaStress, dataAtPts->getVarPiolaPts(),
4151 boost::make_shared<double>(1), vec));
4152 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4153 bubbleField, dataAtPts->getVarPiolaPts(),
4154 boost::make_shared<double>(1), vec, MBMAXTYPE));
4155 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4156 rotAxis, dataAtPts->getVarRotAxisPts(), vec, MBTET));
4157 if (noStretch) {
4158 fe.getOpPtrVector().push_back(
4159 physicalEquations->returnOpCalculateVarStretchFromStress(
4160 dataAtPts, physicalEquations));
4161 } else {
4162 fe.getOpPtrVector().push_back(
4164 stretchTensor, dataAtPts->getVarLogStreachPts(), vec, MBTET));
4165 }
4166 }
4167
4168 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4169 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4170 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4171 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
4172
4173 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4174 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4175 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4176 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
4177 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
4178 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
4179 // evaluate derived quantities
4180 fe.getOpPtrVector().push_back(
4182
4183 // evaluate integration points
4184 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
4185 tag, true, false, dataAtPts, physicalEquations));
4186 if (auto op =
4187 physicalEquations->returnOpCalculateEnergy(dataAtPts, nullptr)) {
4188 fe.getOpPtrVector().push_back(op);
4189 fe.getOpPtrVector().push_back(new OpCalculateEshelbyStress(dataAtPts));
4190 }
4191
4192 // // post-proc
4196
4197 struct OpSidePPMap : public OpPPMap {
4198 OpSidePPMap(moab::Interface &post_proc_mesh,
4199 std::vector<EntityHandle> &map_gauss_pts,
4200 DataMapVec data_map_scalar, DataMapMat data_map_vec,
4201 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
4202 int sense)
4203 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
4204 data_map_vec, data_map_mat, data_symm_map_mat),
4205 tagSense(sense) {}
4206
4207 MoFEMErrorCode doWork(int side, EntityType type,
4210
4211 if (tagSense != 0) {
4212 if (tagSense != OpPPMap::getSkeletonSense())
4214 }
4215
4216 CHKERR OpPPMap::doWork(side, type, data);
4218 }
4219
4220 private:
4221 int tagSense;
4222 };
4223
4224 OpPPMap::DataMapMat vec_fields;
4225 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
4226 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
4227 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
4228 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
4229 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
4230 if (!noStretch) {
4231 vec_fields["EiegnLogStreach"] = dataAtPts->getEigenValsAtPts();
4232 }
4233 if (var_vector) {
4234 auto vec = SmartPetscObj<Vec>(var_vector, true);
4235 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
4236 vec_fields["VarSpatialDisplacementL2"] =
4237 boost::make_shared<MatrixDouble>();
4238 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4239 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], vec, MBTET));
4240 }
4241 if (f_residual) {
4242 auto vec = SmartPetscObj<Vec>(f_residual, true);
4243 vec_fields["ResSpatialDisplacementL2"] =
4244 boost::make_shared<MatrixDouble>();
4245 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4246 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], vec, MBTET));
4247 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
4248 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4249 rotAxis, vec_fields["ResOmega"], vec, MBTET));
4250 }
4251
4252 OpPPMap::DataMapMat mat_fields;
4253 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
4254 if (var_vector) {
4255 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
4256 }
4257 if (f_residual) {
4258 auto vec = SmartPetscObj<Vec>(f_residual, true);
4259 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
4260 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4261 piolaStress, mat_fields["ResPiolaStress"],
4262 boost::make_shared<double>(1), vec));
4263 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4264 bubbleField, mat_fields["ResPiolaStress"],
4265 boost::make_shared<double>(1), vec, MBMAXTYPE));
4266 }
4267 if (!internalStressTagName.empty()) {
4268 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
4269 switch (internalStressInterpOrder) {
4270 case 0:
4271 fe.getOpPtrVector().push_back(
4272 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
4273 break;
4274 case 1:
4275 fe.getOpPtrVector().push_back(
4276 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
4277 break;
4278 default:
4279 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4280 "Unsupported internal stress interpolation order %d",
4281 internalStressInterpOrder);
4282 }
4283 }
4284
4285 OpPPMap::DataMapMat mat_fields_symm;
4286 mat_fields_symm["LogSpatialStretch"] =
4287 dataAtPts->getLogStretchTensorAtPts();
4288 mat_fields_symm["SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
4289 if (var_vector) {
4290 mat_fields_symm["VarLogSpatialStretch"] =
4291 dataAtPts->getVarLogStreachPts();
4292 }
4293 if (f_residual) {
4294 auto vec = SmartPetscObj<Vec>(f_residual, true);
4295 if (!noStretch) {
4296 mat_fields_symm["ResLogSpatialStretch"] =
4297 boost::make_shared<MatrixDouble>();
4298 fe.getOpPtrVector().push_back(
4300 stretchTensor, mat_fields_symm["ResLogSpatialStretch"], vec,
4301 MBTET));
4302 }
4303 }
4304
4305 fe.getOpPtrVector().push_back(
4306
4307 new OpSidePPMap(
4308
4309 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4310
4311 {},
4312
4313 vec_fields,
4314
4315 mat_fields,
4316
4317 mat_fields_symm,
4318
4319 sense
4320
4321 )
4322
4323 );
4324
4325 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
4326 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4327 dataAtPts, sense));
4328
4330 };
4331
4332 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
4333 // H1 material positions
4334 post_proc_ptr->getOpPtrVector().push_back(
4335 new OpCalculateVectorFieldValues<3>(materialH1Positions,
4336 dataAtPts->getLargeXH1AtPts()));
4337
4338 // domain
4340 mField, elementVolumeName, SPACE_DIM);
4341 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
4342 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
4343
4344 return post_proc_ptr;
4345 };
4346
4347 // contact
4348 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
4349 auto &pip) {
4351 // evaluate traction
4352 using EleOnSide =
4354 using SideEleOp = EleOnSide::UserDataOperator;
4355 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4356 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4357 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4358 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase());
4359 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4360 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4361 materialH1Positions, frontAdjEdges);
4362 auto traction_ptr = boost::make_shared<MatrixDouble>();
4363 op_loop_domain_side->getOpPtrVector().push_back(
4365 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
4366
4367 pip.push_back(new OpCalculateVectorFieldValues<3>(
4368 contactDisp, dataAtPts->getContactL2AtPts()));
4369 pip.push_back(op_loop_domain_side);
4370 // evaluate contact displacement and contact conditions
4371 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4372 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
4373 pip.push_back(getOpContactDetection(
4374 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
4375 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
4376 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4377
4379 using BoundaryEle =
4381 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
4382 pip.push_back(op_this);
4383
4384 op_this->getOpPtrVector().push_back(
4385
4386 new OpPPMap(
4387
4388 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4389
4390 {},
4391
4392 {{"ContactDisplacement", dataAtPts->getContactL2AtPts()}},
4393
4394 {},
4395
4396 {}
4397
4398 )
4399
4400 );
4401
4402
4403 if (f_residual) {
4404
4405 auto contact_residual = boost::make_shared<MatrixDouble>();
4406 op_this->getOpPtrVector().push_back(
4408 contactDisp, contact_residual,
4409 SmartPetscObj<Vec>(f_residual, true)));
4410 op_this->getOpPtrVector().push_back(
4411
4412 new OpPPMap(
4413
4414 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4415
4416 {},
4417
4418 {{"res_contact", contact_residual}},
4419
4420 {},
4421
4422 {}
4423
4424 )
4425
4426 );
4427 }
4428
4430 };
4431
4432 auto post_proc_mesh = boost::make_shared<moab::Core>();
4433 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
4434 auto post_proc_negative_sense_ptr =
4435 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
4436 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
4437 CHKERR calcs_side_traction_and_displacements(
4438 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
4439
4440 auto own_tets =
4441 CommInterface::getPartEntities(mField.get_moab(), mField.get_comm_rank())
4442 .subset_by_dimension(SPACE_DIM);
4443 Range own_faces;
4444 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
4445 own_faces, moab::Interface::UNION);
4446
4447 auto get_crack_faces = [&](auto crack_faces) {
4448 auto get_adj = [&](auto e, auto dim) {
4449 Range adj;
4450 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
4451 moab::Interface::UNION);
4452 return adj;
4453 };
4454 // this removes faces
4455 auto tets = get_adj(crack_faces, 3);
4456 // faces adjacent to tets not in crack_faces
4457 auto faces = subtract(get_adj(tets, 2), crack_faces);
4458 // what is left from below, are tets fully inside crack_faces
4459 tets = subtract(tets, get_adj(faces, 3));
4460 return subtract(crack_faces, get_adj(tets, 2));
4461 };
4462
4463 auto side_one_faces = [&](auto &faces) {
4464 std::pair<Range, Range> sides;
4465 for (auto f : faces) {
4466 Range adj;
4467 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
4468 adj = intersect(own_tets, adj);
4469 for (auto t : adj) {
4470 int side, sense, offset;
4471 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
4472 if (sense == 1) {
4473 sides.first.insert(f);
4474 } else {
4475 sides.second.insert(f);
4476 }
4477 }
4478 }
4479 return sides;
4480 };
4481
4482 auto get_interface_from_block = [&](auto block_name) {
4483 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
4484 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
4485 Range faces;
4486 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
4487 faces, moab::Interface::UNION);
4488 faces = subtract(faces, skin);
4489 return faces;
4490 };
4491
4492 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
4493 crack_faces.merge(get_interface_from_block("VOLUME_INTERFACE"));
4494 auto crack_side_faces = side_one_faces(crack_faces);
4495 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
4496 auto ent = fe_method_ptr->getFEEntityHandle();
4497 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
4498 return false;
4499 }
4500 return true;
4501 };
4502 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
4503 auto ent = fe_method_ptr->getFEEntityHandle();
4504 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
4505 return false;
4506 }
4507 return true;
4508 };
4509
4510 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4511 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4512 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
4513
4514 auto post_proc_begin =
4515 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
4516 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
4517 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
4518 post_proc_ptr->exeTestHook = side_one_crack_faces;
4520 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4521 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
4522 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
4523 post_proc_negative_sense_ptr, 0,
4524 mField.get_comm_size());
4525
4526 constexpr bool debug = false;
4527 if (debug) {
4528
4529 auto get_adj_front = [&]() {
4530 auto skeleton_faces = *skeletonFaces;
4531 Range adj_front;
4532 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
4533 moab::Interface::UNION);
4534
4535 adj_front = intersect(adj_front, skeleton_faces);
4536 adj_front = subtract(adj_front, *crackFaces);
4537 adj_front = intersect(own_faces, adj_front);
4538 return adj_front;
4539 };
4540
4541 auto adj_front = filter_owners(mField, get_adj_front());
4542 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
4543 auto ent = fe_method_ptr->getFEEntityHandle();
4544 if (adj_front.find(ent) == adj_front.end()) {
4545 return false;
4546 }
4547 return true;
4548 };
4549
4550 post_proc_ptr->exeTestHook = only_front_faces;
4552 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4553 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
4554 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
4555 post_proc_negative_sense_ptr, 0,
4556 mField.get_comm_size());
4557 }
4558 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
4559 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
4560
4561 CHKERR post_proc_end.writeFile(file.c_str());
4563}
4564
4566EshelbianCore::postProcessSkeletonResults(const int tag, const std::string file,
4567 Vec f_residual,
4568 std::vector<Tag> tags_to_transfer) {
4570
4572
4573 auto post_proc_mesh = boost::make_shared<moab::Core>();
4574 auto post_proc_ptr =
4575 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4576 mField, post_proc_mesh);
4577 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
4578 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4580
4581 auto hybrid_disp = boost::make_shared<MatrixDouble>();
4582 post_proc_ptr->getOpPtrVector().push_back(
4584 post_proc_ptr->getOpPtrVector().push_back(
4586 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
4587
4588 auto op_loop_domain_side =
4590 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4591 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4592
4593 // evaluated in side domain, that is op_loop_domain_side
4594 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4595 boost::make_shared<CGGUserPolynomialBase>();
4596 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4597 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4599 op_loop_domain_side->getOpPtrVector().push_back(
4601 piolaStress, dataAtPts->getApproxPAtPts()));
4602 op_loop_domain_side->getOpPtrVector().push_back(
4604 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
4605 op_loop_domain_side->getOpPtrVector().push_back(
4607 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4608 op_loop_domain_side->getOpPtrVector().push_back(
4610 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4611
4612 if (noStretch) {
4613 op_loop_domain_side->getOpPtrVector().push_back(
4614 physicalEquations->returnOpCalculateStretchFromStress(
4616 } else {
4617 op_loop_domain_side->getOpPtrVector().push_back(
4619 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4620 }
4621
4623
4624 OpPPMap::DataMapMat vec_fields;
4625 vec_fields["HybridDisplacement"] = hybrid_disp;
4626 // note that grad and omega have not trace, so this is only other side value
4627 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
4628 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
4629 OpPPMap::DataMapMat mat_fields;
4630 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
4631 mat_fields["HybridDisplacementGradient"] =
4632 dataAtPts->getGradHybridDispAtPts();
4633 OpPPMap::DataMapMat mat_fields_symm;
4634 mat_fields_symm["LogSpatialStretch"] = dataAtPts->getLogStretchTensorAtPts();
4635
4636 post_proc_ptr->getOpPtrVector().push_back(
4637
4638 new OpPPMap(
4639
4640 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4641
4642 {},
4643
4644 vec_fields,
4645
4646 mat_fields,
4647
4648 mat_fields_symm
4649
4650 )
4651
4652 );
4653
4654 if (f_residual) {
4655 auto hybrid_res = boost::make_shared<MatrixDouble>();
4656 post_proc_ptr->getOpPtrVector().push_back(
4658 hybridSpatialDisp, hybrid_res,
4659 SmartPetscObj<Vec>(f_residual, true)));
4661 post_proc_ptr->getOpPtrVector().push_back(
4662
4663 new OpPPMap(
4664
4665 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4666
4667 {},
4668
4669 {{"res_hybrid", hybrid_res}},
4670
4671 {},
4672
4673 {}
4674
4675 )
4676
4677 );
4678 }
4679
4680 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4681
4682 auto post_proc_begin =
4683 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
4684 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
4685 CHKERR DMoFEMLoopFiniteElements(dM, skeletonElement, post_proc_ptr);
4686 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
4687 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
4688
4689 CHKERR post_proc_end.writeFile(file.c_str());
4690
4692}
4693
4694//! [Getting norms]
4697
4698 auto post_proc_norm_fe =
4699 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
4700
4701 auto post_proc_norm_rule_hook = [](int, int, int p) -> int {
4702 return 2 * (p);
4703 };
4704 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
4705
4706 post_proc_norm_fe->getUserPolynomialBase() =
4707 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase());
4708
4709 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4710 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
4712
4713 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
4714 auto norms_vec =
4715 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
4716 CHKERR VecZeroEntries(norms_vec);
4717
4718 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
4719 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4720 post_proc_norm_fe->getOpPtrVector().push_back(
4722 post_proc_norm_fe->getOpPtrVector().push_back(
4724 post_proc_norm_fe->getOpPtrVector().push_back(
4725 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
4726 post_proc_norm_fe->getOpPtrVector().push_back(
4727 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
4728 post_proc_norm_fe->getOpPtrVector().push_back(
4729 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
4730 u_h1_ptr));
4731
4732 auto piola_ptr = boost::make_shared<MatrixDouble>();
4733 post_proc_norm_fe->getOpPtrVector().push_back(
4735 post_proc_norm_fe->getOpPtrVector().push_back(
4737 MBMAXTYPE));
4738
4739 post_proc_norm_fe->getOpPtrVector().push_back(
4740 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
4741
4742 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
4744 *post_proc_norm_fe);
4745 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
4746
4747 CHKERR VecAssemblyBegin(norms_vec);
4748 CHKERR VecAssemblyEnd(norms_vec);
4749 const double *norms;
4750 CHKERR VecGetArrayRead(norms_vec, &norms);
4751 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
4752 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
4753 MOFEM_LOG("EP", Sev::inform)
4754 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
4755 MOFEM_LOG("EP", Sev::inform)
4756 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
4757 CHKERR VecRestoreArrayRead(norms_vec, &norms);
4758
4760}
4761//! [Getting norms]
4762
4765
4766 auto bc_mng = mField.getInterface<BcManager>();
4768 "", piolaStress, false, false);
4769
4770 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
4771 for (auto bc : bc_mng->getBcMapByBlockName()) {
4772 if (auto disp_bc = bc.second->dispBcPtr) {
4773
4774 auto [field_name, block_name] =
4776 MOFEM_LOG("EP", Sev::inform)
4777 << "Field name: " << field_name << " Block name: " << block_name;
4778 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
4779
4780 std::vector<double> block_attributes(6, 0.);
4781 if (disp_bc->data.flag1 == 1) {
4782 block_attributes[0] = disp_bc->data.value1;
4783 block_attributes[3] = 1;
4784 }
4785 if (disp_bc->data.flag2 == 1) {
4786 block_attributes[1] = disp_bc->data.value2;
4787 block_attributes[4] = 1;
4788 }
4789 if (disp_bc->data.flag3 == 1) {
4790 block_attributes[2] = disp_bc->data.value3;
4791 block_attributes[5] = 1;
4792 }
4793 auto faces = bc.second->bcEnts.subset_by_dimension(2);
4794 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces);
4795 }
4796 }
4797 // old way of naming blocksets for displacement BCs
4798 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
4799
4801 boost::make_shared<NormalDisplacementBcVec>();
4802 for (auto bc : bc_mng->getBcMapByBlockName()) {
4803 auto block_name = "(.*)NORMAL_DISPLACEMENT(.*)";
4804 std::regex reg_name(block_name);
4805 if (std::regex_match(bc.first, reg_name)) {
4806 auto [field_name, block_name] =
4808 MOFEM_LOG("EP", Sev::inform)
4809 << "Field name: " << field_name << " Block name: " << block_name;
4811 block_name, bc.second->bcAttributes,
4812 bc.second->bcEnts.subset_by_dimension(2));
4813 }
4814 }
4815
4817 boost::make_shared<AnalyticalDisplacementBcVec>();
4818
4819 for (auto bc : bc_mng->getBcMapByBlockName()) {
4820 auto block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
4821 std::regex reg_name(block_name);
4822 if (std::regex_match(bc.first, reg_name)) {
4823 auto [field_name, block_name] =
4825 MOFEM_LOG("EP", Sev::inform)
4826 << "Field name: " << field_name << " Block name: " << block_name;
4828 block_name, bc.second->bcAttributes,
4829 bc.second->bcEnts.subset_by_dimension(2));
4830 }
4831 }
4832
4833 auto ts_displacement =
4834 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
4835 for (auto &bc : *bcSpatialDispVecPtr) {
4836 MOFEM_LOG("EP", Sev::noisy)
4837 << "Add time scaling displacement BC: " << bc.blockName;
4838 timeScaleMap[bc.blockName] =
4840 ts_displacement, "disp_history", ".txt", bc.blockName);
4841 }
4842
4843 auto ts_normal_displacement =
4844 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
4845 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
4846 MOFEM_LOG("EP", Sev::noisy)
4847 << "Add time scaling normal displacement BC: " << bc.blockName;
4848 timeScaleMap[bc.blockName] =
4850 ts_normal_displacement, "normal_disp_history", ".txt",
4851 bc.blockName);
4852 }
4853
4855}
4856
4859
4860 auto bc_mng = mField.getInterface<BcManager>();
4862 false, false);
4863
4864 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
4865
4866 for (auto bc : bc_mng->getBcMapByBlockName()) {
4867 if (auto force_bc = bc.second->forceBcPtr) {
4868
4869 auto [field_name, block_name] =
4871 MOFEM_LOG("EP", Sev::inform)
4872 << "Field name: " << field_name << " Block name: " << block_name;
4873 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
4874
4875 std::vector<double> block_attributes(6, 0.);
4876 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
4877 block_attributes[3] = 1;
4878 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
4879 block_attributes[4] = 1;
4880 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
4881 block_attributes[5] = 1;
4882 auto faces = bc.second->bcEnts.subset_by_dimension(2);
4883 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
4884 faces);
4885 }
4886 }
4887 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
4888
4889 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
4890 for (auto bc : bc_mng->getBcMapByBlockName()) {
4891 auto block_name = "(.*)PRESSURE(.*)";
4892 std::regex reg_name(block_name);
4893 if (std::regex_match(bc.first, reg_name)) {
4894
4895 auto [field_name, block_name] =
4897 MOFEM_LOG("EP", Sev::inform)
4898 << "Field name: " << field_name << " Block name: " << block_name;
4899 bcSpatialPressureVecPtr->emplace_back(
4900 block_name, bc.second->bcAttributes,
4901 bc.second->bcEnts.subset_by_dimension(2));
4902 }
4903 }
4904
4906 boost::make_shared<AnalyticalTractionBcVec>();
4907
4908 for (auto bc : bc_mng->getBcMapByBlockName()) {
4909 auto block_name = "(.*)ANALYTICAL_TRACTION(.*)";
4910 std::regex reg_name(block_name);
4911 if (std::regex_match(bc.first, reg_name)) {
4912 auto [field_name, block_name] =
4914 MOFEM_LOG("EP", Sev::inform)
4915 << "Field name: " << field_name << " Block name: " << block_name;
4917 block_name, bc.second->bcAttributes,
4918 bc.second->bcEnts.subset_by_dimension(2));
4919 }
4920 }
4921
4922 auto ts_traction =
4923 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
4924 for (auto &bc : *bcSpatialTractionVecPtr) {
4925 timeScaleMap[bc.blockName] =
4927 ts_traction, "traction_history", ".txt", bc.blockName);
4928 }
4929
4930 auto ts_pressure =
4931 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
4932 for (auto &bc : *bcSpatialPressureVecPtr) {
4933 timeScaleMap[bc.blockName] =
4935 ts_pressure, "pressure_history", ".txt", bc.blockName);
4936 }
4937
4939}
4940
4943
4944 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
4945 &ext_strain_vec_ptr,
4946 const std::string block_name,
4947 const int nb_attributes) {
4949 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
4950 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
4951 std::vector<double> block_attributes;
4952 CHKERR it->getAttributes(block_attributes);
4953 if (block_attributes.size() < nb_attributes) {
4954 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4955 "In block %s expected %d attributes, but given %ld",
4956 it->getName().c_str(), nb_attributes, block_attributes.size());
4957 }
4958
4959 auto get_block_ents = [&]() {
4960 Range ents;
4961 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
4962 true);
4963 return ents;
4964 };
4965 auto Ents = get_block_ents();
4966 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
4967 get_block_ents());
4968 }
4970 };
4971
4972 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
4973
4974 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
4975
4976 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
4977 "externalstrain_history.txt");
4978 for (auto &ext_strain_block : *externalStrainVecPtr) {
4979 MOFEM_LOG("EP", Sev::noisy)
4980 << "Add time scaling external strain: " << ext_strain_block.blockName;
4981 timeScaleMap[ext_strain_block.blockName] =
4983 ts_pre_stretch, "externalstrain_history", ".txt",
4984 ext_strain_block.blockName);
4985 }
4986
4988}
4989
4992
4993 auto print_loc_size = [this](auto v, auto str, auto sev) {
4995 int size;
4996 CHKERR VecGetLocalSize(v.second, &size);
4997 int low, high;
4998 CHKERR VecGetOwnershipRange(v.second, &low, &high);
4999 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5000 << " " << high << " ) ";
5003 };
5004
5006 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5007 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5009 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5010 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5012 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5013 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5015 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5016 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5017
5019}
5020
5022 int start_step,
5023 double start_time) {
5025
5026 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5027
5028 auto cohesive_tao_ctx = createCohesiveTAOCtx(
5029 this,
5030 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges,
5031 [](int p) { return 2 * (p + 1) + 1; }),
5032 SmartPetscObj<TS>(ts, true));
5033
5034 double final_time = 1;
5035 double delta_time = 0.1;
5036 int max_it = 10;
5037 PetscBool ts_h1_update = PETSC_FALSE;
5038
5039 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5040
5041 CHKERR PetscOptionsScalar("-dynamic_final_time",
5042 "dynamic relaxation final time", "", final_time,
5043 &final_time, PETSC_NULLPTR);
5044 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5045 "dynamic relaxation final time", "", delta_time,
5046 &delta_time, PETSC_NULLPTR);
5047 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5048 max_it, &max_it, PETSC_NULLPTR);
5049 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5050 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
5051
5052 PetscOptionsEnd();
5053
5054 MOFEM_LOG("EP", Sev::inform)
5055 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
5056 MOFEM_LOG("EP", Sev::inform)
5057 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
5058 MOFEM_LOG("EP", Sev::inform)
5059 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
5060 MOFEM_LOG("EP", Sev::inform)
5061 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5062 << (ts_h1_update ? "TRUE" : "FALSE");
5063
5064 CHKERR initializeCohesiveKappaField(*this);
5066
5067 auto setup_ts_monitor = [&]() {
5068 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5069 return monitor_ptr;
5070 };
5071 auto monitor_ptr = setup_ts_monitor();
5072
5073 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5074 {elasticFeLhs.get(), elasticFeRhs.get()});
5075 CHKERR TSSetUp(ts);
5076 CHKERR TSElasticPostStep::postStepInitialise(this);
5077
5078 double ts_delta_time;
5079 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5080
5081 if (ts_h1_update) {
5082 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5083 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5084 }
5085
5086 CHKERR TSElasticPostStep::preStepFun(ts);
5087 CHKERR TSElasticPostStep::postStepFun(ts);
5088
5089 auto tao = createTao(mField.get_comm());
5090 CHKERR TaoSetType(tao, TAOLMVM);
5091 auto g = cohesive_tao_ctx->duplicateGradientVec();
5093 cohesiveEvaluateObjectiveAndGradient,
5094 (void *)cohesive_tao_ctx.get());
5095
5096 dynamicTime = start_time;
5097 dynamicStep = start_step;
5098 monitor_ptr->ts_u = PETSC_NULLPTR;
5099 monitor_ptr->ts_t = dynamicTime;
5100 monitor_ptr->ts_step = dynamicStep;
5102
5103 auto tao_sol0 = cohesive_tao_ctx->duplicateKappaVec();
5104 int tao_sol_size, tao_sol_loc_size;
5105 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
5106 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
5107 MOFEM_LOG("EP", Sev::inform)
5108 << "Cohesive crack growth initial kappa vector size " << tao_sol_size
5109 << " local size " << tao_sol_loc_size << " number of interface faces "
5110 << interfaceFaces->size();
5111
5112 CHKERR TaoSetFromOptions(tao);
5113
5114 auto xl = vectorDuplicate(tao_sol0);
5115 auto xu = vectorDuplicate(tao_sol0);
5116 CHKERR VecSet(xl, 0.0);
5117 CHKERR VecSet(xu, PETSC_INFINITY);
5118 CHKERR TaoSetVariableBounds(tao, xl, xu);
5119
5120 for (; dynamicTime < final_time; dynamicTime += delta_time) {
5121 MOFEM_LOG("EP", Sev::inform) << "Load step " << dynamicStep << " Time "
5122 << dynamicTime << " delta time " << delta_time;
5123
5124 CHKERR VecZeroEntries(tao_sol0);
5125 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5126 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5127 CHKERR TaoSetSolution(tao, tao_sol0);
5128 CHKERR TaoSolve(tao);
5129 Vec tao_sol;
5130 CHKERR TaoGetSolution(tao, &tao_sol);
5131
5132 // add solution increment to kappa vec/tags
5133 auto &kappa_vec = cohesive_tao_ctx->getKappaVec();
5135 get_kappa_tag(mField.get_moab()));
5136 CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
5137 CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
5138 SCATTER_FORWARD);
5139 CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
5141 get_kappa_tag(mField.get_moab()));
5142
5143
5144 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5145 SCATTER_FORWARD);
5146 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5147 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5148 monitor_ptr->ts_u = x;
5149 monitor_ptr->ts_t = dynamicTime;
5150 monitor_ptr->ts_step = dynamicStep;
5152
5153 ++dynamicStep;
5154 if (dynamicStep > max_it)
5155 break;
5156 }
5157
5158 CHKERR TSElasticPostStep::postStepDestroy();
5159 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5160 {elasticFeLhs.get(), elasticFeRhs.get()});
5161
5163}
5164
5165} // namespace EshelbianPlasticity
5166
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
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_crack_front_edges(MoFEM::Interface &m_field, Range crack_faces)
Eshelbian plasticity interface.
#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:2270
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
#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 DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
PetscErrorCode DMMoFEMGetTsCtx(DM dm, MoFEM::TsCtx **ts_ctx)
get MoFEM::TsCtx data structure
Definition DMMoFEM.cpp:1132
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
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
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
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.
#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 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< 'j', 3 > j
boost::shared_ptr< ContactSDFPython > setupContactSdf()
Read SDF file and setup contact SDF.
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:1276
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
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.
MoFEM::OpBrokenTopoBase GAUSS
Gaussian quadrature integration.
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 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:1262
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
MoFEMErrorCode addVolumeFiniteElement(const EntityHandle meshset=0)
MoFEMErrorCode addFields(const EntityHandle meshset=0)
static enum StretchSelector stretchSelector
boost::shared_ptr< Range > frontAdjEdges
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 dynamicTime
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 projectInternalStress(const EntityHandle meshset=0)
static int internalStressInterpOrder
MoFEMErrorCode projectGeometry(const EntityHandle meshset=0)
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
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.
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe)
static double griffithEnergy
Griffith energy.
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
static int dynamicStep
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
MoFEMErrorCode getBc(boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
CommInterface::EntitiesPetscVector vertexExchange
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
static PetscBool dynamicRelaxation
const std::string spatialH1Disp
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)
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)
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
static double inv_f_log(const double v)
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
static PetscBool noStretch
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
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 postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
static double crackingAtol
Cracking absolute tolerance.
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)
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
static enum SymmetrySelector symmetrySelector
CommInterface::EntitiesPetscVector edgeExchange
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
static boost::function< double(const double)> f
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
const std::string skinElement
static PetscBool internalStressVoigt
static double inv_dd_f_linear(const double v)
static double inv_dd_f_log_e(const double v)
MoFEMErrorCode getExternalStrain()
MoFEMErrorCode getSpatialTractionBc()
static PetscBool setSingularity
virtual ~EshelbianCore()
static double d_f_log_e(const double v)
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
static double f_log_e_quadratic(const double v)
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 postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
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)
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)
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
static double f_log(const double v)
CommInterface::EntitiesPetscVector faceExchange
SmartPetscObj< DM > dmElastic
Elastic problem.
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)
const std::string contactElement
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)
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
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
base operator to do operations at Gauss Pt. level
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.
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 double precision 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
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
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.
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
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
auto save_range