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