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"
48 using VolumeElementForcesAndSourcesCore::UserDataOperator::UserDataOperator;
52 using FaceElementForcesAndSourcesCore::UserDataOperator::UserDataOperator;
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 = 4;
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 = 4;
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 char tag_name[255] =
"";
998 CHKERR PetscOptionsString(
"-internal_stress_tag_name",
999 "internal stress tag name",
"",
"", tag_name, 255,
1003 "-internal_stress_interp_order",
"internal stress interpolation order",
1005 CHKERR PetscOptionsBool(
"-internal_stress_voigt",
"Voigt index notation",
"",
1010 analytical_expr_file_name, 255, PETSC_NULLPTR);
1016 "Unsupported internal stress interpolation order %d",
1029 static_cast<EnergyReleaseSelector
>(choice_release);
1032 case StretchSelector::LINEAR:
1040 case StretchSelector::LOG:
1042 std::numeric_limits<float>::epsilon()) {
1058 case StretchSelector::LOG_QUADRATIC:
1064 "No logarithmic quadratic stretch for this case");
1080 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaU: -viscosity_alpha_u " <<
alphaU;
1081 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaW: -viscosity_alpha_w " <<
alphaW;
1083 <<
"alphaOmega: -viscosity_alpha_omega " <<
alphaOmega;
1087 MOFEM_LOG(
"EP", Sev::inform) <<
"Gradient of deformation "
1095 MOFEM_LOG(
"EP", Sev::inform) <<
"Base exponent e";
1097 <<
"Stretch: -stretches " << list_stretches[choice_stretch];
1123 <<
"Energy release variant: -energy_release_variant "
1126 <<
"Number of J integral levels: -nb_J_integral_levels "
1129#ifdef ENABLE_PYTHON_BINDING
1130 auto file_exists = [](std::string myfile) {
1131 std::ifstream file(myfile.c_str());
1138 if (file_exists(analytical_expr_file_name)) {
1139 MOFEM_LOG(
"EP", Sev::inform) << analytical_expr_file_name <<
" file found";
1143 analytical_expr_file_name);
1147 << analytical_expr_file_name <<
" file NOT found";
1160 auto get_tets = [&]() {
1166 auto get_tets_skin = [&]() {
1167 Range tets_skin_part;
1169 CHKERR skin.find_skin(0, get_tets(),
false, tets_skin_part);
1170 ParallelComm *pcomm =
1173 CHKERR pcomm->filter_pstatus(tets_skin_part,
1174 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1175 PSTATUS_NOT, -1, &tets_skin);
1179 auto subtract_boundary_conditions = [&](
auto &&tets_skin) {
1185 tets_skin = subtract(tets_skin,
v.faces);
1189 tets_skin = subtract(tets_skin,
v.faces);
1194 tets_skin = subtract(tets_skin,
v.faces);
1200 auto add_blockset = [&](
auto block_name,
auto &&tets_skin) {
1203 tets_skin.merge(crack_faces);
1207 auto subtract_blockset = [&](
auto block_name,
auto &&tets_skin) {
1208 auto contact_range =
1210 tets_skin = subtract(tets_skin, contact_range);
1214 auto get_stress_trace_faces = [&](
auto &&tets_skin) {
1217 faces, moab::Interface::UNION);
1218 Range trace_faces = subtract(faces, tets_skin);
1222 auto tets = get_tets();
1226 auto trace_faces = get_stress_trace_faces(
1228 subtract_blockset(
"CONTACT",
1229 subtract_boundary_conditions(get_tets_skin()))
1236 boost::make_shared<Range>(subtract(trace_faces, *
contactFaces));
1256 auto add_broken_hdiv_field = [
this, meshset](
const std::string
field_name,
1262 auto get_side_map_hdiv = [&]() {
1265 std::pair<EntityType,
1280 get_side_map_hdiv(), MB_TAG_DENSE,
MF_ZERO);
1286 auto add_l2_field = [
this, meshset](
const std::string
field_name,
1287 const int order,
const int dim) {
1296 auto add_h1_field = [
this, meshset](
const std::string
field_name,
1297 const int order,
const int dim) {
1309 auto add_l2_field_by_range = [
this](
const std::string
field_name,
1310 const int order,
const int dim,
1311 const int field_dim,
Range &&r) {
1321 auto add_bubble_field = [
this, meshset](
const std::string
field_name,
1322 const int order,
const int dim) {
1328 auto field_order_table =
1329 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1330 auto get_cgg_bubble_order_zero = [](
int p) {
return 0; };
1331 auto get_cgg_bubble_order_tet = [](
int p) {
1334 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1335 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1336 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1337 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1344 auto add_user_l2_field = [
this, meshset](
const std::string
field_name,
1345 const int order,
const int dim) {
1351 auto field_order_table =
1352 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1353 auto zero_dofs = [](
int p) {
return 0; };
1355 field_order_table[MBVERTEX] = zero_dofs;
1356 field_order_table[MBEDGE] = zero_dofs;
1357 field_order_table[MBTRI] = zero_dofs;
1358 field_order_table[MBTET] = dof_l2_tet;
1376 auto get_hybridised_disp = [&]() {
1378 auto skin = subtract_boundary_conditions(get_tets_skin());
1380 faces.merge(intersect(bc.faces, skin));
1386 get_hybridised_disp());
1412 auto project_ho_geometry = [&](
auto field) {
1418 auto get_adj_front_edges = [&](
auto &front_edges) {
1419 Range front_crack_nodes;
1420 Range crack_front_edges_with_both_nodes_not_at_front;
1424 CHKERR moab.get_connectivity(front_edges, front_crack_nodes,
true);
1425 Range crack_front_edges;
1427 crack_front_edges, moab::Interface::UNION);
1428 crack_front_edges_with_both_nodes_not_at_front =
1429 subtract(crack_front_edges, front_edges);
1433 crack_front_edges_with_both_nodes_not_at_front =
send_type(
1434 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1436 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1437 boost::make_shared<Range>(
1438 crack_front_edges_with_both_nodes_not_at_front));
1445 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*
frontEdges);
1456 (boost::format(
"crack_faces_%d.vtk") % rank).str(),
1459 (boost::format(
"front_edges_%d.vtk") % rank).str(),
1470 auto set_singular_dofs = [&](
auto &front_adj_edges,
auto &front_vertices) {
1478 MOFEM_LOG(
"EP", Sev::inform) <<
"Singularity eps " << beta;
1481 for (
auto edge : front_adj_edges) {
1484 CHKERR moab.get_connectivity(edge, conn, num_nodes,
false);
1486 CHKERR moab.get_coords(conn, num_nodes, coords);
1487 const double dir[3] = {coords[3] - coords[0], coords[4] - coords[1],
1488 coords[5] - coords[2]};
1489 double dof[3] = {0, 0, 0};
1490 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1491 for (
int dd = 0; dd != 3; dd++) {
1492 dof[dd] = -dir[dd] *
eps;
1494 }
else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1495 for (
int dd = 0; dd != 3; dd++) {
1496 dof[dd] = +dir[dd] *
eps;
1501 const int idx = dit->get()->getEntDofIdx();
1503 dit->get()->getFieldData() = 0;
1505 dit->get()->getFieldData() = dof[idx];
1524 auto add_field_to_fe = [
this](
const std::string fe,
1589 auto set_fe_adjacency = [&](
auto fe_name) {
1592 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
1600 auto add_field_to_fe = [
this](
const std::string fe,
1612 Range natural_bc_elements;
1615 natural_bc_elements.merge(
v.faces);
1620 natural_bc_elements.merge(
v.faces);
1625 natural_bc_elements.merge(
v.faces);
1630 natural_bc_elements.merge(
v.faces);
1635 natural_bc_elements.merge(
v.faces);
1640 natural_bc_elements.merge(
v.faces);
1645 natural_bc_elements.merge(
v.faces);
1648 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
1659 auto get_skin = [&](
auto &body_ents) {
1662 CHKERR skin.find_skin(0, body_ents,
false, skin_ents);
1667 Range boundary_ents;
1668 ParallelComm *pcomm =
1670 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1671 PSTATUS_NOT, -1, &boundary_ents);
1672 return boundary_ents;
1806 auto remove_dofs_on_broken_skin = [&](
const std::string prb_name) {
1808 for (
int d : {0, 1, 2}) {
1809 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
1811 ->getSideDofsOnBrokenSpaceEntities(
1822 CHKERR remove_dofs_on_broken_skin(
"ESHELBY_PLASTICITY");
1858 auto set_zero_block = [&]() {
1890 auto set_section = [&]() {
1892 PetscSection section;
1897 CHKERR PetscSectionDestroy(§ion);
1920BcDisp::BcDisp(std::string name, std::vector<double> attr,
Range faces)
1921 : blockName(name), faces(faces) {
1922 vals.resize(3,
false);
1923 flags.resize(3,
false);
1924 for (
int ii = 0; ii != 3; ++ii) {
1925 vals[ii] = attr[ii];
1926 flags[ii] =
static_cast<int>(attr[ii + 3]);
1929 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp " << name;
1931 <<
"Add BCDisp vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
1933 <<
"Add BCDisp flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
1934 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp nb. of faces " <<
faces.size();
1938 : blockName(name), faces(faces) {
1939 vals.resize(attr.size(),
false);
1940 for (
int ii = 0; ii != attr.size(); ++ii) {
1941 vals[ii] = attr[ii];
1947 : blockName(name), faces(faces) {
1948 vals.resize(3,
false);
1949 flags.resize(3,
false);
1950 for (
int ii = 0; ii != 3; ++ii) {
1951 vals[ii] = attr[ii];
1952 flags[ii] =
static_cast<int>(attr[ii + 3]);
1955 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce " << name;
1957 <<
"Add BCForce vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
1959 <<
"Add BCForce flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
1960 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce nb. of faces " <<
faces.size();
1964 std::vector<double> attr,
1966 : blockName(name), faces(faces) {
1969 if (attr.size() < 1) {
1971 "Wrong size of normal displacement BC");
1976 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc " << name;
1977 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc val " <<
val;
1979 <<
"Add NormalDisplacementBc nb. of faces " <<
faces.size();
1983 : blockName(name), faces(faces) {
1986 if (attr.size() < 1) {
1988 "Wrong size of normal displacement BC");
1993 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc " << name;
1994 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc val " <<
val;
1996 <<
"Add PressureBc nb. of faces " <<
faces.size();
2002 : blockName(name), ents(ents) {
2005 if (attr.size() < 2) {
2007 "Wrong size of external strain attribute");
2013 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain " << name;
2014 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain val " <<
val;
2015 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain bulk modulus K "
2018 <<
"Add ExternalStrain nb. of tets " <<
ents.size();
2024 std::vector<double> attr,
2026 : blockName(name), faces(faces) {
2029 if (attr.size() < 3) {
2031 "Wrong size of analytical displacement BC");
2034 flags.resize(3,
false);
2035 for (
int ii = 0; ii != 3; ++ii) {
2036 flags[ii] = attr[ii];
2039 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalDisplacementBc " << name;
2041 <<
"Add AnalyticalDisplacementBc flags " <<
flags[0] <<
" " <<
flags[1]
2044 <<
"Add AnalyticalDisplacementBc nb. of faces " <<
faces.size();
2048 std::vector<double> attr,
2050 : blockName(name), faces(faces) {
2053 if (attr.size() < 3) {
2055 "Wrong size of analytical traction BC");
2058 flags.resize(3,
false);
2059 for (
int ii = 0; ii != 3; ++ii) {
2060 flags[ii] = attr[ii];
2063 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalTractionBc " << name;
2065 <<
"Add AnalyticalTractionBc flags " <<
flags[0] <<
" " <<
flags[1]
2068 <<
"Add AnalyticalTractionBc nb. of faces " <<
faces.size();
2074 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2075 const std::string contact_set_name) {
2080 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2081 Range tets_skin_part;
2082 Skinner skin(&mField.get_moab());
2083 CHKERR skin.find_skin(0, tets,
false, tets_skin_part);
2084 ParallelComm *pcomm =
2087 CHKERR pcomm->filter_pstatus(tets_skin_part,
2088 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2089 PSTATUS_NOT, -1, &tets_skin);
2092 for (
int dd = 0; dd != 3; ++dd)
2093 (*bc_ptr)[dd] = tets_skin;
2096 if (bcSpatialDispVecPtr)
2097 for (
auto &
v : *bcSpatialDispVecPtr) {
2099 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2101 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2103 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2107 if (bcSpatialRotationVecPtr)
2108 for (
auto &
v : *bcSpatialRotationVecPtr) {
2109 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2110 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2111 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2114 if (bcSpatialNormalDisplacementVecPtr)
2115 for (
auto &
v : *bcSpatialNormalDisplacementVecPtr) {
2116 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2117 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2118 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2121 if (bcSpatialAnalyticalDisplacementVecPtr)
2122 for (
auto &
v : *bcSpatialAnalyticalDisplacementVecPtr) {
2124 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2126 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2128 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2131 if (bcSpatialTractionVecPtr)
2132 for (
auto &
v : *bcSpatialTractionVecPtr) {
2133 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2134 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2135 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2138 if (bcSpatialAnalyticalTractionVecPtr)
2139 for (
auto &
v : *bcSpatialAnalyticalTractionVecPtr) {
2140 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2141 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2142 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2145 if (bcSpatialPressureVecPtr)
2146 for (
auto &
v : *bcSpatialPressureVecPtr) {
2147 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2148 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2149 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2154 std::regex((boost::format(
"%s(.*)") % contact_set_name).str()))) {
2156 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2158 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2159 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2160 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2177 return 2 * p_data + 1;
2183 return 2 * (p_data + 1);
2188 boost::shared_ptr<CachePhi> cache_phi_otr)
2192 boost::typeindex::type_index type_index,
2200 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
2205 int nb_gauss_pts = pts.size2();
2206 if (!nb_gauss_pts) {
2210 if (pts.size1() < 3) {
2212 "Wrong dimension of pts, should be at least 3 rows with "
2216 const auto base = this->cTx->bAse;
2219 switch (this->cTx->sPace) {
2224 data.
dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 4,
false);
2227 &pts(0, 0), &pts(1, 0), &pts(2, 0), nb_gauss_pts);
2228 data.
dataOnEntities[MBVERTEX][0].getDiffN(base).resize(4, 3,
false);
2232 CHKERR getValueL2AinsworthBase(pts);
2248 "Wrong base, should be USER_BASE");
2256 const int nb_gauss_pts = pts.size2();
2258 auto check_cache = [
this](
int order,
int nb_gauss_pts) ->
bool {
2267 if (check_cache(
order, nb_gauss_pts)) {
2270 phi.resize(mat.size1(), mat.size2(),
false);
2275 shapeFun.resize(nb_gauss_pts, 4,
false);
2277 &pts(2, 0), nb_gauss_pts);
2279 double diff_shape_fun[12];
2285 phi.resize(nb_gauss_pts, 9 * nb_base_functions,
false);
2308 const int tag,
const bool do_rhs,
const bool do_lhs,
const bool calc_rates,
2310 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe) {
2314 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0,
MatrixDouble());
2315 fe->getUserPolynomialBase() =
2316 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2317 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2318 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2321 fe->getRuleHook = [](int, int, int) {
return -1; };
2322 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges);
2328 dataAtPts->physicsPtr = physicalEquations;
2333 piolaStress, dataAtPts->getApproxPAtPts()));
2335 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2337 piolaStress, dataAtPts->getDivPAtPts()));
2340 fe->getOpPtrVector().push_back(
2341 physicalEquations->returnOpCalculateStretchFromStress(
2342 dataAtPts, physicalEquations));
2344 fe->getOpPtrVector().push_back(
2346 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2350 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
2352 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
2354 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
2358 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
2360 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
2365 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
2368 fe->getOpPtrVector().push_back(
2370 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
2371 fe->getOpPtrVector().push_back(
2373 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
2377 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
2379 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
2382 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
2384 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
2391 piolaStress, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2394 bubbleField, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2395 var_vec, MBMAXTYPE));
2397 rotAxis, dataAtPts->getVarRotAxisPts(), var_vec, MBTET));
2399 piolaStress, dataAtPts->getDivVarPiolaPts(), var_vec));
2401 spatialL2Disp, dataAtPts->getVarWL2Pts(), var_vec, MBTET));
2404 fe->getOpPtrVector().push_back(
2405 physicalEquations->returnOpCalculateVarStretchFromStress(
2406 dataAtPts, physicalEquations));
2408 fe->getOpPtrVector().push_back(
2410 stretchTensor, dataAtPts->getVarLogStreachPts(), var_vec, MBTET));
2416 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
2421 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
2422 tag, do_rhs, do_lhs, dataAtPts, physicalEquations));
2429 const int tag,
const bool add_elastic,
const bool add_material,
2430 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
2431 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
2435 auto get_body_range = [
this](
auto name,
int dim) {
2436 std::map<int, Range> map;
2439 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2441 (boost::format(
"%s(.*)") % name).str()
2447 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
2450 map[m_ptr->getMeshsetId()] = ents;
2456 auto rule_contact = [](int, int,
int o) {
return -1; };
2459 auto set_rule_contact = [refine](
2462 int order_col,
int order_data
2466 auto rule = 2 * order_data;
2472 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2479 fe_rhs->getOpPtrVector().push_back(
2481 fe_rhs->getOpPtrVector().push_back(
2486 if (!internalStressTagName.empty()) {
2487 switch (internalStressInterpOrder) {
2489 fe_rhs->getOpPtrVector().push_back(
2493 fe_rhs->getOpPtrVector().push_back(
2498 "Unsupported internal stress interpolation order %d",
2499 internalStressInterpOrder);
2501 if (internalStressVoigt) {
2502 fe_rhs->getOpPtrVector().push_back(
2506 fe_rhs->getOpPtrVector().push_back(
2511 if (
auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
2512 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap)) {
2513 fe_rhs->getOpPtrVector().push_back(op);
2514 }
else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
2516 "OpSpatialPhysicalExternalStrain not implemented for this "
2520 fe_rhs->getOpPtrVector().push_back(
2521 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
2524 fe_rhs->getOpPtrVector().push_back(
2526 fe_rhs->getOpPtrVector().push_back(
2528 fe_rhs->getOpPtrVector().push_back(
2531 auto set_hybridisation = [&](
auto &pip) {
2538 using SideEleOp = EleOnSide::UserDataOperator;
2539 using BdyEleOp = BoundaryEle::UserDataOperator;
2544 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2546 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2549 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2550 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2552 CHKERR EshelbianPlasticity::
2553 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2554 op_loop_skeleton_side->getOpPtrVector(), {L2},
2555 materialH1Positions, frontAdjEdges);
2559 auto broken_data_ptr =
2560 boost::make_shared<std::vector<BrokenBaseSideData>>();
2563 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2564 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2565 boost::make_shared<CGGUserPolynomialBase>();
2567 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2568 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2569 materialH1Positions, frontAdjEdges);
2570 op_loop_domain_side->getOpPtrVector().push_back(
2572 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
2573 op_loop_domain_side->getOpPtrVector().push_back(
2576 op_loop_domain_side->getOpPtrVector().push_back(
2580 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2582 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
2584 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2585 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dHybrid(
2586 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
2587 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2588 op_loop_skeleton_side->getOpPtrVector().push_back(
2591 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dBroken(
2592 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
2595 pip.push_back(op_loop_skeleton_side);
2600 auto set_contact = [&](
auto &pip) {
2607 using SideEleOp = EleOnSide::UserDataOperator;
2608 using BdyEleOp = BoundaryEle::UserDataOperator;
2613 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2615 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2616 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2617 CHKERR EshelbianPlasticity::
2618 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2619 op_loop_skeleton_side->getOpPtrVector(), {L2},
2620 materialH1Positions, frontAdjEdges);
2624 auto broken_data_ptr =
2625 boost::make_shared<std::vector<BrokenBaseSideData>>();
2628 auto contact_common_data_ptr =
2629 boost::make_shared<ContactOps::CommonData>();
2631 auto add_ops_domain_side = [&](
auto &pip) {
2635 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2636 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2637 boost::make_shared<CGGUserPolynomialBase>();
2639 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2640 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2641 materialH1Positions, frontAdjEdges);
2642 op_loop_domain_side->getOpPtrVector().push_back(
2645 op_loop_domain_side->getOpPtrVector().push_back(
2647 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2648 pip.push_back(op_loop_domain_side);
2652 auto add_ops_contact_rhs = [&](
auto &pip) {
2655 auto contact_sfd_map_range_ptr =
2656 boost::make_shared<std::map<int, Range>>(
2657 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2660 contactDisp, contact_common_data_ptr->contactDispPtr()));
2661 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2664 pip.push_back(
new OpTreeSearch(
2665 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2669 contactDisp, contact_common_data_ptr, contactTreeRhs,
2670 contact_sfd_map_range_ptr));
2673 broken_data_ptr, contact_common_data_ptr, contactTreeRhs));
2679 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2680 CHKERR add_ops_contact_rhs(op_loop_skeleton_side->getOpPtrVector());
2683 pip.push_back(op_loop_skeleton_side);
2688 CHKERR set_hybridisation(fe_rhs->getOpPtrVector());
2689 CHKERR set_contact(fe_rhs->getOpPtrVector());
2692 using BodyNaturalBC =
2694 Assembly<PETSC>::LinearForm<
GAUSS>;
2696 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
2698 auto body_time_scale =
2699 boost::make_shared<DynamicRelaxationTimeScale>(
"body_force.txt");
2700 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
2701 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
2702 "BODY_FORCE", Sev::inform);
2706 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2714 fe_lhs->getOpPtrVector().push_back(
2717 bubbleField, piolaStress, dataAtPts));
2718 fe_lhs->getOpPtrVector().push_back(
2722 fe_lhs->getOpPtrVector().push_back(
2723 physicalEquations->returnOpSpatialPhysical_du_du(
2724 stretchTensor, stretchTensor, dataAtPts, alphaU));
2726 stretchTensor, piolaStress, dataAtPts,
true));
2728 stretchTensor, bubbleField, dataAtPts,
true));
2730 stretchTensor, rotAxis, dataAtPts,
2731 symmetrySelector ==
SYMMETRIC ?
true :
false));
2735 spatialL2Disp, piolaStress, dataAtPts,
true));
2737 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
2740 piolaStress, rotAxis, dataAtPts,
2741 symmetrySelector ==
SYMMETRIC ?
true :
false));
2743 bubbleField, rotAxis, dataAtPts,
2744 symmetrySelector ==
SYMMETRIC ?
true :
false));
2749 rotAxis, stretchTensor, dataAtPts,
false));
2752 rotAxis, piolaStress, dataAtPts,
false));
2754 rotAxis, bubbleField, dataAtPts,
false));
2757 rotAxis, rotAxis, dataAtPts, alphaOmega));
2763 auto set_hybridisation = [&](
auto &pip) {
2770 using SideEleOp = EleOnSide::UserDataOperator;
2771 using BdyEleOp = BoundaryEle::UserDataOperator;
2776 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2778 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2781 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2782 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2783 CHKERR EshelbianPlasticity::
2784 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2785 op_loop_skeleton_side->getOpPtrVector(), {L2},
2786 materialH1Positions, frontAdjEdges);
2790 auto broken_data_ptr =
2791 boost::make_shared<std::vector<BrokenBaseSideData>>();
2794 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2795 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2796 boost::make_shared<CGGUserPolynomialBase>();
2798 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2799 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2800 materialH1Positions, frontAdjEdges);
2801 op_loop_domain_side->getOpPtrVector().push_back(
2804 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2806 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
2807 op_loop_skeleton_side->getOpPtrVector().push_back(
2808 new OpC(hybridSpatialDisp, broken_data_ptr,
2809 boost::make_shared<double>(1.0),
true,
false));
2811 pip.push_back(op_loop_skeleton_side);
2816 auto set_contact = [&](
auto &pip) {
2823 using SideEleOp = EleOnSide::UserDataOperator;
2824 using BdyEleOp = BoundaryEle::UserDataOperator;
2829 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2831 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2832 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2833 CHKERR EshelbianPlasticity::
2834 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2835 op_loop_skeleton_side->getOpPtrVector(), {L2},
2836 materialH1Positions, frontAdjEdges);
2840 auto broken_data_ptr =
2841 boost::make_shared<std::vector<BrokenBaseSideData>>();
2844 auto contact_common_data_ptr =
2845 boost::make_shared<ContactOps::CommonData>();
2847 auto add_ops_domain_side = [&](
auto &pip) {
2851 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2852 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2853 boost::make_shared<CGGUserPolynomialBase>();
2855 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2856 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2857 materialH1Positions, frontAdjEdges);
2858 op_loop_domain_side->getOpPtrVector().push_back(
2861 op_loop_domain_side->getOpPtrVector().push_back(
2863 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2864 pip.push_back(op_loop_domain_side);
2868 auto add_ops_contact_lhs = [&](
auto &pip) {
2871 contactDisp, contact_common_data_ptr->contactDispPtr()));
2872 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2875 pip.push_back(
new OpTreeSearch(
2876 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2881 auto contact_sfd_map_range_ptr =
2882 boost::make_shared<std::map<int, Range>>(
2883 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2886 contactDisp, contactDisp, contact_common_data_ptr, contactTreeRhs,
2887 contact_sfd_map_range_ptr));
2890 contactDisp, broken_data_ptr, contact_common_data_ptr,
2891 contactTreeRhs, contact_sfd_map_range_ptr));
2894 broken_data_ptr, contactDisp, contact_common_data_ptr,
2901 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2902 CHKERR add_ops_contact_lhs(op_loop_skeleton_side->getOpPtrVector());
2905 pip.push_back(op_loop_skeleton_side);
2910 CHKERR set_hybridisation(fe_lhs->getOpPtrVector());
2911 CHKERR set_contact(fe_lhs->getOpPtrVector());
2921 const bool add_elastic,
const bool add_material,
2922 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
2923 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
2926 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2927 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2932 fe_rhs->getRuleHook = [](int, int, int) {
return -1; };
2933 fe_lhs->getRuleHook = [](int, int, int) {
return -1; };
2934 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2935 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2938 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2939 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2941 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2942 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2946 auto get_broken_op_side = [
this](
auto &pip) {
2949 using SideEleOp = EleOnSide::UserDataOperator;
2951 auto broken_data_ptr =
2952 boost::make_shared<std::vector<BrokenBaseSideData>>();
2955 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2956 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2957 boost::make_shared<CGGUserPolynomialBase>();
2959 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2960 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2961 materialH1Positions, frontAdjEdges);
2962 op_loop_domain_side->getOpPtrVector().push_back(
2964 boost::shared_ptr<double> piola_scale_ptr(
new double);
2965 op_loop_domain_side->getOpPtrVector().push_back(
2966 physicalEquations->returnOpSetScale(piola_scale_ptr,
2967 physicalEquations));
2969 auto piola_stress_mat_ptr = boost::make_shared<MatrixDouble>();
2970 op_loop_domain_side->getOpPtrVector().push_back(
2972 piola_stress_mat_ptr));
2973 pip.push_back(op_loop_domain_side);
2974 return std::make_tuple(broken_data_ptr, piola_scale_ptr,
2975 piola_stress_mat_ptr);
2978 auto set_rhs = [&]() {
2981 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
2982 get_broken_op_side(fe_rhs->getOpPtrVector());
2984 fe_rhs->getOpPtrVector().push_back(
2985 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
2987 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
2990 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
2992 fe_rhs->getOpPtrVector().push_back(
2994 piola_scale_ptr, timeScaleMap));
2995 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
2997 fe_rhs->getOpPtrVector().push_back(
2999 hybridSpatialDisp, hybrid_grad_ptr));
3001 hybridSpatialDisp, bcSpatialPressureVecPtr, piola_scale_ptr,
3002 hybrid_grad_ptr, timeScaleMap));
3004 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
3007 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3008 fe_rhs->getOpPtrVector().push_back(
3012 hybridSpatialDisp, hybrid_ptr, piola_stress_mat_ptr,
3013 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3015 auto get_normal_disp_bc_faces = [&]() {
3018 return boost::make_shared<Range>(faces);
3023 using BdyEleOp = BoundaryEle::UserDataOperator;
3025 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3026 fe_rhs->getOpPtrVector().push_back(
new OpC_dBroken(
3027 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3028 get_normal_disp_bc_faces()));
3033 auto set_lhs = [&]() {
3036 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
3037 get_broken_op_side(fe_lhs->getOpPtrVector());
3040 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3042 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
3045 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3047 fe_rhs->getOpPtrVector().push_back(
3049 hybridSpatialDisp, hybrid_grad_ptr));
3051 hybridSpatialDisp, bcSpatialPressureVecPtr, hybrid_grad_ptr,
3054 auto get_normal_disp_bc_faces = [&]() {
3057 return boost::make_shared<Range>(faces);
3062 using BdyEleOp = BoundaryEle::UserDataOperator;
3064 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3065 fe_lhs->getOpPtrVector().push_back(
new OpC(
3066 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3067 true,
true, get_normal_disp_bc_faces()));
3081 boost::shared_ptr<ContactTree> &fe_contact_tree
3087 auto get_body_range = [
this](
auto name,
int dim,
auto sev) {
3088 std::map<int, Range> map;
3091 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3093 (boost::format(
"%s(.*)") % name).str()
3099 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3102 map[m_ptr->getMeshsetId()] = ents;
3103 MOFEM_LOG(
"EPSYNC", sev) <<
"Meshset: " << m_ptr->getMeshsetId() <<
" "
3104 << ents.size() <<
" entities";
3111 auto get_map_skin = [
this](
auto &&map) {
3112 ParallelComm *pcomm =
3115 Skinner skin(&mField.get_moab());
3116 for (
auto &
m : map) {
3118 CHKERR skin.find_skin(0,
m.second,
false, skin_faces);
3120 PSTATUS_SHARED | PSTATUS_MULTISHARED,
3121 PSTATUS_NOT, -1,
nullptr),
3123 m.second.swap(skin_faces);
3133 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
3135 auto calcs_side_traction = [&](
auto &pip) {
3139 using SideEleOp = EleOnSide::UserDataOperator;
3141 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
3142 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3143 boost::make_shared<CGGUserPolynomialBase>();
3144 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3145 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3146 materialH1Positions, frontAdjEdges);
3147 op_loop_domain_side->getOpPtrVector().push_back(
3149 piolaStress, contact_common_data_ptr->contactTractionPtr(),
3150 boost::make_shared<double>(1.0)));
3151 pip.push_back(op_loop_domain_side);
3155 auto add_contact_three = [&]() {
3157 auto tree_moab_ptr = boost::make_shared<moab::Core>();
3158 fe_contact_tree = boost::make_shared<ContactTree>(
3159 mField, tree_moab_ptr, spaceOrder,
3160 get_body_range(
"CONTACT",
SPACE_DIM - 1, Sev::inform));
3161 fe_contact_tree->getOpPtrVector().push_back(
3163 contactDisp, contact_common_data_ptr->contactDispPtr()));
3164 CHKERR calcs_side_traction(fe_contact_tree->getOpPtrVector());
3165 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
3166 fe_contact_tree->getOpPtrVector().push_back(
3168 fe_contact_tree->getOpPtrVector().push_back(
3169 new OpMoveNode(fe_contact_tree, contact_common_data_ptr, u_h1_ptr));
3173 CHKERR add_contact_three();
3183 CHKERR setContactElementRhsOps(contactTreeRhs);
3185 CHKERR setVolumeElementOps(tag,
true,
false, elasticFeRhs, elasticFeLhs);
3186 CHKERR setFaceElementOps(
true,
false, elasticBcRhs, elasticBcLhs);
3189 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3191 auto get_op_contact_bc = [&]() {
3194 mField, contactElement,
SPACE_DIM - 1, Sev::noisy, adj_cache);
3195 return op_loop_side;
3203 boost::shared_ptr<FEMethod> null;
3205 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3237 bool set_ts_monitor) {
3239#ifdef ENABLE_PYTHON_BINDING
3240 auto setup_sdf = [&]() {
3241 boost::shared_ptr<ContactOps::SDFPython> sdf_python_ptr;
3243 auto file_exists = [](std::string myfile) {
3244 std::ifstream file(myfile.c_str());
3251 char sdf_file_name[255] =
"sdf.py";
3253 sdf_file_name, 255, PETSC_NULLPTR);
3255 if (file_exists(sdf_file_name)) {
3256 MOFEM_LOG(
"EP", Sev::inform) << sdf_file_name <<
" file found";
3257 sdf_python_ptr = boost::make_shared<ContactOps::SDFPython>();
3258 CHKERR sdf_python_ptr->sdfInit(sdf_file_name);
3259 ContactOps::sdfPythonWeakPtr = sdf_python_ptr;
3260 MOFEM_LOG(
"EP", Sev::inform) <<
"SdfPython initialized";
3262 MOFEM_LOG(
"EP", Sev::warning) << sdf_file_name <<
" file NOT found";
3264 return sdf_python_ptr;
3266 auto sdf_python_ptr = setup_sdf();
3269 auto setup_ts_monitor = [&]() {
3270 boost::shared_ptr<TsCtx>
ts_ctx;
3272 if (set_ts_monitor) {
3274 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
3278 MOFEM_LOG(
"EP", Sev::inform) <<
"TS monitor setup";
3279 return std::make_tuple(
ts_ctx);
3282 auto setup_snes_monitor = [&]() {
3285 CHKERR TSGetSNES(ts, &snes);
3287 CHKERR SNESMonitorSet(snes,
3290 (
void *)(snes_ctx.get()), PETSC_NULLPTR);
3291 MOFEM_LOG(
"EP", Sev::inform) <<
"SNES monitor setup";
3295 auto setup_snes_conergence_test = [&]() {
3298 auto snes_convergence_test = [](SNES snes, PetscInt it, PetscReal xnorm,
3299 PetscReal snorm, PetscReal fnorm,
3300 SNESConvergedReason *reason,
void *cctx) {
3303 CHKERR SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason,
3307 CHKERR SNESGetSolutionUpdate(snes, &x_update);
3308 CHKERR SNESGetFunction(snes, &r, PETSC_NULLPTR, PETSC_NULLPTR);
3376 auto setup_section = [&]() {
3377 PetscSection section_raw;
3380 CHKERR PetscSectionGetNumFields(section_raw, &num_fields);
3381 for (
int ff = 0; ff != num_fields; ff++) {
3389 auto set_vector_on_mesh = [&]() {
3393 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3394 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3395 MOFEM_LOG(
"EP", Sev::inform) <<
"Vector set on mesh";
3399 auto setup_schur_block_solver = [&]() {
3400 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver";
3401 CHKERR TSAppendOptionsPrefix(ts,
"elastic_");
3402 CHKERR TSSetFromOptions(ts);
3405 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
3406 if constexpr (
A == AssemblyType::BLOCK_MAT) {
3411 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver done";
3418#ifdef ENABLE_PYTHON_BINDING
3419 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
3420 setup_snes_monitor(), setup_snes_conergence_test(),
3421 setup_section(), set_vector_on_mesh(),
3422 setup_schur_block_solver());
3424 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
3425 setup_snes_conergence_test(), setup_section(),
3426 set_vector_on_mesh(), setup_schur_block_solver());
3434 PetscBool debug_model = PETSC_FALSE;
3438 if (debug_model == PETSC_TRUE) {
3440 auto post_proc = [&](TS ts, PetscReal
t, Vec u, Vec u_t, Vec u_tt, Vec
F,
3445 CHKERR TSGetSNES(ts, &snes);
3447 CHKERR SNESGetIterationNumber(snes, &it);
3448 std::string file_name =
"snes_iteration_" + std::to_string(it) +
".h5m";
3449 CHKERR postProcessResults(1, file_name,
F, u_t);
3450 std::string file_skel_name =
3451 "snes_iteration_skel_" + std::to_string(it) +
".h5m";
3453 auto get_material_force_tag = [&]() {
3454 auto &moab = mField.get_moab();
3461 CHKERR calculateFaceMaterialForce(1, ts);
3462 CHKERR postProcessSkeletonResults(1, file_skel_name,
F,
3463 {get_material_force_tag()});
3467 ts_ctx_ptr->tsDebugHook = post_proc;
3472 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3474 CHKERR VecDuplicate(x, &xx);
3475 CHKERR VecZeroEntries(xx);
3476 CHKERR TS2SetSolution(ts, x, xx);
3479 CHKERR TSSetSolution(ts, x);
3482 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3483 {elasticFeLhs.get(), elasticFeRhs.get()});
3488 CHKERR TSSolve(ts, PETSC_NULLPTR);
3490 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3491 {elasticFeLhs.get(), elasticFeRhs.get()});
3494 CHKERR TSGetSNES(ts, &snes);
3495 int lin_solver_iterations;
3496 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
3498 <<
"Number of linear solver iterations " << lin_solver_iterations;
3500 PetscBool test_cook_flg = PETSC_FALSE;
3503 if (test_cook_flg) {
3504 constexpr int expected_lin_solver_iterations = 11;
3505 if (lin_solver_iterations > expected_lin_solver_iterations)
3508 "Expected number of iterations is different than expected %d > %d",
3509 lin_solver_iterations, expected_lin_solver_iterations);
3512 PetscBool test_sslv116_flag = PETSC_FALSE;
3514 &test_sslv116_flag, PETSC_NULLPTR);
3516 if (test_sslv116_flag) {
3517 double max_val = 0.0;
3518 double min_val = 0.0;
3519 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
3521 auto ent_type = ent_ptr->getEntType();
3522 if (ent_type == MBVERTEX) {
3523 max_val = std::max(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], max_val);
3524 min_val = std::min(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], min_val);
3529 field_min_max, spatialH1Disp);
3531 double global_max_val = 0.0;
3532 double global_min_val = 0.0;
3533 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
3535 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
3538 <<
"Max " << spatialH1Disp <<
" value: " << global_max_val;
3540 <<
"Min " << spatialH1Disp <<
" value: " << global_min_val;
3542 double ref_max_val = 0.00767;
3543 double ref_min_val = -0.00329;
3544 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
3546 "Incorrect max value of the displacement field: %f != %f",
3547 global_max_val, ref_max_val);
3549 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
3551 "Incorrect min value of the displacement field: %f != %f",
3552 global_min_val, ref_min_val);
3566 double final_time = 1;
3567 double delta_time = 0.1;
3569 PetscBool ts_h1_update = PETSC_FALSE;
3571 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Dynamic Relaxation Options",
3574 CHKERR PetscOptionsScalar(
"-dynamic_final_time",
3575 "dynamic relaxation final time",
"", final_time,
3576 &final_time, PETSC_NULLPTR);
3577 CHKERR PetscOptionsScalar(
"-dynamic_delta_time",
3578 "dynamic relaxation final time",
"", delta_time,
3579 &delta_time, PETSC_NULLPTR);
3580 CHKERR PetscOptionsInt(
"-dynamic_max_it",
"dynamic relaxation iterations",
"",
3581 max_it, &max_it, PETSC_NULLPTR);
3582 CHKERR PetscOptionsBool(
"-dynamic_h1_update",
"update each ts step",
"",
3583 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
3587 auto setup_ts_monitor = [&]() {
3588 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*
this);
3591 auto monitor_ptr = setup_ts_monitor();
3593 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3594 {elasticFeLhs.get(), elasticFeRhs.get()});
3598 double ts_delta_time;
3599 CHKERR TSGetTimeStep(ts, &ts_delta_time);
3611 monitor_ptr->ts_u = PETSC_NULLPTR;
3612 monitor_ptr->ts_t = dynamicTime;
3613 monitor_ptr->ts_step = dynamicStep;
3615 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3616 << dynamicTime <<
" delta time " << delta_time;
3617 dynamicTime += delta_time;
3620 for (; dynamicTime < final_time; dynamicTime += delta_time) {
3621 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3622 << dynamicTime <<
" delta time " << delta_time;
3624 CHKERR TSSetStepNumber(ts, 0);
3626 CHKERR TSSetTimeStep(ts, ts_delta_time);
3627 if (!ts_h1_update) {
3630 CHKERR TSSolve(ts, PETSC_NULLPTR);
3631 if (!ts_h1_update) {
3635 monitor_ptr->ts_u = PETSC_NULLPTR;
3636 monitor_ptr->ts_t = dynamicTime;
3637 monitor_ptr->ts_step = dynamicStep;
3641 if (dynamicStep > max_it)
3646 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3647 {elasticFeLhs.get(), elasticFeRhs.get()});
3655 auto set_block = [&](
auto name,
int dim) {
3656 std::map<int, Range> map;
3657 auto set_tag_impl = [&](
auto name) {
3662 std::regex((boost::format(
"%s(.*)") % name).str())
3665 for (
auto bc : bcs) {
3667 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
3669 map[bc->getMeshsetId()] = r;
3674 CHKERR set_tag_impl(name);
3676 return std::make_pair(name, map);
3679 auto set_skin = [&](
auto &&map) {
3680 for (
auto &
m : map.second) {
3687 auto set_tag = [&](
auto &&map) {
3689 auto name = map.first;
3690 int def_val[] = {-1};
3692 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER,
th,
3693 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
3695 for (
auto &
m : map.second) {
3703 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"BODY", 3))));
3704 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"MAT_ELASTIC", 3))));
3705 listTagsToTransfer.push_back(
3706 set_tag(set_skin(set_block(
"MAT_NEOHOOKEAN", 3))));
3707 listTagsToTransfer.push_back(set_tag(set_block(
"CONTACT", 2)));
3714 Vec f_residual, Vec var_vector,
3715 std::vector<Tag> tags_to_transfer) {
3721 rval = mField.get_moab().tag_get_handle(
"CRACK",
th);
3722 if (
rval == MB_SUCCESS) {
3723 CHKERR mField.get_moab().tag_delete(
th);
3725 int def_val[] = {0};
3726 CHKERR mField.get_moab().tag_get_handle(
3727 "CRACK", 1, MB_TYPE_INTEGER,
th, MB_TAG_SPARSE | MB_TAG_CREAT, def_val);
3729 CHKERR mField.get_moab().tag_clear_data(
th, *crackFaces, mark);
3730 tags_to_transfer.push_back(
th);
3732 auto get_tag = [&](
auto name,
auto dim) {
3733 auto &mob = mField.get_moab();
3735 double def_val[] = {0., 0., 0.};
3736 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3737 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3742 tags_to_transfer.push_back(get_tag(
"MaterialForce", 3));
3747 for (
auto t : listTagsToTransfer) {
3748 tags_to_transfer.push_back(
t);
3756 struct exclude_sdf {
3757 exclude_sdf(
Range &&r) : map(r) {}
3758 bool operator()(
FEMethod *fe_method_ptr) {
3760 if (map.find(ent) != map.end()) {
3770 contactTreeRhs->exeTestHook =
3775 auto get_post_proc = [&](
auto &post_proc_mesh,
auto sense) {
3777 auto post_proc_ptr =
3778 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
3779 mField, post_proc_mesh);
3780 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3781 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
3784 auto domain_ops = [&](
auto &fe,
int sense) {
3786 fe.getUserPolynomialBase() =
3787 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
3788 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3789 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
3791 auto piola_scale_ptr = boost::make_shared<double>(1.0);
3792 fe.getOpPtrVector().push_back(physicalEquations->returnOpSetScale(
3793 piola_scale_ptr, physicalEquations));
3795 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
3797 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
3800 fe.getOpPtrVector().push_back(
3801 physicalEquations->returnOpCalculateStretchFromStress(
3802 dataAtPts, physicalEquations));
3804 fe.getOpPtrVector().push_back(
3806 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
3811 piolaStress, dataAtPts->getVarPiolaPts(),
3812 boost::make_shared<double>(1), vec));
3814 bubbleField, dataAtPts->getVarPiolaPts(),
3815 boost::make_shared<double>(1), vec, MBMAXTYPE));
3817 rotAxis, dataAtPts->getVarRotAxisPts(), vec, MBTET));
3819 fe.getOpPtrVector().push_back(
3820 physicalEquations->returnOpCalculateVarStretchFromStress(
3821 dataAtPts, physicalEquations));
3823 fe.getOpPtrVector().push_back(
3825 stretchTensor, dataAtPts->getVarLogStreachPts(), vec, MBTET));
3830 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3832 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3835 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3837 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3839 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3841 fe.getOpPtrVector().push_back(
3845 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3846 tag,
true,
false, dataAtPts, physicalEquations));
3848 physicalEquations->returnOpCalculateEnergy(dataAtPts,
nullptr)) {
3849 fe.getOpPtrVector().push_back(op);
3858 struct OpSidePPMap :
public OpPPMap {
3859 OpSidePPMap(moab::Interface &post_proc_mesh,
3860 std::vector<EntityHandle> &map_gauss_pts,
3861 DataMapVec data_map_scalar, DataMapMat data_map_vec,
3862 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
3864 :
OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
3865 data_map_vec, data_map_mat, data_symm_map_mat),
3872 if (tagSense != OpPPMap::getSkeletonSense())
3884 vec_fields[
"SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
3885 vec_fields[
"SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
3886 vec_fields[
"Omega"] = dataAtPts->getRotAxisAtPts();
3887 vec_fields[
"ContactDisplacement"] = dataAtPts->getContactL2AtPts();
3888 vec_fields[
"AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
3889 vec_fields[
"X"] = dataAtPts->getLargeXH1AtPts();
3891 vec_fields[
"EiegnLogStreach"] = dataAtPts->getEigenValsAtPts();
3895 vec_fields[
"VarOmega"] = dataAtPts->getVarRotAxisPts();
3896 vec_fields[
"VarSpatialDisplacementL2"] =
3897 boost::make_shared<MatrixDouble>();
3899 spatialL2Disp, vec_fields[
"VarSpatialDisplacementL2"], vec, MBTET));
3903 vec_fields[
"ResSpatialDisplacementL2"] =
3904 boost::make_shared<MatrixDouble>();
3906 spatialL2Disp, vec_fields[
"ResSpatialDisplacementL2"], vec, MBTET));
3907 vec_fields[
"ResOmega"] = boost::make_shared<MatrixDouble>();
3909 rotAxis, vec_fields[
"ResOmega"], vec, MBTET));
3913 mat_fields[
"PiolaStress"] = dataAtPts->getApproxPAtPts();
3915 mat_fields[
"VarPiolaStress"] = dataAtPts->getVarPiolaPts();
3919 mat_fields[
"ResPiolaStress"] = boost::make_shared<MatrixDouble>();
3921 piolaStress, mat_fields[
"ResPiolaStress"],
3922 boost::make_shared<double>(1), vec));
3924 bubbleField, mat_fields[
"ResPiolaStress"],
3925 boost::make_shared<double>(1), vec, MBMAXTYPE));
3927 if (!internalStressTagName.empty()) {
3928 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
3929 switch (internalStressInterpOrder) {
3931 fe.getOpPtrVector().push_back(
3935 fe.getOpPtrVector().push_back(
3940 "Unsupported internal stress interpolation order %d",
3941 internalStressInterpOrder);
3946 mat_fields_symm[
"LogSpatialStretch"] =
3947 dataAtPts->getLogStretchTensorAtPts();
3948 mat_fields_symm[
"SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
3950 mat_fields_symm[
"VarLogSpatialStretch"] =
3951 dataAtPts->getVarLogStreachPts();
3956 mat_fields_symm[
"ResLogSpatialStretch"] =
3957 boost::make_shared<MatrixDouble>();
3958 fe.getOpPtrVector().push_back(
3960 stretchTensor, mat_fields_symm[
"ResLogSpatialStretch"], vec,
3965 fe.getOpPtrVector().push_back(
3969 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3986 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3992 post_proc_ptr->getOpPtrVector().push_back(
3994 dataAtPts->getContactL2AtPts()));
3996 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
3998 post_proc_ptr->getOpPtrVector().push_back(
4000 dataAtPts->getLargeXH1AtPts()));
4005 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
4006 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
4008 return post_proc_ptr;
4012 auto calcs_side_traction_and_displacements = [&](
auto &post_proc_ptr,
4015 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
4019 using SideEleOp = EleOnSide::UserDataOperator;
4021 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
4022 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4023 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
4024 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4025 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4026 materialH1Positions, frontAdjEdges);
4027 op_loop_domain_side->getOpPtrVector().push_back(
4029 piolaStress, contact_common_data_ptr->contactTractionPtr(),
4030 boost::make_shared<double>(1.0)));
4031 pip.push_back(op_loop_domain_side);
4033 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4036 contactDisp, contact_common_data_ptr->contactDispPtr()));
4037 pip.push_back(
new OpTreeSearch(
4038 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
4040 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4047 pip.push_back(op_this);
4048 auto contact_residual = boost::make_shared<MatrixDouble>();
4049 op_this->getOpPtrVector().push_back(
4051 contactDisp, contact_residual,
4054 op_this->getOpPtrVector().push_back(
4058 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4062 {{
"res_contact", contact_residual}},
4076 auto post_proc_mesh = boost::make_shared<moab::Core>();
4077 auto post_proc_ptr = get_post_proc(post_proc_mesh, 1);
4078 auto post_proc_negative_sense_ptr = get_post_proc(post_proc_mesh, -1);
4079 CHKERR calcs_side_traction_and_displacements(post_proc_ptr,
4080 post_proc_ptr->getOpPtrVector());
4086 CHKERR mField.get_moab().get_adjacencies(own_tets,
SPACE_DIM - 1,
true,
4087 own_faces, moab::Interface::UNION);
4089 auto get_post_negative = [&](
auto &&ents) {
4090 auto crack_faces_pos = ents;
4091 auto crack_faces_neg = crack_faces_pos;
4092 auto skin =
get_skin(mField, own_tets);
4093 auto crack_on_proc_skin = intersect(crack_faces_pos, skin);
4094 for (
auto f : crack_on_proc_skin) {
4096 CHKERR mField.get_moab().get_adjacencies(&f, 1,
SPACE_DIM,
false, tet);
4097 tet = intersect(tet, own_tets);
4098 int side_number, sense, offset;
4099 CHKERR mField.get_moab().side_number(tet[0], f, side_number, sense,
4102 crack_faces_neg.erase(f);
4104 crack_faces_pos.erase(f);
4107 return std::make_pair(crack_faces_pos, crack_faces_neg);
4110 auto get_crack_faces = [&](
auto crack_faces) {
4111 auto get_adj = [&](
auto e,
auto dim) {
4113 CHKERR mField.get_moab().get_adjacencies(e, dim,
true, adj,
4114 moab::Interface::UNION);
4117 auto tets = get_adj(crack_faces, 3);
4118 auto faces = subtract(get_adj(tets, 2), crack_faces);
4119 tets = subtract(tets, get_adj(faces, 3));
4120 return subtract(crack_faces, get_adj(tets, 2));
4123 auto [crack_faces_pos, crack_faces_neg] =
4124 get_post_negative(intersect(own_faces, get_crack_faces(*crackFaces)));
4126 auto only_crack_faces = [&](
FEMethod *fe_method_ptr) {
4127 auto ent = fe_method_ptr->getFEEntityHandle();
4128 if (crack_faces_pos.find(ent) == crack_faces_pos.end()) {
4134 auto only_negative_crack_faces = [&](
FEMethod *fe_method_ptr) {
4135 auto ent = fe_method_ptr->getFEEntityHandle();
4136 if (crack_faces_neg.find(ent) == crack_faces_neg.end()) {
4142 auto get_adj_front = [&]() {
4143 auto skeleton_faces = *skeletonFaces;
4145 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2,
true, adj_front,
4146 moab::Interface::UNION);
4148 adj_front = intersect(adj_front, skeleton_faces);
4149 adj_front = subtract(adj_front, *crackFaces);
4150 adj_front = intersect(own_faces, adj_front);
4154 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4155 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
4157 auto post_proc_begin =
4161 post_proc_ptr->exeTestHook = only_crack_faces;
4162 post_proc_negative_sense_ptr->exeTestHook = only_negative_crack_faces;
4164 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4166 post_proc_negative_sense_ptr, 0,
4167 mField.get_comm_size());
4169 constexpr bool debug =
false;
4172 auto [adj_front_pos, adj_front_neg] =
4175 auto only_front_faces_pos = [adj_front_pos](
FEMethod *fe_method_ptr) {
4176 auto ent = fe_method_ptr->getFEEntityHandle();
4177 if (adj_front_pos.find(ent) == adj_front_pos.end()) {
4183 auto only_front_faces_neg = [adj_front_neg](
FEMethod *fe_method_ptr) {
4184 auto ent = fe_method_ptr->getFEEntityHandle();
4185 if (adj_front_neg.find(ent) == adj_front_neg.end()) {
4191 post_proc_ptr->exeTestHook = only_front_faces_pos;
4193 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4194 post_proc_negative_sense_ptr->exeTestHook = only_front_faces_neg;
4196 post_proc_negative_sense_ptr, 0,
4197 mField.get_comm_size());
4202 CHKERR post_proc_end.writeFile(file.c_str());
4209 std::vector<Tag> tags_to_transfer) {
4214 auto post_proc_mesh = boost::make_shared<moab::Core>();
4215 auto post_proc_ptr =
4216 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4218 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
4222 auto hybrid_disp = boost::make_shared<MatrixDouble>();
4223 post_proc_ptr->getOpPtrVector().push_back(
4225 post_proc_ptr->getOpPtrVector().push_back(
4229 auto op_loop_domain_side =
4232 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4235 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4236 boost::make_shared<CGGUserPolynomialBase>();
4237 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4238 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4240 op_loop_domain_side->getOpPtrVector().push_back(
4243 op_loop_domain_side->getOpPtrVector().push_back(
4246 op_loop_domain_side->getOpPtrVector().push_back(
4250 op_loop_domain_side->getOpPtrVector().push_back(
4254 op_loop_domain_side->getOpPtrVector().push_back(
4262 vec_fields[
"HybridDisplacement"] = hybrid_disp;
4263 vec_fields[
"Omega"] =
dataAtPts->getRotAxisAtPts();
4265 mat_fields[
"PiolaStress"] =
dataAtPts->getApproxPAtPts();
4266 mat_fields[
"HybridDisplacementGradient"] =
4269 mat_fields_symm[
"LogSpatialStretch"] =
dataAtPts->getLogStretchTensorAtPts();
4271 post_proc_ptr->getOpPtrVector().push_back(
4275 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4290 auto hybrid_res = boost::make_shared<MatrixDouble>();
4291 post_proc_ptr->getOpPtrVector().push_back(
4296 post_proc_ptr->getOpPtrVector().push_back(
4300 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4304 {{
"res_hybrid", hybrid_res}},
4315 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4317 auto post_proc_begin =
4324 CHKERR post_proc_end.writeFile(file.c_str());
4332 constexpr bool debug =
false;
4334 auto get_tags_vec = [&](std::vector<std::pair<std::string, int>> names) {
4335 std::vector<Tag> tags;
4336 tags.reserve(names.size());
4337 auto create_and_clean = [&]() {
4339 for (
auto n : names) {
4340 tags.push_back(
Tag());
4341 auto &tag = tags.back();
4343 auto rval = moab.tag_get_handle(
n.first.c_str(), tag);
4344 if (
rval == MB_SUCCESS) {
4345 moab.tag_delete(tag);
4347 double def_val[] = {0., 0., 0.};
4348 CHKERR moab.tag_get_handle(
n.first.c_str(),
n.second, MB_TYPE_DOUBLE,
4349 tag, MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4357 enum ExhangeTags { MATERIALFORCE, AREAGROWTH, GRIFFITHFORCE, FACEPRESSURE };
4359 auto tags = get_tags_vec({{
"MaterialForce", 3},
4361 {
"GriffithForce", 1},
4362 {
"FacePressure", 1}});
4364 auto calculate_material_forces = [&]() {
4370 auto get_face_material_force_fe = [&]() {
4372 auto fe_ptr = boost::make_shared<FaceEle>(
mField);
4373 fe_ptr->getRuleHook = [](int, int, int) {
return -1; };
4374 fe_ptr->setRuleHook =
4378 EshelbianPlasticity::AddHOOps<2, 2, 3>::add(
4380 fe_ptr->getOpPtrVector().push_back(
4383 auto op_loop_domain_side =
4386 fe_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4390 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4391 boost::make_shared<CGGUserPolynomialBase>();
4392 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4393 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4395 op_loop_domain_side->getOpPtrVector().push_back(
4398 op_loop_domain_side->getOpPtrVector().push_back(
4401 op_loop_domain_side->getOpPtrVector().push_back(
4405 op_loop_domain_side->getOpPtrVector().push_back(
4409 op_loop_domain_side->getOpPtrVector().push_back(
4413 op_loop_domain_side->getOpPtrVector().push_back(
4419 auto integrate_face_material_force_fe = [&](
auto &&face_energy_fe) {
4427 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
4430 CHKERR VecGetLocalSize(
v.second, &size);
4432 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
4433 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( "
4434 << low <<
" " << high <<
" ) ";
4438 CHKERR print_loc_size(face_exchange,
"material face_exchange",
4442 mField.
get_moab(), face_exchange, tags[ExhangeTags::MATERIALFORCE]);
4449 "front_skin_faces_material_force_" +
4458 CHKERR integrate_face_material_force_fe(get_face_material_force_fe());
4463 auto calculate_front_material_force = [&]() {
4467 auto get_conn = [&](
auto e) {
4470 "get connectivity");
4474 auto get_conn_range = [&](
auto e) {
4477 "get connectivity");
4481 auto get_adj = [&](
auto e,
auto dim) {
4488 auto get_adj_range = [&](
auto e,
auto dim) {
4491 moab::Interface::UNION),
4496 auto get_material_force = [&](
auto r,
auto th) {
4501 return material_forces;
4506 auto crack_edges = get_adj_range(*
crackFaces, 1);
4507 auto front_nodes = get_conn_range(*
frontEdges);
4514 Range all_skin_faces;
4515 Range all_front_faces;
4518 auto calculate_edge_direction = [&](
auto e) {
4523 "get connectivity");
4524 std::array<double, 6> coords;
4529 &coords[0], &coords[1], &coords[2]};
4531 &coords[3], &coords[4], &coords[5]};
4534 t_dir(
i) = t_p1(
i) - t_p0(
i);
4539 auto calculate_force_through_node = [&]() {
4551 auto body_skin_conn = get_conn_range(body_skin);
4554 for (
auto n : front_nodes) {
4555 auto adj_tets = get_adj(
n, 3);
4557 auto conn = get_conn_range(adj_tets);
4558 adj_tets = get_adj_range(conn, 3);
4561 auto material_forces = get_material_force(skin_faces, tags[0]);
4565 all_skin_faces.merge(skin_faces);
4569 auto calculate_node_material_force = [&]() {
4571 getFTensor1FromPtr<SPACE_DIM>(material_forces.data().data());
4573 for (
auto face : skin_faces) {
4576 t_face_force_tmp(
I) = t_face_T(
I);
4579 auto face_tets = intersect(get_adj(face, 3), adj_tets);
4581 if (face_tets.empty()) {
4585 if (face_tets.size() != 1) {
4587 "face_tets.size() != 1");
4590 int side_number, sense, offset;
4594 "moab side number");
4595 t_face_force_tmp(
I) *= sense;
4596 t_node_force(
I) += t_face_force_tmp(
I);
4599 return t_node_force;
4602 auto calculate_crack_area_growth_direction =
4603 [&](
auto n,
auto &t_node_force) {
4606 auto boundary_node = intersect(
Range(
n,
n), body_skin_conn);
4607 if (boundary_node.size()) {
4608 auto faces = intersect(get_adj(
n, 2), body_skin);
4609 for (
auto f : faces) {
4612 f, &t_normal_face(0));
4613 t_project(
I) += t_normal_face(
I);
4615 t_project.normalize();
4622 if (boundary_node.size()) {
4623 t_Q(
I,
J) -= t_project(
I) * t_project(
J);
4626 auto adj_faces = intersect(get_adj(
n, 2), *
crackFaces);
4627 if (adj_faces.empty()) {
4629 intersect(get_adj(
n, 1), unite(*
frontEdges, body_edges));
4631 for (
auto e : adj_edges) {
4632 auto t_dir = calculate_edge_direction(e);
4638 t_node_force_tmp(
I) = t_node_force(
I);
4640 t_area_dir(
I) = -t_node_force_tmp(
I);
4641 t_area_dir(
I) *=
l / 2;
4646 auto front_edges = get_adj(
n, 1);
4648 for (
auto f : adj_faces) {
4653 std::array<double, 9> coords;
4659 coords.data(), &t_face_normal(0), &t_d_normal(0, 0, 0));
4660 auto n_it = std::find(conn, conn + num_nodes,
n);
4661 auto n_index = std::distance(conn, n_it);
4664 t_d_normal(0, n_index, 0), t_d_normal(0, n_index, 1),
4665 t_d_normal(0, n_index, 2),
4667 t_d_normal(1, n_index, 0), t_d_normal(1, n_index, 1),
4668 t_d_normal(1, n_index, 2),
4670 t_d_normal(2, n_index, 0), t_d_normal(2, n_index, 1),
4671 t_d_normal(2, n_index, 2)};
4674 t_projected_hessian(
I,
J) =
4675 t_Q(
I,
K) * (t_face_hessian(
K,
L) * t_Q(
L,
J));
4678 t_face_normal(
I) * t_projected_hessian(
I,
K) / 2.;
4684 auto t_node_force = calculate_node_material_force();
4688 &
n, 1, &t_node_force(0)),
4691 auto get_area_dir = [&]() {
4692 auto adj_faces = get_adj_range(adj_tets, 2);
4693 auto t_area_dir = calculate_crack_area_growth_direction(
4696 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
4698 auto seed_n = get_conn_range(adj_edges);
4700 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
4701 seed_n = subtract(seed_n, skin_adj_edges);
4703 for (
auto sn : seed_n) {
4704 auto t_area_dir_sn = calculate_crack_area_growth_direction(
4706 t_area_dir(
I) += t_area_dir_sn(
I);
4708 for (
auto sn : skin_adj_edges) {
4709 auto t_area_dir_sn = calculate_crack_area_growth_direction(
4711 t_area_dir(
I) += t_area_dir_sn(
I) / 2;
4718 auto t_area_dir = get_area_dir();
4724 auto griffith = -t_node_force(
I) * t_area_dir(
I) /
4725 (t_area_dir(
K) * t_area_dir(
K));
4733 auto ave_node_force = [&](
auto th) {
4738 auto conn = get_conn(e);
4739 auto data = get_material_force(conn,
th);
4740 auto t_node = getFTensor1FromPtr<SPACE_DIM>(data.data().data());
4742 for (
auto n : conn) {
4743 t_edge(
I) += t_node(
I);
4746 t_edge(
I) /= conn.size();
4749 calculate_edge_direction(e);
4767 auto ave_node_griffith_energy = [&](
auto th) {
4772 tags[ExhangeTags::MATERIALFORCE], &e, 1, &t_edge_force(0));
4775 &e, 1, &t_edge_area_dir(0));
4776 double griffith_energy = -t_edge_force(
I) * t_edge_area_dir(
I) /
4777 (t_edge_area_dir(
K) * t_edge_area_dir(
K));
4783 CHKERR ave_node_force(tags[ExhangeTags::MATERIALFORCE]);
4784 CHKERR ave_node_force(tags[ExhangeTags::AREAGROWTH]);
4785 CHKERR ave_node_griffith_energy(tags[ExhangeTags::GRIFFITHFORCE]);
4790 CHKERR calculate_force_through_node();
4794 auto adj_faces = get_adj(e, 2);
4795 auto crack_face = intersect(get_adj(e, 2), *
crackFaces);
4799 all_front_faces.merge(adj_faces);
4805 &e, 1, &t_edge_force(0));
4807 calculate_edge_direction(e);
4816 for (
auto f : adj_faces) {
4820 int side_number, sense, offset;
4823 auto dot = -sense * t_cross(
I) * t_normal(
I);
4825 tags[ExhangeTags::GRIFFITHFORCE], &
f, 1, &dot),
4833 CHKERR TSGetStepNumber(ts, &ts_step);
4835 "front_edges_material_force_" +
4836 std::to_string(ts_step) +
".vtk",
4839 "front_skin_faces_material_force_" +
4840 std::to_string(ts_step) +
".vtk",
4843 "front_faces_material_force_" +
4844 std::to_string(ts_step) +
".vtk",
4853 mField.
get_moab(), edge_exchange, tags[ExhangeTags::MATERIALFORCE]);
4855 mField.
get_moab(), edge_exchange, tags[ExhangeTags::AREAGROWTH]);
4862 auto print_results = [&]() {
4865 auto get_conn_range = [&](
auto e) {
4868 "get connectivity");
4872 auto get_tag_data = [&](
auto &ents,
auto tag,
auto dim) {
4873 std::vector<double> data(ents.size() * dim);
4880 auto at_nodes = [&]() {
4883 auto material_force =
4884 get_tag_data(conn, tags[ExhangeTags::MATERIALFORCE], 3);
4885 auto area_growth = get_tag_data(conn, tags[ExhangeTags::AREAGROWTH], 3);
4886 auto griffith_force =
4887 get_tag_data(conn, tags[ExhangeTags::GRIFFITHFORCE], 1);
4888 std::vector<double> coords(conn.size() * 3);
4892 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Material force at nodes";
4893 for (
size_t i = 0;
i < conn.size(); ++
i) {
4895 <<
"Node " << conn[
i] <<
" coords "
4896 << coords[
i * 3 + 0] <<
" " << coords[
i * 3 + 1] <<
" "
4897 << coords[
i * 3 + 2] <<
" material force "
4898 << material_force[
i * 3 + 0] <<
" "
4899 << material_force[
i * 3 + 1] <<
" "
4900 << material_force[
i * 3 + 2] <<
" area growth "
4901 << area_growth[
i * 3 + 0] <<
" " << area_growth[
i * 3 + 1]
4902 <<
" " << area_growth[
i * 3 + 2] <<
" griffith force "
4903 << griffith_force[
i];
4913 CHKERR calculate_material_forces();
4914 CHKERR calculate_front_material_force();
4921 bool set_orientation) {
4924 constexpr bool debug =
false;
4925 constexpr auto sev = Sev::verbose;
4930 Range body_skin_edges;
4932 moab::Interface::UNION);
4933 Range boundary_skin_verts;
4935 boundary_skin_verts,
true);
4938 Range geometry_edges_verts;
4940 geometry_edges_verts,
true);
4941 Range crack_faces_verts;
4944 Range crack_faces_edges;
4946 *
crackFaces, 1,
true, crack_faces_edges, moab::Interface::UNION);
4947 Range crack_faces_tets;
4949 *
crackFaces, 3,
true, crack_faces_tets, moab::Interface::UNION);
4955 moab::Interface::UNION);
4956 Range front_verts_edges;
4958 front_verts, 1,
true, front_verts_edges, moab::Interface::UNION);
4960 auto get_tags_vec = [&](
auto tag_name,
int dim) {
4961 std::vector<Tag> tags(1);
4966 auto create_and_clean = [&]() {
4969 auto rval = moab.tag_get_handle(tag_name, tags[0]);
4970 if (
rval == MB_SUCCESS) {
4971 moab.tag_delete(tags[0]);
4973 double def_val[] = {0., 0., 0.};
4974 CHKERR moab.tag_get_handle(tag_name, dim, MB_TYPE_DOUBLE, tags[0],
4975 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4984 auto get_adj_front = [&](
bool subtract_crack) {
4987 adj_front, moab::Interface::UNION);
4989 adj_front = subtract(adj_front, *
crackFaces);
4995 auto th_front_position = get_tags_vec(
"FrontPosition", 3);
4996 auto th_max_face_energy = get_tags_vec(
"MaxFaceEnergy", 1);
5000 auto get_crack_adj_tets = [&](
auto r) {
5001 Range crack_faces_conn;
5003 Range crack_faces_conn_tets;
5005 true, crack_faces_conn_tets,
5006 moab::Interface::UNION);
5007 return crack_faces_conn_tets;
5010 auto get_layers_for_sides = [&](
auto &side) {
5011 std::vector<Range> layers;
5015 auto get_adj = [&](
auto &r,
int dim) {
5018 moab::Interface::UNION);
5022 auto get_tets = [&](
auto r) {
return get_adj(r,
SPACE_DIM); };
5027 Range front_faces = get_adj(front_nodes, 2);
5028 front_faces = subtract(front_faces, *
crackFaces);
5029 auto front_tets = get_tets(front_nodes);
5030 auto front_side = intersect(side, front_tets);
5031 layers.push_back(front_side);
5034 adj_faces = intersect(adj_faces, front_faces);
5035 auto adj_faces_tets = get_tets(adj_faces);
5036 adj_faces_tets = intersect(adj_faces_tets, front_tets);
5037 layers.push_back(unite(layers.back(), adj_faces_tets));
5038 if (layers.back().size() == layers[layers.size() - 2].size()) {
5049 auto layers_top = get_layers_for_sides(sides_pair.first);
5050 auto layers_bottom = get_layers_for_sides(sides_pair.second);
5062 MOFEM_LOG(
"EP", sev) <<
"Nb. layers " << layers_top.size();
5064 for (
auto &r : layers_top) {
5065 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
5068 "layers_top_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
5073 for (
auto &r : layers_bottom) {
5074 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
5077 "layers_bottom_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
5083 auto get_cross = [&](
auto t_dir,
auto f) {
5095 auto get_sense = [&](
auto f,
auto e) {
5096 int side, sense, offset;
5099 return std::make_tuple(side, sense, offset);
5102 auto calculate_edge_direction = [&](
auto e,
auto normalize =
true) {
5106 std::array<double, 6> coords;
5109 &coords[0], &coords[1], &coords[2]};
5111 &coords[3], &coords[4], &coords[5]};
5114 t_dir(
i) = t_p1(
i) - t_p0(
i);
5120 auto evaluate_face_energy_and_set_orientation = [&](
auto front_edges,
5127 Tag th_material_force;
5129 case GRIFFITH_FORCE:
5130 case GRIFFITH_SKELETON:
5137 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
5138 "Unknown energy release selector");
5146 auto find_maximal_face_energy = [&](
auto front_edges,
auto front_faces,
5147 auto &edge_face_max_energy_map) {
5156 for (
auto e : front_edges) {
5158 double griffith_force;
5164 faces = subtract(intersect(faces, front_faces), body_skin);
5165 std::vector<double> face_energy(faces.size());
5167 face_energy.data());
5168 auto max_energy_it =
5169 std::max_element(face_energy.begin(), face_energy.end());
5171 max_energy_it != face_energy.end() ? *max_energy_it : 0;
5173 edge_face_max_energy_map[e] =
5174 std::make_tuple(faces[max_energy_it - face_energy.begin()],
5175 griffith_force,
static_cast<double>(0));
5177 <<
"Edge " << e <<
" griffith force " << griffith_force
5178 <<
" max face energy " << max_energy <<
" factor "
5179 << max_energy / griffith_force;
5181 max_faces.insert(faces[max_energy_it - face_energy.begin()]);
5203 auto calculate_face_orientation = [&](
auto &edge_face_max_energy_map) {
5206 auto up_down_face = [&](
5208 auto &face_angle_map_up,
5209 auto &face_angle_map_down
5214 for (
auto &
m : edge_face_max_energy_map) {
5216 auto [max_face, energy, opt_angle] =
m.second;
5220 faces = intersect(faces, front_faces);
5224 moab::Interface::UNION);
5225 if (adj_tets.size()) {
5230 moab::Interface::UNION);
5231 if (adj_tets.size()) {
5233 Range adj_tets_faces;
5236 adj_tets,
SPACE_DIM - 1,
false, adj_tets_faces,
5237 moab::Interface::UNION);
5238 adj_tets_faces = intersect(adj_tets_faces, faces);
5243 get_cross(calculate_edge_direction(e,
true), max_face);
5244 auto [side_max, sense_max, offset_max] = get_sense(max_face, e);
5245 t_cross_max(
i) *= sense_max;
5247 for (
auto t : adj_tets) {
5248 Range adj_tets_faces;
5250 &
t, 1,
SPACE_DIM - 1,
false, adj_tets_faces);
5251 adj_tets_faces = intersect(adj_tets_faces, faces);
5253 subtract(adj_tets_faces,
Range(max_face, max_face));
5255 if (adj_tets_faces.size() == 1) {
5259 auto t_cross = get_cross(calculate_edge_direction(e,
true),
5261 auto [side, sense, offset] =
5262 get_sense(adj_tets_faces[0], e);
5263 t_cross(
i) *= sense;
5264 double dot = t_cross(
i) * t_cross_max(
i);
5265 auto angle = std::acos(dot);
5269 th_face_energy, adj_tets_faces, &face_energy);
5271 auto [side_face, sense_face, offset_face] =
5272 get_sense(
t, max_face);
5274 if (sense_face > 0) {
5275 face_angle_map_up[e] = std::make_tuple(face_energy, angle,
5279 face_angle_map_down[e] = std::make_tuple(
5280 face_energy, -angle, adj_tets_faces[0]);
5291 auto calc_optimal_angle = [&](
5293 auto &face_angle_map_up,
5294 auto &face_angle_map_down
5299 for (
auto &
m : edge_face_max_energy_map) {
5301 auto &[max_face, e0,
a0] =
m.second;
5303 if (std::abs(e0) > std::numeric_limits<double>::epsilon()) {
5305 if (face_angle_map_up.find(e) == face_angle_map_up.end() ||
5306 face_angle_map_down.find(e) == face_angle_map_down.end()) {
5311 case GRIFFITH_FORCE:
5312 case GRIFFITH_SKELETON: {
5314 Tag th_material_force;
5319 th_material_force, &e, 1, &t_material_force(0));
5320 auto material_force_magnitude = t_material_force.
l2();
5321 if (material_force_magnitude <
5322 std::numeric_limits<double>::epsilon()) {
5327 auto t_edge_dir = calculate_edge_direction(e,
true);
5328 auto t_cross_max = get_cross(t_edge_dir, max_face);
5329 auto [side, sense, offset] = get_sense(max_face, e);
5330 t_cross_max(sense) *= sense;
5337 t_cross_max.normalize();
5340 t_material_force(
J) * t_cross_max(
K);
5341 a0 = -std::asin(t_cross(
I) * t_edge_dir(
I));
5344 <<
"Optimal angle " <<
a0 <<
" energy " << e0;
5350 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
5351 "Unknown energy release selector");
5361 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5363 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5364 face_angle_map_down;
5365 CHKERR up_down_face(face_angle_map_up, face_angle_map_down);
5366 CHKERR calc_optimal_angle(face_angle_map_up, face_angle_map_down);
5370 auto th_angle = get_tags_vec(
"Angle", 1);
5372 for (
auto &
m : face_angle_map_up) {
5373 auto [e,
a, face] =
m.second;
5378 for (
auto &
m : face_angle_map_down) {
5379 auto [e,
a, face] =
m.second;
5384 Range max_energy_faces;
5385 for (
auto &
m : edge_face_max_energy_map) {
5386 auto [face, e, angle] =
m.second;
5387 max_energy_faces.insert(face);
5403 auto get_conn = [&](
auto e) {
5410 auto get_adj = [&](
auto e,
auto dim) {
5413 e, dim,
false, adj, moab::Interface::UNION),
5418 auto get_coords = [&](
auto v) {
5426 auto get_rotated_normal = [&](
auto e,
auto f,
auto angle) {
5429 auto t_edge_dir = calculate_edge_direction(e,
true);
5430 auto [side, sense, offset] = get_sense(
f, e);
5431 t_edge_dir(
i) *= sense;
5432 t_edge_dir.normalize();
5433 t_edge_dir(
i) *= angle;
5438 t_rotated_normal(
i) = t_R(
i,
j) * t_normal(
j);
5439 return std::make_tuple(t_normal, t_rotated_normal);
5442 auto set_coord = [&](
auto v,
auto &adj_vertex_tets_verts,
auto &coords,
5443 auto &t_move,
auto gamma) {
5444 auto index = adj_vertex_tets_verts.index(
v);
5446 for (
auto ii : {0, 1, 2}) {
5447 coords[3 * index + ii] += gamma * t_move(ii);
5454 auto tets_quality = [&](
auto quality,
auto &adj_vertex_tets_verts,
5455 auto &adj_vertex_tets,
auto &coords) {
5456 for (
auto t : adj_vertex_tets) {
5460 std::array<double, 12> tet_coords;
5461 for (
auto n = 0;
n != 4; ++
n) {
5462 auto index = adj_vertex_tets_verts.index(conn[
n]);
5466 for (
auto ii = 0; ii != 3; ++ii) {
5467 tet_coords[3 *
n + ii] = coords[3 * index + ii];
5471 if (!std::isnormal(q))
5473 quality = std::min(quality, q);
5479 auto calculate_free_face_node_displacement =
5480 [&](
auto &edge_face_max_energy_map) {
5482 auto get_vertex_edges = [&](
auto vertex) {
5489 vertex_edges = subtract(vertex_edges, front_verts_edges);
5491 if (boundary_skin_verts.size() &&
5492 boundary_skin_verts.find(vertex[0]) !=
5493 boundary_skin_verts.end()) {
5494 MOFEM_LOG(
"EP", sev) <<
"Boundary vertex";
5495 vertex_edges = intersect(vertex_edges, body_skin_edges);
5497 if (geometry_edges_verts.size() &&
5498 geometry_edges_verts.find(vertex[0]) !=
5499 geometry_edges_verts.end()) {
5500 MOFEM_LOG(
"EP", sev) <<
"Geometry edge vertex";
5501 vertex_edges = intersect(vertex_edges, geometry_edges);
5503 if (crack_faces_verts.size() &&
5504 crack_faces_verts.find(vertex[0]) !=
5505 crack_faces_verts.end()) {
5506 MOFEM_LOG(
"EP", sev) <<
"Crack face vertex";
5507 vertex_edges = intersect(vertex_edges, crack_faces_edges);
5514 return vertex_edges;
5519 using Bundle = std::vector<
5525 std::map<EntityHandle, Bundle> edge_bundle_map;
5527 for (
auto &
m : edge_face_max_energy_map) {
5529 auto edge =
m.first;
5530 auto &[max_face, energy, opt_angle] =
m.second;
5533 auto [t_normal, t_rotated_normal] =
5534 get_rotated_normal(edge, max_face, opt_angle);
5536 auto front_vertex = get_conn(
Range(
m.first,
m.first));
5537 auto adj_tets = get_adj(
Range(max_face, max_face), 3);
5538 auto adj_tets_faces = get_adj(adj_tets, 2);
5539 auto adj_front_faces = subtract(
5540 intersect(get_adj(
Range(edge, edge), 2), adj_tets_faces),
5542 if (adj_front_faces.size() > 3)
5544 "adj_front_faces.size()>3");
5548 &t_material_force(0));
5549 std::vector<double> griffith_energy(adj_front_faces.size());
5551 th_face_energy, adj_front_faces, griffith_energy.data());
5554 auto set_edge_bundle = [&](
auto min_gamma) {
5555 for (
auto rotated_f : adj_front_faces) {
5557 double rotated_face_energy =
5558 griffith_energy[adj_front_faces.index(rotated_f)];
5560 auto vertex = subtract(get_conn(
Range(rotated_f, rotated_f)),
5562 if (vertex.size() != 1) {
5564 "Wrong number of vertex to move");
5566 auto front_vertex_edges_vertex = get_conn(
5567 intersect(get_adj(front_vertex, 1), crack_faces_edges));
5569 vertex, front_vertex_edges_vertex);
5570 if (vertex.empty()) {
5574 auto face_cardinality = [&](
auto f,
auto &seen_front_edges) {
5577 subtract(body_skin_edges, crack_faces_edges));
5580 for (;
c < 10; ++
c) {
5582 subtract(get_adj(faces, 1), seen_front_edges);
5583 if (front_edges.size() == 0) {
5586 auto front_connected_edges =
5587 intersect(front_edges, whole_front);
5588 if (front_connected_edges.size()) {
5589 seen_front_edges.merge(front_connected_edges);
5592 faces.merge(get_adj(front_edges, 2));
5599 double rotated_face_cardinality = face_cardinality(
5605 rotated_face_cardinality = std::max(rotated_face_cardinality,
5608 auto t_vertex_coords = get_coords(vertex);
5609 auto vertex_edges = get_vertex_edges(vertex);
5618 for (
auto e_used_to_move_detection : vertex_edges) {
5619 auto edge_conn = get_conn(
Range(e_used_to_move_detection,
5620 e_used_to_move_detection));
5621 edge_conn = subtract(edge_conn, vertex);
5631 t_v0(
i) = (t_v_e0(
i) + t_v_e1(
i)) / 2;
5635 (t_v0(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5637 (t_v3(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5640 constexpr double eps =
5641 std::numeric_limits<double>::epsilon();
5642 if (std::isnormal(gamma) && gamma < 1.0 -
eps &&
5645 t_move(
i) = gamma * (t_v3(
i) - t_vertex_coords(
i));
5647 auto check_rotated_face_directoon = [&]() {
5649 t_delta(
i) = t_vertex_coords(
i) + t_move(
i) - t_v0(
i);
5652 (t_material_force(
i) / t_material_force.
l2()) *
5654 return -dot > 0 ? true :
false;
5657 if (check_rotated_face_directoon()) {
5660 <<
"Crack edge " << edge <<
" moved face "
5662 <<
" edge: " << e_used_to_move_detection
5663 <<
" face direction/energy " << rotated_face_energy
5664 <<
" face cardinality " << rotated_face_cardinality
5665 <<
" gamma: " << gamma;
5667 auto &bundle = edge_bundle_map[edge];
5668 bundle.emplace_back(rotated_f, e_used_to_move_detection,
5669 vertex[0], t_move, 1,
5670 rotated_face_cardinality, gamma);
5677 set_edge_bundle(std::numeric_limits<double>::epsilon());
5678 if (edge_bundle_map[edge].empty()) {
5679 set_edge_bundle(-1.);
5683 return edge_bundle_map;
5686 auto get_sort_by_energy = [&](
auto &edge_face_max_energy_map) {
5687 std::map<double, std::tuple<EntityHandle, EntityHandle, double>>
5690 for (
auto &
m : edge_face_max_energy_map) {
5692 auto &[max_face, energy, opt_angle] =
m.second;
5693 sort_by_energy[energy] = std::make_tuple(e, max_face, opt_angle);
5696 return sort_by_energy;
5699 auto set_tag = [&](
auto &&adj_edges_map,
auto &&sort_by_energy) {
5702 Tag th_face_pressure;
5704 mField.
get_moab().tag_get_handle(
"FacePressure", th_face_pressure),
5706 auto get_face_pressure = [&](
auto face) {
5715 <<
"Number of edges to check " << sort_by_energy.size();
5717 enum face_energy { POSITIVE, NEGATIVE };
5718 constexpr bool skip_negative =
true;
5720 for (
auto fe : {face_energy::POSITIVE, face_energy::NEGATIVE}) {
5724 for (
auto it = sort_by_energy.rbegin(); it != sort_by_energy.rend();
5727 auto energy = it->first;
5728 auto [max_edge, max_face, opt_angle] = it->second;
5730 auto face_pressure = get_face_pressure(max_face);
5731 if (skip_negative) {
5732 if (fe == face_energy::POSITIVE) {
5733 if (face_pressure < 0) {
5735 <<
"Skip negative face " << max_face <<
" with energy "
5736 << energy <<
" and pressure " << face_pressure;
5743 <<
"Check face " << max_face <<
" edge " << max_edge
5744 <<
" energy " << energy <<
" optimal angle " << opt_angle
5745 <<
" face pressure " << face_pressure;
5747 auto jt = adj_edges_map.find(max_edge);
5748 if (jt == adj_edges_map.end()) {
5750 <<
"Edge " << max_edge <<
" not found in adj_edges_map";
5753 auto &bundle = jt->second;
5755 auto find_max_in_bundle_impl = [&](
auto edge,
auto &bundle,
5762 double max_quality = -2;
5763 double max_quality_evaluated = -2;
5764 double min_cardinality = std::numeric_limits<double>::max();
5768 for (
auto &b : bundle) {
5769 auto &[face, move_edge, vertex, t_move, quality, cardinality,
5772 auto adj_vertex_tets = get_adj(
Range(vertex, vertex), 3);
5773 auto adj_vertex_tets_verts = get_conn(adj_vertex_tets);
5774 std::vector<double> coords(3 * adj_vertex_tets_verts.size());
5776 adj_vertex_tets_verts, coords.data()),
5779 set_coord(vertex, adj_vertex_tets_verts, coords, t_move, gamma);
5780 quality = tets_quality(quality, adj_vertex_tets_verts,
5781 adj_vertex_tets, coords);
5783 auto eval_quality = [](
auto q,
auto c,
auto edge_gamma) {
5787 return ((edge_gamma < 0) ? (q / 2) : q) / pow(
c, 2);
5791 if (eval_quality(quality, cardinality, edge_gamma) >=
5792 max_quality_evaluated) {
5793 max_quality = quality;
5794 min_cardinality = cardinality;
5795 vertex_max = vertex;
5797 move_edge_max = move_edge;
5798 t_move_last(
i) = t_move(
i);
5799 max_quality_evaluated =
5800 eval_quality(max_quality, min_cardinality, edge_gamma);
5804 return std::make_tuple(vertex_max, face_max, t_move_last,
5805 max_quality, min_cardinality);
5808 auto find_max_in_bundle = [&](
auto edge,
auto &bundle) {
5809 auto b_org_bundle = bundle;
5810 auto r = find_max_in_bundle_impl(edge, bundle, 1.);
5811 auto &[vertex_max, face_max, t_move_last, max_quality,
5813 if (max_quality < 0) {
5814 for (
double gamma = 0.95; gamma >= 0.45; gamma -= 0.05) {
5815 bundle = b_org_bundle;
5816 r = find_max_in_bundle_impl(edge, bundle, gamma);
5817 auto &[vertex_max, face_max, t_move_last, max_quality,
5820 <<
"Back tracking: gamma " << gamma <<
" edge " << edge
5821 <<
" quality " << max_quality <<
" cardinality "
5823 if (max_quality > 0.01) {
5825 t_move_last(
I) *= gamma;
5836 auto set_tag_to_vertex_and_face = [&](
auto &&r,
auto &quality) {
5838 auto &[
v,
f, t_move, q, cardinality] = r;
5840 if ((q > 0 && std::isnormal(q)) && energy > 0) {
5843 <<
"Set tag: vertex " <<
v <<
" face " <<
f <<
" "
5844 << max_edge <<
" move " << t_move <<
" energy " << energy
5845 <<
" quality " << q <<
" cardinality " << cardinality;
5856 double quality = -2;
5857 CHKERR set_tag_to_vertex_and_face(
5859 find_max_in_bundle(max_edge, bundle),
5865 if (quality > 0 && std::isnormal(quality) && energy > 0) {
5867 <<
"Crack face set with quality: " << quality;
5880 MOFEM_LOG(
"EP", sev) <<
"Calculate orientation";
5881 std::map<EntityHandle, std::tuple<EntityHandle, double, double>>
5882 edge_face_max_energy_map;
5883 CHKERR find_maximal_face_energy(front_edges, front_faces,
5884 edge_face_max_energy_map);
5885 CHKERR calculate_face_orientation(edge_face_max_energy_map);
5887 MOFEM_LOG(
"EP", sev) <<
"Calculate node positions";
5890 calculate_free_face_node_displacement(edge_face_max_energy_map),
5891 get_sort_by_energy(edge_face_max_energy_map)
5899 CHKERR evaluate_face_energy_and_set_orientation(
5900 *
frontEdges, get_adj_front(
false), sides_pair, th_front_position);
5918 auto get_max_moved_faces = [&]() {
5919 Range max_moved_faces;
5920 auto adj_front = get_adj_front(
false);
5921 std::vector<double> face_energy(adj_front.size());
5923 face_energy.data());
5924 for (
int i = 0;
i != adj_front.size(); ++
i) {
5925 if (face_energy[
i] > std::numeric_limits<double>::epsilon()) {
5926 max_moved_faces.insert(adj_front[
i]);
5930 return boost::make_shared<Range>(max_moved_faces);
5941 "max_moved_faces_" +
5956 Tag th_front_position;
5958 mField.
get_moab().tag_get_handle(
"FrontPosition", th_front_position);
5963 std::vector<double> coords(3 * verts.size());
5965 std::vector<double> pos(3 * verts.size());
5967 for (
int i = 0;
i != 3 * verts.size(); ++
i) {
5968 coords[
i] += pos[
i];
5971 double zero[] = {0., 0., 0.};
5976 constexpr bool debug =
false;
5981 "set_coords_faces_" +
5992 constexpr bool potential_crack_debug =
false;
5993 if constexpr (potential_crack_debug) {
5996 Range crack_front_verts;
6001 Range crack_front_faces;
6003 true, crack_front_faces,
6004 moab::Interface::UNION);
6005 crack_front_faces = intersect(crack_front_faces, add_ents);
6012 auto get_crack_faces = [&]() {
6020 auto get_extended_crack_faces = [&]() {
6021 auto get_faces_of_crack_front_verts = [&](
auto crack_faces_org) {
6022 ParallelComm *pcomm =
6027 if (!pcomm->rank()) {
6029 auto get_nodes = [&](
auto &&e) {
6032 "get connectivity");
6036 auto get_adj = [&](
auto &&e,
auto dim,
6037 auto t = moab::Interface::UNION) {
6049 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
6052 auto front_block_nodes = get_nodes(front_block_edges);
6056 s = crack_faces.size();
6058 auto crack_face_nodes = get_nodes(crack_faces_org);
6059 auto crack_faces_edges =
6060 get_adj(crack_faces_org, 1, moab::Interface::UNION);
6063 front_block_edges = subtract(front_block_edges, crack_skin);
6064 auto crack_skin_nodes = get_nodes(crack_skin);
6065 crack_skin_nodes.merge(front_block_nodes);
6067 auto crack_skin_faces =
6068 get_adj(crack_skin, 2, moab::Interface::UNION);
6070 subtract(subtract(crack_skin_faces, crack_faces_org), body_skin);
6072 crack_faces = crack_faces_org;
6073 for (
auto f : crack_skin_faces) {
6074 auto edges = intersect(
6075 get_adj(
Range(
f,
f), 1, moab::Interface::UNION), crack_skin);
6079 if (edges.size() == 2) {
6081 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6085 if (edges.size() == 2) {
6086 auto edge_conn = get_nodes(
Range(edges));
6087 auto faces = intersect(get_adj(edges, 2, moab::Interface::UNION),
6089 if (faces.size() == 2) {
6090 auto edge0_conn = get_nodes(
Range(edges[0], edges[0]));
6091 auto edge1_conn = get_nodes(
Range(edges[1], edges[1]));
6092 auto edges_conn = intersect(intersect(edge0_conn, edge1_conn),
6098 moab::Interface::INTERSECT),
6103 if (node_edges.size()) {
6108 auto get_t_dir = [&](
auto e_conn) {
6109 auto other_node = subtract(e_conn,
edges_conn);
6113 t_dir(
i) -= t_v0(
i);
6119 get_t_dir(edge0_conn)(
i) + get_t_dir(edge1_conn)(
i);
6122 t_crack_surface_ave_dir(
i) = 0;
6123 for (
auto e : node_edges) {
6124 auto e_conn = get_nodes(
Range(e, e));
6125 auto t_dir = get_t_dir(e_conn);
6126 t_crack_surface_ave_dir(
i) += t_dir(
i);
6129 auto dot = t_ave_dir(
i) * t_crack_surface_ave_dir(
i);
6132 if (dot < -std::numeric_limits<double>::epsilon()) {
6133 crack_faces.insert(
f);
6136 crack_faces.insert(
f);
6140 }
else if (edges.size() == 3) {
6141 crack_faces.insert(
f);
6145 if (edges.size() == 1) {
6147 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6150 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
6151 front_block_edges));
6152 if (edges.size() == 2) {
6153 crack_faces.insert(
f);
6159 crack_faces_org = crack_faces;
6161 }
while (s != crack_faces.size());
6167 return get_faces_of_crack_front_verts(get_crack_faces());
6172 get_extended_crack_faces());
6175 auto reconstruct_crack_faces = [&](
auto crack_faces) {
6176 ParallelComm *pcomm =
6182 Range new_crack_faces;
6183 if (!pcomm->rank()) {
6185 auto get_nodes = [&](
auto &&e) {
6188 "get connectivity");
6192 auto get_adj = [&](
auto &&e,
auto dim,
6193 auto t = moab::Interface::UNION) {
6201 auto get_test_on_crack_surface = [&]() {
6202 auto crack_faces_nodes =
6203 get_nodes(crack_faces);
6204 auto crack_faces_tets =
6205 get_adj(crack_faces_nodes, 3,
6206 moab::Interface::UNION);
6210 auto crack_faces_tets_nodes =
6211 get_nodes(crack_faces_tets);
6212 crack_faces_tets_nodes =
6213 subtract(crack_faces_tets_nodes, crack_faces_nodes);
6215 subtract(crack_faces_tets, get_adj(crack_faces_tets_nodes, 3,
6216 moab::Interface::UNION));
6218 get_adj(crack_faces_tets, 2,
6219 moab::Interface::UNION);
6221 new_crack_faces.merge(crack_faces);
6223 return std::make_tuple(new_crack_faces, crack_faces_tets);
6226 auto carck_faces_test_edges = [&](
auto faces,
auto tets) {
6227 auto adj_tets_faces = get_adj(tets, 2, moab::Interface::UNION);
6228 auto adj_faces_edges = get_adj(subtract(faces, adj_tets_faces), 1,
6229 moab::Interface::UNION);
6230 auto adj_tets_edges = get_adj(tets, 1, moab::Interface::UNION);
6233 adj_faces_edges.merge(geometry_edges);
6234 adj_faces_edges.merge(front_block_edges);
6236 auto boundary_tets_edges = intersect(adj_tets_edges, adj_faces_edges);
6237 auto boundary_test_nodes = get_nodes(boundary_tets_edges);
6238 auto boundary_test_nodes_edges =
6239 get_adj(boundary_test_nodes, 1, moab::Interface::UNION);
6240 auto boundary_test_nodes_edges_nodes = subtract(
6241 get_nodes(boundary_test_nodes_edges), boundary_test_nodes);
6243 boundary_tets_edges =
6244 subtract(boundary_test_nodes_edges,
6245 get_adj(boundary_test_nodes_edges_nodes, 1,
6246 moab::Interface::UNION));
6253 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
6254 body_skin_edges = intersect(get_adj(tets, 1, moab::Interface::UNION),
6256 body_skin = intersect(body_skin, adj_tets_faces);
6257 body_skin_edges = subtract(
6258 body_skin_edges, get_adj(body_skin, 1, moab::Interface::UNION));
6261 for (
auto e : body_skin_edges) {
6262 auto adj_tet = intersect(
6263 get_adj(
Range(e, e), 3, moab::Interface::INTERSECT), tets);
6264 if (adj_tet.size() == 1) {
6265 boundary_tets_edges.insert(e);
6269 return boundary_tets_edges;
6272 auto p = get_test_on_crack_surface();
6273 auto &[new_crack_faces, crack_faces_tets] = p;
6284 auto boundary_tets_edges =
6285 carck_faces_test_edges(new_crack_faces, crack_faces_tets);
6287 boundary_tets_edges);
6289 auto resolve_surface = [&](
auto boundary_tets_edges,
6290 auto crack_faces_tets) {
6291 auto boundary_tets_edges_nodes = get_nodes(boundary_tets_edges);
6292 auto crack_faces_tets_faces =
6293 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6295 Range all_removed_faces;
6296 Range all_removed_tets;
6300 while (size != crack_faces_tets.size()) {
6302 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6306 auto skin_skin_nodes = get_nodes(skin_skin);
6308 size = crack_faces_tets.size();
6310 <<
"Crack faces tets size " << crack_faces_tets.size()
6311 <<
" crack faces size " << crack_faces_tets_faces.size();
6312 auto skin_tets_nodes = subtract(
6313 get_nodes(skin_tets),
6314 boundary_tets_edges_nodes);
6316 skin_tets_nodes = subtract(skin_tets_nodes, skin_skin_nodes);
6318 Range removed_nodes;
6319 Range tets_to_remove;
6320 Range faces_to_remove;
6321 for (
auto n : skin_tets_nodes) {
6323 intersect(get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT),
6325 if (tets.size() == 0) {
6329 auto hole_detetction = [&]() {
6331 get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT);
6336 if (adj_tets.size() == 0) {
6337 return std::make_pair(
6339 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6344 std::vector<Range> tets_groups;
6345 auto test_adj_tets = adj_tets;
6346 while (test_adj_tets.size()) {
6348 Range seed =
Range(test_adj_tets[0], test_adj_tets[0]);
6349 while (seed.size() != seed_size) {
6351 subtract(get_adj(seed, 2, moab::Interface::UNION),
6354 seed_size = seed.size();
6356 intersect(get_adj(adj_faces, 3, moab::Interface::UNION),
6359 tets_groups.push_back(seed);
6360 test_adj_tets = subtract(test_adj_tets, seed);
6362 if (tets_groups.size() == 1) {
6364 return std::make_pair(
6366 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6372 Range tets_to_remove;
6373 Range faces_to_remove;
6374 for (
auto &r : tets_groups) {
6375 auto f = get_adj(r, 2, moab::Interface::UNION);
6376 auto t = intersect(get_adj(
f, 3, moab::Interface::UNION),
6379 if (
f.size() > faces_to_remove.size() ||
6380 faces_to_remove.size() == 0) {
6381 faces_to_remove =
f;
6386 <<
"Hole detection: faces to remove "
6387 << faces_to_remove.size() <<
" tets to remove "
6388 << tets_to_remove.size();
6389 return std::make_pair(faces_to_remove, tets_to_remove);
6392 if (tets.size() < tets_to_remove.size() ||
6393 tets_to_remove.size() == 0) {
6395 auto [h_faces_to_remove, h_tets_to_remove] =
6397 faces_to_remove = h_faces_to_remove;
6398 tets_to_remove = h_tets_to_remove;
6406 all_removed_faces.merge(faces_to_remove);
6407 all_removed_tets.merge(tets_to_remove);
6410 crack_faces_tets = subtract(crack_faces_tets, tets_to_remove);
6411 crack_faces_tets_faces =
6412 subtract(crack_faces_tets_faces, faces_to_remove);
6417 boost::lexical_cast<std::string>(counter) +
".vtk",
6420 "faces_to_remove_" +
6421 boost::lexical_cast<std::string>(counter) +
".vtk",
6425 boost::lexical_cast<std::string>(counter) +
".vtk",
6428 "crack_faces_tets_faces_" +
6429 boost::lexical_cast<std::string>(counter) +
".vtk",
6430 crack_faces_tets_faces);
6432 "crack_faces_tets_" +
6433 boost::lexical_cast<std::string>(counter) +
".vtk",
6439 auto cese_internal_faces = [&]() {
6442 auto adj_faces = get_adj(skin_tets, 2, moab::Interface::UNION);
6444 subtract(adj_faces, skin_tets);
6445 auto adj_tets = get_adj(adj_faces, 3,
6446 moab::Interface::UNION);
6449 subtract(crack_faces_tets,
6452 crack_faces_tets_faces =
6453 subtract(crack_faces_tets_faces, adj_faces);
6455 all_removed_faces.merge(adj_faces);
6456 all_removed_tets.merge(adj_tets);
6460 <<
"Remove internal faces size " << adj_faces.size()
6461 <<
" tets size " << adj_tets.size();
6465 auto case_only_one_free_edge = [&]() {
6468 for (
auto t :
Range(crack_faces_tets)) {
6470 auto adj_faces = get_adj(
6472 moab::Interface::UNION);
6473 auto crack_surface_edges =
6474 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6477 moab::Interface::UNION);
6480 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6481 crack_surface_edges);
6482 adj_edges = subtract(
6484 boundary_tets_edges);
6486 if (adj_edges.size() == 1) {
6488 subtract(crack_faces_tets,
6492 auto faces_to_remove =
6493 get_adj(adj_edges, 2, moab::Interface::UNION);
6496 crack_faces_tets_faces =
6497 subtract(crack_faces_tets_faces, faces_to_remove);
6499 all_removed_faces.merge(faces_to_remove);
6500 all_removed_tets.merge(
Range(
t,
t));
6502 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Remove free one edges ";
6506 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6507 crack_faces_tets_faces =
6508 subtract(crack_faces_tets_faces, all_removed_faces);
6513 auto cese_flat_tet = [&](
auto max_adj_edges) {
6520 auto body_skin_edges =
6521 get_adj(body_skin, 1, moab::Interface::UNION);
6523 for (
auto t :
Range(crack_faces_tets)) {
6525 auto adj_faces = get_adj(
6527 moab::Interface::UNION);
6528 auto crack_surface_edges =
6529 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6532 moab::Interface::UNION);
6535 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6536 crack_surface_edges);
6537 adj_edges = subtract(adj_edges, body_skin_edges);
6539 auto tet_edges = get_adj(
Range(
t,
t), 1,
6540 moab::Interface::UNION);
6542 tet_edges = subtract(tet_edges, adj_edges);
6544 for (
auto e : tet_edges) {
6545 constexpr int opposite_edge[] = {5, 3, 4, 1, 2, 0};
6546 auto get_side = [&](
auto e) {
6547 int side, sense, offset;
6550 "get side number failed");
6553 auto get_side_ent = [&](
auto side) {
6560 adj_edges.erase(get_side_ent(opposite_edge[get_side(e)]));
6563 if (adj_edges.size() <= max_adj_edges) {
6566 Range faces_to_remove;
6567 for (
auto e : adj_edges) {
6568 auto edge_adj_faces =
6569 get_adj(
Range(e, e), 2, moab::Interface::UNION);
6570 edge_adj_faces = intersect(edge_adj_faces, adj_faces);
6571 if (edge_adj_faces.size() != 2) {
6573 "Adj faces size is not 2 for edge " +
6574 boost::lexical_cast<std::string>(e));
6577 auto get_normal = [&](
auto f) {
6581 "get tri normal failed");
6584 auto t_n0 = get_normal(edge_adj_faces[0]);
6585 auto t_n1 = get_normal(edge_adj_faces[1]);
6586 auto get_sense = [&](
auto f) {
6587 int side, sense, offset;
6590 "get side number failed");
6593 auto sense0 = get_sense(edge_adj_faces[0]);
6594 auto sense1 = get_sense(edge_adj_faces[1]);
6599 auto dot_e = (sense0 * sense1) * t_n0(
i) * t_n1(
i);
6600 if (dot_e < dot || e == adj_edges[0]) {
6602 faces_to_remove = edge_adj_faces;
6606 all_removed_faces.merge(faces_to_remove);
6607 all_removed_tets.merge(
Range(
t,
t));
6610 <<
"Remove free edges on flat tet, with considered nb. of "
6612 << adj_edges.size();
6616 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6617 crack_faces_tets_faces =
6618 subtract(crack_faces_tets_faces, all_removed_faces);
6624 "Case only one free edge failed");
6625 for (
auto max_adj_edges : {0, 1, 2, 3}) {
6627 "Case only one free edge failed");
6630 "Case internal faces failed");
6634 "crack_faces_tets_faces_" +
6635 boost::lexical_cast<std::string>(counter) +
".vtk",
6636 crack_faces_tets_faces);
6638 "crack_faces_tets_" +
6639 boost::lexical_cast<std::string>(counter) +
".vtk",
6643 return std::make_tuple(crack_faces_tets_faces, crack_faces_tets,
6644 all_removed_faces, all_removed_tets);
6647 auto [resolved_faces, resolved_tets, all_removed_faces,
6649 resolve_surface(boundary_tets_edges, crack_faces_tets);
6650 resolved_faces.merge(subtract(crack_faces, all_removed_faces));
6658 crack_faces = resolved_faces;
6670 auto resolve_consisten_crack_extension = [&]() {
6672 auto crack_meshset =
6675 auto meshset = crack_meshset->getMeshset();
6679 Range old_crack_faces;
6682 auto extendeded_crack_faces = get_extended_crack_faces();
6683 auto reconstructed_crack_faces =
6684 subtract(reconstruct_crack_faces(extendeded_crack_faces),
6686 if (
nbCrackFaces >= reconstructed_crack_faces.size()) {
6688 <<
"No new crack faces to add, skipping adding to meshset";
6689 extendeded_crack_faces = subtract(
6690 extendeded_crack_faces, subtract(*
crackFaces, old_crack_faces));
6692 <<
"Number crack faces size (extended) "
6693 << extendeded_crack_faces.size();
6699 reconstructed_crack_faces);
6701 <<
"Number crack faces size (reconstructed) "
6702 << reconstructed_crack_faces.size();
6721 CHKERR resolve_consisten_crack_extension();
6734 verts = subtract(verts, conn);
6735 std::vector<double> coords(3 * verts.size());
6737 double def_coords[] = {0., 0., 0.};
6740 "ORG_COORDS", 3, MB_TYPE_DOUBLE, th_org_coords,
6741 MB_TAG_CREAT | MB_TAG_DENSE, def_coords);
6761 auto post_proc_norm_fe =
6762 boost::make_shared<VolumeElementForcesAndSourcesCore>(
mField);
6764 auto post_proc_norm_rule_hook = [](int, int,
int p) ->
int {
6767 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
6769 post_proc_norm_fe->getUserPolynomialBase() =
6770 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
6772 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
6776 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
6779 CHKERR VecZeroEntries(norms_vec);
6781 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
6782 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
6783 post_proc_norm_fe->getOpPtrVector().push_back(
6785 post_proc_norm_fe->getOpPtrVector().push_back(
6787 post_proc_norm_fe->getOpPtrVector().push_back(
6789 post_proc_norm_fe->getOpPtrVector().push_back(
6791 post_proc_norm_fe->getOpPtrVector().push_back(
6795 auto piola_ptr = boost::make_shared<MatrixDouble>();
6796 post_proc_norm_fe->getOpPtrVector().push_back(
6798 post_proc_norm_fe->getOpPtrVector().push_back(
6802 post_proc_norm_fe->getOpPtrVector().push_back(
6805 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
6807 *post_proc_norm_fe);
6808 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
6810 CHKERR VecAssemblyBegin(norms_vec);
6811 CHKERR VecAssemblyEnd(norms_vec);
6812 const double *norms;
6813 CHKERR VecGetArrayRead(norms_vec, &norms);
6814 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u: " << std::sqrt(norms[U_NORM_L2]);
6815 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
6817 <<
"norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
6819 <<
"norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
6820 CHKERR VecRestoreArrayRead(norms_vec, &norms);
6834 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6835 if (
auto disp_bc = bc.second->dispBcPtr) {
6840 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6841 MOFEM_LOG(
"EP", Sev::noisy) <<
"Displacement BC: " << *disp_bc;
6843 std::vector<double> block_attributes(6, 0.);
6844 if (disp_bc->data.flag1 == 1) {
6845 block_attributes[0] = disp_bc->data.value1;
6846 block_attributes[3] = 1;
6848 if (disp_bc->data.flag2 == 1) {
6849 block_attributes[1] = disp_bc->data.value2;
6850 block_attributes[4] = 1;
6852 if (disp_bc->data.flag3 == 1) {
6853 block_attributes[2] = disp_bc->data.value3;
6854 block_attributes[5] = 1;
6856 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6864 boost::make_shared<NormalDisplacementBcVec>();
6865 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6866 auto block_name =
"(.*)NORMAL_DISPLACEMENT(.*)";
6867 std::regex reg_name(block_name);
6868 if (std::regex_match(bc.first, reg_name)) {
6872 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6874 block_name, bc.second->bcAttributes,
6875 bc.second->bcEnts.subset_by_dimension(2));
6880 boost::make_shared<AnalyticalDisplacementBcVec>();
6882 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6883 auto block_name =
"(.*)ANALYTICAL_DISPLACEMENT(.*)";
6884 std::regex reg_name(block_name);
6885 if (std::regex_match(bc.first, reg_name)) {
6889 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6891 block_name, bc.second->bcAttributes,
6892 bc.second->bcEnts.subset_by_dimension(2));
6896 auto ts_displacement =
6897 boost::make_shared<DynamicRelaxationTimeScale>(
"disp_history.txt");
6900 <<
"Add time scaling displacement BC: " << bc.blockName;
6903 ts_displacement,
"disp_history",
".txt", bc.blockName);
6906 auto ts_normal_displacement =
6907 boost::make_shared<DynamicRelaxationTimeScale>(
"normal_disp_history.txt");
6910 <<
"Add time scaling normal displacement BC: " << bc.blockName;
6913 ts_normal_displacement,
"normal_disp_history",
".txt",
6929 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6930 if (
auto force_bc = bc.second->forceBcPtr) {
6935 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6936 MOFEM_LOG(
"EP", Sev::noisy) <<
"Force BC: " << *force_bc;
6938 std::vector<double> block_attributes(6, 0.);
6939 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
6940 block_attributes[3] = 1;
6941 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
6942 block_attributes[4] = 1;
6943 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
6944 block_attributes[5] = 1;
6945 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6953 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6954 auto block_name =
"(.*)PRESSURE(.*)";
6955 std::regex reg_name(block_name);
6956 if (std::regex_match(bc.first, reg_name)) {
6961 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6963 block_name, bc.second->bcAttributes,
6964 bc.second->bcEnts.subset_by_dimension(2));
6969 boost::make_shared<AnalyticalTractionBcVec>();
6971 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6972 auto block_name =
"(.*)ANALYTICAL_TRACTION(.*)";
6973 std::regex reg_name(block_name);
6974 if (std::regex_match(bc.first, reg_name)) {
6978 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6980 block_name, bc.second->bcAttributes,
6981 bc.second->bcEnts.subset_by_dimension(2));
6986 boost::make_shared<DynamicRelaxationTimeScale>(
"traction_history.txt");
6990 ts_traction,
"traction_history",
".txt", bc.blockName);
6994 boost::make_shared<DynamicRelaxationTimeScale>(
"pressure_history.txt");
6998 ts_pressure,
"pressure_history",
".txt", bc.blockName);
7007 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec> &ext_strain_vec_ptr,
7008 const std::string block_name,
7009 const int nb_attributes) {
7012 std::regex((boost::format(
"%s(.*)") % block_name).str()))
7014 std::vector<double> block_attributes;
7015 CHKERR it->getAttributes(block_attributes);
7016 if (block_attributes.size() < nb_attributes) {
7018 "In block %s expected %d attributes, but given %ld",
7019 it->getName().c_str(), nb_attributes, block_attributes.size());
7022 auto get_block_ents = [&]() {
7028 auto Ents = get_block_ents();
7029 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
7038 auto ts_pre_stretch =
7039 boost::make_shared<DynamicRelaxationTimeScale>(
"externalstrain_history.txt");
7042 <<
"Add time scaling external strain: " << ext_strain_block.blockName;
7045 ts_pre_stretch,
"externalstrain_history",
".txt", ext_strain_block.blockName);
7054 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
7057 CHKERR VecGetLocalSize(
v.second, &size);
7059 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
7060 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( " << low
7061 <<
" " << high <<
" ) ";
7093 MOFEM_LOG(
"EP", Sev::inform) <<
"Calculate crack area";
7095 for (
auto f : crack_faces) {
7098 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
7100 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
7102 if (success != MPI_SUCCESS) {
Implementation of tonsorial bubble base div(v) = 0.
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
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)
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 ...
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)
#define _IT_GET_DOFS_FIELD_BY_NAME_AND_ENT_FOR_LOOP_(MFIELD, NAME, ENT, IT)
loop over all dofs from a moFEM field and particular field
PetscErrorCode Legendre_polynomials(int p, double s, double *diff_s, double *L, double *diffL, const int dim)
Calculate Legendre approximation basis.
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
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
#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
MoFEMErrorCode CGG_BubbleBase_MBTET(const int p, const double *N, const double *diffN, FTensor::Tensor2< FTensor::PackPtr< double *, 9 >, 3, 3 > &phi, const int gdim)
Calculate CGGT tonsorial bubble base.
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
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
ElementsAndOps< SPACE_DIM >::SideEle SideEle
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
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
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
MoFEMErrorCode solveDynamicRelaxation(TS ts, Vec x)
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
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)
static int nbJIntegralLevels
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)
CGGUserPolynomialBase(boost::shared_ptr< CachePhi > cache_phi=nullptr)
MoFEMErrorCode getValueHdivForCGGBubble(MatrixDouble &pts)
MoFEMErrorCode getValue(MatrixDouble &pts, boost::shared_ptr< BaseFunctionCtx > ctx_ptr)
boost::shared_ptr< CachePhi > cachePhiPtr
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, BaseFunctionUnknownInterface **iface) const
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.
Simple interface for fast problem set-up.
static std::pair< std::string, std::string > extractStringFromBlockId(const std::string block_id, const std::string prb_name)
Extract block name and block name form block id.
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 block DOFs.
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.
Class used to pass element data to calculate base functions on tet,triangle,edge.
Data on single entity (This is passed as argument to DataOperator::doWork)
data structure for finite element entity
std::array< boost::ptr_vector< EntData >, MBMAXTYPE > dataOnEntities
structure for User Loop Methods on finite elements
EntityHandle getFEEntityHandle() const
default operator for TRI element
Provide data structure for (tensor) field approximation.
Definition of the force bc data structure.
structure to get information form 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.
Get values at integration pts for tensor field rank 1, i.e. vector field.
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
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
Calculate base functions on tetrahedral.
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)
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