v0.16.0
Loading...
Searching...
No Matches
EshelbianPlasticity.cpp
Go to the documentation of this file.
1/**
2 * \file EshelbianPlasticity.cpp
3 * \example
4 * mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp
5 *
6 * \brief Eshelbian plasticity implementation
7 *
8 * \copyright 2024. Various authors, some of them anonymous contributors under
9 * MiT core contributors license agreement.
10 */
11
12#define SINGULARITY
13#include <MoFEM.hpp>
14#include <IntegrationRules.hpp>
15
16#ifdef INCLUDE_MBCOUPLER
17 #include <mbcoupler/Coupler.hpp>
18#endif
19using namespace MoFEM;
20
22
24#include <boost/math/constants/constants.hpp>
25
26#include <cholesky.hpp>
27#ifdef ENABLE_PYTHON_BINDING
28 #include <boost/python.hpp>
29 #include <boost/python/def.hpp>
30 #include <boost/python/numpy.hpp>
31namespace bp = boost::python;
32namespace np = boost::python::numpy;
33#endif
34
35#include <EshelbianAux.hpp>
36#include <EshelbianCohesive.hpp>
37#include <EshelbianContact.hpp>
39#include <TSElasticPostStep.hpp>
40
41extern "C" {
42#include <phg-quadrule/quad.h>
43}
44
45#include <queue>
46
47namespace EshelbianPlasticity {
56
57} // namespace EshelbianPlasticity
58
59static auto send_type(MoFEM::Interface &m_field, Range r,
60 const EntityType type) {
61 ParallelComm *pcomm =
62 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
63
64 auto dim = CN::Dimension(type);
65
66 std::vector<int> sendcounts(pcomm->size());
67 std::vector<int> displs(pcomm->size());
68 std::vector<int> sendbuf(r.size());
69 if (pcomm->rank() == 0) {
70 for (auto p = 1; p != pcomm->size(); p++) {
71 auto part_ents = m_field.getInterface<CommInterface>()
72 ->getPartEntities(m_field.get_moab(), p)
73 .subset_by_dimension(SPACE_DIM);
74 Range faces;
75 CHKERR m_field.get_moab().get_adjacencies(part_ents, dim, true, faces,
76 moab::Interface::UNION);
77 faces = intersect(faces, r);
78 sendcounts[p] = faces.size();
79 displs[p] = sendbuf.size();
80 for (auto f : faces) {
81 auto id = id_from_handle(f);
82 sendbuf.push_back(id);
83 }
84 }
85 }
86
87 int recv_data;
88 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
89 pcomm->comm());
90 std::vector<int> recvbuf(recv_data);
91 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
92 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
93
94 if (pcomm->rank() > 0) {
95 Range r;
96 for (auto &f : recvbuf) {
97 r.insert(ent_form_type_and_id(type, f));
98 }
99 return r;
100 }
101
102 return r;
103}
104
106 const std::string block_name) {
107 Range r;
108
109 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
110 auto bcs = mesh_mng->getCubitMeshsetPtr(
111
112 std::regex((boost::format("%s(.*)") % block_name).str())
113
114 );
115
116 for (auto bc : bcs) {
117 auto meshset = bc->getMeshset();
118 CHK_MOAB_THROW(m_field.get_moab().get_entities_by_handle(meshset, r, true),
119 "get meshset ents");
120 }
121
122 return r;
123};
124
126 const std::string block_name, int dim) {
127 Range r;
128
129 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
130 auto bcs = mesh_mng->getCubitMeshsetPtr(
131
132 std::regex((boost::format("%s(.*)") % block_name).str())
133
134 );
135
136 for (auto bc : bcs) {
137 Range faces;
138 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
139 faces, true),
140 "get meshset ents");
141 r.merge(faces);
142 }
143
144 return r;
145};
146
148 const std::string block_name, int dim) {
149 std::map<std::string, Range> r;
150
151 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
152 auto bcs = mesh_mng->getCubitMeshsetPtr(
153
154 std::regex((boost::format("%s(.*)") % block_name).str())
155
156 );
157
158 for (auto bc : bcs) {
159 Range faces;
160 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
161 faces, true),
162 "get meshset ents");
163 r[bc->getName()] = faces;
164 }
165
166 return r;
167}
168
169static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id,
170 const unsigned int cubit_bc_type) {
171 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
172 EntityHandle meshset;
173 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
174 return meshset;
175};
176
177static auto save_range(moab::Interface &moab, const std::string name,
178 const Range r, std::vector<Tag> tags = {}) {
180 auto out_meshset = get_temp_meshset_ptr(moab);
181 CHKERR moab.add_entities(*out_meshset, r);
182 if (r.size()) {
183 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
184 tags.data(), tags.size());
185 } else {
186 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
187 }
189};
190
191static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin) {
192 Range boundary_ents;
193 ParallelComm *pcomm =
194 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
195 CHK_MOAB_THROW(pcomm->filter_pstatus(skin,
196 PSTATUS_SHARED | PSTATUS_MULTISHARED,
197 PSTATUS_NOT, -1, &boundary_ents),
198 "filter_pstatus");
199 return boundary_ents;
200};
201
202static auto filter_owners(MoFEM::Interface &m_field, Range skin) {
203 Range owner_ents;
204 ParallelComm *pcomm =
205 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
206 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
207 &owner_ents),
208 "filter_pstatus");
209 return owner_ents;
210};
211
212static auto get_skin(MoFEM::Interface &m_field, Range body_ents) {
213 Skinner skin(&m_field.get_moab());
214 Range skin_ents;
215 CHK_MOAB_THROW(skin.find_skin(0, body_ents, false, skin_ents), "find_skin");
216 return skin_ents;
217};
218
220 Range crack_faces) {
221 ParallelComm *pcomm =
222 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
223 auto &moab = m_field.get_moab();
224 Range crack_skin_without_bdy;
225 if (pcomm->rank() == 0) {
226 Range crack_edges;
227 CHKERR moab.get_adjacencies(crack_faces, 1, true, crack_edges,
228 moab::Interface::UNION);
229 auto crack_skin = get_skin(m_field, crack_faces);
230 Range body_ents;
232 m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents),
233 "get_entities_by_dimension");
234 auto body_skin = get_skin(m_field, body_ents);
235 Range body_skin_edges;
236 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1, true, body_skin_edges,
237 moab::Interface::UNION),
238 "get_adjacencies");
239 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
240 auto front_edges_map = get_range_from_block_map(m_field, "FRONT", 1);
241 for (auto &m : front_edges_map) {
242 auto add_front = subtract(m.second, crack_edges);
243 auto i = intersect(m.second, crack_edges);
244 if (i.empty()) {
245 crack_skin_without_bdy.merge(add_front);
246 } else {
247 auto i_skin = get_skin(m_field, i);
248 Range adj_i_skin;
249 CHKERR moab.get_adjacencies(i_skin, 1, true, adj_i_skin,
250 moab::Interface::UNION);
251 adj_i_skin = subtract(intersect(adj_i_skin, m.second), crack_edges);
252 crack_skin_without_bdy.merge(adj_i_skin);
253 }
254 }
255 }
256 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
257}
258
260 Range crack_faces) {
261
262 ParallelComm *pcomm =
263 ParallelComm::get_pcomm(&m_field.get_moab(), MYPCOMM_INDEX);
264
265 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface";
266
267 if (!pcomm->rank()) {
268
269 auto impl = [&](auto &saids) {
271
272 auto &moab = m_field.get_moab();
273
274 auto get_adj = [&](auto e, auto dim) {
275 Range adj;
276 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(
277 e, dim, true, adj, moab::Interface::UNION),
278 "get adj");
279 return adj;
280 };
281
282 auto get_conn = [&](auto e) {
283 Range conn;
284 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(e, conn, true),
285 "get connectivity");
286 return conn;
287 };
288
289 constexpr bool debug = false;
290 Range body_ents;
291 CHKERR m_field.get_moab().get_entities_by_dimension(0, SPACE_DIM,
292 body_ents);
293 auto body_skin = get_skin(m_field, body_ents);
294 auto body_skin_edges = get_adj(body_skin, 1);
295
296 auto crack_skin =
297 subtract(get_skin(m_field, crack_faces), body_skin_edges);
298 auto crack_skin_conn = get_conn(crack_skin);
299 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
300 auto crack_edges = get_adj(crack_faces, 1);
301 crack_edges = subtract(crack_edges, crack_skin);
302 auto all_tets = get_adj(crack_edges, 3);
303 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
304 auto crack_conn = get_conn(crack_edges);
305 all_tets.merge(get_adj(crack_conn, 3));
306
307 if (debug) {
308 CHKERR save_range(m_field.get_moab(), "crack_faces.vtk", crack_faces);
309 CHKERR save_range(m_field.get_moab(), "all_crack_tets.vtk", all_tets);
310 CHKERR save_range(m_field.get_moab(), "crack_edges_all.vtk",
311 crack_edges);
312 }
313
314 if (crack_faces.size()) {
315 auto grow = [&](auto r) {
316 auto crack_faces_conn = get_conn(crack_faces);
317 Range v;
318 auto size_r = 0;
319 while (size_r != r.size() && r.size() > 0) {
320 size_r = r.size();
321 CHKERR moab.get_connectivity(r, v, true);
322 v = subtract(v, crack_faces_conn);
323 if (v.size()) {
324 CHKERR moab.get_adjacencies(v, SPACE_DIM, true, r,
325 moab::Interface::UNION);
326 r = intersect(r, all_tets);
327 }
328 if (r.empty()) {
329 break;
330 }
331 }
332 return r;
333 };
334
335 Range all_tets_ord = all_tets;
336 while (all_tets.size()) {
337 Range faces = get_adj(unite(saids.first, saids.second), 2);
338 faces = subtract(crack_faces, faces);
339 if (faces.size()) {
340 Range tets;
341 auto fit = faces.begin();
342 for (; fit != faces.end(); ++fit) {
343 tets = intersect(get_adj(Range(*fit, *fit), 3), all_tets);
344 if (tets.size() == 2) {
345 break;
346 }
347 }
348 if (tets.empty()) {
349 break;
350 } else {
351 saids.first.insert(tets[0]);
352 saids.first = grow(saids.first);
353 all_tets = subtract(all_tets, saids.first);
354 if (tets.size() == 2) {
355 saids.second.insert(tets[1]);
356 saids.second = grow(saids.second);
357 all_tets = subtract(all_tets, saids.second);
358 }
359 }
360 } else {
361 break;
362 }
363 }
364
365 saids.first = subtract(all_tets_ord, saids.second);
366 saids.second = subtract(all_tets_ord, saids.first);
367 }
368
370 };
371
372 std::pair<Range, Range> saids;
373 if (crack_faces.size())
374 CHK_THROW_MESSAGE(impl(saids), "get crack both sides");
375 return saids;
376 }
377
378 MOFEM_LOG("EP", Sev::noisy) << "get_two_sides_of_crack_surface <- done";
379
380 return std::pair<Range, Range>();
381}
382
383namespace EshelbianPlasticity {
384
385auto vol_rule(int o) { return 2 * (o + 1); };
386auto face_rule(int o) { return 2 * (o + 1); };
387
389
390 using FunRule = boost::function<int(int)>;
392
394 boost::shared_ptr<Range> front_nodes,
395 boost::shared_ptr<Range> front_edges,
396 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
397 : funRule(vol_rule), frontNodes(front_nodes), frontEdges(front_edges),
398 cachePhi(cache_phi) {};
399
401 boost::shared_ptr<Range> front_nodes,
402 boost::shared_ptr<Range> front_edges, FunRule fun_rule,
403 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cache_phi = nullptr)
404 : funRule(fun_rule), frontNodes(front_nodes), frontEdges(front_edges),
405 cachePhi(cache_phi) {};
406
408 int order_col, int order_data) {
410
411 constexpr bool debug = false;
412
413 constexpr int numNodes = 4;
414 constexpr int numEdges = 6;
415 constexpr int refinementLevels = 6;
416
417 auto &m_field = fe_raw_ptr->mField;
418 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
419 auto fe_handle = fe_ptr->getFEEntityHandle();
420
421 auto set_base_quadrature = [&]() {
423 if (!funRule) {
425 }
426 const int rule = funRule(order_data);
427 const auto xiao_rule =
429 if (!xiao_rule) {
430 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
431 "Xiao--Gimbutas tetrahedron rule is available for polynomial "
432 "orders 0 to %d; requested %d",
434 }
435 if (xiao_rule->numBarycentricCoordinates != 4) {
436 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
437 "wrong number of tetrahedron barycentric coordinates");
438 }
439
440 const size_t nb_gauss_pts = xiao_rule->numPoints;
441 auto &gauss_pts = fe_ptr->gaussPts;
442 gauss_pts.resize(4, nb_gauss_pts, false);
443 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[1], 4, &gauss_pts(0, 0),
444 1);
445 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[2], 4, &gauss_pts(1, 0),
446 1);
447 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[3], 4, &gauss_pts(2, 0),
448 1);
449 cblas_dcopy(nb_gauss_pts, xiao_rule->weights, 1, &gauss_pts(3, 0), 1);
450 auto &data = fe_ptr->dataOnElement[H1];
451 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4,
452 false);
453 double *shape_ptr =
454 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
455 cblas_dcopy(4 * nb_gauss_pts, xiao_rule->points, 1, shape_ptr, 1);
457 };
458
459 CHKERR set_base_quadrature();
460
462
463 auto get_singular_nodes = [&]() {
464 int num_nodes;
465 const EntityHandle *conn;
466 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
467 true);
468 std::bitset<numNodes> singular_nodes;
469 for (auto nn = 0; nn != numNodes; ++nn) {
470 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
471 singular_nodes.set(nn);
472 } else {
473 singular_nodes.reset(nn);
474 }
475 }
476 return singular_nodes;
477 };
478
479 auto get_singular_edges = [&]() {
480 std::bitset<numEdges> singular_edges;
481 for (int ee = 0; ee != numEdges; ee++) {
482 EntityHandle edge;
483 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
484 if (frontEdges->find(edge) != frontEdges->end()) {
485 singular_edges.set(ee);
486 } else {
487 singular_edges.reset(ee);
488 }
489 }
490 return singular_edges;
491 };
492
493 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
495 fe_ptr->gaussPts.swap(ref_gauss_pts);
496 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
497 auto &data = fe_ptr->dataOnElement[H1];
498 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
499 double *shape_ptr =
500 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
501 CHKERR ShapeMBTET(shape_ptr, &fe_ptr->gaussPts(0, 0),
502 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
503 nb_gauss_pts);
505 };
506
507 auto singular_nodes = get_singular_nodes();
508 if (singular_nodes.count()) {
509 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
510 if (it_map_ref_coords != mapRefCoords.end()) {
511 CHKERR set_gauss_pts(it_map_ref_coords->second);
513 } else {
514
515 auto refine_quadrature = [&]() {
517
518 const int max_level = refinementLevels;
519 EntityHandle tet;
520
521 moab::Core moab_ref;
522 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
523 EntityHandle nodes[4];
524 for (int nn = 0; nn != 4; nn++)
525 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
526 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
527 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
528 MoFEM::Interface &m_field_ref = mofem_ref_core;
529 {
530 Range tets(tet, tet);
531 Range edges;
532 CHKERR m_field_ref.get_moab().get_adjacencies(
533 tets, 1, true, edges, moab::Interface::UNION);
534 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
535 tets, BitRefLevel().set(0), false, VERBOSE);
536 }
537
538 Range nodes_at_front;
539 for (int nn = 0; nn != numNodes; nn++) {
540 if (singular_nodes[nn]) {
541 EntityHandle ent;
542 CHKERR moab_ref.side_element(tet, 0, nn, ent);
543 nodes_at_front.insert(ent);
544 }
545 }
546
547 auto singular_edges = get_singular_edges();
548
549 EntityHandle meshset;
550 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
551 for (int ee = 0; ee != numEdges; ee++) {
552 if (singular_edges[ee]) {
553 EntityHandle ent;
554 CHKERR moab_ref.side_element(tet, 1, ee, ent);
555 CHKERR moab_ref.add_entities(meshset, &ent, 1);
556 }
557 }
558
559 // refine mesh
560 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
561 for (int ll = 0; ll != max_level; ll++) {
562 Range edges;
563 CHKERR m_field_ref.getInterface<BitRefManager>()
564 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
565 BitRefLevel().set(), MBEDGE,
566 edges);
567 Range ref_edges;
568 CHKERR moab_ref.get_adjacencies(
569 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
570 ref_edges = intersect(ref_edges, edges);
571 Range ents;
572 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
573 ref_edges = intersect(ref_edges, ents);
574 Range tets;
575 CHKERR m_field_ref.getInterface<BitRefManager>()
576 ->getEntitiesByTypeAndRefLevel(
577 BitRefLevel().set(ll), BitRefLevel().set(), MBTET, tets);
578 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
579 ref_edges, BitRefLevel().set(ll + 1));
580 CHKERR m_ref->refineTets(tets, BitRefLevel().set(ll + 1));
581 CHKERR m_field_ref.getInterface<BitRefManager>()
582 ->updateMeshsetByEntitiesChildren(meshset,
583 BitRefLevel().set(ll + 1),
584 meshset, MBEDGE, true);
585 }
586
587 // get ref coords
588 Range tets;
589 CHKERR m_field_ref.getInterface<BitRefManager>()
590 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
591 BitRefLevel().set(), MBTET,
592 tets);
593
594 if (debug) {
595 CHKERR save_range(moab_ref, "ref_tets.vtk", tets);
596 }
597
598 MatrixDouble ref_coords(tets.size(), 12, false);
599 int tt = 0;
600 for (Range::iterator tit = tets.begin(); tit != tets.end();
601 tit++, tt++) {
602 int num_nodes;
603 const EntityHandle *conn;
604 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
605 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
606 }
607
608 auto &data = fe_ptr->dataOnElement[H1];
609 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
610 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
611 MatrixDouble &shape_n =
612 data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
613 int gg = 0;
614 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
615 double *tet_coords = &ref_coords(tt, 0);
616 double det = Tools::tetVolume(tet_coords);
617 det *= 6;
618 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
619 for (int dd = 0; dd != 3; dd++) {
620 ref_gauss_pts(dd, gg) =
621 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
622 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
623 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
624 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
625 }
626 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
627 }
628 }
629
630 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
631 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
632
633 // clear cache bubble
634 cachePhi->get<0>() = 0;
635 cachePhi->get<1>() = 0;
636 // tet base cache
637 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
638 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
639
641 };
642
643 CHKERR refine_quadrature();
644 }
645 }
646 }
647
649 }
650
651private:
652 struct Fe : public ForcesAndSourcesCore {
653 using ForcesAndSourcesCore::dataOnElement;
654
655 private:
656 using ForcesAndSourcesCore::ForcesAndSourcesCore;
657 };
658
659 boost::shared_ptr<Range> frontNodes;
660 boost::shared_ptr<Range> frontEdges;
661
662 boost::shared_ptr<CGGUserPolynomialBase::CachePhi> cachePhi;
663
664 static inline std::map<long int, MatrixDouble> mapRefCoords;
665};
666
668
669 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
670 boost::shared_ptr<Range> front_edges)
671 : frontNodes(front_nodes), frontEdges(front_edges) {};
672
673 SetIntegrationAtFrontFace(boost::shared_ptr<Range> front_nodes,
674 boost::shared_ptr<Range> front_edges,
675 int (*)(int))
676 : frontNodes(front_nodes), frontEdges(front_edges) {};
677
679 int order_col, int order_data) {
681
682 constexpr bool debug = false;
683
684 constexpr int numNodes = 3;
685 constexpr int numEdges = 3;
686 constexpr int refinementLevels = 6;
687
688 auto &m_field = fe_raw_ptr->mField;
689 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
690 auto fe_handle = fe_ptr->getFEEntityHandle();
691
692 auto set_base_quadrature = [&]() {
694 const int rule = face_rule(order_data);
695 const auto xiao_rule = IntRules::XiaoGimbutas::getTriangleRule(rule);
696 if (!xiao_rule) {
697 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
698 "Xiao--Gimbutas triangle rule is available for polynomial "
699 "orders 0 to %d; requested %d",
701 }
702 if (xiao_rule->numBarycentricCoordinates != 3) {
703 SETERRQ(m_field.get_comm(), MOFEM_DATA_INCONSISTENCY,
704 "wrong number of triangle barycentric coordinates");
705 }
706
707 const size_t nb_gauss_pts = xiao_rule->numPoints;
708 auto &gauss_pts = fe_ptr->gaussPts;
709 gauss_pts.resize(3, nb_gauss_pts, false);
710 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[1], 3, &gauss_pts(0, 0),
711 1);
712 cblas_dcopy(nb_gauss_pts, &xiao_rule->points[2], 3, &gauss_pts(1, 0),
713 1);
714 cblas_dcopy(nb_gauss_pts, xiao_rule->weights, 1, &gauss_pts(2, 0), 1);
716 };
717
718 CHKERR set_base_quadrature();
719
721
722 auto get_singular_nodes = [&]() {
723 int num_nodes;
724 const EntityHandle *conn;
725 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
726 true);
727 std::bitset<numNodes> singular_nodes;
728 for (auto nn = 0; nn != numNodes; ++nn) {
729 if (frontNodes->find(conn[nn]) != frontNodes->end()) {
730 singular_nodes.set(nn);
731 } else {
732 singular_nodes.reset(nn);
733 }
734 }
735 return singular_nodes;
736 };
737
738 auto get_singular_edges = [&]() {
739 std::bitset<numEdges> singular_edges;
740 for (int ee = 0; ee != numEdges; ee++) {
741 EntityHandle edge;
742 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
743 if (frontEdges->find(edge) != frontEdges->end()) {
744 singular_edges.set(ee);
745 } else {
746 singular_edges.reset(ee);
747 }
748 }
749 return singular_edges;
750 };
751
752 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
754 fe_ptr->gaussPts.swap(ref_gauss_pts);
756 };
757
758 auto singular_nodes = get_singular_nodes();
759 if (singular_nodes.count()) {
760 auto it_map_ref_coords = mapRefCoords.find(singular_nodes.to_ulong());
761 if (it_map_ref_coords != mapRefCoords.end()) {
762 CHKERR set_gauss_pts(it_map_ref_coords->second);
764 } else {
765
766 auto refine_quadrature = [&]() {
768
769 const int max_level = refinementLevels;
770
771 moab::Core moab_ref;
772 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
773 EntityHandle nodes[numNodes];
774 for (int nn = 0; nn != numNodes; nn++)
775 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
776 EntityHandle tri;
777 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
778 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
779 MoFEM::Interface &m_field_ref = mofem_ref_core;
780 {
781 Range tris(tri, tri);
782 Range edges;
783 CHKERR m_field_ref.get_moab().get_adjacencies(
784 tris, 1, true, edges, moab::Interface::UNION);
785 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
786 tris, BitRefLevel().set(0), false, VERBOSE);
787 }
788
789 Range nodes_at_front;
790 for (int nn = 0; nn != numNodes; nn++) {
791 if (singular_nodes[nn]) {
792 EntityHandle ent;
793 CHKERR moab_ref.side_element(tri, 0, nn, ent);
794 nodes_at_front.insert(ent);
795 }
796 }
797
798 auto singular_edges = get_singular_edges();
799
800 EntityHandle meshset;
801 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
802 for (int ee = 0; ee != numEdges; ee++) {
803 if (singular_edges[ee]) {
804 EntityHandle ent;
805 CHKERR moab_ref.side_element(tri, 1, ee, ent);
806 CHKERR moab_ref.add_entities(meshset, &ent, 1);
807 }
808 }
809
810 // refine mesh
811 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
812 for (int ll = 0; ll != max_level; ll++) {
813 Range edges;
814 CHKERR m_field_ref.getInterface<BitRefManager>()
815 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
816 BitRefLevel().set(), MBEDGE,
817 edges);
818 Range ref_edges;
819 CHKERR moab_ref.get_adjacencies(
820 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
821 ref_edges = intersect(ref_edges, edges);
822 Range ents;
823 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents, true);
824 ref_edges = intersect(ref_edges, ents);
825 Range tris;
826 CHKERR m_field_ref.getInterface<BitRefManager>()
827 ->getEntitiesByTypeAndRefLevel(
828 BitRefLevel().set(ll), BitRefLevel().set(), MBTRI, tris);
829 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
830 ref_edges, BitRefLevel().set(ll + 1));
831 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
832 CHKERR m_field_ref.getInterface<BitRefManager>()
833 ->updateMeshsetByEntitiesChildren(meshset,
834 BitRefLevel().set(ll + 1),
835 meshset, MBEDGE, true);
836 }
837
838 // get ref coords
839 Range tris;
840 CHKERR m_field_ref.getInterface<BitRefManager>()
841 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
842 BitRefLevel().set(), MBTRI,
843 tris);
844
845 if (debug) {
846 CHKERR save_range(moab_ref, "ref_tris.vtk", tris);
847 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
848 }
849
850 MatrixDouble ref_coords(tris.size(), 9, false);
851 int tt = 0;
852 for (Range::iterator tit = tris.begin(); tit != tris.end();
853 tit++, tt++) {
854 int num_nodes;
855 const EntityHandle *conn;
856 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
857 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
858 }
859
860 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
861 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
862 MatrixDouble shape_n(nb_gauss_pts, 3, false);
863 CHKERR ShapeMBTRI(&shape_n(0, 0), &fe_ptr->gaussPts(0, 0),
864 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
865 int gg = 0;
866 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
867 double *tri_coords = &ref_coords(tt, 0);
869 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
870 auto det = t_normal.l2();
871 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
872 for (int dd = 0; dd != 2; dd++) {
873 ref_gauss_pts(dd, gg) =
874 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
875 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
876 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
877 }
878 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
879 }
880 }
881
882 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
883 CHKERR set_gauss_pts(mapRefCoords[singular_nodes.to_ulong()]);
884
886 };
887
888 CHKERR refine_quadrature();
889 }
890 }
891 }
892
894 }
895
896private:
897 struct Fe : public ForcesAndSourcesCore {
898 using ForcesAndSourcesCore::dataOnElement;
899
900 private:
901 using ForcesAndSourcesCore::ForcesAndSourcesCore;
902 };
903
904 boost::shared_ptr<Range> frontNodes;
905 boost::shared_ptr<Range> frontEdges;
906
907 static inline std::map<long int, MatrixDouble> mapRefCoords;
908};
909
910boost::function<double(const double)> EshelbianCore::f = EshelbianCore::f_log_e;
911boost::function<double(const double)> EshelbianCore::d_f =
913boost::function<double(const double)> EshelbianCore::dd_f =
915boost::function<double(const double)> EshelbianCore::inv_f =
917boost::function<double(const double)> EshelbianCore::inv_d_f =
919boost::function<double(const double)> EshelbianCore::inv_dd_f =
921
923EshelbianCore::query_interface(boost::typeindex::type_index type_index,
924 UnknownInterface **iface) const {
925 *iface = const_cast<EshelbianCore *>(this);
926 return 0;
927}
928
929MoFEMErrorCode OpJacobian::doWork(int side, EntityType type, EntData &data) {
931
932 if (evalRhs)
933 CHKERR evaluateRhs(data);
934
935 if (evalLhs)
936 CHKERR evaluateLhs(data);
937
939}
940
942 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
943}
944
946
949 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
950 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
951 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
952 const char *list_broken_hdiv_bases[] = {"demkowicz", "ainsworth"};
953 PetscInt choice_rot = EshelbianCore::rotSelector;
954 PetscInt choice_grad = EshelbianCore::gradApproximator;
955 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
956 PetscInt choice_stretch = StretchSelector::LOG;
957 PetscInt choice_solver = SolverType::TimeSolver;
958 PetscInt choice_broken_hdiv_base = 0;
959 PetscBool l2_user_base_scale_set = PETSC_FALSE;
962 choice_broken_hdiv_base = 0;
963 break;
965 choice_broken_hdiv_base = 1;
966 break;
967 default:
968 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
969 "Unsupported broken HDIV base %s",
971 }
972 char analytical_expr_file_name[255] = "analytical_expr.py";
973 PetscBool no_stretch = isNoStretch() ? PETSC_TRUE : PETSC_FALSE;
974
975 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
976 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
977 spaceOrder, &spaceOrder, PETSC_NULLPTR);
978 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
979 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
980 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
981 "", materialH1Order, &materialH1Order, PETSC_NULLPTR);
982 CHKERR PetscOptionsScalar("-viscosity_alpha_u", "viscosity", "", alphaU,
983 &alphaU, PETSC_NULLPTR);
984 CHKERR PetscOptionsScalar("-viscosity_alpha_w", "viscosity", "", alphaW,
985 &alphaW, PETSC_NULLPTR);
986 CHKERR PetscOptionsScalar("-alpha_omega", "rot H1 penalty", "", alphaOmega,
987 &alphaOmega, PETSC_NULLPTR);
988 CHKERR PetscOptionsScalar("-alpha_omega0", "rot H1 penalty scaled by |M0|",
989 "", alphaOmega0, &alphaOmega0, PETSC_NULLPTR);
990 CHKERR PetscOptionsScalar("-alpha_r", "rot L2 penalty", "", alphaR, &alphaR,
991 PETSC_NULLPTR);
992 CHKERR PetscOptionsScalar("-alpha_r0", "rot L2 penalty scaled by |M0|", "",
993 alphaR0, &alphaR0, PETSC_NULLPTR);
994 CHKERR PetscOptionsScalar("-viscosity_alpha_omega", "rot viscosity", "",
996 PETSC_NULLPTR);
997 CHKERR PetscOptionsScalar("-viscosity_alpha_omega0",
998 "rot viscosity scaled by |M0|", "",
1000 PETSC_NULLPTR);
1001 CHKERR PetscOptionsScalar("-viscosity_alpha_r", "rot L2 viscosity", "",
1002 alphaViscousR, &alphaViscousR, PETSC_NULLPTR);
1003 CHKERR PetscOptionsScalar("-viscosity_alpha_r0",
1004 "rot L2 viscosity scaled by |M0|", "",
1005 alphaViscousR0, &alphaViscousR0, PETSC_NULLPTR);
1006 CHKERR PetscOptionsScalar("-density_alpha_rho", "density", "", alphaRho,
1007 &alphaRho, PETSC_NULLPTR);
1008 CHKERR PetscOptionsScalar("-alpha_tau", "tau", "", alphaTau, &alphaTau,
1009 PETSC_NULLPTR);
1010 CHKERR PetscOptionsScalar("-alpha_tau0", "tau0", "", alphaTau0, &alphaTau0,
1011 PETSC_NULLPTR);
1012 CHKERR PetscOptionsScalar("-alpha_tau_bc_disp", "tau for displacement BC", "",
1013 alphaTauBcDisp, &alphaTauBcDisp, PETSC_NULLPTR);
1014 CHKERR PetscOptionsScalar("-alpha_tau0_bc_disp",
1015 "tau0 for displacement BC", "", alphaTauBcDisp0,
1016 &alphaTauBcDisp0, PETSC_NULLPTR);
1017 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
1018 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
1019 PETSC_NULLPTR);
1020 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
1021 list_rots, NO_H1_CONFIGURATION + 1,
1022 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
1023
1024 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
1025 StretchSelector::STRETCH_SELECTOR_LAST,
1026 list_stretches[choice_stretch], &choice_stretch,
1027 PETSC_NULLPTR);
1028
1029 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
1030 no_stretch, &no_stretch, PETSC_NULLPTR);
1031 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1032 setSingularity, &setSingularity, PETSC_NULLPTR);
1033 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1035 &l2_user_base_scale_set);
1036 CHKERR PetscOptionsEList(
1037 "-broken_hdiv_base", "broken HDIV stress approximation base", "",
1038 list_broken_hdiv_bases, 2,
1039 list_broken_hdiv_bases[choice_broken_hdiv_base],
1040 &choice_broken_hdiv_base, PETSC_NULLPTR);
1041
1042 // dynamic relaxation
1043
1044 // @deprecate this option
1045 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1046 physicalTimeFlg, &physicalTimeFlg, PETSC_NULLPTR);
1047 CHKERR PetscOptionsEList(
1048 "-solver_type", "solver type", "", EshelbianCore::listSolvers,
1050 EshelbianCore::listSolvers[choice_solver], &choice_solver, PETSC_NULLPTR);
1051
1052 if (choice_solver != SolverType::TimeSolver) {
1053 CHKERR PetscOptionsScalar("-physical_final_time", "physical final time", "",
1055 &EshelbianCore::finalPhysicalTime, PETSC_NULLPTR);
1056 CHKERR PetscOptionsScalar("-physical_delta_time", "physical delta time", "",
1058 PETSC_NULLPTR);
1059 CHKERR PetscOptionsInt("-physical_max_steps", "physical max iterations", "",
1061 PETSC_NULLPTR);
1062 CHKERR PetscOptionsBool(
1063 "-physical_h1_update", "update each physicalsolver step", "",
1065 }
1066
1067 // contact parameters
1068 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1070 PETSC_NULLPTR);
1071 // cohesive interface
1072 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1073 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1074 CHKERR PetscOptionsInt(
1075 "-cohesive_interface_remove_level", "cohesive interface remove level", "",
1077
1078 // cracking parameters
1079 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1080 &crackingOn, PETSC_NULLPTR);
1081 CHKERR PetscOptionsScalar("-cracking_add_time", "cracking add time", "",
1082 crackingAddTime, &crackingAddTime, PETSC_NULLPTR);
1083 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1085 PETSC_NULLPTR);
1086 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1087 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1088
1089 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1090 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1091 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1092 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1093 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1094 "", list_release, 2, list_release[choice_release],
1095 &choice_release, PETSC_NULLPTR);
1096 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1098 PETSC_NULLPTR); // backward compatibility
1099 CHKERR PetscOptionsInt(
1100 "-nb_J_integral_contours", "Number of J integral contours", "",
1101 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1102
1103 // internal stress
1104 char tag_name[255] = "";
1105 CHKERR PetscOptionsString("-internal_stress_tag_name",
1106 "internal stress tag name", "", "", tag_name, 255,
1107 PETSC_NULLPTR);
1108 internalStressTagName = string(tag_name);
1109 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1111 PETSC_NULLPTR);
1112
1113 // Heterogenous Young's modulus
1114 char tag_heterogeneous_youngs_modulus_name[255] = "";
1115 CHKERR PetscOptionsString(
1116 "-heterogeneous_youngs_modulus", "heterogeneous Young's modulus tag name",
1117 "", "", tag_heterogeneous_youngs_modulus_name, 255, PETSC_NULLPTR);
1118 heterogeneousYoungModTagName = string(tag_heterogeneous_youngs_modulus_name);
1119
1120 PetscBool has_analytical_expr_file_option = PETSC_FALSE;
1122 PETSC_NULLPTR, PETSC_NULLPTR, "-analytical_expr_file",
1123 analytical_expr_file_name, 255, &has_analytical_expr_file_option);
1124 if (!has_analytical_expr_file_option) {
1125 const auto analytical_expr_script =
1126 mField.getInterface<JsonConfigManager>()->getPythonScriptByKey(
1127 "analytical_expr");
1128 if (!analytical_expr_script.empty()) {
1129 CHKERR PetscStrncpy(analytical_expr_file_name,
1130 analytical_expr_script.c_str(),
1131 sizeof(analytical_expr_file_name));
1132 MOFEM_LOG("EP", Sev::inform)
1133 << "Using Python script 'analytical_expr' from JSON config: "
1134 << analytical_expr_file_name;
1135 }
1136 }
1137
1138 PetscOptionsEnd();
1139
1142
1143 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1144 "none");
1145 char tag_mesh_transfer_source_file_name[255] = "";
1146 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1147 "source.h5m", tag_mesh_transfer_source_file_name,
1149 meshTransferSourceMeshFileName = string(tag_mesh_transfer_source_file_name);
1150 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1151 &meshTransferInterpOrder, PETSC_NULLPTR);
1152 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1154 PETSC_NULLPTR);
1155 PetscOptionsEnd();
1156
1158 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1159 "Unsupported mesh transfer interpolation order %d",
1161 }
1162 if (!internalStressTagName.empty())
1164 if (!heterogeneousYoungModTagName.empty())
1166
1167 const PetscBool l2_user_base_scale_option = l2UserBaseScale;
1168 if (setSingularity && !l2_user_base_scale_set) {
1169 l2UserBaseScale = PETSC_TRUE;
1170 }
1171
1174 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1175 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1176 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1178 static_cast<EnergyReleaseSelector>(choice_release);
1179 switch (choice_broken_hdiv_base) {
1180 case 0:
1182 break;
1183 case 1:
1185 break;
1186 default:
1187 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1188 "Unknown broken HDIV base option");
1189 }
1190
1192 case StretchSelector::LINEAR:
1199 break;
1200 case StretchSelector::LOG:
1207 break;
1208 case StretchSelector::LOG_QUADRATIC:
1215 break;
1216 default:
1217 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1218 break;
1219 };
1220
1221 const PetscBool dynamic_relaxation_option = physicalTimeFlg;
1222 if (physicalTimeFlg) {
1223 MOFEM_LOG("EP", Sev::warning)
1224 << "-dynamic_relaxation option is deprecated, use -solver_type "
1225 "dynamic_relaxation instead.";
1226 choice_solver = SolverType::DynamicRelaxation;
1227 }
1228
1229 switch (choice_solver) {
1232 break;
1236 physicalTimeFlg = PETSC_TRUE;
1237 break;
1240 break;
1243 physicalTimeFlg = PETSC_TRUE;
1244 break;
1248 break;
1252 physicalTimeFlg = PETSC_TRUE;
1253 break;
1254 default:
1255 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1256 break;
1257 };
1258
1259 // start cracking after adding crack elements
1261
1262 const auto yes_no = [](auto flag) { return flag ? "yes" : "no"; };
1263
1264 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1265 MOFEM_LOG("EP", Sev::inform)
1266 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1267 MOFEM_LOG("EP", Sev::inform)
1268 << "materialH1Order: -material_order " << materialH1Order;
1269 MOFEM_LOG("EP", Sev::inform) << "alphaU: -viscosity_alpha_u " << alphaU;
1270 MOFEM_LOG("EP", Sev::inform) << "alphaW: -viscosity_alpha_w " << alphaW;
1271 MOFEM_LOG("EP", Sev::inform) << "alphaOmega: -alpha_omega " << alphaOmega;
1272 MOFEM_LOG("EP", Sev::inform)
1273 << "alphaOmega0: -alpha_omega0 " << alphaOmega0;
1274 MOFEM_LOG("EP", Sev::inform) << "alphaR: -alpha_r " << alphaR;
1275 MOFEM_LOG("EP", Sev::inform) << "alphaR0: -alpha_r0 " << alphaR0;
1276 MOFEM_LOG("EP", Sev::inform)
1277 << "alphaViscousOmega: -viscosity_alpha_omega "
1279 MOFEM_LOG("EP", Sev::inform)
1280 << "alphaViscousOmega0: -viscosity_alpha_omega0 "
1282 MOFEM_LOG("EP", Sev::inform)
1283 << "alphaViscousR: -viscosity_alpha_r " << alphaViscousR;
1284 MOFEM_LOG("EP", Sev::inform)
1285 << "alphaViscousR0: -viscosity_alpha_r0 " << alphaViscousR0;
1286 MOFEM_LOG("EP", Sev::inform) << "alphaRho: -density_alpha_rho " << alphaRho;
1287 MOFEM_LOG("EP", Sev::inform) << "alphaTau: -alpha_tau " << alphaTau;
1288 MOFEM_LOG("EP", Sev::inform) << "alphaTau0: -alpha_tau0 " << alphaTau0;
1289 MOFEM_LOG("EP", Sev::inform)
1290 << "alphaTauBcDisp: -alpha_tau_bc_disp " << alphaTauBcDisp;
1291 MOFEM_LOG("EP", Sev::inform)
1292 << "alphaTauBcDisp0: -alpha_tau0_bc_disp " << alphaTauBcDisp0;
1293 MOFEM_LOG("EP", Sev::inform)
1294 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1295 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation: -grad "
1296 << list_rots[EshelbianCore::gradApproximator];
1297 MOFEM_LOG("EP", Sev::inform)
1298 << "Stretch: -stretches " << list_stretches[choice_stretch];
1299 MOFEM_LOG("EP", Sev::inform)
1300 << "No stretch: -no_stretch "
1301 << (isNoStretch() ? "yes" : "no");
1302
1303 MOFEM_LOG("EP", Sev::inform)
1304 << "Dynamic relaxation: -dynamic_relaxation "
1305 << yes_no(dynamic_relaxation_option);
1306 MOFEM_LOG("EP", Sev::inform) << "Solver type: -solver_type "
1307 << EshelbianCore::listSolvers[choice_solver];
1308 if (choice_solver != SolverType::TimeSolver) {
1309 MOFEM_LOG("EP", Sev::inform)
1310 << "Physical final time: -physical_final_time " << finalPhysicalTime;
1311 MOFEM_LOG("EP", Sev::inform)
1312 << "Physical delta time: -physical_delta_time " << physicalDt;
1313 MOFEM_LOG("EP", Sev::inform)
1314 << "Physical max steps: -physical_max_steps " << physicalMaxSteps;
1315 MOFEM_LOG("EP", Sev::inform)
1316 << "Physical H1 update: -physical_h1_update "
1317 << yes_no(physicalH1Update);
1318 }
1319 MOFEM_LOG("EP", Sev::inform)
1320 << "Singularity: -set_singularity " << yes_no(setSingularity);
1321 MOFEM_LOG("EP", Sev::inform)
1322 << "L2 user base scale: -l2_user_base_scale "
1323 << yes_no(l2_user_base_scale_option);
1324 if (l2UserBaseScale != l2_user_base_scale_option) {
1325 MOFEM_LOG("EP", Sev::inform)
1326 << "Effective L2 user base scale after option processing "
1327 << yes_no(l2UserBaseScale) << " (auto-enabled by -set_singularity)";
1328 }
1329 MOFEM_LOG("EP", Sev::inform)
1330 << "Broken HDIV base: -broken_hdiv_base "
1331 << list_broken_hdiv_bases[choice_broken_hdiv_base];
1332 MOFEM_LOG("EP", Sev::inform)
1333 << "Contact max post-proc ref level: -contact_max_post_proc_ref_level "
1335
1336 MOFEM_LOG("EP", Sev::inform)
1337 << "Cracking on: -cracking_on " << yes_no(crackingOn);
1338 MOFEM_LOG("EP", Sev::inform)
1339 << "Cracking add time: -cracking_add_time " << crackingAddTime;
1340 MOFEM_LOG("EP", Sev::inform)
1341 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1342 MOFEM_LOG("EP", Sev::inform)
1343 << "Griffith energy: -griffith_energy " << griffithEnergy;
1344 MOFEM_LOG("EP", Sev::inform)
1345 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1346 MOFEM_LOG("EP", Sev::inform)
1347 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1348 MOFEM_LOG("EP", Sev::inform)
1349 << "Energy release variant: -energy_release_variant "
1350 << list_release[EshelbianCore::energyReleaseSelector];
1351 MOFEM_LOG("EP", Sev::inform)
1352 << "Number of J integral contours: -nb_J_integral_contours / "
1353 "-nb_J_integral_levels "
1355 MOFEM_LOG("EP", Sev::inform)
1356 << "Cohesive interface on: -cohesive_interface_on "
1357 << ((interfaceCrack == PETSC_TRUE) ? "yes" : "no");
1358 MOFEM_LOG("EP", Sev::inform)
1359 << "Cohesive interface remove level: -cohesive_interface_remove_level "
1361 MOFEM_LOG("EP", Sev::inform)
1362 << "Internal stress tag name: -internal_stress_tag_name "
1364 MOFEM_LOG("EP", Sev::inform)
1365 << "Internal stress Voigt notation: -internal_stress_voigt "
1366 << yes_no(internalStressVoigt);
1367 MOFEM_LOG("EP", Sev::inform)
1368 << "Heterogeneous Young's modulus: -heterogeneous_youngs_modulus "
1370 MOFEM_LOG("EP", Sev::inform)
1371 << "Analytical expression file: -analytical_expr_file "
1372 << analytical_expr_file_name;
1374 MOFEM_LOG("EP", Sev::inform)
1375 << "Mesh transfer source file: -mesh_transfer_source_file "
1377 } else {
1378 MOFEM_LOG("EP", Sev::inform)
1379 << "Mesh transfer source file: -mesh_transfer_source_file <not set>";
1380 }
1381 MOFEM_LOG("EP", Sev::inform)
1382 << "Mesh transfer interpolation order: -mesh_transfer_interp_order "
1384 MOFEM_LOG("EP", Sev::inform)
1385 << "Mesh transfer hybrid interpolation: -mesh_transfer_hybrid_interp "
1386 << yes_no(meshTransferHybridInterp);
1387
1388#ifdef ENABLE_PYTHON_BINDING
1389 auto file_exists = [](std::string myfile) {
1390 std::ifstream file(myfile.c_str());
1391 if (file) {
1392 return true;
1393 }
1394 return false;
1395 };
1396
1397 if (file_exists(analytical_expr_file_name)) {
1398 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1399
1400 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1401 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1402 analytical_expr_file_name);
1403 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1404 } else {
1405 MOFEM_LOG("EP", Sev::warning)
1406 << analytical_expr_file_name << " file NOT found";
1407 }
1408#endif
1409
1410 if (spaceH1Order == -1)
1412
1414}
1415
1416MoFEMErrorCode EshelbianCore::addFields(const EntityHandle meshset,
1417 const bool add_bubble) {
1419
1420 auto get_tets = [&]() {
1421 Range tets;
1422 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1423 return tets;
1424 };
1425
1426 auto get_tets_skin = [&]() {
1427 Range tets_skin_part;
1428 Skinner skin(&mField.get_moab());
1429 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1430 ParallelComm *pcomm =
1431 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1432 Range tets_skin;
1433 CHKERR pcomm->filter_pstatus(tets_skin_part,
1434 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1435 PSTATUS_NOT, -1, &tets_skin);
1436 return tets_skin;
1437 };
1438
1439 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1440 // That mean, that hybrid field on all faces on which traction is applied,
1441 // on other faces, or enforcing displacements as
1442 // natural boundary condition.
1444 for (auto &v : *bcSpatialTractionVecPtr) {
1445 tets_skin = subtract(tets_skin, v.faces);
1446 }
1447
1449 for (auto &v : *bcSpatialSpringVecPtr) {
1450 tets_skin = subtract(tets_skin, v.faces);
1451 }
1452
1454 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1455 tets_skin = subtract(tets_skin, v.faces);
1456 }
1457
1459 for (auto &v : *bcSpatialPressureVecPtr) {
1460 tets_skin = subtract(tets_skin, v.faces);
1461 }
1462
1463 return tets_skin;
1464 };
1465
1466 auto add_blockset = [&](auto block_name, auto &&tets_skin) {
1467 auto crack_faces =
1468 get_range_from_block(mField, "block_name", SPACE_DIM - 1);
1469 tets_skin.merge(crack_faces);
1470 return tets_skin;
1471 };
1472
1473 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1474 auto contact_range =
1475 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1476 tets_skin = subtract(tets_skin, contact_range);
1477 return tets_skin;
1478 };
1479
1480 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1481 Range faces;
1482 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1483 faces, moab::Interface::UNION);
1484 Range trace_faces = subtract(faces, tets_skin);
1485 return trace_faces;
1486 };
1487
1488 auto tets = get_tets();
1489
1490 // remove also contact faces, i.e. that is also kind of hybrid field but
1491 // named but used to enforce contact conditions
1492 auto trace_faces = get_stress_trace_faces(
1493
1494 subtract_blockset("CONTACT",
1495 subtract_boundary_conditions(get_tets_skin()))
1496
1497 );
1498
1499 contactFaces = boost::make_shared<Range>(intersect(
1500 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1502 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1503
1504#ifndef NDEBUG
1505 if (contactFaces->size())
1507 "contact_faces_" +
1508 std::to_string(mField.get_comm_rank()) + ".vtk",
1509 *contactFaces);
1510 if (skeletonFaces->size())
1512 "skeleton_faces_" +
1513 std::to_string(mField.get_comm_rank()) + ".vtk",
1514 *skeletonFaces);
1515#endif
1516
1517 const FieldApproximationBase broken_hdiv_base =
1519
1520 auto add_broken_hdiv_field = [this, meshset, broken_hdiv_base](
1521 const std::string field_name,
1522 const int order) {
1524
1525 const FieldApproximationBase base = broken_hdiv_base;
1526
1527 auto get_side_map_hdiv = [&]() {
1528 return std::vector<
1529
1530 std::pair<EntityType,
1532
1533 >>{
1534
1535 {MBTET,
1536 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1537 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1538 dofs_side_map);
1539 }}
1540
1541 };
1542 };
1543
1545 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1547 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1549 };
1550
1551 auto add_l2_field = [this, meshset](const std::string field_name,
1552 const int order, const int dim) {
1555 MB_TAG_DENSE, MF_ZERO);
1557 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1559 };
1560
1561 auto add_h1_field = [this, meshset](const std::string field_name,
1562 const int order, const int dim) {
1565 MB_TAG_DENSE, MF_ZERO);
1567 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1568 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1569 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1570 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1572 };
1573
1574 auto add_l2_field_by_range = [this](const std::string field_name,
1575 const int order, const int dim,
1576 const int field_dim, Range &&r) {
1579 MB_TAG_DENSE, MF_ZERO);
1580 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1584 };
1585
1586 auto add_bubble_field = [this, meshset](const std::string field_name,
1587 const int order, const int dim) {
1589 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1590 MF_ZERO);
1591 // Modify field
1592 auto field_ptr = mField.get_field_structure(field_name);
1593 auto field_order_table =
1594 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1595 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1596 auto get_cgg_bubble_order_tet = [](int p) {
1597 return NBVOLUMETET_CCG_BUBBLE(p);
1598 };
1599 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1600 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1601 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1602 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1604 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1605 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1607 };
1608
1609 auto add_user_l2_field = [this, meshset](const std::string field_name,
1610 const int order, const int dim) {
1612 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1613 MF_ZERO);
1614 // Modify field
1615 auto field_ptr = mField.get_field_structure(field_name);
1616 auto field_order_table =
1617 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1618 auto zero_dofs = [](int p) { return 0; };
1619 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1620 field_order_table[MBVERTEX] = zero_dofs;
1621 field_order_table[MBEDGE] = zero_dofs;
1622 field_order_table[MBTRI] = zero_dofs;
1623 field_order_table[MBTET] = dof_l2_tet;
1625 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1627 };
1628
1629 if (!skeletonFaces)
1630 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1631 if (!contactFaces)
1632 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1633
1634 auto get_hybridised_disp = [&]() {
1635 auto faces = *skeletonFaces;
1636 auto skin = subtract_boundary_conditions(get_tets_skin());
1637 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1638 faces.merge(intersect(bc.faces, skin));
1639 }
1641 for (auto &bc : *bcSpatialSpringVecPtr) {
1642 faces.merge(intersect(bc.faces, skin));
1643 }
1644 return faces;
1645 };
1646
1647 auto add_spatial_fields = [&]<FieldApproximationBase Base>() {
1649 using Orders = EshelbianCore::FieldOrders<Base>;
1650 CHKERR add_broken_hdiv_field(piolaStress, Orders::stress(spaceOrder));
1651 if (add_bubble) {
1652 CHKERR add_bubble_field(bubbleField, Orders::bubble(spaceOrder), 1);
1653 }
1654 CHKERR add_l2_field(spatialL2Disp, Orders::disp(spaceOrder), 3);
1655 CHKERR add_user_l2_field(rotAxis, Orders::rot(spaceOrder), 3);
1656 CHKERR add_user_l2_field(stretchTensor,
1657 !isNoStretch()
1658 ? Orders::stretch(spaceOrder)
1659 : -1,
1660 6);
1661 CHKERR add_l2_field_by_range(hybridSpatialDisp,
1662 Orders::hybrid(spaceOrder), 2, 3,
1663 get_hybridised_disp());
1664 CHKERR add_l2_field_by_range(contactDisp, Orders::hybrid(spaceOrder), 2, 3,
1667 };
1668
1669 CHKERR withFieldOrders(add_spatial_fields);
1670
1671 // spatial displacement
1672 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1673 // material positions
1674 CHKERR add_h1_field(materialH1Positions, materialH1Order, 3);
1675
1677
1679}
1680
1682 double time) {
1684
1685 Range meshset_ents;
1686 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1687
1688 auto project_ho_geometry = [&](auto field) {
1690 return mField.loop_dofs(field, ent_method);
1691 };
1692 CHKERR project_ho_geometry(materialH1Positions);
1693
1694 auto get_adj_front_edges = [&](auto &front_edges) {
1695 Range front_crack_nodes;
1696 Range crack_front_edges_with_both_nodes_not_at_front;
1697
1698 if (mField.get_comm_rank() == 0) {
1699 auto &moab = mField.get_moab();
1701 moab.get_connectivity(front_edges, front_crack_nodes, true),
1702 "get_connectivity failed");
1703 Range crack_front_edges;
1704 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1705 false, crack_front_edges,
1706 moab::Interface::UNION),
1707 "get_adjacencies failed");
1708 Range crack_front_edges_nodes;
1709 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1710 crack_front_edges_nodes, true),
1711 "get_connectivity failed");
1712 // those nodes are hannging nodes
1713 crack_front_edges_nodes =
1714 subtract(crack_front_edges_nodes, front_crack_nodes);
1715 Range crack_front_edges_with_both_nodes_not_at_front;
1717 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1718 crack_front_edges_with_both_nodes_not_at_front,
1719 moab::Interface::UNION),
1720 "get_adjacencies failed");
1721 // those edges are have one node not at the crack front
1722 crack_front_edges_with_both_nodes_not_at_front = intersect(
1723 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1724 }
1725
1726 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1727 crack_front_edges_with_both_nodes_not_at_front = send_type(
1728 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1729
1730 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1731 boost::make_shared<Range>(
1732 crack_front_edges_with_both_nodes_not_at_front));
1733 };
1734
1735 if ((time - crackingAddTime) > std::numeric_limits<double>::epsilon()) {
1736 crackFaces = boost::make_shared<Range>(
1737 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1738 } else {
1739 crackFaces = boost::make_shared<Range>();
1740 }
1741 frontEdges =
1742 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1743 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1744 frontVertices = front_vertices;
1745 frontAdjEdges = front_adj_edges;
1746
1747 MOFEM_LOG("EP", Sev::inform)
1748 << "Number of crack faces: " << crackFaces->size();
1749 MOFEM_LOG("EP", Sev::inform)
1750 << "Number of front edges: " << frontEdges->size();
1751 MOFEM_LOG("EP", Sev::inform)
1752 << "Number of front vertices: " << frontVertices->size();
1753 MOFEM_LOG("EP", Sev::inform)
1754 << "Number of front adjacent edges: " << frontAdjEdges->size();
1755
1756#ifndef NDEBUG
1757 if (crackingOn) {
1758 auto rank = mField.get_comm_rank();
1759 // CHKERR save_range(mField.get_moab(),
1760 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1761 // meshset_ents);
1763 (boost::format("crack_faces_%d.vtk") % rank).str(),
1764 *crackFaces);
1766 (boost::format("front_edges_%d.vtk") % rank).str(),
1767 *frontEdges);
1768 // CHKERR save_range(mField.get_moab(),
1769 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1770 // *frontVertices);
1771 // CHKERR save_range(mField.get_moab(),
1772 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1773 // *frontAdjEdges);
1774 }
1775#endif // NDEBUG
1776
1777 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1779 auto &moab = mField.get_moab();
1780
1781 double eps = 1;
1782 double beta = 0;
1783 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1784 PETSC_NULLPTR);
1785 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1786 eps -= beta;
1787
1788 auto field_blas = mField.getInterface<FieldBlas>();
1789 auto lambda =
1790 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1792 FTENSOR_INDEX(3, i);
1793 FTENSOR_INDEX(3, j);
1794
1795 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1796 if (nb_dofs == 0) {
1798 }
1799
1800#ifndef NDEBUG
1801 if (field_entity_ptr->getNbOfCoeffs() != 3)
1803 "Expected 3 coefficients per edge");
1804 if (nb_dofs % 3 != 0)
1806 "Expected multiple of 3 coefficients per edge");
1807#endif // NDEBUG
1808
1809 auto get_conn = [&]() {
1810 int num_nodes;
1811 const EntityHandle *conn;
1812 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1813 num_nodes, false);
1814 return std::make_pair(conn, num_nodes);
1815 };
1816
1817 auto get_dir = [&](auto &&conn_p) {
1818 auto [conn, num_nodes] = conn_p;
1819 double coords[6];
1820 CHKERR moab.get_coords(conn, num_nodes, coords);
1821 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
1822 coords[4] - coords[1],
1823 coords[5] - coords[2]};
1824 return t_edge_dir;
1825 };
1826
1827 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
1828 auto [conn, num_nodes] = conn_p;
1829 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
1830 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1831 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
1832 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1833 t_singularity_dof(i) = t_edge_dir(i) * eps;
1834 }
1835 return t_singularity_dof;
1836 };
1837
1838 auto t_singularity_dof =
1839 get_singularity_dof(get_conn(), get_dir(get_conn()));
1840
1841 auto field_data = field_entity_ptr->getEntFieldData();
1843 &field_data[0], &field_data[1], &field_data[2]};
1844
1845 t_dof(i) = t_singularity_dof(i);
1846 ++t_dof;
1847 for (auto n = 1; n < field_data.size() / 3; ++n) {
1848 t_dof(i) = 0;
1849 ++t_dof;
1850 }
1851
1853 };
1854
1855 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
1856 &front_adj_edges);
1857
1859 };
1860
1861 if (setSingularity)
1862 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
1863
1864 interfaceFaces = boost::make_shared<Range>(
1865 get_range_from_block(mField, "INTERFACE", SPACE_DIM - 1));
1866 MOFEM_LOG("EP", Sev::inform)
1867 << "Number of interface elements: " << interfaceFaces->size();
1868
1869 auto get_interface_from_block = [&](auto block_name) {
1870 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
1871 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
1872 Range faces;
1873 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
1874 faces, moab::Interface::UNION);
1875 faces = subtract(faces, skin);
1876 MOFEM_LOG("EP", Sev::inform)
1877 << "Number of vol interface elements: " << vol_eles.size()
1878 << " and faces: " << faces.size();
1879 return faces;
1880 };
1881
1882 interfaceFaces->merge(get_interface_from_block("VOLUME_INTERFACE"));
1883
1884 auto remove_interface_from_block = [&](auto block_name, auto level) {
1886 Range intreface_faces;
1887 if (mField.get_comm_rank() == 0) {
1888 auto ents = get_entities_by_handle(mField, block_name);
1889 for (auto l = 0; l < level; ++l) {
1890 Range adj_tets;
1891 CHKERR mField.get_moab().get_adjacencies(
1892 ents, SPACE_DIM, true, adj_tets, moab::Interface::UNION);
1893 Range adj_tets_faces;
1894 CHKERR mField.get_moab().get_adjacencies(adj_tets, SPACE_DIM - 1, true,
1895 adj_tets_faces,
1896 moab::Interface::UNION);
1897 ents.merge(adj_tets_faces);
1898 }
1899 auto faces = ents.subset_by_dimension(SPACE_DIM - 1);
1900 if (faces.size()) {
1901 MOFEM_LOG("EP", Sev::inform)
1902 << "Removed ents " << faces.size()
1903 << " interface faces: " << interfaceFaces->size();
1904 }
1905 intreface_faces = subtract(*interfaceFaces, faces);
1906 MOFEM_LOG("EP", Sev::noisy)
1907 << "Interface faces after remove " << intreface_faces;
1908 }
1909 auto intreface_faces_global = send_type(mField, intreface_faces, MBTRI);
1910 interfaceFaces->swap(intreface_faces_global);
1912 };
1913 CHKERR remove_interface_from_block("REMOVE_INTERFACE", interfaceRemoveLevel);
1914
1916}
1917
1920#ifdef INCLUDE_MBCOUPLER
1921
1922 double toler = 5.e-10;
1923 MOFEM_LOG_CHANNEL("WORLD");
1924 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
1926 MOFEM_LOG("WORLD", Sev::verbose)
1927 << "No source mesh specified. Skipping projection";
1929 }
1930 MOFEM_LOG("WORLD", Sev::inform)
1931 << "Projecting from source mesh: " << meshTransferSourceMeshFileName;
1932 MOFEM_LOG("WORLD", Sev::verbose)
1933 << "Interpolation Stress tag name: " << internalStressTagName;
1934 MOFEM_LOG("WORLD", Sev::verbose) << "Interpolation Young's modulus tag name: "
1936 MOFEM_LOG("WORLD", Sev::verbose)
1937 << "Interpolation order: " << meshTransferInterpOrder;
1938 MOFEM_LOG("WORLD", Sev::verbose) << "Using hybrid interpolation: "
1939 << (meshTransferHybridInterp ? "yes" : "no");
1940
1941 auto &moab = mField.get_moab();
1942
1943 // check if tag exists
1944 for (const auto &tag_name : listTagsToProject) {
1945 Tag old_interp_tag;
1946 auto rval_check_tag = moab.tag_get_handle(tag_name.c_str(), old_interp_tag);
1947 if (rval_check_tag == MB_SUCCESS) {
1948 MOFEM_LOG("WORLD", Sev::inform)
1949 << "Deleting existing tag on target mesh: " << tag_name;
1950 CHKERR moab.tag_delete(old_interp_tag);
1951 }
1952 }
1953 // make a size-1 communicator for the coupler (rank 0 only)
1954 int world_rank = -1, world_size = -1;
1955 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
1956 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
1957
1958 Range original_meshset_ents;
1959 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
1960
1961 MPI_Comm comm_coupler;
1962 if (world_rank == 0) {
1963 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
1964 } else {
1965 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
1966 }
1967
1968 // build a separate ParallelComm for the coupler (rank 0 only)
1969 ParallelComm *pcomm0 = nullptr;
1970 int pcomm0_id = -1;
1971 if (world_rank == 0) {
1972 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
1973 }
1974
1975 Coupler::Method method;
1976 switch (meshTransferInterpOrder) {
1977 case 0:
1978 method = Coupler::CONSTANT;
1979 break;
1980 case 1:
1981 method = Coupler::LINEAR_FE;
1982 break;
1983 default:
1984 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1985 "Unsupported interpolation order");
1986 }
1987
1988 int nprocs, rank;
1989 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
1990 CHKERRQ(ierr);
1991 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1992 CHKERRQ(ierr);
1993
1994 // std::string read_opts, write_opts;
1995 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
1996 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
1997 // if (world_size > 1)
1998 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
1999 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
2000
2001 // create target mesh from existing meshset
2002 EntityHandle target_root;
2003 CHKERR moab.create_meshset(MESHSET_SET, target_root);
2004 MOFEM_LOG("WORLD", Sev::inform)
2005 << "Creating target mesh from existing meshset";
2006 Range target_meshset_ents;
2007 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
2008 CHKERR moab.add_entities(target_root, target_meshset_ents);
2009
2010 // variables for tags to be broadcast later
2011 std::vector<Tag> interp_tags;
2012 std::vector<int> tag_length;
2013 std::vector<DataType> dtype;
2014 std::vector<TagType> storage;
2015
2016 // load source mesh
2017 Range targ_verts, targ_elems;
2018 if (world_rank == 0) {
2019 EntityHandle source_root;
2020 CHKERR moab.create_meshset(MESHSET_SET, source_root);
2021
2022 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
2023 auto rval_source_mesh = moab.load_file(
2024 meshTransferSourceMeshFileName.c_str(), &source_root, "");
2025 if (rval_source_mesh != MB_SUCCESS) {
2026 MOFEM_LOG("WORLD", Sev::warning) << "Error loading source mesh file: "
2028 }
2029 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
2030
2031 Range src_elems;
2032 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
2033
2034 EntityHandle part_set;
2035 CHKERR pcomm0->create_part(part_set);
2036 CHKERR moab.add_entities(part_set, src_elems);
2037
2038 Range src_elems_part;
2039 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
2040
2041 for (const auto &iterp_tag_name : listTagsToProject) {
2042 std::string tag_to_use = iterp_tag_name;
2043
2044 Tag interp_tag;
2045 CHKERR moab.tag_get_handle(tag_to_use.c_str(), interp_tag);
2046
2047 int interp_tag_len;
2048 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
2049
2050 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
2051 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2052 "Unsupported interpolation tag length: %d", interp_tag_len);
2053 }
2054
2055 // store tag info for later broadcast
2056 tag_length.push_back(interp_tag_len);
2057 dtype.push_back(DataType());
2058 storage.push_back(TagType());
2059 interp_tags.push_back(interp_tag);
2060 CHKERR moab.tag_get_data_type(interp_tag, dtype.back());
2061 CHKERR moab.tag_get_type(interp_tag, storage.back());
2062
2063 // coupler is collective
2064 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
2065
2066 std::vector<double> vpos; // the positions we are interested in
2067 int num_pts = 0;
2068
2069 Range tmp_verts;
2070
2071 // First get all vertices adj to partition entities in target mesh
2072 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
2073
2074 if (meshTransferInterpOrder == 0) {
2075 targ_verts = targ_elems;
2076 } else {
2077 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
2078 moab::Interface::UNION);
2079 }
2080
2081 // Then get non-owned verts and subtract
2082 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
2083 targ_verts = subtract(targ_verts, tmp_verts);
2084
2085 // get position of these entities; these are the target points
2086 num_pts = (int)targ_verts.size();
2087 vpos.resize(3 * targ_verts.size());
2088 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2089
2090 // Locate those points in the source mesh
2091 boost::shared_ptr<TupleList> tl_ptr;
2092 tl_ptr = boost::make_shared<TupleList>();
2093 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2094 false);
2095
2096 // If some points were not located, we need to process them
2097 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
2098 std::vector<double> &vpos,
2099 Range &missing_verts) {
2101 int missing_pts_num = 0;
2102 int i = 0;
2103 auto vit = targ_verts.begin();
2104 for (; vit != targ_verts.end(); i++) {
2105 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
2106 missing_verts.insert(*vit);
2107 vit = targ_verts.erase(vit);
2108 missing_pts_num++;
2109 } else {
2110 vit++;
2111 }
2112 }
2113
2114 int missing_pts_num_global = 0;
2115 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
2116 // MPI_SUM, pcomm0);
2117 if (missing_pts_num_global) {
2118 MOFEM_LOG("WORLD", Sev::warning)
2119 << missing_pts_num_global
2120 << " points in target mesh were not located in source mesh. ";
2121 }
2122
2123 if (missing_pts_num) {
2124 num_pts = (int)targ_verts.size();
2125 vpos.resize(3 * targ_verts.size());
2126 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2127 tl_ptr->reset();
2128 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2129 false);
2130 }
2132 };
2133
2134 Range missing_verts;
2135 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
2136
2137 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
2138 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
2139
2140 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
2141
2142 Tag scalar_tag, adj_count_tag;
2143 double def_scl = 0;
2144 string scalar_tag_name = string(tag_to_use) + "_COMP";
2145 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2146 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2147 &def_scl);
2148
2149 string adj_count_tag_name = "ADJ_COUNT";
2150 double def_adj = 0;
2151 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2152 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2153 &def_adj);
2154
2155 // MBCoupler functionality supports only scalar tags. For the case of
2156 // vector or tensor tags we need to save each component as a scalar tag
2157 auto create_scalar_tags = [&](const Range &src_elems,
2158 const std::vector<double> &source_data,
2159 int itag) {
2161
2162 std::vector<double> source_data_scalar(src_elems.size());
2163 // Populate source_data_scalar
2164 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
2165 source_data_scalar[ielem] =
2166 source_data[itag + ielem * interp_tag_len];
2167 }
2168
2169 // Set data on the scalar tag
2170 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
2171
2172 if (meshTransferInterpOrder == 1) {
2173 // Linear interpolation: compute average value of data on vertices
2174 Range src_verts;
2175 CHKERR moab.get_connectivity(src_elems, src_verts, true);
2176
2177 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
2178 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
2179
2180 for (auto &tet : src_elems) {
2181 double tet_data = 0;
2182 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
2183
2184 Range adj_verts;
2185 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
2186
2187 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
2188 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
2189
2190 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2191 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
2192 &adj_vert_count[0]);
2193
2194 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
2195 adj_vert_data[ivert] += tet_data;
2196 adj_vert_count[ivert] += 1;
2197 }
2198
2199 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2200 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
2201 &adj_vert_count[0]);
2202 }
2203
2204 // Reduce tags for the parallel case
2205 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
2206 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
2207
2208 std::vector<double> src_vert_data(src_verts.size(), 0.0);
2209 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
2210
2211 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
2212 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
2213 &src_vert_adj_count[0]);
2214
2215 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
2216 src_vert_data[ivert] /= src_vert_adj_count[ivert];
2217 }
2218 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
2219 }
2221 };
2222
2223 MOFEM_LOG("WORLD", Sev::inform)
2224 << "Performing interpolation for tag: " << tag_to_use;
2225 MOFEM_LOG("WORLD", Sev::inform)
2226 << "Number of target points to interpolate: " << num_pts;
2227 MOFEM_LOG("WORLD", Sev::inform)
2228 << "Interpolation method: "
2229 << (method == Coupler::CONSTANT ? "constant" : "linear FE");
2230 MOFEM_LOG("WORLD", Sev::inform)
2231 << "Number of components in tag: " << interp_tag_len;
2232
2233 MOFEM_LOG("WORLD", Sev::inform)
2234 << "Source tag data range: ["
2235 << *std::min_element(source_data.begin(), source_data.end()) << ", "
2236 << *std::max_element(source_data.begin(), source_data.end()) << "]";
2237
2238 for (int itag = 0; itag < interp_tag_len; itag++) {
2239
2240 CHKERR create_scalar_tags(src_elems, source_data, itag);
2241
2242 std::vector<double> target_data_scalar(num_pts, 0.0);
2243 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
2244 tl_ptr.get());
2245
2246 for (int ielem = 0; ielem < num_pts; ielem++) {
2247 target_data[itag + ielem * interp_tag_len] =
2248 target_data_scalar[ielem];
2249 }
2250 }
2251
2252 // Use original tag
2253 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2254
2255 if (missing_verts.size() && (meshTransferInterpOrder == 1) &&
2257 MOFEM_LOG("WORLD", Sev::warning)
2258 << "Using hybrid interpolation for "
2259 "missing points in the target mesh.";
2260 Range missing_adj_elems;
2261 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2262 moab::Interface::UNION);
2263
2264 int num_adj_elems = (int)missing_adj_elems.size();
2265 std::vector<double> vpos_adj_elems;
2266
2267 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2268 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2269
2270 // Locate those points in the source mesh
2271 tl_ptr->reset();
2272 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2273 tl_ptr.get(), false);
2274
2275 Range missing_tets;
2276 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2277 vpos_adj_elems, missing_tets);
2278 if (missing_tets.size()) {
2279 MOFEM_LOG("WORLD", Sev::warning)
2280 << missing_tets.size()
2281 << " points in target mesh were not located in source mesh. ";
2282 }
2283
2284 std::vector<double> target_data_adj_elems(
2285 interp_tag_len * num_adj_elems, 0.0);
2286
2287 for (int itag = 0; itag < interp_tag_len; itag++) {
2288 CHKERR create_scalar_tags(src_elems, source_data, itag);
2289
2290 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2291 CHKERR mbc.interpolate(method, scalar_tag_name,
2292 &target_data_adj_elems_scalar[0],
2293 tl_ptr.get());
2294
2295 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2296 target_data_adj_elems[itag + ielem * interp_tag_len] =
2297 target_data_adj_elems_scalar[ielem];
2298 }
2299 }
2300
2301 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2302 &target_data_adj_elems[0]);
2303
2304 // FIXME: add implementation for parallel case
2305 for (auto &vert : missing_verts) {
2306 Range adj_elems;
2307 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2308 moab::Interface::UNION);
2309
2310 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2311 0.0);
2312 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2313
2314 std::vector<double> vert_data(interp_tag_len, 0.0);
2315 for (int itag = 0; itag < interp_tag_len; itag++) {
2316 for (int i = 0; i < adj_elems.size(); i++) {
2317 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2318 }
2319 vert_data[itag] /= adj_elems.size();
2320 }
2321 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2322 }
2323 }
2324
2325 CHKERR moab.tag_delete(scalar_tag);
2326 CHKERR moab.tag_delete(adj_count_tag);
2327 }
2328
2329 // delete source mesh after projection but keep the tags info for broadcast
2330 Range src_mesh_ents;
2331 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2332 CHKERR moab.delete_entities(&source_root, 1);
2333 CHKERR moab.delete_entities(src_mesh_ents);
2334 CHKERR moab.delete_entities(&part_set, 1);
2335 }
2336
2337 // broadcast tag info to other processors
2338 int tag_size = tag_length.size();
2339 MPI_Bcast(&tag_size, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2340 if (rank != 0) {
2341 interp_tags.resize(tag_size);
2342 tag_length.resize(tag_size);
2343 dtype.resize(tag_size);
2344 storage.resize(tag_size);
2345 }
2346 MPI_Bcast(interp_tags.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2347 MPI_Bcast(tag_length.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2348 MPI_Bcast(dtype.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2349 MPI_Bcast(storage.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2350
2351 // create new tag on other processors
2352 // loop over tag index to support multiple tags projection in one run
2353
2354 for (size_t index = 0; index < interp_tags.size(); index++) {
2355 // check if tag exists first
2356 if (world_rank) {
2357 Tag old_interp_tag;
2358 auto rval_check_tag =
2359 moab.tag_get_handle(listTagsToProject[index].c_str(), old_interp_tag);
2360 if (rval_check_tag == MB_SUCCESS) {
2361 MOFEM_LOG("WORLD", Sev::verbose)
2362 << "Deleting existing tag on target mesh (post-projection): "
2363 << listTagsToProject[index];
2364 CHKERR moab.tag_delete(old_interp_tag);
2365 }
2366 }
2367 Tag interp_tag_all;
2368 unsigned flags =
2369 MB_TAG_CREAT | storage[index]; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2370 std::vector<double> def_val(tag_length[index], 0.);
2371 auto rval = moab.tag_get_handle(listTagsToProject[index].c_str(),
2372 tag_length[index], dtype[index],
2373 interp_tag_all, flags, def_val.data());
2374 if (rval != MB_SUCCESS && world_rank) {
2375 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2376 "Unable to create projection tag %s",
2377 listTagsToProject[index].c_str());
2378 }
2379
2380 MPI_Barrier(PETSC_COMM_WORLD);
2381
2382 // exchange data for all entity types across all processors
2383 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2384 mField.get_comm(), mField.get_moab(), 0, tag_length[index],
2385 Sev::inform);
2386 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2387 mField.get_comm(), mField.get_moab(), 3, tag_length[index],
2388 Sev::inform);
2389
2391 mField.get_moab(), vertex_exchange, interp_tag_all);
2393 mField.get_moab(), volume_exchange, interp_tag_all);
2394 }
2395
2396 // delete target meshset but not the entities
2397 CHKERR moab.delete_entities(&target_root, 1);
2398
2399#endif // INCLUDE_MBCOUPLER
2401}
2402
2404EshelbianCore::addVolumeFiniteElement(const EntityHandle meshset,
2405 const bool add_bubble) {
2407
2408 // set finite element fields
2409 auto add_field_to_fe = [this](const std::string fe,
2410 const std::string field_name) {
2416 };
2417
2422
2423 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2424 if (add_bubble) {
2425 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2426 }
2427 if (!isNoStretch())
2428 CHKERR add_field_to_fe(elementVolumeName, stretchTensor);
2429 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2430 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2431 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2432 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2434
2435 // build finite elements data structures
2437 }
2438
2440}
2441
2443EshelbianCore::addBoundaryFiniteElement(const EntityHandle meshset) {
2445
2446 Range meshset_ents;
2447 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2448
2449 auto set_fe_adjacency = [&](auto fe_name) {
2452 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2455 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2457 };
2458
2459 // set finite element fields
2460 auto add_field_to_fe = [this](const std::string fe,
2461 const std::string field_name) {
2470 };
2471
2473
2474 Range natural_bc_elements;
2475 if (bcSpatialDispVecPtr) {
2476 for (auto &v : *bcSpatialDispVecPtr) {
2477 natural_bc_elements.merge(v.faces);
2478 }
2479 }
2481 for (auto &v : *bcSpatialRotationVecPtr) {
2482 natural_bc_elements.merge(v.faces);
2483 }
2484 }
2486 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2487 natural_bc_elements.merge(v.faces);
2488 }
2489 }
2491 for (auto &v : *bcSpatialSpringVecPtr) {
2492 natural_bc_elements.merge(v.faces);
2493 }
2494 }
2497 natural_bc_elements.merge(v.faces);
2498 }
2499 }
2501 for (auto &v : *bcSpatialTractionVecPtr) {
2502 natural_bc_elements.merge(v.faces);
2503 }
2504 }
2506 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2507 natural_bc_elements.merge(v.faces);
2508 }
2509 }
2511 for (auto &v : *bcSpatialPressureVecPtr) {
2512 natural_bc_elements.merge(v.faces);
2513 }
2514 }
2515 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2516
2518 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2520 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2521 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2522 CHKERR set_fe_adjacency(naturalBcElement);
2524 }
2525
2526 auto get_skin = [&](auto &body_ents) {
2527 Skinner skin(&mField.get_moab());
2528 Range skin_ents;
2529 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2530 return skin_ents;
2531 };
2532
2533 auto filter_true_skin = [&](auto &&skin) {
2534 Range boundary_ents;
2535 ParallelComm *pcomm =
2536 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2537 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2538 PSTATUS_NOT, -1, &boundary_ents);
2539 return boundary_ents;
2540 };
2541
2543
2544 Range body_ents;
2545 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2546 body_ents);
2547 auto skin = filter_true_skin(get_skin(body_ents));
2548
2556 contactDisp);
2559
2561 }
2562
2564 if (contactFaces) {
2565 MOFEM_LOG("EP", Sev::inform)
2566 << "Contact elements " << contactFaces->size();
2570 CHKERR add_field_to_fe(contactElement, piolaStress);
2571 CHKERR add_field_to_fe(contactElement, contactDisp);
2572 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2573 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2574 CHKERR set_fe_adjacency(contactElement);
2576 }
2577 }
2578
2580 if (!skeletonFaces)
2581 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2582 MOFEM_LOG("EP", Sev::inform)
2583 << "Skeleton elements " << skeletonFaces->size();
2587 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2588 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2589 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2590 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2591 CHKERR set_fe_adjacency(skeletonElement);
2593 }
2594
2596}
2597
2599 const EntityHandle meshset) {
2601
2602 // find adjacencies between finite elements and dofs
2604
2605 // Create coupled problem
2606 dM = createDM(mField.get_comm(), "DMMOFEM");
2607 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2608 BitRefLevel().set());
2609 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2610 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2616
2617 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2618 CHKERR DMSetUp(dM);
2619 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2620
2621 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2623 for (int d : {0, 1, 2}) {
2624 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2626 ->getSideDofsOnBrokenSpaceEntities(
2627 dofs_to_remove, prb_name, ROW, piolaStress,
2629 // remove piola dofs, i.e. traction free boundary
2630 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2631 dofs_to_remove);
2632 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2633 dofs_to_remove);
2634 }
2636 };
2637 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2638
2639 // Create elastic sub-problem
2640 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2641 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2647 if (!isNoStretch()) {
2649 }
2659 CHKERR DMSetUp(dmElastic);
2660
2661 dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2662 CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2671 if (!isNoStretch()) {
2673 }
2679 CHKERR DMSetUp(dmMaterial);
2680
2681 auto set_zero_block = [&]() {
2683 if (!isNoStretch()) {
2684 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2685 "ELASTIC_PROBLEM", spatialL2Disp, stretchTensor);
2686 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2687 "ELASTIC_PROBLEM", stretchTensor, spatialL2Disp);
2688 }
2689 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2690 "ELASTIC_PROBLEM", spatialL2Disp, rotAxis);
2691 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2692 "ELASTIC_PROBLEM", rotAxis, spatialL2Disp);
2693 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2694 "ELASTIC_PROBLEM", spatialL2Disp, bubbleField);
2695 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2696 "ELASTIC_PROBLEM", bubbleField, spatialL2Disp);
2697 if (!isNoStretch()) {
2698 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2699 "ELASTIC_PROBLEM", bubbleField, bubbleField);
2700 CHKERR
2701 mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2702 "ELASTIC_PROBLEM", piolaStress, piolaStress);
2703 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2704 "ELASTIC_PROBLEM", bubbleField, piolaStress);
2705 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2706 "ELASTIC_PROBLEM", piolaStress, bubbleField);
2707 }
2708
2709 auto zero_kinetic_constraints_block = [&]() {
2711 // we shoudl have sparet bloc names for this. TOPO_FIX_X, TOPO_FIX_Y,
2712 // TOPO_FIX_Z, TOPO_FIX_ALL
2713 auto bc_mng = mField.getInterface<BcManager>();
2714 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_X",
2715 materialH1Positions, 0, 0);
2716 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Y",
2717 materialH1Positions, 1, 1);
2718 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Z",
2719 materialH1Positions, 2, 2);
2720 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_ALL",
2721 materialH1Positions, 0, 3);
2722 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_X",
2723 materialH1Positions, 0, 0);
2724 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Y",
2725 materialH1Positions, 1, 1);
2726 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Z",
2727 materialH1Positions, 2, 2);
2728 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_ALL",
2729 materialH1Positions, 0, 3);
2731 };
2732
2733 // CHKERR zero_kinetic_constraints_block();
2734
2737 };
2738
2739 auto set_section = [&]() {
2741 PetscSection section;
2742 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2743 &section);
2744 CHKERR DMSetSection(dmElastic, section);
2745 CHKERR DMSetGlobalSection(dmElastic, section);
2746 CHKERR PetscSectionDestroy(&section);
2748 };
2749
2750 CHKERR set_zero_block();
2751 CHKERR set_section();
2752
2753 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2754 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2760 CHKERR DMSetUp(dmPrjSpatial);
2761
2762 // CHKERR mField.getInterface<BcManager>()
2763 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2764 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2765
2767}
2768
2769BcDisp::BcDisp(std::string name, std::vector<double> attr, Range faces,
2770 std::string load_history_file)
2771 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2772 vals.resize(3, false);
2773 flags.resize(3, false);
2774 for (int ii = 0; ii != 3; ++ii) {
2775 vals[ii] = attr[ii];
2776 flags[ii] = static_cast<int>(attr[ii + 3]);
2777 }
2778
2779 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp " << name;
2780 MOFEM_LOG("EP", Sev::inform)
2781 << "Add BCDisp vals " << vals[0] << " " << vals[1] << " " << vals[2];
2782 MOFEM_LOG("EP", Sev::inform)
2783 << "Add BCDisp flags " << flags[0] << " " << flags[1] << " " << flags[2];
2784 MOFEM_LOG("EP", Sev::inform) << "Add BCDisp nb. of faces " << faces.size();
2785}
2786
2787BcRot::BcRot(std::string name, std::vector<double> attr, Range faces,
2788 std::string load_history_file)
2789 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2790 vals.resize(attr.size(), false);
2791 for (int ii = 0; ii != attr.size(); ++ii) {
2792 vals[ii] = attr[ii];
2793 }
2794 theta = attr[3];
2795}
2796
2797TractionBc::TractionBc(std::string name, std::vector<double> attr, Range faces,
2798 std::string load_history_file)
2799 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2800 vals.resize(3, false);
2801 flags.resize(3, false);
2802 for (int ii = 0; ii != 3; ++ii) {
2803 vals[ii] = attr[ii];
2804 flags[ii] = static_cast<int>(attr[ii + 3]);
2805 }
2806
2807 MOFEM_LOG("EP", Sev::inform) << "Add BCForce " << name;
2808 MOFEM_LOG("EP", Sev::inform)
2809 << "Add BCForce vals " << vals[0] << " " << vals[1] << " " << vals[2];
2810 MOFEM_LOG("EP", Sev::inform)
2811 << "Add BCForce flags " << flags[0] << " " << flags[1] << " " << flags[2];
2812 MOFEM_LOG("EP", Sev::inform) << "Add BCForce nb. of faces " << faces.size();
2813}
2814
2816 std::vector<double> attr,
2817 Range faces,
2818 std::string load_history_file)
2819 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2820
2821 blockName = name;
2822 if (attr.size() < 1) {
2824 "Wrong size of normal displacement BC");
2825 }
2826
2827 val = attr[0];
2828
2829 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc " << name;
2830 MOFEM_LOG("EP", Sev::inform) << "Add NormalDisplacementBc val " << val;
2831 MOFEM_LOG("EP", Sev::inform)
2832 << "Add NormalDisplacementBc nb. of faces " << faces.size();
2833}
2834
2835SpringBc::SpringBc(std::string name, std::vector<double> attr, Range faces)
2836 : blockName(name), faces(faces) {
2837
2838 blockName = name;
2839 if (attr.size() < 2) {
2841 "Wrong size of spring BC attributes");
2842 }
2843
2844 normalStiffness = attr[0];
2845 tangentialStiffness = attr[1];
2846
2847 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc " << name;
2848 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc kn " << normalStiffness;
2849 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc kt " << tangentialStiffness;
2850 MOFEM_LOG("EP", Sev::inform) << "Add SpringBc nb. of faces " << faces.size();
2851}
2852
2853PressureBc::PressureBc(std::string name, std::vector<double> attr, Range faces,
2854 std::string load_history_file)
2855 : blockName(name), loadHistoryFile(load_history_file), faces(faces) {
2856
2857 blockName = name;
2858 if (attr.size() < 1) {
2860 "Wrong size of normal displacement BC");
2861 }
2862
2863 val = attr[0];
2864
2865 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc " << name;
2866 MOFEM_LOG("EP", Sev::inform) << "Add PressureBc val " << val;
2867 MOFEM_LOG("EP", Sev::inform)
2868 << "Add PressureBc nb. of faces " << faces.size();
2869}
2870
2871ExternalStrain::ExternalStrain(std::string name, std::vector<double> attr,
2872 Range ents, std::string load_history_file)
2873 : blockName(name), loadHistoryFile(load_history_file), ents(ents) {
2874
2875 blockName = name;
2876 if (attr.size() < 2) {
2878 "Wrong size of external strain attribute");
2879 }
2880
2881 val = attr[0];
2882 bulkModulusK = attr[1];
2883
2884 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain " << name;
2885 MOFEM_LOG("EP", Sev::inform) << "Add ExternalStrain val " << val;
2886 MOFEM_LOG("EP", Sev::inform)
2887 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2888 MOFEM_LOG("EP", Sev::inform)
2889 << "Add ExternalStrain bulk modulus K " << bulkModulusK;
2890 MOFEM_LOG("EP", Sev::inform)
2891 << "Add ExternalStrain nb. of tets " << ents.size();
2892}
2893
2895 std::string name, std::vector<double> attr, Range faces,
2896 std::string load_history_file)
2897 : blockName(name), faces(faces) {
2898 (void)load_history_file;
2899 if (attr.size() < 3) {
2901 "Wrong size of analytical displacement BC");
2902 }
2903
2904 flags.resize(3, false);
2905 for (int ii = 0; ii != 3; ++ii) {
2906 flags[ii] = attr[ii];
2907 }
2908
2909 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalDisplacementBc " << name;
2910 MOFEM_LOG("EP", Sev::inform)
2911 << "Add AnalyticalDisplacementBc flags " << flags[0] << " " << flags[1]
2912 << " " << flags[2];
2913 MOFEM_LOG("EP", Sev::inform)
2914 << "Add AnalyticalDisplacementBc nb. of faces " << faces.size();
2915}
2916
2918 std::vector<double> attr,
2919 Range faces,
2920 std::string load_history_file)
2921 : blockName(name), faces(faces) {
2922 (void)load_history_file;
2923 flags.resize(3, false);
2924 for (int ii = 0; ii != 3; ++ii) {
2925 flags[ii] = attr.size() < 3 ? 1 : attr[ii];
2926 }
2927
2928 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc " << name;
2929 MOFEM_LOG("EP", Sev::inform) << "Add AnalyticalTractionBc flags " << flags[0]
2930 << " " << flags[1] << " " << flags[2];
2931 MOFEM_LOG("EP", Sev::inform)
2932 << "Add AnalyticalTractionBc nb. of faces " << faces.size();
2933}
2934
2936EshelbianCore::getTractionFreeBc(const EntityHandle meshset,
2937 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2938 const std::string contact_set_name) {
2940
2941 // get skin from all tets
2942 Range tets;
2943 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2944 Range tets_skin_part;
2945 Skinner skin(&mField.get_moab());
2946 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
2947 ParallelComm *pcomm =
2948 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2949 Range tets_skin;
2950 CHKERR pcomm->filter_pstatus(tets_skin_part,
2951 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2952 PSTATUS_NOT, -1, &tets_skin);
2953
2954 bc_ptr->resize(3);
2955 for (int dd = 0; dd != 3; ++dd)
2956 (*bc_ptr)[dd] = tets_skin;
2957
2958 // Do not remove dofs on which traction is applied
2959 if (bcSpatialDispVecPtr)
2960 for (auto &v : *bcSpatialDispVecPtr) {
2961 if (v.flags[0])
2962 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2963 if (v.flags[1])
2964 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2965 if (v.flags[2])
2966 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2967 }
2968
2969 // Do not remove dofs on which rotation is applied
2970 if (bcSpatialRotationVecPtr)
2971 for (auto &v : *bcSpatialRotationVecPtr) {
2972 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2973 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2974 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2975 }
2976
2977 if (bcSpatialNormalDisplacementVecPtr)
2978 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2979 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2980 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2981 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2982 }
2983
2984 if (bcSpatialAnalyticalDisplacementVecPtr)
2985 for (auto &v : *bcSpatialAnalyticalDisplacementVecPtr) {
2986 if (v.flags[0])
2987 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2988 if (v.flags[1])
2989 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2990 if (v.flags[2])
2991 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2992 }
2993
2994 if (bcSpatialTractionVecPtr)
2995 for (auto &v : *bcSpatialTractionVecPtr) {
2996 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2997 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2998 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2999 }
3000
3001 if (bcSpatialSpringVecPtr)
3002 for (auto &v : *bcSpatialSpringVecPtr) {
3003 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3004 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3005 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3006 }
3007
3008 if (bcSpatialAnalyticalTractionVecPtr)
3009 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
3010 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3011 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3012 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3013 }
3014
3015 if (bcSpatialPressureVecPtr)
3016 for (auto &v : *bcSpatialPressureVecPtr) {
3017 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3018 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3019 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3020 }
3021
3022 // remove contact
3023 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
3024 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
3025 Range faces;
3026 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
3027 true);
3028 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
3029 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
3030 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
3031 }
3032
3034}
3035
3036/**
3037 * @brief Set integration rule on element
3038 * \param order on row
3039 * \param order on column
3040 * \param order on data
3041 *
3042 * Use maximal oder on data in order to determine integration rule
3043 *
3044 */
3045struct VolRule {
3046 int operator()(int p_row, int p_col, int p_data) const {
3047 return 2 * p_data + 1;
3048 }
3049};
3050
3051struct FaceRule {
3052 int operator()(int p_row, int p_col, int p_data) const {
3053 return 2 * (p_data + 1);
3054 }
3055};
3056
3058 const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates,
3059 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
3060 const bool add_bubble) {
3062
3063 auto bubble_cache =
3064 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
3065 fe->getUserPolynomialBase() =
3066 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
3067 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3068 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
3069
3070 // set integration rule
3071 fe->getRuleHook = [](int, int, int) { return -1; };
3072 // auto vol_rule = (SMALL_ROT > 0) ? vol_rule_lin : vol_rule_no_lin;
3073 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
3074 vol_rule, bubble_cache);
3075 // fe->getRuleHook = VolRule();
3076
3077 if (!dataAtPts) {
3078 dataAtPts =
3079 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
3080 dataAtPts->physicsPtr = physicalEquations;
3081 }
3082
3083 // calculate fields values
3084 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3085 piolaStress, dataAtPts->getApproxPAtPts()));
3086 if (add_bubble) {
3087 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
3088 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
3089 }
3090 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
3091 piolaStress, dataAtPts->getDivPAtPts()));
3092 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3093 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3094
3095 if (isNoStretch()) {
3097 fe->getOpPtrVector(), physicalEquations, dataAtPts,
3098 externalStrainVecPtr, timeScaleMap);
3099 } else {
3100 fe->getOpPtrVector().push_back(
3102 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
3103 }
3104
3105 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
3106 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3107 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
3108 if (!isNoStretch()) {
3109 fe->getOpPtrVector().push_back(new OpCalculateTensor2SymmetricFieldValues<3>(
3110 stretchTensor, dataAtPts->getLogStretchTensor0AtPts(), solTSStep,
3111 MBTET));
3112 }
3113
3114 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3115 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3116 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3117 rotAxis, dataAtPts->getRotAxisGradAtPts(), MBTET));
3118 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3119 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3120
3121 // H1 displacements
3122 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3123 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3124 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3125 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3126
3127 // velocities
3128 if (calc_rates) {
3129 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3130 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
3131 if (isNoStretch()) {
3132 } else {
3133 fe->getOpPtrVector().push_back(
3135 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
3136 fe->getOpPtrVector().push_back(
3138 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
3139 MBTET));
3140 }
3141 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3142 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
3143 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
3144 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
3145
3146 // acceleration
3147 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3148 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
3149 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
3150 }
3151 }
3152
3153 // calculate other derived quantities
3154 fe->getOpPtrVector().push_back(
3156
3157 // evaluate integration points
3158 if (isNoStretch()) {
3159 } else {
3160 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3161 do_rhs, do_lhs, dataAtPts, physicalEquations));
3162 }
3163
3165}
3166
3168 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3170
3171 bool has_nonhomogeneous_mat_block =
3173 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_dP(
3174 piolaStress, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3175 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dP(
3176 bubbleField, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3177 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dBubble(
3178 bubbleField, bubbleField, dataAtPts, has_nonhomogeneous_mat_block));
3179
3180 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3181 spatialL2Disp, piolaStress, dataAtPts, true));
3182 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3183 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3184
3185 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3186 piolaStress, rotAxis, dataAtPts,
3187 symmetrySelector == SYMMETRIC ? true : false));
3188 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3189 bubbleField, rotAxis, dataAtPts,
3190 symmetrySelector == SYMMETRIC ? true : false));
3191
3192 if (symmetrySelector > SYMMETRIC) {
3193 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3194 rotAxis, piolaStress, dataAtPts, false));
3195 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3196 rotAxis, bubbleField, dataAtPts, false));
3197 }
3198 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3199 rotAxis, rotAxis, dataAtPts, alphaR, alphaR0, alphaOmega, alphaOmega0,
3200 alphaViscousR, alphaViscousR0, alphaViscousOmega,
3201 alphaViscousOmega0));
3202
3204}
3205
3207 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3209
3210 fe_lhs->getOpPtrVector().push_back(
3211 physicalEquations->returnOpSpatialPhysical_du_du(
3212 stretchTensor, stretchTensor, dataAtPts, alphaU));
3213 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dP(
3214 stretchTensor, piolaStress, dataAtPts, true));
3215 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dBubble(
3216 stretchTensor, bubbleField, dataAtPts, true));
3217 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_domega(
3218 stretchTensor, rotAxis, dataAtPts,
3219 symmetrySelector == SYMMETRIC ? true : false));
3220
3221 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3222 spatialL2Disp, piolaStress, dataAtPts, true));
3223 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3224 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
3225
3226 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3227 piolaStress, rotAxis, dataAtPts,
3228 symmetrySelector == SYMMETRIC ? true : false));
3229 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3230 bubbleField, rotAxis, dataAtPts,
3231 symmetrySelector == SYMMETRIC ? true : false));
3232
3233 if (symmetrySelector > SYMMETRIC) {
3234 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_du(
3235 rotAxis, stretchTensor, dataAtPts, false));
3236 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3237 rotAxis, piolaStress, dataAtPts, false));
3238 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3239 rotAxis, bubbleField, dataAtPts, false));
3240 }
3241 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3242 rotAxis, rotAxis, dataAtPts, alphaR, alphaR0, alphaOmega, alphaOmega0,
3243 alphaViscousR, alphaViscousR0, alphaViscousOmega,
3244 alphaViscousOmega0));
3245
3247}
3248
3250 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3252 CHKERR pushPiolaStressGramOps(fe_lhs);
3253 fe_lhs->getOpPtrVector().push_back(
3254 new OpStressGram_dBubble_dP(bubbleField, piolaStress, dataAtPts));
3255 fe_lhs->getOpPtrVector().push_back(new OpStressGram_dBubble_dBubble(
3256 bubbleField, bubbleField));
3258}
3259
3261 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_lhs) {
3263 fe_lhs->getOpPtrVector().push_back(
3264 new OpStressGram_dP_dP(piolaStress, piolaStress));
3266}
3267
3269 const int tag, const bool add_elastic, const bool add_material,
3270 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
3271 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
3273
3274 /** Contact requires that body is marked */
3275 auto get_body_range = [this](auto name, int dim) {
3276 std::map<int, Range> map;
3277
3278 for (auto m_ptr :
3279 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3280
3281 (boost::format("%s(.*)") % name).str()
3282
3283 ))
3284
3285 ) {
3286 Range ents;
3287 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3288 dim, ents, true),
3289 "by dim");
3290 map[m_ptr->getMeshsetId()] = ents;
3291 }
3292
3293 return map;
3294 };
3295
3296 auto local_tau_sacale = boost::make_shared<double>(1.0);
3297 using BoundaryEle =
3299 using BdyEleOp = BoundaryEle::UserDataOperator;
3300 struct OpSetTauScale : public BdyEleOp {
3301 OpSetTauScale(boost::shared_ptr<double> local_tau_sacale, double alphaTau,
3302 double alphaTau0,
3303 boost::shared_ptr<MatrixDouble> flux_mat_ptr)
3304 : BdyEleOp(NOSPACE, BdyEleOp::OPSPACE),
3305 localTauSacale(local_tau_sacale), alphaTau(alphaTau),
3306 alphaTau0(alphaTau0), fluxMatPtr(flux_mat_ptr) {}
3307 MoFEMErrorCode doWork(int side, EntityType type,
3308 EntitiesFieldData::EntData &data) override {
3310 auto &coords = BdyEleOp::getCoords();
3311 auto [centre, barycenter, h] =
3312 Tools::getTricircumcenter3d(coords.data().data());
3313
3314 FTENSOR_INDEXES(3, i, J);
3315 auto t_P = getFTensor2FromMat<3, 3>(fluxMatPtr);
3316 auto t_normal = getFTensor1NormalsAtGaussPts();
3317 auto t_w = getFTensor0IntegrationWeight();
3318 auto nb_gauss_pts = getGaussPts().size2();
3319 double norm = 0;
3320 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
3322 t_t(i) = t_P(i, J) * t_normal(J);
3323 norm += t_w * sqrt(t_t(i) * t_t(i));
3324 ++t_w;
3325 ++t_normal;
3326 ++t_P;
3327 }
3328
3329 *localTauSacale = (alphaTau / h) + alphaTau0 * norm;
3330
3332 }
3333
3334 private:
3335 boost::shared_ptr<double> localTauSacale;
3336 boost::shared_ptr<MatrixDouble> fluxMatPtr;
3337 double alphaTau;
3338 double alphaTau0;
3339 };
3340
3341 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
3342 auto ent = fe_method_ptr->getFEEntityHandle();
3343 if (
3344
3345 (interfaceFaces->find(ent) != interfaceFaces->end())
3346
3347 || (crackFaces->find(ent) != crackFaces->end())
3348
3349 ) {
3350 return false;
3351 };
3352 return true;
3353 };
3354
3355 // Right hand side
3356 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3357 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
3358
3359 // elastic
3360 if (add_elastic) {
3361
3362 fe_rhs->getOpPtrVector().push_back(
3363 new OpSpatialEquilibrium(spatialL2Disp, dataAtPts, alphaW, alphaRho));
3364 fe_rhs->getOpPtrVector().push_back(
3365 new OpSpatialRotation(rotAxis, dataAtPts, alphaR, alphaR0, alphaOmega,
3366 alphaOmega0, alphaViscousR, alphaViscousR0,
3367 alphaViscousOmega, alphaViscousOmega0));
3368 if (isNoStretch()) {
3369 // do nothing - no stretch approximation
3370 } else {
3371 if (!internalStressTagName.empty()) {
3372 switch (meshTransferInterpOrder) {
3373 case 0:
3374 fe_rhs->getOpPtrVector().push_back(
3375 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
3376 break;
3377 case 1:
3378 fe_rhs->getOpPtrVector().push_back(
3379 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
3380 break;
3381 default:
3382 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3383 "Unsupported mesh transfer interpolation order %d, for "
3384 "internal stress",
3385 meshTransferInterpOrder);
3386 }
3387 // set default time scaling for interal stresses to constant
3388 TimeScale::ScalingFun def_scaling_fun = [](double time) { return 1; };
3389 auto ts_internal_stress =
3390 boost::make_shared<DynamicRelaxationTimeScale>(
3391 "internal_stress_history.txt", false, def_scaling_fun);
3392 if (internalStressVoigt) {
3393 fe_rhs->getOpPtrVector().push_back(
3395 stretchTensor, dataAtPts, ts_internal_stress));
3396 } else {
3397 fe_rhs->getOpPtrVector().push_back(
3399 stretchTensor, dataAtPts, ts_internal_stress));
3400 }
3401 }
3402 if (auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
3403 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
3404 fe_rhs->getOpPtrVector().push_back(op);
3405 } else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
3406 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3407 "OpSpatialPhysicalExternalStrain not implemented for this "
3408 "material");
3409 }
3410
3411 fe_rhs->getOpPtrVector().push_back(
3412 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
3413 alphaU));
3414 }
3415 fe_rhs->getOpPtrVector().push_back(
3416 new OpSpatialConsistencyP(piolaStress, dataAtPts));
3417 fe_rhs->getOpPtrVector().push_back(
3418 new OpSpatialConsistencyBubble(bubbleField, dataAtPts));
3419 fe_rhs->getOpPtrVector().push_back(
3420 new OpSpatialConsistencyDivTerm(piolaStress, dataAtPts));
3421
3422 auto set_hybridisation_rhs = [&](auto &pip) {
3424
3425 using BoundaryEle =
3427 using EleOnSide =
3429 using SideEleOp = EleOnSide::UserDataOperator;
3430 using BdyEleOp = BoundaryEle::UserDataOperator;
3431
3432 // First: Iterate over skeleton FEs adjacent to Domain FEs
3433 // Note: BoundaryEle, i.e. uses skeleton interation rule
3434 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3435 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3436 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3437 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3438 return -1;
3439 };
3440 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3441 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3442
3443 CHKERR EshelbianPlasticity::
3444 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3445 op_loop_skeleton_side->getOpPtrVector(), {L2},
3446 materialH1Positions, frontAdjEdges);
3447
3448 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3449 // domain element.
3450 auto broken_data_ptr =
3451 boost::make_shared<std::vector<BrokenBaseSideData>>();
3452 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3453 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3454 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3455 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3456 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3457 CHKERR
3458 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3459 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3460 materialH1Positions, frontAdjEdges);
3461 op_loop_domain_side->getOpPtrVector().push_back(
3462 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3463 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3464 op_loop_domain_side->getOpPtrVector().push_back(
3466 flux_mat_ptr));
3467 op_loop_domain_side->getOpPtrVector().push_back(
3468 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3469
3470 // Assemble on skeleton
3471 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3473 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
3475 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3476 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
3477 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
3478 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3479 op_loop_skeleton_side->getOpPtrVector().push_back(
3480 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
3481 hybrid_ptr));
3482 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3483 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3484
3485 // Add skeleton to domain pipeline
3486 pip.push_back(op_loop_skeleton_side);
3487
3489 };
3490
3491 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3492 auto hybrid_field) {
3494
3495 using BoundaryEle =
3497 using EleOnSide =
3499 using SideEleOp = EleOnSide::UserDataOperator;
3500 using BdyEleOp = BoundaryEle::UserDataOperator;
3501
3502 // First: Iterate over skeleton FEs adjacent to Domain FEs
3503 // Note: BoundaryEle, i.e. uses skeleton interation rule
3504 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3505 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3506 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3507 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3508 return -1;
3509 };
3510 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3511 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3512 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3513 CHKERR EshelbianPlasticity::
3514 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3515 op_loop_skeleton_side->getOpPtrVector(), {L2},
3516 materialH1Positions, frontAdjEdges);
3517
3518 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3519 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3520 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3521 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3522 CHKERR
3523 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3524 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3525 materialH1Positions, frontAdjEdges);
3526
3527 // Add stabilization operator
3528 auto broken_disp_data_ptr =
3529 boost::make_shared<std::vector<BrokenBaseSideData>>();
3530 op_loop_domain_side->getOpPtrVector().push_back(
3531 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3532 broken_disp_data_ptr));
3533 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3534 op_loop_domain_side->getOpPtrVector().push_back(
3536 disp_mat_ptr));
3537 // Set diag fluxes on skeleton side
3538 op_loop_domain_side->getOpPtrVector().push_back(
3539 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3540 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3541 op_loop_domain_side->getOpPtrVector().push_back(
3543 piolaStress, flux_mat_ptr, boost::make_shared<double>(1.0),
3544 solTSStep));
3545 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3546 op_loop_skeleton_side->getOpPtrVector().push_back(
3547 new OpSetTauScale(local_tau_sacale, alphaTau, alphaTau0,
3548 flux_mat_ptr));
3549
3550 // Add stabilization Ugamma Ugamma skeleton
3551 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3552 op_loop_skeleton_side->getOpPtrVector().push_back(
3554 hybrid_ptr));
3555
3556 // Diag u_gamma - u_gamma faces
3557 op_loop_skeleton_side->getOpPtrVector().push_back(
3559 hybrid_field, hybrid_ptr,
3560 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3561 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3562 }));
3563 // Diag L2 - L2 volumes
3564 op_loop_skeleton_side->getOpPtrVector().push_back(
3566 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3567 return (*local_tau_sacale);
3568 }));
3569 // Off-diag Ugamma - L2
3570 op_loop_skeleton_side->getOpPtrVector().push_back(
3572 hybrid_field, broken_disp_data_ptr,
3573 [local_tau_sacale](double, double, double) {
3574 return -(*local_tau_sacale);
3575 }));
3576 // Off-diag L2 - Ugamma
3577 op_loop_skeleton_side->getOpPtrVector().push_back(
3579 broken_disp_data_ptr, hybrid_ptr,
3580 [local_tau_sacale](double, double, double) {
3581 return -(*local_tau_sacale);
3582 }));
3583
3584 // Add skeleton to domain pipeline
3585 pip.push_back(op_loop_skeleton_side);
3586
3588 };
3589
3590 auto set_tau_stabilsation_disp_bc_rhs = [&](auto &pip, auto side_fe_name) {
3592
3593 using BoundaryEle =
3595 using EleOnSide =
3597 using SideEleOp = EleOnSide::UserDataOperator;
3598 using BdyEleOp = BoundaryEle::UserDataOperator;
3599
3600 // First: Iterate over skeleton FEs adjacent to Domain FEs
3601 // Note: BoundaryEle, i.e. uses skeleton interation rule
3602 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3603 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3604 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3605 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3606 return -1;
3607 };
3608 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3609 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3610 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3611 CHKERR EshelbianPlasticity::
3612 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3613 op_loop_skeleton_side->getOpPtrVector(), {L2},
3614 materialH1Positions, frontAdjEdges);
3615
3616 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3617 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3618 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3619 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3620 CHKERR
3621 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3622 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3623 materialH1Positions, frontAdjEdges);
3624
3625 // Add stabilization operator
3626 auto broken_disp_data_ptr =
3627 boost::make_shared<std::vector<BrokenBaseSideData>>();
3628 op_loop_domain_side->getOpPtrVector().push_back(
3629 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3630 broken_disp_data_ptr));
3631 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3632 op_loop_domain_side->getOpPtrVector().push_back(
3634 disp_mat_ptr));
3635 // Set diag fluxes on skeleton side
3636 op_loop_domain_side->getOpPtrVector().push_back(
3637 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3638
3639 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3640 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3641 op_loop_domain_side->getOpPtrVector().push_back(
3643 piolaStress, flux_mat_ptr, boost::make_shared<double>(1.0),
3644 solTSStep));
3645 op_loop_skeleton_side->getOpPtrVector().push_back(new OpSetTauScale(
3646 local_tau_sacale, alphaTauBcDisp, alphaTauBcDisp0, flux_mat_ptr));
3647
3648 // Diag L2 - L2 volumes
3649 op_loop_skeleton_side->getOpPtrVector().push_back(
3651 broken_disp_data_ptr, bcSpatialDispVecPtr, timeScaleMap,
3652 [local_tau_sacale](double, double, double) {
3653 return (*local_tau_sacale);
3654 }));
3655 op_loop_skeleton_side->getOpPtrVector().push_back(
3657 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3658 timeScaleMap, [local_tau_sacale](double, double, double) {
3659 return (*local_tau_sacale);
3660 }));
3661 op_loop_skeleton_side->getOpPtrVector().push_back(
3663 broken_disp_data_ptr, bcSpatialRotationVecPtr, timeScaleMap,
3664 [local_tau_sacale](double, double, double) {
3665 return (*local_tau_sacale);
3666 }));
3667
3668 // Add skeleton to domain pipeline
3669 pip.push_back(op_loop_skeleton_side);
3670
3672 };
3673
3674 auto set_contact_rhs = [&](auto &pip) {
3675 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3676 };
3677
3678 auto set_cohesive_rhs = [&](auto &pip) {
3679 return pushCohesiveOpsRhs(
3680 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3681 interfaceFaces, pip);
3682 };
3683
3684 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3685 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3686 if (alphaTau > 0.0 || alphaTau0 > 0.0) {
3687 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3688 hybridSpatialDisp);
3689 }
3690 if (alphaTauBcDisp > 0.0 || alphaTauBcDisp0 > 0.0) {
3691 CHKERR set_tau_stabilsation_disp_bc_rhs(fe_rhs->getOpPtrVector(),
3692 naturalBcElement);
3693 }
3694 if (interfaceCrack == PETSC_TRUE) {
3695 CHKERR set_cohesive_rhs(fe_rhs->getOpPtrVector());
3696 }
3697
3698 // Body forces
3699 using BodyNaturalBC =
3701 Assembly<PETSC>::LinearForm<GAUSS>;
3702 using OpBodyForce =
3703 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3704
3705 std::string body_force_history;
3706 CHKERR getStringArgumentFromJsonBlocksets("BODY_FORCE", "load_history",
3707 body_force_history);
3708 if (body_force_history.empty()) {
3709 body_force_history = "body_force.txt";
3710 } else {
3711 MOFEM_LOG("EP", Sev::inform)
3712 << "Body force load history from JSON: " << body_force_history;
3713 }
3714 auto body_time_scale =
3715 boost::make_shared<DynamicRelaxationTimeScale>(body_force_history);
3716 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3717 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3718 "BODY_FORCE", Sev::inform);
3719 }
3720
3721 // Left hand side
3722 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3723 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3724
3725 // elastic
3726 if (add_elastic) {
3727
3728 if (isNoStretch()) {
3729 CHKERR pushNoStretchVolumeA00Ops(fe_lhs);
3730 } else {
3731 CHKERR pushStretchVolumeA00Ops(fe_lhs);
3732 }
3733
3734 auto set_hybridisation_lhs = [&](auto &pip) {
3736
3737 using BoundaryEle =
3739 using EleOnSide =
3741 using SideEleOp = EleOnSide::UserDataOperator;
3742 using BdyEleOp = BoundaryEle::UserDataOperator;
3743
3744 // First: Iterate over skeleton FEs adjacent to Domain FEs
3745 // Note: BoundaryEle, i.e. uses skeleton interation rule
3746 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3747 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3748 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3749 return -1;
3750 };
3751 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3752 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3753 CHKERR EshelbianPlasticity::
3754 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3755 op_loop_skeleton_side->getOpPtrVector(), {L2},
3756 materialH1Positions, frontAdjEdges);
3757
3758 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3759 // domain element.
3760 auto broken_data_ptr =
3761 boost::make_shared<std::vector<BrokenBaseSideData>>();
3762 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3763 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3764 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3765 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3766 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3767 CHKERR
3768 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3769 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3770 materialH1Positions, frontAdjEdges);
3771 op_loop_domain_side->getOpPtrVector().push_back(
3772 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3773
3774 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3776 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3777 op_loop_skeleton_side->getOpPtrVector().push_back(
3778 new OpC(hybridSpatialDisp, broken_data_ptr,
3779 boost::make_shared<double>(1.0), true, false));
3780
3781 pip.push_back(op_loop_skeleton_side);
3782
3784 };
3785
3786 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3787 auto hybrid_field) {
3789
3790 using BoundaryEle =
3792 using EleOnSide =
3794 using SideEleOp = EleOnSide::UserDataOperator;
3795 using BdyEleOp = BoundaryEle::UserDataOperator;
3796
3797 // First: Iterate over skeleton FEs adjacent to Domain FEs
3798 // Note: BoundaryEle, i.e. uses skeleton interation rule
3799 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3800 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3801 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3802 return -1;
3803 };
3804 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3805 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3806 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3807 CHKERR EshelbianPlasticity::
3808 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3809 op_loop_skeleton_side->getOpPtrVector(), {L2},
3810 materialH1Positions, frontAdjEdges);
3811
3812 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3813 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3814 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3815 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3816 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3817 CHKERR
3818 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3819 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3820 materialH1Positions, frontAdjEdges);
3821
3822 auto broken_disp_data_ptr =
3823 boost::make_shared<std::vector<BrokenBaseSideData>>();
3824 op_loop_domain_side->getOpPtrVector().push_back(
3825 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3826 broken_disp_data_ptr));
3827 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3828 op_loop_domain_side->getOpPtrVector().push_back(
3830 piolaStress, flux_mat_ptr, boost::make_shared<double>(1.0),
3831 solTSStep));
3832 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3833 op_loop_skeleton_side->getOpPtrVector().push_back(
3834 new OpSetTauScale(local_tau_sacale, alphaTau, alphaTau0,
3835 flux_mat_ptr));
3836
3837 // Diag Ugamma-Ugamma skeleton
3838 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3839 hybrid_field, hybrid_field,
3840 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3841 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3842 }));
3843 // Diag L2-L2 volumes
3844 op_loop_skeleton_side->getOpPtrVector().push_back(
3846 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3847 return (*local_tau_sacale);
3848 }));
3849 // Off-diag Ugamma - L2
3850 op_loop_skeleton_side->getOpPtrVector().push_back(
3852 hybrid_field, broken_disp_data_ptr,
3853 [local_tau_sacale](double, double, double) {
3854 return -(*local_tau_sacale);
3855 },
3856 false, false));
3857 // Off-diag L2 - Ugamma
3858 op_loop_skeleton_side->getOpPtrVector().push_back(
3860 hybrid_field, broken_disp_data_ptr,
3861 [local_tau_sacale](double, double, double) {
3862 return -(*local_tau_sacale);
3863 },
3864 true, true));
3865
3866 pip.push_back(op_loop_skeleton_side);
3867
3869 };
3870
3871 auto set_tau_stabilsation_disp_bc_lhs = [&](auto &pip, auto side_fe_name) {
3873
3874 using BoundaryEle =
3876 using EleOnSide =
3878 using SideEleOp = EleOnSide::UserDataOperator;
3879 using BdyEleOp = BoundaryEle::UserDataOperator;
3880
3881 // First: Iterate over skeleton FEs adjacent to Domain FEs
3882 // Note: BoundaryEle, i.e. uses skeleton interation rule
3883 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3884 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3885 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3886 return -1;
3887 };
3888 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3889 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3890 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3891 CHKERR EshelbianPlasticity::
3892 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3893 op_loop_skeleton_side->getOpPtrVector(), {L2},
3894 materialH1Positions, frontAdjEdges);
3895
3896 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3897 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3898 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3899 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3900 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3901 CHKERR
3902 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3903 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3904 materialH1Positions, frontAdjEdges);
3905
3906 auto broken_disp_data_ptr =
3907 boost::make_shared<std::vector<BrokenBaseSideData>>();
3908 op_loop_domain_side->getOpPtrVector().push_back(
3909 new OpGetBrokenBaseSideData<SideEleOp>(spatialL2Disp,
3910 broken_disp_data_ptr));
3911 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3912 op_loop_domain_side->getOpPtrVector().push_back(
3914 piolaStress, flux_mat_ptr, boost::make_shared<double>(1.0),
3915 solTSStep));
3916 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3917 op_loop_skeleton_side->getOpPtrVector().push_back(new OpSetTauScale(
3918 local_tau_sacale, alphaTauBcDisp, alphaTauBcDisp0, flux_mat_ptr));
3919
3920 // Diag L2-L2 volumes
3921 op_loop_skeleton_side->getOpPtrVector().push_back(
3923 broken_disp_data_ptr, bcSpatialDispVecPtr,
3924 [local_tau_sacale](double, double, double) {
3925 return (*local_tau_sacale);
3926 }));
3927 op_loop_skeleton_side->getOpPtrVector().push_back(
3929 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3930 [local_tau_sacale](double, double, double) {
3931 return (*local_tau_sacale);
3932 }));
3933 op_loop_skeleton_side->getOpPtrVector().push_back(
3935 broken_disp_data_ptr, bcSpatialRotationVecPtr,
3936 [local_tau_sacale](double, double, double) {
3937 return (*local_tau_sacale);
3938 }));
3939
3940 pip.push_back(op_loop_skeleton_side);
3941
3943 };
3944
3945 auto set_contact_lhs = [&](auto &pip) {
3946 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3947 };
3948
3949 auto set_cohesive_lhs = [&](auto &pip) {
3950 return pushCohesiveOpsLhs(
3951 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3952 interfaceFaces, pip);
3953 };
3954
3955 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3956 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3957 if (alphaTau > 0.0 || alphaTau0 > 0.0) {
3958 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3959 hybridSpatialDisp);
3960 }
3961 if (alphaTauBcDisp > 0.0 || alphaTauBcDisp0 > 0.0) {
3962 CHKERR set_tau_stabilsation_disp_bc_lhs(fe_lhs->getOpPtrVector(),
3963 naturalBcElement);
3964 }
3965 if (interfaceCrack == PETSC_TRUE) {
3966 CHKERR set_cohesive_lhs(fe_lhs->getOpPtrVector());
3967 }
3968 }
3969
3970 if (add_material) {
3971 }
3972
3974}
3975
3977 const bool add_elastic, const bool add_material,
3978 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
3979 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
3981
3982 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3983 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3984
3985 // set integration rule
3986 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3987 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3988 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
3989 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
3990 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3991 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3992
3993 CHKERR
3994 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3995 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3996 CHKERR
3997 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3998 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3999
4000 if (add_elastic) {
4001
4002 auto get_broken_op_side = [this](auto &pip) {
4003 using EleOnSide =
4005 using SideEleOp = EleOnSide::UserDataOperator;
4006 // Iterate over domain FEs adjacent to boundary.
4007 auto broken_data_ptr =
4008 boost::make_shared<std::vector<BrokenBaseSideData>>();
4009 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
4010 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4011 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4012 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4013 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
4014 CHKERR
4015 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4016 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4017 materialH1Positions, frontAdjEdges);
4018 op_loop_domain_side->getOpPtrVector().push_back(
4019 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
4020 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
4021 op_loop_domain_side->getOpPtrVector().push_back(
4023 flux_mat_ptr));
4024 op_loop_domain_side->getOpPtrVector().push_back(
4025 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
4026 pip.push_back(op_loop_domain_side);
4027 return broken_data_ptr;
4028 };
4029
4030 auto set_rhs = [&]() {
4032
4033 auto broken_data_ptr = get_broken_op_side(fe_rhs->getOpPtrVector());
4034
4035 fe_rhs->getOpPtrVector().push_back(
4036 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
4037 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
4038 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
4039 timeScaleMap));
4040 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
4041 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
4042
4043 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4044 fe_rhs->getOpPtrVector().push_back(
4045 new OpBrokenTractionBc(hybridSpatialDisp, bcSpatialTractionVecPtr,
4046 piola_scale_ptr, timeScaleMap));
4047 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4048 // if you push gradient of L2 base to physical element, it will not work.
4049 fe_rhs->getOpPtrVector().push_back(
4051 hybridSpatialDisp, hybrid_grad_ptr));
4052 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
4053 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
4054 hybrid_grad_ptr, timeScaleMap));
4055 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
4056 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
4057 timeScaleMap));
4058
4059 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
4060 fe_rhs->getOpPtrVector().push_back(
4061 new OpCalculateVectorFieldValues<SPACE_DIM>(hybridSpatialDisp,
4062 hybrid_ptr));
4063 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
4064 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4065 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
4066 fe_rhs->getOpPtrVector().push_back(
4067 new OpSpringRhsBc(hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4068 bcSpatialSpringVecPtr));
4069
4070 auto get_normal_disp_bc_faces = [&]() {
4071 auto faces =
4072 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4073 return boost::make_shared<Range>(faces);
4074 };
4075
4076 auto get_spring_bc_faces = [&]() {
4077 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4078 return boost::make_shared<Range>(faces);
4079 };
4080
4081 using BoundaryEle =
4083 using BdyEleOp = BoundaryEle::UserDataOperator;
4085 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
4086 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4087 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4088 get_normal_disp_bc_faces()));
4089 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4090 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4091 get_spring_bc_faces()));
4092
4094 };
4095
4096 auto set_lhs = [&]() {
4098
4099 auto broken_data_ptr = get_broken_op_side(fe_lhs->getOpPtrVector());
4100
4101 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
4102 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
4103 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
4104 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
4105 timeScaleMap));
4106 fe_lhs->getOpPtrVector().push_back(
4107 new OpSpringLhsBc_dU(hybridSpatialDisp, bcSpatialSpringVecPtr));
4108 fe_lhs->getOpPtrVector().push_back(new OpSpringLhsBc_dP(
4109 hybridSpatialDisp, broken_data_ptr, bcSpatialSpringVecPtr));
4110
4111 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4112 // if you push gradient of L2 base to physical element, it will not work.
4113 fe_lhs->getOpPtrVector().push_back(
4115 hybridSpatialDisp, hybrid_grad_ptr));
4116 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
4117 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
4118 timeScaleMap));
4119
4120 auto get_normal_disp_bc_faces = [&]() {
4121 auto faces =
4122 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4123 return boost::make_shared<Range>(faces);
4124 };
4125
4126 auto get_spring_bc_faces = [&]() {
4127 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4128 return boost::make_shared<Range>(faces);
4129 };
4130
4131 using BoundaryEle =
4133 using BdyEleOp = BoundaryEle::UserDataOperator;
4135 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
4136 fe_lhs->getOpPtrVector().push_back(new OpC(
4137 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4138 true, true, get_normal_disp_bc_faces()));
4139 fe_lhs->getOpPtrVector().push_back(new OpC(
4140 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4141 true, true, get_spring_bc_faces()));
4142
4144 };
4145
4146 CHKERR set_rhs();
4147 CHKERR set_lhs();
4148 }
4149
4151}
4152
4154 const bool add_elastic, const bool add_material,
4155 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
4156 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
4159}
4160
4162
4163 boost::shared_ptr<ForcesAndSourcesCore> &fe_contact_tree
4164
4165) {
4167 fe_contact_tree = createContactDetectionFiniteElement(*this);
4169}
4170
4173
4174 // Add contact operators. Note that only for rhs. THe lhs is assembled with
4175 // volume element, to enable schur complement evaluation.
4176 CHKERR setContactElementRhsOps(contactTreeRhs);
4177
4178 CHKERR setVolumeElementOps(tag, true, false, elasticFeRhs, elasticFeLhs);
4179 CHKERR setFaceElementOps(true, false, elasticBcRhs, elasticBcLhs);
4180
4181 auto adj_cache =
4182 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
4183
4184 auto get_op_contact_bc = [&]() {
4186 auto op_loop_side = new OpLoopSide<SideEle>(
4187 mField, contactElement, SPACE_DIM - 1, Sev::noisy, adj_cache);
4188 return op_loop_side;
4189 };
4190
4192}
4193
4196 boost::shared_ptr<FEMethod> null;
4197
4198 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4199
4200 CHKERR DMMoFEMTSSetI2Function(dm, elementVolumeName, elasticFeRhs, null,
4201 null);
4202 CHKERR DMMoFEMTSSetI2Function(dm, naturalBcElement, elasticBcRhs, null,
4203 null);
4204 CHKERR DMMoFEMTSSetI2Jacobian(dm, elementVolumeName, elasticFeLhs, null,
4205 null);
4206 CHKERR DMMoFEMTSSetI2Jacobian(dm, naturalBcElement, elasticBcLhs, null,
4207 null);
4208
4209 } else {
4210 CHKERR DMMoFEMTSSetIFunction(dm, elementVolumeName, elasticFeRhs, null,
4211 null);
4212 CHKERR DMMoFEMTSSetIFunction(dm, naturalBcElement, elasticBcRhs, null,
4213 null);
4214 CHKERR DMMoFEMTSSetIJacobian(dm, elementVolumeName, elasticFeLhs, null,
4215 null);
4216 CHKERR DMMoFEMTSSetIJacobian(dm, naturalBcElement, elasticBcLhs, null,
4217 null);
4218 }
4219
4221}
4222
4226#include "impl/SetUpSchurImpl.cpp"
4227
4229
4230 inline static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x,
4231 bool set_ts_monitor) {
4232
4233#ifdef ENABLE_PYTHON_BINDING
4234 auto setup_sdf = [&]() { return setupContactSdf(ep_ptr->mField); };
4235#endif
4236
4237 auto setup_ts_monitor = [&]() {
4238 boost::shared_ptr<TsCtx> ts_ctx;
4240 "get TS ctx");
4241 if (set_ts_monitor) {
4243 TSMonitorSet(ts, TsMonitorSet, ts_ctx.get(), PETSC_NULLPTR),
4244 "TS monitor set");
4245 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
4246 auto testing_monitor_ptr =
4247 boost::make_shared<EshelbianTestingMonitor>(*ep_ptr, monitor_ptr);
4248 ts_ctx->getLoopsMonitor().push_back(
4249 TsCtx::PairNameFEMethodPtr(ep_ptr->elementVolumeName, monitor_ptr));
4250
4251 PetscBool test_cook_flg = PETSC_FALSE;
4252 PetscBool test_cook_pts_flg = PETSC_FALSE;
4253 PetscInt atom_test = 0;
4254 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook",
4255 &test_cook_flg, PETSC_NULLPTR);
4256 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook_pts",
4257 &test_cook_pts_flg, PETSC_NULLPTR);
4258 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
4259 PETSC_NULLPTR);
4260 if (atom_test || test_cook_flg || test_cook_pts_flg) {
4262 ep_ptr->elementVolumeName, testing_monitor_ptr));
4263 }
4264 }
4265 MOFEM_LOG("EP", Sev::inform) << "TS monitor setup";
4266 return std::make_tuple(ts_ctx);
4267 };
4268
4269 auto setup_snes_monitor = [&]() {
4271 SNES snes;
4272 CHKERR TSGetSNES(ts, &snes);
4273 auto snes_ctx = getDMSnesCtx(ep_ptr->dmElastic);
4274 CHKERR SNESMonitorSet(snes,
4275 (MoFEMErrorCode (*)(SNES, PetscInt, PetscReal,
4276 void *))MoFEMSNESMonitorEnergy,
4277 (void *)(snes_ctx.get()), PETSC_NULLPTR);
4278 MOFEM_LOG("EP", Sev::inform) << "SNES monitor setup";
4280 };
4281
4282 auto setup_snes_conergence_test = [&]() {
4284
4285 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
4286 PetscReal snorm, PetscReal fnorm,
4287 SNESConvergedReason *reason, void *cctx) {
4289 // EshelbianCore *ep_ptr = (EshelbianCore *)cctx;
4290 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
4291 PETSC_NULLPTR);
4292
4293 Vec x_update, r;
4294 CHKERR SNESGetSolutionUpdate(snes, &x_update);
4295 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
4296
4298 };
4299
4300 // SNES snes;
4301 // CHKERR TSGetSNES(ts, &snes);
4302 // CHKERR SNESSetConvergenceTest(snes, snes_convergence_test, ep_ptr,
4303 // PETSC_NULLPTR);
4304 // MOFEM_LOG("EP", Sev::inform) << "SNES convergence test setup";
4306 };
4307
4308 auto setup_section = [&]() {
4309 PetscSection section_raw;
4310 CHK_THROW_MESSAGE(DMGetSection(ep_ptr->dmElastic, &section_raw),
4311 "get DM section");
4312 int num_fields;
4313 CHK_THROW_MESSAGE(PetscSectionGetNumFields(section_raw, &num_fields),
4314 "get num fields");
4315 for (int ff = 0; ff != num_fields; ff++) {
4316 const char *field_name;
4318 PetscSectionGetFieldName(section_raw, ff, &field_name),
4319 "get field name");
4320 MOFEM_LOG_C("EP", Sev::inform, "Field %d name %s", ff, field_name);
4321 }
4322 return SmartPetscObj<PetscSection>(section_raw, true);
4323 };
4324
4325 auto set_vector_on_mesh = [&]() {
4327 CHKERR DMoFEMMeshToLocalVector(ep_ptr->dmElastic, x, INSERT_VALUES,
4328 SCATTER_FORWARD);
4329 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4330 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4331 MOFEM_LOG("EP", Sev::inform) << "Vector set on mesh";
4333 };
4334
4335 auto setup_schur_block_solver = [&]() {
4336 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver";
4337 CHK_THROW_MESSAGE(TSAppendOptionsPrefix(ts, "elastic_"),
4338 "append options prefix");
4339 CHK_THROW_MESSAGE(TSSetFromOptions(ts), "set from options");
4340 CHK_THROW_MESSAGE(TSSetDM(ts, ep_ptr->dmElastic), "set DM");
4341 // Adding field split solver
4342 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
4343 if constexpr (A == AssemblyType::BLOCK_MAT) {
4344 schur_ptr =
4346 CHK_THROW_MESSAGE(schur_ptr->setUp(ts), "setup schur");
4347 }
4348 MOFEM_LOG("EP", Sev::inform) << "Setting up Schur block solver done";
4349 return schur_ptr;
4350 };
4351
4352 // Warning: sequence of construction is not guaranteed for tuple. You have
4353 // to enforce order by proper packaging.
4354
4355#ifdef ENABLE_PYTHON_BINDING
4356 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
4357 setup_snes_monitor(), setup_snes_conergence_test(),
4358 setup_section(), set_vector_on_mesh(),
4359 setup_schur_block_solver());
4360#else
4361 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
4362 setup_snes_conergence_test(), setup_section(),
4363 set_vector_on_mesh(), setup_schur_block_solver());
4364#endif
4365 }
4366};
4367
4370
4371 PetscBool debug_model = PETSC_FALSE;
4372 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
4373 PETSC_NULLPTR);
4374 MOFEM_LOG("EP", Sev::inform)
4375 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
4376
4377 if (debug_model == PETSC_TRUE) {
4378 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4379 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
4380 void *ctx) {
4382
4383 SNES snes;
4384 CHKERR TSGetSNES(ts, &snes);
4385 int it;
4386 CHKERR SNESGetIterationNumber(snes, &it);
4387 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
4388 CHKERR postProcessResults(1, file_name, F, u_t, PETSC_NULLPTR, {}, ts);
4389 std::string file_skel_name =
4390 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
4391
4392 auto get_material_force_tag = [&]() {
4393 auto &moab = mField.get_moab();
4394 Tag tag;
4395 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
4396 "can't get tag");
4397 return tag;
4398 };
4399
4400 CHKERR calculateFaceMaterialForce(1, ts);
4401 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
4402 {get_material_force_tag()}, ts);
4403
4405 };
4406 ts_ctx_ptr->tsDebugHook = post_proc;
4407 }
4408
4410}
4411
4414
4415 CHKERR addDebugModel(ts);
4416
4417 auto storage = solve_elastic_setup::setup(this, ts, x, true);
4418
4419 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4420 Vec xx;
4421 CHKERR VecDuplicate(x, &xx);
4422 CHKERR VecZeroEntries(xx);
4423 CHKERR TS2SetSolution(ts, x, xx);
4424 CHKERR VecDestroy(&xx);
4425 } else {
4426 CHKERR TSSetSolution(ts, x);
4427 }
4428
4429 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4430 {elasticFeLhs.get(), elasticFeRhs.get()});
4431 CHKERR TSSetUp(ts);
4432 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4433 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4435 CHKERR TSSolve(ts, PETSC_NULLPTR);
4437 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4438 {elasticFeLhs.get(), elasticFeRhs.get()});
4439
4440#ifndef NDEBUG
4441 // Make graph
4442 if (mField.get_comm_rank() == 0) {
4443 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4445 "solve_elastic_graph.dot");
4446 }
4447#endif
4448
4449 SNES snes;
4450 CHKERR TSGetSNES(ts, &snes);
4451 int lin_solver_iterations;
4452 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
4453 MOFEM_LOG("EP", Sev::inform)
4454 << "Number of linear solver iterations " << lin_solver_iterations;
4455
4456 PetscBool test_cook_flg = PETSC_FALSE;
4457 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
4458 PETSC_NULLPTR);
4459 if (test_cook_flg) {
4460 PetscInt expected_lin_solver_iterations = 11;
4461 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "",
4462 "-test_cook_max_linear_iterations",
4463 &expected_lin_solver_iterations, PETSC_NULLPTR);
4464 if (lin_solver_iterations > expected_lin_solver_iterations)
4465 SETERRQ(
4466 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4467 "Expected number of iterations is different than expected %d > %d",
4468 lin_solver_iterations, expected_lin_solver_iterations);
4469 }
4470
4471 PetscBool test_sslv116_flag = PETSC_FALSE;
4472 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
4473 &test_sslv116_flag, PETSC_NULLPTR);
4474
4475 if (test_sslv116_flag) {
4476 double max_val = 0.0;
4477 double min_val = 0.0;
4478 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
4480 auto ent_type = ent_ptr->getEntType();
4481 if (ent_type == MBVERTEX) {
4482 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
4483 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
4484 }
4486 };
4487 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
4488 field_min_max, spatialH1Disp);
4489
4490 double global_max_val = 0.0;
4491 double global_min_val = 0.0;
4492 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
4493 mField.get_comm());
4494 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
4495 mField.get_comm());
4496 MOFEM_LOG("EP", Sev::inform)
4497 << "Max " << spatialH1Disp << " value: " << global_max_val;
4498 MOFEM_LOG("EP", Sev::inform)
4499 << "Min " << spatialH1Disp << " value: " << global_min_val;
4500
4501 double ref_max_val = 0.00767;
4502 double ref_min_val = -0.00329;
4503 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
4504 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4505 "Incorrect max value of the displacement field: %f != %f",
4506 global_max_val, ref_max_val);
4507 }
4508 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
4509 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4510 "Incorrect min value of the displacement field: %f != %f",
4511 global_min_val, ref_min_val);
4512 }
4513 }
4514
4515 CHKERR gettingNorms();
4516
4518}
4519
4521 int start_step,
4522 double start_time) {
4524
4525 auto storage = solve_elastic_setup::setup(this, ts, x, false);
4526
4527 // Deprecated options
4528 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
4529
4530 CHKERR PetscOptionsScalar(
4531 "-dynamic_final_time", "dynamic relaxation final time", "",
4532 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
4533 CHKERR PetscOptionsScalar("-dynamic_delta_time",
4534 "dynamic relaxation final time", "", physicalDt,
4535 &physicalDt, PETSC_NULLPTR);
4536 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
4537 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
4538 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
4539 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
4540
4541 PetscOptionsEnd();
4542
4543 MOFEM_LOG("EP", Sev::warning)
4544 << "Following options are deprecated, use -physical prefix options "
4545 "instead";
4546 MOFEM_LOG("EP", Sev::inform)
4547 << "Dynamic relaxation final time -dynamic_final_time = "
4548 << finalPhysicalTime;
4549 MOFEM_LOG("EP", Sev::inform)
4550 << "Dynamic relaxation delta time -dynamic_delta_time = " << physicalDt;
4551 MOFEM_LOG("EP", Sev::inform)
4552 << "Dynamic relaxation max iterations -dynamic_max_it = "
4553 << physicalMaxSteps;
4554 MOFEM_LOG("EP", Sev::inform)
4555 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
4556 << (physicalH1Update ? "TRUE" : "FALSE");
4557
4558 CHKERR addDebugModel(ts);
4559
4560 auto setup_ts_monitor = [&]() {
4561 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
4562 return monitor_ptr;
4563 };
4564 auto monitor_ptr = setup_ts_monitor();
4565
4566 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4567 {elasticFeLhs.get(), elasticFeRhs.get()});
4568 CHKERR TSSetUp(ts);
4570
4571 double ts_delta_time;
4572 CHKERR TSGetTimeStep(ts, &ts_delta_time);
4573 CHKERR TSSetSolution(ts, x);
4574
4575 if (physicalH1Update) {
4576 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4577 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4578 } else {
4579 CHKERR TSSetPreStep(ts, PETSC_NULLPTR);
4580 CHKERR TSSetPostStep(ts, PETSC_NULLPTR);
4581 }
4582
4585
4586 currentPhysicalTime = start_time;
4587 physicalStepNumber = start_step;
4588 monitor_ptr->ts = PETSC_NULLPTR;
4589 monitor_ptr->ts_u = PETSC_NULLPTR;
4590 monitor_ptr->ts_t = currentPhysicalTime;
4591 monitor_ptr->ts_step = physicalStepNumber;
4592 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4593
4594 if (physicalDt <= 0.) {
4595 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY,
4596 "physicalDt must be positive, got %g", physicalDt);
4597 }
4598 for (; currentPhysicalTime < finalPhysicalTime;) {
4599 MOFEM_LOG("EP", Sev::inform)
4600 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
4601 << " delta time " << physicalDt;
4602
4603 CHKERR TSSetStepNumber(ts, 0);
4604 CHKERR TSSetTime(ts, 0);
4605 CHKERR TSSetTimeStep(ts, ts_delta_time);
4606 CHKERR TSSetSolution(ts, x);
4607 if (!physicalH1Update) {
4609 }
4610 CHKERR TSSolve(ts, PETSC_NULLPTR);
4611 if (!physicalH1Update) {
4613 }
4614
4615 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
4616 SCATTER_FORWARD);
4617 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4618 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4619
4620 monitor_ptr->ts = PETSC_NULLPTR;
4621 monitor_ptr->ts_u = x;
4622 monitor_ptr->ts_t = currentPhysicalTime;
4623 monitor_ptr->ts_step = physicalStepNumber;
4624 CHKERR DMoFEMLoopFiniteElements(dmElastic, elementVolumeName, monitor_ptr);
4625
4626 ++physicalStepNumber;
4627 if (physicalStepNumber > physicalMaxSteps)
4628 break;
4629
4630 const double remainingPhysicalTime =
4631 finalPhysicalTime - currentPhysicalTime;
4632 if (physicalDt >= remainingPhysicalTime) {
4633 currentPhysicalTime = finalPhysicalTime;
4634 } else {
4635 currentPhysicalTime += physicalDt;
4636 }
4637 }
4638
4640 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4641 {elasticFeLhs.get(), elasticFeRhs.get()});
4642
4644}
4645
4648
4649 auto set_block = [&](auto name, int dim) {
4650 std::map<int, Range> map;
4651 auto set_tag_impl = [&](auto name) {
4653 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4654 auto bcs = mesh_mng->getCubitMeshsetPtr(
4655
4656 std::regex((boost::format("%s(.*)") % name).str())
4657
4658 );
4659 for (auto bc : bcs) {
4660 Range r;
4661 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4662 true);
4663 map[bc->getMeshsetId()] = r;
4664 MOFEM_LOG("EP", Sev::inform)
4665 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4666 << r.size() << " entities";
4667 }
4669 };
4670
4671 CHKERR set_tag_impl(name);
4672
4673 return std::make_pair(name, map);
4674 };
4675
4676 auto set_skin = [&](auto &&map) {
4677 for (auto &m : map.second) {
4678 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4679 m.second.swap(s);
4680 MOFEM_LOG("EP", Sev::inform)
4681 << "Skin for block " << map.first << " id " << m.first << " has "
4682 << m.second.size() << " entities";
4683 }
4684 return map;
4685 };
4686
4687 auto set_tag = [&](auto &&map) {
4688 Tag th;
4689 auto name = map.first;
4690 int def_val[] = {-1};
4692 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4693 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4694 "create tag");
4695 for (auto &m : map.second) {
4696 int id = m.first;
4697 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4698 "clear tag");
4699 }
4700 return th;
4701 };
4702
4703 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4704 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4705 listTagsToTransfer.push_back(
4706 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4707 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4708
4710}
4711
4713EshelbianCore::postProcessRestartMesh(const int tag, const std::string file,
4714 std::vector<Tag> tags_to_transfer) {
4716 ParallelComm *pcomm =
4717 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
4718 // write file with only crack surfaces and full mesh
4719 if (crackingOn && !pcomm->rank()) {
4720 auto meshsets_mng = mField.getInterface<MeshsetsManager>();
4721
4722 std::vector<boost::shared_ptr<TempMeshset>> meshsets_tmp_list;
4723 auto &list = meshsets_mng->getMeshsetsMultindex();
4724 std::vector<Tag> tags_list;
4725
4726 auto meshset_ptr = get_temp_meshset_ptr(mField.get_moab());
4727
4728 for (auto &m : list) {
4729 meshsets_tmp_list.push_back(get_temp_meshset_ptr(mField.get_moab()));
4730 EntityHandle new_meshset = *meshsets_tmp_list.back();
4731 auto meshset = m.getMeshset();
4732 std::vector<Tag> tmp_tags_list;
4733 CHKERR mField.get_moab().tag_get_tags_on_entity(meshset, tmp_tags_list);
4734 Range ents;
4735 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
4736 CHKERR mField.get_moab().add_entities(new_meshset, ents);
4737 for (auto t : tmp_tags_list) {
4738 void *tag_vals[1];
4739 int tag_size[1];
4740 CHKERR mField.get_moab().tag_get_by_ptr(
4741 t, &meshset, 1, (const void **)tag_vals, tag_size);
4742 CHKERR mField.get_moab().tag_set_by_ptr(t, &new_meshset, 1, tag_vals,
4743 tag_size);
4744 }
4745 std::vector<std::string> remove_tags;
4746 remove_tags.push_back("AKDTree_coord_norm");
4747 remove_tags.push_back("__PARALLEL_");
4748 remove_tags.push_back("_RefBitLevel");
4749
4750 for (auto t : tmp_tags_list) {
4751 std::string tag_name;
4752 CHKERR mField.get_moab().tag_get_name(t, tag_name);
4753 bool add = true;
4754
4755 for (auto &p : remove_tags) {
4756 if (tag_name.compare(0, p.size(), p) == 0) {
4757 add = false;
4758 break;
4759 }
4760 }
4761
4762 if (add)
4763 tags_list.push_back(t);
4764 }
4765 }
4766
4767 for (auto &m_ptr : meshsets_tmp_list) {
4768 EntityHandle m = *m_ptr;
4769 CHKERR mField.get_moab().add_entities(*meshset_ptr, &m, 1);
4770 }
4771
4772 // meshsets_tmp_list has all meshsets to write
4773 std::sort(tags_list.begin(), tags_list.end());
4774 auto new_end = std::unique(tags_list.begin(), tags_list.end());
4775 tags_list.resize(std::distance(tags_list.begin(), new_end));
4776
4777 EntityHandle save_meshset = *meshset_ptr;
4778 CHKERR mField.get_moab().write_file(file.c_str(), "MOAB", "", &save_meshset,
4779 1, &tags_list[0], tags_list.size());
4780 }
4782}
4783
4785EshelbianCore::postProcessResults(const int tag, const std::string file,
4786 Vec f_residual, Vec var_vector, Vec gradient,
4787 std::vector<Tag> tags_to_transfer, TS ts) {
4789
4790 SmartPetscObj<Vec> f_r, v_v;
4791 if (f_residual != PETSC_NULLPTR || var_vector != PETSC_NULLPTR) {
4793 SmartPetscObj<Vec> xout;
4794 xout = createDMVector(dM);
4795 auto xin = f_residual != PETSC_NULLPTR ? f_residual : var_vector;
4796 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4797 xin, "ELASTIC_PROBLEM", RowColData::ROW, xout, "ESHELBY_PLASTICITY",
4798 RowColData::ROW, scatter);
4799 if (f_residual) {
4800 f_r = vectorDuplicate(xout);
4801 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
4802 SCATTER_FORWARD);
4803 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
4804 SCATTER_FORWARD);
4805 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
4806 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
4807 }
4808 if (var_vector) {
4809 v_v = createDMVector(dM);
4810 CHKERR VecScatterBegin(scatter, var_vector, v_v, INSERT_VALUES,
4811 SCATTER_FORWARD);
4812 CHKERR VecScatterEnd(scatter, var_vector, v_v, INSERT_VALUES,
4813 SCATTER_FORWARD);
4814 CHKERR VecGhostUpdateBegin(v_v, INSERT_VALUES, SCATTER_FORWARD);
4815 CHKERR VecGhostUpdateEnd(v_v, INSERT_VALUES, SCATTER_FORWARD);
4816 }
4817 }
4818
4820 if (gradient) {
4822 g = createDMVector(dM);
4823 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4824 gradient, "MATERIAL_PROBLEM", RowColData::ROW, g, "ESHELBY_PLASTICITY",
4825 RowColData::ROW, scatter);
4826 CHKERR VecScatterBegin(scatter, gradient, g, INSERT_VALUES,
4827 SCATTER_FORWARD);
4828 CHKERR VecScatterEnd(scatter, gradient, g, INSERT_VALUES, SCATTER_FORWARD);
4829 CHKERR VecGhostUpdateBegin(g, INSERT_VALUES, SCATTER_FORWARD);
4830 CHKERR VecGhostUpdateEnd(g, INSERT_VALUES, SCATTER_FORWARD);
4831 }
4832
4833 // mark crack surface
4834 if (crackingOn) {
4835 auto get_tag = [&](auto name, auto dim) {
4836 auto &mob = mField.get_moab();
4837 Tag tag;
4838 double def_val[] = {0., 0., 0.};
4839 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4840 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4841 "create tag");
4842 return tag;
4843 };
4844 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4845 }
4846
4847 {
4848 auto get_crack_tag = [&]() {
4849 Tag th;
4850 rval = mField.get_moab().tag_get_handle("CRACK", th);
4851 if (rval == MB_SUCCESS) {
4852 MOAB_THROW(mField.get_moab().tag_delete(th));
4853 }
4854 int def_val[] = {0};
4855 MOAB_THROW(mField.get_moab().tag_get_handle(
4856 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4857 def_val));
4858 return th;
4859 };
4860
4861 Tag th = get_crack_tag();
4862 tags_to_transfer.push_back(th);
4863 int mark[] = {1};
4864 Range mark_faces;
4865 if (crackFaces)
4866 mark_faces.merge(*crackFaces);
4867 if (interfaceFaces)
4868 mark_faces.merge(*interfaceFaces);
4869 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4870 }
4871
4872 // add tags to transfer
4873 for (auto t : listTagsToTransfer) {
4874 std::string name;
4875 CHKERR mField.get_moab().tag_get_name(t, name);
4876 MOFEM_LOG("EP", Sev::verbose)
4877 << "Adding tag " << name << " to transfer list for post-processing";
4878 tags_to_transfer.push_back(t);
4879 }
4880
4881 if (!dataAtPts) {
4882 dataAtPts =
4883 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
4884 }
4885
4886 CHKERR DMoFEMLoopFiniteElements(dM, contactElement, contactTreeRhs);
4887
4888 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
4890 auto post_proc_ptr =
4891 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4892 mField, post_proc_mesh);
4893 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4894 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4895 frontAdjEdges);
4896
4897 if (ts != PETSC_NULLPTR) {
4898 post_proc_ptr->data_ctx |= PetscData::CTX_SET_TIME;
4899 CHKERR TSGetTime(ts, &(post_proc_ptr->ts_t));
4900 CHKERR TSGetTimeStep(ts, &(post_proc_ptr->ts_dt));
4901 }
4902
4903 auto domain_ops = [&](auto &fe, int sense) {
4905
4906 auto bubble_cache = boost::make_shared<CGGUserPolynomialBase::CachePhi>(
4907 0, 0, MatrixDouble());
4908 fe.getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
4909 new CGGUserPolynomialBase(bubble_cache));
4910 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4911 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
4912 frontAdjEdges);
4913 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4914 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4915 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
4916 constexpr bool add_bubble = true;
4917 if (add_bubble) {
4918 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4919 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
4920 SmartPetscObj<Vec>(), MBMAXTYPE));
4921 }
4922 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4923 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4924 if (isNoStretch()) {
4926 fe.getOpPtrVector(), physicalEquations, dataAtPts,
4927 externalStrainVecPtr, timeScaleMap);
4928 } else {
4929 fe.getOpPtrVector().push_back(
4931 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4932 }
4933 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
4934 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4935 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
4936 if (add_bubble) {
4937 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4938 bubbleField, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep,
4939 MBMAXTYPE));
4940 }
4941 if (!isNoStretch()) {
4942 fe.getOpPtrVector().push_back(
4944 stretchTensor, dataAtPts->getLogStretchTensor0AtPts(),
4945 solTSStep, MBTET));
4946 }
4947 if (var_vector) {
4948 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4949 piolaStress, dataAtPts->getVarPiolaPts(),
4950 boost::make_shared<double>(1), v_v));
4951 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4952 bubbleField, dataAtPts->getVarPiolaPts(),
4953 boost::make_shared<double>(1), v_v, MBMAXTYPE));
4954 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4955 rotAxis, dataAtPts->getVarRotAxisPts(), v_v, MBTET));
4956 if (isNoStretch()) {
4957 fe.getOpPtrVector().push_back(
4958 physicalEquations->returnOpCalculateVarStretchFromStress(
4959 dataAtPts, physicalEquations));
4960 } else {
4961 fe.getOpPtrVector().push_back(
4963 stretchTensor, dataAtPts->getVarLogStreachPts(), v_v, MBTET));
4964 }
4965 }
4966 if (gradient) {
4967 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4968 materialH1Positions, dataAtPts->getGradientAtPts(), g));
4969 }
4970
4971 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4972 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
4973
4974 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4975 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4976 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4977 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
4978 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
4979 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
4980 // evaluate derived quantities
4981 fe.getOpPtrVector().push_back(
4983
4984 // evaluate integration points
4985 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
4986 true, false, dataAtPts, physicalEquations));
4987 if (auto op =
4988 physicalEquations->returnOpCalculateEnergy(dataAtPts, nullptr)) {
4989 fe.getOpPtrVector().push_back(op);
4990 fe.getOpPtrVector().push_back(new OpCalculateEshelbyStress(dataAtPts));
4991 }
4992
4993 // // post-proc
4997
4998 struct OpSidePPMap : public OpPPMap {
4999 OpSidePPMap(moab::Interface &post_proc_mesh,
5000 std::vector<EntityHandle> &map_gauss_pts,
5001 DataMapVec data_map_scalar, DataMapMat data_map_vec,
5002 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
5003 int sense)
5004 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
5005 data_map_vec, data_map_mat, data_symm_map_mat),
5006 tagSense(sense) {}
5007
5008 MoFEMErrorCode doWork(int side, EntityType type,
5011
5012 if (tagSense != 0) {
5013 if (tagSense != OpPPMap::getSkeletonSense())
5015 }
5016
5017 CHKERR OpPPMap::doWork(side, type, data);
5019 }
5020
5021 private:
5022 int tagSense;
5023 };
5024
5025 OpPPMap::DataMapMat vec_fields;
5026 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
5027 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
5028 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5029 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
5030 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
5031 if (!isNoStretch()) {
5032 vec_fields["EiegnLogStreach"] = dataAtPts->getEigenVals();
5033 }
5034 if (var_vector) {
5035 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
5036 vec_fields["VarSpatialDisplacementL2"] =
5037 boost::make_shared<MatrixDouble>();
5038 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5039 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], v_v, MBTET));
5040 }
5041 if (f_residual) {
5042 vec_fields["ResSpatialDisplacementL2"] =
5043 boost::make_shared<MatrixDouble>();
5044 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5045 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], f_r, MBTET));
5046 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
5047 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5048 rotAxis, vec_fields["ResOmega"], f_r, MBTET));
5049 }
5050 if (gradient) {
5051 vec_fields["Gradient"] = dataAtPts->getGradientAtPts();
5052 }
5053
5054 OpPPMap::DataMapMat mat_fields;
5055 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5056 if (var_vector) {
5057 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
5058 }
5059 if (f_residual) {
5060 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
5061 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5062 piolaStress, mat_fields["ResPiolaStress"],
5063 boost::make_shared<double>(1), f_r));
5064 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5065 bubbleField, mat_fields["ResPiolaStress"],
5066 boost::make_shared<double>(1), f_r, MBMAXTYPE));
5067 }
5068 if (!internalStressTagName.empty()) {
5069 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
5070 switch (meshTransferInterpOrder) {
5071 case 0:
5072 fe.getOpPtrVector().push_back(
5073 new OpGetInternalStress<0>(dataAtPts, internalStressTagName));
5074 break;
5075 case 1:
5076 fe.getOpPtrVector().push_back(
5077 new OpGetInternalStress<1>(dataAtPts, internalStressTagName));
5078 break;
5079 default:
5080 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
5081 "Unsupported mesh transfer interpolation order %d, for "
5082 "internal stress",
5083 meshTransferInterpOrder);
5084 }
5085 }
5086
5087 OpPPMap::DataMapMat mat_fields_symm;
5088 mat_fields_symm["LogSpatialStretch"] =
5089 dataAtPts->getLogStretchTensorAtPts();
5090 mat_fields_symm["SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
5091 if (var_vector) {
5092 mat_fields_symm["VarLogSpatialStretch"] =
5093 dataAtPts->getVarLogStreachPts();
5094 }
5095 if (f_residual) {
5096 if (!isNoStretch()) {
5097 mat_fields_symm["ResLogSpatialStretch"] =
5098 boost::make_shared<MatrixDouble>();
5099 fe.getOpPtrVector().push_back(
5101 stretchTensor, mat_fields_symm["ResLogSpatialStretch"], f_r,
5102 MBTET));
5103 }
5104 }
5105
5106 fe.getOpPtrVector().push_back(
5107
5108 new OpSidePPMap(
5109
5110 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5111
5112 {},
5113
5114 vec_fields,
5115
5116 mat_fields,
5117
5118 mat_fields_symm,
5119
5120 sense
5121
5122 )
5123
5124 );
5125
5126 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
5127 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5128 dataAtPts, sense));
5129
5131 };
5132
5133 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
5134 // H1 material positions
5135 post_proc_ptr->getOpPtrVector().push_back(
5136 new OpCalculateVectorFieldValues<3>(materialH1Positions,
5137 dataAtPts->getLargeXH1AtPts()));
5138
5139 // domain
5141 mField, elementVolumeName, SPACE_DIM);
5142 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
5143 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
5144
5145 return post_proc_ptr;
5146 };
5147
5148 // contact
5149 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
5150 auto &pip) {
5152 // evaluate traction
5153 using EleOnSide =
5155 using SideEleOp = EleOnSide::UserDataOperator;
5156 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
5157 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5158 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5159 boost::shared_ptr<BaseFunction>(
5160 new CGGUserPolynomialBase(nullptr, true));
5161 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5162 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5163 materialH1Positions, frontAdjEdges);
5164 auto traction_ptr = boost::make_shared<MatrixDouble>();
5165 op_loop_domain_side->getOpPtrVector().push_back(
5167 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
5168
5169 pip.push_back(new OpCalculateVectorFieldValues<3>(
5170 contactDisp, dataAtPts->getContactL2AtPts()));
5171 pip.push_back(op_loop_domain_side);
5172 // evaluate contact displacement and contact conditions
5173 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5174 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
5175 pip.push_back(getOpContactDetection(
5176 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
5177 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
5178 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
5179
5181 using BoundaryEle =
5183 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
5184 pip.push_back(op_this);
5185
5186 op_this->getOpPtrVector().push_back(
5187
5188 new OpPPMap(
5189
5190 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5191
5192 {},
5193
5194 {{"ContactDisplacement", dataAtPts->getContactL2AtPts()}},
5195
5196 {},
5197
5198 {}
5199
5200 )
5201
5202 );
5203
5204 if (f_residual) {
5205
5206 auto contact_residual = boost::make_shared<MatrixDouble>();
5207 op_this->getOpPtrVector().push_back(
5209 contactDisp, contact_residual, f_r, MBTET));
5210 op_this->getOpPtrVector().push_back(
5211
5212 new OpPPMap(
5213
5214 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5215
5216 {},
5217
5218 {{"res_contact", contact_residual}},
5219
5220 {},
5221
5222 {}
5223
5224 )
5225
5226 );
5227 }
5228
5230 };
5231
5232 auto post_proc_mesh = boost::make_shared<moab::Core>();
5233 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5234 auto post_proc_negative_sense_ptr =
5235 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
5236 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5237 CHKERR calcs_side_traction_and_displacements(
5238 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
5239
5240 auto own_tets =
5241 CommInterface::getPartEntities(mField.get_moab(), mField.get_comm_rank())
5242 .subset_by_dimension(SPACE_DIM);
5243 Range own_faces;
5244 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
5245 own_faces, moab::Interface::UNION);
5246
5247 auto get_crack_faces = [&](auto crack_faces) {
5248 auto get_adj = [&](auto e, auto dim) {
5249 Range adj;
5250 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
5251 moab::Interface::UNION);
5252 return adj;
5253 };
5254 // this removes faces
5255 auto tets = get_adj(crack_faces, 3);
5256 // faces adjacent to tets not in crack_faces
5257 auto faces = subtract(get_adj(tets, 2), crack_faces);
5258 // what is left from below, are tets fully inside crack_faces
5259 tets = subtract(tets, get_adj(faces, 3));
5260 return subtract(crack_faces, get_adj(tets, 2));
5261 };
5262
5263 auto side_one_faces = [&](auto &faces) {
5264 std::pair<Range, Range> sides;
5265 for (auto f : faces) {
5266 Range adj;
5267 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
5268 adj = intersect(own_tets, adj);
5269 for (auto t : adj) {
5270 int side, sense, offset;
5271 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
5272 if (sense == 1) {
5273 sides.first.insert(f);
5274 } else {
5275 sides.second.insert(f);
5276 }
5277 }
5278 }
5279 return sides;
5280 };
5281
5282 auto get_interface_from_block = [&](auto block_name) {
5283 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
5284 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
5285 Range faces;
5286 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
5287 faces, moab::Interface::UNION);
5288 faces = subtract(faces, skin);
5289 return faces;
5290 };
5291
5292 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
5293 // VOLUME_INTERFACE faces were already merged into interfaceFaces in
5294 // projectGeometry(), after applying REMOVE_INTERFACE exclusions.
5295 auto crack_side_faces = side_one_faces(crack_faces);
5296 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5297 auto ent = fe_method_ptr->getFEEntityHandle();
5298 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
5299 return false;
5300 }
5301 return true;
5302 };
5303 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5304 auto ent = fe_method_ptr->getFEEntityHandle();
5305 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
5306 return false;
5307 }
5308 return true;
5309 };
5310
5311 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5312 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5313 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
5314
5315 auto post_proc_begin =
5316 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5317 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5318 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
5319 post_proc_ptr->exeTestHook = side_one_crack_faces;
5321 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5322 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
5323 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5324 post_proc_negative_sense_ptr, 0,
5325 mField.get_comm_size());
5326
5327 constexpr bool debug = false;
5328 if (debug) {
5329
5330 auto get_adj_front = [&]() {
5331 auto skeleton_faces = *skeletonFaces;
5332 Range adj_front;
5333 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
5334 moab::Interface::UNION);
5335
5336 adj_front = intersect(adj_front, skeleton_faces);
5337 adj_front = subtract(adj_front, *crackFaces);
5338 adj_front = intersect(own_faces, adj_front);
5339 return adj_front;
5340 };
5341
5342 auto adj_front = filter_owners(mField, get_adj_front());
5343 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
5344 auto ent = fe_method_ptr->getFEEntityHandle();
5345 if (adj_front.find(ent) == adj_front.end()) {
5346 return false;
5347 }
5348 return true;
5349 };
5350
5351 post_proc_ptr->exeTestHook = only_front_faces;
5353 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5354 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
5355 CHKERR DMoFEMLoopFiniteElementsUpAndLowRank(dM, skeletonElement,
5356 post_proc_negative_sense_ptr, 0,
5357 mField.get_comm_size());
5358 }
5359 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5360 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5361
5362 CHKERR post_proc_end.writeFile(file.c_str());
5364}
5365
5367EshelbianCore::postProcessSkeletonResults(const int tag, const std::string file,
5368 Vec f_residual,
5369 std::vector<Tag> tags_to_transfer,
5370 TS ts) {
5372
5374 if (f_residual != PETSC_NULLPTR) {
5376 f_r = createDMVector(dM);
5377 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
5378 f_residual, "ELASTIC_PROBLEM", RowColData::ROW, f_r,
5379 "ESHELBY_PLASTICITY", RowColData::ROW, scatter);
5380 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
5381 SCATTER_FORWARD);
5382 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
5383 SCATTER_FORWARD);
5384 }
5385
5387
5388 auto post_proc_mesh = boost::make_shared<moab::Core>();
5389 auto post_proc_ptr =
5390 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5391 mField, post_proc_mesh);
5392 if (ts != PETSC_NULLPTR) {
5393 post_proc_ptr->data_ctx |= PetscData::CtxSetTime;
5394 CHKERR TSGetTime(ts, &post_proc_ptr->ts_t);
5395 CHKERR TSGetTimeStep(ts, &post_proc_ptr->ts_dt);
5396 }
5397 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
5398 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5400
5401 auto hybrid_disp = boost::make_shared<MatrixDouble>();
5402 post_proc_ptr->getOpPtrVector().push_back(
5404 post_proc_ptr->getOpPtrVector().push_back(
5406 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
5407
5408 auto op_loop_domain_side =
5410 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5411 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
5412
5413 // evaluated in side domain, that is op_loop_domain_side
5414 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5415 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
5416 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5417 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5419 op_loop_domain_side->getOpPtrVector().push_back(
5421 piolaStress, dataAtPts->getApproxPAtPts()));
5422 op_loop_domain_side->getOpPtrVector().push_back(
5424 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
5425 op_loop_domain_side->getOpPtrVector().push_back(
5427 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
5428
5429 if (isNoStretch()) {
5430 pushOpCalculateStretchFromStress(
5431 op_loop_domain_side->getOpPtrVector(), physicalEquations, dataAtPts,
5433 } else {
5434 op_loop_domain_side->getOpPtrVector().push_back(
5436 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
5437 }
5438
5440
5441 OpPPMap::DataMapMat vec_fields;
5442 vec_fields["HybridDisplacement"] = hybrid_disp;
5443 // note that grad and omega have not trace, so this is only other side value
5444 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
5445 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5446 OpPPMap::DataMapMat mat_fields;
5447 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5448 mat_fields["HybridDisplacementGradient"] =
5449 dataAtPts->getGradHybridDispAtPts();
5450 OpPPMap::DataMapMat mat_fields_symm;
5451 mat_fields_symm["LogSpatialStretch"] = dataAtPts->getLogStretchTensorAtPts();
5452
5453 post_proc_ptr->getOpPtrVector().push_back(
5454
5455 new OpPPMap(
5456
5457 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5458
5459 {},
5460
5461 vec_fields,
5462
5463 mat_fields,
5464
5465 mat_fields_symm
5466
5467 )
5468
5469 );
5470
5471 if (f_residual) {
5472 auto hybrid_res = boost::make_shared<MatrixDouble>();
5473 post_proc_ptr->getOpPtrVector().push_back(
5475 f_r));
5477 post_proc_ptr->getOpPtrVector().push_back(
5478
5479 new OpPPMap(
5480
5481 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5482
5483 {},
5484
5485 {{"res_hybrid", hybrid_res}},
5486
5487 {},
5488
5489 {}
5490
5491 )
5492
5493 );
5494 }
5495
5496 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5497
5498 auto post_proc_begin =
5499 PostProcBrokenMeshInMoabBaseBegin(mField, post_proc_mesh);
5500 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5501 CHKERR DMoFEMLoopFiniteElements(dM, skeletonElement, post_proc_ptr);
5502 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5503 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5504
5505 CHKERR post_proc_end.writeFile(file.c_str());
5506
5508}
5509
5510//! [Getting norms]
5513
5514 auto post_proc_norm_fe =
5515 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
5516
5517 auto bubble_cache =
5518 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
5519 post_proc_norm_fe->getUserPolynomialBase() =
5520 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase(bubble_cache));
5521 post_proc_norm_fe->getRuleHook = [](int, int, int) { return -1; };
5522 post_proc_norm_fe->setRuleHook = SetIntegrationAtFrontVolume(
5523 frontVertices, frontAdjEdges, vol_rule, bubble_cache);
5524 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5525 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
5527
5528 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
5529 auto norms_vec =
5530 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
5531 CHKERR VecZeroEntries(norms_vec);
5532
5533 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
5534 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5535 post_proc_norm_fe->getOpPtrVector().push_back(
5537 post_proc_norm_fe->getOpPtrVector().push_back(
5539 post_proc_norm_fe->getOpPtrVector().push_back(
5540 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
5541 post_proc_norm_fe->getOpPtrVector().push_back(
5542 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
5543 post_proc_norm_fe->getOpPtrVector().push_back(
5544 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
5545 u_h1_ptr));
5546
5547 auto piola_ptr = boost::make_shared<MatrixDouble>();
5548 post_proc_norm_fe->getOpPtrVector().push_back(
5550 post_proc_norm_fe->getOpPtrVector().push_back(
5552 MBMAXTYPE));
5553
5554 post_proc_norm_fe->getOpPtrVector().push_back(
5555 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
5556
5557 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
5559 *post_proc_norm_fe);
5560 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
5561
5562 CHKERR VecAssemblyBegin(norms_vec);
5563 CHKERR VecAssemblyEnd(norms_vec);
5564 const double *norms;
5565 CHKERR VecGetArrayRead(norms_vec, &norms);
5566 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
5567 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
5568 MOFEM_LOG("EP", Sev::inform)
5569 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
5570 MOFEM_LOG("EP", Sev::inform)
5571 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
5572 CHKERR VecRestoreArrayRead(norms_vec, &norms);
5573
5575}
5576//! [Getting norms]
5577
5580
5581 auto bc_mng = mField.getInterface<BcManager>();
5583 "", piolaStress, false, false);
5584 CHKERR bc_mng->pushMarkDOFsOnEntities<BcDisplacementMeshsetType<BLOCKSET>>(
5585 "", piolaStress, false, false);
5586
5587 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
5588 auto get_fix_load_history = [&](const std::string &block_name) {
5589 for (const auto type_name : {"FIX_X", "FIX_Y", "FIX_Z", "FIX_ALL"}) {
5590 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5591 std::regex(
5592
5593 (boost::format("%s(.*)") % type_name).str()
5594
5595 ))
5596
5597 ) {
5598 if (it->getName() == block_name) {
5600 type_name, it->getMeshsetId(), "load_history");
5601 }
5602 }
5603 }
5604 return std::string();
5605 };
5606
5607 for (auto bc : bc_mng->getBcMapByBlockName()) {
5608 if (auto disp_bc = bc.second->dispBcPtr) {
5609
5610 auto [field_name, block_name] =
5612 MOFEM_LOG("EP", Sev::inform)
5613 << "Field name: " << field_name << " Block name: " << block_name;
5614 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
5615
5616 std::vector<double> block_attributes(6, 0.);
5617 if (disp_bc->data.flag1 == 1) {
5618 block_attributes[0] = disp_bc->data.value1;
5619 block_attributes[3] = 1;
5620 }
5621 if (disp_bc->data.flag2 == 1) {
5622 block_attributes[1] = disp_bc->data.value2;
5623 block_attributes[4] = 1;
5624 }
5625 if (disp_bc->data.flag3 == 1) {
5626 block_attributes[2] = disp_bc->data.value3;
5627 block_attributes[5] = 1;
5628 }
5629 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5630 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces,
5631 get_fix_load_history(block_name));
5632 }
5633 }
5634 // old way of naming blocksets for displacement BCs
5635 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
5636
5638 boost::make_shared<NormalDisplacementBcVec>();
5639 CHKERR getBc(bcSpatialNormalDisplacementVecPtr, "NORMAL_DISPLACEMENT", 1);
5640
5641 bcSpatialSpringVecPtr = boost::make_shared<SpringBcVec>();
5642 auto mesh_mng = mField.getInterface<MeshsetsManager>();
5643 for (auto it : mesh_mng->getCubitMeshsetPtr(
5644 std::regex((boost::format("(.*)%s(.*)") % "SPRING_BC").str()))) {
5645 std::vector<double> block_attributes;
5646 CHKERR it->getAttributes(block_attributes);
5647 if (block_attributes.size() < 2) {
5648 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5649 "In block %s expected 2 attributes, but given %ld",
5650 it->getName().c_str(), block_attributes.size());
5651 }
5652 Range faces;
5653 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
5654 true);
5655 MOFEM_LOG("EP", Sev::inform)
5656 << "Found spring BC on block " << it->getName();
5657 MOFEM_LOG("EP", Sev::inform)
5658 << " kn = " << block_attributes[0] << ", kt = " << block_attributes[1];
5659 MOFEM_LOG("EP", Sev::inform) << " nb. of faces " << faces.size();
5660 bcSpatialSpringVecPtr->emplace_back(it->getName(), block_attributes, faces);
5661 }
5662
5664 boost::make_shared<AnalyticalDisplacementBcVec>();
5665 CHKERR getBc(bcSpatialAnalyticalDisplacementVecPtr, "ANALYTICAL_DISPLACEMENT",
5666 3);
5667
5668 auto ts_displacement =
5669 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
5670 for (auto &bc : *bcSpatialDispVecPtr) {
5671 MOFEM_LOG("EP", Sev::noisy)
5672 << "Add time scaling displacement BC: " << bc.blockName;
5673 if (!bc.loadHistoryFile.empty()) {
5674 MOFEM_LOG("EP", Sev::inform)
5675 << "Displacement load history from JSON for " << bc.blockName << ": "
5676 << bc.loadHistoryFile;
5677 timeScaleMap[bc.blockName] =
5678 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5679 } else {
5680 timeScaleMap[bc.blockName] =
5682 ts_displacement, "disp_history", ".txt", bc.blockName);
5683 }
5684 }
5685
5686 auto ts_normal_displacement =
5687 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
5688 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
5689 MOFEM_LOG("EP", Sev::noisy)
5690 << "Add time scaling normal displacement BC: " << bc.blockName;
5691 if (!bc.loadHistoryFile.empty()) {
5692 MOFEM_LOG("EP", Sev::inform)
5693 << "Normal displacement load history from JSON for " << bc.blockName
5694 << ": " << bc.loadHistoryFile;
5695 timeScaleMap[bc.blockName] =
5696 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5697 } else {
5698 timeScaleMap[bc.blockName] =
5700 ts_normal_displacement, "normal_disp_history", ".txt",
5701 bc.blockName);
5702 }
5703 }
5704
5706}
5707
5710
5711 auto bc_mng = mField.getInterface<BcManager>();
5713 false, false);
5714
5715 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
5716
5717 for (auto bc : bc_mng->getBcMapByBlockName()) {
5718 if (auto force_bc = bc.second->forceBcPtr) {
5719
5720 auto [field_name, block_name] =
5722 MOFEM_LOG("EP", Sev::inform)
5723 << "Field name: " << field_name << " Block name: " << block_name;
5724 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
5725
5726 std::vector<double> block_attributes(6, 0.);
5727 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
5728 block_attributes[3] = 1;
5729 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
5730 block_attributes[4] = 1;
5731 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
5732 block_attributes[5] = 1;
5733 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5734 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
5735 faces);
5736 }
5737 }
5738 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
5739
5740 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
5741 CHKERR getBc(bcSpatialPressureVecPtr, "PRESSURE", 1);
5742
5744 boost::make_shared<AnalyticalTractionBcVec>();
5745 CHKERR getBc(bcSpatialAnalyticalTractionVecPtr, "ANALYTICAL_TRACTION", 3);
5746
5747 auto ts_traction =
5748 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
5749 for (auto &bc : *bcSpatialTractionVecPtr) {
5750 if (!bc.loadHistoryFile.empty()) {
5751 MOFEM_LOG("EP", Sev::inform)
5752 << "Traction load history from JSON for " << bc.blockName << ": "
5753 << bc.loadHistoryFile;
5754 timeScaleMap[bc.blockName] =
5755 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5756 } else {
5757 timeScaleMap[bc.blockName] =
5759 ts_traction, "traction_history", ".txt", bc.blockName);
5760 }
5761 }
5762
5763 auto ts_pressure =
5764 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
5765 for (auto &bc : *bcSpatialPressureVecPtr) {
5766 if (!bc.loadHistoryFile.empty()) {
5767 MOFEM_LOG("EP", Sev::inform)
5768 << "Pressure load history from JSON for " << bc.blockName << ": "
5769 << bc.loadHistoryFile;
5770 timeScaleMap[bc.blockName] =
5771 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5772 } else {
5773 timeScaleMap[bc.blockName] =
5775 ts_pressure, "pressure_history", ".txt", bc.blockName);
5776 }
5777 }
5778
5780}
5781
5784
5785 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
5786 &ext_strain_vec_ptr,
5787 const std::string block_name,
5788 const int nb_attributes) {
5790 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5791 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
5792 std::vector<double> block_attributes;
5793 const bool analytical_external_strain = std::regex_match(
5794 it->getName(), std::regex("(.*)ANALYTICAL_EXTERNALSTRAIN(.*)"));
5795 const std::string json_block_name =
5796 analytical_external_strain ? "ANALYTICAL_EXTERNALSTRAIN" : block_name;
5797
5798 CHKERR it->getAttributes(block_attributes);
5799
5800 if (block_attributes.size() < nb_attributes) {
5801 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5802 "In block %s expected %d attributes, but given %ld",
5803 it->getName().c_str(), nb_attributes, block_attributes.size());
5804 }
5805
5806 auto get_block_ents = [&]() {
5807 Range ents;
5808 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
5809 true);
5810 return ents;
5811 };
5812
5813 std::string load_history;
5814 if (!analytical_external_strain) {
5815 load_history = getStringArgumentFromJsonBlockset(
5816 json_block_name, it->getMeshsetId(), "load_history");
5817 }
5818 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
5819 get_block_ents(), load_history);
5820 }
5822 };
5823
5824 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
5825
5826 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
5827
5828 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
5829 "externalstrain_history.txt");
5830 for (auto &ext_strain_block : *externalStrainVecPtr) {
5831 MOFEM_LOG("EP", Sev::noisy)
5832 << "Add time scaling external strain: " << ext_strain_block.blockName;
5833 if (!ext_strain_block.loadHistoryFile.empty()) {
5834 MOFEM_LOG("EP", Sev::inform)
5835 << "External strain load history from JSON for "
5836 << ext_strain_block.blockName << ": "
5837 << ext_strain_block.loadHistoryFile;
5838 timeScaleMap[ext_strain_block.blockName] =
5839 boost::make_shared<DynamicRelaxationTimeScale>(
5840 ext_strain_block.loadHistoryFile);
5841 } else {
5842 timeScaleMap[ext_strain_block.blockName] =
5844 ts_pre_stretch, "externalstrain_history", ".txt",
5845 ext_strain_block.blockName);
5846 }
5847 }
5848
5850}
5851
5854
5855 auto print_loc_size = [this](auto v, auto str, auto sev) {
5857 int size;
5858 CHKERR VecGetLocalSize(v.second, &size);
5859 int low, high;
5860 CHKERR VecGetOwnershipRange(v.second, &low, &high);
5861 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5862 << " " << high << " ) ";
5865 };
5866
5868 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5869 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5871 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5872 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5874 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5875 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5877 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5878 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5879
5881}
5882
5884 int start_step,
5885 double start_time) {
5887
5888 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5889
5890 auto cohesive_tao_ctx = createCohesiveTAOCtx(
5891 this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
5892 SmartPetscObj<TS>(ts, true));
5893
5894 // Deprecated options
5895 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5896
5897 CHKERR PetscOptionsScalar(
5898 "-dynamic_final_time", "dynamic relaxation final time", "",
5899 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
5900 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5901 "dynamic relaxation final time", "", physicalDt,
5902 &physicalDt, PETSC_NULLPTR);
5903 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5904 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
5905 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5906 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
5907
5908 PetscOptionsEnd();
5909
5910 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
5911 MOFEM_LOG("EP", Sev::inform)
5912 << "Dynamic relaxation final time -dynamic_final_time = "
5914 MOFEM_LOG("EP", Sev::inform)
5915 << "Dynamic relaxation delta time -dynamic_delta_time = " << physicalDt;
5916 MOFEM_LOG("EP", Sev::inform)
5917 << "Dynamic relaxation max iterations -dynamic_max_it = "
5919 MOFEM_LOG("EP", Sev::inform)
5920 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5921 << (physicalH1Update ? "TRUE" : "FALSE");
5922
5923 CHKERR initializeCohesiveKappaField(*this);
5925
5926 auto setup_ts_monitor = [&]() {
5927 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5928 return monitor_ptr;
5929 };
5930 auto monitor_ptr = setup_ts_monitor();
5931
5932 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5933 {elasticFeLhs.get(), elasticFeRhs.get()});
5934 CHKERR TSSetUp(ts);
5935 CHKERR TSElasticPostStep::postStepInitialise(this);
5936
5937 double ts_delta_time;
5938 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5939
5940 if (physicalH1Update) {
5941 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5942 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5943 }
5944
5945 auto tao = createTao(mField.get_comm());
5946 CHKERR TaoSetType(tao, TAOLMVM);
5947 auto g = cohesive_tao_ctx->duplicateGradientVec();
5949 cohesiveEvaluateObjectiveAndGradient,
5950 (void *)cohesive_tao_ctx.get());
5951
5952 currentPhysicalTime = start_time;
5953 physicalStepNumber = start_step;
5954 monitor_ptr->ts = PETSC_NULLPTR;
5955 monitor_ptr->ts_u = PETSC_NULLPTR;
5956 monitor_ptr->ts_t = currentPhysicalTime;
5957 monitor_ptr->ts_step = physicalStepNumber;
5959
5960 auto tao_sol0 = cohesive_tao_ctx->duplicateKappaVec();
5961 int tao_sol_size, tao_sol_loc_size;
5962 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
5963 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
5964 MOFEM_LOG("EP", Sev::inform)
5965 << "Cohesive crack growth initial kappa vector size " << tao_sol_size
5966 << " local size " << tao_sol_loc_size << " number of interface faces "
5967 << interfaceFaces->size();
5968
5969 CHKERR TaoSetFromOptions(tao);
5970
5971 auto xl = vectorDuplicate(tao_sol0);
5972 auto xu = vectorDuplicate(tao_sol0);
5973 CHKERR VecSet(xl, 0.0);
5974 CHKERR VecSet(xu, PETSC_INFINITY);
5975 CHKERR TaoSetVariableBounds(tao, xl, xu);
5976
5977 if (physicalDt <= 0.) {
5979 "physicalDt must be positive, got %g", physicalDt);
5980 }
5982 MOFEM_LOG("EP", Sev::inform)
5983 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
5984 << " delta time " << physicalDt;
5985
5986 CHKERR VecZeroEntries(tao_sol0);
5987 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5988 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5989 CHKERR TaoSetSolution(tao, tao_sol0);
5990
5991 if (!physicalH1Update && physicalStepNumber > start_step) {
5992 CHKERR TSElasticPostStep::preStepFun(ts);
5993 }
5994 CHKERR TaoSolve(tao);
5995
5996 Vec tao_sol;
5997 CHKERR TaoGetSolution(tao, &tao_sol);
5998
5999 // add solution increment to kappa vec/tags
6000 auto &kappa_vec = cohesive_tao_ctx->getKappaVec();
6002 get_kappa_tag(mField.get_moab()));
6003 CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
6004 CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
6005 SCATTER_FORWARD);
6006 CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
6008 get_kappa_tag(mField.get_moab()));
6009
6010 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6011 SCATTER_FORWARD);
6012 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6013 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6014 monitor_ptr->ts = PETSC_NULLPTR;
6015 monitor_ptr->ts_u = x;
6016 monitor_ptr->ts_t = currentPhysicalTime;
6017 monitor_ptr->ts_step = physicalStepNumber;
6019
6020 if (!physicalH1Update) {
6021 CHKERR TSElasticPostStep::postStepFun(ts);
6022 }
6023
6026 break;
6027
6028 const double remainingPhysicalTime =
6030 if (physicalDt >= remainingPhysicalTime) {
6032 } else {
6034 }
6035 }
6036
6037 CHKERR TSElasticPostStep::postStepDestroy();
6038 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6039 {elasticFeLhs.get(), elasticFeRhs.get()});
6040
6042}
6043
6045 double start_time) {
6047
6048 loadFactorTSSolveExecuted = PETSC_FALSE;
6049
6050 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6051
6053
6054 auto setup_ts_monitor = [&]() {
6055 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6056 return monitor_ptr;
6057 };
6058 auto monitor_ptr = setup_ts_monitor();
6059
6060 auto test_monitor_ptr =
6061 boost::make_shared<EshelbianTestingMonitor>(*this, monitor_ptr);
6062
6063 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6064 {elasticFeLhs.get(), elasticFeRhs.get()});
6065 CHKERR TSSetUp(ts);
6066 CHKERR TSElasticPostStep::postStepInitialise(this);
6067
6068 double ts_delta_time;
6069 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6070
6071 if (physicalH1Update) {
6072 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6073 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6074 }
6075
6076 CHKERR TSElasticPostStep::preStepFun(ts);
6077 CHKERR TSElasticPostStep::postStepFun(ts);
6078
6079 double load_factor_change_clip = 0.1;
6080
6081 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Load Factor Options", "none");
6082
6083 CHKERR PetscOptionsScalar("-initial_load_factor", "Initial load factor", "",
6084 loadFactor, &loadFactor, PETSC_NULLPTR);
6085 CHKERR PetscOptionsScalar(
6086 "-max_crack_ext_area", "Maximum crack extension area", "",
6087 maxCrackExtension, &maxCrackExtension, PETSC_NULLPTR);
6088 CHKERR PetscOptionsScalar(
6089 "-clip_load_factor_percent", "Upper bound for load factor change", "",
6090 load_factor_change_clip, &load_factor_change_clip, PETSC_NULLPTR);
6091 PetscOptionsEnd();
6092
6093 currentPhysicalTime = start_time;
6094 physicalStepNumber = start_step;
6095 monitor_ptr->ts = ts;
6096 monitor_ptr->ts_u = PETSC_NULLPTR;
6097 monitor_ptr->ts_t = currentPhysicalTime;
6098 monitor_ptr->ts_step = physicalStepNumber;
6100
6101 PetscBool test_cook_flg = PETSC_FALSE;
6102 PetscInt atom_test = 0;
6103 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
6104 PETSC_NULLPTR);
6105 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
6106 PETSC_NULLPTR);
6107 if (atom_test || test_cook_flg) {
6108 test_monitor_ptr->ts = ts;
6109 test_monitor_ptr->ts_u = PETSC_NULLPTR;
6110 test_monitor_ptr->ts_t = currentPhysicalTime;
6111 test_monitor_ptr->ts_step = physicalStepNumber;
6112
6114 test_monitor_ptr);
6115 }
6116
6117 MOFEM_LOG("EP", Sev::inform)
6118 << "Initial crack area: " << *currentCrackAreaPtr;
6119 MOFEM_LOG("EP", Sev::inform) << "Initial load factor: " << loadFactor;
6120 MOFEM_LOG("EP", Sev::inform)
6121 << "Initial crack front energy: " << avgGriffithsEnergy;
6122
6124 MOFEM_LOG("EP", Sev::inform)
6125 << "Load step " << physicalStepNumber << " Load Factor "
6126 << currentPhysicalTime << " delta load factor " << physicalDt;
6127
6131
6132 CHKERR TSSetStepNumber(ts, 0);
6133 CHKERR TSSetTime(ts, 0);
6134 CHKERR TSSetTimeStep(ts, ts_delta_time);
6135 if (!physicalH1Update) {
6136 CHKERR TSElasticPostStep::preStepFun(ts);
6137 }
6138 CHKERR TSSetSolution(ts, x);
6139 CHKERR TSSolve(ts, PETSC_NULLPTR);
6140 loadFactorTSSolveExecuted = PETSC_TRUE;
6141 if (!physicalH1Update) {
6142 CHKERR TSElasticPostStep::postStepFun(ts);
6143 }
6144
6145 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6146 SCATTER_FORWARD);
6147 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6148 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6149
6150 monitor_ptr->ts = ts;
6151 monitor_ptr->ts_u = x;
6152 monitor_ptr->ts_t = currentPhysicalTime;
6153 monitor_ptr->ts_step = physicalStepNumber;
6155
6156 if (atom_test || test_cook_flg) {
6157 test_monitor_ptr->ts = ts;
6158 test_monitor_ptr->ts_u = x;
6159 test_monitor_ptr->ts_t = currentPhysicalTime;
6160 test_monitor_ptr->ts_step = physicalStepNumber;
6162 test_monitor_ptr);
6163 }
6164
6165 if (mField.get_comm_rank() == 0) {
6166 const double delta_area = *currentCrackAreaPtr - oldCrackArea;
6167 const bool has_crack_extension = delta_area > 0.0;
6168
6169 if (has_crack_extension) {
6170 const double denom = 0.5 * std::abs(avgGriffithsEnergy);
6171 if (denom > 0.0) {
6172 const double updated_load_factor =
6173 oldLoadFactor * std::sqrt(griffithEnergy / denom);
6174 loadFactor = std::max(updated_load_factor, 1.0e-6);
6175 }
6176 }
6177
6178 const bool is_first_step = physicalStepNumber == start_step;
6179 const double initial_step_range = 5;
6180 const double min_load_factor = 1.0e-6;
6181 const double max_load_factor =
6182 oldLoadFactor * (1.0 + load_factor_change_clip);
6183
6184 if (physicalStepNumber >= start_step + initial_step_range) {
6185 loadFactor = std::clamp(loadFactor, min_load_factor, max_load_factor);
6186 MOFEM_LOG("EP", Sev::inform)
6187 << "Allowable range for load factor [" << min_load_factor << ", "
6188 << max_load_factor << "]";
6189 }
6190
6191 const double previous_load_factor = is_first_step ? 0. : oldLoadFactor;
6192 physicalDt = loadFactor - previous_load_factor;
6193
6194 MOFEM_LOG("EP", Sev::inform)
6195 << "Setting new load factor to: " << loadFactor;
6196 }
6197 double load_control_data[] = {physicalDt, loadFactor};
6198 CHKERR MPI_Bcast(load_control_data, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
6199 physicalDt = load_control_data[0];
6200 loadFactor = load_control_data[1];
6201
6204 break;
6205
6206 const double remainingPhysicalTime =
6208 if (physicalDt >= remainingPhysicalTime) {
6210 } else {
6212 }
6213 }
6214
6215 CHKERR TSElasticPostStep::postStepDestroy();
6216 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6217 {elasticFeLhs.get(), elasticFeRhs.get()});
6218 MOFEM_LOG("EP", Sev::inform) << "Final load factor: " << loadFactor;
6219
6221}
6222
6224 int start_step,
6225 double start_time) {
6227
6228 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6229
6230 auto topological_tao_ctx = createTopologicalTAOCtx(
6231 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6232 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6233 SmartPetscObj<TS>(ts, true));
6234
6235 double final_time = 1;
6236 double delta_time = 0.1;
6237 int max_it = 10;
6238 PetscBool ts_h1_update = PETSC_FALSE;
6239
6240 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
6241
6242 CHKERR PetscOptionsScalar("-dynamic_final_time",
6243 "dynamic relaxation final time", "", final_time,
6244 &final_time, PETSC_NULLPTR);
6245 CHKERR PetscOptionsScalar("-dynamic_delta_time",
6246 "dynamic relaxation final time", "", delta_time,
6247 &delta_time, PETSC_NULLPTR);
6248 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
6249 max_it, &max_it, PETSC_NULLPTR);
6250 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
6251 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
6252
6253 PetscOptionsEnd();
6254
6255 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6256 MOFEM_LOG("EP", Sev::inform)
6257 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
6258 MOFEM_LOG("EP", Sev::inform)
6259 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
6260 MOFEM_LOG("EP", Sev::inform)
6261 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
6262 MOFEM_LOG("EP", Sev::inform)
6263 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
6264 << (ts_h1_update ? "TRUE" : "FALSE");
6265
6267
6268 auto setup_ts_monitor = [&]() {
6269 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6270 return monitor_ptr;
6271 };
6272 auto monitor_ptr = setup_ts_monitor();
6273
6274 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6275 {elasticFeLhs.get(), elasticFeRhs.get()});
6276 CHKERR TSSetUp(ts);
6277 CHKERR TSElasticPostStep::postStepInitialise(this);
6278
6279 double ts_delta_time;
6280 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6281
6282 if (ts_h1_update) {
6283 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6284 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6285 }
6286
6287 CHKERR TSElasticPostStep::preStepFun(ts);
6288 CHKERR TSElasticPostStep::postStepFun(ts);
6289
6290 auto tao = createTao(mField.get_comm());
6291 CHKERR TaoSetType(tao, TAOLMVM);
6294 topologicalEvaluateObjectiveAndGradient,
6295 (void *)topological_tao_ctx.get());
6296
6297 currentPhysicalTime = start_time;
6298 physicalStepNumber = start_step;
6299 monitor_ptr->ts = PETSC_NULLPTR;
6300 monitor_ptr->ts_u = PETSC_NULLPTR;
6301 monitor_ptr->ts_t = currentPhysicalTime;
6302 monitor_ptr->ts_step = physicalStepNumber;
6304
6305 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6306 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6307 SCATTER_FORWARD, RowColData::ROW);
6308 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6309 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6310
6311 int tao_sol_size, tao_sol_loc_size;
6312 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6313 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6314 MOFEM_LOG("EP", Sev::inform)
6315 << "Toplogical data vector size " << tao_sol_size << " local size "
6316 << tao_sol_loc_size << " number of interface faces "
6317 << interfaceFaces->size();
6318
6319 CHKERR TaoSetFromOptions(tao);
6320
6321 if (delta_time <= 0.) {
6323 "delta_time must be positive, got %g", delta_time);
6324 }
6325 for (; currentPhysicalTime < final_time;) {
6326 MOFEM_LOG("EP", Sev::inform)
6327 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
6328 << " delta time " << delta_time;
6329
6330 CHKERR VecZeroEntries(tao_sol0);
6331 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6332 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6333 CHKERR TaoSetSolution(tao, tao_sol0);
6334 CHKERR TaoSolve(tao);
6335 Vec tao_sol;
6336 CHKERR TaoGetSolution(tao, &tao_sol);
6337
6338 // // add solution increment to kappa vec/tags
6339 // auto &kappa_vec = topological_tao_ctx->getKappaVec();
6340 // CHKERR CommInterface::setVectorFromTag(mField.get_moab(), kappa_vec,
6341 // get_kappa_tag(mField.get_moab()));
6342 // CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
6343 // CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
6344 // SCATTER_FORWARD);
6345 // CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES,
6346 // SCATTER_FORWARD); CHKERR
6347 // CommInterface::setTagFromVector(mField.get_moab(), kappa_vec,
6348 // get_kappa_tag(mField.get_moab()));
6349
6350 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6351 SCATTER_FORWARD);
6352 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6353 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6354 monitor_ptr->ts = PETSC_NULLPTR;
6355 monitor_ptr->ts_u = x;
6356 monitor_ptr->ts_t = currentPhysicalTime;
6357 monitor_ptr->ts_step = physicalStepNumber;
6359
6361 if (physicalStepNumber > max_it)
6362 break;
6363
6364 const double remainingPhysicalTime = final_time - currentPhysicalTime;
6365 if (delta_time >= remainingPhysicalTime) {
6366 currentPhysicalTime = final_time;
6367 } else {
6368 currentPhysicalTime += delta_time;
6369 }
6370 }
6371
6372 CHKERR TSElasticPostStep::postStepDestroy();
6373 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6374 {elasticFeLhs.get(), elasticFeRhs.get()});
6375
6377}
6378
6380 int start_step,
6381 double start_time) {
6383
6384 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6385
6386 auto topological_tao_ctx = createTopologicalTAOCtx(
6387 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6388 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6389 SmartPetscObj<TS>(ts, true));
6390
6391 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6393
6394 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6395
6396 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6397 {elasticFeLhs.get(), elasticFeRhs.get()});
6398 CHKERR TSSetUp(ts);
6399 CHKERR TSElasticPostStep::postStepInitialise(this);
6400
6401 double ts_delta_time;
6402 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6403
6404 if (physicalH1Update) {
6405 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6406 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6407 }
6408
6409 CHKERR TSElasticPostStep::preStepFun(ts);
6410 CHKERR TSElasticPostStep::postStepFun(ts);
6411
6412 const bool restart_run =
6413 start_step != 0 ||
6414 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6415 const double test_time = restart_run ? start_time : finalPhysicalTime;
6416 if (!restart_run &&
6417 std::abs(test_time) < std::numeric_limits<double>::epsilon()) {
6419 "Set non-zero -physical_final_time for test_topological_derivative");
6420 }
6421
6422 currentPhysicalTime = test_time;
6423 physicalStepNumber = start_step;
6424 monitor_ptr->ts = PETSC_NULLPTR;
6425 monitor_ptr->ts_u = PETSC_NULLPTR;
6426 monitor_ptr->ts_t = currentPhysicalTime;
6427 monitor_ptr->ts_step = physicalStepNumber;
6429
6430 MOFEM_LOG("EP", Sev::inform)
6431 << "Solving load step before topological derivative test: "
6432 << physicalStepNumber << " Time " << currentPhysicalTime
6433 << " TS delta time " << ts_delta_time;
6434
6435 CHKERR TSSetStepNumber(ts, 0);
6436 CHKERR TSSetTime(ts, 0);
6437 CHKERR TSSetTimeStep(ts, ts_delta_time);
6438 if (!physicalH1Update) {
6439 CHKERR TSElasticPostStep::preStepFun(ts);
6440 }
6441 CHKERR TSSetSolution(ts, x);
6442 CHKERR TSSolve(ts, PETSC_NULLPTR);
6443 if (!physicalH1Update) {
6444 CHKERR TSElasticPostStep::postStepFun(ts);
6445 }
6446
6447 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6448 SCATTER_FORWARD);
6449 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6450 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6451
6452 monitor_ptr->ts = PETSC_NULLPTR;
6453 monitor_ptr->ts_u = x;
6454 monitor_ptr->ts_t = currentPhysicalTime;
6455 monitor_ptr->ts_step = physicalStepNumber;
6457
6458 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6459 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6460 SCATTER_FORWARD, RowColData::ROW);
6461 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6462 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6463
6464 int tao_sol_size, tao_sol_loc_size;
6465 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6466 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6467 MOFEM_LOG("EP", Sev::inform)
6468 << "Topological data vector size " << tao_sol_size << " local size "
6469 << tao_sol_loc_size << " number of interface faces "
6470 << interfaceFaces->size();
6471
6472 const char *list_objective_models[ObjectiveModelType::LAST_MODEL] = {
6473 "python_model", "hencky_model"};
6474#ifdef ENABLE_PYTHON_BINDING
6475 PetscInt choice_objective_model = ObjectiveModelType::PYTHON_MODEL;
6476#else
6477 PetscInt choice_objective_model = ObjectiveModelType::HENCKY_MODEL;
6478#endif
6480 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_model_type",
6481 list_objective_models, ObjectiveModelType::LAST_MODEL,
6482 &choice_objective_model, PETSC_NULLPTR);
6483 const auto objective_model_type =
6484 static_cast<ObjectiveModelType>(choice_objective_model);
6485 MOFEM_LOG("EP", Sev::inform)
6486 << "Objective model type: -objective_model_type "
6487 << list_objective_models[objective_model_type];
6488
6490 PetscReal obj_value;
6491 CHKERR testTopologicalDerivative(topological_tao_ctx.get(), tao_sol0,
6492 &obj_value, g, objective_model_type);
6493
6494 CHKERR TSElasticPostStep::postStepDestroy();
6495 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6496 {elasticFeLhs.get(), elasticFeRhs.get()});
6497
6499}
6500
6501} // namespace EshelbianPlasticity
6502
Implementation of tonsorial bubble base div(v) = 0.
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
Implementation of CGGUserPolynomialBase class.
Auxilary functions for Eshelbian plasticity.
Contains definition of EshelbianMonitor class.
FormsIntegrators< FaceElementForcesAndSourcesCore::UserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMassVectorFace
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 9, 9 > OpStressGram_dBubble_dBubble
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 3, 9 > OpStressGram_dP_dP
static auto send_type(MoFEM::Interface &m_field, Range r, const EntityType type)
static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id, const unsigned int cubit_bc_type)
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto get_two_sides_of_crack_surface(MoFEM::Interface &m_field, Range crack_faces)
static auto get_range_from_block_map(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto filter_owners(MoFEM::Interface &m_field, Range skin)
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
static auto get_entities_by_handle(MoFEM::Interface &m_field, const std::string block_name)
static auto get_crack_front_edges(MoFEM::Interface &m_field, Range crack_faces)
Eshelbian plasticity interface.
Contains definition of EshelbianTestingMonitor class.
std::string type
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_C(channel, severity, format,...)
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
Definition adjoint.cpp:2254
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
cholesky decomposition
@ QUIET
@ VERBOSE
@ COL
@ ROW
@ MF_ZERO
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ NOBASE
Definition definitions.h:59
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define MOAB_THROW(err)
Check error code of MoAB function and throw MoFEM exception.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MYPCOMM_INDEX
default communicator number PCOMM
@ DISCONTINUOUS
Broken continuity (No effect on L2 space)
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
static const char *const ApproximationBaseNames[]
Definition definitions.h:72
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr int order
static const bool debug
PetscErrorCode ShapeMBTET(double *N, const double *G_X, const double *G_Y, const double *G_Z, int DIM)
calculate shape functions
Definition fem_tools.c:306
PetscErrorCode ShapeMBTRI(double *N, const double *X, const double *Y, const int G_DIM)
calculate shape functions on triangle
Definition fem_tools.c:182
@ F
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMTSSetIFunction(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set TS implicit function evaluation function
Definition DMMoFEM.cpp:790
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:114
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
PetscErrorCode DMMoFEMGetTsCtx(DM dm, MoFEM::TsCtx **ts_ctx)
get MoFEM::TsCtx data structure
Definition DMMoFEM.cpp:1132
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMMoFEMTSSetIJacobian(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS Jacobian evaluation function
Definition DMMoFEM.cpp:843
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
PetscErrorCode DMMoFEMTSSetI2Jacobian(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS Jacobian evaluation function
Definition DMMoFEM.cpp:1007
PetscErrorCode DMMoFEMTSSetI2Function(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS implicit function evaluation function
Definition DMMoFEM.cpp:965
PetscErrorCode DMoFEMLoopFiniteElementsUpAndLowRank(DM dm, const char fe_name[], MoFEM::FEMethod *method, int low_rank, int up_rank, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:557
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_adjacency_table(const std::string &fe_name, const EntityType type, ElementAdjacencyFunct function)=0
modify finite element table, only for advanced user
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
@ GAUSS
Gaussian quadrature integration.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
virtual MoFEMErrorCode loop_finite_elements(const std::string problem_name, const std::string &fe_name, FEMethod &method, boost::shared_ptr< NumeredEntFiniteElement_multiIndex > fe_ptr=nullptr, MoFEMTypes bh=MF_EXIST, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr(), int verb=DEFAULT_VERBOSITY)=0
Make a loop over finite elements.
MoFEMErrorCode getMeshset(const int ms_id, const unsigned int cubit_bc_type, EntityHandle &meshset) const
get meshset from CUBIT Id and CUBIT type
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
MoFEMErrorCode removeBlockDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true, bool is_distributed_mesh=true)
Remove DOFs from problem based on block entities.
Definition BcManager.cpp:72
MoFEMErrorCode pushMarkDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true)
Mark DOFs on block entities for boundary conditions.
#define NBVOLUMETET_L2(P)
Number of base functions on tetrahedron for L2 space.
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
MoFEM::TsCtx * ts_ctx
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static 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)
boost::shared_ptr< ContactSDFPython > setupContactSdf(MoFEM::Interface &m_field)
Read SDF file and setup contact SDF.
MoFEMErrorCode pushCohesiveOpsRhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
void pushOpCalculateStretchFromStress(OpVector &op_vector, boost::shared_ptr< PhysicalEquations > physics_ptr, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< ExternalStrainVec > external_strain_vec_ptr, const std::map< std::string, boost::shared_ptr< ScalingMethod > > &smv, boost::shared_ptr< MatrixDouble > strain_ptr=nullptr)
Push pointwise external-pressure evaluation before stress recovery.
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.
const Rule * getTriangleRule(const int order)
const Rule * getTetrahedronRule(const int order)
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode TsMonitorSet(TS ts, PetscInt step, PetscReal t, Vec u, void *ctx)
Set monitor for TS solver.
Definition TsCtx.cpp:263
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1279
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:434
MoFEMErrorCode MoFEMSNESMonitorEnergy(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
Definition SnesCtx.cpp:656
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
static const bool debug
auto id_from_handle(const EntityHandle h)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PostProcBrokenMeshInMoabBaseEndImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseEnd
Enable to run stack of post-processing elements. Use this to end stack.
PostProcBrokenMeshInMoabBaseBeginImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseBegin
Enable to run stack of post-processing elements. Use this to begin stack.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
Definition TaoCtx.cpp:178
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1265
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
auto createTao(MPI_Comm comm)
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
int r
Definition sdf.py:205
constexpr AssemblyType A
double h
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
constexpr double g
FTensor::Index< 'm', 3 > m
CGG User Polynomial Base.
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field, EshelbianCore *ep_core_ptr)
MoFEMErrorCode setElasticElementOps(const int tag)
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
static PetscBool physicalH1Update
static enum StretchSelector stretchSelector
boost::shared_ptr< Range > frontAdjEdges
static int interfaceRemoveLevel
MoFEMErrorCode addBoundaryFiniteElement(const EntityHandle meshset=0)
const std::string skeletonElement
static double inv_dd_f_linear(const double)
static double inv_f_linear(const double v)
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
boost::shared_ptr< Range > contactFaces
static double dd_f_log_e_quadratic(const double v)
static double inv_d_f_linear(const double)
static double dd_f_linear(const double)
BitRefLevel bitAdjEnt
bit ref level for parent
static boost::function< double(const double)> inv_dd_f
MoFEM::Interface & mField
const std::string spatialL2Disp
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static enum SolverType solverType
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
static PetscBool l2UserBaseScale
SmartPetscObj< DM > dM
Coupled problem all fields.
MoFEMErrorCode solveSchapeOptimisation(TS ts, Vec x, int start_step, double start_time)
Solve shape optimisation problem.
static enum StretchHandling stretchHandling
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
static const char * listSolvers[]
const std::string materialH1Positions
static int nbJIntegralContours
MoFEMErrorCode setBlockTagsOnSkin()
static PetscBool crackingOn
MoFEMErrorCode getTractionFreeBc(const EntityHandle meshset, boost::shared_ptr< TractionFreeBc > &bc_ptr, const std::string contact_set_name)
Remove all, but entities where kinematic constrains are applied.
static double griffithEnergy
Griffith energy.
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
MoFEMErrorCode postProcessRestartMesh(const int tag, const std::string file, std::vector< Tag > tags_to_transfer={})
const std::string elementVolumeName
static double dd_f_log_e(const double v)
static double d_f_linear(const double)
static enum RotSelector rotSelector
MoFEMErrorCode addDebugModel(TS ts)
Add debug to model.
static enum RotSelector gradApproximator
PetscBool loadFactorTSSolveExecuted
MoFEMErrorCode postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, Vec gradient=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
MoFEMErrorCode getBc(boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
static double inv_dd_f_log_e_quadratic(const double stretch)
static double physicalDt
CommInterface::EntitiesPetscVector vertexExchange
static std::vector< std::string > listTagsToProject
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
static std::string heterogeneousYoungModTagName
const std::string spatialH1Disp
static FieldApproximationBase brokenHdivBase
static double maxCrackExtension
static int physicalMaxSteps
MoFEMErrorCode solveElastic(TS ts, Vec x)
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)
std::string getStringArgumentFromJsonBlockset(const std::string &type_name, const int meshset_id, const std::string &param_name)
static int physicalStepNumber
MoFEMErrorCode gettingNorms()
[Getting norms]
boost::shared_ptr< Range > interfaceFaces
MoFEMErrorCode setVolumeElementOps(const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
static PetscBool physicalTimeFlg
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Getting interface of core database.
const std::string bubbleField
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
SmartPetscObj< DM > dmMaterial
Material problem.
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
static double crackingAddTime
double alphaViscousOmega0
MoFEMErrorCode setFaceElementOps(const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
MoFEMErrorCode projectGeometry(const EntityHandle meshset=0, double time=0)
static double currentPhysicalTime
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
boost::shared_ptr< SpringBcVec > bcSpatialSpringVecPtr
static double crackingAtol
Cracking absolute tolerance.
MoFEMErrorCode projectMaterialTags(const EntityHandle meshset=0)
boost::shared_ptr< Range > skeletonFaces
static double crackingRtol
Cracking relative tolerance.
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
static PetscBool meshTransferHybridInterp
BitRefLevel bitAdjParentMask
bit ref level for parent parent
MoFEMErrorCode solveDynamicRelaxation(TS ts, Vec x, int start_step, double start_time)
Solve problem using dynamic relaxation method.
const std::string contactDisp
static std::string internalStressTagName
CommInterface::EntitiesPetscVector edgeExchange
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
static boost::function< double(const double)> f
MoFEMErrorCode solveTestTopologicalDerivative(TS ts, Vec x, int start_step, double start_time)
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
static double finalPhysicalTime
const std::string skinElement
static PetscBool internalStressVoigt
MoFEMErrorCode addVolumeFiniteElement(const EntityHandle meshset=0, const bool add_bubble=true)
static double inv_dd_f_log_e(const double v)
MoFEMErrorCode getExternalStrain()
MoFEMErrorCode getSpatialTractionBc()
MoFEMErrorCode pushNoStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
static PetscBool setSingularity
virtual ~EshelbianCore()
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, const bool add_bubble=true)
static double d_f_log_e(const double v)
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
boost::shared_ptr< double > currentCrackAreaPtr
static PetscBool meshTransferSourceMeshFileSpecified
static double f_log_e_quadratic(const double v)
double avgGriffithsEnergy
static double inv_f_log_e_quadratic(const double stretch)
static bool hasNonHomogeneousMaterialBlock
MoFEMErrorCode addDMs(const BitRefLevel bit=BitRefLevel().set(0), const EntityHandle meshset=0)
MoFEMErrorCode solveCohesiveCrackGrowth(TS ts, Vec x, int start_step, double start_time)
Solve cohesive crack growth problem.
MoFEMErrorCode getSpatialDispBc()
[Getting norms]
BitRefLevel bitAdjParent
bit ref level for parent
MoFEMErrorCode setContactElementRhsOps(boost::shared_ptr< ForcesAndSourcesCore > &fe_contact_tree)
static PetscBool interfaceCrack
MoFEMErrorCode solveLoadFactor(TS ts, Vec x, int start_step, double start_time)
Solve load factor crack growth problem.
static double d_f_log_e_quadratic(const double v)
CommInterface::EntitiesPetscVector volumeExchange
const std::string naturalBcElement
static boost::function< double(const double)> dd_f
static double f_log_e(const double v)
static double inv_f_log_e(const double v)
MoFEMErrorCode createExchangeVectors(Sev sev)
MoFEMErrorCode pushStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > crackFaces
static boost::function< double(const double)> d_f
static bool isNoStretch()
boost::shared_ptr< Range > frontVertices
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_d_f
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
static int meshTransferInterpOrder
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
static double inv_d_f_log_e_quadratic(const double stretch)
CommInterface::EntitiesPetscVector faceExchange
SmartPetscObj< DM > dmElastic
Elastic problem.
static std::string meshTransferSourceMeshFileName
EshelbianCore(MoFEM::Interface &m_field)
boost::shared_ptr< Range > frontEdges
static boost::function< double(const double)> inv_f
const std::string stretchTensor
BitRefLevel bitAdjEntMask
bit ref level for parent parent
static double f_linear(const double v)
MoFEMErrorCode addFields(const EntityHandle meshset=0, const bool add_bubble=true)
MoFEMErrorCode withFieldOrders(Op &&op) const
MoFEMErrorCode pushStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
const std::string contactElement
MoFEMErrorCode pushPiolaStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
AnalyticalDisplacementBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
AnalyticalTractionBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
BcRot(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
ExternalStrain(std::string name, std::vector< double > attr, Range ents, std::string load_history_file="")
int operator()(int p_row, int p_col, int p_data) const
NormalDisplacementBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
PressureBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, int(*)(int))
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges)
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cachePhi
SetIntegrationAtFrontVolume(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cache_phi=nullptr)
SetIntegrationAtFrontVolume(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, FunRule fun_rule, boost::shared_ptr< CGGUserPolynomialBase::CachePhi > cache_phi=nullptr)
SpringBc(std::string name, std::vector< double > attr, Range faces)
static MoFEMErrorCode preStepFun(TS ts)
static MoFEMErrorCode postStepFun(TS ts)
static MoFEMErrorCode postStepInitialise(EshelbianCore *ep_ptr)
TractionBc(std::string name, std::vector< double > attr, Range faces, std::string load_history_file="")
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.
Template specialization for displacement boundary conditions.
Boundary condition manager for finite element problem setup.
static std::pair< std::string, std::string > extractStringFromBlockId(const std::string block_id, const std::string prb_name)
Extract block name and block name from block id.
Template specialization system for type-safe boundary condition handling.
Managing BitRefLevels.
Managing BitRefLevels.
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
static Range getPartEntities(moab::Interface &moab, int part)
static MoFEMErrorCode setVectorFromTag(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Vector From Tag object.
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Tag From Vector object.
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode add_broken_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const std::vector< std::pair< EntityType, std::function< MoFEMErrorCode(BaseFunction::DofsSideMap &)> > > list_dof_side_map, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual bool check_finite_element(const std::string &name) const =0
Check if finite element is in database.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
Structure for user loop methods on finite elements.
EntityHandle getFEEntityHandle() const
Get the entity handle of the current finite element.
Basic algebra on fields.
Definition FieldBlas.hpp:21
Field data structure for finite element approximation.
Definition of the force bc data structure.
Definition BCData.hpp:135
UserDataOperator(const FieldSpace space, const char type=OPSPACE, const bool symm=true)
Constructor for operators working on finite element spaces.
structure to get information from mofem into EntitiesFieldData
static boost::shared_ptr< ScalingMethod > get(boost::shared_ptr< ScalingMethod > ts, std::string file_prefix, std::string file_suffix, std::string block_name, Args &&...args)
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
Mesh refinement interface.
Interface for managing meshsets containing materials and boundary conditions.
CubitMeshSet_multiIndex & getMeshsetsMultindex()
Natural boundary conditions.
Definition Natural.hpp:57
Operator for broken loop side.
Get norm of input MatrixDouble for Tensor1.
Get norm of input MatrixDouble for Tensor2.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate divergence of tonsorial field using vectorial base.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Calculate trace of vector (Hdiv/Hcurl) space.
Calculate symmetric tensor field rates ant integratio pts.
Calculate symmetric tensor field values at integration pts.
Get field gradients time derivative at integration pts for scalar field rank 0, i....
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Specialization for MatrixDouble vector field values calculation.
Element used to execute operators on side of the element.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
@ CTX_SET_TIME
Time value is set.
static constexpr Switches CtxSetTime
Time value switch.
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.
Template struct for dimension-specific finite element types.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
intrusive_ptr for managing petsc objects
std::function< double(double)> ScalingFun
static MoFEMErrorCode getTriNormal(const double *coords, double *normal, double *d_normal=nullptr)
Get the Tri Normal objectGet triangle normal.
Definition Tools.cpp:353
static double tetVolume(const double *coords)
Calculate volume of tetrahedron.
Definition Tools.cpp:30
static std::tuple< std::array< double, 3 >, std::array< double, 2 >, double > getTricircumcenter3d(double *coords_ptr)
Calculate triangle circumcenter in 3d.
Definition Tools.cpp:878
FEMethodsSequence & getLoopsMonitor()
Get the loops to do Monitor object.
Definition TsCtx.hpp:102
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Apply rotation boundary condition.
BoundaryEle::UserDataOperator BdyEleOp
int atom_test
Atom test.
Definition plastic.cpp:122
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62
auto save_range