18#include <boost/math/constants/constants.hpp>
21#ifdef ENABLE_PYTHON_BINDING
22 #include <boost/python.hpp>
23 #include <boost/python/def.hpp>
24 #include <boost/python/numpy.hpp>
25namespace bp = boost::python;
26namespace np = boost::python::numpy;
28 #pragma message "With ENABLE_PYTHON_BINDING"
32 #pragma message "Without ENABLE_PYTHON_BINDING"
58 const EntityType type) {
62 auto dim = CN::Dimension(type);
64 std::vector<int> sendcounts(pcomm->size());
65 std::vector<int> displs(pcomm->size());
66 std::vector<int> sendbuf(r.size());
67 if (pcomm->rank() == 0) {
68 for (
auto p = 1; p != pcomm->size(); p++) {
70 ->getPartEntities(m_field.
get_moab(), p)
73 CHKERR m_field.
get_moab().get_adjacencies(part_ents, dim,
true, faces,
74 moab::Interface::UNION);
75 faces = intersect(faces, r);
76 sendcounts[p] = faces.size();
77 displs[p] = sendbuf.size();
78 for (
auto f : faces) {
80 sendbuf.push_back(
id);
86 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
88 std::vector<int> recvbuf(recv_data);
89 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
90 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
92 if (pcomm->rank() > 0) {
94 for (
auto &f : recvbuf) {
104 const std::string block_name,
int dim) {
110 std::regex((boost::format(
"%s(.*)") % block_name).str())
114 for (
auto bc : bcs) {
126 const std::string block_name,
int dim) {
127 std::map<std::string, Range> r;
132 std::regex((boost::format(
"%s(.*)") % block_name).str())
136 for (
auto bc : bcs) {
141 r[bc->getName()] = faces;
148 const unsigned int cubit_bc_type) {
151 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
155static auto save_range(moab::Interface &moab,
const std::string name,
156 const Range r, std::vector<Tag> tags = {}) {
159 CHKERR moab.add_entities(*out_meshset, r);
161 CHKERR moab.write_file(name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1,
162 tags.data(), tags.size());
164 MOFEM_LOG(
"SELF", Sev::warning) <<
"Empty range for " << name;
171 ParallelComm *pcomm =
174 PSTATUS_SHARED | PSTATUS_MULTISHARED,
175 PSTATUS_NOT, -1, &boundary_ents),
177 return boundary_ents;
182 ParallelComm *pcomm =
184 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
193 CHK_MOAB_THROW(skin.find_skin(0, body_ents,
false, skin_ents),
"find_skin");
199 ParallelComm *pcomm =
202 Range crack_skin_without_bdy;
203 if (pcomm->rank() == 0) {
205 CHKERR moab.get_adjacencies(crack_faces, 1,
true, crack_edges,
206 moab::Interface::UNION);
207 auto crack_skin =
get_skin(m_field, crack_faces);
211 "get_entities_by_dimension");
212 auto body_skin =
get_skin(m_field, body_ents);
213 Range body_skin_edges;
214 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1,
true, body_skin_edges,
215 moab::Interface::UNION),
217 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
219 for (
auto &
m : front_edges_map) {
220 auto add_front = subtract(
m.second, crack_edges);
221 auto i = intersect(
m.second, crack_edges);
223 crack_skin_without_bdy.merge(add_front);
227 CHKERR moab.get_adjacencies(i_skin, 1,
true, adj_i_skin,
228 moab::Interface::UNION);
229 adj_i_skin = subtract(intersect(adj_i_skin,
m.second), crack_edges);
230 crack_skin_without_bdy.merge(adj_i_skin);
234 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
240 ParallelComm *pcomm =
243 MOFEM_LOG(
"EP", Sev::noisy) <<
"get_two_sides_of_crack_surface";
245 if (!pcomm->rank()) {
247 auto impl = [&](
auto &saids) {
252 auto get_adj = [&](
auto e,
auto dim) {
255 e, dim,
true, adj, moab::Interface::UNION),
260 auto get_conn = [&](
auto e) {
267 constexpr bool debug =
false;
271 auto body_skin =
get_skin(m_field, body_ents);
272 auto body_skin_edges = get_adj(body_skin, 1);
275 subtract(
get_skin(m_field, crack_faces), body_skin_edges);
276 auto crack_skin_conn = get_conn(crack_skin);
277 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
278 auto crack_edges = get_adj(crack_faces, 1);
279 crack_edges = subtract(crack_edges, crack_skin);
280 auto all_tets = get_adj(crack_edges, 3);
281 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
282 auto crack_conn = get_conn(crack_edges);
283 all_tets.merge(get_adj(crack_conn, 3));
292 if (crack_faces.size()) {
293 auto grow = [&](
auto r) {
294 auto crack_faces_conn = get_conn(crack_faces);
297 while (size_r != r.size() && r.size() > 0) {
299 CHKERR moab.get_connectivity(r,
v,
true);
300 v = subtract(
v, crack_faces_conn);
303 moab::Interface::UNION);
304 r = intersect(r, all_tets);
313 Range all_tets_ord = all_tets;
314 while (all_tets.size()) {
315 Range faces = get_adj(unite(saids.first, saids.second), 2);
316 faces = subtract(crack_faces, faces);
319 auto fit = faces.begin();
320 for (; fit != faces.end(); ++fit) {
321 tets = intersect(get_adj(
Range(*fit, *fit), 3), all_tets);
322 if (tets.size() == 2) {
329 saids.first.insert(tets[0]);
330 saids.first = grow(saids.first);
331 all_tets = subtract(all_tets, saids.first);
332 if (tets.size() == 2) {
333 saids.second.insert(tets[1]);
334 saids.second = grow(saids.second);
335 all_tets = subtract(all_tets, saids.second);
343 saids.first = subtract(all_tets_ord, saids.second);
344 saids.second = subtract(all_tets_ord, saids.first);
350 std::pair<Range, Range> saids;
351 if (crack_faces.size())
356 MOFEM_LOG(
"EP", Sev::noisy) <<
"get_two_sides_of_crack_surface <- done";
358 return std::pair<Range, Range>();
366 boost::shared_ptr<Range> front_edges)
370 int order_col,
int order_data) {
373 constexpr bool debug =
false;
375 constexpr int numNodes = 4;
376 constexpr int numEdges = 6;
377 constexpr int refinementLevels = 6;
379 auto &m_field = fe_raw_ptr->
mField;
380 auto fe_ptr =
static_cast<Fe *
>(fe_raw_ptr);
383 auto set_base_quadrature = [&]() {
385 int rule = 2 * order_data + 1;
396 auto &gauss_pts = fe_ptr->gaussPts;
397 gauss_pts.resize(4, nb_gauss_pts,
false);
398 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[1], 4,
399 &gauss_pts(0, 0), 1);
400 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[2], 4,
401 &gauss_pts(1, 0), 1);
402 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[3], 4,
403 &gauss_pts(2, 0), 1);
405 &gauss_pts(3, 0), 1);
406 auto &data = fe_ptr->dataOnElement[
H1];
407 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4,
410 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
411 cblas_dcopy(4 * nb_gauss_pts,
QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
420 CHKERR set_base_quadrature();
424 auto get_singular_nodes = [&]() {
427 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
429 std::bitset<numNodes> singular_nodes;
430 for (
auto nn = 0; nn != numNodes; ++nn) {
432 singular_nodes.set(nn);
434 singular_nodes.reset(nn);
437 return singular_nodes;
440 auto get_singular_edges = [&]() {
441 std::bitset<numEdges> singular_edges;
442 for (
int ee = 0; ee != numEdges; ee++) {
444 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
446 singular_edges.set(ee);
448 singular_edges.reset(ee);
451 return singular_edges;
454 auto set_gauss_pts = [&](
auto &ref_gauss_pts) {
456 fe_ptr->gaussPts.swap(ref_gauss_pts);
457 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
458 auto &data = fe_ptr->dataOnElement[
H1];
459 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
461 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
463 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
468 auto singular_nodes = get_singular_nodes();
469 if (singular_nodes.count()) {
470 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
472 CHKERR set_gauss_pts(it_map_ref_coords->second);
476 auto refine_quadrature = [&]() {
479 const int max_level = refinementLevels;
483 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
485 for (
int nn = 0; nn != 4; nn++)
486 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
487 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
491 Range tets(tet, tet);
494 tets, 1,
true, edges, moab::Interface::UNION);
499 Range nodes_at_front;
500 for (
int nn = 0; nn != numNodes; nn++) {
501 if (singular_nodes[nn]) {
503 CHKERR moab_ref.side_element(tet, 0, nn, ent);
504 nodes_at_front.insert(ent);
508 auto singular_edges = get_singular_edges();
511 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
512 for (
int ee = 0; ee != numEdges; ee++) {
513 if (singular_edges[ee]) {
515 CHKERR moab_ref.side_element(tet, 1, ee, ent);
516 CHKERR moab_ref.add_entities(meshset, &ent, 1);
522 for (
int ll = 0; ll != max_level; ll++) {
525 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
529 CHKERR moab_ref.get_adjacencies(
530 nodes_at_front, 1,
true, ref_edges, moab::Interface::UNION);
531 ref_edges = intersect(ref_edges, edges);
533 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
534 ref_edges = intersect(ref_edges, ents);
537 ->getEntitiesByTypeAndRefLevel(
539 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
543 ->updateMeshsetByEntitiesChildren(meshset,
545 meshset, MBEDGE,
true);
551 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
561 for (Range::iterator tit = tets.begin(); tit != tets.end();
565 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
566 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
569 auto &data = fe_ptr->dataOnElement[
H1];
570 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
571 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
573 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
575 for (
size_t tt = 0; tt != ref_coords.size1(); tt++) {
576 double *tet_coords = &ref_coords(tt, 0);
579 for (
size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
580 for (
int dd = 0; dd != 3; dd++) {
581 ref_gauss_pts(dd, gg) =
582 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
583 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
584 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
585 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
587 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
591 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
597 CHKERR refine_quadrature();
607 using ForcesAndSourcesCore::dataOnElement;
610 using ForcesAndSourcesCore::ForcesAndSourcesCore;
625 boost::shared_ptr<Range> front_edges)
629 boost::shared_ptr<Range> front_edges,
634 int order_col,
int order_data) {
637 constexpr bool debug =
false;
639 constexpr int numNodes = 3;
640 constexpr int numEdges = 3;
641 constexpr int refinementLevels = 6;
643 auto &m_field = fe_raw_ptr->
mField;
644 auto fe_ptr =
static_cast<Fe *
>(fe_raw_ptr);
647 auto set_base_quadrature = [&]() {
649 int rule =
funRule(order_data);
659 fe_ptr->gaussPts.resize(3, nb_gauss_pts,
false);
660 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[1], 3,
661 &fe_ptr->gaussPts(0, 0), 1);
662 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[2], 3,
663 &fe_ptr->gaussPts(1, 0), 1);
665 &fe_ptr->gaussPts(2, 0), 1);
666 auto &data = fe_ptr->dataOnElement[
H1];
667 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 3,
670 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
671 cblas_dcopy(3 * nb_gauss_pts,
QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
673 data->dataOnEntities[MBVERTEX][0].getDiffN(
NOBASE).resize(3, 2,
false);
676 data->dataOnEntities[MBVERTEX][0].getDiffN(
NOBASE).data().begin());
685 CHKERR set_base_quadrature();
689 auto get_singular_nodes = [&]() {
692 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
694 std::bitset<numNodes> singular_nodes;
695 for (
auto nn = 0; nn != numNodes; ++nn) {
697 singular_nodes.set(nn);
699 singular_nodes.reset(nn);
702 return singular_nodes;
705 auto get_singular_edges = [&]() {
706 std::bitset<numEdges> singular_edges;
707 for (
int ee = 0; ee != numEdges; ee++) {
709 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
711 singular_edges.set(ee);
713 singular_edges.reset(ee);
716 return singular_edges;
719 auto set_gauss_pts = [&](
auto &ref_gauss_pts) {
721 fe_ptr->gaussPts.swap(ref_gauss_pts);
722 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
723 auto &data = fe_ptr->dataOnElement[
H1];
724 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
726 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
728 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
732 auto singular_nodes = get_singular_nodes();
733 if (singular_nodes.count()) {
734 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
736 CHKERR set_gauss_pts(it_map_ref_coords->second);
740 auto refine_quadrature = [&]() {
743 const int max_level = refinementLevels;
746 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
748 for (
int nn = 0; nn != numNodes; nn++)
749 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
751 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
755 Range tris(tri, tri);
758 tris, 1,
true, edges, moab::Interface::UNION);
763 Range nodes_at_front;
764 for (
int nn = 0; nn != numNodes; nn++) {
765 if (singular_nodes[nn]) {
767 CHKERR moab_ref.side_element(tri, 0, nn, ent);
768 nodes_at_front.insert(ent);
772 auto singular_edges = get_singular_edges();
775 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
776 for (
int ee = 0; ee != numEdges; ee++) {
777 if (singular_edges[ee]) {
779 CHKERR moab_ref.side_element(tri, 1, ee, ent);
780 CHKERR moab_ref.add_entities(meshset, &ent, 1);
786 for (
int ll = 0; ll != max_level; ll++) {
789 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
793 CHKERR moab_ref.get_adjacencies(
794 nodes_at_front, 1,
true, ref_edges, moab::Interface::UNION);
795 ref_edges = intersect(ref_edges, edges);
797 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
798 ref_edges = intersect(ref_edges, ents);
801 ->getEntitiesByTypeAndRefLevel(
803 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
807 ->updateMeshsetByEntitiesChildren(meshset,
809 meshset, MBEDGE,
true);
815 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
826 for (Range::iterator tit = tris.begin(); tit != tris.end();
830 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
831 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
834 auto &data = fe_ptr->dataOnElement[
H1];
835 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
836 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
838 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
840 for (
size_t tt = 0; tt != ref_coords.size1(); tt++) {
841 double *tri_coords = &ref_coords(tt, 0);
844 auto det = t_normal.
l2();
845 for (
size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
846 for (
int dd = 0; dd != 2; dd++) {
847 ref_gauss_pts(dd, gg) =
848 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
849 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
850 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
852 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
856 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
862 CHKERR refine_quadrature();
872 using ForcesAndSourcesCore::dataOnElement;
875 using ForcesAndSourcesCore::ForcesAndSourcesCore;
924 const char *list_rots[] = {
"small",
"moderate",
"large",
"no_h1"};
925 const char *list_symm[] = {
"symm",
"not_symm"};
926 const char *list_release[] = {
"griffith_force",
"griffith_skeleton"};
927 const char *list_stretches[] = {
"linear",
"log",
"log_quadratic"};
932 PetscInt choice_stretch = StretchSelector::LOG;
933 char analytical_expr_file_name[255] =
"analytical_expr.py";
935 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Eshelbian plasticity",
937 CHKERR PetscOptionsInt(
"-space_order",
"approximation oder for space",
"",
939 CHKERR PetscOptionsInt(
"-space_h1_order",
"approximation oder for space",
"",
941 CHKERR PetscOptionsInt(
"-material_order",
"approximation oder for material",
943 CHKERR PetscOptionsScalar(
"-viscosity_alpha_u",
"viscosity",
"",
alphaU,
945 CHKERR PetscOptionsScalar(
"-viscosity_alpha_w",
"viscosity",
"",
alphaW,
947 CHKERR PetscOptionsScalar(
"-viscosity_alpha_omega",
"rot viscosity",
"",
949 CHKERR PetscOptionsScalar(
"-density_alpha_rho",
"density",
"",
alphaRho,
951 CHKERR PetscOptionsEList(
"-rotations",
"rotations",
"", list_rots,
952 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
954 CHKERR PetscOptionsEList(
"-grad",
"gradient of defamation approximate",
"",
955 list_rots, NO_H1_CONFIGURATION + 1,
956 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
957 CHKERR PetscOptionsEList(
"-symm",
"symmetric variant",
"", list_symm, 2,
958 list_symm[choice_symm], &choice_symm, PETSC_NULLPTR);
962 CHKERR PetscOptionsEList(
"-stretches",
"stretches",
"", list_stretches,
963 StretchSelector::STRETCH_SELECTOR_LAST,
964 list_stretches[choice_stretch], &choice_stretch,
967 CHKERR PetscOptionsBool(
"-no_stretch",
"do not solve for stretch",
"",
969 CHKERR PetscOptionsBool(
"-set_singularity",
"set singularity",
"",
971 CHKERR PetscOptionsBool(
"-l2_user_base_scale",
"streach scale",
"",
975 CHKERR PetscOptionsBool(
"-dynamic_relaxation",
"dynamic time relaxation",
"",
979 CHKERR PetscOptionsInt(
"-contact_max_post_proc_ref_level",
"refinement level",
986 CHKERR PetscOptionsScalar(
"-cracking_start_time",
"cracking start time",
"",
988 CHKERR PetscOptionsScalar(
"-griffith_energy",
"Griffith energy",
"",
990 CHKERR PetscOptionsEList(
"-energy_release_variant",
"energy release variant",
991 "", list_release, 2, list_release[choice_release],
992 &choice_release, PETSC_NULLPTR);
993 CHKERR PetscOptionsInt(
"-nb_J_integral_levels",
"Number of J integarl levels",
997 "-nb_J_integral_contours",
"Number of J integral contours",
"",
1001 char tag_name[255] =
"";
1002 CHKERR PetscOptionsString(
"-internal_stress_tag_name",
1003 "internal stress tag name",
"",
"", tag_name, 255,
1007 "-internal_stress_interp_order",
"internal stress interpolation order",
1009 CHKERR PetscOptionsBool(
"-internal_stress_voigt",
"Voigt index notation",
"",
1014 analytical_expr_file_name, 255, PETSC_NULLPTR);
1020 "Unsupported internal stress interpolation order %d",
1033 static_cast<EnergyReleaseSelector
>(choice_release);
1036 case StretchSelector::LINEAR:
1044 case StretchSelector::LOG:
1046 std::numeric_limits<float>::epsilon()) {
1062 case StretchSelector::LOG_QUADRATIC:
1068 "No logarithmic quadratic stretch for this case");
1084 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaU: -viscosity_alpha_u " <<
alphaU;
1085 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaW: -viscosity_alpha_w " <<
alphaW;
1087 <<
"alphaOmega: -viscosity_alpha_omega " <<
alphaOmega;
1091 MOFEM_LOG(
"EP", Sev::inform) <<
"Gradient of deformation "
1099 MOFEM_LOG(
"EP", Sev::inform) <<
"Base exponent e";
1101 <<
"Stretch: -stretches " << list_stretches[choice_stretch];
1127 <<
"Energy release variant: -energy_release_variant "
1130 <<
"Number of J integral contours: -nb_J_integral_contours "
1133#ifdef ENABLE_PYTHON_BINDING
1134 auto file_exists = [](std::string myfile) {
1135 std::ifstream file(myfile.c_str());
1142 if (file_exists(analytical_expr_file_name)) {
1143 MOFEM_LOG(
"EP", Sev::inform) << analytical_expr_file_name <<
" file found";
1147 analytical_expr_file_name);
1151 << analytical_expr_file_name <<
" file NOT found";
1164 auto get_tets = [&]() {
1170 auto get_tets_skin = [&]() {
1171 Range tets_skin_part;
1173 CHKERR skin.find_skin(0, get_tets(),
false, tets_skin_part);
1174 ParallelComm *pcomm =
1177 CHKERR pcomm->filter_pstatus(tets_skin_part,
1178 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1179 PSTATUS_NOT, -1, &tets_skin);
1183 auto subtract_boundary_conditions = [&](
auto &&tets_skin) {
1189 tets_skin = subtract(tets_skin,
v.faces);
1193 tets_skin = subtract(tets_skin,
v.faces);
1198 tets_skin = subtract(tets_skin,
v.faces);
1204 auto add_blockset = [&](
auto block_name,
auto &&tets_skin) {
1207 tets_skin.merge(crack_faces);
1211 auto subtract_blockset = [&](
auto block_name,
auto &&tets_skin) {
1212 auto contact_range =
1214 tets_skin = subtract(tets_skin, contact_range);
1218 auto get_stress_trace_faces = [&](
auto &&tets_skin) {
1221 faces, moab::Interface::UNION);
1222 Range trace_faces = subtract(faces, tets_skin);
1226 auto tets = get_tets();
1230 auto trace_faces = get_stress_trace_faces(
1232 subtract_blockset(
"CONTACT",
1233 subtract_boundary_conditions(get_tets_skin()))
1240 boost::make_shared<Range>(subtract(trace_faces, *
contactFaces));
1260 auto add_broken_hdiv_field = [
this, meshset](
const std::string
field_name,
1266 auto get_side_map_hdiv = [&]() {
1269 std::pair<EntityType,
1284 get_side_map_hdiv(), MB_TAG_DENSE,
MF_ZERO);
1290 auto add_l2_field = [
this, meshset](
const std::string
field_name,
1291 const int order,
const int dim) {
1300 auto add_h1_field = [
this, meshset](
const std::string
field_name,
1301 const int order,
const int dim) {
1313 auto add_l2_field_by_range = [
this](
const std::string
field_name,
1314 const int order,
const int dim,
1315 const int field_dim,
Range &&r) {
1325 auto add_bubble_field = [
this, meshset](
const std::string
field_name,
1326 const int order,
const int dim) {
1332 auto field_order_table =
1333 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1334 auto get_cgg_bubble_order_zero = [](
int p) {
return 0; };
1335 auto get_cgg_bubble_order_tet = [](
int p) {
1338 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1339 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1340 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1341 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1348 auto add_user_l2_field = [
this, meshset](
const std::string
field_name,
1349 const int order,
const int dim) {
1355 auto field_order_table =
1356 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1357 auto zero_dofs = [](
int p) {
return 0; };
1359 field_order_table[MBVERTEX] = zero_dofs;
1360 field_order_table[MBEDGE] = zero_dofs;
1361 field_order_table[MBTRI] = zero_dofs;
1362 field_order_table[MBTET] = dof_l2_tet;
1380 auto get_hybridised_disp = [&]() {
1382 auto skin = subtract_boundary_conditions(get_tets_skin());
1384 faces.merge(intersect(bc.faces, skin));
1390 get_hybridised_disp());
1416 auto project_ho_geometry = [&](
auto field) {
1422 auto get_adj_front_edges = [&](
auto &front_edges) {
1423 Range front_crack_nodes;
1424 Range crack_front_edges_with_both_nodes_not_at_front;
1429 moab.get_connectivity(front_edges, front_crack_nodes,
true),
1430 "get_connectivity failed");
1431 Range crack_front_edges;
1433 false, crack_front_edges,
1434 moab::Interface::UNION),
1435 "get_adjacencies failed");
1436 Range crack_front_edges_nodes;
1438 crack_front_edges_nodes,
true),
1439 "get_connectivity failed");
1441 crack_front_edges_nodes =
1442 subtract(crack_front_edges_nodes, front_crack_nodes);
1443 Range crack_front_edges_with_both_nodes_not_at_front;
1445 moab.get_adjacencies(crack_front_edges_nodes, 1,
false,
1446 crack_front_edges_with_both_nodes_not_at_front,
1447 moab::Interface::UNION),
1448 "get_adjacencies failed");
1450 crack_front_edges_with_both_nodes_not_at_front =
1451 intersect(crack_front_edges,
1452 crack_front_edges_with_both_nodes_not_at_front);
1456 crack_front_edges_with_both_nodes_not_at_front =
send_type(
1457 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1459 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1460 boost::make_shared<Range>(
1461 crack_front_edges_with_both_nodes_not_at_front));
1468 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*
frontEdges);
1473 <<
"Number of crack faces: " <<
crackFaces->size();
1475 <<
"Number of front edges: " <<
frontEdges->size();
1479 <<
"Number of front adjacent edges: " <<
frontAdjEdges->size();
1488 (boost::format(
"crack_faces_%d.vtk") % rank).str(),
1491 (boost::format(
"front_edges_%d.vtk") % rank).str(),
1502 auto set_singular_dofs = [&](
auto &front_adj_edges,
auto &front_vertices) {
1510 MOFEM_LOG(
"EP", Sev::inform) <<
"Singularity eps " << beta;
1515 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) ->
MoFEMErrorCode {
1520 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1526 if (field_entity_ptr->getNbOfCoeffs() != 3)
1528 "Expected 3 coefficients per edge");
1529 if (nb_dofs % 3 != 0)
1531 "Expected multiple of 3 coefficients per edge");
1534 auto get_conn = [&]() {
1537 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1539 return std::make_pair(conn, num_nodes);
1542 auto get_dir = [&](
auto &&conn_p) {
1543 auto [conn, num_nodes] = conn_p;
1545 CHKERR moab.get_coords(conn, num_nodes, coords);
1547 coords[4] - coords[1],
1548 coords[5] - coords[2]};
1552 auto get_singularity_dof = [&](
auto &&conn_p,
auto &&t_edge_dir) {
1553 auto [conn, num_nodes] = conn_p;
1555 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1556 t_singularity_dof(
i) = t_edge_dir(
i) * (-
eps);
1557 }
else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1558 t_singularity_dof(
i) = t_edge_dir(
i) *
eps;
1560 return t_singularity_dof;
1563 auto t_singularity_dof =
1564 get_singularity_dof(get_conn(), get_dir(get_conn()));
1566 auto field_data = field_entity_ptr->getEntFieldData();
1568 &field_data[0], &field_data[1], &field_data[2]};
1570 t_dof(
i) = t_singularity_dof(
i);
1572 for (
auto n = 1;
n < field_data.size() / 3; ++
n) {
1597 auto add_field_to_fe = [
this](
const std::string fe,
1662 auto set_fe_adjacency = [&](
auto fe_name) {
1665 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
1673 auto add_field_to_fe = [
this](
const std::string fe,
1685 Range natural_bc_elements;
1688 natural_bc_elements.merge(
v.faces);
1693 natural_bc_elements.merge(
v.faces);
1698 natural_bc_elements.merge(
v.faces);
1703 natural_bc_elements.merge(
v.faces);
1708 natural_bc_elements.merge(
v.faces);
1713 natural_bc_elements.merge(
v.faces);
1718 natural_bc_elements.merge(
v.faces);
1721 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
1732 auto get_skin = [&](
auto &body_ents) {
1735 CHKERR skin.find_skin(0, body_ents,
false, skin_ents);
1740 Range boundary_ents;
1741 ParallelComm *pcomm =
1743 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1744 PSTATUS_NOT, -1, &boundary_ents);
1745 return boundary_ents;
1879 auto remove_dofs_on_broken_skin = [&](
const std::string prb_name) {
1881 for (
int d : {0, 1, 2}) {
1882 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
1884 ->getSideDofsOnBrokenSpaceEntities(
1895 CHKERR remove_dofs_on_broken_skin(
"ESHELBY_PLASTICITY");
1931 auto set_zero_block = [&]() {
1963 auto set_section = [&]() {
1965 PetscSection section;
1970 CHKERR PetscSectionDestroy(§ion);
1993BcDisp::BcDisp(std::string name, std::vector<double> attr,
Range faces)
1994 : blockName(name), faces(faces) {
1995 vals.resize(3,
false);
1996 flags.resize(3,
false);
1997 for (
int ii = 0; ii != 3; ++ii) {
1998 vals[ii] = attr[ii];
1999 flags[ii] =
static_cast<int>(attr[ii + 3]);
2002 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp " << name;
2004 <<
"Add BCDisp vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
2006 <<
"Add BCDisp flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
2007 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp nb. of faces " <<
faces.size();
2011 : blockName(name), faces(faces) {
2012 vals.resize(attr.size(),
false);
2013 for (
int ii = 0; ii != attr.size(); ++ii) {
2014 vals[ii] = attr[ii];
2020 : blockName(name), faces(faces) {
2021 vals.resize(3,
false);
2022 flags.resize(3,
false);
2023 for (
int ii = 0; ii != 3; ++ii) {
2024 vals[ii] = attr[ii];
2025 flags[ii] =
static_cast<int>(attr[ii + 3]);
2028 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce " << name;
2030 <<
"Add BCForce vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
2032 <<
"Add BCForce flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
2033 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce nb. of faces " <<
faces.size();
2037 std::vector<double> attr,
2039 : blockName(name), faces(faces) {
2042 if (attr.size() < 1) {
2044 "Wrong size of normal displacement BC");
2049 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc " << name;
2050 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc val " <<
val;
2052 <<
"Add NormalDisplacementBc nb. of faces " <<
faces.size();
2056 : blockName(name), faces(faces) {
2059 if (attr.size() < 1) {
2061 "Wrong size of normal displacement BC");
2066 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc " << name;
2067 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc val " <<
val;
2069 <<
"Add PressureBc nb. of faces " <<
faces.size();
2075 : blockName(name), ents(ents) {
2078 if (attr.size() < 2) {
2080 "Wrong size of external strain attribute");
2086 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain " << name;
2087 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain val " <<
val;
2088 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain bulk modulus K "
2091 <<
"Add ExternalStrain nb. of tets " <<
ents.size();
2097 std::vector<double> attr,
2099 : blockName(name), faces(faces) {
2102 if (attr.size() < 3) {
2104 "Wrong size of analytical displacement BC");
2107 flags.resize(3,
false);
2108 for (
int ii = 0; ii != 3; ++ii) {
2109 flags[ii] = attr[ii];
2112 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalDisplacementBc " << name;
2114 <<
"Add AnalyticalDisplacementBc flags " <<
flags[0] <<
" " <<
flags[1]
2117 <<
"Add AnalyticalDisplacementBc nb. of faces " <<
faces.size();
2121 std::vector<double> attr,
2123 : blockName(name), faces(faces) {
2126 if (attr.size() < 3) {
2128 "Wrong size of analytical traction BC");
2131 flags.resize(3,
false);
2132 for (
int ii = 0; ii != 3; ++ii) {
2133 flags[ii] = attr[ii];
2136 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalTractionBc " << name;
2138 <<
"Add AnalyticalTractionBc flags " <<
flags[0] <<
" " <<
flags[1]
2141 <<
"Add AnalyticalTractionBc nb. of faces " <<
faces.size();
2147 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2148 const std::string contact_set_name) {
2153 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2154 Range tets_skin_part;
2155 Skinner skin(&mField.get_moab());
2156 CHKERR skin.find_skin(0, tets,
false, tets_skin_part);
2157 ParallelComm *pcomm =
2160 CHKERR pcomm->filter_pstatus(tets_skin_part,
2161 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2162 PSTATUS_NOT, -1, &tets_skin);
2165 for (
int dd = 0; dd != 3; ++dd)
2166 (*bc_ptr)[dd] = tets_skin;
2169 if (bcSpatialDispVecPtr)
2170 for (
auto &
v : *bcSpatialDispVecPtr) {
2172 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2174 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2176 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2180 if (bcSpatialRotationVecPtr)
2181 for (
auto &
v : *bcSpatialRotationVecPtr) {
2182 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2183 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2184 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2187 if (bcSpatialNormalDisplacementVecPtr)
2188 for (
auto &
v : *bcSpatialNormalDisplacementVecPtr) {
2189 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2190 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2191 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2194 if (bcSpatialAnalyticalDisplacementVecPtr)
2195 for (
auto &
v : *bcSpatialAnalyticalDisplacementVecPtr) {
2197 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2199 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2201 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2204 if (bcSpatialTractionVecPtr)
2205 for (
auto &
v : *bcSpatialTractionVecPtr) {
2206 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2207 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2208 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2211 if (bcSpatialAnalyticalTractionVecPtr)
2212 for (
auto &
v : *bcSpatialAnalyticalTractionVecPtr) {
2213 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2214 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2215 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2218 if (bcSpatialPressureVecPtr)
2219 for (
auto &
v : *bcSpatialPressureVecPtr) {
2220 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2221 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2222 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2227 std::regex((boost::format(
"%s(.*)") % contact_set_name).str()))) {
2229 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2231 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2232 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2233 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2250 return 2 * p_data + 1;
2256 return 2 * (p_data + 1);
2263 const int tag,
const bool do_rhs,
const bool do_lhs,
const bool calc_rates,
2265 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe) {
2269 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0,
MatrixDouble());
2270 fe->getUserPolynomialBase() =
2271 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2272 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2273 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2276 fe->getRuleHook = [](int, int, int) {
return -1; };
2277 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges);
2283 dataAtPts->physicsPtr = physicalEquations;
2288 piolaStress, dataAtPts->getApproxPAtPts()));
2290 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2292 piolaStress, dataAtPts->getDivPAtPts()));
2295 fe->getOpPtrVector().push_back(
2296 physicalEquations->returnOpCalculateStretchFromStress(
2297 dataAtPts, physicalEquations));
2299 fe->getOpPtrVector().push_back(
2301 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2305 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
2307 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
2309 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
2313 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
2315 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
2320 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
2323 fe->getOpPtrVector().push_back(
2325 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
2326 fe->getOpPtrVector().push_back(
2328 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
2332 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
2334 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
2337 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
2339 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
2346 piolaStress, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2349 bubbleField, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2350 var_vec, MBMAXTYPE));
2352 rotAxis, dataAtPts->getVarRotAxisPts(), var_vec, MBTET));
2354 piolaStress, dataAtPts->getDivVarPiolaPts(), var_vec));
2356 spatialL2Disp, dataAtPts->getVarWL2Pts(), var_vec, MBTET));
2359 fe->getOpPtrVector().push_back(
2360 physicalEquations->returnOpCalculateVarStretchFromStress(
2361 dataAtPts, physicalEquations));
2363 fe->getOpPtrVector().push_back(
2365 stretchTensor, dataAtPts->getVarLogStreachPts(), var_vec, MBTET));
2371 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
2376 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
2377 tag, do_rhs, do_lhs, dataAtPts, physicalEquations));
2384 const int tag,
const bool add_elastic,
const bool add_material,
2385 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
2386 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
2390 auto get_body_range = [
this](
auto name,
int dim) {
2391 std::map<int, Range> map;
2394 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2396 (boost::format(
"%s(.*)") % name).str()
2402 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
2405 map[m_ptr->getMeshsetId()] = ents;
2411 auto rule_contact = [](int, int,
int o) {
return -1; };
2414 auto set_rule_contact = [refine](
2417 int order_col,
int order_data
2421 auto rule = 2 * order_data;
2427 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2434 fe_rhs->getOpPtrVector().push_back(
2436 fe_rhs->getOpPtrVector().push_back(
2441 if (!internalStressTagName.empty()) {
2442 switch (internalStressInterpOrder) {
2444 fe_rhs->getOpPtrVector().push_back(
2448 fe_rhs->getOpPtrVector().push_back(
2453 "Unsupported internal stress interpolation order %d",
2454 internalStressInterpOrder);
2456 if (internalStressVoigt) {
2457 fe_rhs->getOpPtrVector().push_back(
2461 fe_rhs->getOpPtrVector().push_back(
2466 if (
auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
2467 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
2468 fe_rhs->getOpPtrVector().push_back(op);
2469 }
else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
2471 "OpSpatialPhysicalExternalStrain not implemented for this "
2475 fe_rhs->getOpPtrVector().push_back(
2476 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
2479 fe_rhs->getOpPtrVector().push_back(
2481 fe_rhs->getOpPtrVector().push_back(
2483 fe_rhs->getOpPtrVector().push_back(
2486 auto set_hybridisation = [&](
auto &pip) {
2493 using SideEleOp = EleOnSide::UserDataOperator;
2494 using BdyEleOp = BoundaryEle::UserDataOperator;
2499 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2501 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2504 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2505 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2507 CHKERR EshelbianPlasticity::
2508 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2509 op_loop_skeleton_side->getOpPtrVector(), {L2},
2510 materialH1Positions, frontAdjEdges);
2514 auto broken_data_ptr =
2515 boost::make_shared<std::vector<BrokenBaseSideData>>();
2518 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2519 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2520 boost::make_shared<CGGUserPolynomialBase>();
2522 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2523 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2524 materialH1Positions, frontAdjEdges);
2525 op_loop_domain_side->getOpPtrVector().push_back(
2527 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
2528 op_loop_domain_side->getOpPtrVector().push_back(
2531 op_loop_domain_side->getOpPtrVector().push_back(
2535 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2537 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
2539 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2540 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dHybrid(
2541 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
2542 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2543 op_loop_skeleton_side->getOpPtrVector().push_back(
2546 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dBroken(
2547 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
2550 pip.push_back(op_loop_skeleton_side);
2555 auto set_contact = [&](
auto &pip) {
2562 using SideEleOp = EleOnSide::UserDataOperator;
2563 using BdyEleOp = BoundaryEle::UserDataOperator;
2568 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2570 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2571 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2572 CHKERR EshelbianPlasticity::
2573 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2574 op_loop_skeleton_side->getOpPtrVector(), {L2},
2575 materialH1Positions, frontAdjEdges);
2579 auto broken_data_ptr =
2580 boost::make_shared<std::vector<BrokenBaseSideData>>();
2583 auto contact_common_data_ptr =
2584 boost::make_shared<ContactOps::CommonData>();
2586 auto add_ops_domain_side = [&](
auto &pip) {
2590 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2591 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2592 boost::make_shared<CGGUserPolynomialBase>();
2594 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2595 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2596 materialH1Positions, frontAdjEdges);
2597 op_loop_domain_side->getOpPtrVector().push_back(
2600 op_loop_domain_side->getOpPtrVector().push_back(
2602 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2603 pip.push_back(op_loop_domain_side);
2607 auto add_ops_contact_rhs = [&](
auto &pip) {
2610 auto contact_sfd_map_range_ptr =
2611 boost::make_shared<std::map<int, Range>>(
2612 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2615 contactDisp, contact_common_data_ptr->contactDispPtr()));
2616 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2619 pip.push_back(
new OpTreeSearch(
2620 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2624 contactDisp, contact_common_data_ptr, contactTreeRhs,
2625 contact_sfd_map_range_ptr));
2628 broken_data_ptr, contact_common_data_ptr, contactTreeRhs));
2634 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2635 CHKERR add_ops_contact_rhs(op_loop_skeleton_side->getOpPtrVector());
2638 pip.push_back(op_loop_skeleton_side);
2643 CHKERR set_hybridisation(fe_rhs->getOpPtrVector());
2644 CHKERR set_contact(fe_rhs->getOpPtrVector());
2647 using BodyNaturalBC =
2649 Assembly<PETSC>::LinearForm<
GAUSS>;
2651 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
2653 auto body_time_scale =
2654 boost::make_shared<DynamicRelaxationTimeScale>(
"body_force.txt");
2655 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
2656 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
2657 "BODY_FORCE", Sev::inform);
2661 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2669 fe_lhs->getOpPtrVector().push_back(
2672 bubbleField, piolaStress, dataAtPts));
2673 fe_lhs->getOpPtrVector().push_back(
2677 fe_lhs->getOpPtrVector().push_back(
2678 physicalEquations->returnOpSpatialPhysical_du_du(
2679 stretchTensor, stretchTensor, dataAtPts, alphaU));
2681 stretchTensor, piolaStress, dataAtPts,
true));
2683 stretchTensor, bubbleField, dataAtPts,
true));
2685 stretchTensor, rotAxis, dataAtPts,
2686 symmetrySelector ==
SYMMETRIC ?
true :
false));
2690 spatialL2Disp, piolaStress, dataAtPts,
true));
2692 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
2695 piolaStress, rotAxis, dataAtPts,
2696 symmetrySelector ==
SYMMETRIC ?
true :
false));
2698 bubbleField, rotAxis, dataAtPts,
2699 symmetrySelector ==
SYMMETRIC ?
true :
false));
2704 rotAxis, stretchTensor, dataAtPts,
false));
2707 rotAxis, piolaStress, dataAtPts,
false));
2709 rotAxis, bubbleField, dataAtPts,
false));
2712 rotAxis, rotAxis, dataAtPts, alphaOmega));
2714 auto set_hybridisation = [&](
auto &pip) {
2721 using SideEleOp = EleOnSide::UserDataOperator;
2722 using BdyEleOp = BoundaryEle::UserDataOperator;
2727 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2729 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2732 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2733 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2734 CHKERR EshelbianPlasticity::
2735 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2736 op_loop_skeleton_side->getOpPtrVector(), {L2},
2737 materialH1Positions, frontAdjEdges);
2741 auto broken_data_ptr =
2742 boost::make_shared<std::vector<BrokenBaseSideData>>();
2745 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2746 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2747 boost::make_shared<CGGUserPolynomialBase>();
2749 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2750 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2751 materialH1Positions, frontAdjEdges);
2752 op_loop_domain_side->getOpPtrVector().push_back(
2755 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2757 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
2758 op_loop_skeleton_side->getOpPtrVector().push_back(
2759 new OpC(hybridSpatialDisp, broken_data_ptr,
2760 boost::make_shared<double>(1.0),
true,
false));
2762 pip.push_back(op_loop_skeleton_side);
2767 auto set_contact = [&](
auto &pip) {
2774 using SideEleOp = EleOnSide::UserDataOperator;
2775 using BdyEleOp = BoundaryEle::UserDataOperator;
2780 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2782 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2783 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2784 CHKERR EshelbianPlasticity::
2785 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2786 op_loop_skeleton_side->getOpPtrVector(), {L2},
2787 materialH1Positions, frontAdjEdges);
2791 auto broken_data_ptr =
2792 boost::make_shared<std::vector<BrokenBaseSideData>>();
2795 auto contact_common_data_ptr =
2796 boost::make_shared<ContactOps::CommonData>();
2798 auto add_ops_domain_side = [&](
auto &pip) {
2802 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2803 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2804 boost::make_shared<CGGUserPolynomialBase>();
2806 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2807 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2808 materialH1Positions, frontAdjEdges);
2809 op_loop_domain_side->getOpPtrVector().push_back(
2812 op_loop_domain_side->getOpPtrVector().push_back(
2814 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2815 pip.push_back(op_loop_domain_side);
2819 auto add_ops_contact_lhs = [&](
auto &pip) {
2822 contactDisp, contact_common_data_ptr->contactDispPtr()));
2823 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2826 pip.push_back(
new OpTreeSearch(
2827 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2832 auto contact_sfd_map_range_ptr =
2833 boost::make_shared<std::map<int, Range>>(
2834 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2837 contactDisp, contactDisp, contact_common_data_ptr, contactTreeRhs,
2838 contact_sfd_map_range_ptr));
2841 contactDisp, broken_data_ptr, contact_common_data_ptr,
2842 contactTreeRhs, contact_sfd_map_range_ptr));
2845 broken_data_ptr, contactDisp, contact_common_data_ptr,
2852 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2853 CHKERR add_ops_contact_lhs(op_loop_skeleton_side->getOpPtrVector());
2856 pip.push_back(op_loop_skeleton_side);
2861 CHKERR set_hybridisation(fe_lhs->getOpPtrVector());
2862 CHKERR set_contact(fe_lhs->getOpPtrVector());
2872 const bool add_elastic,
const bool add_material,
2873 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
2874 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
2877 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2878 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2883 fe_rhs->getRuleHook = [](int, int, int) {
return -1; };
2884 fe_lhs->getRuleHook = [](int, int, int) {
return -1; };
2885 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2886 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2889 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2890 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2892 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2893 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2897 auto get_broken_op_side = [
this](
auto &pip) {
2900 using SideEleOp = EleOnSide::UserDataOperator;
2902 auto broken_data_ptr =
2903 boost::make_shared<std::vector<BrokenBaseSideData>>();
2906 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2907 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2908 boost::make_shared<CGGUserPolynomialBase>();
2910 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2911 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2912 materialH1Positions, frontAdjEdges);
2913 op_loop_domain_side->getOpPtrVector().push_back(
2915 boost::shared_ptr<double> piola_scale_ptr(
new double);
2916 op_loop_domain_side->getOpPtrVector().push_back(
2917 physicalEquations->returnOpSetScale(piola_scale_ptr,
2918 physicalEquations));
2920 auto piola_stress_mat_ptr = boost::make_shared<MatrixDouble>();
2921 op_loop_domain_side->getOpPtrVector().push_back(
2923 piola_stress_mat_ptr));
2924 pip.push_back(op_loop_domain_side);
2925 return std::make_tuple(broken_data_ptr, piola_scale_ptr,
2926 piola_stress_mat_ptr);
2929 auto set_rhs = [&]() {
2932 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
2933 get_broken_op_side(fe_rhs->getOpPtrVector());
2935 fe_rhs->getOpPtrVector().push_back(
2936 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
2938 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
2941 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
2943 fe_rhs->getOpPtrVector().push_back(
2945 piola_scale_ptr, timeScaleMap));
2946 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
2948 fe_rhs->getOpPtrVector().push_back(
2950 hybridSpatialDisp, hybrid_grad_ptr));
2952 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
2953 hybrid_grad_ptr, timeScaleMap));
2955 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
2958 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2959 fe_rhs->getOpPtrVector().push_back(
2963 hybridSpatialDisp, hybrid_ptr, piola_stress_mat_ptr,
2964 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
2966 auto get_normal_disp_bc_faces = [&]() {
2969 return boost::make_shared<Range>(faces);
2974 using BdyEleOp = BoundaryEle::UserDataOperator;
2976 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2977 fe_rhs->getOpPtrVector().push_back(
new OpC_dBroken(
2978 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
2979 get_normal_disp_bc_faces()));
2984 auto set_lhs = [&]() {
2987 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
2988 get_broken_op_side(fe_lhs->getOpPtrVector());
2991 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
2993 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
2996 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
2998 fe_rhs->getOpPtrVector().push_back(
3000 hybridSpatialDisp, hybrid_grad_ptr));
3002 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
3005 auto get_normal_disp_bc_faces = [&]() {
3008 return boost::make_shared<Range>(faces);
3013 using BdyEleOp = BoundaryEle::UserDataOperator;
3015 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3016 fe_lhs->getOpPtrVector().push_back(
new OpC(
3017 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3018 true,
true, get_normal_disp_bc_faces()));
3032 boost::shared_ptr<ContactTree> &fe_contact_tree
3038 auto get_body_range = [
this](
auto name,
int dim,
auto sev) {
3039 std::map<int, Range> map;
3042 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3044 (boost::format(
"%s(.*)") % name).str()
3050 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3053 map[m_ptr->getMeshsetId()] = ents;
3054 MOFEM_LOG(
"EPSYNC", sev) <<
"Meshset: " << m_ptr->getMeshsetId() <<
" "
3055 << ents.size() <<
" entities";
3062 auto get_map_skin = [
this](
auto &&map) {
3063 ParallelComm *pcomm =
3066 Skinner skin(&mField.get_moab());
3067 for (
auto &
m : map) {
3069 CHKERR skin.find_skin(0,
m.second,
false, skin_faces);
3071 PSTATUS_SHARED | PSTATUS_MULTISHARED,
3072 PSTATUS_NOT, -1,
nullptr),
3074 m.second.swap(skin_faces);
3084 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
3086 auto calcs_side_traction = [&](
auto &pip) {
3090 using SideEleOp = EleOnSide::UserDataOperator;
3092 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
3093 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3094 boost::make_shared<CGGUserPolynomialBase>();
3095 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3096 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3097 materialH1Positions, frontAdjEdges);
3098 op_loop_domain_side->getOpPtrVector().push_back(
3100 piolaStress, contact_common_data_ptr->contactTractionPtr(),
3101 boost::make_shared<double>(1.0)));
3102 pip.push_back(op_loop_domain_side);
3106 auto add_contact_three = [&]() {
3108 auto tree_moab_ptr = boost::make_shared<moab::Core>();
3109 fe_contact_tree = boost::make_shared<ContactTree>(
3110 mField, tree_moab_ptr, spaceOrder,
3111 get_body_range(
"CONTACT",
SPACE_DIM - 1, Sev::inform));
3112 fe_contact_tree->getOpPtrVector().push_back(
3114 contactDisp, contact_common_data_ptr->contactDispPtr()));
3115 CHKERR calcs_side_traction(fe_contact_tree->getOpPtrVector());
3116 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
3117 fe_contact_tree->getOpPtrVector().push_back(
3119 fe_contact_tree->getOpPtrVector().push_back(
3120 new OpMoveNode(fe_contact_tree, contact_common_data_ptr, u_h1_ptr));
3124 CHKERR add_contact_three();
3134 CHKERR setContactElementRhsOps(contactTreeRhs);
3136 CHKERR setVolumeElementOps(tag,
true,
false, elasticFeRhs, elasticFeLhs);
3137 CHKERR setFaceElementOps(
true,
false, elasticBcRhs, elasticBcLhs);
3140 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3142 auto get_op_contact_bc = [&]() {
3145 mField, contactElement,
SPACE_DIM - 1, Sev::noisy, adj_cache);
3146 return op_loop_side;
3154 boost::shared_ptr<FEMethod> null;
3156 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3189 bool set_ts_monitor) {
3191#ifdef ENABLE_PYTHON_BINDING
3192 auto setup_sdf = [&]() {
3193 boost::shared_ptr<ContactOps::SDFPython> sdf_python_ptr;
3195 auto file_exists = [](std::string myfile) {
3196 std::ifstream file(myfile.c_str());
3203 char sdf_file_name[255] =
"sdf.py";
3205 sdf_file_name, 255, PETSC_NULLPTR);
3207 if (file_exists(sdf_file_name)) {
3208 MOFEM_LOG(
"EP", Sev::inform) << sdf_file_name <<
" file found";
3209 sdf_python_ptr = boost::make_shared<ContactOps::SDFPython>();
3210 CHKERR sdf_python_ptr->sdfInit(sdf_file_name);
3211 ContactOps::sdfPythonWeakPtr = sdf_python_ptr;
3212 MOFEM_LOG(
"EP", Sev::inform) <<
"SdfPython initialized";
3214 MOFEM_LOG(
"EP", Sev::warning) << sdf_file_name <<
" file NOT found";
3216 return sdf_python_ptr;
3218 auto sdf_python_ptr = setup_sdf();
3221 auto setup_ts_monitor = [&]() {
3222 boost::shared_ptr<TsCtx>
ts_ctx;
3224 if (set_ts_monitor) {
3226 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
3230 MOFEM_LOG(
"EP", Sev::inform) <<
"TS monitor setup";
3231 return std::make_tuple(
ts_ctx);
3234 auto setup_snes_monitor = [&]() {
3237 CHKERR TSGetSNES(ts, &snes);
3239 CHKERR SNESMonitorSet(snes,
3242 (
void *)(snes_ctx.get()), PETSC_NULLPTR);
3243 MOFEM_LOG(
"EP", Sev::inform) <<
"SNES monitor setup";
3247 auto setup_snes_conergence_test = [&]() {
3250 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
3251 PetscReal snorm, PetscReal fnorm,
3252 SNESConvergedReason *reason,
void *cctx) {
3255 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
3259 CHKERR SNESGetSolutionUpdate(snes, &x_update);
3260 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
3328 auto setup_section = [&]() {
3329 PetscSection section_raw;
3332 CHKERR PetscSectionGetNumFields(section_raw, &num_fields);
3333 for (
int ff = 0; ff != num_fields; ff++) {
3341 auto set_vector_on_mesh = [&]() {
3345 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3346 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3347 MOFEM_LOG(
"EP", Sev::inform) <<
"Vector set on mesh";
3351 auto setup_schur_block_solver = [&]() {
3352 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver";
3353 CHKERR TSAppendOptionsPrefix(ts,
"elastic_");
3354 CHKERR TSSetFromOptions(ts);
3357 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
3358 if constexpr (
A == AssemblyType::BLOCK_MAT) {
3363 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver done";
3370#ifdef ENABLE_PYTHON_BINDING
3371 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
3372 setup_snes_monitor(), setup_snes_conergence_test(),
3373 setup_section(), set_vector_on_mesh(),
3374 setup_schur_block_solver());
3376 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
3377 setup_snes_conergence_test(), setup_section(),
3378 set_vector_on_mesh(), setup_schur_block_solver());
3386 PetscBool debug_model = PETSC_FALSE;
3390 if (debug_model == PETSC_TRUE) {
3392 auto post_proc = [&](TS ts, PetscReal
t, Vec u, Vec u_t, Vec u_tt, Vec
F,
3397 CHKERR TSGetSNES(ts, &snes);
3399 CHKERR SNESGetIterationNumber(snes, &it);
3400 std::string file_name =
"snes_iteration_" + std::to_string(it) +
".h5m";
3401 CHKERR postProcessResults(1, file_name,
F, u_t);
3402 std::string file_skel_name =
3403 "snes_iteration_skel_" + std::to_string(it) +
".h5m";
3405 auto get_material_force_tag = [&]() {
3406 auto &moab = mField.get_moab();
3413 CHKERR calculateFaceMaterialForce(1, ts);
3414 CHKERR postProcessSkeletonResults(1, file_skel_name,
F,
3415 {get_material_force_tag()});
3419 ts_ctx_ptr->tsDebugHook = post_proc;
3424 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3426 CHKERR VecDuplicate(x, &xx);
3427 CHKERR VecZeroEntries(xx);
3428 CHKERR TS2SetSolution(ts, x, xx);
3431 CHKERR TSSetSolution(ts, x);
3434 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3435 {elasticFeLhs.get(), elasticFeRhs.get()});
3440 CHKERR TSSolve(ts, PETSC_NULLPTR);
3442 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3443 {elasticFeLhs.get(), elasticFeRhs.get()});
3446 CHKERR TSGetSNES(ts, &snes);
3447 int lin_solver_iterations;
3448 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
3450 <<
"Number of linear solver iterations " << lin_solver_iterations;
3452 PetscBool test_cook_flg = PETSC_FALSE;
3455 if (test_cook_flg) {
3456 constexpr int expected_lin_solver_iterations = 11;
3457 if (lin_solver_iterations > expected_lin_solver_iterations)
3460 "Expected number of iterations is different than expected %d > %d",
3461 lin_solver_iterations, expected_lin_solver_iterations);
3464 PetscBool test_sslv116_flag = PETSC_FALSE;
3466 &test_sslv116_flag, PETSC_NULLPTR);
3468 if (test_sslv116_flag) {
3469 double max_val = 0.0;
3470 double min_val = 0.0;
3471 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
3473 auto ent_type = ent_ptr->getEntType();
3474 if (ent_type == MBVERTEX) {
3475 max_val = std::max(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], max_val);
3476 min_val = std::min(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], min_val);
3481 field_min_max, spatialH1Disp);
3483 double global_max_val = 0.0;
3484 double global_min_val = 0.0;
3485 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
3487 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
3490 <<
"Max " << spatialH1Disp <<
" value: " << global_max_val;
3492 <<
"Min " << spatialH1Disp <<
" value: " << global_min_val;
3494 double ref_max_val = 0.00767;
3495 double ref_min_val = -0.00329;
3496 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
3498 "Incorrect max value of the displacement field: %f != %f",
3499 global_max_val, ref_max_val);
3501 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
3503 "Incorrect min value of the displacement field: %f != %f",
3504 global_min_val, ref_min_val);
3515 double start_time) {
3520 double final_time = 1;
3521 double delta_time = 0.1;
3523 PetscBool ts_h1_update = PETSC_FALSE;
3525 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Dynamic Relaxation Options",
3528 CHKERR PetscOptionsScalar(
"-dynamic_final_time",
3529 "dynamic relaxation final time",
"", final_time,
3530 &final_time, PETSC_NULLPTR);
3531 CHKERR PetscOptionsScalar(
"-dynamic_delta_time",
3532 "dynamic relaxation final time",
"", delta_time,
3533 &delta_time, PETSC_NULLPTR);
3534 CHKERR PetscOptionsInt(
"-dynamic_max_it",
"dynamic relaxation iterations",
"",
3535 max_it, &max_it, PETSC_NULLPTR);
3536 CHKERR PetscOptionsBool(
"-dynamic_h1_update",
"update each ts step",
"",
3537 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
3541 auto setup_ts_monitor = [&]() {
3542 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*
this);
3545 auto monitor_ptr = setup_ts_monitor();
3547 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3548 {elasticFeLhs.get(), elasticFeRhs.get()});
3552 double ts_delta_time;
3553 CHKERR TSGetTimeStep(ts, &ts_delta_time);
3563 dynamicTime = start_time;
3564 dynamicStep = start_step;
3565 monitor_ptr->ts_u = PETSC_NULLPTR;
3566 monitor_ptr->ts_t = dynamicTime;
3567 monitor_ptr->ts_step = dynamicStep;
3569 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3570 << dynamicTime <<
" delta time " << delta_time;
3571 dynamicTime += delta_time;
3574 for (; dynamicTime < final_time; dynamicTime += delta_time) {
3575 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3576 << dynamicTime <<
" delta time " << delta_time;
3578 CHKERR TSSetStepNumber(ts, 0);
3580 CHKERR TSSetTimeStep(ts, ts_delta_time);
3581 if (!ts_h1_update) {
3584 CHKERR TSSolve(ts, PETSC_NULLPTR);
3585 if (!ts_h1_update) {
3589 monitor_ptr->ts_u = PETSC_NULLPTR;
3590 monitor_ptr->ts_t = dynamicTime;
3591 monitor_ptr->ts_step = dynamicStep;
3595 if (dynamicStep > max_it)
3600 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3601 {elasticFeLhs.get(), elasticFeRhs.get()});
3609 auto set_block = [&](
auto name,
int dim) {
3610 std::map<int, Range> map;
3611 auto set_tag_impl = [&](
auto name) {
3616 std::regex((boost::format(
"%s(.*)") % name).str())
3619 for (
auto bc : bcs) {
3621 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
3623 map[bc->getMeshsetId()] = r;
3628 CHKERR set_tag_impl(name);
3630 return std::make_pair(name, map);
3633 auto set_skin = [&](
auto &&map) {
3634 for (
auto &
m : map.second) {
3641 auto set_tag = [&](
auto &&map) {
3643 auto name = map.first;
3644 int def_val[] = {-1};
3646 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER,
th,
3647 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
3649 for (
auto &
m : map.second) {
3657 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"BODY", 3))));
3658 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"MAT_ELASTIC", 3))));
3659 listTagsToTransfer.push_back(
3660 set_tag(set_skin(set_block(
"MAT_NEOHOOKEAN", 3))));
3661 listTagsToTransfer.push_back(set_tag(set_block(
"CONTACT", 2)));
3668 Vec f_residual, Vec var_vector,
3669 std::vector<Tag> tags_to_transfer) {
3675 rval = mField.get_moab().tag_get_handle(
"CRACK",
th);
3676 if (
rval == MB_SUCCESS) {
3677 CHKERR mField.get_moab().tag_delete(
th);
3679 int def_val[] = {0};
3680 CHKERR mField.get_moab().tag_get_handle(
3681 "CRACK", 1, MB_TYPE_INTEGER,
th, MB_TAG_SPARSE | MB_TAG_CREAT, def_val);
3683 CHKERR mField.get_moab().tag_clear_data(
th, *crackFaces, mark);
3684 tags_to_transfer.push_back(
th);
3686 auto get_tag = [&](
auto name,
auto dim) {
3687 auto &mob = mField.get_moab();
3689 double def_val[] = {0., 0., 0.};
3690 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3691 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3696 tags_to_transfer.push_back(get_tag(
"MaterialForce", 3));
3701 for (
auto t : listTagsToTransfer) {
3702 tags_to_transfer.push_back(
t);
3710 struct exclude_sdf {
3711 exclude_sdf(
Range &&r) : map(r) {}
3712 bool operator()(
FEMethod *fe_method_ptr) {
3714 if (map.find(ent) != map.end()) {
3724 contactTreeRhs->exeTestHook =
3729 auto get_post_proc = [&](
auto &post_proc_mesh,
auto sense) {
3731 auto post_proc_ptr =
3732 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
3733 mField, post_proc_mesh);
3734 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3735 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
3738 auto domain_ops = [&](
auto &fe,
int sense) {
3740 fe.getUserPolynomialBase() =
3742 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3743 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
3745 auto piola_scale_ptr = boost::make_shared<double>(1.0);
3746 fe.getOpPtrVector().push_back(physicalEquations->returnOpSetScale(
3747 piola_scale_ptr, physicalEquations));
3749 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
3751 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
3754 fe.getOpPtrVector().push_back(
3755 physicalEquations->returnOpCalculateStretchFromStress(
3756 dataAtPts, physicalEquations));
3758 fe.getOpPtrVector().push_back(
3760 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
3765 piolaStress, dataAtPts->getVarPiolaPts(),
3766 boost::make_shared<double>(1), vec));
3768 bubbleField, dataAtPts->getVarPiolaPts(),
3769 boost::make_shared<double>(1), vec, MBMAXTYPE));
3771 rotAxis, dataAtPts->getVarRotAxisPts(), vec, MBTET));
3773 fe.getOpPtrVector().push_back(
3774 physicalEquations->returnOpCalculateVarStretchFromStress(
3775 dataAtPts, physicalEquations));
3777 fe.getOpPtrVector().push_back(
3779 stretchTensor, dataAtPts->getVarLogStreachPts(), vec, MBTET));
3784 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3786 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3789 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3791 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3793 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3795 fe.getOpPtrVector().push_back(
3799 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3800 tag,
true,
false, dataAtPts, physicalEquations));
3802 physicalEquations->returnOpCalculateEnergy(dataAtPts,
nullptr)) {
3803 fe.getOpPtrVector().push_back(op);
3812 struct OpSidePPMap :
public OpPPMap {
3813 OpSidePPMap(moab::Interface &post_proc_mesh,
3814 std::vector<EntityHandle> &map_gauss_pts,
3815 DataMapVec data_map_scalar, DataMapMat data_map_vec,
3816 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
3818 :
OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
3819 data_map_vec, data_map_mat, data_symm_map_mat),
3826 if (tagSense != OpPPMap::getSkeletonSense())
3838 vec_fields[
"SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
3839 vec_fields[
"SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
3840 vec_fields[
"Omega"] = dataAtPts->getRotAxisAtPts();
3841 vec_fields[
"ContactDisplacement"] = dataAtPts->getContactL2AtPts();
3842 vec_fields[
"AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
3843 vec_fields[
"X"] = dataAtPts->getLargeXH1AtPts();
3845 vec_fields[
"EiegnLogStreach"] = dataAtPts->getEigenValsAtPts();
3849 vec_fields[
"VarOmega"] = dataAtPts->getVarRotAxisPts();
3850 vec_fields[
"VarSpatialDisplacementL2"] =
3851 boost::make_shared<MatrixDouble>();
3853 spatialL2Disp, vec_fields[
"VarSpatialDisplacementL2"], vec, MBTET));
3857 vec_fields[
"ResSpatialDisplacementL2"] =
3858 boost::make_shared<MatrixDouble>();
3860 spatialL2Disp, vec_fields[
"ResSpatialDisplacementL2"], vec, MBTET));
3861 vec_fields[
"ResOmega"] = boost::make_shared<MatrixDouble>();
3863 rotAxis, vec_fields[
"ResOmega"], vec, MBTET));
3867 mat_fields[
"PiolaStress"] = dataAtPts->getApproxPAtPts();
3869 mat_fields[
"VarPiolaStress"] = dataAtPts->getVarPiolaPts();
3873 mat_fields[
"ResPiolaStress"] = boost::make_shared<MatrixDouble>();
3875 piolaStress, mat_fields[
"ResPiolaStress"],
3876 boost::make_shared<double>(1), vec));
3878 bubbleField, mat_fields[
"ResPiolaStress"],
3879 boost::make_shared<double>(1), vec, MBMAXTYPE));
3881 if (!internalStressTagName.empty()) {
3882 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
3883 switch (internalStressInterpOrder) {
3885 fe.getOpPtrVector().push_back(
3889 fe.getOpPtrVector().push_back(
3894 "Unsupported internal stress interpolation order %d",
3895 internalStressInterpOrder);
3900 mat_fields_symm[
"LogSpatialStretch"] =
3901 dataAtPts->getLogStretchTensorAtPts();
3902 mat_fields_symm[
"SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
3904 mat_fields_symm[
"VarLogSpatialStretch"] =
3905 dataAtPts->getVarLogStreachPts();
3910 mat_fields_symm[
"ResLogSpatialStretch"] =
3911 boost::make_shared<MatrixDouble>();
3912 fe.getOpPtrVector().push_back(
3914 stretchTensor, mat_fields_symm[
"ResLogSpatialStretch"], vec,
3919 fe.getOpPtrVector().push_back(
3923 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3940 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3946 post_proc_ptr->getOpPtrVector().push_back(
3948 dataAtPts->getContactL2AtPts()));
3950 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
3952 post_proc_ptr->getOpPtrVector().push_back(
3954 dataAtPts->getLargeXH1AtPts()));
3959 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
3960 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
3962 return post_proc_ptr;
3966 auto calcs_side_traction_and_displacements = [&](
auto &post_proc_ptr,
3969 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
3973 using SideEleOp = EleOnSide::UserDataOperator;
3975 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
3976 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3978 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3979 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3980 materialH1Positions, frontAdjEdges);
3981 op_loop_domain_side->getOpPtrVector().push_back(
3983 piolaStress, contact_common_data_ptr->contactTractionPtr(),
3984 boost::make_shared<double>(1.0)));
3985 pip.push_back(op_loop_domain_side);
3987 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
3990 contactDisp, contact_common_data_ptr->contactDispPtr()));
3991 pip.push_back(
new OpTreeSearch(
3992 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
3994 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4001 pip.push_back(op_this);
4002 auto contact_residual = boost::make_shared<MatrixDouble>();
4003 op_this->getOpPtrVector().push_back(
4005 contactDisp, contact_residual,
4008 op_this->getOpPtrVector().push_back(
4012 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4016 {{
"res_contact", contact_residual}},
4030 auto post_proc_mesh = boost::make_shared<moab::Core>();
4031 auto post_proc_ptr = get_post_proc(post_proc_mesh, 1);
4032 auto post_proc_negative_sense_ptr = get_post_proc(post_proc_mesh, -1);
4033 CHKERR calcs_side_traction_and_displacements(post_proc_ptr,
4034 post_proc_ptr->getOpPtrVector());
4040 CHKERR mField.get_moab().get_adjacencies(own_tets,
SPACE_DIM - 1,
true,
4041 own_faces, moab::Interface::UNION);
4043 auto get_post_negative = [&](
auto &&ents) {
4044 auto crack_faces_pos = ents;
4045 auto crack_faces_neg = crack_faces_pos;
4046 auto skin =
get_skin(mField, own_tets);
4047 auto crack_on_proc_skin = intersect(crack_faces_pos, skin);
4048 for (
auto f : crack_on_proc_skin) {
4050 CHKERR mField.get_moab().get_adjacencies(&f, 1,
SPACE_DIM,
false, tet);
4051 tet = intersect(tet, own_tets);
4052 int side_number, sense, offset;
4053 CHKERR mField.get_moab().side_number(tet[0], f, side_number, sense,
4056 crack_faces_neg.erase(f);
4058 crack_faces_pos.erase(f);
4061 return std::make_pair(crack_faces_pos, crack_faces_neg);
4064 auto get_crack_faces = [&](
auto crack_faces) {
4065 auto get_adj = [&](
auto e,
auto dim) {
4067 CHKERR mField.get_moab().get_adjacencies(e, dim,
true, adj,
4068 moab::Interface::UNION);
4071 auto tets = get_adj(crack_faces, 3);
4072 auto faces = subtract(get_adj(tets, 2), crack_faces);
4073 tets = subtract(tets, get_adj(faces, 3));
4074 return subtract(crack_faces, get_adj(tets, 2));
4077 auto [crack_faces_pos, crack_faces_neg] =
4078 get_post_negative(intersect(own_faces, get_crack_faces(*crackFaces)));
4080 auto only_crack_faces = [&](
FEMethod *fe_method_ptr) {
4081 auto ent = fe_method_ptr->getFEEntityHandle();
4082 if (crack_faces_pos.find(ent) == crack_faces_pos.end()) {
4088 auto only_negative_crack_faces = [&](
FEMethod *fe_method_ptr) {
4089 auto ent = fe_method_ptr->getFEEntityHandle();
4090 if (crack_faces_neg.find(ent) == crack_faces_neg.end()) {
4096 auto get_adj_front = [&]() {
4097 auto skeleton_faces = *skeletonFaces;
4099 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2,
true, adj_front,
4100 moab::Interface::UNION);
4102 adj_front = intersect(adj_front, skeleton_faces);
4103 adj_front = subtract(adj_front, *crackFaces);
4104 adj_front = intersect(own_faces, adj_front);
4108 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4109 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
4111 auto post_proc_begin =
4115 post_proc_ptr->exeTestHook = only_crack_faces;
4116 post_proc_negative_sense_ptr->exeTestHook = only_negative_crack_faces;
4118 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4120 post_proc_negative_sense_ptr, 0,
4121 mField.get_comm_size());
4123 constexpr bool debug =
false;
4126 auto [adj_front_pos, adj_front_neg] =
4129 auto only_front_faces_pos = [adj_front_pos](
FEMethod *fe_method_ptr) {
4130 auto ent = fe_method_ptr->getFEEntityHandle();
4131 if (adj_front_pos.find(ent) == adj_front_pos.end()) {
4137 auto only_front_faces_neg = [adj_front_neg](
FEMethod *fe_method_ptr) {
4138 auto ent = fe_method_ptr->getFEEntityHandle();
4139 if (adj_front_neg.find(ent) == adj_front_neg.end()) {
4145 post_proc_ptr->exeTestHook = only_front_faces_pos;
4147 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4148 post_proc_negative_sense_ptr->exeTestHook = only_front_faces_neg;
4150 post_proc_negative_sense_ptr, 0,
4151 mField.get_comm_size());
4156 CHKERR post_proc_end.writeFile(file.c_str());
4163 std::vector<Tag> tags_to_transfer) {
4168 auto post_proc_mesh = boost::make_shared<moab::Core>();
4169 auto post_proc_ptr =
4170 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4172 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
4176 auto hybrid_disp = boost::make_shared<MatrixDouble>();
4177 post_proc_ptr->getOpPtrVector().push_back(
4179 post_proc_ptr->getOpPtrVector().push_back(
4183 auto op_loop_domain_side =
4186 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4189 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4190 boost::make_shared<CGGUserPolynomialBase>();
4191 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4192 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4194 op_loop_domain_side->getOpPtrVector().push_back(
4197 op_loop_domain_side->getOpPtrVector().push_back(
4200 op_loop_domain_side->getOpPtrVector().push_back(
4204 op_loop_domain_side->getOpPtrVector().push_back(
4208 op_loop_domain_side->getOpPtrVector().push_back(
4216 vec_fields[
"HybridDisplacement"] = hybrid_disp;
4217 vec_fields[
"Omega"] =
dataAtPts->getRotAxisAtPts();
4219 mat_fields[
"PiolaStress"] =
dataAtPts->getApproxPAtPts();
4220 mat_fields[
"HybridDisplacementGradient"] =
4223 mat_fields_symm[
"LogSpatialStretch"] =
dataAtPts->getLogStretchTensorAtPts();
4225 post_proc_ptr->getOpPtrVector().push_back(
4229 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4244 auto hybrid_res = boost::make_shared<MatrixDouble>();
4245 post_proc_ptr->getOpPtrVector().push_back(
4250 post_proc_ptr->getOpPtrVector().push_back(
4254 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4258 {{
"res_hybrid", hybrid_res}},
4269 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4271 auto post_proc_begin =
4278 CHKERR post_proc_end.writeFile(file.c_str());
4286 constexpr bool debug =
false;
4288 auto get_tags_vec = [&](std::vector<std::pair<std::string, int>> names) {
4289 std::vector<Tag> tags;
4290 tags.reserve(names.size());
4291 auto create_and_clean = [&]() {
4293 for (
auto n : names) {
4294 tags.push_back(
Tag());
4295 auto &tag = tags.back();
4297 auto rval = moab.tag_get_handle(
n.first.c_str(), tag);
4298 if (
rval == MB_SUCCESS) {
4299 moab.tag_delete(tag);
4301 double def_val[] = {0., 0., 0.};
4302 CHKERR moab.tag_get_handle(
n.first.c_str(),
n.second, MB_TYPE_DOUBLE,
4303 tag, MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4311 enum ExhangeTags { MATERIALFORCE, AREAGROWTH, GRIFFITHFORCE, FACEPRESSURE };
4313 auto tags = get_tags_vec({{
"MaterialForce", 3},
4315 {
"GriffithForce", 1},
4316 {
"FacePressure", 1}});
4318 auto calculate_material_forces = [&]() {
4324 auto get_face_material_force_fe = [&]() {
4326 auto fe_ptr = boost::make_shared<FaceEle>(
mField);
4327 fe_ptr->getRuleHook = [](int, int, int) {
return -1; };
4328 fe_ptr->setRuleHook =
4332 EshelbianPlasticity::AddHOOps<2, 2, 3>::add(
4336 fe_ptr->getOpPtrVector().push_back(
4339 auto op_loop_domain_side =
4342 fe_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4346 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4347 boost::make_shared<CGGUserPolynomialBase>();
4349 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4350 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4352 op_loop_domain_side->getOpPtrVector().push_back(
4355 op_loop_domain_side->getOpPtrVector().push_back(
4365 op_loop_domain_side->getOpPtrVector().push_back(
4369 op_loop_domain_side->getOpPtrVector().push_back(
4373 op_loop_domain_side->getOpPtrVector().push_back(
4378 op_loop_domain_side->getOpPtrVector().push_back(
4384 auto integrate_face_material_force_fe = [&](
auto &&face_energy_fe) {
4392 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
4395 CHKERR VecGetLocalSize(
v.second, &size);
4397 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
4398 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( "
4399 << low <<
" " << high <<
" ) ";
4403 CHKERR print_loc_size(face_exchange,
"material face_exchange",
4407 mField.
get_moab(), face_exchange, tags[ExhangeTags::MATERIALFORCE]);
4414 "front_skin_faces_material_force_" +
4423 CHKERR integrate_face_material_force_fe(get_face_material_force_fe());
4428 auto calculate_front_material_force = [&](
auto nb_J_integral_contours) {
4432 auto get_conn = [&](
auto e) {
4435 "get connectivity");
4439 auto get_conn_range = [&](
auto e) {
4442 "get connectivity");
4446 auto get_adj = [&](
auto e,
auto dim) {
4453 auto get_adj_range = [&](
auto e,
auto dim) {
4456 moab::Interface::UNION),
4461 auto get_material_force = [&](
auto r,
auto th) {
4466 return material_forces;
4471 auto crack_edges = get_adj_range(*
crackFaces, 1);
4472 auto front_nodes = get_conn_range(*
frontEdges);
4479 Range all_skin_faces;
4480 Range all_front_faces;
4483 auto calculate_edge_direction = [&](
auto e) {
4488 "get connectivity");
4489 std::array<double, 6> coords;
4494 &coords[0], &coords[1], &coords[2]};
4496 &coords[3], &coords[4], &coords[5]};
4499 t_dir(
i) = t_p1(
i) - t_p0(
i);
4504 auto calculate_force_through_node = [&]() {
4516 auto body_skin_conn = get_conn_range(body_skin);
4519 for (
auto n : front_nodes) {
4520 auto adj_tets = get_adj(
n, 3);
4521 for (
int ll = 0; ll < nb_J_integral_contours; ++ll) {
4522 auto conn = get_conn_range(adj_tets);
4523 adj_tets = get_adj_range(conn, 3);
4526 auto material_forces = get_material_force(skin_faces, tags[0]);
4530 all_skin_faces.merge(skin_faces);
4534 auto calculate_node_material_force = [&]() {
4536 getFTensor1FromPtr<SPACE_DIM>(material_forces.data().data());
4538 for (
auto face : skin_faces) {
4541 t_face_force_tmp(
I) = t_face_T(
I);
4544 auto face_tets = intersect(get_adj(face, 3), adj_tets);
4546 if (face_tets.empty()) {
4550 if (face_tets.size() != 1) {
4552 "face_tets.size() != 1");
4555 int side_number, sense, offset;
4559 "moab side number");
4560 t_face_force_tmp(
I) *= sense;
4561 t_node_force(
I) += t_face_force_tmp(
I);
4564 return t_node_force;
4567 auto calculate_crack_area_growth_direction =
4568 [&](
auto n,
auto &t_node_force) {
4571 auto boundary_node = intersect(
Range(
n,
n), body_skin_conn);
4572 if (boundary_node.size()) {
4573 auto faces = intersect(get_adj(
n, 2), body_skin);
4574 for (
auto f : faces) {
4577 f, &t_normal_face(0));
4578 t_project(
I) += t_normal_face(
I);
4580 t_project.normalize();
4587 if (boundary_node.size()) {
4588 t_Q(
I,
J) -= t_project(
I) * t_project(
J);
4591 auto adj_faces = intersect(get_adj(
n, 2), *
crackFaces);
4592 if (adj_faces.empty()) {
4594 intersect(get_adj(
n, 1), unite(*
frontEdges, body_edges));
4596 for (
auto e : adj_edges) {
4597 auto t_dir = calculate_edge_direction(e);
4603 t_node_force_tmp(
I) = t_node_force(
I);
4605 t_area_dir(
I) = -t_node_force_tmp(
I);
4606 t_area_dir(
I) *=
l / 2;
4611 auto front_edges = get_adj(
n, 1);
4613 for (
auto f : adj_faces) {
4618 std::array<double, 9> coords;
4624 coords.data(), &t_face_normal(0), &t_d_normal(0, 0, 0));
4625 auto n_it = std::find(conn, conn + num_nodes,
n);
4626 auto n_index = std::distance(conn, n_it);
4629 t_d_normal(0, n_index, 0), t_d_normal(0, n_index, 1),
4630 t_d_normal(0, n_index, 2),
4632 t_d_normal(1, n_index, 0), t_d_normal(1, n_index, 1),
4633 t_d_normal(1, n_index, 2),
4635 t_d_normal(2, n_index, 0), t_d_normal(2, n_index, 1),
4636 t_d_normal(2, n_index, 2)};
4639 t_projected_hessian(
I,
J) =
4640 t_Q(
I,
K) * (t_face_hessian(
K,
L) * t_Q(
L,
J));
4643 t_face_normal(
I) * t_projected_hessian(
I,
K) / 2.;
4649 auto t_node_force = calculate_node_material_force();
4653 &
n, 1, &t_node_force(0)),
4656 auto get_area_dir = [&]() {
4658 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
4660 auto seed_n = get_conn_range(adj_edges);
4662 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
4663 seed_n = subtract(seed_n, skin_adj_edges);
4665 for (
auto sn : seed_n) {
4666 auto t_area_dir_sn =
4667 calculate_crack_area_growth_direction(sn, t_node_force);
4668 t_area_dir(
I) += t_area_dir_sn(
I);
4670 for (
auto sn : skin_adj_edges) {
4671 auto t_area_dir_sn =
4672 calculate_crack_area_growth_direction(sn, t_node_force);
4673 t_area_dir(
I) += t_area_dir_sn(
I) / 2;
4678 auto t_area_dir = get_area_dir();
4684 auto griffith = -t_node_force(
I) * t_area_dir(
I) /
4685 (t_area_dir(
K) * t_area_dir(
K));
4693 auto ave_node_force = [&](
auto th) {
4698 auto conn = get_conn(e);
4699 auto data = get_material_force(conn,
th);
4700 auto t_node = getFTensor1FromPtr<SPACE_DIM>(data.data().data());
4702 for (
auto n : conn) {
4704 t_edge(
I) += t_node(
I);
4707 t_edge(
I) /= conn.size();
4710 calculate_edge_direction(e);
4728 auto ave_node_griffith_energy = [&](
auto th) {
4733 tags[ExhangeTags::MATERIALFORCE], &e, 1, &t_edge_force(0));
4736 &e, 1, &t_edge_area_dir(0));
4737 double griffith_energy = -t_edge_force(
I) * t_edge_area_dir(
I) /
4738 (t_edge_area_dir(
K) * t_edge_area_dir(
K));
4744 CHKERR ave_node_force(tags[ExhangeTags::MATERIALFORCE]);
4745 CHKERR ave_node_force(tags[ExhangeTags::AREAGROWTH]);
4746 CHKERR ave_node_griffith_energy(tags[ExhangeTags::GRIFFITHFORCE]);
4751 CHKERR calculate_force_through_node();
4755 auto adj_faces = get_adj(e, 2);
4756 auto crack_face = intersect(get_adj(e, 2), *
crackFaces);
4760 all_front_faces.merge(adj_faces);
4766 &e, 1, &t_edge_force(0));
4768 calculate_edge_direction(e);
4777 for (
auto f : adj_faces) {
4781 int side_number, sense, offset;
4784 auto dot = -sense * t_cross(
I) * t_normal(
I);
4786 tags[ExhangeTags::GRIFFITHFORCE], &
f, 1, &dot),
4794 CHKERR TSGetStepNumber(ts, &ts_step);
4796 "front_edges_material_force_" +
4797 std::to_string(ts_step) +
".vtk",
4800 "front_skin_faces_material_force_" +
4801 std::to_string(ts_step) +
".vtk",
4804 "front_faces_material_force_" +
4805 std::to_string(ts_step) +
".vtk",
4814 mField.
get_moab(), edge_exchange, tags[ExhangeTags::MATERIALFORCE]);
4816 mField.
get_moab(), edge_exchange, tags[ExhangeTags::AREAGROWTH]);
4823 auto print_results = [&](
auto nb_J_integral_conturs) {
4826 auto get_conn_range = [&](
auto e) {
4829 "get connectivity");
4833 auto get_tag_data = [&](
auto &ents,
auto tag,
auto dim) {
4834 std::vector<double> data(ents.size() * dim);
4841 auto at_nodes = [&]() {
4844 auto material_force =
4845 get_tag_data(conn, tags[ExhangeTags::MATERIALFORCE], 3);
4846 auto area_growth = get_tag_data(conn, tags[ExhangeTags::AREAGROWTH], 3);
4847 auto griffith_force =
4848 get_tag_data(conn, tags[ExhangeTags::GRIFFITHFORCE], 1);
4849 std::vector<double> coords(conn.size() * 3);
4853 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Material force at nodes";
4854 for (
size_t i = 0;
i < conn.size(); ++
i) {
4856 <<
"Node " << conn[
i] <<
" coords " << coords[
i * 3 + 0] <<
" "
4857 << coords[
i * 3 + 1] <<
" " << coords[
i * 3 + 2]
4858 <<
" material force " << material_force[
i * 3 + 0] <<
" "
4859 << material_force[
i * 3 + 1] <<
" " << material_force[
i * 3 + 2]
4860 <<
" area growth " << area_growth[
i * 3 + 0] <<
" "
4861 << area_growth[
i * 3 + 1] <<
" " << area_growth[
i * 3 + 2]
4862 <<
" griffith force " << std::setprecision(12)
4863 << griffith_force[
i] <<
" contour " << nb_J_integral_conturs;
4873 CHKERR calculate_material_forces();
4875 PetscBool all_conturs = PETSC_FALSE;
4877 "-calculate_J_integral_all_levels", &all_conturs,
4880 "-calculate_J_integral_all_contours", &all_conturs,
4884 if (all_conturs == PETSC_TRUE) {
4886 CHKERR calculate_front_material_force(
l);
4900 bool set_orientation) {
4904 constexpr auto sev = Sev::verbose;
4909 Range body_skin_edges;
4911 moab::Interface::UNION);
4912 Range boundary_skin_verts;
4914 boundary_skin_verts,
true);
4917 Range geometry_edges_verts;
4919 geometry_edges_verts,
true);
4920 Range crack_faces_verts;
4923 Range crack_faces_edges;
4925 *
crackFaces, 1,
true, crack_faces_edges, moab::Interface::UNION);
4926 Range crack_faces_tets;
4928 *
crackFaces, 3,
true, crack_faces_tets, moab::Interface::UNION);
4934 moab::Interface::UNION);
4935 Range front_verts_edges;
4937 front_verts, 1,
true, front_verts_edges, moab::Interface::UNION);
4939 auto get_tags_vec = [&](
auto tag_name,
int dim) {
4940 std::vector<Tag> tags(1);
4945 auto create_and_clean = [&]() {
4948 auto rval = moab.tag_get_handle(tag_name, tags[0]);
4949 if (
rval == MB_SUCCESS) {
4950 moab.tag_delete(tags[0]);
4952 double def_val[] = {0., 0., 0.};
4953 CHKERR moab.tag_get_handle(tag_name, dim, MB_TYPE_DOUBLE, tags[0],
4954 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4963 auto get_adj_front = [&](
bool subtract_crack) {
4966 adj_front, moab::Interface::UNION);
4968 adj_front = subtract(adj_front, *
crackFaces);
4974 auto th_front_position = get_tags_vec(
"FrontPosition", 3);
4975 auto th_max_face_energy = get_tags_vec(
"MaxFaceEnergy", 1);
4979 auto get_crack_adj_tets = [&](
auto r) {
4980 Range crack_faces_conn;
4982 Range crack_faces_conn_tets;
4984 true, crack_faces_conn_tets,
4985 moab::Interface::UNION);
4986 return crack_faces_conn_tets;
4989 auto get_layers_for_sides = [&](
auto &side) {
4990 std::vector<Range> layers;
4994 auto get_adj = [&](
auto &r,
int dim) {
4997 moab::Interface::UNION);
5001 auto get_tets = [&](
auto r) {
return get_adj(r,
SPACE_DIM); };
5006 Range front_faces = get_adj(front_nodes, 2);
5007 front_faces = subtract(front_faces, *
crackFaces);
5008 auto front_tets = get_tets(front_nodes);
5009 auto front_side = intersect(side, front_tets);
5010 layers.push_back(front_side);
5013 adj_faces = intersect(adj_faces, front_faces);
5014 auto adj_faces_tets = get_tets(adj_faces);
5015 adj_faces_tets = intersect(adj_faces_tets, front_tets);
5016 layers.push_back(unite(layers.back(), adj_faces_tets));
5017 if (layers.back().size() == layers[layers.size() - 2].size()) {
5028 auto layers_top = get_layers_for_sides(sides_pair.first);
5029 auto layers_bottom = get_layers_for_sides(sides_pair.second);
5041 MOFEM_LOG(
"EP", sev) <<
"Nb. layers " << layers_top.size();
5043 for (
auto &r : layers_top) {
5044 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
5047 "layers_top_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
5052 for (
auto &r : layers_bottom) {
5053 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
5056 "layers_bottom_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
5062 auto get_cross = [&](
auto t_dir,
auto f) {
5074 auto get_sense = [&](
auto f,
auto e) {
5075 int side, sense, offset;
5078 return std::make_tuple(side, sense, offset);
5081 auto calculate_edge_direction = [&](
auto e,
auto normalize =
true) {
5085 std::array<double, 6> coords;
5088 &coords[0], &coords[1], &coords[2]};
5090 &coords[3], &coords[4], &coords[5]};
5093 t_dir(
i) = t_p1(
i) - t_p0(
i);
5099 auto evaluate_face_energy_and_set_orientation = [&](
auto front_edges,
5106 Tag th_material_force;
5108 case GRIFFITH_FORCE:
5109 case GRIFFITH_SKELETON:
5116 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
5117 "Unknown energy release selector");
5125 auto find_maximal_face_energy = [&](
auto front_edges,
auto front_faces,
5126 auto &edge_face_max_energy_map) {
5135 for (
auto e : front_edges) {
5137 double griffith_force;
5143 faces = subtract(intersect(faces, front_faces), body_skin);
5144 std::vector<double> face_energy(faces.size());
5146 face_energy.data());
5147 auto max_energy_it =
5148 std::max_element(face_energy.begin(), face_energy.end());
5150 max_energy_it != face_energy.end() ? *max_energy_it : 0;
5152 edge_face_max_energy_map[e] =
5153 std::make_tuple(faces[max_energy_it - face_energy.begin()],
5154 griffith_force,
static_cast<double>(0));
5156 <<
"Edge " << e <<
" griffith force " << griffith_force
5157 <<
" max face energy " << max_energy <<
" factor "
5158 << max_energy / griffith_force;
5160 max_faces.insert(faces[max_energy_it - face_energy.begin()]);
5182 auto calculate_face_orientation = [&](
auto &edge_face_max_energy_map) {
5185 auto up_down_face = [&](
5187 auto &face_angle_map_up,
5188 auto &face_angle_map_down
5193 for (
auto &
m : edge_face_max_energy_map) {
5195 auto [max_face, energy, opt_angle] =
m.second;
5199 faces = intersect(faces, front_faces);
5203 moab::Interface::UNION);
5204 if (adj_tets.size()) {
5209 moab::Interface::UNION);
5210 if (adj_tets.size()) {
5212 Range adj_tets_faces;
5215 adj_tets,
SPACE_DIM - 1,
false, adj_tets_faces,
5216 moab::Interface::UNION);
5217 adj_tets_faces = intersect(adj_tets_faces, faces);
5222 get_cross(calculate_edge_direction(e,
true), max_face);
5223 auto [side_max, sense_max, offset_max] = get_sense(max_face, e);
5224 t_cross_max(
i) *= sense_max;
5226 for (
auto t : adj_tets) {
5227 Range adj_tets_faces;
5229 &
t, 1,
SPACE_DIM - 1,
false, adj_tets_faces);
5230 adj_tets_faces = intersect(adj_tets_faces, faces);
5232 subtract(adj_tets_faces,
Range(max_face, max_face));
5234 if (adj_tets_faces.size() == 1) {
5238 auto t_cross = get_cross(calculate_edge_direction(e,
true),
5240 auto [side, sense, offset] =
5241 get_sense(adj_tets_faces[0], e);
5242 t_cross(
i) *= sense;
5243 double dot = t_cross(
i) * t_cross_max(
i);
5244 auto angle = std::acos(dot);
5248 th_face_energy, adj_tets_faces, &face_energy);
5250 auto [side_face, sense_face, offset_face] =
5251 get_sense(
t, max_face);
5253 if (sense_face > 0) {
5254 face_angle_map_up[e] = std::make_tuple(face_energy, angle,
5258 face_angle_map_down[e] = std::make_tuple(
5259 face_energy, -angle, adj_tets_faces[0]);
5270 auto calc_optimal_angle = [&](
5272 auto &face_angle_map_up,
5273 auto &face_angle_map_down
5278 for (
auto &
m : edge_face_max_energy_map) {
5280 auto &[max_face, e0,
a0] =
m.second;
5282 if (std::abs(e0) > std::numeric_limits<double>::epsilon()) {
5284 if (face_angle_map_up.find(e) == face_angle_map_up.end() ||
5285 face_angle_map_down.find(e) == face_angle_map_down.end()) {
5290 case GRIFFITH_FORCE:
5291 case GRIFFITH_SKELETON: {
5293 Tag th_material_force;
5298 th_material_force, &e, 1, &t_material_force(0));
5299 auto material_force_magnitude = t_material_force.
l2();
5300 if (material_force_magnitude <
5301 std::numeric_limits<double>::epsilon()) {
5306 auto t_edge_dir = calculate_edge_direction(e,
true);
5307 auto t_cross_max = get_cross(t_edge_dir, max_face);
5308 auto [side, sense, offset] = get_sense(max_face, e);
5309 t_cross_max(sense) *= sense;
5316 t_cross_max.normalize();
5319 t_material_force(
J) * t_cross_max(
K);
5320 a0 = -std::asin(t_cross(
I) * t_edge_dir(
I));
5323 <<
"Optimal angle " <<
a0 <<
" energy " << e0;
5329 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
5330 "Unknown energy release selector");
5340 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5342 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5343 face_angle_map_down;
5344 CHKERR up_down_face(face_angle_map_up, face_angle_map_down);
5345 CHKERR calc_optimal_angle(face_angle_map_up, face_angle_map_down);
5349 auto th_angle = get_tags_vec(
"Angle", 1);
5351 for (
auto &
m : face_angle_map_up) {
5352 auto [e,
a, face] =
m.second;
5357 for (
auto &
m : face_angle_map_down) {
5358 auto [e,
a, face] =
m.second;
5363 Range max_energy_faces;
5364 for (
auto &
m : edge_face_max_energy_map) {
5365 auto [face, e, angle] =
m.second;
5366 max_energy_faces.insert(face);
5382 auto get_conn = [&](
auto e) {
5389 auto get_adj = [&](
auto e,
auto dim) {
5392 e, dim,
false, adj, moab::Interface::UNION),
5397 auto get_coords = [&](
auto v) {
5405 auto get_rotated_normal = [&](
auto e,
auto f,
auto angle) {
5408 auto t_edge_dir = calculate_edge_direction(e,
true);
5409 auto [side, sense, offset] = get_sense(
f, e);
5410 t_edge_dir(
i) *= sense;
5411 t_edge_dir.normalize();
5412 t_edge_dir(
i) *= angle;
5417 t_rotated_normal(
i) = t_R(
i,
j) * t_normal(
j);
5418 return std::make_tuple(t_normal, t_rotated_normal);
5421 auto set_coord = [&](
auto v,
auto &adj_vertex_tets_verts,
auto &coords,
5422 auto &t_move,
auto gamma) {
5423 auto index = adj_vertex_tets_verts.index(
v);
5425 for (
auto ii : {0, 1, 2}) {
5426 coords[3 * index + ii] += gamma * t_move(ii);
5433 auto tets_quality = [&](
auto quality,
auto &adj_vertex_tets_verts,
5434 auto &adj_vertex_tets,
auto &coords) {
5435 for (
auto t : adj_vertex_tets) {
5439 std::array<double, 12> tet_coords;
5440 for (
auto n = 0;
n != 4; ++
n) {
5441 auto index = adj_vertex_tets_verts.index(conn[
n]);
5445 for (
auto ii = 0; ii != 3; ++ii) {
5446 tet_coords[3 *
n + ii] = coords[3 * index + ii];
5450 if (!std::isnormal(q))
5452 quality = std::min(quality, q);
5458 auto calculate_free_face_node_displacement =
5459 [&](
auto &edge_face_max_energy_map) {
5461 auto get_vertex_edges = [&](
auto vertex) {
5468 vertex_edges = subtract(vertex_edges, front_verts_edges);
5470 if (boundary_skin_verts.size() &&
5471 boundary_skin_verts.find(vertex[0]) !=
5472 boundary_skin_verts.end()) {
5473 MOFEM_LOG(
"EP", sev) <<
"Boundary vertex";
5474 vertex_edges = intersect(vertex_edges, body_skin_edges);
5476 if (geometry_edges_verts.size() &&
5477 geometry_edges_verts.find(vertex[0]) !=
5478 geometry_edges_verts.end()) {
5479 MOFEM_LOG(
"EP", sev) <<
"Geometry edge vertex";
5480 vertex_edges = intersect(vertex_edges, geometry_edges);
5482 if (crack_faces_verts.size() &&
5483 crack_faces_verts.find(vertex[0]) !=
5484 crack_faces_verts.end()) {
5485 MOFEM_LOG(
"EP", sev) <<
"Crack face vertex";
5486 vertex_edges = intersect(vertex_edges, crack_faces_edges);
5493 return vertex_edges;
5498 using Bundle = std::vector<
5504 std::map<EntityHandle, Bundle> edge_bundle_map;
5506 for (
auto &
m : edge_face_max_energy_map) {
5508 auto edge =
m.first;
5509 auto &[max_face, energy, opt_angle] =
m.second;
5512 auto [t_normal, t_rotated_normal] =
5513 get_rotated_normal(edge, max_face, opt_angle);
5515 auto front_vertex = get_conn(
Range(
m.first,
m.first));
5516 auto adj_tets = get_adj(
Range(max_face, max_face), 3);
5517 auto adj_tets_faces = get_adj(adj_tets, 2);
5518 auto adj_front_faces = subtract(
5519 intersect(get_adj(
Range(edge, edge), 2), adj_tets_faces),
5521 if (adj_front_faces.size() > 3)
5523 "adj_front_faces.size()>3");
5527 &t_material_force(0));
5528 std::vector<double> griffith_energy(adj_front_faces.size());
5530 th_face_energy, adj_front_faces, griffith_energy.data());
5533 auto set_edge_bundle = [&](
auto min_gamma) {
5534 for (
auto rotated_f : adj_front_faces) {
5536 double rotated_face_energy =
5537 griffith_energy[adj_front_faces.index(rotated_f)];
5539 auto vertex = subtract(get_conn(
Range(rotated_f, rotated_f)),
5541 if (vertex.size() != 1) {
5543 "Wrong number of vertex to move");
5545 auto front_vertex_edges_vertex = get_conn(
5546 intersect(get_adj(front_vertex, 1), crack_faces_edges));
5548 vertex, front_vertex_edges_vertex);
5549 if (vertex.empty()) {
5553 auto face_cardinality = [&](
auto f,
auto &seen_front_edges) {
5556 subtract(body_skin_edges, crack_faces_edges));
5559 for (;
c < 10; ++
c) {
5561 subtract(get_adj(faces, 1), seen_front_edges);
5562 if (front_edges.size() == 0) {
5565 auto front_connected_edges =
5566 intersect(front_edges, whole_front);
5567 if (front_connected_edges.size()) {
5568 seen_front_edges.merge(front_connected_edges);
5571 faces.merge(get_adj(front_edges, 2));
5578 double rotated_face_cardinality = face_cardinality(
5584 rotated_face_cardinality = std::max(rotated_face_cardinality,
5587 auto t_vertex_coords = get_coords(vertex);
5588 auto vertex_edges = get_vertex_edges(vertex);
5597 for (
auto e_used_to_move_detection : vertex_edges) {
5598 auto edge_conn = get_conn(
Range(e_used_to_move_detection,
5599 e_used_to_move_detection));
5600 edge_conn = subtract(edge_conn, vertex);
5610 t_v0(
i) = (t_v_e0(
i) + t_v_e1(
i)) / 2;
5614 (t_v0(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5616 (t_v3(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5619 constexpr double eps =
5620 std::numeric_limits<double>::epsilon();
5621 if (std::isnormal(gamma) && gamma < 1.0 -
eps &&
5624 t_move(
i) = gamma * (t_v3(
i) - t_vertex_coords(
i));
5626 auto check_rotated_face_directoon = [&]() {
5628 t_delta(
i) = t_vertex_coords(
i) + t_move(
i) - t_v0(
i);
5631 (t_material_force(
i) / t_material_force.
l2()) *
5633 return -dot > 0 ? true :
false;
5636 if (check_rotated_face_directoon()) {
5639 <<
"Crack edge " << edge <<
" moved face "
5641 <<
" edge: " << e_used_to_move_detection
5642 <<
" face direction/energy " << rotated_face_energy
5643 <<
" face cardinality " << rotated_face_cardinality
5644 <<
" gamma: " << gamma;
5646 auto &bundle = edge_bundle_map[edge];
5647 bundle.emplace_back(rotated_f, e_used_to_move_detection,
5648 vertex[0], t_move, 1,
5649 rotated_face_cardinality, gamma);
5656 set_edge_bundle(std::numeric_limits<double>::epsilon());
5657 if (edge_bundle_map[edge].empty()) {
5658 set_edge_bundle(-1.);
5662 return edge_bundle_map;
5665 auto get_sort_by_energy = [&](
auto &edge_face_max_energy_map) {
5666 std::map<double, std::tuple<EntityHandle, EntityHandle, double>>
5669 for (
auto &
m : edge_face_max_energy_map) {
5671 auto &[max_face, energy, opt_angle] =
m.second;
5672 sort_by_energy[energy] = std::make_tuple(e, max_face, opt_angle);
5675 return sort_by_energy;
5678 auto set_tag = [&](
auto &&adj_edges_map,
auto &&sort_by_energy) {
5681 Tag th_face_pressure;
5683 mField.
get_moab().tag_get_handle(
"FacePressure", th_face_pressure),
5685 auto get_face_pressure = [&](
auto face) {
5694 <<
"Number of edges to check " << sort_by_energy.size();
5696 enum face_energy { POSITIVE, NEGATIVE };
5697 constexpr bool skip_negative =
true;
5699 for (
auto fe : {face_energy::POSITIVE, face_energy::NEGATIVE}) {
5703 for (
auto it = sort_by_energy.rbegin(); it != sort_by_energy.rend();
5706 auto energy = it->first;
5707 auto [max_edge, max_face, opt_angle] = it->second;
5709 auto face_pressure = get_face_pressure(max_face);
5710 if (skip_negative) {
5711 if (fe == face_energy::POSITIVE) {
5712 if (face_pressure < 0) {
5714 <<
"Skip negative face " << max_face <<
" with energy "
5715 << energy <<
" and pressure " << face_pressure;
5722 <<
"Check face " << max_face <<
" edge " << max_edge
5723 <<
" energy " << energy <<
" optimal angle " << opt_angle
5724 <<
" face pressure " << face_pressure;
5726 auto jt = adj_edges_map.find(max_edge);
5727 if (jt == adj_edges_map.end()) {
5729 <<
"Edge " << max_edge <<
" not found in adj_edges_map";
5732 auto &bundle = jt->second;
5734 auto find_max_in_bundle_impl = [&](
auto edge,
auto &bundle,
5741 double max_quality = -2;
5742 double max_quality_evaluated = -2;
5743 double min_cardinality = std::numeric_limits<double>::max();
5747 for (
auto &b : bundle) {
5748 auto &[face, move_edge, vertex, t_move, quality, cardinality,
5751 auto adj_vertex_tets = get_adj(
Range(vertex, vertex), 3);
5752 auto adj_vertex_tets_verts = get_conn(adj_vertex_tets);
5753 std::vector<double> coords(3 * adj_vertex_tets_verts.size());
5755 adj_vertex_tets_verts, coords.data()),
5758 set_coord(vertex, adj_vertex_tets_verts, coords, t_move, gamma);
5759 quality = tets_quality(quality, adj_vertex_tets_verts,
5760 adj_vertex_tets, coords);
5762 auto eval_quality = [](
auto q,
auto c,
auto edge_gamma) {
5766 return ((edge_gamma < 0) ? (q / 2) : q) / pow(
c, 2);
5770 if (eval_quality(quality, cardinality, edge_gamma) >=
5771 max_quality_evaluated) {
5772 max_quality = quality;
5773 min_cardinality = cardinality;
5774 vertex_max = vertex;
5776 move_edge_max = move_edge;
5777 t_move_last(
i) = t_move(
i);
5778 max_quality_evaluated =
5779 eval_quality(max_quality, min_cardinality, edge_gamma);
5783 return std::make_tuple(vertex_max, face_max, t_move_last,
5784 max_quality, min_cardinality);
5787 auto find_max_in_bundle = [&](
auto edge,
auto &bundle) {
5788 auto b_org_bundle = bundle;
5789 auto r = find_max_in_bundle_impl(edge, bundle, 1.);
5790 auto &[vertex_max, face_max, t_move_last, max_quality,
5792 if (max_quality < 0) {
5793 for (
double gamma = 0.95; gamma >= 0.45; gamma -= 0.05) {
5794 bundle = b_org_bundle;
5795 r = find_max_in_bundle_impl(edge, bundle, gamma);
5796 auto &[vertex_max, face_max, t_move_last, max_quality,
5799 <<
"Back tracking: gamma " << gamma <<
" edge " << edge
5800 <<
" quality " << max_quality <<
" cardinality "
5802 if (max_quality > 0.01) {
5804 t_move_last(
I) *= gamma;
5815 auto set_tag_to_vertex_and_face = [&](
auto &&r,
auto &quality) {
5817 auto &[
v,
f, t_move, q, cardinality] = r;
5819 if ((q > 0 && std::isnormal(q)) && energy > 0) {
5822 <<
"Set tag: vertex " <<
v <<
" face " <<
f <<
" "
5823 << max_edge <<
" move " << t_move <<
" energy " << energy
5824 <<
" quality " << q <<
" cardinality " << cardinality;
5835 double quality = -2;
5836 CHKERR set_tag_to_vertex_and_face(
5838 find_max_in_bundle(max_edge, bundle),
5844 if (quality > 0 && std::isnormal(quality) && energy > 0) {
5846 <<
"Crack face set with quality: " << quality;
5859 MOFEM_LOG(
"EP", sev) <<
"Calculate orientation";
5860 std::map<EntityHandle, std::tuple<EntityHandle, double, double>>
5861 edge_face_max_energy_map;
5862 CHKERR find_maximal_face_energy(front_edges, front_faces,
5863 edge_face_max_energy_map);
5864 CHKERR calculate_face_orientation(edge_face_max_energy_map);
5866 MOFEM_LOG(
"EP", sev) <<
"Calculate node positions";
5869 calculate_free_face_node_displacement(edge_face_max_energy_map),
5870 get_sort_by_energy(edge_face_max_energy_map)
5878 CHKERR evaluate_face_energy_and_set_orientation(
5879 *
frontEdges, get_adj_front(
false), sides_pair, th_front_position);
5897 auto get_max_moved_faces = [&]() {
5898 Range max_moved_faces;
5899 auto adj_front = get_adj_front(
false);
5900 std::vector<double> face_energy(adj_front.size());
5902 face_energy.data());
5903 for (
int i = 0;
i != adj_front.size(); ++
i) {
5904 if (face_energy[
i] > std::numeric_limits<double>::epsilon()) {
5905 max_moved_faces.insert(adj_front[
i]);
5909 return boost::make_shared<Range>(max_moved_faces);
5920 "max_moved_faces_" +
5935 Tag th_front_position;
5937 mField.
get_moab().tag_get_handle(
"FrontPosition", th_front_position);
5942 std::vector<double> coords(3 * verts.size());
5944 std::vector<double> pos(3 * verts.size());
5946 for (
int i = 0;
i != 3 * verts.size(); ++
i) {
5947 coords[
i] += pos[
i];
5950 double zero[] = {0., 0., 0.};
5955 constexpr bool debug =
false;
5960 "set_coords_faces_" +
5971 constexpr bool potential_crack_debug =
false;
5972 if constexpr (potential_crack_debug) {
5975 Range crack_front_verts;
5980 Range crack_front_faces;
5982 true, crack_front_faces,
5983 moab::Interface::UNION);
5984 crack_front_faces = intersect(crack_front_faces, add_ents);
5991 auto get_crack_faces = [&]() {
5999 auto get_extended_crack_faces = [&]() {
6000 auto get_faces_of_crack_front_verts = [&](
auto crack_faces_org) {
6001 ParallelComm *pcomm =
6006 if (!pcomm->rank()) {
6008 auto get_nodes = [&](
auto &&e) {
6011 "get connectivity");
6015 auto get_adj = [&](
auto &&e,
auto dim,
6016 auto t = moab::Interface::UNION) {
6028 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
6031 auto front_block_nodes = get_nodes(front_block_edges);
6035 s = crack_faces.size();
6037 auto crack_face_nodes = get_nodes(crack_faces_org);
6038 auto crack_faces_edges =
6039 get_adj(crack_faces_org, 1, moab::Interface::UNION);
6042 front_block_edges = subtract(front_block_edges, crack_skin);
6043 auto crack_skin_nodes = get_nodes(crack_skin);
6044 crack_skin_nodes.merge(front_block_nodes);
6046 auto crack_skin_faces =
6047 get_adj(crack_skin, 2, moab::Interface::UNION);
6049 subtract(subtract(crack_skin_faces, crack_faces_org), body_skin);
6051 crack_faces = crack_faces_org;
6052 for (
auto f : crack_skin_faces) {
6053 auto edges = intersect(
6054 get_adj(
Range(
f,
f), 1, moab::Interface::UNION), crack_skin);
6058 if (edges.size() == 2) {
6060 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6064 if (edges.size() == 2) {
6065 auto edge_conn = get_nodes(
Range(edges));
6066 auto faces = intersect(get_adj(edges, 2, moab::Interface::UNION),
6068 if (faces.size() == 2) {
6069 auto edge0_conn = get_nodes(
Range(edges[0], edges[0]));
6070 auto edge1_conn = get_nodes(
Range(edges[1], edges[1]));
6071 auto edges_conn = intersect(intersect(edge0_conn, edge1_conn),
6077 moab::Interface::INTERSECT),
6082 if (node_edges.size()) {
6087 auto get_t_dir = [&](
auto e_conn) {
6088 auto other_node = subtract(e_conn,
edges_conn);
6092 t_dir(
i) -= t_v0(
i);
6098 get_t_dir(edge0_conn)(
i) + get_t_dir(edge1_conn)(
i);
6101 t_crack_surface_ave_dir(
i) = 0;
6102 for (
auto e : node_edges) {
6103 auto e_conn = get_nodes(
Range(e, e));
6104 auto t_dir = get_t_dir(e_conn);
6105 t_crack_surface_ave_dir(
i) += t_dir(
i);
6108 auto dot = t_ave_dir(
i) * t_crack_surface_ave_dir(
i);
6111 if (dot < -std::numeric_limits<double>::epsilon()) {
6112 crack_faces.insert(
f);
6115 crack_faces.insert(
f);
6119 }
else if (edges.size() == 3) {
6120 crack_faces.insert(
f);
6124 if (edges.size() == 1) {
6126 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6129 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6130 front_block_edges));
6131 if (edges.size() == 2) {
6132 crack_faces.insert(
f);
6138 crack_faces_org = crack_faces;
6140 }
while (s != crack_faces.size());
6146 return get_faces_of_crack_front_verts(get_crack_faces());
6151 get_extended_crack_faces());
6154 auto reconstruct_crack_faces = [&](
auto crack_faces) {
6155 ParallelComm *pcomm =
6161 Range new_crack_faces;
6162 if (!pcomm->rank()) {
6164 auto get_nodes = [&](
auto &&e) {
6167 "get connectivity");
6171 auto get_adj = [&](
auto &&e,
auto dim,
6172 auto t = moab::Interface::UNION) {
6180 auto get_test_on_crack_surface = [&]() {
6181 auto crack_faces_nodes =
6182 get_nodes(crack_faces);
6183 auto crack_faces_tets =
6184 get_adj(crack_faces_nodes, 3,
6185 moab::Interface::UNION);
6189 auto crack_faces_tets_nodes =
6190 get_nodes(crack_faces_tets);
6191 crack_faces_tets_nodes =
6192 subtract(crack_faces_tets_nodes, crack_faces_nodes);
6194 subtract(crack_faces_tets, get_adj(crack_faces_tets_nodes, 3,
6195 moab::Interface::UNION));
6197 get_adj(crack_faces_tets, 2,
6198 moab::Interface::UNION);
6200 new_crack_faces.merge(crack_faces);
6202 return std::make_tuple(new_crack_faces, crack_faces_tets);
6205 auto carck_faces_test_edges = [&](
auto faces,
auto tets) {
6206 auto adj_tets_faces = get_adj(tets, 2, moab::Interface::UNION);
6207 auto adj_faces_edges = get_adj(subtract(faces, adj_tets_faces), 1,
6208 moab::Interface::UNION);
6209 auto adj_tets_edges = get_adj(tets, 1, moab::Interface::UNION);
6212 adj_faces_edges.merge(geometry_edges);
6213 adj_faces_edges.merge(front_block_edges);
6215 auto boundary_tets_edges = intersect(adj_tets_edges, adj_faces_edges);
6216 auto boundary_test_nodes = get_nodes(boundary_tets_edges);
6217 auto boundary_test_nodes_edges =
6218 get_adj(boundary_test_nodes, 1, moab::Interface::UNION);
6219 auto boundary_test_nodes_edges_nodes = subtract(
6220 get_nodes(boundary_test_nodes_edges), boundary_test_nodes);
6222 boundary_tets_edges =
6223 subtract(boundary_test_nodes_edges,
6224 get_adj(boundary_test_nodes_edges_nodes, 1,
6225 moab::Interface::UNION));
6232 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
6233 body_skin_edges = intersect(get_adj(tets, 1, moab::Interface::UNION),
6235 body_skin = intersect(body_skin, adj_tets_faces);
6236 body_skin_edges = subtract(
6237 body_skin_edges, get_adj(body_skin, 1, moab::Interface::UNION));
6240 for (
auto e : body_skin_edges) {
6241 auto adj_tet = intersect(
6242 get_adj(
Range(e, e), 3, moab::Interface::INTERSECT), tets);
6243 if (adj_tet.size() == 1) {
6244 boundary_tets_edges.insert(e);
6248 return boundary_tets_edges;
6251 auto p = get_test_on_crack_surface();
6252 auto &[new_crack_faces, crack_faces_tets] = p;
6263 auto boundary_tets_edges =
6264 carck_faces_test_edges(new_crack_faces, crack_faces_tets);
6266 boundary_tets_edges);
6268 auto resolve_surface = [&](
auto boundary_tets_edges,
6269 auto crack_faces_tets) {
6270 auto boundary_tets_edges_nodes = get_nodes(boundary_tets_edges);
6271 auto crack_faces_tets_faces =
6272 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6274 Range all_removed_faces;
6275 Range all_removed_tets;
6279 while (size != crack_faces_tets.size()) {
6281 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6285 auto skin_skin_nodes = get_nodes(skin_skin);
6287 size = crack_faces_tets.size();
6289 <<
"Crack faces tets size " << crack_faces_tets.size()
6290 <<
" crack faces size " << crack_faces_tets_faces.size();
6291 auto skin_tets_nodes = subtract(
6292 get_nodes(skin_tets),
6293 boundary_tets_edges_nodes);
6295 skin_tets_nodes = subtract(skin_tets_nodes, skin_skin_nodes);
6297 Range removed_nodes;
6298 Range tets_to_remove;
6299 Range faces_to_remove;
6300 for (
auto n : skin_tets_nodes) {
6302 intersect(get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT),
6304 if (tets.size() == 0) {
6308 auto hole_detetction = [&]() {
6310 get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT);
6315 if (adj_tets.size() == 0) {
6316 return std::make_pair(
6318 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6323 std::vector<Range> tets_groups;
6324 auto test_adj_tets = adj_tets;
6325 while (test_adj_tets.size()) {
6327 Range seed =
Range(test_adj_tets[0], test_adj_tets[0]);
6328 while (seed.size() != seed_size) {
6330 subtract(get_adj(seed, 2, moab::Interface::UNION),
6333 seed_size = seed.size();
6335 intersect(get_adj(adj_faces, 3, moab::Interface::UNION),
6338 tets_groups.push_back(seed);
6339 test_adj_tets = subtract(test_adj_tets, seed);
6341 if (tets_groups.size() == 1) {
6343 return std::make_pair(
6345 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6351 Range tets_to_remove;
6352 Range faces_to_remove;
6353 for (
auto &r : tets_groups) {
6354 auto f = get_adj(r, 2, moab::Interface::UNION);
6355 auto t = intersect(get_adj(
f, 3, moab::Interface::UNION),
6358 if (
f.size() > faces_to_remove.size() ||
6359 faces_to_remove.size() == 0) {
6360 faces_to_remove =
f;
6365 <<
"Hole detection: faces to remove "
6366 << faces_to_remove.size() <<
" tets to remove "
6367 << tets_to_remove.size();
6368 return std::make_pair(faces_to_remove, tets_to_remove);
6371 if (tets.size() < tets_to_remove.size() ||
6372 tets_to_remove.size() == 0) {
6374 auto [h_faces_to_remove, h_tets_to_remove] =
6376 faces_to_remove = h_faces_to_remove;
6377 tets_to_remove = h_tets_to_remove;
6385 all_removed_faces.merge(faces_to_remove);
6386 all_removed_tets.merge(tets_to_remove);
6389 crack_faces_tets = subtract(crack_faces_tets, tets_to_remove);
6390 crack_faces_tets_faces =
6391 subtract(crack_faces_tets_faces, faces_to_remove);
6396 boost::lexical_cast<std::string>(counter) +
".vtk",
6399 "faces_to_remove_" +
6400 boost::lexical_cast<std::string>(counter) +
".vtk",
6404 boost::lexical_cast<std::string>(counter) +
".vtk",
6407 "crack_faces_tets_faces_" +
6408 boost::lexical_cast<std::string>(counter) +
".vtk",
6409 crack_faces_tets_faces);
6411 "crack_faces_tets_" +
6412 boost::lexical_cast<std::string>(counter) +
".vtk",
6418 auto cese_internal_faces = [&]() {
6421 auto adj_faces = get_adj(skin_tets, 2, moab::Interface::UNION);
6423 subtract(adj_faces, skin_tets);
6424 auto adj_tets = get_adj(adj_faces, 3,
6425 moab::Interface::UNION);
6428 subtract(crack_faces_tets,
6431 crack_faces_tets_faces =
6432 subtract(crack_faces_tets_faces, adj_faces);
6434 all_removed_faces.merge(adj_faces);
6435 all_removed_tets.merge(adj_tets);
6439 <<
"Remove internal faces size " << adj_faces.size()
6440 <<
" tets size " << adj_tets.size();
6444 auto case_only_one_free_edge = [&]() {
6447 for (
auto t :
Range(crack_faces_tets)) {
6449 auto adj_faces = get_adj(
6451 moab::Interface::UNION);
6452 auto crack_surface_edges =
6453 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6456 moab::Interface::UNION);
6459 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6460 crack_surface_edges);
6461 adj_edges = subtract(
6463 boundary_tets_edges);
6465 if (adj_edges.size() == 1) {
6467 subtract(crack_faces_tets,
6471 auto faces_to_remove =
6472 get_adj(adj_edges, 2, moab::Interface::UNION);
6475 crack_faces_tets_faces =
6476 subtract(crack_faces_tets_faces, faces_to_remove);
6478 all_removed_faces.merge(faces_to_remove);
6479 all_removed_tets.merge(
Range(
t,
t));
6481 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Remove free one edges ";
6485 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6486 crack_faces_tets_faces =
6487 subtract(crack_faces_tets_faces, all_removed_faces);
6492 auto cese_flat_tet = [&](
auto max_adj_edges) {
6499 auto body_skin_edges =
6500 get_adj(body_skin, 1, moab::Interface::UNION);
6502 for (
auto t :
Range(crack_faces_tets)) {
6504 auto adj_faces = get_adj(
6506 moab::Interface::UNION);
6507 auto crack_surface_edges =
6508 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6511 moab::Interface::UNION);
6514 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6515 crack_surface_edges);
6516 adj_edges = subtract(adj_edges, body_skin_edges);
6518 auto tet_edges = get_adj(
Range(
t,
t), 1,
6519 moab::Interface::UNION);
6521 tet_edges = subtract(tet_edges, adj_edges);
6523 for (
auto e : tet_edges) {
6524 constexpr int opposite_edge[] = {5, 3, 4, 1, 2, 0};
6525 auto get_side = [&](
auto e) {
6526 int side, sense, offset;
6529 "get side number failed");
6532 auto get_side_ent = [&](
auto side) {
6539 adj_edges.erase(get_side_ent(opposite_edge[get_side(e)]));
6542 if (adj_edges.size() <= max_adj_edges) {
6545 Range faces_to_remove;
6546 for (
auto e : adj_edges) {
6547 auto edge_adj_faces =
6548 get_adj(
Range(e, e), 2, moab::Interface::UNION);
6549 edge_adj_faces = intersect(edge_adj_faces, adj_faces);
6550 if (edge_adj_faces.size() != 2) {
6552 "Adj faces size is not 2 for edge " +
6553 boost::lexical_cast<std::string>(e));
6556 auto get_normal = [&](
auto f) {
6560 "get tri normal failed");
6563 auto t_n0 = get_normal(edge_adj_faces[0]);
6564 auto t_n1 = get_normal(edge_adj_faces[1]);
6565 auto get_sense = [&](
auto f) {
6566 int side, sense, offset;
6569 "get side number failed");
6572 auto sense0 = get_sense(edge_adj_faces[0]);
6573 auto sense1 = get_sense(edge_adj_faces[1]);
6578 auto dot_e = (sense0 * sense1) * t_n0(
i) * t_n1(
i);
6579 if (dot_e < dot || e == adj_edges[0]) {
6581 faces_to_remove = edge_adj_faces;
6585 all_removed_faces.merge(faces_to_remove);
6586 all_removed_tets.merge(
Range(
t,
t));
6589 <<
"Remove free edges on flat tet, with considered nb. of "
6591 << adj_edges.size();
6595 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6596 crack_faces_tets_faces =
6597 subtract(crack_faces_tets_faces, all_removed_faces);
6603 "Case only one free edge failed");
6604 for (
auto max_adj_edges : {0, 1, 2, 3}) {
6606 "Case only one free edge failed");
6609 "Case internal faces failed");
6613 "crack_faces_tets_faces_" +
6614 boost::lexical_cast<std::string>(counter) +
".vtk",
6615 crack_faces_tets_faces);
6617 "crack_faces_tets_" +
6618 boost::lexical_cast<std::string>(counter) +
".vtk",
6622 return std::make_tuple(crack_faces_tets_faces, crack_faces_tets,
6623 all_removed_faces, all_removed_tets);
6626 auto [resolved_faces, resolved_tets, all_removed_faces,
6628 resolve_surface(boundary_tets_edges, crack_faces_tets);
6629 resolved_faces.merge(subtract(crack_faces, all_removed_faces));
6637 crack_faces = resolved_faces;
6649 auto resolve_consisten_crack_extension = [&]() {
6651 auto crack_meshset =
6654 auto meshset = crack_meshset->getMeshset();
6658 Range old_crack_faces;
6661 auto extendeded_crack_faces = get_extended_crack_faces();
6662 auto reconstructed_crack_faces =
6663 subtract(reconstruct_crack_faces(extendeded_crack_faces),
6665 if (
nbCrackFaces >= reconstructed_crack_faces.size()) {
6667 <<
"No new crack faces to add, skipping adding to meshset";
6668 extendeded_crack_faces = subtract(
6669 extendeded_crack_faces, subtract(*
crackFaces, old_crack_faces));
6671 <<
"Number crack faces size (extended) "
6672 << extendeded_crack_faces.size();
6678 reconstructed_crack_faces);
6680 <<
"Number crack faces size (reconstructed) "
6681 << reconstructed_crack_faces.size();
6700 CHKERR resolve_consisten_crack_extension();
6713 verts = subtract(verts, conn);
6714 std::vector<double> coords(3 * verts.size());
6716 double def_coords[] = {0., 0., 0.};
6719 "ORG_COORDS", 3, MB_TYPE_DOUBLE, th_org_coords,
6720 MB_TAG_CREAT | MB_TAG_DENSE, def_coords);
6740 auto post_proc_norm_fe =
6741 boost::make_shared<VolumeElementForcesAndSourcesCore>(
mField);
6743 auto post_proc_norm_rule_hook = [](int, int,
int p) ->
int {
6746 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
6748 post_proc_norm_fe->getUserPolynomialBase() =
6751 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
6755 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
6758 CHKERR VecZeroEntries(norms_vec);
6760 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
6761 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
6762 post_proc_norm_fe->getOpPtrVector().push_back(
6764 post_proc_norm_fe->getOpPtrVector().push_back(
6766 post_proc_norm_fe->getOpPtrVector().push_back(
6768 post_proc_norm_fe->getOpPtrVector().push_back(
6770 post_proc_norm_fe->getOpPtrVector().push_back(
6774 auto piola_ptr = boost::make_shared<MatrixDouble>();
6775 post_proc_norm_fe->getOpPtrVector().push_back(
6777 post_proc_norm_fe->getOpPtrVector().push_back(
6781 post_proc_norm_fe->getOpPtrVector().push_back(
6784 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
6786 *post_proc_norm_fe);
6787 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
6789 CHKERR VecAssemblyBegin(norms_vec);
6790 CHKERR VecAssemblyEnd(norms_vec);
6791 const double *norms;
6792 CHKERR VecGetArrayRead(norms_vec, &norms);
6793 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u: " << std::sqrt(norms[U_NORM_L2]);
6794 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
6796 <<
"norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
6798 <<
"norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
6799 CHKERR VecRestoreArrayRead(norms_vec, &norms);
6813 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6814 if (
auto disp_bc = bc.second->dispBcPtr) {
6819 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6820 MOFEM_LOG(
"EP", Sev::noisy) <<
"Displacement BC: " << *disp_bc;
6822 std::vector<double> block_attributes(6, 0.);
6823 if (disp_bc->data.flag1 == 1) {
6824 block_attributes[0] = disp_bc->data.value1;
6825 block_attributes[3] = 1;
6827 if (disp_bc->data.flag2 == 1) {
6828 block_attributes[1] = disp_bc->data.value2;
6829 block_attributes[4] = 1;
6831 if (disp_bc->data.flag3 == 1) {
6832 block_attributes[2] = disp_bc->data.value3;
6833 block_attributes[5] = 1;
6835 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6843 boost::make_shared<NormalDisplacementBcVec>();
6844 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6845 auto block_name =
"(.*)NORMAL_DISPLACEMENT(.*)";
6846 std::regex reg_name(block_name);
6847 if (std::regex_match(bc.first, reg_name)) {
6851 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6853 block_name, bc.second->bcAttributes,
6854 bc.second->bcEnts.subset_by_dimension(2));
6859 boost::make_shared<AnalyticalDisplacementBcVec>();
6861 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6862 auto block_name =
"(.*)ANALYTICAL_DISPLACEMENT(.*)";
6863 std::regex reg_name(block_name);
6864 if (std::regex_match(bc.first, reg_name)) {
6868 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6870 block_name, bc.second->bcAttributes,
6871 bc.second->bcEnts.subset_by_dimension(2));
6875 auto ts_displacement =
6876 boost::make_shared<DynamicRelaxationTimeScale>(
"disp_history.txt");
6879 <<
"Add time scaling displacement BC: " << bc.blockName;
6882 ts_displacement,
"disp_history",
".txt", bc.blockName);
6885 auto ts_normal_displacement =
6886 boost::make_shared<DynamicRelaxationTimeScale>(
"normal_disp_history.txt");
6889 <<
"Add time scaling normal displacement BC: " << bc.blockName;
6892 ts_normal_displacement,
"normal_disp_history",
".txt",
6908 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6909 if (
auto force_bc = bc.second->forceBcPtr) {
6914 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6915 MOFEM_LOG(
"EP", Sev::noisy) <<
"Force BC: " << *force_bc;
6917 std::vector<double> block_attributes(6, 0.);
6918 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
6919 block_attributes[3] = 1;
6920 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
6921 block_attributes[4] = 1;
6922 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
6923 block_attributes[5] = 1;
6924 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6932 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6933 auto block_name =
"(.*)PRESSURE(.*)";
6934 std::regex reg_name(block_name);
6935 if (std::regex_match(bc.first, reg_name)) {
6940 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6942 block_name, bc.second->bcAttributes,
6943 bc.second->bcEnts.subset_by_dimension(2));
6948 boost::make_shared<AnalyticalTractionBcVec>();
6950 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6951 auto block_name =
"(.*)ANALYTICAL_TRACTION(.*)";
6952 std::regex reg_name(block_name);
6953 if (std::regex_match(bc.first, reg_name)) {
6957 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6959 block_name, bc.second->bcAttributes,
6960 bc.second->bcEnts.subset_by_dimension(2));
6965 boost::make_shared<DynamicRelaxationTimeScale>(
"traction_history.txt");
6969 ts_traction,
"traction_history",
".txt", bc.blockName);
6973 boost::make_shared<DynamicRelaxationTimeScale>(
"pressure_history.txt");
6977 ts_pressure,
"pressure_history",
".txt", bc.blockName);
6986 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec> &ext_strain_vec_ptr,
6987 const std::string block_name,
6988 const int nb_attributes) {
6991 std::regex((boost::format(
"%s(.*)") % block_name).str()))
6993 std::vector<double> block_attributes;
6994 CHKERR it->getAttributes(block_attributes);
6995 if (block_attributes.size() < nb_attributes) {
6997 "In block %s expected %d attributes, but given %ld",
6998 it->getName().c_str(), nb_attributes, block_attributes.size());
7001 auto get_block_ents = [&]() {
7007 auto Ents = get_block_ents();
7008 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
7017 auto ts_pre_stretch =
7018 boost::make_shared<DynamicRelaxationTimeScale>(
"externalstrain_history.txt");
7021 <<
"Add time scaling external strain: " << ext_strain_block.blockName;
7024 ts_pre_stretch,
"externalstrain_history",
".txt", ext_strain_block.blockName);
7033 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
7036 CHKERR VecGetLocalSize(
v.second, &size);
7038 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
7039 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( " << low
7040 <<
" " << high <<
" ) ";
7072 MOFEM_LOG(
"EP", Sev::inform) <<
"Calculate crack area";
7074 for (
auto f : crack_faces) {
7077 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
7079 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
7081 if (success != MPI_SUCCESS) {
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.
static auto send_type(MoFEM::Interface &m_field, Range r, const EntityType type)
static auto get_block_meshset(MoFEM::Interface &m_field, const int ms_id, const unsigned int cubit_bc_type)
static auto get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto get_two_sides_of_crack_surface(MoFEM::Interface &m_field, Range crack_faces)
static auto get_range_from_block_map(MoFEM::Interface &m_field, const std::string block_name, int dim)
static auto filter_owners(MoFEM::Interface &m_field, Range skin)
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
static auto get_crack_front_edges(MoFEM::Interface &m_field, Range crack_faces)
Eshelbian plasticity interface.
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define MOFEM_LOG_C(channel, severity, format,...)
#define FTENSOR_INDEX(DIM, I)
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
constexpr int SPACE_DIM
[Define dimension]
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Tensor1< T, Tensor_Dim > normalize()
FieldApproximationBase
approximation base
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
@ USER_BASE
user implemented approximation base
#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
@ HDIV
field with continuous normal traction
#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_OPERATION_UNSUCCESSFUL
@ MOFEM_ATOM_TEST_INVALID
@ MOFEM_DATA_INCONSISTENCY
#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
Order displacement.
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
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
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.
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
PetscErrorCode DMMoFEMGetTsCtx(DM dm, MoFEM::TsCtx **ts_ctx)
get MoFEM::TsCtx data structure
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
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
auto createDMVector(DM dm)
Get smart vector from DM.
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
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
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.
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_adjacency_table(const std::string &fe_name, const EntityType type, ElementAdjacencyFunct function)=0
modify finite element table, only for advanced user
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
#define MOFEM_LOG_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 addMeshset(const CubitBCType cubit_bc_type, const int ms_id, const std::string name="")
Add CUBIT meshset to manager.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
MoFEMErrorCode pushMarkDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true)
Mark DOFs on block entities for boundary conditions.
#define NBVOLUMETET_L2(P)
Number of base functions on tetrahedron for L2 space.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
implementation of Data Operators for Forces and Sources
PetscErrorCode TsMonitorSet(TS ts, PetscInt step, PetscReal t, Vec u, void *ctx)
Set monitor for TS solver.
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
MoFEMErrorCode MoFEMSNESMonitorEnergy(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
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)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
PostProcBrokenMeshInMoabBaseEndImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseEnd
Enable to run stack of post-processing elements. Use this to end stack.
PostProcBrokenMeshInMoabBaseBeginImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseBegin
Enable to run stack of post-processing elements. Use this to begin stack.
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
static constexpr int edges_conn[]
auto ent_form_type_and_id(const EntityType type, const EntityID id)
get entity handle from type and id
constexpr IntegrationType I
constexpr AssemblyType A
[Define dimension]
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
constexpr double t
plate stiffness
constexpr auto field_name
#define QUAD_2D_TABLE_SIZE
#define QUAD_3D_TABLE_SIZE
static QUAD *const QUAD_2D_TABLE[]
static QUAD *const QUAD_3D_TABLE[]
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
FTensor::Index< 'm', 3 > m
CGG User Polynomial Base.
static boost::shared_ptr< SetUpSchur > createSetUpSchur(MoFEM::Interface &m_field, EshelbianCore *ep_core_ptr)
MoFEMErrorCode setElasticElementOps(const int tag)
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
MoFEMErrorCode addVolumeFiniteElement(const EntityHandle meshset=0)
MoFEMErrorCode addFields(const EntityHandle meshset=0)
static enum StretchSelector stretchSelector
boost::shared_ptr< Range > frontAdjEdges
MoFEMErrorCode createCrackSurfaceMeshset()
MoFEMErrorCode addBoundaryFiniteElement(const EntityHandle meshset=0)
const std::string skeletonElement
static double inv_f_linear(const double v)
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
boost::shared_ptr< Range > contactFaces
static double dd_f_log_e_quadratic(const double v)
static double dd_f_log(const double v)
BitRefLevel bitAdjEnt
bit ref level for parent
static boost::function< double(const double)> inv_dd_f
MoFEM::Interface & mField
const std::string spatialL2Disp
static double inv_d_f_log(const double v)
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static PetscBool l2UserBaseScale
SmartPetscObj< DM > dM
Coupled problem all fields.
static int internalStressInterpOrder
MoFEMErrorCode projectGeometry(const EntityHandle meshset=0)
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
const std::string materialH1Positions
static int nbJIntegralContours
MoFEMErrorCode setBlockTagsOnSkin()
static PetscBool crackingOn
MoFEMErrorCode getTractionFreeBc(const EntityHandle meshset, boost::shared_ptr< TractionFreeBc > &bc_ptr, const std::string contact_set_name)
Remove all, but entities where kinematic constrains are applied.
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, SmartPetscObj< Vec > ver_vec, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe)
MoFEMErrorCode calculateFaceMaterialForce(const int tag, TS ts)
static double griffithEnergy
Griffith energy.
MoFEMErrorCode calculateCrackArea(boost::shared_ptr< double > area_ptr)
const std::string elementVolumeName
static double dd_f_log_e(const double v)
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
MoFEMErrorCode getBc(boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
CommInterface::EntitiesPetscVector vertexExchange
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
boost::shared_ptr< Range > maxMovedFaces
static PetscBool dynamicRelaxation
const std::string spatialH1Disp
MoFEMErrorCode solveElastic(TS ts, Vec x)
static double d_f_log(const double v)
boost::shared_ptr< NormalDisplacementBcVec > bcSpatialNormalDisplacementVecPtr
static double crackingStartTime
MoFEMErrorCode getOptions()
const std::string piolaStress
MoFEMErrorCode setElasticElementToTs(DM dm)
static double inv_d_f_log_e(const double v)
int contactRefinementLevels
MoFEMErrorCode gettingNorms()
[Getting norms]
MoFEMErrorCode setVolumeElementOps(const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Getting interface of core database.
const std::string bubbleField
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
MoFEMErrorCode calculateOrientation(const int tag, bool set_orientation)
static double inv_f_log(const double v)
static PetscBool noStretch
MoFEMErrorCode setNewFrontCoordinates()
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
static double exponentBase
MoFEMErrorCode setContactElementRhsOps(boost::shared_ptr< ContactTree > &fe_contact_tree)
static double dd_f_linear(const double v)
MoFEMErrorCode setFaceElementOps(const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
boost::shared_ptr< Range > skeletonFaces
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
static double inv_d_f_linear(const double v)
BitRefLevel bitAdjParentMask
bit ref level for parent parent
MoFEMErrorCode solveDynamicRelaxation(TS ts, Vec x, int start_step, double start_time)
Solve problem using dynamic relaxation method.
static double inv_dd_f_log(const double v)
const std::string contactDisp
static std::string internalStressTagName
static enum SymmetrySelector symmetrySelector
CommInterface::EntitiesPetscVector edgeExchange
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
static boost::function< double(const double)> f
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
const std::string skinElement
static PetscBool internalStressVoigt
static double inv_dd_f_linear(const double v)
static double inv_dd_f_log_e(const double v)
MoFEMErrorCode getExternalStrain()
MoFEMErrorCode getSpatialTractionBc()
static PetscBool setSingularity
static double d_f_log_e(const double v)
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
static double f_log_e_quadratic(const double v)
MoFEMErrorCode addCrackSurfaces(const bool debug=false)
MoFEMErrorCode addDMs(const BitRefLevel bit=BitRefLevel().set(0), const EntityHandle meshset=0)
MoFEMErrorCode getSpatialDispBc()
[Getting norms]
BitRefLevel bitAdjParent
bit ref level for parent
MoFEMErrorCode postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
static double d_f_log_e_quadratic(const double v)
CommInterface::EntitiesPetscVector volumeExchange
MoFEMErrorCode saveOrgCoords()
const std::string naturalBcElement
static boost::function< double(const double)> dd_f
static double f_log_e(const double v)
static int addCrackMeshsetId
static double inv_f_log_e(const double v)
MoFEMErrorCode createExchangeVectors(Sev sev)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > crackFaces
static boost::function< double(const double)> d_f
boost::shared_ptr< Range > frontVertices
static enum EnergyReleaseSelector energyReleaseSelector
static boost::function< double(const double)> inv_d_f
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
static double d_f_linear(const double v)
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
static double f_log(const double v)
CommInterface::EntitiesPetscVector faceExchange
SmartPetscObj< DM > dmElastic
Elastic problem.
EshelbianCore(MoFEM::Interface &m_field)
boost::shared_ptr< Range > frontEdges
static boost::function< double(const double)> inv_f
const std::string stretchTensor
BitRefLevel bitAdjEntMask
bit ref level for parent parent
static double f_linear(const double v)
const std::string contactElement
AnalyticalDisplacementBc(std::string name, std::vector< double > attr, Range faces)
AnalyticalTractionBc(std::string name, std::vector< double > attr, Range faces)
BcRot(std::string name, std::vector< double > attr, Range faces)
ExternalStrain(std::string name, std::vector< double > attr, Range ents)
int operator()(int p_row, int p_col, int p_data) const
NormalDisplacementBc(std::string name, std::vector< double > attr, Range faces)
PressureBc(std::string name, std::vector< double > attr, Range faces)
boost::shared_ptr< Range > frontNodes
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges)
boost::shared_ptr< Range > frontEdges
boost::function< int(int)> FunRule
SetIntegrationAtFrontFace(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges, FunRule fun_rule)
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
static std::map< long int, MatrixDouble > mapRefCoords
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
boost::shared_ptr< Range > frontNodes
static std::map< long int, MatrixDouble > mapRefCoords
SetIntegrationAtFrontVolume(boost::shared_ptr< Range > front_nodes, boost::shared_ptr< Range > front_edges)
boost::shared_ptr< Range > frontEdges
TractionBc(std::string name, std::vector< double > attr, Range faces)
Set integration rule on element.
int operator()(int p_row, int p_col, int p_data) const
static auto setup(EshelbianCore *ep_ptr, TS ts, Vec x, bool set_ts_monitor)
static auto exp(A &&t_w_vee, B &&theta)
multi_index_container< DofsSideMapData, indexed_by< ordered_non_unique< tag< TypeSide_mi_tag >, composite_key< DofsSideMapData, member< DofsSideMapData, EntityType, &DofsSideMapData::type >, member< DofsSideMapData, int, &DofsSideMapData::side > > >, ordered_unique< tag< EntDofIdx_mi_tag >, member< DofsSideMapData, int, &DofsSideMapData::dof > > > > DofsSideMap
Map entity stype and side to element/entity dof index.
Boundary condition manager for finite element problem setup.
static std::pair< std::string, std::string > extractStringFromBlockId(const std::string block_id, const std::string prb_name)
Extract block name and block name from block id.
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
static Range getPartEntities(moab::Interface &moab, int part)
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, int dim, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0)
Create a ghost vector for exchanging data.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode add_broken_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const std::vector< std::pair< EntityType, std::function< MoFEMErrorCode(BaseFunction::DofsSideMap &)> > > list_dof_side_map, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual bool check_finite_element(const std::string &name) const =0
Check if finite element is in database.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Definition of the displacement bc data structure.
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.
default operator for TRI element
Field data structure for finite element approximation.
Definition of the force bc data structure.
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
MatrixDouble gaussPts
Matrix of integration points.
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.
Mesh refinement interface.
Interface for managing meshsets containing materials and boundary conditions.
Natural boundary conditions.
Operator for broken loop side.
Get norm of input MatrixDouble for Tensor1.
Get norm of input MatrixDouble for Tensor2.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate divergence of tonsorial field using vectorial base.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Calculate trace of vector (Hdiv/Hcurl) space.
Calculate symmetric tensor field rates ant integratio pts.
Calculate symmetric tensor field values at integration pts.
Get field gradients time derivative at integration pts for scalar field rank 0, i....
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Approximate field values for given petsc vector.
Specialization for double precision vector field values calculation.
Element used to execute operators on side of the element.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
Template struct for dimension-specific finite element types.
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
intrusive_ptr for managing petsc objects
FEMethodsSequence & getLoopsMonitor()
Get the loops to do Monitor object.
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
default operator for TET element
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Apply rotation boundary condition.
static MoFEMErrorCode postStepInitialise(EshelbianCore *ep_ptr)
static MoFEMErrorCode postStepDestroy()
static MoFEMErrorCode preStepFun(TS ts)
static MoFEMErrorCode postStepFun(TS ts)
BoundaryEle::UserDataOperator BdyEleOp
ElementsAndOps< SPACE_DIM >::SideEle SideEle