19#include <boost/math/constants/constants.hpp>
20#include <boost/math/special_functions/lambert_w.hpp>
28 static inline constexpr double eps = 1e-8;
30 static inline constexpr double pi = boost::math::constants::pi<double>();
32 boost::math::constants::root_pi<double>();
34 template <
typename T>
static inline T
getTau(
const T &
k,
double gc) {
35 const T
c =
static_cast<T
>(gc) /
root_pi;
36 return c * std::exp(-
k) / std::sqrt(
k);
41 return -tau * (1.0 + (1.0 / (2.0 *
kappa)));
54 T dnom =
kappa * min_stiffness + tau;
55 return (tau -
kappa * diff_tau) / (dnom * dnom);
58 template <
typename T>
static auto invTau(
const T &tau,
double Gf) {
59 const T z = (2.0 * Gf * Gf) / (
pi * tau * tau);
60 return T(0.5) * boost::math::lambert_w0(z);
65 return tau * std::sqrt(2.0 / (
kappa + 1.5));
76 double lower_kappa = 0;
77 double upper_kappa =
invTau(strength, gc);
81 constexpr int max_bisection_iterations = 100;
82 for (
int i = 0;
i != max_bisection_iterations; ++
i) {
83 const double mid_kappa = 0.5 * (lower_kappa + upper_kappa);
85 lower_kappa = mid_kappa;
87 upper_kappa = mid_kappa;
90 return 0.5 * (lower_kappa + upper_kappa);
95 double min_stiffness) {
97 return 0.5 * t_eff * t_eff * diff_alpha;
100 template <
typename T>
102 const T &
kappa,
double gc,
103 double min_stiffness) {
105 return Y * delta_kappa;
108 template <
typename T>
110 const T &
kappa,
double gc,
111 double min_stiffness) {
114 return -
M * delta_kappa;
117 template <
typename T>
120 const T &
kappa,
double gc,
121 double min_stiffness) {
123 std::complex<T> cpx_delta = delta_kappa;
124 std::complex<T> cpx_t_eff = t_eff;
125 std::complex<T> cpx_kappa =
kappa;
126 cpx_delta +=
eps * 1
i;
128 cpx_delta, cpx_t_eff, cpx_kappa, gc, min_stiffness);
129 return cpx_M.imag() /
eps;
132 template <
typename T>
136 double beta,
double min_stiffness) {
139 std::complex<T> cpx_delta = delta_kappa;
140 std::complex<T> cpx_kappa =
kappa;
142 for (
auto jj = 0; jj != 3; ++jj) {
143 t_cpx_traction(
i) = t_traction(
i);
144 t_cpx_traction(jj) +=
eps * 1
i;
145 std::complex<T> cpx_teff =
148 cpx_delta, cpx_teff, cpx_kappa, gc, min_stiffness);
149 t_diff_traction(jj) = cpx_M.imag() /
eps;
151 return t_diff_traction;
154 template <
typename T>
157 double alpha,
double beta,
158 bool sign_sensitive =
true) {
163 t_P(
i,
j) = t_n_normalize(
i) * t_n_normalize(
j);
167 t_normal(
i) = t_P(
i,
j) * t_traction(
j);
169 t_tangential(
i) = t_Q(
i,
j) * t_traction(
j);
171 if (sign_sensitive) {
172 T s = std::sqrt((t_normal(
i) * t_normal(
i)) / 4. +
173 (1. / beta) * t_tangential(
i) * t_tangential(
i));
174 T teff = (t_n_normalize(
i) * t_normal(
i) / 2.) + s;
177 if (std::real(s) > std::numeric_limits<double>::epsilon()) {
180 t_n_normalize(
i) * teff / 2. +
182 (1.0 / 4.0) * (teff / s) * t_normal(
i) +
184 (1.0 / beta) * (teff / s) * t_tangential(
i)
188 return std::make_pair(teff, t_gap);
190 T teff = std::sqrt((t_normal(
i) * t_normal(
i)) +
191 (1. / beta) * t_tangential(
i) * t_tangential(
i));
195 t_normal(
i) + (1.0 / beta) * t_tangential(
i)
198 return std::make_pair(teff, t_gap);
202 template <
typename T>
206 double alpha,
double beta,
207 bool sign_sensitive =
true) {
212 for (
auto jj = 0; jj != 3; ++jj) {
213 t_cpx_traction(
i) = t_traction(
i);
214 t_cpx_traction(jj) +=
eps * 1
i;
215 auto [teff_cpx, t_cpx_gap] =
calculateGap(t_cpx_traction, t_n_normalize,
216 alpha, beta, sign_sensitive);
217 for (
auto ii = 0; ii != 3; ++ii) {
218 auto v = t_cpx_gap(ii).imag();
219 t_dgap(ii, jj) =
v /
eps;
225 template <
typename T>
230 auto [teff, t_gap] =
calculateGap(t_traction, t_n_normalize, 1.0, beta);
259 PetscOptionsBegin(PETSC_COMM_WORLD,
"interface_",
"",
"none");
261 CHKERR PetscOptionsScalar(
"-gc",
"Griffith energy release rate",
"",
263 CHKERR PetscOptionsScalar(
"-min_stiffness",
"Minimal interface stiffness",
265 CHKERR PetscOptionsScalar(
"-strength",
"Strength of interface",
"",
267 CHKERR PetscOptionsScalar(
"-min_kappa",
268 "Minimal kappa to avoid singularity",
"",
270 CHKERR PetscOptionsScalar(
"-kappa0",
"Characteristic length kappa0",
"",
272 CHKERR PetscOptionsScalar(
"-beta",
"Cohesive tangential coupling",
"",
278 <<
"Interface Griffith energy release rate Gc -interface_gc = "
281 <<
"Interface min stiffness -interface_min_stiffness = "
284 <<
"Interface strength -interface_strength = " <<
strength;
286 <<
"Interface minimal kappa -interface_min_kappa = " <<
min_kappa;
288 <<
"Interface characteristic length kappa0 -interface_kappa0 = "
291 <<
"Interface tangential coupling -interface_beta = " <<
beta;
298 <<
"Adjusted interface min kappa for initial Mode-I strength = "
299 <<
min_kappa <<
", resulting strength = "
312static Tag get_tag(moab::Interface &moab, std::string tag_name,
int size) {
313 std::vector<double> dummy(size, 0.);
315 rval = moab.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE, tag,
316 MB_TAG_CREAT | MB_TAG_SPARSE, dummy.data());
317 if (
rval == MB_ALREADY_ALLOCATED)
324 return get_tag(moab,
"KAPPA", 1);
328 return get_tag(moab,
"DELTA_KAPPA", 1);
337 Assembly<A>::OpBrokenBase;
339 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_flux_data_ptr,
340 boost::shared_ptr<Range> ents_ptr =
nullptr)
341 :
OP(broken_flux_data_ptr, ents_ptr) {}
349 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
354 if (!brokenBaseSideData) {
359 auto do_work_rhs = [
this](
int row_side, EntityType row_type,
363 auto base = row_data.
getBase();
366 "row base not set properly");
375 OP::nbIntegrationPts = OP::getGaussPts().size2();
377 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
379 OP::locF.resize(OP::nbRows,
false);
381 OP::locMat.resize(OP::nbRows, OP::nbRows,
false);
385 CHKERR this->iNtegrate(row_data);
387 CHKERR this->aSsemble(row_data);
392 switch (OP::opType) {
394 for (
auto &bd : *brokenBaseSideData) {
396 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
398 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
405 (std::string(
"wrong op type ") +
406 OpBaseDerivativesBase::OpTypeNames[OP::opType])
422 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
423 boost::shared_ptr<double> gc_ptr,
424 boost::shared_ptr<VectorDouble> kappa_ptr,
425 boost::shared_ptr<VectorDouble> kappa_delta_ptr,
426 boost::shared_ptr<std::array<MatrixDouble, 2>> lambda_ptr =
nullptr,
427 Tag dissipation_tags =
Tag(),
Tag grad_dissipation_tags =
Tag(),
429 boost::shared_ptr<Range> ents_ptr =
nullptr)
438 auto get_sense_index = [
this]() {
return (
faceSense == 1) ? 0 : 1; };
444 int nb_integration_pts = OP::getGaussPts().size2();
447 auto t_kappa = getFTensor0FromVec<0>(*
kappaPtr);
449 auto t_face_normal = getFTensor1NormalsAtGaussPts();
451 int nb_base_functions = data.
getN().size2() / 3;
453 auto t_w = OP::getFTensor0IntegrationWeight();
463 for (
auto gg = 0; gg != nb_integration_pts; ++gg) {
467 t_normalized_normal(
J) = t_normal(
J);
470 t_traction(
i) = t_P(
i,
J) * t_normalized_normal(
J);
472 auto fracture = [
this](
auto &t_traction,
auto &t_normalized_normal,
473 auto &t_kappa,
auto &t_delta_kappa,
auto gc) {
474 double kappa =
static_cast<double>(t_kappa + t_delta_kappa);
482 t_gap_double(
i) = -t_gap(
i) / 2.;
487 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
489 for (; bb != nb_dofs /
SPACE_DIM; ++bb) {
490 double row_base = t_w * (t_row_base_fun(
J) * t_normal(
J));
491 t_nf(
i) += row_base * t_gap(
i);
495 for (; bb != nb_base_functions; ++bb)
499 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
513 boost::shared_ptr<std::array<MatrixDouble, 2>>
lambdaPtr;
529 auto get_sense_index = [
this]() {
return (
faceSense == 1) ? 0 : 1; };
536 int nb_integration_pts = OP::getGaussPts().size2();
539 auto t_kappa = getFTensor0FromVec<0>(*
kappaPtr);
541 auto t_face_normal = getFTensor1NormalsAtGaussPts();
543 int nb_base_functions = data.
getN().size2() / 3;
545 auto t_w = OP::getFTensor0IntegrationWeight();
555 for (
auto gg = 0; gg != nb_integration_pts; ++gg) {
559 t_normalized_normal(
J) = t_normal(
J);
562 t_traction(
i) = t_P(
i,
J) * t_normalized_normal(
J);
564 auto fracture = [
this](
auto &t_traction,
auto &t_normalized_normal,
565 auto &t_kappa,
auto &t_delta_kappa,
auto gc) {
566 double kappa =
static_cast<double>(t_kappa + t_delta_kappa);
575 t_dgap_double(
i,
j) = -t_dgap(
i,
j) / 2.;
576 return t_dgap_double;
581 for (; rr != nb_dofs /
SPACE_DIM; ++rr) {
582 auto t_mat = getFTensor2FromArray<3, 3, 3>(OP::locMat, 3 * rr);
583 double row_base = t_w * (t_row_base_fun(
J) * t_normal(
J));
585 for (
int cc = 0; cc != nb_dofs /
SPACE_DIM; ++cc) {
586 double col_base = t_col_base_fun(
J) * t_normalized_normal(
J);
587 t_mat(
i,
j) += (row_base * col_base) * t_dgap(
i,
j);
593 for (; rr != nb_base_functions; ++rr)
597 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
609 if (!this->timeScalingFun.empty())
610 this->locMat *= this->timeScalingFun(this->getFEMethod()->ts_t);
611 if (!this->feScalingFun.empty())
612 this->locMat *= this->feScalingFun(this->getFEMethod());
614 CHKERR this->matSetValuesHook(
this, data, data, this->locMat);
630 auto get_sense_index = [
this]() {
return (
faceSense == 1) ? 0 : 1; };
636 int nb_integration_pts = OP::getGaussPts().size2();
639 auto t_lambda = getFTensor2FromMat<3, 3>(
lambdaPtr->at(get_sense_index()));
640 auto t_kappa = getFTensor0FromVec<0>(*
kappaPtr);
642 auto t_face_normal = getFTensor1NormalsAtGaussPts();
643 auto t_w = OP::getFTensor0IntegrationWeight();
654 double face_dissipation = 0.0;
655 double face_grad_dissipation = 0.0;
656 auto face_handle = OP::getFEEntityHandle();
660 &face_grad_dissipation);
662 for (
auto gg = 0; gg != nb_integration_pts; ++gg) {
666 t_normalized_normal(
J) = t_normal(
J);
669 t_traction(
i) = t_P(
i,
J) * t_normalized_normal(
J);
671 auto dJ_dkappa = [](
auto &t_delta_kappa,
auto &t_traction,
672 auto &t_normalized_normal,
auto &t_kappa,
auto gc) {
673 double kappa =
static_cast<double>(t_kappa);
674 double delta_kappa =
static_cast<double>(t_delta_kappa);
682 return boost::make_tuple(
m, m_grad);
685 auto dr_kappa = [](
auto &t_delta_kappa,
auto &t_traction,
686 auto &t_normalized_normal,
auto &t_kappa,
auto gc) {
687 double kappa =
static_cast<double>(t_kappa);
688 double delta_kappa =
static_cast<double>(t_delta_kappa);
689 double kappa_plus_delta =
kappa + delta_kappa;
696 t_gap_double(
i) = -t_gap(
i);
700 auto [
J, dJ] = dJ_dkappa(t_delta_kappa, t_traction, t_normalized_normal,
702 face_dissipation += t_w *
J * t_normal.
l2();
703 face_grad_dissipation += t_w * dJ * t_normal.
l2();
705 auto t_dr = dr_kappa(t_delta_kappa, t_traction, t_normalized_normal,
708 t_l(
i) = t_lambda(
i,
K) * t_normal(
K);
709 face_grad_dissipation -= t_w * t_l(
i) * t_dr(
i);
717 &face_grad_dissipation);
742 int nb_integration_pts = OP::getGaussPts().size2();
745 int nb_base_functions = data.
getN().size2() / 3;
747 auto t_w = OP::getFTensor0IntegrationWeight();
750 auto t_kappa = getFTensor0FromVec<0>(*
kappaPtr);
752 auto t_face_normal = getFTensor1NormalsAtGaussPts();
762 for (
auto gg = 0; gg != nb_integration_pts; ++gg) {
766 t_normalized_normal(
J) = t_normal(
J);
769 t_traction(
i) = t_P(
i,
J) * t_normalized_normal(
J);
771 auto dJ_dtraction = [](
auto &t_traction,
auto &t_normalized_normal,
772 auto &t_delta_kappa,
auto &t_kappa,
auto gc) {
773 double kappa =
static_cast<double>(t_kappa);
774 double delta_kappa =
static_cast<double>(t_delta_kappa);
777 t_traction_double(
i) = t_traction(
i);
780 t_traction_double, delta_kappa,
kappa, t_normalized_normal, gc,
783 t_dJ_double(
i) = t_dM(
i);
789 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
791 for (; bb != nb_dofs /
SPACE_DIM; ++bb) {
792 double row_base = t_w * (t_row_base_fun(
J) * t_normal(
J));
793 t_nf(
i) += row_base * t_dJ(
i);
797 for (; bb != nb_base_functions; ++bb)
801 assemble(dJ_dtraction(t_traction, t_normalized_normal, t_delta_kappa,
813 return VecSetValues<AssemblyTypeSelector<A>>(
vec_dJdu, data, OP::locF,
828 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
830 boost::shared_ptr<VectorDouble> tag_data_ptr,
831 boost::shared_ptr<Range> ents_ptr =
nullptr)
838 auto get_sense_index = [
this]() {
return (
faceSense == 1) ? 0 : 1; };
850 auto get_data = [&](
auto &
v) {
853 auto &moab = getMoab();
854 auto fe_ent = getFEEntityHandle();
858 rval = moab.tag_get_by_ptr(
tagHandle, &fe_ent, 1, (
const void **)&data,
862 rval == MB_SUCCESS && size > 0 && size !=
v.size()
866 "Inconsistent size of tag data");
870 tag_size[0] =
v.size();
871 void const *tag_data[] = {&
v[0]};
875 (
const void **)&data, &size);
876 std::copy(data, data + size,
v.begin());
901 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
906 using SideEleOp = EleOnSide::UserDataOperator;
908 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
911 auto domain_side_flux = [&](
auto &pip) {
913 auto broken_data_ptr =
914 boost::make_shared<std::vector<BrokenBaseSideData>>();
917 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
922 return broken_data_ptr;
925 auto get_lambda = [&](
auto &pip) {
926 boost::shared_ptr<std::array<MatrixDouble, 2>> array_lambda_ptr;
928 array_lambda_ptr = boost::make_shared<std::array<MatrixDouble, 2>>();
929 auto lambda_mat_ptr = boost::make_shared<MatrixDouble>();
931 ep.
piolaStress, lambda_mat_ptr, boost::make_shared<double>(1.0),
936 [lambda_mat_ptr, array_lambda_ptr](
940 auto op_ptr =
static_cast<OP *
>(base_op_ptr);
941 auto get_sense_index = [op_ptr]() {
942 return (op_ptr->getSkeletonSense() == 1) ? 0 : 1;
944 array_lambda_ptr->at(get_sense_index()) = *lambda_mat_ptr;
949 return array_lambda_ptr;
952 return std::make_pair(domain_side_flux(pip), get_lambda(pip));
958 boost::shared_ptr<Range> interface_range_ptr,
961 auto &m_field = ep.
mField;
967 using SideEleOp = EleOnSide::UserDataOperator;
968 using BdyEleOp = BoundaryEle::UserDataOperator;
970 auto face_side = [&]() {
973 auto op_loop_skeleton_side =
975 interface_range_ptr, Sev::noisy);
976 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
979 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
980 set_integration_at_front_face;
982 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
986 return op_loop_skeleton_side;
989 auto op_loop_skeleton_side = face_side();
996 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
997 boost::make_shared<CGGUserPolynomialBase>(
nullptr,
true);
999 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
1002 op_reset_broken_data->doWorkRhsHook =
1003 [broken_data_flux_ptr](
DataOperator *base_op_ptr,
int side,
1006 broken_data_flux_ptr->resize(0);
1009 op_loop_skeleton_side->getOpPtrVector().push_back(op_reset_broken_data);
1010 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
1012 auto kappa_ptr = boost::make_shared<VectorDouble>();
1013 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
1014 auto gc_ptr = boost::make_shared<double>();
1016 op_loop_skeleton_side->getOpPtrVector().push_back(
1018 op_loop_skeleton_side->getOpPtrVector().push_back(
1021 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpGetTag(
1025 return std::make_tuple(op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr,
1026 kappa_ptr, kappa_delta_ptr);
1032 boost::shared_ptr<Range> interface_range_ptr,
1033 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1036 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
1039 interface_range_ptr);
1041 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
1042 op_loop_skeleton_side->getOpPtrVector().push_back(
1045 op_loop_skeleton_side->getOpPtrVector().push_back(
new OpCohesiveRhs(
1046 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
1048 pip.push_back(op_loop_skeleton_side);
1056 boost::shared_ptr<Range> interface_range_ptr,
1057 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1060 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
1063 interface_range_ptr);
1064 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
1065 op_loop_skeleton_side->getOpPtrVector().push_back(
1069 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
1071 pip.push_back(op_loop_skeleton_side);
1078 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1080 auto &m_field = ep.
mField;
1086 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1087 boost::make_shared<CGGUserPolynomialBase>(
nullptr,
true);
1089 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
1093 op_reset_broken_data->doWorkRhsHook =
1094 [broken_data_flux_ptr](
DataOperator *base_op_ptr,
int side,
1097 broken_data_flux_ptr->resize(0);
1100 pip.push_back(op_reset_broken_data);
1101 pip.push_back(op_loop_domain_side);
1103 auto tag_dissipation =
get_tag(m_field.get_moab(),
"COHESIVE_DISSIPATION", 1);
1104 auto tag_grad_dissipation =
1105 get_tag(m_field.get_moab(),
"COHESIVE_DISSIPATION_GRAD", 1);
1107 auto kappa_ptr = boost::make_shared<VectorDouble>();
1108 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
1109 auto gc_ptr = boost::make_shared<double>();
1112 pip.push_back(
new OpGetTag(broken_data_flux_ptr,
1115 pip.push_back(
new OpGetTag(broken_data_flux_ptr,
1120 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr, lambda_ptr,
1121 tag_dissipation, tag_grad_dissipation));
1123 return std::make_pair(tag_dissipation, tag_grad_dissipation);
1128 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1129 auto &m_field = ep.
mField;
1135 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1136 boost::make_shared<CGGUserPolynomialBase>(
nullptr,
true);
1137 auto [broken_data_flux_ptr, lambda_ptr] =
1142 op_reset_broken_data->doWorkRhsHook =
1143 [broken_data_flux_ptr](
DataOperator *base_op_ptr,
int side,
1146 broken_data_flux_ptr->resize(0);
1149 pip.push_back(op_reset_broken_data);
1150 pip.push_back(op_loop_domain_side);
1152 auto kappa_ptr = boost::make_shared<VectorDouble>();
1153 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
1154 auto gc_ptr = boost::make_shared<double>();
1157 pip.push_back(
new OpGetTag(broken_data_flux_ptr,
1160 pip.push_back(
new OpGetTag(broken_data_flux_ptr,
1164 pip.push_back(
new OpCohesive_dJ_dP(broken_data_flux_ptr, gc_ptr, kappa_ptr,
1165 kappa_delta_ptr, lambda_ptr,
Tag(),
Tag(),
1181 using BdyEleOp = BoundaryEle::UserDataOperator;
1183 auto get_face_ele = [&]() {
1184 auto fe_ptr = boost::make_shared<BoundaryEle>(ep.
mField);
1185 fe_ptr->getRuleHook = [](int, int, int) {
return -1; };
1186 fe_ptr->setRuleHook = set_integration_at_front_face;
1187 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
1191 auto interface_face = [&](
FEMethod *fe_method_ptr) {
1192 auto ent = fe_method_ptr->getFEEntityHandle();
1203 fe_ptr->exeTestHook = interface_face;
1208 auto face_fe = get_face_ele();
1209 auto [tag_dissipation, tag_grad_dissipation] =
1212 constexpr double zero = 0.0;
1221 ep.
mField.
get_moab(), grad_dissipation_vec, tag_grad_dissipation);
1234 using BdyEleOp = BoundaryEle::UserDataOperator;
1236 auto get_face_ele = [&]() {
1237 auto fe_ptr = boost::make_shared<BoundaryEle>(ep.
mField);
1238 fe_ptr->getRuleHook = [](int, int, int) {
return -1; };
1239 fe_ptr->setRuleHook = set_integration_at_front_face;
1240 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
1244 auto interface_face = [&](
FEMethod *fe_method_ptr) {
1245 auto ent = fe_method_ptr->getFEEntityHandle();
1256 fe_ptr->exeTestHook = interface_face;
1261 auto face_fe = get_face_ele();
1265 CHKERR VecAssemblyBegin(dJ_dx);
1266 CHKERR VecAssemblyEnd(dJ_dx);
1267 CHKERR VecGhostUpdateBegin(dJ_dx, ADD_VALUES, SCATTER_REVERSE);
1268 CHKERR VecGhostUpdateEnd(dJ_dx, ADD_VALUES, SCATTER_REVERSE);
1269 CHKERR VecGhostUpdateBegin(dJ_dx, INSERT_VALUES, SCATTER_FORWARD);
1270 CHKERR VecGhostUpdateEnd(dJ_dx, INSERT_VALUES, SCATTER_FORWARD);
1272 CHKERR VecNorm(dJ_dx, NORM_2, &dJ_dx_norm2);
1274 <<
"evaluateCohesiveLambdaImpl: Norm of dJ/dx vector: " << dJ_dx_norm2;
1275 constexpr double tol = 1e-16;
1276 if (dJ_dx_norm2 <
tol) {
1277 CHKERR VecZeroEntries(lambda_vec);
1279 CHKERR KSPSolveTranspose(ksp, dJ_dx, lambda_vec);
1281 CHKERR VecGhostUpdateBegin(lambda_vec, INSERT_VALUES, SCATTER_FORWARD);
1282 CHKERR VecGhostUpdateEnd(lambda_vec, INSERT_VALUES, SCATTER_FORWARD);
1283 double lambda_norm2;
1284 CHKERR VecNorm(lambda_vec, NORM_2, &lambda_norm2);
1286 <<
"evaluateCohesiveLambdaImpl: Norm of lambda vector: " << lambda_norm2;
1296 CHKERR TSSetFromOptions(ts);
1297 CHKERR TSSetStepNumber(ts, 0);
1299 CHKERR TSSetSolution(ts, x);
1303 <<
"evaluatePrimalProblemCohesiveImpl: Time step dt: " <<
dt;
1304 CHKERR TSSolve(ts, PETSC_NULLPTR);
1309 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
1310 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
1313 CHKERR VecNorm(x, NORM_2, &x_norm2);
1315 <<
"evaluatePrimalProblemCohesiveImpl: Norm of displacement vector: "
1332 ep->mField.get_comm(), ep->mField.get_moab(),
1337 [&ep](
Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1341 [&ep](
Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1379 return boost::make_shared<CohesiveTAOCtxImpl>(
1380 ep_ptr, set_integration_at_front_face, time_solver);
1384 PetscReal *f, Vec
g,
1389 auto &ep = *(cohesive_ctx->ep_ptr);
1392 CHKERR VecView(delta_kappa, PETSC_VIEWER_STDOUT_WORLD);
1395 CHKERR VecCopy(delta_kappa, cohesive_ctx->kappaVec.second);
1396 CHKERR VecGhostUpdateBegin(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1398 CHKERR VecGhostUpdateEnd(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1406 cohesive_ctx->kspSolVec);
1410 ksp, cohesive_ctx->lambdaVec);
1413 ep, cohesive_ctx->setIntegrationAtFrontFace, cohesive_ctx->lambdaVec,
1414 cohesive_ctx->dissipationVec, cohesive_ctx->gradDissipationVec);
1416 CHKERR VecSum(cohesive_ctx->dissipationVec.second, f);
1417 CHKERR VecCopy(cohesive_ctx->gradDissipationVec.second,
g);
1420 <<
"Cohesive objective function (negative total dissipation): " << *f;
Eshelbian plasticity interface.
#define FTENSOR_INDEX(DIM, I)
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Tensor1< T, Tensor_Dim > normalize()
#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 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_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
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.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
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)
FTensor::Index< 'J', DIM1 > J
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
Tag get_delta_kappa_tag(moab::Interface &moab)
static Tag get_tag(moab::Interface &moab, std::string tag_name, int size)
static MoFEMErrorCode evaluateDissipationAndGradImpl(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, SmartPetscObj< Vec > lambda_vec, CommInterface::EntitiesPetscVector &dissipation_vec, CommInterface::EntitiesPetscVector &grad_dissipation_vec)
static auto pushCohesiveOpsImpl(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, SmartPetscObj< Vec > lambda_vec=SmartPetscObj< Vec >())
boost::shared_ptr< CohesiveTAOCtx > createCohesiveTAOCtx(EshelbianCore *ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, SmartPetscObj< TS > time_solver)
static MoFEMErrorCode evaluatePrimalProblemCohesiveImpl(EshelbianCore &ep, SmartPetscObj< TS > ts, SmartPetscObj< Vec > x)
MoFEMErrorCode pushCohesiveOpsLhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
static auto pushCohesiveOpsDomainImpl(EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, SmartPetscObj< Vec > lambda_vec=SmartPetscObj< Vec >())
Tag get_kappa_tag(moab::Interface &moab)
MoFEMErrorCode pushCohesiveOpsRhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
ForcesAndSourcesCore::UserDataOperator UserDataOperator
static auto pushCohesive_dJ_dkappa_Impl(EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, SmartPetscObj< Vec > lambda_vec)
MoFEMErrorCode initializeCohesiveKappaField(EshelbianCore &ep)
static MoFEMErrorCode evaluateCohesiveLambdaImpl(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, SmartPetscObj< KSP > ksp, SmartPetscObj< Vec > lambda_vec)
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
static auto pushCohesive_dJ_dx_Impl(EshelbianCore &ep, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
MoFEMErrorCode cohesiveEvaluateObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
auto snesGetKSP(SNES snes)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
FTensor::Index< 'm', 3 > m
boost::shared_ptr< Range > frontAdjEdges
const std::string skeletonElement
MoFEM::Interface & mField
const std::string materialH1Positions
std::vector< Tag > listTagsToTransfer
list of tags to transfer to postprocessor
const std::string elementVolumeName
const std::string piolaStress
boost::shared_ptr< Range > interfaceFaces
const std::string hybridSpatialDisp
SmartPetscObj< DM > dmElastic
Elastic problem.
SmartPetscObj< Vec > lambdaVec
SmartPetscObj< Vec > kspSolVec
SmartPetscObj< Vec > duplicateGradientVec() override
SmartPetscObj< Vec > duplicateKappaVec() override
CommInterface::EntitiesPetscVector & getKappaVec() override
SmartPetscObj< TS > timeSolver
CohesiveTAOCtxImpl(EshelbianCore *ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, SmartPetscObj< TS > time_solver)
ForcesAndSourcesCore::GaussHookFun setIntegrationAtFrontFace
CommInterface::EntitiesPetscVector gradDissipationVec
friend MoFEMErrorCode cohesiveEvaluateObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
SmartPetscObj< Vec > duplicateDissipationVec() override
CommInterface::EntitiesPetscVector kappaVec
CommInterface::EntitiesPetscVector dissipationVec
static double invInitialStrength(double strength, double gc)
static double getInitialStrength(double kappa, double gc)
static auto calculateDissipationSurplus(const T &delta_kappa, const T t_eff, const T &kappa, double gc, double min_stiffness)
static T getAlpha(const T &kappa, double gc, double min_stiffness)
static constexpr double pi
static auto calculateDissipationSurplusDiffTraction(const FTensor::Tensor1< T, 3 > &t_traction, const T &delta_kappa, const T &kappa, FTensor::Tensor1< double, 3 > &t_n_normalize, double gc, double beta, double min_stiffness)
static auto calculateY(const T t_eff, const T &kappa, double gc, double min_stiffness)
static auto calculateGap(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double alpha, double beta, bool sign_sensitive=true)
static auto invTau(const T &tau, double Gf)
static auto getDiffTau(const T &tau, const T &kappa, double gc)
static auto calculateEffectiveTraction(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double beta)
static auto calculateDiffGapDTraction(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double alpha, double beta, bool sign_sensitive=true)
static T getDiffAlpha(const T &kappa, double gc, double min_stiffness)
static constexpr double eps
static T getTau(const T &k, double gc)
static constexpr double root_pi
static auto calculateDissipation(const T &delta_kappa, const T t_eff, const T &kappa, double gc, double min_stiffness)
static auto calculateDissipationSurplusDiffKappa(const T &delta_kappa, const T &t_eff, const T &kappa, double gc, double min_stiffness)
boost::shared_ptr< MatrixDouble > fluxMatPtr
OpBrokenBaseCohesive(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_flux_data_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
MoFEMErrorCode aSsemble(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
boost::shared_ptr< double > tatalDissipationGrad
MoFEMErrorCode iNtegrate(EntData &data)
boost::shared_ptr< double > gcPtr
OpCohesiveRhs(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< double > gc_ptr, boost::shared_ptr< VectorDouble > kappa_ptr, boost::shared_ptr< VectorDouble > kappa_delta_ptr, boost::shared_ptr< std::array< MatrixDouble, 2 > > lambda_ptr=nullptr, Tag dissipation_tags=Tag(), Tag grad_dissipation_tags=Tag(), SmartPetscObj< Vec > vec_dJ_dx=SmartPetscObj< Vec >(), boost::shared_ptr< Range > ents_ptr=nullptr)
boost::shared_ptr< VectorDouble > kappaDeltaPtr
boost::shared_ptr< VectorDouble > kappaPtr
boost::shared_ptr< MatrixDouble > uGammaPtr
SmartPetscObj< Vec > vec_dJdu
boost::shared_ptr< double > totalDissipation
boost::shared_ptr< std::array< MatrixDouble, 2 > > lambdaPtr
MoFEMErrorCode aSsemble(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode aSsemble(EntData &data)
static double min_stiffness
MoFEMErrorCode getOptions()
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
boost::shared_ptr< double > gcPtr
OpGetParameters(boost::shared_ptr< double > gc_ptr, Sev severity=Sev::inform)
MoFEMErrorCode iNtegrate(EntData &data)
OpGetTag(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, Tag tag, TagGetType tag_get_type, boost::shared_ptr< VectorDouble > tag_data_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode aSsemble(EntData &data)
boost::shared_ptr< VectorDouble > tagDataPtr
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Tag From Vector object.
std::pair< std::pair< Range, Range >, SmartPetscObj< Vec > > EntitiesPetscVector
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
base operator to do operations at Gauss Pt. level
Data on single entity (This is passed as argument to DataOperator::doWork)
FieldApproximationBase & getBase()
Get approximation base.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Structure for user loop methods on finite elements.
default operator for TRI element
@ OPSPACE
operator do Work is execute on space data
boost::function< MoFEMErrorCode(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)> GaussHookFun
Operator for broken loop side.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Specialization for MatrixDouble vector field values calculation.
Element used to execute operators on side of the element.
Template struct for dimension-specific finite element types.
intrusive_ptr for managing petsc objects
default operator for TET element
BoundaryEle::UserDataOperator BdyEleOp