15#include <boost/math/constants/constants.hpp>
18#ifdef ENABLE_PYTHON_BINDING
19 #include <boost/python.hpp>
20 #include <boost/python/def.hpp>
21 #include <boost/python/numpy.hpp>
22namespace bp = boost::python;
23namespace np = boost::python::numpy;
25 #pragma message "With ENABLE_PYTHON_BINDING"
29 #pragma message "Without ENABLE_PYTHON_BINDING"
45 using VolumeElementForcesAndSourcesCore::UserDataOperator::UserDataOperator;
49 using FaceElementForcesAndSourcesCore::UserDataOperator::UserDataOperator;
55 const EntityType type) {
59 auto dim = CN::Dimension(type);
61 std::vector<int> sendcounts(pcomm->size());
62 std::vector<int> displs(pcomm->size());
63 std::vector<int> sendbuf(r.size());
64 if (pcomm->rank() == 0) {
65 for (
auto p = 1; p != pcomm->size(); p++) {
67 ->getPartEntities(m_field.
get_moab(), p)
70 CHKERR m_field.
get_moab().get_adjacencies(part_ents, dim,
true, faces,
71 moab::Interface::UNION);
72 faces = intersect(faces, r);
73 sendcounts[p] = faces.size();
74 displs[p] = sendbuf.size();
75 for (
auto f : faces) {
77 sendbuf.push_back(
id);
83 MPI_Scatter(sendcounts.data(), 1, MPI_INT, &recv_data, 1, MPI_INT, 0,
85 std::vector<int> recvbuf(recv_data);
86 MPI_Scatterv(sendbuf.data(), sendcounts.data(), displs.data(), MPI_INT,
87 recvbuf.data(), recv_data, MPI_INT, 0, pcomm->comm());
89 if (pcomm->rank() > 0) {
91 for (
auto &f : recvbuf) {
101 const std::string block_name,
int dim) {
107 std::regex((boost::format(
"%s(.*)") % block_name).str())
111 for (
auto bc : bcs) {
123 const std::string block_name,
int dim) {
124 std::map<std::string, Range> r;
129 std::regex((boost::format(
"%s(.*)") % block_name).str())
133 for (
auto bc : bcs) {
138 r[bc->getName()] = faces;
145 const unsigned int cubit_bc_type) {
148 CHKERR mesh_mng->getMeshset(ms_id, cubit_bc_type, meshset);
152static auto save_range(moab::Interface &moab,
const std::string name,
153 const Range r, std::vector<Tag> tags = {}) {
156 CHKERR moab.add_entities(*out_meshset, r);
158 CHKERR moab.write_file(name.c_str(),
"VTK",
"", out_meshset->get_ptr(), 1,
159 tags.data(), tags.size());
161 MOFEM_LOG(
"SELF", Sev::warning) <<
"Empty range for " << name;
168 ParallelComm *pcomm =
171 PSTATUS_SHARED | PSTATUS_MULTISHARED,
172 PSTATUS_NOT, -1, &boundary_ents),
174 return boundary_ents;
179 ParallelComm *pcomm =
181 CHK_MOAB_THROW(pcomm->filter_pstatus(skin, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1,
190 CHK_MOAB_THROW(skin.find_skin(0, body_ents,
false, skin_ents),
"find_skin");
196 ParallelComm *pcomm =
199 Range crack_skin_without_bdy;
200 if (pcomm->rank() == 0) {
202 CHKERR moab.get_adjacencies(crack_faces, 1,
true, crack_edges,
203 moab::Interface::UNION);
204 auto crack_skin =
get_skin(m_field, crack_faces);
208 "get_entities_by_dimension");
209 auto body_skin =
get_skin(m_field, body_ents);
210 Range body_skin_edges;
211 CHK_MOAB_THROW(moab.get_adjacencies(body_skin, 1,
true, body_skin_edges,
212 moab::Interface::UNION),
214 crack_skin_without_bdy = subtract(crack_skin, body_skin_edges);
216 for (
auto &
m : front_edges_map) {
217 auto add_front = subtract(
m.second, crack_edges);
218 auto i = intersect(
m.second, crack_edges);
220 crack_skin_without_bdy.merge(add_front);
224 CHKERR moab.get_adjacencies(i_skin, 1,
true, adj_i_skin,
225 moab::Interface::UNION);
226 adj_i_skin = subtract(intersect(adj_i_skin,
m.second), crack_edges);
227 crack_skin_without_bdy.merge(adj_i_skin);
231 return send_type(m_field, crack_skin_without_bdy, MBEDGE);
237 ParallelComm *pcomm =
240 MOFEM_LOG(
"EP", Sev::noisy) <<
"get_two_sides_of_crack_surface";
242 if (!pcomm->rank()) {
244 auto impl = [&](
auto &saids) {
249 auto get_adj = [&](
auto e,
auto dim) {
252 e, dim,
true, adj, moab::Interface::UNION),
257 auto get_conn = [&](
auto e) {
264 constexpr bool debug =
false;
268 auto body_skin =
get_skin(m_field, body_ents);
269 auto body_skin_edges = get_adj(body_skin, 1);
272 subtract(
get_skin(m_field, crack_faces), body_skin_edges);
273 auto crack_skin_conn = get_conn(crack_skin);
274 auto crack_skin_conn_edges = get_adj(crack_skin_conn, 1);
275 auto crack_edges = get_adj(crack_faces, 1);
276 crack_edges = subtract(crack_edges, crack_skin);
277 auto all_tets = get_adj(crack_edges, 3);
278 crack_edges = subtract(crack_edges, crack_skin_conn_edges);
279 auto crack_conn = get_conn(crack_edges);
280 all_tets.merge(get_adj(crack_conn, 3));
289 if (crack_faces.size()) {
290 auto grow = [&](
auto r) {
291 auto crack_faces_conn = get_conn(crack_faces);
294 while (size_r != r.size() && r.size() > 0) {
296 CHKERR moab.get_connectivity(r,
v,
true);
297 v = subtract(
v, crack_faces_conn);
300 moab::Interface::UNION);
301 r = intersect(r, all_tets);
310 Range all_tets_ord = all_tets;
311 while (all_tets.size()) {
312 Range faces = get_adj(unite(saids.first, saids.second), 2);
313 faces = subtract(crack_faces, faces);
316 auto fit = faces.begin();
317 for (; fit != faces.end(); ++fit) {
318 tets = intersect(get_adj(
Range(*fit, *fit), 3), all_tets);
319 if (tets.size() == 2) {
326 saids.first.insert(tets[0]);
327 saids.first = grow(saids.first);
328 all_tets = subtract(all_tets, saids.first);
329 if (tets.size() == 2) {
330 saids.second.insert(tets[1]);
331 saids.second = grow(saids.second);
332 all_tets = subtract(all_tets, saids.second);
340 saids.first = subtract(all_tets_ord, saids.second);
341 saids.second = subtract(all_tets_ord, saids.first);
347 std::pair<Range, Range> saids;
348 if (crack_faces.size())
353 MOFEM_LOG(
"EP", Sev::noisy) <<
"get_two_sides_of_crack_surface <- done";
355 return std::pair<Range, Range>();
363 boost::shared_ptr<Range> front_edges)
367 int order_col,
int order_data) {
370 constexpr bool debug =
false;
372 constexpr int numNodes = 4;
373 constexpr int numEdges = 6;
374 constexpr int refinementLevels = 4;
376 auto &m_field = fe_raw_ptr->
mField;
377 auto fe_ptr =
static_cast<Fe *
>(fe_raw_ptr);
380 auto set_base_quadrature = [&]() {
382 int rule = 2 * order_data + 1;
393 auto &gauss_pts = fe_ptr->gaussPts;
394 gauss_pts.resize(4, nb_gauss_pts,
false);
395 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[1], 4,
396 &gauss_pts(0, 0), 1);
397 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[2], 4,
398 &gauss_pts(1, 0), 1);
399 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[3], 4,
400 &gauss_pts(2, 0), 1);
402 &gauss_pts(3, 0), 1);
403 auto &data = fe_ptr->dataOnElement[
H1];
404 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4,
407 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
408 cblas_dcopy(4 * nb_gauss_pts,
QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
417 CHKERR set_base_quadrature();
421 auto get_singular_nodes = [&]() {
424 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
426 std::bitset<numNodes> singular_nodes;
427 for (
auto nn = 0; nn != numNodes; ++nn) {
429 singular_nodes.set(nn);
431 singular_nodes.reset(nn);
434 return singular_nodes;
437 auto get_singular_edges = [&]() {
438 std::bitset<numEdges> singular_edges;
439 for (
int ee = 0; ee != numEdges; ee++) {
441 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
443 singular_edges.set(ee);
445 singular_edges.reset(ee);
448 return singular_edges;
451 auto set_gauss_pts = [&](
auto &ref_gauss_pts) {
453 fe_ptr->gaussPts.swap(ref_gauss_pts);
454 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
455 auto &data = fe_ptr->dataOnElement[
H1];
456 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
458 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
460 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
465 auto singular_nodes = get_singular_nodes();
466 if (singular_nodes.count()) {
467 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
469 CHKERR set_gauss_pts(it_map_ref_coords->second);
473 auto refine_quadrature = [&]() {
476 const int max_level = refinementLevels;
480 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
482 for (
int nn = 0; nn != 4; nn++)
483 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
484 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
488 Range tets(tet, tet);
491 tets, 1,
true, edges, moab::Interface::UNION);
496 Range nodes_at_front;
497 for (
int nn = 0; nn != numNodes; nn++) {
498 if (singular_nodes[nn]) {
500 CHKERR moab_ref.side_element(tet, 0, nn, ent);
501 nodes_at_front.insert(ent);
505 auto singular_edges = get_singular_edges();
508 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
509 for (
int ee = 0; ee != numEdges; ee++) {
510 if (singular_edges[ee]) {
512 CHKERR moab_ref.side_element(tet, 1, ee, ent);
513 CHKERR moab_ref.add_entities(meshset, &ent, 1);
519 for (
int ll = 0; ll != max_level; ll++) {
522 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
526 CHKERR moab_ref.get_adjacencies(
527 nodes_at_front, 1,
true, ref_edges, moab::Interface::UNION);
528 ref_edges = intersect(ref_edges, edges);
530 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
531 ref_edges = intersect(ref_edges, ents);
534 ->getEntitiesByTypeAndRefLevel(
536 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
540 ->updateMeshsetByEntitiesChildren(meshset,
542 meshset, MBEDGE,
true);
548 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
558 for (Range::iterator tit = tets.begin(); tit != tets.end();
562 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
563 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
566 auto &data = fe_ptr->dataOnElement[
H1];
567 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
568 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
570 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
572 for (
size_t tt = 0; tt != ref_coords.size1(); tt++) {
573 double *tet_coords = &ref_coords(tt, 0);
576 for (
size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
577 for (
int dd = 0; dd != 3; dd++) {
578 ref_gauss_pts(dd, gg) =
579 shape_n(ggg, 0) * tet_coords[3 * 0 + dd] +
580 shape_n(ggg, 1) * tet_coords[3 * 1 + dd] +
581 shape_n(ggg, 2) * tet_coords[3 * 2 + dd] +
582 shape_n(ggg, 3) * tet_coords[3 * 3 + dd];
584 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
588 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
594 CHKERR refine_quadrature();
604 using ForcesAndSourcesCore::dataOnElement;
607 using ForcesAndSourcesCore::ForcesAndSourcesCore;
622 boost::shared_ptr<Range> front_edges)
626 boost::shared_ptr<Range> front_edges,
631 int order_col,
int order_data) {
634 constexpr bool debug =
false;
636 constexpr int numNodes = 3;
637 constexpr int numEdges = 3;
638 constexpr int refinementLevels = 4;
640 auto &m_field = fe_raw_ptr->
mField;
641 auto fe_ptr =
static_cast<Fe *
>(fe_raw_ptr);
644 auto set_base_quadrature = [&]() {
646 int rule =
funRule(order_data);
656 fe_ptr->gaussPts.resize(3, nb_gauss_pts,
false);
657 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[1], 3,
658 &fe_ptr->gaussPts(0, 0), 1);
659 cblas_dcopy(nb_gauss_pts, &
QUAD_2D_TABLE[rule]->points[2], 3,
660 &fe_ptr->gaussPts(1, 0), 1);
662 &fe_ptr->gaussPts(2, 0), 1);
663 auto &data = fe_ptr->dataOnElement[
H1];
664 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 3,
667 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
668 cblas_dcopy(3 * nb_gauss_pts,
QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
670 data->dataOnEntities[MBVERTEX][0].getDiffN(
NOBASE).resize(3, 2,
false);
673 data->dataOnEntities[MBVERTEX][0].getDiffN(
NOBASE).data().begin());
682 CHKERR set_base_quadrature();
686 auto get_singular_nodes = [&]() {
689 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
691 std::bitset<numNodes> singular_nodes;
692 for (
auto nn = 0; nn != numNodes; ++nn) {
694 singular_nodes.set(nn);
696 singular_nodes.reset(nn);
699 return singular_nodes;
702 auto get_singular_edges = [&]() {
703 std::bitset<numEdges> singular_edges;
704 for (
int ee = 0; ee != numEdges; ee++) {
706 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
708 singular_edges.set(ee);
710 singular_edges.reset(ee);
713 return singular_edges;
716 auto set_gauss_pts = [&](
auto &ref_gauss_pts) {
718 fe_ptr->gaussPts.swap(ref_gauss_pts);
719 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
720 auto &data = fe_ptr->dataOnElement[
H1];
721 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
723 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
725 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
729 auto singular_nodes = get_singular_nodes();
730 if (singular_nodes.count()) {
731 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
733 CHKERR set_gauss_pts(it_map_ref_coords->second);
737 auto refine_quadrature = [&]() {
740 const int max_level = refinementLevels;
743 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
745 for (
int nn = 0; nn != numNodes; nn++)
746 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
748 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
752 Range tris(tri, tri);
755 tris, 1,
true, edges, moab::Interface::UNION);
760 Range nodes_at_front;
761 for (
int nn = 0; nn != numNodes; nn++) {
762 if (singular_nodes[nn]) {
764 CHKERR moab_ref.side_element(tri, 0, nn, ent);
765 nodes_at_front.insert(ent);
769 auto singular_edges = get_singular_edges();
772 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
773 for (
int ee = 0; ee != numEdges; ee++) {
774 if (singular_edges[ee]) {
776 CHKERR moab_ref.side_element(tri, 1, ee, ent);
777 CHKERR moab_ref.add_entities(meshset, &ent, 1);
783 for (
int ll = 0; ll != max_level; ll++) {
786 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
790 CHKERR moab_ref.get_adjacencies(
791 nodes_at_front, 1,
true, ref_edges, moab::Interface::UNION);
792 ref_edges = intersect(ref_edges, edges);
794 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
795 ref_edges = intersect(ref_edges, ents);
798 ->getEntitiesByTypeAndRefLevel(
800 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
804 ->updateMeshsetByEntitiesChildren(meshset,
806 meshset, MBEDGE,
true);
812 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
823 for (Range::iterator tit = tris.begin(); tit != tris.end();
827 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
828 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
831 auto &data = fe_ptr->dataOnElement[
H1];
832 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
833 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
835 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
837 for (
size_t tt = 0; tt != ref_coords.size1(); tt++) {
838 double *tri_coords = &ref_coords(tt, 0);
841 auto det = t_normal.
l2();
842 for (
size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
843 for (
int dd = 0; dd != 2; dd++) {
844 ref_gauss_pts(dd, gg) =
845 shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
846 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
847 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
849 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
853 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
859 CHKERR refine_quadrature();
869 using ForcesAndSourcesCore::dataOnElement;
872 using ForcesAndSourcesCore::ForcesAndSourcesCore;
921 const char *list_rots[] = {
"small",
"moderate",
"large",
"no_h1"};
922 const char *list_symm[] = {
"symm",
"not_symm"};
923 const char *list_release[] = {
"griffith_force",
"griffith_skelton"};
924 const char *list_stretches[] = {
"linear",
"log"};
929 PetscInt choice_stretch = StretchSelector::LOG;
930 char analytical_expr_file_name[255] =
"analytical_expr.py";
932 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Eshelbian plasticity",
934 CHKERR PetscOptionsInt(
"-space_order",
"approximation oder for space",
"",
936 CHKERR PetscOptionsInt(
"-space_h1_order",
"approximation oder for space",
"",
938 CHKERR PetscOptionsInt(
"-material_order",
"approximation oder for material",
940 CHKERR PetscOptionsScalar(
"-viscosity_alpha_u",
"viscosity",
"",
alphaU,
942 CHKERR PetscOptionsScalar(
"-viscosity_alpha_w",
"viscosity",
"",
alphaW,
944 CHKERR PetscOptionsScalar(
"-viscosity_alpha_omega",
"rot viscosity",
"",
946 CHKERR PetscOptionsScalar(
"-density_alpha_rho",
"density",
"",
alphaRho,
948 CHKERR PetscOptionsEList(
"-rotations",
"rotations",
"", list_rots,
949 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
951 CHKERR PetscOptionsEList(
"-grad",
"gradient of defamation approximate",
"",
952 list_rots, NO_H1_CONFIGURATION + 1,
953 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
954 CHKERR PetscOptionsEList(
"-symm",
"symmetric variant",
"", list_symm, 2,
955 list_symm[choice_symm], &choice_symm, PETSC_NULLPTR);
960 "-stretches",
"stretches",
"", list_stretches, StretchSelector::LOG + 1,
961 list_stretches[choice_stretch], &choice_stretch, PETSC_NULLPTR);
963 CHKERR PetscOptionsBool(
"-no_stretch",
"do not solve for stretch",
"",
965 CHKERR PetscOptionsBool(
"-set_singularity",
"set singularity",
"",
967 CHKERR PetscOptionsBool(
"-l2_user_base_scale",
"streach scale",
"",
971 CHKERR PetscOptionsBool(
"-dynamic_relaxation",
"dynamic time relaxation",
"",
975 CHKERR PetscOptionsInt(
"-contact_max_post_proc_ref_level",
"refinement level",
982 CHKERR PetscOptionsScalar(
"-cracking_start_time",
"cracking start time",
"",
984 CHKERR PetscOptionsScalar(
"-griffith_energy",
"Griffith energy",
"",
986 CHKERR PetscOptionsEList(
"-energy_release_variant",
"energy release variant",
987 "", list_release, 2, list_release[choice_release],
988 &choice_release, PETSC_NULLPTR);
989 CHKERR PetscOptionsInt(
"-nb_J_integral_levels",
"Number of J integarl levels",
993 char tag_name[255] =
"";
994 CHKERR PetscOptionsString(
"-internal_stress_tag_name",
995 "internal stress tag name",
"",
"", tag_name, 255,
999 "-internal_stress_interp_order",
"internal stress interpolation order",
1001 CHKERR PetscOptionsBool(
"-internal_stress_voigt",
"Voigt index notation",
"",
1006 analytical_expr_file_name, 255, PETSC_NULLPTR);
1012 "Unsupported internal stress interpolation order %d",
1025 static_cast<EnergyReleaseSelector
>(choice_release);
1028 case StretchSelector::LINEAR:
1036 case StretchSelector::LOG:
1063 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaU: -viscosity_alpha_u " <<
alphaU;
1064 MOFEM_LOG(
"EP", Sev::inform) <<
"alphaW: -viscosity_alpha_w " <<
alphaW;
1066 <<
"alphaOmega: -viscosity_alpha_omega " <<
alphaOmega;
1070 MOFEM_LOG(
"EP", Sev::inform) <<
"Gradient of deformation "
1078 MOFEM_LOG(
"EP", Sev::inform) <<
"Base exponent e";
1080 <<
"Stretch: -stretches " << list_stretches[choice_stretch];
1106 <<
"Energy release variant: -energy_release_variant "
1109 <<
"Number of J integral levels: -nb_J_integral_levels "
1112#ifdef ENABLE_PYTHON_BINDING
1113 auto file_exists = [](std::string myfile) {
1114 std::ifstream file(myfile.c_str());
1121 if (file_exists(analytical_expr_file_name)) {
1122 MOFEM_LOG(
"EP", Sev::inform) << analytical_expr_file_name <<
" file found";
1126 analytical_expr_file_name);
1130 << analytical_expr_file_name <<
" file NOT found";
1143 auto get_tets = [&]() {
1149 auto get_tets_skin = [&]() {
1150 Range tets_skin_part;
1152 CHKERR skin.find_skin(0, get_tets(),
false, tets_skin_part);
1153 ParallelComm *pcomm =
1156 CHKERR pcomm->filter_pstatus(tets_skin_part,
1157 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1158 PSTATUS_NOT, -1, &tets_skin);
1162 auto subtract_boundary_conditions = [&](
auto &&tets_skin) {
1168 tets_skin = subtract(tets_skin,
v.faces);
1172 tets_skin = subtract(tets_skin,
v.faces);
1177 tets_skin = subtract(tets_skin,
v.faces);
1183 auto add_blockset = [&](
auto block_name,
auto &&tets_skin) {
1186 tets_skin.merge(crack_faces);
1190 auto subtract_blockset = [&](
auto block_name,
auto &&tets_skin) {
1191 auto contact_range =
1193 tets_skin = subtract(tets_skin, contact_range);
1197 auto get_stress_trace_faces = [&](
auto &&tets_skin) {
1200 faces, moab::Interface::UNION);
1201 Range trace_faces = subtract(faces, tets_skin);
1205 auto tets = get_tets();
1209 auto trace_faces = get_stress_trace_faces(
1211 subtract_blockset(
"CONTACT",
1212 subtract_boundary_conditions(get_tets_skin()))
1219 boost::make_shared<Range>(subtract(trace_faces, *
contactFaces));
1239 auto add_broken_hdiv_field = [
this, meshset](
const std::string
field_name,
1245 auto get_side_map_hdiv = [&]() {
1248 std::pair<EntityType,
1263 get_side_map_hdiv(), MB_TAG_DENSE,
MF_ZERO);
1269 auto add_l2_field = [
this, meshset](
const std::string
field_name,
1270 const int order,
const int dim) {
1279 auto add_h1_field = [
this, meshset](
const std::string
field_name,
1280 const int order,
const int dim) {
1292 auto add_l2_field_by_range = [
this](
const std::string
field_name,
1293 const int order,
const int dim,
1294 const int field_dim,
Range &&r) {
1304 auto add_bubble_field = [
this, meshset](
const std::string
field_name,
1305 const int order,
const int dim) {
1311 auto field_order_table =
1312 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1313 auto get_cgg_bubble_order_zero = [](
int p) {
return 0; };
1314 auto get_cgg_bubble_order_tet = [](
int p) {
1317 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1318 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1319 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1320 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1327 auto add_user_l2_field = [
this, meshset](
const std::string
field_name,
1328 const int order,
const int dim) {
1334 auto field_order_table =
1335 const_cast<Field *
>(field_ptr)->getFieldOrderTable();
1336 auto zero_dofs = [](
int p) {
return 0; };
1338 field_order_table[MBVERTEX] = zero_dofs;
1339 field_order_table[MBEDGE] = zero_dofs;
1340 field_order_table[MBTRI] = zero_dofs;
1341 field_order_table[MBTET] = dof_l2_tet;
1359 auto get_hybridised_disp = [&]() {
1361 auto skin = subtract_boundary_conditions(get_tets_skin());
1363 faces.merge(intersect(bc.faces, skin));
1369 get_hybridised_disp());
1395 auto project_ho_geometry = [&](
auto field) {
1401 auto get_adj_front_edges = [&](
auto &front_edges) {
1402 Range front_crack_nodes;
1403 Range crack_front_edges_with_both_nodes_not_at_front;
1407 CHKERR moab.get_connectivity(front_edges, front_crack_nodes,
true);
1408 Range crack_front_edges;
1410 crack_front_edges, moab::Interface::UNION);
1412 intersect(subtract(crack_front_edges, front_edges), meshset_ents);
1413 Range crack_front_edges_nodes;
1414 CHKERR moab.get_connectivity(crack_front_edges, crack_front_edges_nodes,
1416 crack_front_edges_nodes =
1417 subtract(crack_front_edges_nodes, front_crack_nodes);
1418 CHKERR moab.get_adjacencies(
1419 crack_front_edges_nodes,
SPACE_DIM - 2,
false,
1420 crack_front_edges_with_both_nodes_not_at_front,
1421 moab::Interface::UNION);
1422 crack_front_edges_with_both_nodes_not_at_front = intersect(
1423 crack_front_edges_with_both_nodes_not_at_front, meshset_ents);
1424 crack_front_edges_with_both_nodes_not_at_front = intersect(
1425 crack_front_edges_with_both_nodes_not_at_front, crack_front_edges);
1429 crack_front_edges_with_both_nodes_not_at_front =
send_type(
1430 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1432 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1433 boost::make_shared<Range>(
1434 crack_front_edges_with_both_nodes_not_at_front));
1441 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*
frontEdges);
1452 (boost::format(
"crack_faces_%d.vtk") % rank).str(),
1455 (boost::format(
"front_edges_%d.vtk") % rank).str(),
1466 auto set_singular_dofs = [&](
auto &front_adj_edges,
auto &front_vertices) {
1474 MOFEM_LOG(
"EP", Sev::inform) <<
"Singularity eps " << beta;
1477 for (
auto edge : front_adj_edges) {
1480 CHKERR moab.get_connectivity(edge, conn, num_nodes,
false);
1482 CHKERR moab.get_coords(conn, num_nodes, coords);
1483 const double dir[3] = {coords[3] - coords[0], coords[4] - coords[1],
1484 coords[5] - coords[2]};
1485 double dof[3] = {0, 0, 0};
1486 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1487 for (
int dd = 0; dd != 3; dd++) {
1488 dof[dd] = -dir[dd] *
eps;
1490 }
else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1491 for (
int dd = 0; dd != 3; dd++) {
1492 dof[dd] = +dir[dd] *
eps;
1497 const int idx = dit->get()->getEntDofIdx();
1499 dit->get()->getFieldData() = 0;
1501 dit->get()->getFieldData() = dof[idx];
1520 auto add_field_to_fe = [
this](
const std::string fe,
1585 auto set_fe_adjacency = [&](
auto fe_name) {
1588 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
1596 auto add_field_to_fe = [
this](
const std::string fe,
1608 Range natural_bc_elements;
1611 natural_bc_elements.merge(
v.faces);
1616 natural_bc_elements.merge(
v.faces);
1621 natural_bc_elements.merge(
v.faces);
1626 natural_bc_elements.merge(
v.faces);
1631 natural_bc_elements.merge(
v.faces);
1636 natural_bc_elements.merge(
v.faces);
1641 natural_bc_elements.merge(
v.faces);
1644 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
1655 auto get_skin = [&](
auto &body_ents) {
1658 CHKERR skin.find_skin(0, body_ents,
false, skin_ents);
1663 Range boundary_ents;
1664 ParallelComm *pcomm =
1666 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
1667 PSTATUS_NOT, -1, &boundary_ents);
1668 return boundary_ents;
1802 auto remove_dofs_on_broken_skin = [&](
const std::string prb_name) {
1804 for (
int d : {0, 1, 2}) {
1805 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
1807 ->getSideDofsOnBrokenSpaceEntities(
1818 CHKERR remove_dofs_on_broken_skin(
"ESHELBY_PLASTICITY");
1854 auto set_zero_block = [&]() {
1886 auto set_section = [&]() {
1888 PetscSection section;
1893 CHKERR PetscSectionDestroy(§ion);
1916BcDisp::BcDisp(std::string name, std::vector<double> attr,
Range faces)
1917 : blockName(name), faces(faces) {
1918 vals.resize(3,
false);
1919 flags.resize(3,
false);
1920 for (
int ii = 0; ii != 3; ++ii) {
1921 vals[ii] = attr[ii];
1922 flags[ii] =
static_cast<int>(attr[ii + 3]);
1925 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp " << name;
1927 <<
"Add BCDisp vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
1929 <<
"Add BCDisp flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
1930 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCDisp nb. of faces " <<
faces.size();
1934 : blockName(name), faces(faces) {
1935 vals.resize(attr.size(),
false);
1936 for (
int ii = 0; ii != attr.size(); ++ii) {
1937 vals[ii] = attr[ii];
1943 : blockName(name), faces(faces) {
1944 vals.resize(3,
false);
1945 flags.resize(3,
false);
1946 for (
int ii = 0; ii != 3; ++ii) {
1947 vals[ii] = attr[ii];
1948 flags[ii] =
static_cast<int>(attr[ii + 3]);
1951 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce " << name;
1953 <<
"Add BCForce vals " <<
vals[0] <<
" " <<
vals[1] <<
" " <<
vals[2];
1955 <<
"Add BCForce flags " <<
flags[0] <<
" " <<
flags[1] <<
" " <<
flags[2];
1956 MOFEM_LOG(
"EP", Sev::inform) <<
"Add BCForce nb. of faces " <<
faces.size();
1960 std::vector<double> attr,
1962 : blockName(name), faces(faces) {
1965 if (attr.size() < 1) {
1967 "Wrong size of normal displacement BC");
1972 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc " << name;
1973 MOFEM_LOG(
"EP", Sev::inform) <<
"Add NormalDisplacementBc val " <<
val;
1975 <<
"Add NormalDisplacementBc nb. of faces " <<
faces.size();
1979 : blockName(name), faces(faces) {
1982 if (attr.size() < 1) {
1984 "Wrong size of normal displacement BC");
1989 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc " << name;
1990 MOFEM_LOG(
"EP", Sev::inform) <<
"Add PressureBc val " <<
val;
1992 <<
"Add PressureBc nb. of faces " <<
faces.size();
1998 : blockName(name), ents(ents) {
2001 if (attr.size() < 1) {
2003 "Wrong size of external strain attribute");
2008 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain " << name;
2009 MOFEM_LOG(
"EP", Sev::inform) <<
"Add ExternalStrain val " <<
val;
2011 <<
"Add ExternalStrain nb. of tets " <<
ents.size();
2017 std::vector<double> attr,
2019 : blockName(name), faces(faces) {
2022 if (attr.size() < 3) {
2024 "Wrong size of analytical displacement BC");
2027 flags.resize(3,
false);
2028 for (
int ii = 0; ii != 3; ++ii) {
2029 flags[ii] = attr[ii];
2032 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalDisplacementBc " << name;
2034 <<
"Add AnalyticalDisplacementBc flags " <<
flags[0] <<
" " <<
flags[1]
2037 <<
"Add AnalyticalDisplacementBc nb. of faces " <<
faces.size();
2041 std::vector<double> attr,
2043 : blockName(name), faces(faces) {
2046 if (attr.size() < 3) {
2048 "Wrong size of analytical traction BC");
2051 flags.resize(3,
false);
2052 for (
int ii = 0; ii != 3; ++ii) {
2053 flags[ii] = attr[ii];
2056 MOFEM_LOG(
"EP", Sev::inform) <<
"Add AnalyticalTractionBc " << name;
2058 <<
"Add AnalyticalTractionBc flags " <<
flags[0] <<
" " <<
flags[1]
2061 <<
"Add AnalyticalTractionBc nb. of faces " <<
faces.size();
2067 boost::shared_ptr<TractionFreeBc> &bc_ptr,
2068 const std::string contact_set_name) {
2073 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2074 Range tets_skin_part;
2075 Skinner skin(&mField.get_moab());
2076 CHKERR skin.find_skin(0, tets,
false, tets_skin_part);
2077 ParallelComm *pcomm =
2080 CHKERR pcomm->filter_pstatus(tets_skin_part,
2081 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2082 PSTATUS_NOT, -1, &tets_skin);
2085 for (
int dd = 0; dd != 3; ++dd)
2086 (*bc_ptr)[dd] = tets_skin;
2089 if (bcSpatialDispVecPtr)
2090 for (
auto &
v : *bcSpatialDispVecPtr) {
2092 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2094 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2096 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2100 if (bcSpatialRotationVecPtr)
2101 for (
auto &
v : *bcSpatialRotationVecPtr) {
2102 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2103 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2104 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2107 if (bcSpatialNormalDisplacementVecPtr)
2108 for (
auto &
v : *bcSpatialNormalDisplacementVecPtr) {
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 (bcSpatialAnalyticalDisplacementVecPtr)
2115 for (
auto &
v : *bcSpatialAnalyticalDisplacementVecPtr) {
2117 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2119 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2121 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2124 if (bcSpatialTractionVecPtr)
2125 for (
auto &
v : *bcSpatialTractionVecPtr) {
2126 (*bc_ptr)[0] = subtract((*bc_ptr)[0],
v.faces);
2127 (*bc_ptr)[1] = subtract((*bc_ptr)[1],
v.faces);
2128 (*bc_ptr)[2] = subtract((*bc_ptr)[2],
v.faces);
2131 if (bcSpatialAnalyticalTractionVecPtr)
2132 for (
auto &
v : *bcSpatialAnalyticalTractionVecPtr) {
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 (bcSpatialPressureVecPtr)
2139 for (
auto &
v : *bcSpatialPressureVecPtr) {
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);
2147 std::regex((boost::format(
"%s(.*)") % contact_set_name).str()))) {
2149 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2151 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2152 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2153 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2170 return 2 * p_data + 1;
2176 return 2 * (p_data + 1);
2181 boost::shared_ptr<CachePhi> cache_phi_otr)
2185 boost::typeindex::type_index type_index,
2193 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
2198 int nb_gauss_pts = pts.size2();
2199 if (!nb_gauss_pts) {
2203 if (pts.size1() < 3) {
2205 "Wrong dimension of pts, should be at least 3 rows with "
2209 const auto base = this->cTx->bAse;
2212 switch (this->cTx->sPace) {
2217 data.
dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 4,
false);
2220 &pts(0, 0), &pts(1, 0), &pts(2, 0), nb_gauss_pts);
2221 data.
dataOnEntities[MBVERTEX][0].getDiffN(base).resize(4, 3,
false);
2225 CHKERR getValueL2AinsworthBase(pts);
2241 "Wrong base, should be USER_BASE");
2249 const int nb_gauss_pts = pts.size2();
2251 auto check_cache = [
this](
int order,
int nb_gauss_pts) ->
bool {
2260 if (check_cache(
order, nb_gauss_pts)) {
2263 phi.resize(mat.size1(), mat.size2(),
false);
2268 shapeFun.resize(nb_gauss_pts, 4,
false);
2270 &pts(2, 0), nb_gauss_pts);
2272 double diff_shape_fun[12];
2278 phi.resize(nb_gauss_pts, 9 * nb_base_functions,
false);
2301 const int tag,
const bool do_rhs,
const bool do_lhs,
const bool calc_rates,
2303 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe) {
2307 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0,
MatrixDouble());
2308 fe->getUserPolynomialBase() =
2309 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2310 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2311 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2314 fe->getRuleHook = [](int, int, int) {
return -1; };
2315 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges);
2321 dataAtPts->physicsPtr = physicalEquations;
2326 piolaStress, dataAtPts->getApproxPAtPts()));
2328 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2330 piolaStress, dataAtPts->getDivPAtPts()));
2333 fe->getOpPtrVector().push_back(
2334 physicalEquations->returnOpCalculateStretchFromStress(
2335 dataAtPts, physicalEquations));
2337 fe->getOpPtrVector().push_back(
2339 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2343 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
2345 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
2347 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
2351 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
2353 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
2358 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
2361 fe->getOpPtrVector().push_back(
2363 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
2364 fe->getOpPtrVector().push_back(
2366 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
2370 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
2372 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
2375 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
2377 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
2384 piolaStress, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2387 bubbleField, dataAtPts->getVarPiolaPts(), boost::make_shared<double>(1),
2388 var_vec, MBMAXTYPE));
2390 rotAxis, dataAtPts->getVarRotAxisPts(), var_vec, MBTET));
2392 piolaStress, dataAtPts->getDivVarPiolaPts(), var_vec));
2394 spatialL2Disp, dataAtPts->getVarWL2Pts(), var_vec, MBTET));
2397 fe->getOpPtrVector().push_back(
2398 physicalEquations->returnOpCalculateVarStretchFromStress(
2399 dataAtPts, physicalEquations));
2401 fe->getOpPtrVector().push_back(
2403 stretchTensor, dataAtPts->getVarLogStreachPts(), var_vec, MBTET));
2409 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
2414 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
2415 tag, do_rhs, do_lhs, dataAtPts, physicalEquations));
2422 const int tag,
const bool add_elastic,
const bool add_material,
2423 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_rhs,
2424 boost::shared_ptr<VolumeElementForcesAndSourcesCore> &fe_lhs) {
2428 auto get_body_range = [
this](
auto name,
int dim) {
2429 std::map<int, Range> map;
2432 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
2434 (boost::format(
"%s(.*)") % name).str()
2440 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
2443 map[m_ptr->getMeshsetId()] = ents;
2449 auto rule_contact = [](int, int,
int o) {
return -1; };
2452 auto set_rule_contact = [refine](
2455 int order_col,
int order_data
2459 auto rule = 2 * order_data;
2465 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2472 fe_rhs->getOpPtrVector().push_back(
2474 fe_rhs->getOpPtrVector().push_back(
2479 if (!internalStressTagName.empty()) {
2480 switch (internalStressInterpOrder) {
2482 fe_rhs->getOpPtrVector().push_back(
2486 fe_rhs->getOpPtrVector().push_back(
2491 "Unsupported internal stress interpolation order %d",
2492 internalStressInterpOrder);
2494 if (internalStressVoigt) {
2495 fe_rhs->getOpPtrVector().push_back(
2499 fe_rhs->getOpPtrVector().push_back(
2504 fe_rhs->getOpPtrVector().push_back(
2506 stretchTensor, dataAtPts, externalStrainVecPtr, timeScaleMap));
2507 fe_rhs->getOpPtrVector().push_back(
2508 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
2511 fe_rhs->getOpPtrVector().push_back(
2513 fe_rhs->getOpPtrVector().push_back(
2515 fe_rhs->getOpPtrVector().push_back(
2518 auto set_hybridisation = [&](
auto &pip) {
2525 using SideEleOp = EleOnSide::UserDataOperator;
2526 using BdyEleOp = BoundaryEle::UserDataOperator;
2531 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2533 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2536 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2537 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2539 CHKERR EshelbianPlasticity::
2540 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2541 op_loop_skeleton_side->getOpPtrVector(), {L2},
2542 materialH1Positions, frontAdjEdges);
2546 auto broken_data_ptr =
2547 boost::make_shared<std::vector<BrokenBaseSideData>>();
2550 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2551 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2552 boost::make_shared<CGGUserPolynomialBase>();
2554 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2555 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2556 materialH1Positions, frontAdjEdges);
2557 op_loop_domain_side->getOpPtrVector().push_back(
2559 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
2560 op_loop_domain_side->getOpPtrVector().push_back(
2563 op_loop_domain_side->getOpPtrVector().push_back(
2567 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2569 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
2571 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
2572 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dHybrid(
2573 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
2574 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2575 op_loop_skeleton_side->getOpPtrVector().push_back(
2578 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpC_dBroken(
2579 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
2582 pip.push_back(op_loop_skeleton_side);
2587 auto set_contact = [&](
auto &pip) {
2594 using SideEleOp = EleOnSide::UserDataOperator;
2595 using BdyEleOp = BoundaryEle::UserDataOperator;
2600 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2602 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2603 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2604 CHKERR EshelbianPlasticity::
2605 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2606 op_loop_skeleton_side->getOpPtrVector(), {L2},
2607 materialH1Positions, frontAdjEdges);
2611 auto broken_data_ptr =
2612 boost::make_shared<std::vector<BrokenBaseSideData>>();
2615 auto contact_common_data_ptr =
2616 boost::make_shared<ContactOps::CommonData>();
2618 auto add_ops_domain_side = [&](
auto &pip) {
2622 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2623 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2624 boost::make_shared<CGGUserPolynomialBase>();
2626 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2627 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2628 materialH1Positions, frontAdjEdges);
2629 op_loop_domain_side->getOpPtrVector().push_back(
2632 op_loop_domain_side->getOpPtrVector().push_back(
2634 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2635 pip.push_back(op_loop_domain_side);
2639 auto add_ops_contact_rhs = [&](
auto &pip) {
2642 auto contact_sfd_map_range_ptr =
2643 boost::make_shared<std::map<int, Range>>(
2644 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2647 contactDisp, contact_common_data_ptr->contactDispPtr()));
2648 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2651 pip.push_back(
new OpTreeSearch(
2652 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2656 contactDisp, contact_common_data_ptr, contactTreeRhs,
2657 contact_sfd_map_range_ptr));
2660 broken_data_ptr, contact_common_data_ptr, contactTreeRhs));
2666 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2667 CHKERR add_ops_contact_rhs(op_loop_skeleton_side->getOpPtrVector());
2670 pip.push_back(op_loop_skeleton_side);
2675 CHKERR set_hybridisation(fe_rhs->getOpPtrVector());
2676 CHKERR set_contact(fe_rhs->getOpPtrVector());
2679 using BodyNaturalBC =
2681 Assembly<PETSC>::LinearForm<
GAUSS>;
2683 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
2685 auto body_time_scale =
2686 boost::make_shared<DynamicRelaxationTimeScale>(
"body_force.txt");
2687 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
2688 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
2689 "BODY_FORCE", Sev::inform);
2693 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
2701 fe_lhs->getOpPtrVector().push_back(
2704 bubbleField, piolaStress, dataAtPts));
2705 fe_lhs->getOpPtrVector().push_back(
2709 fe_lhs->getOpPtrVector().push_back(
2710 physicalEquations->returnOpSpatialPhysical_du_du(
2711 stretchTensor, stretchTensor, dataAtPts, alphaU));
2713 stretchTensor, piolaStress, dataAtPts,
true));
2715 stretchTensor, bubbleField, dataAtPts,
true));
2717 stretchTensor, rotAxis, dataAtPts,
2718 symmetrySelector ==
SYMMETRIC ?
true :
false));
2722 spatialL2Disp, piolaStress, dataAtPts,
true));
2724 spatialL2Disp, spatialL2Disp, dataAtPts, alphaW, alphaRho));
2727 piolaStress, rotAxis, dataAtPts,
2728 symmetrySelector ==
SYMMETRIC ?
true :
false));
2730 bubbleField, rotAxis, dataAtPts,
2731 symmetrySelector ==
SYMMETRIC ?
true :
false));
2733 if (symmetrySelector ==
SYMMETRIC ?
false :
true) {
2735 rotAxis, stretchTensor, dataAtPts,
false));
2737 rotAxis, piolaStress, dataAtPts,
false));
2739 rotAxis, bubbleField, dataAtPts,
false));
2742 rotAxis, rotAxis, dataAtPts, alphaOmega));
2744 auto set_hybridisation = [&](
auto &pip) {
2751 using SideEleOp = EleOnSide::UserDataOperator;
2752 using BdyEleOp = BoundaryEle::UserDataOperator;
2757 mField, skeletonElement,
SPACE_DIM - 1, Sev::noisy);
2759 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
2762 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
2763 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2764 CHKERR EshelbianPlasticity::
2765 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2766 op_loop_skeleton_side->getOpPtrVector(), {L2},
2767 materialH1Positions, frontAdjEdges);
2771 auto broken_data_ptr =
2772 boost::make_shared<std::vector<BrokenBaseSideData>>();
2775 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2776 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2777 boost::make_shared<CGGUserPolynomialBase>();
2779 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2780 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2781 materialH1Positions, frontAdjEdges);
2782 op_loop_domain_side->getOpPtrVector().push_back(
2785 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
2787 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
2788 op_loop_skeleton_side->getOpPtrVector().push_back(
2789 new OpC(hybridSpatialDisp, broken_data_ptr,
2790 boost::make_shared<double>(1.0),
true,
false));
2792 pip.push_back(op_loop_skeleton_side);
2797 auto set_contact = [&](
auto &pip) {
2804 using SideEleOp = EleOnSide::UserDataOperator;
2805 using BdyEleOp = BoundaryEle::UserDataOperator;
2810 mField, contactElement,
SPACE_DIM - 1, Sev::noisy);
2812 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = rule_contact;
2813 op_loop_skeleton_side->getSideFEPtr()->setRuleHook = set_rule_contact;
2814 CHKERR EshelbianPlasticity::
2815 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2816 op_loop_skeleton_side->getOpPtrVector(), {L2},
2817 materialH1Positions, frontAdjEdges);
2821 auto broken_data_ptr =
2822 boost::make_shared<std::vector<BrokenBaseSideData>>();
2825 auto contact_common_data_ptr =
2826 boost::make_shared<ContactOps::CommonData>();
2828 auto add_ops_domain_side = [&](
auto &pip) {
2832 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2833 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2834 boost::make_shared<CGGUserPolynomialBase>();
2836 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2837 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2838 materialH1Positions, frontAdjEdges);
2839 op_loop_domain_side->getOpPtrVector().push_back(
2842 op_loop_domain_side->getOpPtrVector().push_back(
2844 piolaStress, contact_common_data_ptr->contactTractionPtr()));
2845 pip.push_back(op_loop_domain_side);
2849 auto add_ops_contact_lhs = [&](
auto &pip) {
2852 contactDisp, contact_common_data_ptr->contactDispPtr()));
2853 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
2856 pip.push_back(
new OpTreeSearch(
2857 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
2862 auto contact_sfd_map_range_ptr =
2863 boost::make_shared<std::map<int, Range>>(
2864 get_body_range(
"CONTACT_SDF",
SPACE_DIM - 1));
2867 contactDisp, contactDisp, contact_common_data_ptr, contactTreeRhs,
2868 contact_sfd_map_range_ptr));
2871 contactDisp, broken_data_ptr, contact_common_data_ptr,
2872 contactTreeRhs, contact_sfd_map_range_ptr));
2875 broken_data_ptr, contactDisp, contact_common_data_ptr,
2882 CHKERR add_ops_domain_side(op_loop_skeleton_side->getOpPtrVector());
2883 CHKERR add_ops_contact_lhs(op_loop_skeleton_side->getOpPtrVector());
2886 pip.push_back(op_loop_skeleton_side);
2891 CHKERR set_hybridisation(fe_lhs->getOpPtrVector());
2892 CHKERR set_contact(fe_lhs->getOpPtrVector());
2902 const bool add_elastic,
const bool add_material,
2903 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_rhs,
2904 boost::shared_ptr<FaceElementForcesAndSourcesCore> &fe_lhs) {
2907 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2908 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
2913 fe_rhs->getRuleHook = [](int, int, int) {
return -1; };
2914 fe_lhs->getRuleHook = [](int, int, int) {
return -1; };
2915 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2916 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
2919 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2920 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2922 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
2923 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
2927 auto get_broken_op_side = [
this](
auto &pip) {
2930 using SideEleOp = EleOnSide::UserDataOperator;
2932 auto broken_data_ptr =
2933 boost::make_shared<std::vector<BrokenBaseSideData>>();
2936 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
2937 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
2938 boost::make_shared<CGGUserPolynomialBase>();
2940 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2941 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
2942 materialH1Positions, frontAdjEdges);
2943 op_loop_domain_side->getOpPtrVector().push_back(
2945 boost::shared_ptr<double> piola_scale_ptr(
new double);
2946 op_loop_domain_side->getOpPtrVector().push_back(
2947 physicalEquations->returnOpSetScale(piola_scale_ptr,
2948 physicalEquations));
2950 auto piola_stress_mat_ptr = boost::make_shared<MatrixDouble>();
2951 op_loop_domain_side->getOpPtrVector().push_back(
2953 piola_stress_mat_ptr));
2954 pip.push_back(op_loop_domain_side);
2955 return std::make_tuple(broken_data_ptr, piola_scale_ptr,
2956 piola_stress_mat_ptr);
2959 auto set_rhs = [&]() {
2962 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
2963 get_broken_op_side(fe_rhs->getOpPtrVector());
2965 fe_rhs->getOpPtrVector().push_back(
2966 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
2968 broken_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
2971 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
2973 fe_rhs->getOpPtrVector().push_back(
2975 piola_scale_ptr, timeScaleMap));
2976 fe_rhs->getOpPtrVector().push_back(
2978 piola_scale_ptr, timeScaleMap));
2980 hybridSpatialDisp, bcSpatialAnalyticalTractionVecPtr, piola_scale_ptr,
2983 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
2984 fe_rhs->getOpPtrVector().push_back(
2988 hybridSpatialDisp, hybrid_ptr, piola_stress_mat_ptr,
2989 bcSpatialNormalDisplacementVecPtr, timeScaleMap));
2991 auto get_normal_disp_bc_faces = [&]() {
2994 return boost::make_shared<Range>(faces);
2999 using BdyEleOp = BoundaryEle::UserDataOperator;
3001 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3002 fe_rhs->getOpPtrVector().push_back(
new OpC_dBroken(
3003 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3004 get_normal_disp_bc_faces()));
3009 auto set_lhs = [&]() {
3012 auto [broken_data_ptr, piola_scale_ptr, piola_stress_mat_ptr] =
3013 get_broken_op_side(fe_lhs->getOpPtrVector());
3016 hybridSpatialDisp, bcSpatialNormalDisplacementVecPtr, timeScaleMap));
3018 hybridSpatialDisp, broken_data_ptr, bcSpatialNormalDisplacementVecPtr,
3021 auto get_normal_disp_bc_faces = [&]() {
3024 return boost::make_shared<Range>(faces);
3029 using BdyEleOp = BoundaryEle::UserDataOperator;
3031 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3032 fe_lhs->getOpPtrVector().push_back(
new OpC(
3033 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3034 true,
true, get_normal_disp_bc_faces()));
3048 boost::shared_ptr<ContactTree> &fe_contact_tree
3054 auto get_body_range = [
this](
auto name,
int dim,
auto sev) {
3055 std::map<int, Range> map;
3058 mField.getInterface<
MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3060 (boost::format(
"%s(.*)") % name).str()
3066 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3069 map[m_ptr->getMeshsetId()] = ents;
3070 MOFEM_LOG(
"EPSYNC", sev) <<
"Meshset: " << m_ptr->getMeshsetId() <<
" "
3071 << ents.size() <<
" entities";
3078 auto get_map_skin = [
this](
auto &&map) {
3079 ParallelComm *pcomm =
3082 Skinner skin(&mField.get_moab());
3083 for (
auto &
m : map) {
3085 CHKERR skin.find_skin(0,
m.second,
false, skin_faces);
3087 PSTATUS_SHARED | PSTATUS_MULTISHARED,
3088 PSTATUS_NOT, -1,
nullptr),
3090 m.second.swap(skin_faces);
3100 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
3102 auto calcs_side_traction = [&](
auto &pip) {
3106 using SideEleOp = EleOnSide::UserDataOperator;
3108 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
3109 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3110 boost::make_shared<CGGUserPolynomialBase>();
3111 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3112 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3113 materialH1Positions, frontAdjEdges);
3114 op_loop_domain_side->getOpPtrVector().push_back(
3116 piolaStress, contact_common_data_ptr->contactTractionPtr(),
3117 boost::make_shared<double>(1.0)));
3118 pip.push_back(op_loop_domain_side);
3122 auto add_contact_three = [&]() {
3124 auto tree_moab_ptr = boost::make_shared<moab::Core>();
3125 fe_contact_tree = boost::make_shared<ContactTree>(
3126 mField, tree_moab_ptr, spaceOrder,
3127 get_body_range(
"CONTACT",
SPACE_DIM - 1, Sev::inform));
3128 fe_contact_tree->getOpPtrVector().push_back(
3130 contactDisp, contact_common_data_ptr->contactDispPtr()));
3131 CHKERR calcs_side_traction(fe_contact_tree->getOpPtrVector());
3132 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
3133 fe_contact_tree->getOpPtrVector().push_back(
3135 fe_contact_tree->getOpPtrVector().push_back(
3136 new OpMoveNode(fe_contact_tree, contact_common_data_ptr, u_h1_ptr));
3140 CHKERR add_contact_three();
3150 CHKERR setContactElementRhsOps(contactTreeRhs);
3152 CHKERR setVolumeElementOps(tag,
true,
false, elasticFeRhs, elasticFeLhs);
3153 CHKERR setFaceElementOps(
true,
false, elasticBcRhs, elasticBcLhs);
3156 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3158 auto get_op_contact_bc = [&]() {
3161 mField, contactElement,
SPACE_DIM - 1, Sev::noisy, adj_cache);
3162 return op_loop_side;
3170 boost::shared_ptr<FEMethod> null;
3172 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3204 bool set_ts_monitor) {
3206#ifdef ENABLE_PYTHON_BINDING
3207 auto setup_sdf = [&]() {
3208 boost::shared_ptr<ContactOps::SDFPython> sdf_python_ptr;
3210 auto file_exists = [](std::string myfile) {
3211 std::ifstream file(myfile.c_str());
3218 char sdf_file_name[255] =
"sdf.py";
3220 sdf_file_name, 255, PETSC_NULLPTR);
3222 if (file_exists(sdf_file_name)) {
3223 MOFEM_LOG(
"EP", Sev::inform) << sdf_file_name <<
" file found";
3224 sdf_python_ptr = boost::make_shared<ContactOps::SDFPython>();
3225 CHKERR sdf_python_ptr->sdfInit(sdf_file_name);
3226 ContactOps::sdfPythonWeakPtr = sdf_python_ptr;
3227 MOFEM_LOG(
"EP", Sev::inform) <<
"SdfPython initialized";
3229 MOFEM_LOG(
"EP", Sev::warning) << sdf_file_name <<
" file NOT found";
3231 return sdf_python_ptr;
3233 auto sdf_python_ptr = setup_sdf();
3236 auto setup_ts_monitor = [&]() {
3237 boost::shared_ptr<TsCtx>
ts_ctx;
3239 if (set_ts_monitor) {
3241 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*ep_ptr);
3245 MOFEM_LOG(
"EP", Sev::inform) <<
"TS monitor setup";
3246 return std::make_tuple(
ts_ctx);
3249 auto setup_snes_monitor = [&]() {
3252 CHKERR TSGetSNES(ts, &snes);
3253 PetscViewerAndFormat *vf;
3254 CHKERR PetscViewerAndFormatCreate(PETSC_VIEWER_STDOUT_WORLD,
3255 PETSC_VIEWER_DEFAULT, &vf);
3259 void *))SNESMonitorFields,
3261 MOFEM_LOG(
"EP", Sev::inform) <<
"SNES monitor setup";
3265 auto setup_section = [&]() {
3266 PetscSection section_raw;
3269 CHKERR PetscSectionGetNumFields(section_raw, &num_fields);
3270 for (
int ff = 0; ff != num_fields; ff++) {
3278 auto set_vector_on_mesh = [&]() {
3282 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
3283 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
3284 MOFEM_LOG(
"EP", Sev::inform) <<
"Vector set on mesh";
3288 auto setup_schur_block_solver = [&]() {
3289 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver";
3290 CHKERR TSAppendOptionsPrefix(ts,
"elastic_");
3291 CHKERR TSSetFromOptions(ts);
3294 boost::shared_ptr<EshelbianCore::SetUpSchur> schur_ptr;
3295 if constexpr (
A == AssemblyType::BLOCK_MAT) {
3300 MOFEM_LOG(
"EP", Sev::inform) <<
"Setting up Schur block solver done";
3307#ifdef ENABLE_PYTHON_BINDING
3308 return std::make_tuple(setup_sdf(), setup_ts_monitor(),
3309 setup_snes_monitor(), setup_section(),
3310 set_vector_on_mesh(), setup_schur_block_solver());
3312 return std::make_tuple(setup_ts_monitor(), setup_snes_monitor(),
3313 setup_section(), set_vector_on_mesh(),
3314 setup_schur_block_solver());
3322 PetscBool debug_model = PETSC_FALSE;
3326 if (debug_model == PETSC_TRUE) {
3328 auto post_proc = [&](TS ts, PetscReal
t, Vec u, Vec u_t, Vec u_tt, Vec
F,
3333 CHKERR TSGetSNES(ts, &snes);
3335 CHKERR SNESGetIterationNumber(snes, &it);
3336 std::string file_name =
"snes_iteration_" + std::to_string(it) +
".h5m";
3337 CHKERR postProcessResults(1, file_name,
F);
3338 std::string file_skel_name =
3339 "snes_iteration_skel_" + std::to_string(it) +
".h5m";
3341 auto get_material_force_tag = [&]() {
3342 auto &moab = mField.get_moab();
3349 CHKERR calculateFaceMaterialForce(1, ts);
3350 CHKERR postProcessSkeletonResults(1, file_skel_name,
F,
3351 {get_material_force_tag()});
3355 ts_ctx_ptr->tsDebugHook = post_proc;
3360 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3362 CHKERR VecDuplicate(x, &xx);
3363 CHKERR VecZeroEntries(xx);
3364 CHKERR TS2SetSolution(ts, x, xx);
3367 CHKERR TSSetSolution(ts, x);
3370 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3371 {elasticFeLhs.get(), elasticFeRhs.get()});
3376 CHKERR TSSolve(ts, PETSC_NULLPTR);
3378 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3379 {elasticFeLhs.get(), elasticFeRhs.get()});
3382 CHKERR TSGetSNES(ts, &snes);
3383 int lin_solver_iterations;
3384 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
3386 <<
"Number of linear solver iterations " << lin_solver_iterations;
3388 PetscBool test_cook_flg = PETSC_FALSE;
3391 if (test_cook_flg) {
3392 constexpr int expected_lin_solver_iterations = 11;
3393 if (lin_solver_iterations > expected_lin_solver_iterations)
3396 "Expected number of iterations is different than expected %d > %d",
3397 lin_solver_iterations, expected_lin_solver_iterations);
3400 PetscBool test_sslv116_flag = PETSC_FALSE;
3402 &test_sslv116_flag, PETSC_NULLPTR);
3404 if (test_sslv116_flag) {
3405 double max_val = 0.0;
3406 double min_val = 0.0;
3407 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
3409 auto ent_type = ent_ptr->getEntType();
3410 if (ent_type == MBVERTEX) {
3411 max_val = std::max(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], max_val);
3412 min_val = std::min(ent_ptr->getEntFieldData()[
SPACE_DIM - 1], min_val);
3417 field_min_max, spatialH1Disp);
3419 double global_max_val = 0.0;
3420 double global_min_val = 0.0;
3421 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
3423 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
3426 <<
"Max " << spatialH1Disp <<
" value: " << global_max_val;
3428 <<
"Min " << spatialH1Disp <<
" value: " << global_min_val;
3430 double ref_max_val = 0.00767;
3431 double ref_min_val = -0.00329;
3432 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
3434 "Incorrect max value of the displacement field: %f != %f",
3435 global_max_val, ref_max_val);
3437 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
3439 "Incorrect min value of the displacement field: %f != %f",
3440 global_min_val, ref_min_val);
3454 double final_time = 1;
3455 double delta_time = 0.1;
3457 PetscBool ts_h1_update = PETSC_FALSE;
3459 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Dynamic Relaxation Options",
3462 CHKERR PetscOptionsScalar(
"-dynamic_final_time",
3463 "dynamic relaxation final time",
"", final_time,
3464 &final_time, PETSC_NULLPTR);
3465 CHKERR PetscOptionsScalar(
"-dynamic_delta_time",
3466 "dynamic relaxation final time",
"", delta_time,
3467 &delta_time, PETSC_NULLPTR);
3468 CHKERR PetscOptionsInt(
"-dynamic_max_it",
"dynamic relaxation iterations",
"",
3469 max_it, &max_it, PETSC_NULLPTR);
3470 CHKERR PetscOptionsBool(
"-dynamic_h1_update",
"update each ts step",
"",
3471 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
3475 auto setup_ts_monitor = [&]() {
3476 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*
this);
3479 auto monitor_ptr = setup_ts_monitor();
3481 TetPolynomialBase::switchCacheBaseOn<HDIV>(
3482 {elasticFeLhs.get(), elasticFeRhs.get()});
3486 double ts_delta_time;
3487 CHKERR TSGetTimeStep(ts, &ts_delta_time);
3499 monitor_ptr->ts_u = PETSC_NULLPTR;
3500 monitor_ptr->ts_t = dynamicTime;
3501 monitor_ptr->ts_step = dynamicStep;
3503 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3504 << dynamicTime <<
" delta time " << delta_time;
3505 dynamicTime += delta_time;
3508 for (; dynamicTime < final_time; dynamicTime += delta_time) {
3509 MOFEM_LOG(
"EP", Sev::inform) <<
"IT " << dynamicStep <<
" Time "
3510 << dynamicTime <<
" delta time " << delta_time;
3512 CHKERR TSSetStepNumber(ts, 0);
3514 CHKERR TSSetTimeStep(ts, ts_delta_time);
3515 if (!ts_h1_update) {
3518 CHKERR TSSolve(ts, PETSC_NULLPTR);
3519 if (!ts_h1_update) {
3523 monitor_ptr->ts_u = PETSC_NULLPTR;
3524 monitor_ptr->ts_t = dynamicTime;
3525 monitor_ptr->ts_step = dynamicStep;
3529 if (dynamicStep > max_it)
3534 TetPolynomialBase::switchCacheBaseOff<HDIV>(
3535 {elasticFeLhs.get(), elasticFeRhs.get()});
3543 auto set_block = [&](
auto name,
int dim) {
3544 std::map<int, Range> map;
3545 auto set_tag_impl = [&](
auto name) {
3550 std::regex((boost::format(
"%s(.*)") % name).str())
3553 for (
auto bc : bcs) {
3555 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
3557 map[bc->getMeshsetId()] = r;
3562 CHKERR set_tag_impl(name);
3564 return std::make_pair(name, map);
3567 auto set_skin = [&](
auto &&map) {
3568 for (
auto &
m : map.second) {
3575 auto set_tag = [&](
auto &&map) {
3577 auto name = map.first;
3578 int def_val[] = {-1};
3580 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER,
th,
3581 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
3583 for (
auto &
m : map.second) {
3591 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"BODY", 3))));
3592 listTagsToTransfer.push_back(set_tag(set_skin(set_block(
"MAT_ELASTIC", 3))));
3593 listTagsToTransfer.push_back(
3594 set_tag(set_skin(set_block(
"MAT_NEOHOOKEAN", 3))));
3595 listTagsToTransfer.push_back(set_tag(set_block(
"CONTACT", 2)));
3602 Vec f_residual, Vec var_vector,
3603 std::vector<Tag> tags_to_transfer) {
3609 rval = mField.get_moab().tag_get_handle(
"CRACK",
th);
3610 if (
rval == MB_SUCCESS) {
3611 CHKERR mField.get_moab().tag_delete(
th);
3613 int def_val[] = {0};
3614 CHKERR mField.get_moab().tag_get_handle(
3615 "CRACK", 1, MB_TYPE_INTEGER,
th, MB_TAG_SPARSE | MB_TAG_CREAT, def_val);
3617 CHKERR mField.get_moab().tag_clear_data(
th, *crackFaces, mark);
3618 tags_to_transfer.push_back(
th);
3620 auto get_tag = [&](
auto name,
auto dim) {
3621 auto &mob = mField.get_moab();
3623 double def_val[] = {0., 0., 0.};
3624 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
3625 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
3630 tags_to_transfer.push_back(get_tag(
"MaterialForce", 3));
3635 for (
auto t : listTagsToTransfer) {
3636 tags_to_transfer.push_back(
t);
3644 struct exclude_sdf {
3645 exclude_sdf(
Range &&r) : map(r) {}
3646 bool operator()(
FEMethod *fe_method_ptr) {
3648 if (map.find(ent) != map.end()) {
3658 contactTreeRhs->exeTestHook =
3663 auto get_post_proc = [&](
auto &post_proc_mesh,
auto sense) {
3665 auto post_proc_ptr =
3666 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
3667 mField, post_proc_mesh);
3668 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3669 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
3672 auto domain_ops = [&](
auto &fe,
int sense) {
3674 fe.getUserPolynomialBase() =
3675 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
3676 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3677 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
3679 auto piola_scale_ptr = boost::make_shared<double>(1.0);
3680 fe.getOpPtrVector().push_back(physicalEquations->returnOpSetScale(
3681 piola_scale_ptr, physicalEquations));
3683 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
3685 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
3688 fe.getOpPtrVector().push_back(
3689 physicalEquations->returnOpCalculateStretchFromStress(
3690 dataAtPts, physicalEquations));
3692 fe.getOpPtrVector().push_back(
3694 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
3699 piolaStress, dataAtPts->getVarPiolaPts(),
3700 boost::make_shared<double>(1), vec));
3702 bubbleField, dataAtPts->getVarPiolaPts(),
3703 boost::make_shared<double>(1), vec, MBMAXTYPE));
3705 rotAxis, dataAtPts->getVarRotAxisPts(), vec, MBTET));
3707 fe.getOpPtrVector().push_back(
3708 physicalEquations->returnOpCalculateVarStretchFromStress(
3709 dataAtPts, physicalEquations));
3711 fe.getOpPtrVector().push_back(
3713 stretchTensor, dataAtPts->getVarLogStreachPts(), vec, MBTET));
3718 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3720 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3723 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3725 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3727 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3729 fe.getOpPtrVector().push_back(
3733 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3734 tag,
true,
false, dataAtPts, physicalEquations));
3736 physicalEquations->returnOpCalculateEnergy(dataAtPts,
nullptr)) {
3737 fe.getOpPtrVector().push_back(op);
3746 struct OpSidePPMap :
public OpPPMap {
3747 OpSidePPMap(moab::Interface &post_proc_mesh,
3748 std::vector<EntityHandle> &map_gauss_pts,
3749 DataMapVec data_map_scalar, DataMapMat data_map_vec,
3750 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
3752 :
OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
3753 data_map_vec, data_map_mat, data_symm_map_mat),
3760 if (tagSense != OpPPMap::getSkeletonSense())
3772 vec_fields[
"SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
3773 vec_fields[
"SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
3774 vec_fields[
"Omega"] = dataAtPts->getRotAxisAtPts();
3775 vec_fields[
"ContactDisplacement"] = dataAtPts->getContactL2AtPts();
3776 vec_fields[
"AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
3777 vec_fields[
"X"] = dataAtPts->getLargeXH1AtPts();
3780 vec_fields[
"VarOmega"] = dataAtPts->getVarRotAxisPts();
3781 vec_fields[
"VarSpatialDisplacementL2"] =
3782 boost::make_shared<MatrixDouble>();
3784 spatialL2Disp, vec_fields[
"VarSpatialDisplacementL2"], vec, MBTET));
3788 vec_fields[
"ResSpatialDisplacementL2"] =
3789 boost::make_shared<MatrixDouble>();
3791 spatialL2Disp, vec_fields[
"ResSpatialDisplacementL2"], vec, MBTET));
3792 vec_fields[
"ResOmega"] = boost::make_shared<MatrixDouble>();
3794 rotAxis, vec_fields[
"ResOmega"], vec, MBTET));
3798 mat_fields[
"PiolaStress"] = dataAtPts->getApproxPAtPts();
3800 mat_fields[
"VarPiolaStress"] = dataAtPts->getVarPiolaPts();
3804 mat_fields[
"ResPiolaStress"] = boost::make_shared<MatrixDouble>();
3806 piolaStress, mat_fields[
"ResPiolaStress"],
3807 boost::make_shared<double>(1), vec));
3809 bubbleField, mat_fields[
"ResPiolaStress"],
3810 boost::make_shared<double>(1), vec, MBMAXTYPE));
3812 if (!internalStressTagName.empty()) {
3813 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
3814 switch (internalStressInterpOrder) {
3816 fe.getOpPtrVector().push_back(
3820 fe.getOpPtrVector().push_back(
3825 "Unsupported internal stress interpolation order %d",
3826 internalStressInterpOrder);
3831 mat_fields_symm[
"LogSpatialStretch"] =
3832 dataAtPts->getLogStretchTensorAtPts();
3833 mat_fields_symm[
"SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
3835 mat_fields_symm[
"VarLogSpatialStretch"] =
3836 dataAtPts->getVarLogStreachPts();
3841 mat_fields_symm[
"ResLogSpatialStretch"] =
3842 boost::make_shared<MatrixDouble>();
3843 fe.getOpPtrVector().push_back(
3845 stretchTensor, mat_fields_symm[
"ResLogSpatialStretch"], vec,
3850 fe.getOpPtrVector().push_back(
3854 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3871 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3877 post_proc_ptr->getOpPtrVector().push_back(
3879 dataAtPts->getContactL2AtPts()));
3881 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
3883 post_proc_ptr->getOpPtrVector().push_back(
3885 dataAtPts->getLargeXH1AtPts()));
3890 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
3891 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
3893 return post_proc_ptr;
3897 auto calcs_side_traction_and_displacements = [&](
auto &post_proc_ptr,
3900 auto contact_common_data_ptr = boost::make_shared<ContactOps::CommonData>();
3904 using SideEleOp = EleOnSide::UserDataOperator;
3906 mField, elementVolumeName,
SPACE_DIM, Sev::noisy);
3907 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3908 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
3909 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3910 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3911 materialH1Positions, frontAdjEdges);
3912 op_loop_domain_side->getOpPtrVector().push_back(
3914 piolaStress, contact_common_data_ptr->contactTractionPtr(),
3915 boost::make_shared<double>(1.0)));
3916 pip.push_back(op_loop_domain_side);
3918 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
3921 contactDisp, contact_common_data_ptr->contactDispPtr()));
3922 pip.push_back(
new OpTreeSearch(
3923 contactTreeRhs, contact_common_data_ptr, u_h1_ptr,
3925 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
3932 pip.push_back(op_this);
3933 auto contact_residual = boost::make_shared<MatrixDouble>();
3934 op_this->getOpPtrVector().push_back(
3936 contactDisp, contact_residual,
3939 op_this->getOpPtrVector().push_back(
3943 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
3947 {{
"res_contact", contact_residual}},
3961 auto post_proc_mesh = boost::make_shared<moab::Core>();
3962 auto post_proc_ptr = get_post_proc(post_proc_mesh, 1);
3963 auto post_proc_negative_sense_ptr = get_post_proc(post_proc_mesh, -1);
3964 CHKERR calcs_side_traction_and_displacements(post_proc_ptr,
3965 post_proc_ptr->getOpPtrVector());
3971 CHKERR mField.get_moab().get_adjacencies(own_tets,
SPACE_DIM - 1,
true,
3972 own_faces, moab::Interface::UNION);
3974 auto get_post_negative = [&](
auto &&ents) {
3975 auto crack_faces_pos = ents;
3976 auto crack_faces_neg = crack_faces_pos;
3977 auto skin =
get_skin(mField, own_tets);
3978 auto crack_on_proc_skin = intersect(crack_faces_pos, skin);
3979 for (
auto f : crack_on_proc_skin) {
3981 CHKERR mField.get_moab().get_adjacencies(&f, 1,
SPACE_DIM,
false, tet);
3982 tet = intersect(tet, own_tets);
3983 int side_number, sense, offset;
3984 CHKERR mField.get_moab().side_number(tet[0], f, side_number, sense,
3987 crack_faces_neg.erase(f);
3989 crack_faces_pos.erase(f);
3992 return std::make_pair(crack_faces_pos, crack_faces_neg);
3995 auto get_crack_faces = [&](
auto crack_faces) {
3996 auto get_adj = [&](
auto e,
auto dim) {
3998 CHKERR mField.get_moab().get_adjacencies(e, dim,
true, adj,
3999 moab::Interface::UNION);
4002 auto tets = get_adj(crack_faces, 3);
4003 auto faces = subtract(get_adj(tets, 2), crack_faces);
4004 tets = subtract(tets, get_adj(faces, 3));
4005 return subtract(crack_faces, get_adj(tets, 2));
4008 auto [crack_faces_pos, crack_faces_neg] =
4009 get_post_negative(intersect(own_faces, get_crack_faces(*crackFaces)));
4011 auto only_crack_faces = [&](
FEMethod *fe_method_ptr) {
4012 auto ent = fe_method_ptr->getFEEntityHandle();
4013 if (crack_faces_pos.find(ent) == crack_faces_pos.end()) {
4019 auto only_negative_crack_faces = [&](
FEMethod *fe_method_ptr) {
4020 auto ent = fe_method_ptr->getFEEntityHandle();
4021 if (crack_faces_neg.find(ent) == crack_faces_neg.end()) {
4027 auto get_adj_front = [&]() {
4028 auto skeleton_faces = *skeletonFaces;
4030 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2,
true, adj_front,
4031 moab::Interface::UNION);
4033 adj_front = intersect(adj_front, skeleton_faces);
4034 adj_front = subtract(adj_front, *crackFaces);
4035 adj_front = intersect(own_faces, adj_front);
4039 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4040 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
4042 auto post_proc_begin =
4046 post_proc_ptr->exeTestHook = only_crack_faces;
4047 post_proc_negative_sense_ptr->exeTestHook = only_negative_crack_faces;
4049 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4051 post_proc_negative_sense_ptr, 0,
4052 mField.get_comm_size());
4054 constexpr bool debug =
false;
4057 auto [adj_front_pos, adj_front_neg] =
4060 auto only_front_faces_pos = [adj_front_pos](
FEMethod *fe_method_ptr) {
4061 auto ent = fe_method_ptr->getFEEntityHandle();
4062 if (adj_front_pos.find(ent) == adj_front_pos.end()) {
4068 auto only_front_faces_neg = [adj_front_neg](
FEMethod *fe_method_ptr) {
4069 auto ent = fe_method_ptr->getFEEntityHandle();
4070 if (adj_front_neg.find(ent) == adj_front_neg.end()) {
4076 post_proc_ptr->exeTestHook = only_front_faces_pos;
4078 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
4079 post_proc_negative_sense_ptr->exeTestHook = only_front_faces_neg;
4081 post_proc_negative_sense_ptr, 0,
4082 mField.get_comm_size());
4087 CHKERR post_proc_end.writeFile(file.c_str());
4094 std::vector<Tag> tags_to_transfer) {
4099 auto post_proc_mesh = boost::make_shared<moab::Core>();
4100 auto post_proc_ptr =
4101 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4103 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4107 auto hybrid_disp = boost::make_shared<MatrixDouble>();
4108 post_proc_ptr->getOpPtrVector().push_back(
4111 auto hybrid_res = boost::make_shared<MatrixDouble>();
4112 post_proc_ptr->getOpPtrVector().push_back(
4116 post_proc_ptr->getOpPtrVector().push_back(
4120 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4124 {{
"hybrid_disp", hybrid_disp}},
4135 auto hybrid_res = boost::make_shared<MatrixDouble>();
4136 post_proc_ptr->getOpPtrVector().push_back(
4138 hybridSpatialDisp, hybrid_res,
4141 post_proc_ptr->getOpPtrVector().push_back(
4145 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4149 {{
"res_hybrid", hybrid_res}},
4160 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
4162 auto post_proc_begin =
4169 CHKERR post_proc_end.writeFile(file.c_str());
4177 constexpr bool debug =
false;
4179 auto get_tags_vec = [&](std::vector<std::pair<std::string, int>> names) {
4180 std::vector<Tag> tags;
4181 tags.reserve(names.size());
4182 auto create_and_clean = [&]() {
4184 for (
auto n : names) {
4185 tags.push_back(Tag());
4186 auto &tag = tags.back();
4188 auto rval = moab.tag_get_handle(
n.first.c_str(), tag);
4189 if (
rval == MB_SUCCESS) {
4190 moab.tag_delete(tag);
4192 double def_val[] = {0., 0., 0.};
4193 CHKERR moab.tag_get_handle(
n.first.c_str(),
n.second, MB_TYPE_DOUBLE,
4194 tag, MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4202 enum ExhangeTags { MATERIALFORCE, AREAGROWTH, GRIFFITHFORCE, FACEPRESSURE };
4204 auto tags = get_tags_vec({{
"MaterialForce", 3},
4206 {
"GriffithForce", 1},
4207 {
"FacePressure", 1}});
4209 auto calculate_material_forces = [&]() {
4215 auto get_face_material_force_fe = [&]() {
4217 auto fe_ptr = boost::make_shared<FaceEle>(
mField);
4218 fe_ptr->getRuleHook = [](int, int, int) {
return -1; };
4219 fe_ptr->setRuleHook =
4221 EshelbianPlasticity::AddHOOps<2, 2, 3>::add(
4223 fe_ptr->getOpPtrVector().push_back(
4227 auto op_loop_domain_side =
4230 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4231 boost::make_shared<CGGUserPolynomialBase>();
4232 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4233 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4235 op_loop_domain_side->getOpPtrVector().push_back(
4238 op_loop_domain_side->getOpPtrVector().push_back(
4242 op_loop_domain_side->getOpPtrVector().push_back(
4247 op_loop_domain_side->getOpPtrVector().push_back(
4249 fe_ptr->getOpPtrVector().push_back(op_loop_domain_side);
4255 auto integrate_face_material_force_fe = [&](
auto &&face_energy_fe) {
4263 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
4266 CHKERR VecGetLocalSize(
v.second, &size);
4268 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
4269 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( "
4270 << low <<
" " << high <<
" ) ";
4274 CHKERR print_loc_size(face_exchange,
"material face_exchange",
4278 mField.
get_moab(), face_exchange, tags[ExhangeTags::MATERIALFORCE]);
4285 "front_skin_faces_material_force_" +
4294 CHKERR integrate_face_material_force_fe(get_face_material_force_fe());
4299 auto calculate_front_material_force = [&]() {
4303 auto get_conn = [&](
auto e) {
4306 "get connectivity");
4310 auto get_conn_range = [&](
auto e) {
4313 "get connectivity");
4317 auto get_adj = [&](
auto e,
auto dim) {
4324 auto get_adj_range = [&](
auto e,
auto dim) {
4327 moab::Interface::UNION),
4332 auto get_material_force = [&](
auto r,
auto th) {
4337 return material_forces;
4342 auto crack_edges = get_adj_range(*
crackFaces, 1);
4343 auto front_nodes = get_conn_range(*
frontEdges);
4350 Range all_skin_faces;
4351 Range all_front_faces;
4354 auto calculate_edge_direction = [&](
auto e) {
4359 "get connectivity");
4360 std::array<double, 6> coords;
4365 &coords[0], &coords[1], &coords[2]};
4367 &coords[3], &coords[4], &coords[5]};
4370 t_dir(
i) = t_p1(
i) - t_p0(
i);
4375 auto calculate_force_through_node = [&]() {
4387 auto body_skin_conn = get_conn_range(body_skin);
4390 for (
auto n : front_nodes) {
4391 auto adj_tets = get_adj(
n, 3);
4393 auto conn = get_conn_range(adj_tets);
4394 adj_tets = get_adj_range(conn, 3);
4397 auto material_forces = get_material_force(skin_faces, tags[0]);
4401 all_skin_faces.merge(skin_faces);
4405 auto calculate_node_material_force = [&]() {
4407 getFTensor1FromPtr<SPACE_DIM>(material_forces.data().data());
4409 for (
auto face : skin_faces) {
4412 t_face_force_tmp(
I) = t_face_T(
I);
4415 auto face_tets = intersect(get_adj(face, 3), adj_tets);
4417 if (face_tets.empty()) {
4421 if (face_tets.size() != 1) {
4423 "face_tets.size() != 1");
4426 int side_number, sense, offset;
4430 "moab side number");
4431 t_face_force_tmp(
I) *= sense;
4432 t_node_force(
I) += t_face_force_tmp(
I);
4435 return t_node_force;
4438 auto calculate_crack_area_growth_direction = [&](
auto n,
4439 auto &t_node_force) {
4442 auto boundary_node = intersect(
Range(
n,
n), body_skin_conn);
4443 if (boundary_node.size()) {
4444 auto faces = intersect(get_adj(
n, 2), body_skin);
4445 for (
auto f : faces) {
4448 f, &t_normal_face(0));
4449 t_project(
I) += t_normal_face(
I);
4451 t_project.normalize();
4454 auto adj_faces = intersect(get_adj(
n, 2), *
crackFaces);
4455 if (adj_faces.empty()) {
4457 intersect(get_adj(
n, 1), unite(*
frontEdges, body_edges));
4459 for (
auto e : adj_edges) {
4460 auto t_dir = calculate_edge_direction(e);
4465 t_area_dir(
I) = -t_node_force(
I) / t_node_force.
l2();
4466 t_area_dir(
I) *=
l / 2;
4474 if (boundary_node.size()) {
4475 t_Q(
I,
J) -= t_project(
I) * t_project(
J);
4479 auto front_edges = get_adj(
n, 1);
4481 for (
auto f : adj_faces) {
4486 std::array<double, 9> coords;
4492 coords.data(), &t_face_normal(0), &t_d_normal(0, 0, 0));
4493 auto n_it = std::find(conn, conn + num_nodes,
n);
4494 auto n_index = std::distance(conn, n_it);
4497 t_d_normal(0, n_index, 0), t_d_normal(0, n_index, 1),
4498 t_d_normal(0, n_index, 2),
4500 t_d_normal(1, n_index, 0), t_d_normal(1, n_index, 1),
4501 t_d_normal(1, n_index, 2),
4503 t_d_normal(2, n_index, 0), t_d_normal(2, n_index, 1),
4504 t_d_normal(2, n_index, 2)};
4507 t_projected_hessian(
I,
J) =
4508 t_Q(
I,
K) * (t_face_hessian(
K,
L) * t_Q(
L,
J));
4511 t_face_normal(
I) * t_projected_hessian(
I,
K) / 2.;
4517 auto t_node_force = calculate_node_material_force();
4521 &
n, 1, &t_node_force(0)),
4524 auto get_area_dir = [&]() {
4526 calculate_crack_area_growth_direction(
n, t_node_force);
4531 adj_edges.merge(intersect(get_adj_range(seed_n, 1),
4533 seed_n = get_conn_range(adj_edges);
4536 skin_adj_edges.merge(
Range(
n,
n));
4537 seed_n = subtract(seed_n, skin_adj_edges);
4538 for (
auto sn : seed_n) {
4539 auto t_area_dir_sn =
4540 calculate_crack_area_growth_direction(sn, t_node_force);
4541 t_area_dir(
I) += t_area_dir_sn(
I);
4547 auto t_area_dir = get_area_dir();
4553 auto griffith = -t_node_force(
I) * t_area_dir(
I) /
4554 (t_area_dir(
K) * t_area_dir(
K));
4561 auto ave_node_force = [&](
auto th) {
4566 auto conn = get_conn(e);
4567 auto data = get_material_force(conn,
th);
4568 auto t_node = getFTensor1FromPtr<SPACE_DIM>(data.data().data());
4570 for (
auto n : conn) {
4571 t_edge(
I) += t_node(
I);
4574 t_edge(
I) /= conn.size();
4577 calculate_edge_direction(e);
4594 auto ave_node_griffith_energy = [&](
auto th) {
4599 tags[ExhangeTags::MATERIALFORCE], &e, 1, &t_edge_force(0));
4602 &e, 1, &t_edge_area_dir(0));
4603 double griffith_energy = -t_edge_force(
I) * t_edge_area_dir(
I) /
4604 (t_edge_area_dir(
K) * t_edge_area_dir(
K));
4610 CHKERR ave_node_force(tags[ExhangeTags::MATERIALFORCE]);
4611 CHKERR ave_node_force(tags[ExhangeTags::AREAGROWTH]);
4612 CHKERR ave_node_griffith_energy(tags[ExhangeTags::GRIFFITHFORCE]);
4617 CHKERR calculate_force_through_node();
4621 auto adj_faces = get_adj(e, 2);
4622 auto crack_face = intersect(get_adj(e, 2), *
crackFaces);
4626 all_front_faces.merge(adj_faces);
4632 &e, 1, &t_edge_force(0));
4634 calculate_edge_direction(e);
4643 for (
auto f : adj_faces) {
4647 int side_number, sense, offset;
4650 auto dot = -sense * t_cross(
I) * t_normal(
I);
4652 tags[ExhangeTags::GRIFFITHFORCE], &
f, 1, &dot),
4660 CHKERR TSGetStepNumber(ts, &ts_step);
4662 "front_edges_material_force_" +
4663 std::to_string(ts_step) +
".vtk",
4666 "front_skin_faces_material_force_" +
4667 std::to_string(ts_step) +
".vtk",
4670 "front_faces_material_force_" +
4671 std::to_string(ts_step) +
".vtk",
4680 mField.
get_moab(), edge_exchange, tags[ExhangeTags::MATERIALFORCE]);
4682 mField.
get_moab(), edge_exchange, tags[ExhangeTags::AREAGROWTH]);
4689 auto print_results = [&]() {
4692 auto get_conn_range = [&](
auto e) {
4695 "get connectivity");
4699 auto get_tag_data = [&](
auto &ents,
auto tag,
auto dim) {
4700 std::vector<double> data(ents.size() * dim);
4707 auto at_nodes = [&]() {
4710 auto material_force =
4711 get_tag_data(conn, tags[ExhangeTags::MATERIALFORCE], 3);
4712 auto area_growth = get_tag_data(conn, tags[ExhangeTags::AREAGROWTH], 3);
4713 auto griffith_force =
4714 get_tag_data(conn, tags[ExhangeTags::GRIFFITHFORCE], 1);
4715 std::vector<double> coords(conn.size() * 3);
4718 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Material force at nodes";
4719 for (
size_t i = 0;
i < conn.size(); ++
i) {
4721 <<
"Node " << conn[
i] <<
" coords "
4722 << coords[
i * 3 + 0] <<
" " << coords[
i * 3 + 1] <<
" "
4723 << coords[
i * 3 + 2] <<
" material force "
4724 << material_force[
i * 3 + 0] <<
" "
4725 << material_force[
i * 3 + 1] <<
" "
4726 << material_force[
i * 3 + 2] <<
" area growth "
4727 << area_growth[
i * 3 + 0] <<
" " << area_growth[
i * 3 + 1]
4728 <<
" " << area_growth[
i * 3 + 2] <<
" griffith force "
4729 << griffith_force[
i];
4739 CHKERR calculate_material_forces();
4740 CHKERR calculate_front_material_force();
4747 bool set_orientation) {
4750 constexpr bool debug =
false;
4751 constexpr auto sev = Sev::verbose;
4756 Range body_skin_edges;
4758 moab::Interface::UNION);
4759 Range boundary_skin_verts;
4761 boundary_skin_verts,
true);
4764 Range geometry_edges_verts;
4766 geometry_edges_verts,
true);
4767 Range crack_faces_verts;
4770 Range crack_faces_edges;
4772 *
crackFaces, 1,
true, crack_faces_edges, moab::Interface::UNION);
4773 Range crack_faces_tets;
4775 *
crackFaces, 3,
true, crack_faces_tets, moab::Interface::UNION);
4781 moab::Interface::UNION);
4782 Range front_verts_edges;
4784 front_verts, 1,
true, front_verts_edges, moab::Interface::UNION);
4786 auto get_tags_vec = [&](
auto tag_name,
int dim) {
4787 std::vector<Tag> tags(1);
4792 auto create_and_clean = [&]() {
4795 auto rval = moab.tag_get_handle(tag_name, tags[0]);
4796 if (
rval == MB_SUCCESS) {
4797 moab.tag_delete(tags[0]);
4799 double def_val[] = {0., 0., 0.};
4800 CHKERR moab.tag_get_handle(tag_name, dim, MB_TYPE_DOUBLE, tags[0],
4801 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
4810 auto get_adj_front = [&](
bool subtract_crack) {
4813 adj_front, moab::Interface::UNION);
4815 adj_front = subtract(adj_front, *
crackFaces);
4821 auto th_front_position = get_tags_vec(
"FrontPosition", 3);
4822 auto th_max_face_energy = get_tags_vec(
"MaxFaceEnergy", 1);
4826 auto get_crack_adj_tets = [&](
auto r) {
4827 Range crack_faces_conn;
4829 Range crack_faces_conn_tets;
4831 true, crack_faces_conn_tets,
4832 moab::Interface::UNION);
4833 return crack_faces_conn_tets;
4836 auto get_layers_for_sides = [&](
auto &side) {
4837 std::vector<Range> layers;
4841 auto get_adj = [&](
auto &r,
int dim) {
4844 moab::Interface::UNION);
4848 auto get_tets = [&](
auto r) {
return get_adj(r,
SPACE_DIM); };
4853 Range front_faces = get_adj(front_nodes, 2);
4854 front_faces = subtract(front_faces, *
crackFaces);
4855 auto front_tets = get_tets(front_nodes);
4856 auto front_side = intersect(side, front_tets);
4857 layers.push_back(front_side);
4860 adj_faces = intersect(adj_faces, front_faces);
4861 auto adj_faces_tets = get_tets(adj_faces);
4862 adj_faces_tets = intersect(adj_faces_tets, front_tets);
4863 layers.push_back(unite(layers.back(), adj_faces_tets));
4864 if (layers.back().size() == layers[layers.size() - 2].size()) {
4875 auto layers_top = get_layers_for_sides(sides_pair.first);
4876 auto layers_bottom = get_layers_for_sides(sides_pair.second);
4888 MOFEM_LOG(
"EP", sev) <<
"Nb. layers " << layers_top.size();
4890 for (
auto &r : layers_top) {
4891 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
4894 "layers_top_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
4899 for (
auto &r : layers_bottom) {
4900 MOFEM_LOG(
"EP", sev) <<
"Layer " <<
l <<
" size " << r.size();
4903 "layers_bottom_" + boost::lexical_cast<std::string>(
l) +
".vtk", r);
4909 auto get_cross = [&](
auto t_dir,
auto f) {
4921 auto get_sense = [&](
auto f,
auto e) {
4922 int side, sense, offset;
4925 return std::make_tuple(side, sense, offset);
4928 auto calculate_edge_direction = [&](
auto e,
auto normalize =
true) {
4932 std::array<double, 6> coords;
4935 &coords[0], &coords[1], &coords[2]};
4937 &coords[3], &coords[4], &coords[5]};
4940 t_dir(
i) = t_p1(
i) - t_p0(
i);
4946 auto evaluate_face_energy_and_set_orientation = [&](
auto front_edges,
4953 Tag th_material_force;
4955 case GRIFFITH_FORCE:
4956 case GRIFFITH_SKELETON:
4963 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
4964 "Unknown energy release selector");
4972 auto find_maximal_face_energy = [&](
auto front_edges,
auto front_faces,
4973 auto &edge_face_max_energy_map) {
4982 for (
auto e : front_edges) {
4984 double griffith_force;
4990 faces = subtract(intersect(faces, front_faces), body_skin);
4991 std::vector<double> face_energy(faces.size());
4993 face_energy.data());
4994 auto max_energy_it =
4995 std::max_element(face_energy.begin(), face_energy.end());
4997 max_energy_it != face_energy.end() ? *max_energy_it : 0;
4999 edge_face_max_energy_map[e] =
5000 std::make_tuple(faces[max_energy_it - face_energy.begin()],
5001 griffith_force,
static_cast<double>(0));
5003 <<
"Edge " << e <<
" griffith force " << griffith_force
5004 <<
" max face energy " << max_energy <<
" factor "
5005 << max_energy / griffith_force;
5007 max_faces.insert(faces[max_energy_it - face_energy.begin()]);
5029 auto calculate_face_orientation = [&](
auto &edge_face_max_energy_map) {
5032 auto up_down_face = [&](
5034 auto &face_angle_map_up,
5035 auto &face_angle_map_down
5040 for (
auto &
m : edge_face_max_energy_map) {
5042 auto [max_face, energy, opt_angle] =
m.second;
5046 faces = intersect(faces, front_faces);
5050 moab::Interface::UNION);
5051 if (adj_tets.size()) {
5056 moab::Interface::UNION);
5057 if (adj_tets.size()) {
5059 Range adj_tets_faces;
5062 adj_tets,
SPACE_DIM - 1,
false, adj_tets_faces,
5063 moab::Interface::UNION);
5064 adj_tets_faces = intersect(adj_tets_faces, faces);
5069 get_cross(calculate_edge_direction(e,
true), max_face);
5070 auto [side_max, sense_max, offset_max] = get_sense(max_face, e);
5071 t_cross_max(
i) *= sense_max;
5073 for (
auto t : adj_tets) {
5074 Range adj_tets_faces;
5076 &
t, 1,
SPACE_DIM - 1,
false, adj_tets_faces);
5077 adj_tets_faces = intersect(adj_tets_faces, faces);
5079 subtract(adj_tets_faces,
Range(max_face, max_face));
5081 if (adj_tets_faces.size() == 1) {
5085 auto t_cross = get_cross(calculate_edge_direction(e,
true),
5087 auto [side, sense, offset] =
5088 get_sense(adj_tets_faces[0], e);
5089 t_cross(
i) *= sense;
5090 double dot = t_cross(
i) * t_cross_max(
i);
5091 auto angle = std::acos(dot);
5095 th_face_energy, adj_tets_faces, &face_energy);
5097 auto [side_face, sense_face, offset_face] =
5098 get_sense(
t, max_face);
5100 if (sense_face > 0) {
5101 face_angle_map_up[e] = std::make_tuple(face_energy, angle,
5105 face_angle_map_down[e] = std::make_tuple(
5106 face_energy, -angle, adj_tets_faces[0]);
5117 auto calc_optimal_angle = [&](
5119 auto &face_angle_map_up,
5120 auto &face_angle_map_down
5125 for (
auto &
m : edge_face_max_energy_map) {
5127 auto &[max_face, e0,
a0] =
m.second;
5129 if (std::abs(e0) > std::numeric_limits<double>::epsilon()) {
5131 if (face_angle_map_up.find(e) == face_angle_map_up.end() ||
5132 face_angle_map_down.find(e) == face_angle_map_down.end()) {
5137 case GRIFFITH_FORCE:
5138 case GRIFFITH_SKELETON: {
5140 Tag th_material_force;
5145 th_material_force, &e, 1, &t_material_force(0));
5146 auto material_force_magnitude = t_material_force.
l2();
5147 if (material_force_magnitude <
5148 std::numeric_limits<double>::epsilon()) {
5153 auto t_edge_dir = calculate_edge_direction(e,
true);
5154 auto t_cross_max = get_cross(t_edge_dir, max_face);
5155 auto [side, sense, offset] = get_sense(max_face, e);
5156 t_cross_max(sense) *= sense;
5163 t_cross_max.normalize();
5166 t_material_force(
J) * t_cross_max(
K);
5167 a0 = -std::asin(t_cross(
I) * t_edge_dir(
I));
5170 <<
"Optimal angle " <<
a0 <<
" energy " << e0;
5176 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
5177 "Unknown energy release selector");
5187 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5189 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
5190 face_angle_map_down;
5191 CHKERR up_down_face(face_angle_map_up, face_angle_map_down);
5192 CHKERR calc_optimal_angle(face_angle_map_up, face_angle_map_down);
5196 auto th_angle = get_tags_vec(
"Angle", 1);
5198 for (
auto &
m : face_angle_map_up) {
5199 auto [e,
a, face] =
m.second;
5204 for (
auto &
m : face_angle_map_down) {
5205 auto [e,
a, face] =
m.second;
5210 Range max_energy_faces;
5211 for (
auto &
m : edge_face_max_energy_map) {
5212 auto [face, e, angle] =
m.second;
5213 max_energy_faces.insert(face);
5229 auto get_conn = [&](
auto e) {
5236 auto get_adj = [&](
auto e,
auto dim) {
5239 e, dim,
false, adj, moab::Interface::UNION),
5244 auto get_coords = [&](
auto v) {
5252 auto get_rotated_normal = [&](
auto e,
auto f,
auto angle) {
5255 auto t_edge_dir = calculate_edge_direction(e,
true);
5256 auto [side, sense, offset] = get_sense(
f, e);
5257 t_edge_dir(
i) *= sense;
5258 t_edge_dir.normalize();
5259 t_edge_dir(
i) *= angle;
5264 t_rotated_normal(
i) = t_R(
i,
j) * t_normal(
j);
5265 return std::make_tuple(t_normal, t_rotated_normal);
5268 auto set_coord = [&](
auto v,
auto &adj_vertex_tets_verts,
auto &coords,
5269 auto &t_move,
auto gamma) {
5270 auto index = adj_vertex_tets_verts.index(
v);
5272 for (
auto ii : {0, 1, 2}) {
5273 coords[3 * index + ii] += gamma * t_move(ii);
5280 auto tets_quality = [&](
auto quality,
auto &adj_vertex_tets_verts,
5281 auto &adj_vertex_tets,
auto &coords) {
5282 for (
auto t : adj_vertex_tets) {
5286 std::array<double, 12> tet_coords;
5287 for (
auto n = 0;
n != 4; ++
n) {
5288 auto index = adj_vertex_tets_verts.index(conn[
n]);
5292 for (
auto ii = 0; ii != 3; ++ii) {
5293 tet_coords[3 *
n + ii] = coords[3 * index + ii];
5297 if (!std::isnormal(q))
5299 quality = std::min(quality, q);
5305 auto calculate_free_face_node_displacement =
5306 [&](
auto &edge_face_max_energy_map) {
5308 auto get_vertex_edges = [&](
auto vertex) {
5315 vertex_edges = subtract(vertex_edges, front_verts_edges);
5317 if (boundary_skin_verts.size() &&
5318 boundary_skin_verts.find(vertex[0]) !=
5319 boundary_skin_verts.end()) {
5320 MOFEM_LOG(
"EP", sev) <<
"Boundary vertex";
5321 vertex_edges = intersect(vertex_edges, body_skin_edges);
5323 if (geometry_edges_verts.size() &&
5324 geometry_edges_verts.find(vertex[0]) !=
5325 geometry_edges_verts.end()) {
5326 MOFEM_LOG(
"EP", sev) <<
"Geometry edge vertex";
5327 vertex_edges = intersect(vertex_edges, geometry_edges);
5329 if (crack_faces_verts.size() &&
5330 crack_faces_verts.find(vertex[0]) !=
5331 crack_faces_verts.end()) {
5332 MOFEM_LOG(
"EP", sev) <<
"Crack face vertex";
5333 vertex_edges = intersect(vertex_edges, crack_faces_edges);
5340 return vertex_edges;
5345 using Bundle = std::vector<
5351 std::map<EntityHandle, Bundle> edge_bundle_map;
5353 for (
auto &
m : edge_face_max_energy_map) {
5355 auto edge =
m.first;
5356 auto &[max_face, energy, opt_angle] =
m.second;
5359 auto [t_normal, t_rotated_normal] =
5360 get_rotated_normal(edge, max_face, opt_angle);
5362 auto front_vertex = get_conn(
Range(
m.first,
m.first));
5363 auto adj_tets = get_adj(
Range(max_face, max_face), 3);
5364 auto adj_tets_faces = get_adj(adj_tets, 2);
5365 auto adj_front_faces = subtract(
5366 intersect(get_adj(
Range(edge, edge), 2), adj_tets_faces),
5368 if (adj_front_faces.size() > 3)
5370 "adj_front_faces.size()>3");
5374 &t_material_force(0));
5375 std::vector<double> griffith_energy(adj_front_faces.size());
5377 th_face_energy, adj_front_faces, griffith_energy.data());
5380 auto set_edge_bundle = [&](
auto min_gamma) {
5381 for (
auto rotated_f : adj_front_faces) {
5383 double rotated_face_energy =
5384 griffith_energy[adj_front_faces.index(rotated_f)];
5386 auto vertex = subtract(get_conn(
Range(rotated_f, rotated_f)),
5388 if (vertex.size() != 1) {
5390 "Wrong number of vertex to move");
5392 auto front_vertex_edges_vertex = get_conn(
5393 intersect(get_adj(front_vertex, 1), crack_faces_edges));
5395 vertex, front_vertex_edges_vertex);
5396 if (vertex.empty()) {
5400 auto face_cardinality = [&](
auto f,
auto &seen_front_edges) {
5403 subtract(body_skin_edges, crack_faces_edges));
5406 for (;
c < 10; ++
c) {
5408 subtract(get_adj(faces, 1), seen_front_edges);
5409 if (front_edges.size() == 0) {
5412 auto front_connected_edges =
5413 intersect(front_edges, whole_front);
5414 if (front_connected_edges.size()) {
5415 seen_front_edges.merge(front_connected_edges);
5418 faces.merge(get_adj(front_edges, 2));
5425 double rotated_face_cardinality = face_cardinality(
5431 rotated_face_cardinality = std::max(rotated_face_cardinality,
5434 auto t_vertex_coords = get_coords(vertex);
5435 auto vertex_edges = get_vertex_edges(vertex);
5444 for (
auto e_used_to_move_detection : vertex_edges) {
5445 auto edge_conn = get_conn(
Range(e_used_to_move_detection,
5446 e_used_to_move_detection));
5447 edge_conn = subtract(edge_conn, vertex);
5457 t_v0(
i) = (t_v_e0(
i) + t_v_e1(
i)) / 2;
5461 (t_v0(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5463 (t_v3(
i) - t_vertex_coords(
i)) * t_rotated_normal(
i);
5466 constexpr double eps =
5467 std::numeric_limits<double>::epsilon();
5468 if (std::isnormal(gamma) && gamma < 1.0 -
eps &&
5471 t_move(
i) = gamma * (t_v3(
i) - t_vertex_coords(
i));
5473 auto check_rotated_face_directoon = [&]() {
5475 t_delta(
i) = t_vertex_coords(
i) + t_move(
i) - t_v0(
i);
5478 (t_material_force(
i) / t_material_force.
l2()) *
5480 return -dot > 0 ? true :
false;
5483 if (check_rotated_face_directoon()) {
5486 <<
"Crack edge " << edge <<
" moved face "
5488 <<
" edge: " << e_used_to_move_detection
5489 <<
" face direction/energy " << rotated_face_energy
5490 <<
" face cardinality " << rotated_face_cardinality
5491 <<
" gamma: " << gamma;
5493 auto &bundle = edge_bundle_map[edge];
5494 bundle.emplace_back(rotated_f, e_used_to_move_detection,
5495 vertex[0], t_move, 1,
5496 rotated_face_cardinality, gamma);
5503 set_edge_bundle(std::numeric_limits<double>::epsilon());
5504 if (edge_bundle_map[edge].empty()) {
5505 set_edge_bundle(-1.);
5509 return edge_bundle_map;
5512 auto get_sort_by_energy = [&](
auto &edge_face_max_energy_map) {
5513 std::map<double, std::tuple<EntityHandle, EntityHandle, double>>
5516 for (
auto &
m : edge_face_max_energy_map) {
5518 auto &[max_face, energy, opt_angle] =
m.second;
5519 sort_by_energy[energy] = std::make_tuple(e, max_face, opt_angle);
5522 return sort_by_energy;
5525 auto set_tag = [&](
auto &&adj_edges_map,
auto &&sort_by_energy) {
5528 Tag th_face_pressure;
5530 mField.
get_moab().tag_get_handle(
"FacePressure", th_face_pressure),
5532 auto get_face_pressure = [&](
auto face) {
5541 <<
"Number of edges to check " << sort_by_energy.size();
5543 enum face_energy { POSITIVE, NEGATIVE };
5544 constexpr bool skip_negative =
true;
5546 for (
auto fe : {face_energy::POSITIVE, face_energy::NEGATIVE}) {
5550 for (
auto it = sort_by_energy.rbegin(); it != sort_by_energy.rend();
5553 auto energy = it->first;
5554 auto [max_edge, max_face, opt_angle] = it->second;
5556 auto face_pressure = get_face_pressure(max_face);
5557 if (skip_negative) {
5558 if (fe == face_energy::POSITIVE) {
5559 if (face_pressure < 0) {
5561 <<
"Skip negative face " << max_face <<
" with energy "
5562 << energy <<
" and pressure " << face_pressure;
5569 <<
"Check face " << max_face <<
" edge " << max_edge
5570 <<
" energy " << energy <<
" optimal angle " << opt_angle
5571 <<
" face pressure " << face_pressure;
5573 auto jt = adj_edges_map.find(max_edge);
5574 if (jt == adj_edges_map.end()) {
5576 <<
"Edge " << max_edge <<
" not found in adj_edges_map";
5579 auto &bundle = jt->second;
5581 auto find_max_in_bundle_impl = [&](
auto edge,
auto &bundle,
5588 double max_quality = -2;
5589 double max_quality_evaluated = -2;
5590 double min_cardinality = std::numeric_limits<double>::max();
5594 for (
auto &b : bundle) {
5595 auto &[face, move_edge, vertex, t_move, quality, cardinality,
5598 auto adj_vertex_tets = get_adj(
Range(vertex, vertex), 3);
5599 auto adj_vertex_tets_verts = get_conn(adj_vertex_tets);
5600 std::vector<double> coords(3 * adj_vertex_tets_verts.size());
5602 adj_vertex_tets_verts, coords.data()),
5605 set_coord(vertex, adj_vertex_tets_verts, coords, t_move, gamma);
5606 quality = tets_quality(quality, adj_vertex_tets_verts,
5607 adj_vertex_tets, coords);
5609 auto eval_quality = [](
auto q,
auto c,
auto edge_gamma) {
5613 return ((edge_gamma < 0) ? (q / 2) : q) / pow(
c, 2);
5617 if (eval_quality(quality, cardinality, edge_gamma) >=
5618 max_quality_evaluated) {
5619 max_quality = quality;
5620 min_cardinality = cardinality;
5621 vertex_max = vertex;
5623 move_edge_max = move_edge;
5624 t_move_last(
i) = t_move(
i);
5625 max_quality_evaluated =
5626 eval_quality(max_quality, min_cardinality, edge_gamma);
5630 return std::make_tuple(vertex_max, face_max, t_move_last,
5631 max_quality, min_cardinality);
5634 auto find_max_in_bundle = [&](
auto edge,
auto &bundle) {
5635 auto b_org_bundle = bundle;
5636 auto r = find_max_in_bundle_impl(edge, bundle, 1.);
5637 auto &[vertex_max, face_max, t_move_last, max_quality,
5639 if (max_quality < 0) {
5640 for (
double gamma = 0.95; gamma >= 0.45; gamma -= 0.05) {
5641 bundle = b_org_bundle;
5642 r = find_max_in_bundle_impl(edge, bundle, gamma);
5643 auto &[vertex_max, face_max, t_move_last, max_quality,
5646 <<
"Back tracking: gamma " << gamma <<
" edge " << edge
5647 <<
" quality " << max_quality <<
" cardinality "
5649 if (max_quality > 0.01) {
5651 t_move_last(
I) *= gamma;
5662 auto set_tag_to_vertex_and_face = [&](
auto &&r,
auto &quality) {
5664 auto &[
v,
f, t_move, q, cardinality] = r;
5666 if ((q > 0 && std::isnormal(q)) && energy > 0) {
5669 <<
"Set tag: vertex " <<
v <<
" face " <<
f <<
" "
5670 << max_edge <<
" move " << t_move <<
" energy " << energy
5671 <<
" quality " << q <<
" cardinality " << cardinality;
5682 double quality = -2;
5683 CHKERR set_tag_to_vertex_and_face(
5685 find_max_in_bundle(max_edge, bundle),
5691 if (quality > 0 && std::isnormal(quality) && energy > 0) {
5693 <<
"Crack face set with quality: " << quality;
5706 MOFEM_LOG(
"EP", sev) <<
"Calculate orientation";
5707 std::map<EntityHandle, std::tuple<EntityHandle, double, double>>
5708 edge_face_max_energy_map;
5709 CHKERR find_maximal_face_energy(front_edges, front_faces,
5710 edge_face_max_energy_map);
5711 CHKERR calculate_face_orientation(edge_face_max_energy_map);
5713 MOFEM_LOG(
"EP", sev) <<
"Calculate node positions";
5716 calculate_free_face_node_displacement(edge_face_max_energy_map),
5717 get_sort_by_energy(edge_face_max_energy_map)
5725 CHKERR evaluate_face_energy_and_set_orientation(
5726 *
frontEdges, get_adj_front(
false), sides_pair, th_front_position);
5744 auto get_max_moved_faces = [&]() {
5745 Range max_moved_faces;
5746 auto adj_front = get_adj_front(
false);
5747 std::vector<double> face_energy(adj_front.size());
5749 face_energy.data());
5750 for (
int i = 0;
i != adj_front.size(); ++
i) {
5751 if (face_energy[
i] > std::numeric_limits<double>::epsilon()) {
5752 max_moved_faces.insert(adj_front[
i]);
5756 return boost::make_shared<Range>(max_moved_faces);
5767 "max_moved_faces_" +
5782 Tag th_front_position;
5784 mField.
get_moab().tag_get_handle(
"FrontPosition", th_front_position);
5789 std::vector<double> coords(3 * verts.size());
5791 std::vector<double> pos(3 * verts.size());
5793 for (
int i = 0;
i != 3 * verts.size(); ++
i) {
5794 coords[
i] += pos[
i];
5797 double zero[] = {0., 0., 0.};
5802 constexpr bool debug =
false;
5807 "set_coords_faces_" +
5818 constexpr bool potential_crack_debug =
false;
5819 if constexpr (potential_crack_debug) {
5822 Range crack_front_verts;
5827 Range crack_front_faces;
5829 true, crack_front_faces,
5830 moab::Interface::UNION);
5831 crack_front_faces = intersect(crack_front_faces, add_ents);
5838 auto get_crack_faces = [&]() {
5846 auto get_extended_crack_faces = [&]() {
5847 auto get_faces_of_crack_front_verts = [&](
auto crack_faces_org) {
5848 ParallelComm *pcomm =
5853 if (!pcomm->rank()) {
5855 auto get_nodes = [&](
auto &&e) {
5858 "get connectivity");
5862 auto get_adj = [&](
auto &&e,
auto dim,
5863 auto t = moab::Interface::UNION) {
5875 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
5878 auto front_block_nodes = get_nodes(front_block_edges);
5882 s = crack_faces.size();
5884 auto crack_face_nodes = get_nodes(crack_faces_org);
5885 auto crack_faces_edges =
5886 get_adj(crack_faces_org, 1, moab::Interface::UNION);
5889 front_block_edges = subtract(front_block_edges, crack_skin);
5890 auto crack_skin_nodes = get_nodes(crack_skin);
5891 crack_skin_nodes.merge(front_block_nodes);
5893 auto crack_skin_faces =
5894 get_adj(crack_skin, 2, moab::Interface::UNION);
5896 subtract(subtract(crack_skin_faces, crack_faces_org), body_skin);
5898 crack_faces = crack_faces_org;
5899 for (
auto f : crack_skin_faces) {
5900 auto edges = intersect(
5901 get_adj(
Range(
f,
f), 1, moab::Interface::UNION), crack_skin);
5905 if (edges.size() == 2) {
5907 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
5911 if (edges.size() == 2) {
5912 auto edge_conn = get_nodes(
Range(edges));
5913 auto faces = intersect(get_adj(edges, 2, moab::Interface::UNION),
5915 if (faces.size() == 2) {
5916 auto edge0_conn = get_nodes(
Range(edges[0], edges[0]));
5917 auto edge1_conn = get_nodes(
Range(edges[1], edges[1]));
5918 auto edges_conn = intersect(intersect(edge0_conn, edge1_conn),
5924 moab::Interface::INTERSECT),
5929 if (node_edges.size()) {
5934 auto get_t_dir = [&](
auto e_conn) {
5935 auto other_node = subtract(e_conn,
edges_conn);
5939 t_dir(
i) -= t_v0(
i);
5945 get_t_dir(edge0_conn)(
i) + get_t_dir(edge1_conn)(
i);
5948 t_crack_surface_ave_dir(
i) = 0;
5949 for (
auto e : node_edges) {
5950 auto e_conn = get_nodes(
Range(e, e));
5951 auto t_dir = get_t_dir(e_conn);
5952 t_crack_surface_ave_dir(
i) += t_dir(
i);
5955 auto dot = t_ave_dir(
i) * t_crack_surface_ave_dir(
i);
5958 if (dot < -std::numeric_limits<double>::epsilon()) {
5959 crack_faces.insert(
f);
5962 crack_faces.insert(
f);
5966 }
else if (edges.size() == 3) {
5967 crack_faces.insert(
f);
5971 if (edges.size() == 1) {
5973 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
5976 intersect(get_adj(
Range(
f,
f), 1, moab::Interface::UNION),
5977 front_block_edges));
5978 if (edges.size() == 2) {
5979 crack_faces.insert(
f);
5985 crack_faces_org = crack_faces;
5987 }
while (s != crack_faces.size());
5993 return get_faces_of_crack_front_verts(get_crack_faces());
5998 get_extended_crack_faces());
6001 auto reconstruct_crack_faces = [&](
auto crack_faces) {
6002 ParallelComm *pcomm =
6008 Range new_crack_faces;
6009 if (!pcomm->rank()) {
6011 auto get_nodes = [&](
auto &&e) {
6014 "get connectivity");
6018 auto get_adj = [&](
auto &&e,
auto dim,
6019 auto t = moab::Interface::UNION) {
6027 auto get_test_on_crack_surface = [&]() {
6028 auto crack_faces_nodes =
6029 get_nodes(crack_faces);
6030 auto crack_faces_tets =
6031 get_adj(crack_faces_nodes, 3,
6032 moab::Interface::UNION);
6036 auto crack_faces_tets_nodes =
6037 get_nodes(crack_faces_tets);
6038 crack_faces_tets_nodes =
6039 subtract(crack_faces_tets_nodes, crack_faces_nodes);
6041 subtract(crack_faces_tets, get_adj(crack_faces_tets_nodes, 3,
6042 moab::Interface::UNION));
6044 get_adj(crack_faces_tets, 2,
6045 moab::Interface::UNION);
6047 new_crack_faces.merge(crack_faces);
6049 return std::make_tuple(new_crack_faces, crack_faces_tets);
6052 auto carck_faces_test_edges = [&](
auto faces,
auto tets) {
6053 auto adj_tets_faces = get_adj(tets, 2, moab::Interface::UNION);
6054 auto adj_faces_edges = get_adj(subtract(faces, adj_tets_faces), 1,
6055 moab::Interface::UNION);
6056 auto adj_tets_edges = get_adj(tets, 1, moab::Interface::UNION);
6059 adj_faces_edges.merge(geometry_edges);
6060 adj_faces_edges.merge(front_block_edges);
6062 auto boundary_tets_edges = intersect(adj_tets_edges, adj_faces_edges);
6063 auto boundary_test_nodes = get_nodes(boundary_tets_edges);
6064 auto boundary_test_nodes_edges =
6065 get_adj(boundary_test_nodes, 1, moab::Interface::UNION);
6066 auto boundary_test_nodes_edges_nodes = subtract(
6067 get_nodes(boundary_test_nodes_edges), boundary_test_nodes);
6069 boundary_tets_edges =
6070 subtract(boundary_test_nodes_edges,
6071 get_adj(boundary_test_nodes_edges_nodes, 1,
6072 moab::Interface::UNION));
6079 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
6080 body_skin_edges = intersect(get_adj(tets, 1, moab::Interface::UNION),
6082 body_skin = intersect(body_skin, adj_tets_faces);
6083 body_skin_edges = subtract(
6084 body_skin_edges, get_adj(body_skin, 1, moab::Interface::UNION));
6087 for (
auto e : body_skin_edges) {
6088 auto adj_tet = intersect(
6089 get_adj(
Range(e, e), 3, moab::Interface::INTERSECT), tets);
6090 if (adj_tet.size() == 1) {
6091 boundary_tets_edges.insert(e);
6095 return boundary_tets_edges;
6098 auto p = get_test_on_crack_surface();
6099 auto &[new_crack_faces, crack_faces_tets] = p;
6110 auto boundary_tets_edges =
6111 carck_faces_test_edges(new_crack_faces, crack_faces_tets);
6113 boundary_tets_edges);
6115 auto resolve_surface = [&](
auto boundary_tets_edges,
6116 auto crack_faces_tets) {
6117 auto boundary_tets_edges_nodes = get_nodes(boundary_tets_edges);
6118 auto crack_faces_tets_faces =
6119 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6121 Range all_removed_faces;
6122 Range all_removed_tets;
6126 while (size != crack_faces_tets.size()) {
6128 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
6132 auto skin_skin_nodes = get_nodes(skin_skin);
6134 size = crack_faces_tets.size();
6136 <<
"Crack faces tets size " << crack_faces_tets.size()
6137 <<
" crack faces size " << crack_faces_tets_faces.size();
6138 auto skin_tets_nodes = subtract(
6139 get_nodes(skin_tets),
6140 boundary_tets_edges_nodes);
6142 skin_tets_nodes = subtract(skin_tets_nodes, skin_skin_nodes);
6144 Range removed_nodes;
6145 Range tets_to_remove;
6146 Range faces_to_remove;
6147 for (
auto n : skin_tets_nodes) {
6149 intersect(get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT),
6151 if (tets.size() == 0) {
6155 auto hole_detetction = [&]() {
6157 get_adj(
Range(
n,
n), 3, moab::Interface::INTERSECT);
6162 if (adj_tets.size() == 0) {
6163 return std::make_pair(
6165 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6170 std::vector<Range> tets_groups;
6171 auto test_adj_tets = adj_tets;
6172 while (test_adj_tets.size()) {
6174 Range seed =
Range(test_adj_tets[0], test_adj_tets[0]);
6175 while (seed.size() != seed_size) {
6177 subtract(get_adj(seed, 2, moab::Interface::UNION),
6180 seed_size = seed.size();
6182 intersect(get_adj(adj_faces, 3, moab::Interface::UNION),
6185 tets_groups.push_back(seed);
6186 test_adj_tets = subtract(test_adj_tets, seed);
6188 if (tets_groups.size() == 1) {
6190 return std::make_pair(
6192 get_adj(
Range(
n,
n), 2, moab::Interface::INTERSECT),
6198 Range tets_to_remove;
6199 Range faces_to_remove;
6200 for (
auto &r : tets_groups) {
6201 auto f = get_adj(r, 2, moab::Interface::UNION);
6202 auto t = intersect(get_adj(
f, 3, moab::Interface::UNION),
6205 if (
f.size() > faces_to_remove.size() ||
6206 faces_to_remove.size() == 0) {
6207 faces_to_remove =
f;
6212 <<
"Hole detection: faces to remove "
6213 << faces_to_remove.size() <<
" tets to remove "
6214 << tets_to_remove.size();
6215 return std::make_pair(faces_to_remove, tets_to_remove);
6218 if (tets.size() < tets_to_remove.size() ||
6219 tets_to_remove.size() == 0) {
6221 auto [h_faces_to_remove, h_tets_to_remove] =
6223 faces_to_remove = h_faces_to_remove;
6224 tets_to_remove = h_tets_to_remove;
6232 all_removed_faces.merge(faces_to_remove);
6233 all_removed_tets.merge(tets_to_remove);
6236 crack_faces_tets = subtract(crack_faces_tets, tets_to_remove);
6237 crack_faces_tets_faces =
6238 subtract(crack_faces_tets_faces, faces_to_remove);
6243 boost::lexical_cast<std::string>(counter) +
".vtk",
6246 "faces_to_remove_" +
6247 boost::lexical_cast<std::string>(counter) +
".vtk",
6251 boost::lexical_cast<std::string>(counter) +
".vtk",
6254 "crack_faces_tets_faces_" +
6255 boost::lexical_cast<std::string>(counter) +
".vtk",
6256 crack_faces_tets_faces);
6258 "crack_faces_tets_" +
6259 boost::lexical_cast<std::string>(counter) +
".vtk",
6265 auto cese_internal_faces = [&]() {
6268 auto adj_faces = get_adj(skin_tets, 2, moab::Interface::UNION);
6270 subtract(adj_faces, skin_tets);
6271 auto adj_tets = get_adj(adj_faces, 3,
6272 moab::Interface::UNION);
6275 subtract(crack_faces_tets,
6278 crack_faces_tets_faces =
6279 subtract(crack_faces_tets_faces, adj_faces);
6281 all_removed_faces.merge(adj_faces);
6282 all_removed_tets.merge(adj_tets);
6286 <<
"Remove internal faces size " << adj_faces.size()
6287 <<
" tets size " << adj_tets.size();
6291 auto case_only_one_free_edge = [&]() {
6294 for (
auto t :
Range(crack_faces_tets)) {
6296 auto adj_faces = get_adj(
6298 moab::Interface::UNION);
6299 auto crack_surface_edges =
6300 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6303 moab::Interface::UNION);
6306 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6307 crack_surface_edges);
6308 adj_edges = subtract(
6310 boundary_tets_edges);
6312 if (adj_edges.size() == 1) {
6314 subtract(crack_faces_tets,
6318 auto faces_to_remove =
6319 get_adj(adj_edges, 2, moab::Interface::UNION);
6322 crack_faces_tets_faces =
6323 subtract(crack_faces_tets_faces, faces_to_remove);
6325 all_removed_faces.merge(faces_to_remove);
6326 all_removed_tets.merge(
Range(
t,
t));
6328 MOFEM_LOG(
"EPSELF", Sev::inform) <<
"Remove free one edges ";
6332 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6333 crack_faces_tets_faces =
6334 subtract(crack_faces_tets_faces, all_removed_faces);
6339 auto cese_flat_tet = [&](
auto max_adj_edges) {
6346 auto body_skin_edges =
6347 get_adj(body_skin, 1, moab::Interface::UNION);
6349 for (
auto t :
Range(crack_faces_tets)) {
6351 auto adj_faces = get_adj(
6353 moab::Interface::UNION);
6354 auto crack_surface_edges =
6355 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
6358 moab::Interface::UNION);
6361 subtract(get_adj(
Range(
t,
t), 1, moab::Interface::INTERSECT),
6362 crack_surface_edges);
6363 adj_edges = subtract(adj_edges, body_skin_edges);
6365 auto tet_edges = get_adj(
Range(
t,
t), 1,
6366 moab::Interface::UNION);
6368 tet_edges = subtract(tet_edges, adj_edges);
6370 for (
auto e : tet_edges) {
6371 constexpr int opposite_edge[] = {5, 3, 4, 1, 2, 0};
6372 auto get_side = [&](
auto e) {
6373 int side, sense, offset;
6376 "get side number failed");
6379 auto get_side_ent = [&](
auto side) {
6386 adj_edges.erase(get_side_ent(opposite_edge[get_side(e)]));
6389 if (adj_edges.size() <= max_adj_edges) {
6392 Range faces_to_remove;
6393 for (
auto e : adj_edges) {
6394 auto edge_adj_faces =
6395 get_adj(
Range(e, e), 2, moab::Interface::UNION);
6396 edge_adj_faces = intersect(edge_adj_faces, adj_faces);
6397 if (edge_adj_faces.size() != 2) {
6399 "Adj faces size is not 2 for edge " +
6400 boost::lexical_cast<std::string>(e));
6403 auto get_normal = [&](
auto f) {
6407 "get tri normal failed");
6410 auto t_n0 = get_normal(edge_adj_faces[0]);
6411 auto t_n1 = get_normal(edge_adj_faces[1]);
6412 auto get_sense = [&](
auto f) {
6413 int side, sense, offset;
6416 "get side number failed");
6419 auto sense0 = get_sense(edge_adj_faces[0]);
6420 auto sense1 = get_sense(edge_adj_faces[1]);
6425 auto dot_e = (sense0 * sense1) * t_n0(
i) * t_n1(
i);
6426 if (dot_e < dot || e == adj_edges[0]) {
6428 faces_to_remove = edge_adj_faces;
6432 all_removed_faces.merge(faces_to_remove);
6433 all_removed_tets.merge(
Range(
t,
t));
6436 <<
"Remove free edges on flat tet, with considered nb. of "
6438 << adj_edges.size();
6442 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
6443 crack_faces_tets_faces =
6444 subtract(crack_faces_tets_faces, all_removed_faces);
6450 "Case only one free edge failed");
6451 for (
auto max_adj_edges : {0, 1, 2, 3}) {
6453 "Case only one free edge failed");
6456 "Case internal faces failed");
6460 "crack_faces_tets_faces_" +
6461 boost::lexical_cast<std::string>(counter) +
".vtk",
6462 crack_faces_tets_faces);
6464 "crack_faces_tets_" +
6465 boost::lexical_cast<std::string>(counter) +
".vtk",
6469 return std::make_tuple(crack_faces_tets_faces, crack_faces_tets,
6470 all_removed_faces, all_removed_tets);
6473 auto [resolved_faces, resolved_tets, all_removed_faces,
6475 resolve_surface(boundary_tets_edges, crack_faces_tets);
6476 resolved_faces.merge(subtract(crack_faces, all_removed_faces));
6484 crack_faces = resolved_faces;
6496 auto resolve_consisten_crack_extension = [&]() {
6498 auto crack_meshset =
6501 auto meshset = crack_meshset->getMeshset();
6505 Range old_crack_faces;
6508 auto extendeded_crack_faces = get_extended_crack_faces();
6509 auto reconstructed_crack_faces =
6510 subtract(reconstruct_crack_faces(extendeded_crack_faces),
6512 if (
nbCrackFaces >= reconstructed_crack_faces.size()) {
6514 <<
"No new crack faces to add, skipping adding to meshset";
6515 extendeded_crack_faces = subtract(
6516 extendeded_crack_faces, subtract(*
crackFaces, old_crack_faces));
6518 <<
"Number crack faces size (extended) "
6519 << extendeded_crack_faces.size();
6525 reconstructed_crack_faces);
6527 <<
"Number crack faces size (reconstructed) "
6528 << reconstructed_crack_faces.size();
6547 CHKERR resolve_consisten_crack_extension();
6560 verts = subtract(verts, conn);
6561 std::vector<double> coords(3 * verts.size());
6563 double def_coords[] = {0., 0., 0.};
6566 "ORG_COORDS", 3, MB_TYPE_DOUBLE, th_org_coords,
6567 MB_TAG_CREAT | MB_TAG_DENSE, def_coords);
6587 auto post_proc_norm_fe =
6588 boost::make_shared<VolumeElementForcesAndSourcesCore>(
mField);
6590 auto post_proc_norm_rule_hook = [](int, int,
int p) ->
int {
6593 post_proc_norm_fe->getRuleHook = post_proc_norm_rule_hook;
6595 post_proc_norm_fe->getUserPolynomialBase() =
6596 boost::shared_ptr<BaseFunction>(
new CGGUserPolynomialBase());
6598 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
6602 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
6605 CHKERR VecZeroEntries(norms_vec);
6607 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
6608 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
6609 post_proc_norm_fe->getOpPtrVector().push_back(
6611 post_proc_norm_fe->getOpPtrVector().push_back(
6613 post_proc_norm_fe->getOpPtrVector().push_back(
6615 post_proc_norm_fe->getOpPtrVector().push_back(
6617 post_proc_norm_fe->getOpPtrVector().push_back(
6621 auto piola_ptr = boost::make_shared<MatrixDouble>();
6622 post_proc_norm_fe->getOpPtrVector().push_back(
6624 post_proc_norm_fe->getOpPtrVector().push_back(
6628 post_proc_norm_fe->getOpPtrVector().push_back(
6631 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
6633 *post_proc_norm_fe);
6634 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
6636 CHKERR VecAssemblyBegin(norms_vec);
6637 CHKERR VecAssemblyEnd(norms_vec);
6638 const double *norms;
6639 CHKERR VecGetArrayRead(norms_vec, &norms);
6640 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u: " << std::sqrt(norms[U_NORM_L2]);
6641 MOFEM_LOG(
"EP", Sev::inform) <<
"norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
6643 <<
"norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
6645 <<
"norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
6646 CHKERR VecRestoreArrayRead(norms_vec, &norms);
6660 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6661 if (
auto disp_bc = bc.second->dispBcPtr) {
6666 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6667 MOFEM_LOG(
"EP", Sev::noisy) <<
"Displacement BC: " << *disp_bc;
6669 std::vector<double> block_attributes(6, 0.);
6670 if (disp_bc->data.flag1 == 1) {
6671 block_attributes[0] = disp_bc->data.value1;
6672 block_attributes[3] = 1;
6674 if (disp_bc->data.flag2 == 1) {
6675 block_attributes[1] = disp_bc->data.value2;
6676 block_attributes[4] = 1;
6678 if (disp_bc->data.flag3 == 1) {
6679 block_attributes[2] = disp_bc->data.value3;
6680 block_attributes[5] = 1;
6682 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6690 boost::make_shared<NormalDisplacementBcVec>();
6691 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6692 auto block_name =
"(.*)NORMAL_DISPLACEMENT(.*)";
6693 std::regex reg_name(block_name);
6694 if (std::regex_match(bc.first, reg_name)) {
6698 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6700 block_name, bc.second->bcAttributes,
6701 bc.second->bcEnts.subset_by_dimension(2));
6706 boost::make_shared<AnalyticalDisplacementBcVec>();
6708 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6709 auto block_name =
"(.*)ANALYTICAL_DISPLACEMENT(.*)";
6710 std::regex reg_name(block_name);
6711 if (std::regex_match(bc.first, reg_name)) {
6715 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6717 block_name, bc.second->bcAttributes,
6718 bc.second->bcEnts.subset_by_dimension(2));
6722 auto ts_displacement =
6723 boost::make_shared<DynamicRelaxationTimeScale>(
"disp_history.txt");
6726 <<
"Add time scaling displacement BC: " << bc.blockName;
6729 ts_displacement,
"disp_history",
".txt", bc.blockName);
6732 auto ts_normal_displacement =
6733 boost::make_shared<DynamicRelaxationTimeScale>(
"normal_disp_history.txt");
6736 <<
"Add time scaling normal displacement BC: " << bc.blockName;
6739 ts_normal_displacement,
"normal_disp_history",
".txt",
6755 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6756 if (
auto force_bc = bc.second->forceBcPtr) {
6761 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6762 MOFEM_LOG(
"EP", Sev::noisy) <<
"Force BC: " << *force_bc;
6764 std::vector<double> block_attributes(6, 0.);
6765 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
6766 block_attributes[3] = 1;
6767 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
6768 block_attributes[4] = 1;
6769 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
6770 block_attributes[5] = 1;
6771 auto faces = bc.second->bcEnts.subset_by_dimension(2);
6779 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6780 auto block_name =
"(.*)PRESSURE(.*)";
6781 std::regex reg_name(block_name);
6782 if (std::regex_match(bc.first, reg_name)) {
6787 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6789 block_name, bc.second->bcAttributes,
6790 bc.second->bcEnts.subset_by_dimension(2));
6795 boost::make_shared<AnalyticalTractionBcVec>();
6797 for (
auto bc : bc_mng->getBcMapByBlockName()) {
6798 auto block_name =
"(.*)ANALYTICAL_TRACTION(.*)";
6799 std::regex reg_name(block_name);
6800 if (std::regex_match(bc.first, reg_name)) {
6804 <<
"Field name: " <<
field_name <<
" Block name: " << block_name;
6806 block_name, bc.second->bcAttributes,
6807 bc.second->bcEnts.subset_by_dimension(2));
6812 boost::make_shared<DynamicRelaxationTimeScale>(
"traction_history.txt");
6816 ts_traction,
"traction_history",
".txt", bc.blockName);
6820 boost::make_shared<DynamicRelaxationTimeScale>(
"pressure_history.txt");
6824 ts_pressure,
"pressure_history",
".txt", bc.blockName);
6833 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec> &ext_strain_vec_ptr,
6834 const std::string block_name,
6835 const int nb_attributes) {
6838 std::regex((boost::format(
"%s(.*)") % block_name).str()))
6840 std::vector<double> block_attributes;
6841 CHKERR it->getAttributes(block_attributes);
6842 if (block_attributes.size() < nb_attributes) {
6844 "In block %s expected %d attributes, but given %ld",
6845 it->getName().c_str(), nb_attributes, block_attributes.size());
6848 auto get_block_ents = [&]() {
6854 auto Ents = get_block_ents();
6855 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
6864 auto ts_pre_stretch =
6865 boost::make_shared<DynamicRelaxationTimeScale>(
"externalstrain_history.txt");
6868 <<
"Add time scaling external strain: " << ext_strain_block.blockName;
6871 ts_pre_stretch,
"externalstrain_history",
".txt", ext_strain_block.blockName);
6880 auto print_loc_size = [
this](
auto v,
auto str,
auto sev) {
6883 CHKERR VecGetLocalSize(
v.second, &size);
6885 CHKERR VecGetOwnershipRange(
v.second, &low, &high);
6886 MOFEM_LOG(
"EPSYNC", sev) << str <<
" local size " << size <<
" ( " << low
6887 <<
" " << high <<
" ) ";
6919 MOFEM_LOG(
"EP", Sev::inform) <<
"Calculate crack area";
6921 for (
auto f : crack_faces) {
6924 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
6926 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0,
mField.
get_comm());
6928 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)
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)
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 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(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 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={})
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.
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