v0.15.4
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
33 #pragma message "With ENABLE_PYTHON_BINDING"
34
35#else
36
37 #pragma message "Without ENABLE_PYTHON_BINDING"
38
39#endif
40
41#include <EshelbianAux.hpp>
42#include <EshelbianContact.hpp>
43#include <EshlabianCohesive.hpp>
44#include <TSElasticPostStep.hpp>
45
46extern "C" {
47#include <phg-quadrule/quad.h>
48}
49
50#include <queue>
51
52namespace EshelbianPlasticity {
61
62} // namespace EshelbianPlasticity
63
64static auto send_type(MoFEM::Interface &m_field, Range r,
65 const EntityType type) {
66 ParallelComm *pcomm =
67 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
68
69 auto dim = CN::Dimension(type);
70
71 std::vector<int> sendcounts(pcomm->size());
72 std::vector<int> displs(pcomm->size());
73 std::vector<int> sendbuf(r.size());
74 if (pcomm->rank() == 0) {
75 for (auto p = 1; p != pcomm->size(); p++) {
76 auto part_ents = m_field.getInterface<CommInterface>()
77 ->getPartEntities(m_field.get_moab(), p)
78 .subset_by_dimension(SPACE_DIM);
79 Range faces;
80 CHKERR m_field.get_moab().get_adjacencies(part_ents, dim, true, faces,
81 moab::Interface::UNION);
82 faces = intersect(faces, r);
83 sendcounts[p] = faces.size();
84 displs[p] = sendbuf.size();
85 for (auto f : faces) {
86 auto id = id_from_handle(f);
87 sendbuf.push_back(id);
88 }
89 }
90 }
91
92 int recv_data;
93 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
94 pcomm->comm());
95 std::vector<int> recvbuf(recv_data);
96 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
97 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
98
99 if (pcomm->rank() > 0) {
100 Range r;
101 for (auto &f : recvbuf) {
102 r.insert(ent_form_type_and_id(type, f));
103 }
104 return r;
105 }
106
107 return r;
108}
109
111 const std::string block_name, int dim) {
112 Range r;
113
114 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
115 auto bcs = mesh_mng->getCubitMeshsetPtr(
116
117 std::regex((boost::format("%s(.*)") % block_name).str())
118
119 );
120
121 for (auto bc : bcs) {
122 Range faces;
123 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
124 faces, true),
125 "get meshset ents");
126 r.merge(faces);
127 }
128
129 return r;
130};
131
133 const std::string block_name, int dim) {
134 std::map<std::string, Range> r;
135
136 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
137 auto bcs = mesh_mng->getCubitMeshsetPtr(
138
139 std::regex((boost::format("%s(.*)") % block_name).str())
140
141 );
142
143 for (auto bc : bcs) {
144 Range faces;
145 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
146 faces, true),
147 "get meshset ents");
148 r[bc->getName()] = faces;
149 }
150
151 return r;
152}
153
154static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id,
155 const unsigned int cubit_bc_type) {
156 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
157 EntityHandle meshset;
158 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
159 return meshset;
160};
161
162static auto save_range(moab::Interface &moab, const std::string name,
163 const Range r, std::vector<Tag> tags = {}) {
165 auto out_meshset = get_temp_meshset_ptr(moab);
166 CHKERR moab.add_entities(*out_meshset, r);
167 if (r.size()) {
168 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
169 tags.data(), tags.size());
170 } else {
171 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
172 }
174};
175
176static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
177 Range boundary_ents;
178 ParallelComm *pcomm =
179 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
180 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
181 PSTATUS_SHARED | PSTATUS_MULTISHARED,
182 PSTATUS_NOT, -1, &boundary_ents),
183 "filter_pstatus");
184 return boundary_ents;
185};
186
187static auto filter_owners(MoFEM::Interface &m_field, Range skin) {
188 Range owner_ents;
189 ParallelComm *pcomm =
190 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
191 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
192 &owner_ents),
193 "filter_pstatus");
194 return owner_ents;
195};
196
197static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
198 Skinner skin(&m_field.get_moab());
199 Range skin_ents;
200 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
201 return skin_ents;
202};
203
205 Range crack_faces) {
206 ParallelComm *pcomm =
207 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
208 auto &moab = m_field.get_moab();
209 Range crack_skin_without_bdy;
210 if (pcomm->rank() == 0) {
211 Range crack_edges;
212 CHKERR moab.get_adjacencies(crack_faces, 1, true, crack_edges,
213 moab::Interface::UNION);
214 auto crack_skin = get_skin(m_field, crack_faces);
215 Range body_ents;
217 m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents),
218 "get_entities_by_dimension");
219 auto body_skin = get_skin(m_field, body_ents);
220 Range body_skin_edges;
221 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1, true, body_skin_edges,
222 moab::Interface::UNION),
223 "get_adjacencies");
224 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
225 auto front_edges_map = get_range_from_block_map(m_field, "FRONT", 1);
226 for (auto &m : front_edges_map) {
227 auto add_front = subtract(m.second, crack_edges);
228 auto i = intersect(m.second, crack_edges);
229 if (i.empty()) {
230 crack_skin_without_bdy.merge(add_front);
231 } else {
232 auto i_skin = get_skin(m_field, i);
233 Range adj_i_skin;
234 CHKERR moab.get_adjacencies(i_skin, 1, true, adj_i_skin,
235 moab::Interface::UNION);
236 adj_i_skin = subtract(intersect(adj_i_skin, m.second), crack_edges);
237 crack_skin_without_bdy.merge(adj_i_skin);
238 }
239 }
240 }
241 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
242}
243
245 Range crack_faces) {
246
247 ParallelComm *pcomm =
248 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
249
250 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface";
251
252 if (!pcomm->rank()) {
253
254 auto impl = [&](auto &saids) {
256
257 auto &moab = m_field.get_moab();
258
259 auto get_adj = [&](auto e, auto dim) {
260 Range adj;
261 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(
262 e, dim, true, adj, moab::Interface::UNION),
263 "get adj");
264 return adj;
265 };
266
267 auto get_conn = [&](auto e) {
268 Range conn;
269 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(e, conn, true),
270 "get connectivity");
271 return conn;
272 };
273
274 constexpr bool debug = false;
275 Range body_ents;
276 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
277 body_ents);
278 auto body_skin = get_skin(m_field, body_ents);
279 auto body_skin_edges = get_adj(body_skin, 1);
280
281 auto crack_skin =
282 subtract(get_skin(m_field, crack_faces), body_skin_edges);
283 auto crack_skin_conn = get_conn(crack_skin);
284 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
285 auto crack_edges = get_adj(crack_faces, 1);
286 crack_edges = subtract(crack_edges, crack_skin);
287 auto all_tets = get_adj(crack_edges, 3);
288 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
289 auto crack_conn = get_conn(crack_edges);
290 all_tets.merge(get_adj(crack_conn, 3));
291
292 if (debug) {
293 CHKERR save_range(m_field.get_moab(), "crack_faces.vtk", crack_faces);
294 CHKERR save_range(m_field.get_moab(), "all_crack_tets.vtk", all_tets);
295 CHKERR save_range(m_field.get_moab(), "crack_edges_all.vtk",
296 crack_edges);
297 }
298
299 if (crack_faces.size()) {
300 auto grow = [&](auto r) {
301 auto crack_faces_conn = get_conn(crack_faces);
302 Range v;
303 auto size_r = 0;
304 while (size_r != r.size() && r.size() > 0) {
305 size_r = r.size();
306 CHKERR moab.get_connectivity(r, v, true);
307 v = subtract(v, crack_faces_conn);
308 if (v.size()) {
309 CHKERR moab.get_adjacencies(v, SPACE_DIM, true, r,
310 moab::Interface::UNION);
311 r = intersect(r, all_tets);
312 }
313 if (r.empty()) {
314 break;
315 }
316 }
317 return r;
318 };
319
320 Range all_tets_ord = all_tets;
321 while (all_tets.size()) {
322 Range faces = get_adj(unite(saids.first, saids.second), 2);
323 faces = subtract(crack_faces, faces);
324 if (faces.size()) {
325 Range tets;
326 auto fit = faces.begin();
327 for (; fit != faces.end(); ++fit) {
328 tets = intersect(get_adj(Range(*fit, *fit), 3), all_tets);
329 if (tets.size() == 2) {
330 break;
331 }
332 }
333 if (tets.empty()) {
334 break;
335 } else {
336 saids.first.insert(tets[0]);
337 saids.first = grow(saids.first);
338 all_tets = subtract(all_tets, saids.first);
339 if (tets.size() == 2) {
340 saids.second.insert(tets[1]);
341 saids.second = grow(saids.second);
342 all_tets = subtract(all_tets, saids.second);
343 }
344 }
345 } else {
346 break;
347 }
348 }
349
350 saids.first = subtract(all_tets_ord, saids.second);
351 saids.second = subtract(all_tets_ord, saids.first);
352 }
353
355 };
356
357 std::pair<Range, Range> saids;
358 if (crack_faces.size())
359 CHK_THROW_MESSAGE(impl(saids), "get crack both sides");
360 return saids;
361 }
362
363 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface <- done";
364
365 return std::pair<Range, Range>();
366}
367
368namespace EshelbianPlasticity {
369
371
372 using FunRule = boost::function<int(int)>;
373 FunRule funRule = [](int p) { return 2 * p + 1; };
374
376 boost::shared_ptr<Range> front_nodes,
377 boost::shared_ptr<Range> front_edges,
378 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
379 : frontNodes(front_nodes), frontEdges(front_edges), cachePhi(cache_phi){};
380
382 boost::shared_ptr<Range> front_nodes,
383 boost::shared_ptr<Range> front_edges, FunRule fun_rule,
384 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
385 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule),
386 cachePhi(cache_phi){};
387
389 int order_col, int order_data) {
391
392 constexpr bool debug = false;
393
394 constexpr int numNodes = 4;
395 constexpr int numEdges = 6;
396 constexpr int refinementLevels = 6;
397
398 auto &m_field = fe_raw_ptr->mField;
399 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
400 auto fe_handle = fe_ptr->getFEEntityHandle();
401
402 auto set_base_quadrature = [&]() {
404 int rule = funRule(order_data);
405 if (rule < QUAD_3D_TABLE_SIZE) {
406 if (QUAD_3D_TABLE[rule]->dim != 3) {
407 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
408 "wrong dimension");
409 }
410 if (QUAD_3D_TABLE[rule]->order < rule) {
411 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
412 "wrong order %d != %d", QUAD_3D_TABLE[rule]->order, rule);
413 }
414 const size_t nb_gauss_pts = QUAD_3D_TABLE[rule]->npoints;
415 auto &gauss_pts = fe_ptr->gaussPts;
416 gauss_pts.resize(4, nb_gauss_pts, false);
417 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[1], 4,
418 &gauss_pts(0, 0), 1);
419 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[2], 4,
420 &gauss_pts(1, 0), 1);
421 cblas_dcopy(nb_gauss_pts, &QUAD_3D_TABLE[rule]->points[3], 4,
422 &gauss_pts(2, 0), 1);
423 cblas_dcopy(nb_gauss_pts, QUAD_3D_TABLE[rule]->weights, 1,
424 &gauss_pts(3, 0), 1);
425 auto &data = fe_ptr->dataOnElement[H1];
426 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4,
427 false);
428 double *shape_ptr =
429 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
430 cblas_dcopy(4 * nb_gauss_pts, QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
431 1);
432 } else {
433 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
434 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
435 }
437 };
438
439 CHKERR set_base_quadrature();
440
442
443 auto get_singular_nodes = [&]() {
444 int num_nodes;
445 const EntityHandle *conn;
446 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
447 true);
448 std::bitset<numNodes> singular_nodes;
449 for (auto nn = 0; nn != numNodes; ++nn) {
450 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
451 singular_nodes.set(nn);
452 } else {
453 singular_nodes.reset(nn);
454 }
455 }
456 return singular_nodes;
457 };
458
459 auto get_singular_edges = [&]() {
460 std::bitset<numEdges> singular_edges;
461 for (int ee = 0; ee != numEdges; ee++) {
462 EntityHandle edge;
463 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
464 if (frontEdges->find(edge) != frontEdges->end()) {
465 singular_edges.set(ee);
466 } else {
467 singular_edges.reset(ee);
468 }
469 }
470 return singular_edges;
471 };
472
473 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
475 fe_ptr->gaussPts.swap(ref_gauss_pts);
476 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
477 auto &data = fe_ptr->dataOnElement[H1];
478 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
479 double *shape_ptr =
480 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
481 CHKERR ShapeMBTET(shape_ptr, &fe_ptr->gaussPts(0, 0),
482 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
483 nb_gauss_pts);
485 };
486
487 auto singular_nodes = get_singular_nodes();
488 if (singular_nodes.count()) {
489 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
490 if (it_map_ref_coords != mapRefCoords.end()) {
491 CHKERR set_gauss_pts(it_map_ref_coords->second);
493 } else {
494
495 auto refine_quadrature = [&]() {
497
498 const int max_level = refinementLevels;
499 EntityHandle tet;
500
501 moab::Core moab_ref;
502 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
503 EntityHandle nodes[4];
504 for (int nn = 0; nn != 4; nn++)
505 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
506 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
507 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
508 MoFEM::Interface &m_field_ref = mofem_ref_core;
509 {
510 Range tets(tet, tet);
511 Range edges;
512 CHKERR m_field_ref.get_moab().get_adjacencies(
513 tets, 1, true, edges, moab::Interface::UNION);
514 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
515 tets, BitRefLevel().set(0), false, VERBOSE);
516 }
517
518 Range nodes_at_front;
519 for (int nn = 0; nn != numNodes; nn++) {
520 if (singular_nodes[nn]) {
521 EntityHandle ent;
522 CHKERR moab_ref.side_element(tet, 0, nn, ent);
523 nodes_at_front.insert(ent);
524 }
525 }
526
527 auto singular_edges = get_singular_edges();
528
529 EntityHandle meshset;
530 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
531 for (int ee = 0; ee != numEdges; ee++) {
532 if (singular_edges[ee]) {
533 EntityHandle ent;
534 CHKERR moab_ref.side_element(tet, 1, ee, ent);
535 CHKERR moab_ref.add_entities(meshset, &ent, 1);
536 }
537 }
538
539 // refine mesh
540 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
541 for (int ll = 0; ll != max_level; ll++) {
542 Range edges;
543 CHKERR m_field_ref.getInterface<BitRefManager>()
544 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
545 BitRefLevel().set(), MBEDGE,
546 edges);
547 Range ref_edges;
548 CHKERR moab_ref.get_adjacencies(
549 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
550 ref_edges = intersect(ref_edges, edges);
551 Range ents;
552 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
553 ref_edges = intersect(ref_edges, ents);
554 Range tets;
555 CHKERR m_field_ref.getInterface<BitRefManager>()
556 ->getEntitiesByTypeAndRefLevel(
557 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
558 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
559 ref_edges, BitRefLevel().set(ll + 1));
560 CHKERR m_ref->refineTets(tets, BitRefLevel().set(ll + 1));
561 CHKERR m_field_ref.getInterface<BitRefManager>()
562 ->updateMeshsetByEntitiesChildren(meshset,
563 BitRefLevel().set(ll + 1),
564 meshset, MBEDGE, true);
565 }
566
567 // get ref coords
568 Range tets;
569 CHKERR m_field_ref.getInterface<BitRefManager>()
570 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
571 BitRefLevel().set(), MBTET,
572 tets);
573
574 if (debug) {
575 CHKERR save_range(moab_ref, "ref_tets.vtk", tets);
576 }
577
578 MatrixDouble ref_coords(tets.size(), 12, false);
579 int tt = 0;
580 for (Range::iterator tit = tets.begin(); tit != tets.end();
581 tit++, tt++) {
582 int num_nodes;
583 const EntityHandle *conn;
584 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
585 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
586 }
587
588 auto &data = fe_ptr->dataOnElement[H1];
589 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
590 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
591 MatrixDouble &shape_n =
592 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
593 int gg = 0;
594 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
595 double *tet_coords = &ref_coords(tt, 0);
596 double det = Tools::tetVolume(tet_coords);
597 det *= 6;
598 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
599 for (int dd = 0; dd != 3; dd++) {
600 ref_gauss_pts(dd, gg) =
601 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
602 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
603 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
604 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
605 }
606 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
607 }
608 }
609
610 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
611 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
612
613 // clear cache bubble
614 cachePhi->get<0>() = 0;
615 cachePhi->get<1>() = 0;
616 // tet base cache
617 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
618 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
619
621 };
622
623 CHKERR refine_quadrature();
624 }
625 }
626 }
627
629 }
630
631private:
632 struct Fe : public ForcesAndSourcesCore {
633 using ForcesAndSourcesCore::dataOnElement;
634
635 private:
636 using ForcesAndSourcesCore::ForcesAndSourcesCore;
637 };
638
639 boost::shared_ptr<Range> frontNodes;
640 boost::shared_ptr<Range> frontEdges;
641
642 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cachePhi;
643
644 static inline std::map<long int, MatrixDouble> mapRefCoords;
645};
646
648
649 using FunRule = boost::function<int(int)>;
650 FunRule funRule = [](int p) { return 2 * (p + 1) + 1; };
651
652 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
653 boost::shared_ptr<Range> front_edges)
654 : frontNodes(front_nodes), frontEdges(front_edges){};
655
656 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
657 boost::shared_ptr<Range> front_edges,
658 FunRule fun_rule)
659 : frontNodes(front_nodes), frontEdges(front_edges), funRule(fun_rule){};
660
662 int order_col, int order_data) {
664
665 constexpr bool debug = false;
666
667 constexpr int numNodes = 3;
668 constexpr int numEdges = 3;
669 constexpr int refinementLevels = 6;
670
671 auto &m_field = fe_raw_ptr->mField;
672 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
673 auto fe_handle = fe_ptr->getFEEntityHandle();
674
675 auto set_base_quadrature = [&]() {
677 int rule = funRule(order_data);
678 if (rule < QUAD_2D_TABLE_SIZE) {
679 if (QUAD_2D_TABLE[rule]->dim != 2) {
680 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
681 }
682 if (QUAD_2D_TABLE[rule]->order < rule) {
683 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
684 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
685 }
686 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
687 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
688 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
689 &fe_ptr->gaussPts(0, 0), 1);
690 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
691 &fe_ptr->gaussPts(1, 0), 1);
692 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
693 &fe_ptr->gaussPts(2, 0), 1);
694 auto &data = fe_ptr->dataOnElement[H1];
695 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
696 false);
697 double *shape_ptr =
698 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
699 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
700 1);
701 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
702 std::copy(
704 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
705
706 } else {
707 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
708 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
709 }
711 };
712
713 CHKERR set_base_quadrature();
714
716
717 auto get_singular_nodes = [&]() {
718 int num_nodes;
719 const EntityHandle *conn;
720 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
721 true);
722 std::bitset<numNodes> singular_nodes;
723 for (auto nn = 0; nn != numNodes; ++nn) {
724 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
725 singular_nodes.set(nn);
726 } else {
727 singular_nodes.reset(nn);
728 }
729 }
730 return singular_nodes;
731 };
732
733 auto get_singular_edges = [&]() {
734 std::bitset<numEdges> singular_edges;
735 for (int ee = 0; ee != numEdges; ee++) {
736 EntityHandle edge;
737 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
738 if (frontEdges->find(edge) != frontEdges->end()) {
739 singular_edges.set(ee);
740 } else {
741 singular_edges.reset(ee);
742 }
743 }
744 return singular_edges;
745 };
746
747 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
749 fe_ptr->gaussPts.swap(ref_gauss_pts);
750 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
751 auto &data = fe_ptr->dataOnElement[H1];
752 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
753 double *shape_ptr =
754 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
755 CHKERR ShapeMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
756 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
758 };
759
760 auto singular_nodes = get_singular_nodes();
761 if (singular_nodes.count()) {
762 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
763 if (it_map_ref_coords != mapRefCoords.end()) {
764 CHKERR set_gauss_pts(it_map_ref_coords->second);
766 } else {
767
768 auto refine_quadrature = [&]() {
770
771 const int max_level = refinementLevels;
772
773 moab::Core moab_ref;
774 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
775 EntityHandle nodes[numNodes];
776 for (int nn = 0; nn != numNodes; nn++)
777 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
778 EntityHandle tri;
779 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
780 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
781 MoFEM::Interface &m_field_ref = mofem_ref_core;
782 {
783 Range tris(tri, tri);
784 Range edges;
785 CHKERR m_field_ref.get_moab().get_adjacencies(
786 tris, 1, true, edges, moab::Interface::UNION);
787 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
788 tris, BitRefLevel().set(0), false, VERBOSE);
789 }
790
791 Range nodes_at_front;
792 for (int nn = 0; nn != numNodes; nn++) {
793 if (singular_nodes[nn]) {
794 EntityHandle ent;
795 CHKERR moab_ref.side_element(tri, 0, nn, ent);
796 nodes_at_front.insert(ent);
797 }
798 }
799
800 auto singular_edges = get_singular_edges();
801
802 EntityHandle meshset;
803 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
804 for (int ee = 0; ee != numEdges; ee++) {
805 if (singular_edges[ee]) {
806 EntityHandle ent;
807 CHKERR moab_ref.side_element(tri, 1, ee, ent);
808 CHKERR moab_ref.add_entities(meshset, &ent, 1);
809 }
810 }
811
812 // refine mesh
813 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
814 for (int ll = 0; ll != max_level; ll++) {
815 Range edges;
816 CHKERR m_field_ref.getInterface<BitRefManager>()
817 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
818 BitRefLevel().set(), MBEDGE,
819 edges);
820 Range ref_edges;
821 CHKERR moab_ref.get_adjacencies(
822 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
823 ref_edges = intersect(ref_edges, edges);
824 Range ents;
825 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
826 ref_edges = intersect(ref_edges, ents);
827 Range tris;
828 CHKERR m_field_ref.getInterface<BitRefManager>()
829 ->getEntitiesByTypeAndRefLevel(
830 BitRefLevel().set(ll), BitRefLevel().set(), MBTRI, tris);
831 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
832 ref_edges, BitRefLevel().set(ll + 1));
833 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
834 CHKERR m_field_ref.getInterface<BitRefManager>()
835 ->updateMeshsetByEntitiesChildren(meshset,
836 BitRefLevel().set(ll + 1),
837 meshset, MBEDGE, true);
838 }
839
840 // get ref coords
841 Range tris;
842 CHKERR m_field_ref.getInterface<BitRefManager>()
843 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
844 BitRefLevel().set(), MBTRI,
845 tris);
846
847 if (debug) {
848 CHKERR save_range(moab_ref, "ref_tris.vtk", tris);
849 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
850 }
851
852 MatrixDouble ref_coords(tris.size(), 9, false);
853 int tt = 0;
854 for (Range::iterator tit = tris.begin(); tit != tris.end();
855 tit++, tt++) {
856 int num_nodes;
857 const EntityHandle *conn;
858 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
859 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
860 }
861
862 auto &data = fe_ptr->dataOnElement[H1];
863 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
864 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
865 MatrixDouble &shape_n =
866 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
867 int gg = 0;
868 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
869 double *tri_coords = &ref_coords(tt, 0);
871 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
872 auto det = t_normal.l2();
873 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
874 for (int dd = 0; dd != 2; dd++) {
875 ref_gauss_pts(dd, gg) =
876 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
877 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
878 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
879 }
880 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
881 }
882 }
883
884 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
885 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
886
888 };
889
890 CHKERR refine_quadrature();
891 }
892 }
893 }
894
896 }
897
898private:
899 struct Fe : public ForcesAndSourcesCore {
900 using ForcesAndSourcesCore::dataOnElement;
901
902 private:
903 using ForcesAndSourcesCore::ForcesAndSourcesCore;
904 };
905
906 boost::shared_ptr<Range> frontNodes;
907 boost::shared_ptr<Range> frontEdges;
908
909 static inline std::map<long int, MatrixDouble> mapRefCoords;
910};
911
912double EshelbianCore::exponentBase = exp(1);
913boost::function<double(const double)> EshelbianCore::f = EshelbianCore::f_log_e;
914boost::function<double(const double)> EshelbianCore::d_f =
916boost::function<double(const double)> EshelbianCore::dd_f =
918boost::function<double(const double)> EshelbianCore::inv_f =
920boost::function<double(const double)> EshelbianCore::inv_d_f =
922boost::function<double(const double)> EshelbianCore::inv_dd_f =
924
926EshelbianCore::query_interface(boost::typeindex::type_index type_index,
927 UnknownInterface **iface) const {
928 *iface = const_cast<EshelbianCore *>(this);
929 return 0;
930}
931
932MoFEMErrorCode OpJacobian::doWork(int side, EntityType type, EntData &data) {
934
935 if (evalRhs)
936 CHKERR evaluateRhs(data);
937
938 if (evalLhs)
939 CHKERR evaluateLhs(data);
940
942}
943
945 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
946}
947
949
952 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
953 const char *list_symm[] = {"symm", "not_symm"};
954 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
955 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
956 const char *list_solvers[] = {"time_solver", "dynamic_relaxation",
957 "cohesive"};
958 PetscInt choice_rot = EshelbianCore::rotSelector;
959 PetscInt choice_grad = EshelbianCore::gradApproximator;
960 PetscInt choice_symm = EshelbianCore::symmetrySelector;
961 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
962 PetscInt choice_stretch = StretchSelector::LOG;
963 PetscInt choice_solver = SolverType::TimeSolver;
964 char analytical_expr_file_name[255] = "analytical_expr.py";
965
966 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
967 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
968 spaceOrder, &spaceOrder, PETSC_NULLPTR);
969 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
970 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
971 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
972 "", materialOrder, &materialOrder, PETSC_NULLPTR);
973 CHKERR PetscOptionsScalar("-viscosity_alpha_u", "viscosity", "", alphaU,
974 &alphaU, PETSC_NULLPTR);
975 CHKERR PetscOptionsScalar("-viscosity_alpha_w", "viscosity", "", alphaW,
976 &alphaW, PETSC_NULLPTR);
977 CHKERR PetscOptionsScalar("-viscosity_alpha_omega", "rot viscosity", "",
978 alphaOmega, &alphaOmega, PETSC_NULLPTR);
979 CHKERR PetscOptionsScalar("-density_alpha_rho", "density", "", alphaRho,
980 &alphaRho, PETSC_NULLPTR);
981 CHKERR PetscOptionsScalar("-alpha_tau", "tau", "", alphaTau, &alphaTau,
982 PETSC_NULLPTR);
983 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
984 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
985 PETSC_NULLPTR);
986 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
987 list_rots, NO_H1_CONFIGURATION + 1,
988 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
989 CHKERR PetscOptionsEList("-symm", "symmetric variant", "", list_symm, 2,
990 list_symm[choice_symm], &choice_symm, PETSC_NULLPTR);
991
992 CHKERR PetscOptionsScalar("-exponent_base", "exponent_base", "", exponentBase,
993 &EshelbianCore::exponentBase, PETSC_NULLPTR);
994 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
995 StretchSelector::STRETCH_SELECTOR_LAST,
996 list_stretches[choice_stretch], &choice_stretch,
997 PETSC_NULLPTR);
998
999 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
1000 noStretch, &noStretch, PETSC_NULLPTR);
1001 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1002 setSingularity, &setSingularity, PETSC_NULLPTR);
1003 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1004 l2UserBaseScale, &l2UserBaseScale, PETSC_NULLPTR);
1005
1006 // dynamic relaxation
1007
1008 // @deprecate this option
1009 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1010 dynamicRelaxation, &dynamicRelaxation, PETSC_NULLPTR);
1011 CHKERR PetscOptionsEList("-solver_type", "solver type", "", list_solvers,
1012 SolverType::LastSolver, list_solvers[choice_solver],
1013 &choice_solver, PETSC_NULLPTR);
1014
1015 // contact parameters
1016 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1018 PETSC_NULLPTR);
1019 // cohesive interfae
1020 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1021 intefaceCrack, &intefaceCrack, PETSC_NULLPTR);
1022
1023 // cracking parameters
1024 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1025 &crackingOn, PETSC_NULLPTR);
1026 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1028 PETSC_NULLPTR);
1029 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1030 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1031 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1032 "", list_release, 2, list_release[choice_release],
1033 &choice_release, PETSC_NULLPTR);
1034 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1036 PETSC_NULLPTR); // backward compatibility
1037 CHKERR PetscOptionsInt(
1038 "-nb_J_integral_contours", "Number of J integral contours", "",
1039 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1040
1041 // internal stress
1042 char tag_name[255] = "";
1043 CHKERR PetscOptionsString("-internal_stress_tag_name",
1044 "internal stress tag name", "", "", tag_name, 255,
1045 PETSC_NULLPTR);
1046 internalStressTagName = string(tag_name);
1047 CHKERR PetscOptionsInt(
1048 "-internal_stress_interp_order", "internal stress interpolation order",
1050 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1052 PETSC_NULLPTR);
1053
1054 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
1055 "-analytical_expr_file",
1056 analytical_expr_file_name, 255, PETSC_NULLPTR);
1057
1058 PetscOptionsEnd();
1059
1061 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1062 "Unsupported internal stress interpolation order %d",
1064 }
1065
1066 if (setSingularity) {
1067 l2UserBaseScale = PETSC_TRUE;
1068 }
1069
1070 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1071 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1072 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1073 EshelbianCore::symmetrySelector = static_cast<SymmetrySelector>(choice_symm);
1075 static_cast<EnergyReleaseSelector>(choice_release);
1076
1078 case StretchSelector::LINEAR:
1085 break;
1086 case StretchSelector::LOG:
1087 if (std::fabs(EshelbianCore::exponentBase - exp(1)) >
1088 std::numeric_limits<float>::epsilon()) {
1095 } else {
1102 }
1103 break;
1104 case StretchSelector::LOG_QUADRATIC:
1108 EshelbianCore::inv_f = [](const double x) {
1110 "No logarithmic quadratic stretch for this case");
1111 return 0;
1112 };
1115 break; // no stretch, do not use stretch functions
1116 default:
1117 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1118 break;
1119 };
1120
1121 if (dynamicRelaxation) {
1122 MOFEM_LOG("EP", Sev::warning)
1123 << "-dynamic_relaxation option is deprecated, use -solver_type "
1124 "dynamic_relaxation instead.";
1125 choice_solver = SolverType::DynamicRelaxation;
1126 }
1127
1128 switch (choice_solver) {
1131 break;
1135 dynamicRelaxation = PETSC_TRUE;
1136 break;
1139 break;
1140 default:
1141 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1142 break;
1143 };
1144
1145 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1146 MOFEM_LOG("EP", Sev::inform)
1147 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1148 MOFEM_LOG("EP", Sev::inform)
1149 << "materialOrder: -material_order " << materialOrder;
1150 MOFEM_LOG("EP", Sev::inform) << "alphaU: -viscosity_alpha_u " << alphaU;
1151 MOFEM_LOG("EP", Sev::inform) << "alphaW: -viscosity_alpha_w " << alphaW;
1152 MOFEM_LOG("EP", Sev::inform)
1153 << "alphaOmega: -viscosity_alpha_omega " << alphaOmega;
1154 MOFEM_LOG("EP", Sev::inform) << "alphaRho: -density_alpha_rho " << alphaRho;
1155 MOFEM_LOG("EP", Sev::inform) << "alphaTau: -alpha_tau " << alphaTau;
1156 MOFEM_LOG("EP", Sev::inform)
1157 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1158 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation "
1159 << list_rots[EshelbianCore::gradApproximator];
1160 MOFEM_LOG("EP", Sev::inform)
1161 << "Symmetry: -symm " << list_symm[EshelbianCore::symmetrySelector];
1162 if (exponentBase != exp(1))
1163 MOFEM_LOG("EP", Sev::inform)
1164 << "Base exponent: -exponent_base " << EshelbianCore::exponentBase;
1165 else
1166 MOFEM_LOG("EP", Sev::inform) << "Base exponent e";
1167 MOFEM_LOG("EP", Sev::inform)
1168 << "Stretch: -stretches " << list_stretches[choice_stretch];
1169 MOFEM_LOG("EP", Sev::inform) << "No stretch: -no_stretch " << (noStretch)
1170 ? "yes"
1171 : "no";
1172
1173 MOFEM_LOG("EP", Sev::inform)
1174 << "Dynamic relaxation: -dynamic_relaxation " << (dynamicRelaxation)
1175 ? "yes"
1176 : "no";
1177 MOFEM_LOG("EP", Sev::inform)
1178 << "Solver type: -solver_type " << list_solvers[choice_solver];
1179 MOFEM_LOG("EP", Sev::inform)
1180 << "Singularity: -set_singularity " << (setSingularity)
1181 ? "yes"
1182 : "no";
1183 MOFEM_LOG("EP", Sev::inform)
1184 << "L2 user base scale: -l2_user_base_scale " << (l2UserBaseScale)
1185 ? "yes"
1186 : "no";
1187
1188 MOFEM_LOG("EP", Sev::inform) << "Cracking on: -cracking_on " << (crackingOn)
1189 ? "yes"
1190 : "no";
1191 MOFEM_LOG("EP", Sev::inform)
1192 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1193 MOFEM_LOG("EP", Sev::inform)
1194 << "Griffith energy: -griffith_energy " << griffithEnergy;
1195 MOFEM_LOG("EP", Sev::inform)
1196 << "Energy release variant: -energy_release_variant "
1197 << list_release[EshelbianCore::energyReleaseSelector];
1198 MOFEM_LOG("EP", Sev::inform)
1199 << "Number of J integral contours: -nb_J_integral_contours "
1201 MOFEM_LOG("EP", Sev::inform)
1202 << "Cohesive interface on: -cohesive_interface_on "
1203 << (intefaceCrack == PETSC_TRUE)
1204 ? "yes"
1205 : "no";
1206
1207#ifdef ENABLE_PYTHON_BINDING
1208 auto file_exists = [](std::string myfile) {
1209 std::ifstream file(myfile.c_str());
1210 if (file) {
1211 return true;
1212 }
1213 return false;
1214 };
1215
1216 if (file_exists(analytical_expr_file_name)) {
1217 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1218
1219 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1220 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1221 analytical_expr_file_name);
1222 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1223 } else {
1224 MOFEM_LOG("EP", Sev::warning)
1225 << analytical_expr_file_name << " file NOT found";
1226 }
1227#endif
1228
1229 if (spaceH1Order == -1)
1231
1233}
1234
1237
1238 auto get_tets = [&]() {
1239 Range tets;
1240 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1241 return tets;
1242 };
1243
1244 auto get_tets_skin = [&]() {
1245 Range tets_skin_part;
1246 Skinner skin(&mField.get_moab());
1247 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1248 ParallelComm *pcomm =
1249 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1250 Range tets_skin;
1251 CHKERR pcomm->filter_pstatus(tets_skin_part,
1252 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1253 PSTATUS_NOT, -1, &tets_skin);
1254 return tets_skin;
1255 };
1256
1257 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1258 // That mean, that hybrid field on all faces on which traction is applied,
1259 // on other faces, or enforcing displacements as
1260 // natural boundary condition.
1262 for (auto &v : *bcSpatialTractionVecPtr) {
1263 tets_skin = subtract(tets_skin, v.faces);
1264 }
1266 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1267 tets_skin = subtract(tets_skin, v.faces);
1268 }
1269
1271 for (auto &v : *bcSpatialPressureVecPtr) {
1272 tets_skin = subtract(tets_skin, v.faces);
1273 }
1274
1275 return tets_skin;
1276 };
1277
1278 auto add_blockset = [&](auto block_name, auto &&tets_skin) {
1279 auto crack_faces =
1280 get_range_from_block(mField, "block_name", SPACE_DIM - 1);
1281 tets_skin.merge(crack_faces);
1282 return tets_skin;
1283 };
1284
1285 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1286 auto contact_range =
1287 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1288 tets_skin = subtract(tets_skin, contact_range);
1289 return tets_skin;
1290 };
1291
1292 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1293 Range faces;
1294 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1295 faces, moab::Interface::UNION);
1296 Range trace_faces = subtract(faces, tets_skin);
1297 return trace_faces;
1298 };
1299
1300 auto tets = get_tets();
1301
1302 // remove also contact faces, i.e. that is also kind of hybrid field but
1303 // named but used to enforce contact conditions
1304 auto trace_faces = get_stress_trace_faces(
1305
1306 subtract_blockset("CONTACT",
1307 subtract_boundary_conditions(get_tets_skin()))
1308
1309 );
1310
1311 contactFaces = boost::make_shared<Range>(intersect(
1312 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1314 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1315
1316#ifndef NDEBUG
1317 if (contactFaces->size())
1319 "contact_faces_" +
1320 std::to_string(mField.get_comm_rank()) + ".vtk",
1321 *contactFaces);
1322 if (skeletonFaces->size())
1324 "skeleton_faces_" +
1325 std::to_string(mField.get_comm_rank()) + ".vtk",
1326 *skeletonFaces);
1327#endif
1328
1329 auto add_broken_hdiv_field = [this, meshset](const std::string field_name,
1330 const int order) {
1332
1334
1335 auto get_side_map_hdiv = [&]() {
1336 return std::vector<
1337
1338 std::pair<EntityType,
1340
1341 >>{
1342
1343 {MBTET,
1344 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1345 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1346 dofs_side_map);
1347 }}
1348
1349 };
1350 };
1351
1353 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1355 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1357 };
1358
1359 auto add_l2_field = [this, meshset](const std::string field_name,
1360 const int order, const int dim) {
1363 MB_TAG_DENSE, MF_ZERO);
1365 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1367 };
1368
1369 auto add_h1_field = [this, meshset](const std::string field_name,
1370 const int order, const int dim) {
1373 MB_TAG_DENSE, MF_ZERO);
1375 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1376 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1377 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1378 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1380 };
1381
1382 auto add_l2_field_by_range = [this](const std::string field_name,
1383 const int order, const int dim,
1384 const int field_dim, Range &&r) {
1387 MB_TAG_DENSE, MF_ZERO);
1388 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1392 };
1393
1394 auto add_bubble_field = [this, meshset](const std::string field_name,
1395 const int order, const int dim) {
1397 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1398 MF_ZERO);
1399 // Modify field
1400 auto field_ptr = mField.get_field_structure(field_name);
1401 auto field_order_table =
1402 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1403 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1404 auto get_cgg_bubble_order_tet = [](int p) {
1405 return NBVOLUMETET_CCG_BUBBLE(p);
1406 };
1407 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1408 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1409 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1410 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1412 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1413 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1415 };
1416
1417 auto add_user_l2_field = [this, meshset](const std::string field_name,
1418 const int order, const int dim) {
1420 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1421 MF_ZERO);
1422 // Modify field
1423 auto field_ptr = mField.get_field_structure(field_name);
1424 auto field_order_table =
1425 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1426 auto zero_dofs = [](int p) { return 0; };
1427 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1428 field_order_table[MBVERTEX] = zero_dofs;
1429 field_order_table[MBEDGE] = zero_dofs;
1430 field_order_table[MBTRI] = zero_dofs;
1431 field_order_table[MBTET] = dof_l2_tet;
1433 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1435 };
1436
1437 // spatial fields
1438 CHKERR add_broken_hdiv_field(piolaStress, spaceOrder);
1439 CHKERR add_bubble_field(bubbleField, spaceOrder, 1);
1440 CHKERR add_l2_field(spatialL2Disp, spaceOrder - 1, 3);
1441 CHKERR add_user_l2_field(rotAxis, spaceOrder - 1, 3);
1442 CHKERR add_user_l2_field(stretchTensor, noStretch ? -1 : spaceOrder, 6);
1443
1444 if (!skeletonFaces)
1445 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1446 if (!contactFaces)
1447 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1448
1449 auto get_hybridised_disp = [&]() {
1450 auto faces = *skeletonFaces;
1451 auto skin = subtract_boundary_conditions(get_tets_skin());
1452 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1453 faces.merge(intersect(bc.faces, skin));
1454 }
1455 return faces;
1456 };
1457
1458 CHKERR add_l2_field_by_range(hybridSpatialDisp, spaceOrder - 1, 2, 3,
1459 get_hybridised_disp());
1460 CHKERR add_l2_field_by_range(contactDisp, spaceOrder - 1, 2, 3,
1462
1463 // spatial displacement
1464 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1465 // material positions
1466 CHKERR add_h1_field(materialH1Positions, 2, 3);
1467
1468 // Eshelby stress
1469 // CHKERR add_broken_hdiv_field(eshelbyStress, spaceOrder);
1470 // CHKERR add_l2_field(materialL2Disp, spaceOrder - 1, 3);
1471 // CHKERR add_l2_field_by_range(hybridMaterialDisp, spaceOrder - 1, 2, 3,
1472 // Range(*materialSkeletonFaces));
1473
1475
1477}
1478
1481
1482 Range meshset_ents;
1483 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1484
1485 auto project_ho_geometry = [&](auto field) {
1487 return mField.loop_dofs(field, ent_method);
1488 };
1489 CHKERR project_ho_geometry(materialH1Positions);
1490
1491 auto get_adj_front_edges = [&](auto &front_edges) {
1492 Range front_crack_nodes;
1493 Range crack_front_edges_with_both_nodes_not_at_front;
1494
1495 if (mField.get_comm_rank() == 0) {
1496 auto &moab = mField.get_moab();
1498 moab.get_connectivity(front_edges, front_crack_nodes, true),
1499 "get_connectivity failed");
1500 Range crack_front_edges;
1501 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1502 false, crack_front_edges,
1503 moab::Interface::UNION),
1504 "get_adjacencies failed");
1505 Range crack_front_edges_nodes;
1506 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1507 crack_front_edges_nodes, true),
1508 "get_connectivity failed");
1509 // those nodes are hannging nodes
1510 crack_front_edges_nodes =
1511 subtract(crack_front_edges_nodes, front_crack_nodes);
1512 Range crack_front_edges_with_both_nodes_not_at_front;
1514 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1515 crack_front_edges_with_both_nodes_not_at_front,
1516 moab::Interface::UNION),
1517 "get_adjacencies failed");
1518 // those edges are have one node not at the crack front
1519 crack_front_edges_with_both_nodes_not_at_front = intersect(
1520 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1521 }
1522
1523 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1524 crack_front_edges_with_both_nodes_not_at_front = send_type(
1525 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1526
1527 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1528 boost::make_shared<Range>(
1529 crack_front_edges_with_both_nodes_not_at_front));
1530 };
1531
1532 crackFaces = boost::make_shared<Range>(
1533 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1534 frontEdges =
1535 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1536 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1537 frontVertices = front_vertices;
1538 frontAdjEdges = front_adj_edges;
1539
1540 MOFEM_LOG("EP", Sev::inform)
1541 << "Number of crack faces: " << crackFaces->size();
1542 MOFEM_LOG("EP", Sev::inform)
1543 << "Number of front edges: " << frontEdges->size();
1544 MOFEM_LOG("EP", Sev::inform)
1545 << "Number of front vertices: " << frontVertices->size();
1546 MOFEM_LOG("EP", Sev::inform)
1547 << "Number of front adjacent edges: " << frontAdjEdges->size();
1548
1549#ifndef NDEBUG
1550 if (crackingOn) {
1551 auto rank = mField.get_comm_rank();
1552 // CHKERR save_range(mField.get_moab(),
1553 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1554 // meshset_ents);
1556 (boost::format("crack_faces_%d.vtk") % rank).str(),
1557 *crackFaces);
1559 (boost::format("front_edges_%d.vtk") % rank).str(),
1560 *frontEdges);
1561 // CHKERR save_range(mField.get_moab(),
1562 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1563 // *frontVertices);
1564 // CHKERR save_range(mField.get_moab(),
1565 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1566 // *frontAdjEdges);
1567 }
1568#endif // NDEBUG
1569
1570 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1572 auto &moab = mField.get_moab();
1573
1574 double eps = 1;
1575 double beta = 0;
1576 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1577 PETSC_NULLPTR);
1578 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1579 eps -= beta;
1580
1581 auto field_blas = mField.getInterface<FieldBlas>();
1582 auto lambda =
1583 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1585 FTENSOR_INDEX(3, i);
1586 FTENSOR_INDEX(3, j);
1587
1588 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1589 if (nb_dofs == 0) {
1591 }
1592
1593#ifndef NDEBUG
1594 if (field_entity_ptr->getNbOfCoeffs() != 3)
1596 "Expected 3 coefficients per edge");
1597 if (nb_dofs % 3 != 0)
1599 "Expected multiple of 3 coefficients per edge");
1600#endif // NDEBUG
1601
1602 auto get_conn = [&]() {
1603 int num_nodes;
1604 const EntityHandle *conn;
1605 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1606 num_nodes, false);
1607 return std::make_pair(conn, num_nodes);
1608 };
1609
1610 auto get_dir = [&](auto &&conn_p) {
1611 auto [conn, num_nodes] = conn_p;
1612 double coords[6];
1613 CHKERR moab.get_coords(conn, num_nodes, coords);
1614 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
1615 coords[4] - coords[1],
1616 coords[5] - coords[2]};
1617 return t_edge_dir;
1618 };
1619
1620 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
1621 auto [conn, num_nodes] = conn_p;
1622 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
1623 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1624 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
1625 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1626 t_singularity_dof(i) = t_edge_dir(i) * eps;
1627 }
1628 return t_singularity_dof;
1629 };
1630
1631 auto t_singularity_dof =
1632 get_singularity_dof(get_conn(), get_dir(get_conn()));
1633
1634 auto field_data = field_entity_ptr->getEntFieldData();
1636 &field_data[0], &field_data[1], &field_data[2]};
1637
1638 t_dof(i) = t_singularity_dof(i);
1639 ++t_dof;
1640 for (auto n = 1; n < field_data.size() / 3; ++n) {
1641 t_dof(i) = 0;
1642 ++t_dof;
1643 }
1644
1646 };
1647
1648 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
1649 &front_adj_edges);
1650
1652 };
1653
1654 if (setSingularity)
1655 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
1656
1657 interfaceFaces = boost::make_shared<Range>(
1658 get_range_from_block(mField, "INTERFACE", SPACE_DIM - 1));
1659 MOFEM_LOG("EP", Sev::inform)
1660 << "Number of interface elements: " << interfaceFaces->size();
1661
1663}
1664
1668#ifdef INCLUDE_MBCOUPLER
1669
1670 char mesh_source_file[255] = "source.h5m";
1671 char iterp_tag_name[255] = "INTERNAL_STRESS";
1672
1673 int interp_order = 1;
1674 PetscBool hybrid_interp = PETSC_TRUE;
1675 PetscBool project_internal_stress = PETSC_FALSE;
1676
1677 double toler = 5.e-10;
1678 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1679 "none");
1680 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1681 "source.h5m", mesh_source_file, 255,
1682 &project_internal_stress);
1683 CHKERR PetscOptionsString("-interp_tag", "interpolation tag name", "",
1684 "INTERNAL_STRESS", iterp_tag_name, 255,
1685 PETSC_NULLPTR);
1686 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1687 &interp_order, PETSC_NULLPTR);
1688 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1689 hybrid_interp, &hybrid_interp, PETSC_NULLPTR);
1690 PetscOptionsEnd();
1691
1692 MOFEM_LOG_CHANNEL("WORLD");
1693 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
1694 if (!project_internal_stress) {
1695 MOFEM_LOG("WORLD", Sev::inform)
1696 << "No internal stress source mesh specified. Skipping projection of "
1697 "internal stress";
1699 }
1700 MOFEM_LOG("WORLD", Sev::inform)
1701 << "Projecting internal stress from source mesh: " << mesh_source_file;
1702
1703 auto &moab = mField.get_moab();
1704
1705 // check if tag exists
1706 Tag old_interp_tag;
1707 auto rval_check_tag = moab.tag_get_handle(iterp_tag_name, old_interp_tag);
1708 if (rval_check_tag == MB_SUCCESS) {
1709 MOFEM_LOG("WORLD", Sev::inform)
1710 << "Deleting existing tag on target mesh: " << iterp_tag_name;
1711 CHKERR moab.tag_delete(old_interp_tag);
1712 }
1713
1714 // make a size-1 communicator for the coupler (rank 0 only)
1715 int world_rank = -1, world_size = -1;
1716 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
1717 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
1718
1719 Range original_meshset_ents;
1720 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
1721
1722 MPI_Comm comm_coupler;
1723 if (world_rank == 0) {
1724 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
1725 } else {
1726 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
1727 }
1728
1729 // build a separate ParallelComm for the coupler (rank 0 only)
1730 ParallelComm *pcomm0 = nullptr;
1731 int pcomm0_id = -1;
1732 if (world_rank == 0) {
1733 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
1734 }
1735
1736 Coupler::Method method;
1737 switch (interp_order) {
1738 case 0:
1739 method = Coupler::CONSTANT;
1740 break;
1741 case 1:
1742 method = Coupler::LINEAR_FE;
1743 break;
1744 default:
1745 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1746 "Unsupported interpolation order");
1747 }
1748
1749 int nprocs, rank;
1750 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
1751 CHKERRQ(ierr);
1752 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1753 CHKERRQ(ierr);
1754
1755 // std::string read_opts, write_opts;
1756 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
1757 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
1758 // if (world_size > 1)
1759 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
1760 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
1761
1762 // create target mesh from existing meshset
1763 EntityHandle target_root;
1764 CHKERR moab.create_meshset(MESHSET_SET, target_root);
1765 MOFEM_LOG("WORLD", Sev::inform)
1766 << "Creating target mesh from existing meshset";
1767 Range target_meshset_ents;
1768 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
1769 CHKERR moab.add_entities(target_root, target_meshset_ents);
1770
1771 // variables for tags to be broadcast later
1772 int tag_length;
1773 DataType dtype;
1774 TagType storage;
1775
1776 // load source mesh
1777 Range targ_verts, targ_elems;
1778 if (world_rank == 0) {
1779
1780 EntityHandle source_root;
1781 CHKERR moab.create_meshset(MESHSET_SET, source_root);
1782
1783 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
1784 auto rval_source_mesh = moab.load_file(mesh_source_file, &source_root, "");
1785 if (rval_source_mesh != MB_SUCCESS) {
1786 MOFEM_LOG("WORLD", Sev::warning)
1787 << "Error loading source mesh file: " << mesh_source_file;
1788 }
1789 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
1790
1791 Range src_elems;
1792 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
1793
1794 EntityHandle part_set;
1795 CHKERR pcomm0->create_part(part_set);
1796 CHKERR moab.add_entities(part_set, src_elems);
1797
1798 Range src_elems_part;
1799 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
1800
1801 Tag interp_tag;
1802 CHKERR moab.tag_get_handle(iterp_tag_name, interp_tag);
1803
1804 int interp_tag_len;
1805 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
1806
1807 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
1808 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1809 "Unsupported interpolation tag length: %d", interp_tag_len);
1810 }
1811
1812 // store tag info for later broadcast
1813 tag_length = interp_tag_len;
1814 CHKERR moab.tag_get_data_type(interp_tag, dtype);
1815 CHKERR moab.tag_get_type(interp_tag, storage);
1816
1817 // coupler is collective
1818 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
1819
1820 std::vector<double> vpos; // the positions we are interested in
1821 int num_pts = 0;
1822
1823 Range tmp_verts;
1824
1825 // First get all vertices adj to partition entities in target mesh
1826 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
1827
1828 if (interp_order == 0) {
1829 targ_verts = targ_elems;
1830 } else {
1831 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
1832 moab::Interface::UNION);
1833 }
1834
1835 // Then get non-owned verts and subtract
1836 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
1837 targ_verts = subtract(targ_verts, tmp_verts);
1838
1839 // get position of these entities; these are the target points
1840 num_pts = (int)targ_verts.size();
1841 vpos.resize(3 * targ_verts.size());
1842 CHKERR moab.get_coords(targ_verts, &vpos[0]);
1843
1844 // Locate those points in the source mesh
1845 boost::shared_ptr<TupleList> tl_ptr;
1846 tl_ptr = boost::make_shared<TupleList>();
1847 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(), false);
1848
1849 // If some points were not located, we need to process them
1850 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
1851 std::vector<double> &vpos,
1852 Range &missing_verts) {
1854 int missing_pts_num = 0;
1855 int i = 0;
1856 auto vit = targ_verts.begin();
1857 for (; vit != targ_verts.end(); i++) {
1858 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
1859 missing_verts.insert(*vit);
1860 vit = targ_verts.erase(vit);
1861 missing_pts_num++;
1862 } else {
1863 vit++;
1864 }
1865 }
1866
1867 int missing_pts_num_global = 0;
1868 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
1869 // MPI_SUM, pcomm0);
1870 if (missing_pts_num_global) {
1871 MOFEM_LOG("WORLD", Sev::warning)
1872 << missing_pts_num_global
1873 << " points in target mesh were not located in source mesh. ";
1874 }
1875
1876 if (missing_pts_num) {
1877 num_pts = (int)targ_verts.size();
1878 vpos.resize(3 * targ_verts.size());
1879 CHKERR moab.get_coords(targ_verts, &vpos[0]);
1880 tl_ptr->reset();
1881 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
1882 false);
1883 }
1885 };
1886
1887 Range missing_verts;
1888 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
1889
1890 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
1891 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
1892
1893 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
1894
1895 Tag scalar_tag, adj_count_tag;
1896 double def_scl = 0;
1897 string scalar_tag_name = string(iterp_tag_name) + "_COMP";
1898 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
1899 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
1900 &def_scl);
1901
1902 string adj_count_tag_name = "ADJ_COUNT";
1903 double def_adj = 0;
1904 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
1905 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
1906 &def_adj);
1907
1908 // MBCoupler functionality supports only scalar tags. For the case of
1909 // vector or tensor tags we need to save each component as a scalar tag
1910 auto create_scalar_tags = [&](const Range &src_elems,
1911 const std::vector<double> &source_data,
1912 int itag) {
1914
1915 std::vector<double> source_data_scalar(src_elems.size());
1916 // Populate source_data_scalar
1917 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
1918 source_data_scalar[ielem] = source_data[itag + ielem * interp_tag_len];
1919 }
1920
1921 // Set data on the scalar tag
1922 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
1923
1924 if (interp_order == 1) {
1925 // Linear interpolation: compute average value of data on vertices
1926 Range src_verts;
1927 CHKERR moab.get_connectivity(src_elems, src_verts, true);
1928
1929 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
1930 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
1931
1932 for (auto &tet : src_elems) {
1933 double tet_data = 0;
1934 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
1935
1936 Range adj_verts;
1937 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
1938
1939 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
1940 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
1941
1942 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
1943 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
1944 &adj_vert_count[0]);
1945
1946 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
1947 adj_vert_data[ivert] += tet_data;
1948 adj_vert_count[ivert] += 1;
1949 }
1950
1951 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
1952 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
1953 &adj_vert_count[0]);
1954 }
1955
1956 // Reduce tags for the parallel case
1957 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
1958 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
1959
1960 std::vector<double> src_vert_data(src_verts.size(), 0.0);
1961 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
1962
1963 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
1964 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
1965 &src_vert_adj_count[0]);
1966
1967 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
1968 src_vert_data[ivert] /= src_vert_adj_count[ivert];
1969 }
1970 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
1971 }
1973 };
1974
1975 for (int itag = 0; itag < interp_tag_len; itag++) {
1976
1977 CHKERR create_scalar_tags(src_elems, source_data, itag);
1978
1979 std::vector<double> target_data_scalar(num_pts, 0.0);
1980 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
1981 tl_ptr.get());
1982
1983 for (int ielem = 0; ielem < num_pts; ielem++) {
1984 target_data[itag + ielem * interp_tag_len] = target_data_scalar[ielem];
1985 }
1986 }
1987
1988 // Use original tag
1989 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
1990
1991 if (missing_verts.size() && (interp_order == 1) && hybrid_interp) {
1992 MOFEM_LOG("WORLD", Sev::warning) << "Using hybrid interpolation for "
1993 "missing points in the target mesh.";
1994 Range missing_adj_elems;
1995 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
1996 moab::Interface::UNION);
1997
1998 int num_adj_elems = (int)missing_adj_elems.size();
1999 std::vector<double> vpos_adj_elems;
2000
2001 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2002 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2003
2004 // Locate those points in the source mesh
2005 tl_ptr->reset();
2006 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2007 tl_ptr.get(), false);
2008
2009 Range missing_tets;
2010 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2011 vpos_adj_elems, missing_tets);
2012 if (missing_tets.size()) {
2013 MOFEM_LOG("WORLD", Sev::warning)
2014 << missing_tets.size()
2015 << "points in target mesh were not located in source mesh. ";
2016 }
2017
2018 std::vector<double> target_data_adj_elems(interp_tag_len * num_adj_elems,
2019 0.0);
2020
2021 for (int itag = 0; itag < interp_tag_len; itag++) {
2022 CHKERR create_scalar_tags(src_elems, source_data, itag);
2023
2024 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2025 CHKERR mbc.interpolate(method, scalar_tag_name,
2026 &target_data_adj_elems_scalar[0], tl_ptr.get());
2027
2028 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2029 target_data_adj_elems[itag + ielem * interp_tag_len] =
2030 target_data_adj_elems_scalar[ielem];
2031 }
2032 }
2033
2034 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2035 &target_data_adj_elems[0]);
2036
2037 // FIXME: add implementation for parallel case
2038 for (auto &vert : missing_verts) {
2039 Range adj_elems;
2040 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2041 moab::Interface::UNION);
2042
2043 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2044 0.0);
2045 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2046
2047 std::vector<double> vert_data(interp_tag_len, 0.0);
2048 for (int itag = 0; itag < interp_tag_len; itag++) {
2049 for (int i = 0; i < adj_elems.size(); i++) {
2050 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2051 }
2052 vert_data[itag] /= adj_elems.size();
2053 }
2054 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2055 }
2056 }
2057
2058 CHKERR moab.tag_delete(scalar_tag);
2059 CHKERR moab.tag_delete(adj_count_tag);
2060 // delete source mesh
2061 Range src_mesh_ents;
2062 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2063 CHKERR moab.delete_entities(&source_root, 1);
2064 CHKERR moab.delete_entities(src_mesh_ents);
2065 CHKERR moab.delete_entities(&part_set, 1);
2066 }
2067
2068 // broadcast tag info to other processors
2069 MPI_Bcast(&tag_length, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2070 MPI_Bcast(&dtype, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2071 MPI_Bcast(&storage, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2072
2073 // create tag on other processors
2074 Tag interp_tag_all;
2075 unsigned flags =
2076 MB_TAG_CREAT | storage; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2077 std::vector<double> def_val(tag_length, 0.);
2078 CHKERR moab.tag_get_handle(iterp_tag_name, tag_length, dtype, interp_tag_all,
2079 flags, def_val.data());
2080 MPI_Barrier(PETSC_COMM_WORLD);
2081
2082 // exchange data for all entity types across all processors
2083 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2084 mField.get_comm(), mField.get_moab(), 0, tag_length, Sev::inform);
2085 auto edge_exchange = CommInterface::createEntitiesPetscVector(
2086 mField.get_comm(), mField.get_moab(), 1, tag_length, Sev::inform);
2087 auto face_exchange = CommInterface::createEntitiesPetscVector(
2088 mField.get_comm(), mField.get_moab(), 2, tag_length, Sev::inform);
2089 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2090 mField.get_comm(), mField.get_moab(), 3, tag_length, Sev::inform);
2091
2093 mField.get_moab(), vertex_exchange, interp_tag_all);
2095 mField.get_moab(), edge_exchange, interp_tag_all);
2097 mField.get_moab(), face_exchange, interp_tag_all);
2099 mField.get_moab(), volume_exchange, interp_tag_all);
2100
2101 // delete target meshset but not the entities
2102 CHKERR moab.delete_entities(&target_root, 1);
2103
2104#endif // INCLUDE_MBCOUPLER
2106}
2107
2111
2112 // set finite element fields
2113 auto add_field_to_fe = [this](const std::string fe,
2114 const std::string field_name) {
2120 };
2121
2126
2127 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2128 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2129 if (!noStretch)
2130 CHKERR add_field_to_fe(elementVolumeName, stretchTensor);
2131 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2132 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2133 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2134 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2137
2138 // build finite elements data structures
2140 }
2141
2143}
2144
2148
2149 Range meshset_ents;
2150 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2151
2152 auto set_fe_adjacency = [&](auto fe_name) {
2155 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2158 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2160 };
2161
2162 // set finite element fields
2163 auto add_field_to_fe = [this](const std::string fe,
2164 const std::string field_name) {
2171 };
2172
2174
2175 Range natural_bc_elements;
2176 if (bcSpatialDispVecPtr) {
2177 for (auto &v : *bcSpatialDispVecPtr) {
2178 natural_bc_elements.merge(v.faces);
2179 }
2180 }
2182 for (auto &v : *bcSpatialRotationVecPtr) {
2183 natural_bc_elements.merge(v.faces);
2184 }
2185 }
2187 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2188 natural_bc_elements.merge(v.faces);
2189 }
2190 }
2193 natural_bc_elements.merge(v.faces);
2194 }
2195 }
2197 for (auto &v : *bcSpatialTractionVecPtr) {
2198 natural_bc_elements.merge(v.faces);
2199 }
2200 }
2202 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2203 natural_bc_elements.merge(v.faces);
2204 }
2205 }
2207 for (auto &v : *bcSpatialPressureVecPtr) {
2208 natural_bc_elements.merge(v.faces);
2209 }
2210 }
2211 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2212
2214 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2216 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2217 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2218 CHKERR set_fe_adjacency(naturalBcElement);
2220 }
2221
2222 auto get_skin = [&](auto &body_ents) {
2223 Skinner skin(&mField.get_moab());
2224 Range skin_ents;
2225 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2226 return skin_ents;
2227 };
2228
2229 auto filter_true_skin = [&](auto &&skin) {
2230 Range boundary_ents;
2231 ParallelComm *pcomm =
2232 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2233 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2234 PSTATUS_NOT, -1, &boundary_ents);
2235 return boundary_ents;
2236 };
2237
2239
2240 Range body_ents;
2241 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2242 body_ents);
2243 auto skin = filter_true_skin(get_skin(body_ents));
2244
2252 contactDisp);
2255
2257 }
2258
2260 if (contactFaces) {
2261 MOFEM_LOG("EP", Sev::inform)
2262 << "Contact elements " << contactFaces->size();
2266 CHKERR add_field_to_fe(contactElement, piolaStress);
2267 CHKERR add_field_to_fe(contactElement, contactDisp);
2268 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2269 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2270 CHKERR set_fe_adjacency(contactElement);
2272 }
2273 }
2274
2276 if (!skeletonFaces)
2277 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2278 MOFEM_LOG("EP", Sev::inform)
2279 << "Skeleton elements " << skeletonFaces->size();
2283 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2284 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2285 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2286 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2287 CHKERR set_fe_adjacency(skeletonElement);
2289 }
2290
2292}
2293
2295 const EntityHandle meshset) {
2297
2298 // find adjacencies between finite elements and dofs
2300
2301 // Create coupled problem
2302 dM = createDM(mField.get_comm(), "DMMOFEM");
2303 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2304 BitRefLevel().set());
2305 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2306 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2312
2313 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2314 CHKERR DMSetUp(dM);
2315 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2316
2317 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2319 for (int d : {0, 1, 2}) {
2320 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2322 ->getSideDofsOnBrokenSpaceEntities(
2323 dofs_to_remove, prb_name, ROW, piolaStress,
2325 // remove piola dofs, i.e. traction free boundary
2326 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2327 dofs_to_remove);
2328 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2329 dofs_to_remove);
2330 }
2332 };
2333 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2334
2335 // Create elastic sub-problem
2336 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2337 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2343 if (!noStretch) {
2345 }
2355 CHKERR DMSetUp(dmElastic);
2356
2357 // dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2358 // CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2359 // CHKERR DMMoFEMSetDestroyProblem(dmMaterial, PETSC_TRUE);
2360 // CHKERR DMMoFEMAddSubFieldRow(dmMaterial, eshelbyStress);
2361 // CHKERR DMMoFEMAddSubFieldRow(dmMaterial, materialL2Disp);
2362 // CHKERR DMMoFEMAddElement(dmMaterh elementVolumeName);
2363 // CHKERR DMMoFEMAddElement(dmMaterial, naturalBcElement);
2364 // CHKERR DMMoFEMAddElement(dmMaterial, skinElement);
2365 // CHKERR DMMoFEMSetSquareProblem(dmMaterial, PETSC_TRUE);
2366 // CHKERR DMMoFEMSetIsPartitioned(dmMaterial, PETSC_TRUE);
2367 // CHKERR DMSetUp(dmMaterial);
2368
2369 auto set_zero_block = [&]() {
2371 if (!noStretch) {
2372 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2373 "ELASTIC_PROBLEM", spatialL2Disp, stretchTensor);
2374 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2375 "ELASTIC_PROBLEM", stretchTensor, spatialL2Disp);
2376 }
2377 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2378 "ELASTIC_PROBLEM", spatialL2Disp, rotAxis);
2379 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2380 "ELASTIC_PROBLEM", rotAxis, spatialL2Disp);
2381 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2382 "ELASTIC_PROBLEM", spatialL2Disp, bubbleField);
2383 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2384 "ELASTIC_PROBLEM", bubbleField, spatialL2Disp);
2385 if (!noStretch) {
2386 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2387 "ELASTIC_PROBLEM", bubbleField, bubbleField);
2388 CHKERR
2389 mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2390 "ELASTIC_PROBLEM", piolaStress, piolaStress);
2391 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2392 "ELASTIC_PROBLEM", bubbleField, piolaStress);
2393 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2394 "ELASTIC_PROBLEM", piolaStress, bubbleField);
2395 }
2396
2399 };
2400
2401 auto set_section = [&]() {
2403 PetscSection section;
2404 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2405 &section);
2406 CHKERR DMSetSection(dmElastic, section);
2407 CHKERR DMSetGlobalSection(dmElastic, section);
2408 CHKERR PetscSectionDestroy(&section);
2410 };
2411
2412 CHKERR set_zero_block();
2413 CHKERR set_section();
2414
2415 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2416 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2422 CHKERR DMSetUp(dmPrjSpatial);
2423
2424 // CHKERR mField.getInterface<BcManager>()
2425 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2426 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2427
2429}
2430
2431BcDisp::BcDisp(std::string name, std::vector<double> attr, Range faces)
2432 : blockName(name), faces(faces) {
2433 vals.resize(3, false);
2434 flags.resize(3, false);
2435 for (int ii = 0; ii != 3; ++ii) {
2436 vals[ii] = attr[ii];
2437 flags[ii] = static_cast<int>(attr[ii + 3]);
2438 }
2439
2440 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp " << name;
2441 MOFEM_LOG("EP", Sev::inform)
2442 << "Add BCDisp vals " << vals[0] << " " << vals[1] << " " << vals[2];
2443 MOFEM_LOG("EP", Sev::inform)
2444 << "Add BCDisp flags " << flags[0] << " " << flags[1] << " " << flags[2];
2445 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp nb. of faces " << faces.size();
2446}
2447
2448BcRot::BcRot(std::string name, std::vector<double> attr, Range faces)
2449 : blockName(name), faces(faces) {
2450 vals.resize(attr.size(), false);
2451 for (int ii = 0; ii != attr.size(); ++ii) {
2452 vals[ii] = attr[ii];
2453 }
2454 theta = attr[3];
2455}
2456
2457TractionBc::TractionBc(std::string name, std::vector<double> attr, Range faces)
2458 : blockName(name), faces(faces) {
2459 vals.resize(3, false);
2460 flags.resize(3, false);
2461 for (int ii = 0; ii != 3; ++ii) {
2462 vals[ii] = attr[ii];
2463 flags[ii] = static_cast<int>(attr[ii + 3]);
2464 }
2465
2466 MOFEM_LOG("EP", Sev::inform) << "Add BCForce " << name;
2467 MOFEM_LOG("EP", Sev::inform)
2468 << "Add BCForce vals " << vals[0] << " " << vals[1] << " " << vals[2];
2469 MOFEM_LOG("EP", Sev::inform)
2470 << "Add BCForce flags " << flags[0] << " " << flags[1] << " " << flags[2];
2471 MOFEM_LOG("EP", Sev::inform) << "Add BCForce nb. of faces " << faces.size();
2472}
2473
2475 std::vector<double> attr,
2476 Range faces)
2477 : blockName(name), faces(faces) {
2478
2479 blockName = name;
2480 if (attr.size() < 1) {
2482 "Wrong size of normal displacement BC");
2483 }
2484
2485 val = attr[0];
2486
2487 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc " << name;
2488 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc val " << val;
2489 MOFEM_LOG("EP", Sev::inform)
2490 << "Add NormalDisplacementBc nb. of faces " << faces.size();
2491}
2492
2493PressureBc::PressureBc(std::string name, std::vector<double> attr, 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 PressureBc " << name;
2505 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc val " << val;
2506 MOFEM_LOG("EP", Sev::inform)
2507 << "Add PressureBc nb. of faces " << faces.size();
2508}
2509
2510ExternalStrain::ExternalStrain(std::string name, std::vector<double> attr,
2511 Range ents)
2512 : blockName(name), ents(ents) {
2513
2514 blockName = name;
2515 if (attr.size() < 2) {
2517 "Wrong size of external strain attribute");
2518 }
2519
2520 val = attr[0];
2521 bulkModulusK = attr[1];
2522
2523 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain " << name;
2524 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain val " << val;
2525 MOFEM_LOG("EP", Sev::inform)
2526 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2527 MOFEM_LOG("EP", Sev::inform)
2528 << "Add ExternalStrain nb. of tets " << ents.size();
2529}
2530
2532 std::vector<double> attr,
2533 Range faces)
2534 : blockName(name), faces(faces) {
2535
2536 blockName = name;
2537 if (attr.size() < 3) {
2539 "Wrong size of analytical displacement BC");
2540 }
2541
2542 flags.resize(3, false);
2543 for (int ii = 0; ii != 3; ++ii) {
2544 flags[ii] = attr[ii];
2545 }
2546
2547 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalDisplacementBc " << name;
2548 MOFEM_LOG("EP", Sev::inform)
2549 << "Add AnalyticalDisplacementBc flags " << flags[0] << " " << flags[1]
2550 << " " << flags[2];
2551 MOFEM_LOG("EP", Sev::inform)
2552 << "Add AnalyticalDisplacementBc nb. of faces " << faces.size();
2553}
2554
2556 std::vector<double> attr,
2557 Range faces)
2558 : blockName(name), faces(faces) {
2559
2560 blockName = name;
2561 if (attr.size() < 3) {
2563 "Wrong size of analytical traction BC");
2564 }
2565
2566 flags.resize(3, false);
2567 for (int ii = 0; ii != 3; ++ii) {
2568 flags[ii] = attr[ii];
2569 }
2570
2571 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc " << name;
2572 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc flags " << flags[0]
2573 << " " << flags[1] << " " << flags[2];
2574 MOFEM_LOG("EP", Sev::inform)
2575 << "Add AnalyticalTractionBc nb. of faces " << faces.size();
2576}
2577
2580 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2581 const std::string contact_set_name) {
2583
2584 // get skin from all tets
2585 Range tets;
2586 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2587 Range tets_skin_part;
2588 Skinner skin(&mField.get_moab());
2589 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
2590 ParallelComm *pcomm =
2591 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2592 Range tets_skin;
2593 CHKERR pcomm->filter_pstatus(tets_skin_part,
2594 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2595 PSTATUS_NOT, -1, &tets_skin);
2596
2597 bc_ptr->resize(3);
2598 for (int dd = 0; dd != 3; ++dd)
2599 (*bc_ptr)[dd] = tets_skin;
2600
2601 // Do not remove dofs on which traction is applied
2602 if (bcSpatialDispVecPtr)
2603 for (auto &v : *bcSpatialDispVecPtr) {
2604 if (v.flags[0])
2605 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2606 if (v.flags[1])
2607 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2608 if (v.flags[2])
2609 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2610 }
2611
2612 // Do not remove dofs on which rotation is applied
2613 if (bcSpatialRotationVecPtr)
2614 for (auto &v : *bcSpatialRotationVecPtr) {
2615 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2616 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2617 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2618 }
2619
2620 if (bcSpatialNormalDisplacementVecPtr)
2621 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2622 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2623 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2624 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2625 }
2626
2627 if (bcSpatialAnalyticalDisplacementVecPtr)
2628 for (auto &v : *bcSpatialAnalyticalDisplacementVecPtr) {
2629 if (v.flags[0])
2630 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2631 if (v.flags[1])
2632 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2633 if (v.flags[2])
2634 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2635 }
2636
2637 if (bcSpatialTractionVecPtr)
2638 for (auto &v : *bcSpatialTractionVecPtr) {
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 (bcSpatialAnalyticalTractionVecPtr)
2645 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2646 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2647 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2648 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2649 }
2650
2651 if (bcSpatialPressureVecPtr)
2652 for (auto &v : *bcSpatialPressureVecPtr) {
2653 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2654 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2655 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2656 }
2657
2658 // remove contact
2659 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
2660 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
2661 Range faces;
2662 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2663 true);
2664 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2665 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2666 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2667 }
2668
2670}
2671
2672/**
2673 * @brief Set integration rule on element
2674 * \param order on row
2675 * \param order on column
2676 * \param order on data
2677 *
2678 * Use maximal oder on data in order to determine integration rule
2679 *
2680 */
2681struct VolRule {
2682 int operator()(int p_row, int p_col, int p_data) const {
2683 return 2 * p_data + 1;
2684 }
2685};
2686
2687struct FaceRule {
2688 int operator()(int p_row, int p_col, int p_data) const {
2689 return 2 * (p_data + 1);
2690 }
2691};
2692
2694 const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates,
2695 SmartPetscObj<Vec> var_vec,
2696 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe) {
2698
2699 auto bubble_cache =
2700 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
2701 fe->getUserPolynomialBase() =
2702 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2703 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2704 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2705
2706 // set integration rule
2707 fe->getRuleHook = [](int, int, int) { return -1; };
2708 auto vol_rule_lin = [](int o) { return 2 * o + 1; };
2709 auto vol_rule_no_lin = [](int o) { return 2 * o + (o - 1) + 1; };
2710 auto vol_rule = (SMALL_ROT > 0) ? vol_rule_lin : vol_rule_no_lin;
2711 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
2712 vol_rule, bubble_cache);
2713 // fe->getRuleHook = VolRule();
2714
2715 if (!dataAtPts) {
2716 dataAtPts =
2717 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
2718 dataAtPts->physicsPtr = physicalEquations;
2719 }
2720
2721 // calculate fields values
2722 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
2723 piolaStress, dataAtPts->getApproxPAtPts()));
2724 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
2725 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2726 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
2727 piolaStress, dataAtPts->getDivPAtPts()));
2728
2729 if (noStretch) {
2730 fe->getOpPtrVector().push_back(
2731 physicalEquations->returnOpCalculateStretchFromStress(
2732 dataAtPts, physicalEquations));
2733 } else {
2734 fe->getOpPtrVector().push_back(
2736 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2737 }
2738
2739 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2740 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
2741 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2742 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
2743 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2744 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
2745
2746 // H1 displacements
2747 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2748 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
2749 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
2750 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
2751
2752 // velocities
2753 if (calc_rates) {
2754 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
2755 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
2756 if (noStretch) {
2757 } else {
2758 fe->getOpPtrVector().push_back(
2760 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
2761 fe->getOpPtrVector().push_back(
2763 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
2764 MBTET));
2765 }
2766 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
2767 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
2768 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
2769 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
2770
2771 // acceleration
2772 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
2773 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
2774 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
2775 }
2776 }
2777
2778 // variations
2779 if (var_vec.use_count()) {
2780 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
2781 piolaStress, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2782 var_vec));
2783 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
2784 bubbleField, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2785 var_vec, MBMAXTYPE));
2786 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2787 rotAxis, dataAtPts->getVarRotAxisPts(), var_vec, MBTET));
2788 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
2789 piolaStress, dataAtPts->getDivVarPiolaPts(), var_vec));
2790 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
2791 spatialL2Disp, dataAtPts->getVarWL2Pts(), var_vec, MBTET));
2792
2793 if (noStretch) {
2794 fe->getOpPtrVector().push_back(
2795 physicalEquations->returnOpCalculateVarStretchFromStress(
2796 dataAtPts, physicalEquations));
2797 } else {
2798 fe->getOpPtrVector().push_back(
2800 stretchTensor, dataAtPts->getVarLogStreachPts(), var_vec, MBTET));
2801 }
2802 }
2803
2804 // calculate other derived quantities
2805 fe->getOpPtrVector().push_back(new OpCalculateRotationAndSpatialGradient(
2806 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
2807
2808 // evaluate integration points
2809 if (noStretch) {
2810 } else {
2811 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
2812 tag, do_rhs, do_lhs, dataAtPts, physicalEquations));
2813 }
2814
2816}
2817
2819 const int tag, const bool add_elastic, const bool add_material,
2820 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
2821 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
2823
2824 /** Contact requires that body is marked */
2825 auto get_body_range = [this](auto name, int dim) {
2826 std::map<int, Range> map;
2827
2828 for (auto m_ptr :
2829 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2830
2831 (boost::format("%s(.*)") % name).str()
2832
2833 ))
2834
2835 ) {
2836 Range ents;
2837 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
2838 dim, ents, true),
2839 "by dim");
2840 map[m_ptr->getMeshsetId()] = ents;
2841 }
2842
2843 return map;
2844 };
2845
2846 constexpr bool stab_tau_dot_variant = false;
2847
2848 auto local_tau_sacale = boost::make_shared<double>(1.0);
2849 using BoundaryEle =
2851 using BdyEleOp = BoundaryEle::UserDataOperator;
2852 auto set_scale_op = new BdyEleOp(NOSPACE, BdyEleOp::OPSPACE);
2853 set_scale_op->doWorkRhsHook =
2854 [this,
2855 local_tau_sacale](DataOperator *raw_op_ptr, int side, EntityType type,
2858 auto op_ptr = static_cast<BdyEleOp *>(raw_op_ptr);
2859 auto h = std::sqrt(op_ptr->getFTensor1Normal().l2());
2860 *local_tau_sacale = (alphaTau / h);
2862 };
2863
2864 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
2865 auto ent = fe_method_ptr->getFEEntityHandle();
2866 if (
2867
2868 (interfaceFaces->find(ent) != interfaceFaces->end())
2869
2870 || (crackFaces->find(ent) != crackFaces->end())
2871
2872 ) {
2873 return false;
2874 };
2875 return true;
2876 };
2877
2878 // Right hand side
2879 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2880 CHKERR setBaseVolumeElementOps(tag, true, false, true, SmartPetscObj<Vec>(),
2881 fe_rhs);
2882
2883 // elastic
2884 if (add_elastic) {
2885
2886 fe_rhs->getOpPtrVector().push_back(
2887 new OpSpatialEquilibrium(spatialL2Disp, dataAtPts, alphaW, alphaRho));
2888 fe_rhs->getOpPtrVector().push_back(
2889 new OpSpatialRotation(rotAxis, dataAtPts, alphaOmega));
2890 if (noStretch) {
2891 // do nothing - no stretch approximation
2892 } else {
2893 if (!internalStressTagName.empty()) {
2894 switch (internalStressInterpOrder) {
2895 case 0:
2896 fe_rhs->getOpPtrVector().push_back(
2897 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
2898 break;
2899 case 1:
2900 fe_rhs->getOpPtrVector().push_back(
2901 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
2902 break;
2903 default:
2904 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2905 "Unsupported internal stress interpolation order %d",
2906 internalStressInterpOrder);
2907 }
2908 // set default time scaling for interal stresses to constant
2909 TimeScale::ScalingFun def_scaling_fun = [](double time) { return 1; };
2910 auto ts_internal_stress =
2911 boost::make_shared<DynamicRelaxationTimeScale>(
2912 "internal_stress_history.txt", false, def_scaling_fun);
2913 if (internalStressVoigt) {
2914 fe_rhs->getOpPtrVector().push_back(
2916 stretchTensor, dataAtPts, ts_internal_stress));
2917 } else {
2918 fe_rhs->getOpPtrVector().push_back(
2920 stretchTensor, dataAtPts, ts_internal_stress));
2921 }
2922 }
2923 if (auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
2924 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
2925 fe_rhs->getOpPtrVector().push_back(op);
2926 } else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
2927 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2928 "OpSpatialPhysicalExternalStrain not implemented for this "
2929 "material");
2930 }
2931
2932 fe_rhs->getOpPtrVector().push_back(
2933 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
2934 alphaU));
2935 }
2936 fe_rhs->getOpPtrVector().push_back(
2937 new OpSpatialConsistencyP(piolaStress, dataAtPts));
2938 fe_rhs->getOpPtrVector().push_back(
2939 new OpSpatialConsistencyBubble(bubbleField, dataAtPts));
2940 fe_rhs->getOpPtrVector().push_back(
2941 new OpSpatialConsistencyDivTerm(piolaStress, dataAtPts));
2942
2943 auto set_hybridisation_rhs = [&](auto &pip) {
2945
2946 using BoundaryEle =
2948 using EleOnSide =
2950 using SideEleOp = EleOnSide::UserDataOperator;
2951 using BdyEleOp = BoundaryEle::UserDataOperator;
2952
2953 // First: Iterate over skeleton FEs adjacent to Domain FEs
2954 // Note: BoundaryEle, i.e. uses skeleton interation rule
2955 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
2956 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
2957 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
2958 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2959 return -1;
2960 };
2961 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2962 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2963
2964 CHKERR EshelbianPlasticity::
2965 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2966 op_loop_skeleton_side->getOpPtrVector(), {L2},
2967 materialH1Positions, frontAdjEdges);
2968
2969 // Second: Iterate over domain FEs adjacent to skelton, particularly one
2970 // domain element.
2971 auto broken_data_ptr =
2972 boost::make_shared<std::vector<BrokenBaseSideData>>();
2973 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
2974 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
2975 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
2976 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2977 boost::make_shared<CGGUserPolynomialBase>();
2978 CHKERR
2979 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2980 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2981 materialH1Positions, frontAdjEdges);
2982 op_loop_domain_side->getOpPtrVector().push_back(
2983 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
2984 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
2985 op_loop_domain_side->getOpPtrVector().push_back(
2987 flux_mat_ptr));
2988 op_loop_domain_side->getOpPtrVector().push_back(
2989 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
2990
2991 // Assemble on skeleton
2992 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2994 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
2996 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2997 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
2998 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
2999 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3000 op_loop_skeleton_side->getOpPtrVector().push_back(
3001 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3002 hybrid_ptr));
3003 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3004 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3005
3006 // Add skeleton to domain pipeline
3007 pip.push_back(op_loop_skeleton_side);
3008
3010 };
3011
3012 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3013 auto hybrid_field) {
3015
3016 using BoundaryEle =
3018 using EleOnSide =
3020 using SideEleOp = EleOnSide::UserDataOperator;
3021 using BdyEleOp = BoundaryEle::UserDataOperator;
3022
3023 // First: Iterate over skeleton FEs adjacent to Domain FEs
3024 // Note: BoundaryEle, i.e. uses skeleton interation rule
3025 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3026 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3027 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3028 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3029 return -1;
3030 };
3031 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3032 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3033 CHKERR EshelbianPlasticity::
3034 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3035 op_loop_skeleton_side->getOpPtrVector(), {L2},
3036 materialH1Positions, frontAdjEdges);
3037
3038 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3039 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3040 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3041 boost::make_shared<CGGUserPolynomialBase>();
3042 CHKERR
3043 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3044 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3045 materialH1Positions, frontAdjEdges);
3046
3047 // Add stabilization operator
3048 auto broken_disp_data_ptr =
3049 boost::make_shared<std::vector<BrokenBaseSideData>>();
3050 op_loop_domain_side->getOpPtrVector().push_back(
3051 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3052 broken_disp_data_ptr));
3053 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3054 if (stab_tau_dot_variant) {
3055 op_loop_domain_side->getOpPtrVector().push_back(
3057 disp_mat_ptr));
3058 } else {
3059 op_loop_domain_side->getOpPtrVector().push_back(
3061 disp_mat_ptr));
3062 }
3063 // Set diag fluxes on skeleton side
3064 op_loop_domain_side->getOpPtrVector().push_back(
3065 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3066
3067 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3068 op_loop_skeleton_side->getOpPtrVector().push_back(set_scale_op);
3069
3070 // Add stabilization Ugamma Ugamma skeleton
3071 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3072 if (stab_tau_dot_variant) {
3073 op_loop_skeleton_side->getOpPtrVector().push_back(
3075 hybrid_ptr));
3076 } else {
3077 op_loop_skeleton_side->getOpPtrVector().push_back(
3079 hybrid_ptr));
3080 }
3081
3082 // Diag u_gamma - u_gamma faces
3083 op_loop_skeleton_side->getOpPtrVector().push_back(
3085 hybrid_field, hybrid_ptr,
3086 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3087 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3088 }));
3089 // Diag L2 - L2 volumes
3090 op_loop_skeleton_side->getOpPtrVector().push_back(
3092 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3093 return (*local_tau_sacale);
3094 }));
3095 // Off-diag Ugamma - L2
3096 op_loop_skeleton_side->getOpPtrVector().push_back(
3098 hybrid_field, broken_disp_data_ptr,
3099 [local_tau_sacale](double, double, double) {
3100 return -(*local_tau_sacale);
3101 }));
3102 // Off-diag L2 - Ugamma
3103 op_loop_skeleton_side->getOpPtrVector().push_back(
3105 broken_disp_data_ptr, hybrid_ptr,
3106 [local_tau_sacale](double, double, double) {
3107 return -(*local_tau_sacale);
3108 }));
3109
3110 // Add skeleton to domain pipeline
3111 pip.push_back(op_loop_skeleton_side);
3112
3114 };
3115
3116 auto set_contact_rhs = [&](auto &pip) {
3117 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3118 };
3119
3120 auto set_cohesive_rhs = [&](auto &pip) {
3121 return pushCohesiveOpsRhs(
3122 *this,
3123 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges,
3124 [](int p) { return 2 * (p + 1) + 1; }),
3125 interfaceFaces, pip);
3126 };
3127
3128 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3129 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3130 if (alphaTau > 0.0) {
3131 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3132 hybridSpatialDisp);
3133 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), contactElement,
3134 contactDisp);
3135 }
3136 if (intefaceCrack == PETSC_TRUE) {
3137 CHKERR set_cohesive_rhs(fe_rhs->getOpPtrVector());
3138 }
3139
3140 // Body forces
3141 using BodyNaturalBC =
3143 Assembly<PETSC>::LinearForm<GAUSS>;
3144 using OpBodyForce =
3145 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3146
3147 auto body_time_scale =
3148 boost::make_shared<DynamicRelaxationTimeScale>("body_force.txt");
3149 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3150 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3151 "BODY_FORCE", Sev::inform);
3152 }
3153
3154 // Left hand side
3155 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3156 CHKERR setBaseVolumeElementOps(tag, true, true, true, SmartPetscObj<Vec>(),
3157 fe_lhs);
3158
3159 // elastic
3160 if (add_elastic) {
3161
3162 if (noStretch) {
3163 fe_lhs->getOpPtrVector().push_back(
3164 new OpSpatialConsistency_dP_dP(piolaStress, piolaStress, dataAtPts));
3165 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dP(
3166 bubbleField, piolaStress, dataAtPts));
3167 fe_lhs->getOpPtrVector().push_back(
3168 new OpSpatialConsistency_dBubble_dBubble(bubbleField, bubbleField,
3169 dataAtPts));
3170 } else {
3171 fe_lhs->getOpPtrVector().push_back(
3172 physicalEquations->returnOpSpatialPhysical_du_du(
3173 stretchTensor, stretchTensor, dataAtPts, alphaU));
3174 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dP(
3175 stretchTensor, piolaStress, dataAtPts, true));
3176 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dBubble(
3177 stretchTensor, bubbleField, dataAtPts, true));
3178 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_domega(
3179 stretchTensor, rotAxis, dataAtPts,
3180 symmetrySelector == SYMMETRIC ? true : false));
3181 }
3182
3183 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3184 spatialL2Disp, piolaStress, dataAtPts, true));
3185 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3186 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3187
3188 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3189 piolaStress, rotAxis, dataAtPts,
3190 symmetrySelector == SYMMETRIC ? true : false));
3191 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3192 bubbleField, rotAxis, dataAtPts,
3193 symmetrySelector == SYMMETRIC ? true : false));
3194
3195 if (symmetrySelector > SYMMETRIC) {
3196 if (!noStretch) {
3197 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_du(
3198 rotAxis, stretchTensor, dataAtPts, false));
3199 }
3200 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3201 rotAxis, piolaStress, dataAtPts, false));
3202 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3203 rotAxis, bubbleField, dataAtPts, false));
3204 }
3205 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3206 rotAxis, rotAxis, dataAtPts, alphaOmega));
3207
3208 auto set_hybridisation_lhs = [&](auto &pip) {
3210
3211 using BoundaryEle =
3213 using EleOnSide =
3215 using SideEleOp = EleOnSide::UserDataOperator;
3216 using BdyEleOp = BoundaryEle::UserDataOperator;
3217
3218 // First: Iterate over skeleton FEs adjacent to Domain FEs
3219 // Note: BoundaryEle, i.e. uses skeleton interation rule
3220 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3221 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3222 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3223 return -1;
3224 };
3225 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3226 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3227 CHKERR EshelbianPlasticity::
3228 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3229 op_loop_skeleton_side->getOpPtrVector(), {L2},
3230 materialH1Positions, frontAdjEdges);
3231
3232 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3233 // domain element.
3234 auto broken_data_ptr =
3235 boost::make_shared<std::vector<BrokenBaseSideData>>();
3236 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3237 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3238 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3239 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3240 boost::make_shared<CGGUserPolynomialBase>();
3241 CHKERR
3242 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3243 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3244 materialH1Positions, frontAdjEdges);
3245 op_loop_domain_side->getOpPtrVector().push_back(
3246 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3247
3248 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3250 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3251 op_loop_skeleton_side->getOpPtrVector().push_back(
3252 new OpC(hybridSpatialDisp, broken_data_ptr,
3253 boost::make_shared<double>(1.0), true, false));
3254
3255 pip.push_back(op_loop_skeleton_side);
3256
3258 };
3259
3260 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3261 auto hybrid_field) {
3263
3264 using BoundaryEle =
3266 using EleOnSide =
3268 using SideEleOp = EleOnSide::UserDataOperator;
3269 using BdyEleOp = BoundaryEle::UserDataOperator;
3270
3271 // First: Iterate over skeleton FEs adjacent to Domain FEs
3272 // Note: BoundaryEle, i.e. uses skeleton interation rule
3273 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3274 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3275 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3276 return -1;
3277 };
3278 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3279 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3280 CHKERR EshelbianPlasticity::
3281 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3282 op_loop_skeleton_side->getOpPtrVector(), {L2},
3283 materialH1Positions, frontAdjEdges);
3284
3285 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3286 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3287 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3288 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3289 boost::make_shared<CGGUserPolynomialBase>();
3290 CHKERR
3291 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3292 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3293 materialH1Positions, frontAdjEdges);
3294
3295 auto broken_disp_data_ptr =
3296 boost::make_shared<std::vector<BrokenBaseSideData>>();
3297 op_loop_domain_side->getOpPtrVector().push_back(
3298 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3299 broken_disp_data_ptr));
3300 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3301 op_loop_skeleton_side->getOpPtrVector().push_back(set_scale_op);
3302
3303 auto time_shift = [](const FEMethod *fe_ptr) { return fe_ptr->ts_a; };
3304
3305 // Diag Ugamma-Ugamma skeleton
3306 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3307 hybrid_field, hybrid_field,
3308 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3309 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3310 }));
3311 if (stab_tau_dot_variant) {
3312 static_cast<OpMassVectorFace &>(
3313 op_loop_skeleton_side->getOpPtrVector().back())
3314 .feScalingFun = time_shift;
3315 }
3316 // Diag L2-L2 volumes
3317 op_loop_skeleton_side->getOpPtrVector().push_back(
3319 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3320 return (*local_tau_sacale);
3321 }));
3322 if (stab_tau_dot_variant) {
3323 static_cast<OpBrokenBaseBrokenBase &>(
3324 op_loop_skeleton_side->getOpPtrVector().back())
3325 .feScalingFun = time_shift;
3326 }
3327 // Off-diag Ugamma - L2
3328 op_loop_skeleton_side->getOpPtrVector().push_back(
3330 hybrid_field, broken_disp_data_ptr,
3331 [local_tau_sacale](double, double, double) {
3332 return -(*local_tau_sacale);
3333 },
3334 false, false));
3335 if (stab_tau_dot_variant) {
3336 static_cast<OpHyrbridBaseBrokenBase &>(
3337 op_loop_skeleton_side->getOpPtrVector().back())
3338 .feScalingFun = time_shift;
3339 }
3340
3341 // Off-diag L2 - Ugamma
3342 op_loop_skeleton_side->getOpPtrVector().push_back(
3344 hybrid_field, broken_disp_data_ptr,
3345 [local_tau_sacale](double, double, double) {
3346 return -(*local_tau_sacale);
3347 },
3348 true, true));
3349 if (stab_tau_dot_variant) {
3350 static_cast<OpHyrbridBaseBrokenBase &>(
3351 op_loop_skeleton_side->getOpPtrVector().back())
3352 .feScalingFun = time_shift;
3353 }
3354
3355 pip.push_back(op_loop_skeleton_side);
3356
3358 };
3359
3360 auto set_contact_lhs = [&](auto &pip) {
3361 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3362 };
3363
3364 auto set_cohesive_lhs = [&](auto &pip) {
3365 return pushCohesiveOpsLhs(
3366 *this,
3367 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges,
3368 [](int p) { return 2 * (p + 1) + 1; }),
3369 interfaceFaces, pip);
3370 };
3371
3372 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3373 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3374 if (alphaTau > 0.0) {
3375 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3376 hybridSpatialDisp);
3377 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), contactElement,
3378 contactDisp);
3379 }
3380 if (intefaceCrack == PETSC_TRUE) {
3381 CHKERR set_cohesive_lhs(fe_lhs->getOpPtrVector());
3382 }
3383 }
3384
3385 if (add_material) {
3386 }
3387
3389}
3390
3392 const bool add_elastic, const bool add_material,
3393 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3394 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3396
3397 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3398 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3399
3400 // set integration rule
3401 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3402 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3403 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
3404 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
3405 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3406 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3407
3408 CHKERR
3409 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3410 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3411 CHKERR
3412 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3413 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3414
3415 if (add_elastic) {
3416
3417 auto get_broken_op_side = [this](auto &pip) {
3418 using EleOnSide =
3420 using SideEleOp = EleOnSide::UserDataOperator;
3421 // Iterate over domain FEs adjacent to boundary.
3422 auto broken_data_ptr =
3423 boost::make_shared<std::vector<BrokenBaseSideData>>();
3424 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3425 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
3426 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3427 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3428 boost::make_shared<CGGUserPolynomialBase>();
3429 CHKERR
3430 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3431 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3432 materialH1Positions, frontAdjEdges);
3433 op_loop_domain_side->getOpPtrVector().push_back(
3434 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3435 boost::shared_ptr<double> piola_scale_ptr(new double);
3436 op_loop_domain_side->getOpPtrVector().push_back(
3437 physicalEquations->returnOpSetScale(piola_scale_ptr,
3438 physicalEquations));
3439 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3440 op_loop_domain_side->getOpPtrVector().push_back(
3442 flux_mat_ptr));
3443 op_loop_domain_side->getOpPtrVector().push_back(
3444 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3445 pip.push_back(op_loop_domain_side);
3446 return std::make_tuple(broken_data_ptr, piola_scale_ptr);
3447 };
3448
3449 auto set_rhs = [&]() {
3451
3452 auto [broken_data_ptr, piola_scale_ptr] =
3453 get_broken_op_side(fe_rhs->getOpPtrVector());
3454
3455 fe_rhs->getOpPtrVector().push_back(
3456 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
3457 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
3458 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3459 timeScaleMap));
3460 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
3461 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
3462
3463 fe_rhs->getOpPtrVector().push_back(
3464 new OpBrokenTractionBc(hybridSpatialDisp, bcSpatialTractionVecPtr,
3465 piola_scale_ptr, timeScaleMap));
3466 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3467 // if you push gradient of L2 base to physical element, it will not work.
3468 fe_rhs->getOpPtrVector().push_back(
3470 hybridSpatialDisp, hybrid_grad_ptr));
3471 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
3472 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
3473 hybrid_grad_ptr, timeScaleMap));
3474 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
3475 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
3476 timeScaleMap));
3477
3478 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3479 fe_rhs->getOpPtrVector().push_back(
3480 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3481 hybrid_ptr));
3482 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
3483 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
3484 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3485
3486 auto get_normal_disp_bc_faces = [&]() {
3487 auto faces =
3488 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3489 return boost::make_shared<Range>(faces);
3490 };
3491
3492 using BoundaryEle =
3494 using BdyEleOp = BoundaryEle::UserDataOperator;
3496 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3497 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
3498 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3499 get_normal_disp_bc_faces()));
3500
3502 };
3503
3504 auto set_lhs = [&]() {
3506
3507 auto [broken_data_ptr, piola_scale_ptr] =
3508 get_broken_op_side(fe_lhs->getOpPtrVector());
3509
3510 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
3511 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3512 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
3513 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
3514 timeScaleMap));
3515
3516 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3517 // if you push gradient of L2 base to physical element, it will not work.
3518 fe_lhs->getOpPtrVector().push_back(
3520 hybridSpatialDisp, hybrid_grad_ptr));
3521 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
3522 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
3523 timeScaleMap));
3524
3525 auto get_normal_disp_bc_faces = [&]() {
3526 auto faces =
3527 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3528 return boost::make_shared<Range>(faces);
3529 };
3530
3531 using BoundaryEle =
3533 using BdyEleOp = BoundaryEle::UserDataOperator;
3535 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3536 fe_lhs->getOpPtrVector().push_back(new OpC(
3537 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3538 true, true, get_normal_disp_bc_faces()));
3539
3541 };
3542
3543 CHKERR set_rhs();
3544 CHKERR set_lhs();
3545 }
3546
3548}
3549
3551 const bool add_elastic, const bool add_material,
3552 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3553 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3556}
3557
3559
3560 boost::shared_ptr<ForcesAndSourcesCore> &fe_contact_tree
3561
3562) {
3564 fe_contact_tree = createContactDetectionFiniteElement(*this);
3566}
3567
3570
3571 // Add contact operators. Note that only for rhs. THe lhs is assembled with
3572 // volume element, to enable schur complement evaluation.
3573 CHKERR setContactElementRhsOps(contactTreeRhs);
3574
3575 CHKERR setVolumeElementOps(tag, true, false, elasticFeRhs, elasticFeLhs);
3576 CHKERR setFaceElementOps(true, false, elasticBcRhs, elasticBcLhs);
3577
3578 auto adj_cache =
3579 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3580
3581 auto get_op_contact_bc = [&]() {
3583 auto op_loop_side = new OpLoopSide<SideEle>(
3584 mField, contactElement, SPACE_DIM - 1, Sev::noisy, adj_cache);
3585 return op_loop_side;
3586 };
3587
3589}
3590
3593 boost::shared_ptr<FEMethod> null;
3594
3595 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3596
3597 CHKERR DMMoFEMTSSetI2Function(dm, elementVolumeName, elasticFeRhs, null,
3598 null);
3599 CHKERR DMMoFEMTSSetI2Function(dm, naturalBcElement, elasticBcRhs, null,
3600 null);
3601 CHKERR DMMoFEMTSSetI2Jacobian(dm, elementVolumeName, elasticFeLhs, null,
3602 null);
3603 CHKERR DMMoFEMTSSetI2Jacobian(dm, naturalBcElement, elasticBcLhs, null,
3604 null);
3605
3606 } else {
3607 CHKERR DMMoFEMTSSetIFunction(dm, elementVolumeName, elasticFeRhs, null,
3608 null);
3609 CHKERR DMMoFEMTSSetIFunction(dm, naturalBcElement, elasticBcRhs, null,
3610 null);
3611 CHKERR DMMoFEMTSSetIJacobian(dm, elementVolumeName, elasticFeLhs, null,
3612 null);
3613 CHKERR DMMoFEMTSSetIJacobian(dm, naturalBcElement, elasticBcLhs, null,
3614 null);
3615 }
3616
3618}
3619
3622#include "impl/SetUpSchurImpl.cpp"
3623
3625
3626 inline static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x,
3627 bool set_ts_monitor) {
3628
3629#ifdef ENABLE_PYTHON_BINDING
3630 auto setup_sdf = [&]() { return setupContactSdf(); };
3631#endif
3632
3633 auto setup_ts_monitor = [&]() {
3634 boost::shared_ptr<TsCtx> ts_ctx;
3636 "get TS ctx");
3637 if (set_ts_monitor) {
3639 TSMonitorSet(ts, TsMonitorSet, ts_ctx.get(), PETSC_NULLPTR),
3640 "TS monitor set");
3641 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
3642 ts_ctx->getLoopsMonitor().push_back(
3643 TsCtx::PairNameFEMethodPtr(ep_ptr->elementVolumeName, monitor_ptr));
3644 }
3645 MOFEM_LOG("EP", Sev::inform) << "TS monitor setup";
3646 return std::make_tuple(ts_ctx);
3647 };
3648
3649 auto setup_snes_monitor = [&]() {
3651 SNES snes;
3652 CHKERR TSGetSNES(ts, &snes);
3653 auto snes_ctx = getDMSnesCtx(ep_ptr->dmElastic);
3654 CHKERR SNESMonitorSet(snes,
3655 (MoFEMErrorCode(*)(SNES, PetscInt, PetscReal,
3656 void *))MoFEMSNESMonitorEnergy,
3657 (void *)(snes_ctx.get()), PETSC_NULLPTR);
3658 MOFEM_LOG("EP", Sev::inform) << "SNES monitor setup";
3660 };
3661
3662 auto setup_snes_conergence_test = [&]() {
3664
3665 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
3666 PetscReal snorm, PetscReal fnorm,
3667 SNESConvergedReason *reason, void *cctx) {
3669 // EshelbianCore *ep_ptr = (EshelbianCore *)cctx;
3670 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
3671 PETSC_NULLPTR);
3672
3673 Vec x_update, r;
3674 CHKERR SNESGetSolutionUpdate(snes, &x_update);
3675 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
3676
3678 };
3679
3680 // SNES snes;
3681 // CHKERR TSGetSNES(ts, &snes);
3682 // CHKERR SNESSetConvergenceTest(snes, snes_convergence_test, ep_ptr,
3683 // PETSC_NULLPTR);
3684 // MOFEM_LOG("EP", Sev::inform) << "SNES convergence test setup";
3686 };
3687
3688 auto setup_section = [&]() {
3689 PetscSection section_raw;
3690 CHK_THROW_MESSAGE(DMGetSection(ep_ptr->dmElastic, &section_raw),
3691 "get DM section");
3692 int num_fields;
3693 CHK_THROW_MESSAGE(PetscSectionGetNumFields(section_raw, &num_fields),
3694 "get num fields");
3695 for (int ff = 0; ff != num_fields; ff++) {
3696 const char *field_name;
3698 PetscSectionGetFieldName(section_raw, ff, &field_name),
3699 "get field name");
3700 MOFEM_LOG_C("EP", Sev::inform, "Field %d name %s", ff, field_name);
3701 }
3702 return SmartPetscObj<PetscSection>(section_raw, true);
3703 };
3704
3705 auto set_vector_on_mesh = [&]() {
3707 CHKERR DMoFEMMeshToLocalVector(ep_ptr->dmElastic, x, INSERT_VALUES,
3708 SCATTER_FORWARD);
3709 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3710 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3711 MOFEM_LOG("EP", Sev::inform) << "Vector set on mesh";
3713 };
3714
3715 auto setup_schur_block_solver = [&]() {
3716 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver";
3717 CHK_THROW_MESSAGE(TSAppendOptionsPrefix(ts, "elastic_"),
3718 "append options prefix");
3719 CHK_THROW_MESSAGE(TSSetFromOptions(ts), "set from options");
3720 CHK_THROW_MESSAGE(TSSetDM(ts, ep_ptr->dmElastic), "set DM");
3721 // Adding field split solver
3722 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
3723 if constexpr (A == AssemblyType::BLOCK_MAT) {
3724 schur_ptr =
3726 CHK_THROW_MESSAGE(schur_ptr->setUp(ts), "setup schur");
3727 }
3728 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver done";
3729 return schur_ptr;
3730 };
3731
3732 // Warning: sequence of construction is not guaranteed for tuple. You have
3733 // to enforce order by proper packaging.
3734
3735#ifdef ENABLE_PYTHON_BINDING
3736 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
3737 setup_snes_monitor(), setup_snes_conergence_test(),
3738 setup_section(), set_vector_on_mesh(),
3739 setup_schur_block_solver());
3740#else
3741 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
3742 setup_snes_conergence_test(), setup_section(),
3743 set_vector_on_mesh(), setup_schur_block_solver());
3744#endif
3745 }
3746};
3747
3750
3751 PetscBool debug_model = PETSC_FALSE;
3752 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
3753 PETSC_NULLPTR);
3754 MOFEM_LOG("EP", Sev::inform)
3755 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
3756
3757 if (debug_model == PETSC_TRUE) {
3758 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
3759 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
3760 void *ctx) {
3762
3763 SNES snes;
3764 CHKERR TSGetSNES(ts, &snes);
3765 int it;
3766 CHKERR SNESGetIterationNumber(snes, &it);
3767 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
3768 CHKERR postProcessResults(1, file_name, F, u_t);
3769 std::string file_skel_name =
3770 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
3771
3772 auto get_material_force_tag = [&]() {
3773 auto &moab = mField.get_moab();
3774 Tag tag;
3775 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
3776 "can't get tag");
3777 return tag;
3778 };
3779
3780 CHKERR calculateFaceMaterialForce(1, ts);
3781 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
3782 {get_material_force_tag()});
3783
3785 };
3786 ts_ctx_ptr->tsDebugHook = post_proc;
3787 }
3788
3790}
3791
3794
3795 CHKERR addDebugModel(ts);
3796
3797 auto storage = solve_elastic_setup::setup(this, ts, x, true);
3798
3799 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3800 Vec xx;
3801 CHKERR VecDuplicate(x, &xx);
3802 CHKERR VecZeroEntries(xx);
3803 CHKERR TS2SetSolution(ts, x, xx);
3804 CHKERR VecDestroy(&xx);
3805 } else {
3806 CHKERR TSSetSolution(ts, x);
3807 }
3808
3809 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3810 {elasticFeLhs.get(), elasticFeRhs.get()});
3811 CHKERR TSSetUp(ts);
3812 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
3813 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
3815 CHKERR TSSolve(ts, PETSC_NULLPTR);
3817 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3818 {elasticFeLhs.get(), elasticFeRhs.get()});
3819
3820#ifndef NDEBUG
3821 // Make graph
3822 if (mField.get_comm_rank() == 0) {
3823 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
3824 CHKERR PipelineGraph::writeTSGraphGraphviz(ts_ctx_ptr.get(),
3825 "solve_elastic_graph.dot");
3826 }
3827#endif
3828
3829 SNES snes;
3830 CHKERR TSGetSNES(ts, &snes);
3831 int lin_solver_iterations;
3832 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
3833 MOFEM_LOG("EP", Sev::inform)
3834 << "Number of linear solver iterations " << lin_solver_iterations;
3835
3836 PetscBool test_cook_flg = PETSC_FALSE;
3837 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
3838 PETSC_NULLPTR);
3839 if (test_cook_flg) {
3840 constexpr int expected_lin_solver_iterations = 11;
3841 if (lin_solver_iterations > expected_lin_solver_iterations)
3842 SETERRQ(
3843 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3844 "Expected number of iterations is different than expected %d > %d",
3845 lin_solver_iterations, expected_lin_solver_iterations);
3846 }
3847
3848 PetscBool test_sslv116_flag = PETSC_FALSE;
3849 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
3850 &test_sslv116_flag, PETSC_NULLPTR);
3851
3852 if (test_sslv116_flag) {
3853 double max_val = 0.0;
3854 double min_val = 0.0;
3855 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
3857 auto ent_type = ent_ptr->getEntType();
3858 if (ent_type == MBVERTEX) {
3859 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
3860 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
3861 }
3863 };
3864 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
3865 field_min_max, spatialH1Disp);
3866
3867 double global_max_val = 0.0;
3868 double global_min_val = 0.0;
3869 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
3870 mField.get_comm());
3871 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
3872 mField.get_comm());
3873 MOFEM_LOG("EP", Sev::inform)
3874 << "Max " << spatialH1Disp << " value: " << global_max_val;
3875 MOFEM_LOG("EP", Sev::inform)
3876 << "Min " << spatialH1Disp << " value: " << global_min_val;
3877
3878 double ref_max_val = 0.00767;
3879 double ref_min_val = -0.00329;
3880 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
3881 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3882 "Incorrect max value of the displacement field: %f != %f",
3883 global_max_val, ref_max_val);
3884 }
3885 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
3886 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
3887 "Incorrect min value of the displacement field: %f != %f",
3888 global_min_val, ref_min_val);
3889 }
3890 }
3891
3892 CHKERR gettingNorms();
3893
3895}
3896
3898 int start_step,
3899 double start_time) {
3901
3902 auto storage = solve_elastic_setup::setup(this, ts, x, false);
3903
3904 double final_time = 1;
3905 double delta_time = 0.1;
3906 int max_it = 10;
3907 PetscBool ts_h1_update = PETSC_FALSE;
3908
3909 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
3910
3911 CHKERR PetscOptionsScalar("-dynamic_final_time",
3912 "dynamic relaxation final time", "", final_time,
3913 &final_time, PETSC_NULLPTR);
3914 CHKERR PetscOptionsScalar("-dynamic_delta_time",
3915 "dynamic relaxation final time", "", delta_time,
3916 &delta_time, PETSC_NULLPTR);
3917 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
3918 max_it, &max_it, PETSC_NULLPTR);
3919 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
3920 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
3921
3922 PetscOptionsEnd();
3923
3924 MOFEM_LOG("EP", Sev::inform)
3925 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
3926 MOFEM_LOG("EP", Sev::inform)
3927 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
3928 MOFEM_LOG("EP", Sev::inform)
3929 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
3930 MOFEM_LOG("EP", Sev::inform)
3931 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
3932 << (ts_h1_update ? "TRUE" : "FALSE");
3933
3934 CHKERR addDebugModel(ts);
3935
3936 auto setup_ts_monitor = [&]() {
3937 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
3938 return monitor_ptr;
3939 };
3940 auto monitor_ptr = setup_ts_monitor();
3941
3942 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3943 {elasticFeLhs.get(), elasticFeRhs.get()});
3944 CHKERR TSSetUp(ts);
3946
3947 double ts_delta_time;
3948 CHKERR TSGetTimeStep(ts, &ts_delta_time);
3949
3950 if (ts_h1_update) {
3951 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
3952 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
3953 }
3954
3957
3958 dynamicTime = start_time;
3959 dynamicStep = start_step;
3960 monitor_ptr->ts_u = PETSC_NULLPTR;
3961 monitor_ptr->ts_t = dynamicTime;
3962 monitor_ptr->ts_step = dynamicStep;
3963 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
3964
3965 for (; dynamicTime < final_time; dynamicTime += delta_time) {
3966 MOFEM_LOG("EP", Sev::inform) << "Load step " << dynamicStep << " Time "
3967 << dynamicTime << " delta time " << delta_time;
3968
3969 CHKERR TSSetStepNumber(ts, 0);
3970 CHKERR TSSetTime(ts, 0);
3971 CHKERR TSSetTimeStep(ts, ts_delta_time);
3972 if (!ts_h1_update) {
3974 }
3975 CHKERR TSSetSolution(ts, x);
3976 CHKERR TSSolve(ts, PETSC_NULLPTR);
3977 if (!ts_h1_update) {
3979 }
3980
3981 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
3982 SCATTER_FORWARD);
3983 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3984 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3985
3986 monitor_ptr->ts_u = x;
3987 monitor_ptr->ts_t = dynamicTime;
3988 monitor_ptr->ts_step = dynamicStep;
3989 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
3990
3991 ++dynamicStep;
3992 if (dynamicStep > max_it)
3993 break;
3994 }
3995
3997 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3998 {elasticFeLhs.get(), elasticFeRhs.get()});
3999
4001}
4002
4005
4006 auto set_block = [&](auto name, int dim) {
4007 std::map<int, Range> map;
4008 auto set_tag_impl = [&](auto name) {
4010 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4011 auto bcs = mesh_mng->getCubitMeshsetPtr(
4012
4013 std::regex((boost::format("%s(.*)") % name).str())
4014
4015 );
4016 for (auto bc : bcs) {
4017 Range r;
4018 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4019 true);
4020 map[bc->getMeshsetId()] = r;
4021 MOFEM_LOG("EP", Sev::inform)
4022 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4023 << r.size() << " entities";
4024 }
4026 };
4027
4028 CHKERR set_tag_impl(name);
4029
4030 return std::make_pair(name, map);
4031 };
4032
4033 auto set_skin = [&](auto &&map) {
4034 for (auto &m : map.second) {
4035 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4036 m.second.swap(s);
4037 MOFEM_LOG("EP", Sev::inform)
4038 << "Skin for block " << map.first << " id " << m.first << " has "
4039 << m.second.size() << " entities";
4040 }
4041 return map;
4042 };
4043
4044 auto set_tag = [&](auto &&map) {
4045 Tag th;
4046 auto name = map.first;
4047 int def_val[] = {-1};
4049 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4050 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4051 "create tag");
4052 for (auto &m : map.second) {
4053 int id = m.first;
4054 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4055 "clear tag");
4056 }
4057 return th;
4058 };
4059
4060 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4061 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4062 listTagsToTransfer.push_back(
4063 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4064 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4065
4067}
4068
4070EshelbianCore::postProcessResults(const int tag, const std::string file,
4071 Vec f_residual, Vec var_vector,
4072 std::vector<Tag> tags_to_transfer) {
4074
4075 // mark crack surface
4076 if (crackingOn) {
4077 auto get_tag = [&](auto name, auto dim) {
4078 auto &mob = mField.get_moab();
4079 Tag tag;
4080 double def_val[] = {0., 0., 0.};
4081 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4082 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4083 "create tag");
4084 return tag;
4085 };
4086 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4087 }
4088
4089 {
4090 auto get_crack_tag = [&]() {
4091 Tag th;
4092 rval = mField.get_moab().tag_get_handle("CRACK", th);
4093 if (rval == MB_SUCCESS) {
4094 MOAB_THROW(mField.get_moab().tag_delete(th));
4095 }
4096 int def_val[] = {0};
4097 MOAB_THROW(mField.get_moab().tag_get_handle(
4098 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4099 def_val));
4100 return th;
4101 };
4102
4103 Tag th = get_crack_tag();
4104 tags_to_transfer.push_back(th);
4105 int mark[] = {1};
4106 Range mark_faces;
4107 if (crackFaces)
4108 mark_faces.merge(*crackFaces);
4109 if (interfaceFaces)
4110 mark_faces.merge(*interfaceFaces);
4111 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4112 }
4113
4114 // add tags to transfer
4115 for (auto t : listTagsToTransfer) {
4116 tags_to_transfer.push_back(t);
4117 }
4118
4119 if (!dataAtPts) {
4120 dataAtPts =
4121 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
4122 }
4123
4124 CHKERR DMoFEMLoopFiniteElements(dM, contactElement, contactTreeRhs);
4125
4126 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
4128 auto post_proc_ptr =
4129 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4130 mField, post_proc_mesh);
4131 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4132 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4133 frontAdjEdges);
4134
4135 auto domain_ops = [&](auto &fe, int sense) {
4137 fe.getUserPolynomialBase() =
4138 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase());
4139 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4140 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
4141 frontAdjEdges);
4142 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4143 fe.getOpPtrVector().push_back(physicalEquations->returnOpSetScale(
4144 piola_scale_ptr, physicalEquations));
4145 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4146 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
4147 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4148 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
4149 SmartPetscObj<Vec>(), MBMAXTYPE));
4150 if (noStretch) {
4151 fe.getOpPtrVector().push_back(
4152 physicalEquations->returnOpCalculateStretchFromStress(
4153 dataAtPts, physicalEquations));
4154 } else {
4155 fe.getOpPtrVector().push_back(
4157 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4158 }
4159 if (var_vector) {
4160 auto vec = SmartPetscObj<Vec>(var_vector, true);
4161 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4162 piolaStress, dataAtPts->getVarPiolaPts(),
4163 boost::make_shared<double>(1), vec));
4164 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4165 bubbleField, dataAtPts->getVarPiolaPts(),
4166 boost::make_shared<double>(1), vec, MBMAXTYPE));
4167 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4168 rotAxis, dataAtPts->getVarRotAxisPts(), vec, MBTET));
4169 if (noStretch) {
4170 fe.getOpPtrVector().push_back(
4171 physicalEquations->returnOpCalculateVarStretchFromStress(
4172 dataAtPts, physicalEquations));
4173 } else {
4174 fe.getOpPtrVector().push_back(
4176 stretchTensor, dataAtPts->getVarLogStreachPts(), vec, MBTET));
4177 }
4178 }
4179
4180 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4181 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4182 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4183 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
4184
4185 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4186 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4187 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4188 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
4189 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
4190 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
4191 // evaluate derived quantities
4192 fe.getOpPtrVector().push_back(
4194
4195 // evaluate integration points
4196 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
4197 tag, true, false, dataAtPts, physicalEquations));
4198 if (auto op =
4199 physicalEquations->returnOpCalculateEnergy(dataAtPts, nullptr)) {
4200 fe.getOpPtrVector().push_back(op);
4201 fe.getOpPtrVector().push_back(new OpCalculateEshelbyStress(dataAtPts));
4202 }
4203
4204 // // post-proc
4208
4209 struct OpSidePPMap : public OpPPMap {
4210 OpSidePPMap(moab::Interface &post_proc_mesh,
4211 std::vector<EntityHandle> &map_gauss_pts,
4212 DataMapVec data_map_scalar, DataMapMat data_map_vec,
4213 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
4214 int sense)
4215 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
4216 data_map_vec, data_map_mat, data_symm_map_mat),
4217 tagSense(sense) {}
4218
4219 MoFEMErrorCode doWork(int side, EntityType type,
4222
4223 if (tagSense != 0) {
4224 if (tagSense != OpPPMap::getSkeletonSense())
4226 }
4227
4228 CHKERR OpPPMap::doWork(side, type, data);
4230 }
4231
4232 private:
4233 int tagSense;
4234 };
4235
4236 OpPPMap::DataMapMat vec_fields;
4237 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
4238 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
4239 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
4240 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
4241 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
4242 if (!noStretch) {
4243 vec_fields["EiegnLogStreach"] = dataAtPts->getEigenValsAtPts();
4244 }
4245 if (var_vector) {
4246 auto vec = SmartPetscObj<Vec>(var_vector, true);
4247 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
4248 vec_fields["VarSpatialDisplacementL2"] =
4249 boost::make_shared<MatrixDouble>();
4250 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4251 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], vec, MBTET));
4252 }
4253 if (f_residual) {
4254 auto vec = SmartPetscObj<Vec>(f_residual, true);
4255 vec_fields["ResSpatialDisplacementL2"] =
4256 boost::make_shared<MatrixDouble>();
4257 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4258 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], vec, MBTET));
4259 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
4260 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4261 rotAxis, vec_fields["ResOmega"], vec, MBTET));
4262 }
4263
4264 OpPPMap::DataMapMat mat_fields;
4265 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
4266 if (var_vector) {
4267 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
4268 }
4269 if (f_residual) {
4270 auto vec = SmartPetscObj<Vec>(f_residual, true);
4271 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
4272 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4273 piolaStress, mat_fields["ResPiolaStress"],
4274 boost::make_shared<double>(1), vec));
4275 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4276 bubbleField, mat_fields["ResPiolaStress"],
4277 boost::make_shared<double>(1), vec, MBMAXTYPE));
4278 }
4279 if (!internalStressTagName.empty()) {
4280 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
4281 switch (internalStressInterpOrder) {
4282 case 0:
4283 fe.getOpPtrVector().push_back(
4284 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
4285 break;
4286 case 1:
4287 fe.getOpPtrVector().push_back(
4288 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
4289 break;
4290 default:
4291 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4292 "Unsupported internal stress interpolation order %d",
4293 internalStressInterpOrder);
4294 }
4295 }
4296
4297 OpPPMap::DataMapMat mat_fields_symm;
4298 mat_fields_symm["LogSpatialStretch"] =
4299 dataAtPts->getLogStretchTensorAtPts();
4300 mat_fields_symm["SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
4301 if (var_vector) {
4302 mat_fields_symm["VarLogSpatialStretch"] =
4303 dataAtPts->getVarLogStreachPts();
4304 }
4305 if (f_residual) {
4306 auto vec = SmartPetscObj<Vec>(f_residual, true);
4307 if (!noStretch) {
4308 mat_fields_symm["ResLogSpatialStretch"] =
4309 boost::make_shared<MatrixDouble>();
4310 fe.getOpPtrVector().push_back(
4312 stretchTensor, mat_fields_symm["ResLogSpatialStretch"], vec,
4313 MBTET));
4314 }
4315 }
4316
4317 fe.getOpPtrVector().push_back(
4318
4319 new OpSidePPMap(
4320
4321 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4322
4323 {},
4324
4325 vec_fields,
4326
4327 mat_fields,
4328
4329 mat_fields_symm,
4330
4331 sense
4332
4333 )
4334
4335 );
4336
4337 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
4338 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4339 dataAtPts, sense));
4340
4342 };
4343
4344 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
4345 // H1 material positions
4346 post_proc_ptr->getOpPtrVector().push_back(
4347 new OpCalculateVectorFieldValues<3>(materialH1Positions,
4348 dataAtPts->getLargeXH1AtPts()));
4349
4350 // domain
4352 mField, elementVolumeName, SPACE_DIM);
4353 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
4354 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
4355
4356 return post_proc_ptr;
4357 };
4358
4359 // contact
4360 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
4361 auto &pip) {
4363 // evaluate traction
4364 using EleOnSide =
4366 using SideEleOp = EleOnSide::UserDataOperator;
4367 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4368 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4369 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4370 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase());
4371 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4372 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4373 materialH1Positions, frontAdjEdges);
4374 auto traction_ptr = boost::make_shared<MatrixDouble>();
4375 op_loop_domain_side->getOpPtrVector().push_back(
4377 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
4378
4379 pip.push_back(new OpCalculateVectorFieldValues<3>(
4380 contactDisp, dataAtPts->getContactL2AtPts()));
4381 pip.push_back(op_loop_domain_side);
4382 // evaluate contact displacement and contact conditions
4383 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4384 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
4385 pip.push_back(getOpContactDetection(
4386 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
4387 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
4388 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4389
4391 using BoundaryEle =
4393 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
4394 op_this->getOpPtrVector().push_back(
4395
4396 new OpPPMap(
4397
4398 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4399
4400 {},
4401
4402 {{"ContactDisplacement", dataAtPts->getContactL2AtPts()}},
4403
4404 {},
4405
4406 {}
4407
4408 )
4409
4410 );
4411
4412 if (f_residual) {
4413
4414 pip.push_back(op_this);
4415 auto contact_residual = boost::make_shared<MatrixDouble>();
4416 op_this->getOpPtrVector().push_back(
4418 contactDisp, contact_residual,
4419 SmartPetscObj<Vec>(f_residual, true)));
4420 op_this->getOpPtrVector().push_back(
4421
4422 new OpPPMap(
4423
4424 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4425
4426 {},
4427
4428 {{"res_contact", contact_residual}},
4429
4430 {},
4431
4432 {}
4433
4434 )
4435
4436 );
4437 }
4438
4440 };
4441
4442 auto post_proc_mesh = boost::make_shared<moab::Core>();
4443 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
4444 auto post_proc_negative_sense_ptr =
4445 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
4446 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
4447 CHKERR calcs_side_traction_and_displacements(
4448 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
4449
4450 auto own_tets =
4451 CommInterface::getPartEntities(mField.get_moab(), mField.get_comm_rank())
4452 .subset_by_dimension(SPACE_DIM);
4453 Range own_faces;
4454 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
4455 own_faces, moab::Interface::UNION);
4456
4457 auto get_crack_faces = [&](auto crack_faces) {
4458 auto get_adj = [&](auto e, auto dim) {
4459 Range adj;
4460 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
4461 moab::Interface::UNION);
4462 return adj;
4463 };
4464 // this removes faces
4465 auto tets = get_adj(crack_faces, 3);
4466 // faces adjacent to tets not in crack_faces
4467 auto faces = subtract(get_adj(tets, 2), crack_faces);
4468 // what is left from below, are tets fully inside crack_faces
4469 tets = subtract(tets, get_adj(faces, 3));
4470 return subtract(crack_faces, get_adj(tets, 2));
4471 };
4472
4473 auto side_one_faces = [&](auto &faces) {
4474 std::pair<Range, Range> sides;
4475 for (auto f : faces) {
4476 Range adj;
4477 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
4478 adj = intersect(own_tets, adj);
4479 for (auto t : adj) {
4480 int side, sense, offset;
4481 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
4482 if (sense == 1) {
4483 sides.first.insert(f);
4484 } else {
4485 sides.second.insert(f);
4486 }
4487 }
4488 }
4489 return sides;
4490 };
4491
4492 auto crack_faces =
4493 unite(get_crack_faces(*crackFaces), get_crack_faces(*interfaceFaces));
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();
5134 CHKERR CommInterface::setVectorFromTag(mField.get_moab(), kappa_vec,
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);
5140 CHKERR CommInterface::setTagFromVector(mField.get_moab(), kappa_vec,
5141 get_kappa_tag(mField.get_moab()));
5142
5143 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5144 SCATTER_FORWARD);
5145 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5146 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5147 monitor_ptr->ts_u = x;
5148 monitor_ptr->ts_t = dynamicTime;
5149 monitor_ptr->ts_step = dynamicStep;
5151
5152 ++dynamicStep;
5153 if (dynamicStep > max_it)
5154 break;
5155 }
5156
5157 CHKERR TSElasticPostStep::postStepDestroy();
5158 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5159 {elasticFeLhs.get(), elasticFeRhs.get()});
5160
5162}
5163
5164} // namespace EshelbianPlasticity
5165
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.
Add cohesive elements to Eshelbian plasticity module.
#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:3283
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.
@ GAUSS
Gaussian quadrature integration.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
virtual MoFEMErrorCode loop_finite_elements(const std::string problem_name, const std::string &fe_name, FEMethod &method, boost::shared_ptr< NumeredEntFiniteElement_multiIndex > fe_ptr=nullptr, MoFEMTypes bh=MF_EXIST, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr(), int verb=DEFAULT_VERBOSITY)=0
Make a loop over finite elements.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
MoFEMErrorCode 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:652
static const bool debug
auto id_from_handle(const EntityHandle h)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PostProcBrokenMeshInMoabBaseEndImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseEnd
Enable to run stack of post-processing elements. Use this to end stack.
PostProcBrokenMeshInMoabBaseBeginImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseBegin
Enable to run stack of post-processing elements. Use this to begin stack.
PetscErrorCode 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, SmartPetscObj< Vec > ver_vec, 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
boost::shared_ptr< Range > skeletonFaces
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)
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
static PetscBool intefaceCrack
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 EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, int dim, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0)
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
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)
Operator for linear form, usually to calculate values on right hand side.
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