v0.16.0
Loading...
Searching...
No Matches
EshelbianCohesive.cpp
Go to the documentation of this file.
1/**
2 * @file EshelbianCohesive.cpp
3 * @author your name (you@domain.com)
4 * @brief
5 * @version 0.1
6 * @date 2025-12-21
7 *
8 * @copyright Copyright (c) 2025
9 *
10 */
11
12#define SINGULARITY
13#include <MoFEM.hpp>
14using namespace MoFEM;
15
17#include <TSElasticPostStep.hpp>
18
19#include <boost/math/constants/constants.hpp>
20#include <boost/math/special_functions/lambert_w.hpp>
21
22#include <EshelbianCohesive.hpp>
23
24namespace EshelbianPlasticity {
25
27
28 static inline constexpr double eps = 1e-8;
29
30 static inline constexpr double pi = boost::math::constants::pi<double>();
31 static inline constexpr double root_pi =
32 boost::math::constants::root_pi<double>();
33
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);
37 }
38
39 template <typename T>
40 static inline auto getDiffTau(const T &tau, const T &kappa, double gc) {
41 return -tau * (1.0 + (1.0 / (2.0 * kappa)));
42 }
43
44 template <typename T>
45 static T getAlpha(const T &kappa, double gc, double min_stiffness) {
46 auto tau = getTau(kappa, gc);
47 return kappa / (kappa * min_stiffness + tau);
48 }
49
50 template <typename T>
51 static T getDiffAlpha(const T &kappa, double gc, double min_stiffness) {
52 T tau = getTau(kappa, gc);
53 T diff_tau = getDiffTau(tau, kappa, gc);
54 T dnom = kappa * min_stiffness + tau;
55 return (tau - kappa * diff_tau) / (dnom * dnom);
56 }
57
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); // k=0 == principal branch
61 }
62
63 static double getInitialStrength(double kappa, double gc) {
64 const double tau = getTau(kappa, gc);
65 return tau * std::sqrt(2.0 / (kappa + 1.5));
66 }
67
68 static double invInitialStrength(double strength, double gc) {
69 // For negligible residual stiffness, the Mode-I damage-onset condition
70 //
71 // 0.5 * strength^2 * alpha'(kappa) = tau(kappa)
72 //
73 // gives strength = tau(kappa) * sqrt(2 / (kappa + 3/2)). This
74 // function is strictly decreasing, so use invTau(strength) as an
75 // initial upper bound and enlarge it until the root is bracketed.
76 double lower_kappa = 0;
77 double upper_kappa = invTau(strength, gc);
78 while (getInitialStrength(upper_kappa, gc) > strength)
79 upper_kappa *= 2;
80
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);
84 if (getInitialStrength(mid_kappa, gc) > strength)
85 lower_kappa = mid_kappa;
86 else
87 upper_kappa = mid_kappa;
88 }
89
90 return 0.5 * (lower_kappa + upper_kappa);
91 }
92
93 template <typename T>
94 static auto calculateY(const T t_eff, const T &kappa, double gc,
95 double min_stiffness) {
96 T diff_alpha = getDiffAlpha(kappa, gc, min_stiffness);
97 return 0.5 * t_eff * t_eff * diff_alpha;
98 }
99
100 template <typename T>
101 static auto calculateDissipation(const T &delta_kappa, const T t_eff,
102 const T &kappa, double gc,
103 double min_stiffness) {
104 T Y = calculateY(t_eff, kappa + delta_kappa, gc, min_stiffness);
105 return Y * delta_kappa;
106 }
107
108 template <typename T>
109 static auto calculateDissipationSurplus(const T &delta_kappa, const T t_eff,
110 const T &kappa, double gc,
111 double min_stiffness) {
112 T M = calculateY(t_eff, kappa + delta_kappa, gc, min_stiffness) -
113 getTau(kappa + delta_kappa, gc);
114 return -M * delta_kappa;
115 }
116
117 template <typename T>
118 static auto calculateDissipationSurplusDiffKappa(const T &delta_kappa,
119 const T &t_eff,
120 const T &kappa, double gc,
121 double min_stiffness) {
122
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 * 1i;
127 std::complex<T> cpx_M = calculateDissipationSurplus(
128 cpx_delta, cpx_t_eff, cpx_kappa, gc, min_stiffness);
129 return cpx_M.imag() / eps;
130 }
131
132 template <typename T>
134 const FTensor::Tensor1<T, 3> &t_traction, const T &delta_kappa,
135 const T &kappa, FTensor::Tensor1<double, 3> &t_n_normalize, double gc,
136 double beta, double min_stiffness) {
137 FTENSOR_INDEX(3, i);
138 FTensor::Tensor1<double, 3> t_diff_traction;
139 std::complex<T> cpx_delta = delta_kappa;
140 std::complex<T> cpx_kappa = kappa;
141 FTensor::Tensor1<std::complex<T>, 3> t_cpx_traction;
142 for (auto jj = 0; jj != 3; ++jj) {
143 t_cpx_traction(i) = t_traction(i);
144 t_cpx_traction(jj) += eps * 1i;
145 std::complex<T> cpx_teff =
146 calculateEffectiveTraction(t_cpx_traction, t_n_normalize, beta);
147 std::complex<T> cpx_M = calculateDissipationSurplus(
148 cpx_delta, cpx_teff, cpx_kappa, gc, min_stiffness);
149 t_diff_traction(jj) = cpx_M.imag() / eps;
150 }
151 return t_diff_traction;
152 }
153
154 template <typename T>
155 static auto calculateGap(const FTensor::Tensor1<T, 3> &t_traction,
156 FTensor::Tensor1<double, 3> &t_n_normalize,
157 double alpha, double beta,
158 bool sign_sensitive = true) {
159 FTENSOR_INDEX(3, i);
160 FTENSOR_INDEX(3, j);
161 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
163 t_P(i, j) = t_n_normalize(i) * t_n_normalize(j);
165 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
166 FTensor::Tensor1<T, 3> t_normal;
167 t_normal(i) = t_P(i, j) * t_traction(j);
168 FTensor::Tensor1<T, 3> t_tangential;
169 t_tangential(i) = t_Q(i, j) * t_traction(j);
170
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;
175
176 FTensor::Tensor1<T, 3> t_gap{0., 0., 0.};
177 if (std::real(s) > std::numeric_limits<double>::epsilon()) {
178 t_gap(i) = alpha * (
179
180 t_n_normalize(i) * teff / 2. +
181
182 (1.0 / 4.0) * (teff / s) * t_normal(i) +
183
184 (1.0 / beta) * (teff / s) * t_tangential(i)
185
186 );
187 }
188 return std::make_pair(teff, t_gap);
189 } else {
190 T teff = std::sqrt((t_normal(i) * t_normal(i)) +
191 (1. / beta) * t_tangential(i) * t_tangential(i));
193 t_gap(i) = alpha * (
194
195 t_normal(i) + (1.0 / beta) * t_tangential(i)
196
197 );
198 return std::make_pair(teff, t_gap);
199 }
200 }
201
202 template <typename T>
203 static auto
205 FTensor::Tensor1<double, 3> &t_n_normalize,
206 double alpha, double beta,
207 bool sign_sensitive = true) {
208 FTENSOR_INDEX(3, i);
210 FTensor::Tensor1<std::complex<T>, 3> t_cpx_delta;
211 FTensor::Tensor1<std::complex<T>, 3> t_cpx_traction;
212 for (auto jj = 0; jj != 3; ++jj) {
213 t_cpx_traction(i) = t_traction(i);
214 t_cpx_traction(jj) += eps * 1i;
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;
220 }
221 }
222 return t_dgap;
223 }
224
225 template <typename T>
226 static auto
228 FTensor::Tensor1<double, 3> &t_n_normalize,
229 double beta) {
230 auto [teff, t_gap] = calculateGap(t_traction, t_n_normalize, 1.0, beta);
231 return teff;
232 }
233};
234
236 OpGetParameters(boost::shared_ptr<double> gc_ptr, Sev severity = Sev::inform)
238 gcPtr(gc_ptr), logSev(severity) {
239 CHK_THROW_MESSAGE(getOptions(), "Failed to get EshelbianCohesive options");
240 }
241
242 MoFEMErrorCode doWork(int row_side, EntityType row_type,
243 EntitiesFieldData::EntData &row_data) {
245 *gcPtr = defaultGc;
247 }
248
249 static inline double strength = -1;
250 static inline double min_kappa = 1e-12;
251 static inline double min_stiffness = 1e-2;
252 static inline double kappa0 = 1;
253 static inline double beta = 1;
254
255private:
258
259 PetscOptionsBegin(PETSC_COMM_WORLD, "interface_", "", "none");
260
261 CHKERR PetscOptionsScalar("-gc", "Griffith energy release rate", "",
262 defaultGc, &defaultGc, PETSC_NULLPTR);
263 CHKERR PetscOptionsScalar("-min_stiffness", "Minimal interface stiffness",
264 "", min_stiffness, &min_stiffness, PETSC_NULLPTR);
265 CHKERR PetscOptionsScalar("-strength", "Strength of interface", "",
266 strength, &strength, PETSC_NULLPTR);
267 CHKERR PetscOptionsScalar("-min_kappa",
268 "Minimal kappa to avoid singularity", "",
269 min_kappa, &min_kappa, PETSC_NULLPTR);
270 CHKERR PetscOptionsScalar("-kappa0", "Characteristic length kappa0", "",
271 kappa0, &kappa0, PETSC_NULLPTR);
272 CHKERR PetscOptionsScalar("-beta", "Cohesive tangential coupling", "",
273 beta, &beta, PETSC_NULLPTR);
274
275 PetscOptionsEnd();
276
277 MOFEM_LOG("EP", logSev)
278 << "Interface Griffith energy release rate Gc -interface_gc = "
279 << defaultGc;
280 MOFEM_LOG("EP", logSev)
281 << "Interface min stiffness -interface_min_stiffness = "
282 << min_stiffness;
283 MOFEM_LOG("EP", logSev)
284 << "Interface strength -interface_strength = " << strength;
285 MOFEM_LOG("EP", logSev)
286 << "Interface minimal kappa -interface_min_kappa = " << min_kappa;
287 MOFEM_LOG("EP", logSev)
288 << "Interface characteristic length kappa0 -interface_kappa0 = "
289 << kappa0;
290 MOFEM_LOG("EP", logSev)
291 << "Interface tangential coupling -interface_beta = " << beta;
292
293 if (strength > 0) {
294 const double kappa_strength = GriffithCohesiveLaw::invInitialStrength(
295 static_cast<double>(strength), defaultGc);
296 min_kappa = std::max(min_kappa, kappa_strength);
297 MOFEM_LOG("EP", logSev)
298 << "Adjusted interface min kappa for initial Mode-I strength = "
299 << min_kappa << ", resulting strength = "
301 }
302
304 }
305
306 double defaultGc = 1.0;
307 boost::shared_ptr<double> gcPtr;
309};
310
311
312static Tag get_tag(moab::Interface &moab, std::string tag_name, int size) {
313 std::vector<double> dummy(size, 0.);
314 Tag tag;
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)
318 rval = MB_SUCCESS;
319 CHK_MOAB_THROW(rval, "Failed to get tag " + tag_name);
320 return tag;
321};
322
323Tag get_kappa_tag(moab::Interface &moab) {
324 return get_tag(moab, "KAPPA", 1);
325}
326
327Tag get_delta_kappa_tag(moab::Interface &moab) {
328 return get_tag(moab, "DELTA_KAPPA", 1);
329}
330
332 : public FormsIntegrators<FaceElementForcesAndSourcesCore::
333 UserDataOperator>::Assembly<A>::OpBrokenBase {
334
335 using OP =
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) {}
342
343 MoFEMErrorCode doWork(int row_side, EntityType row_type,
344 EntitiesFieldData::EntData &row_data) {
345
347
348 if (OP::entsPtr) {
349 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
351 }
352
353#ifndef NDEBUG
354 if (!brokenBaseSideData) {
355 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
356 }
357#endif // NDEBUG
358
359 auto do_work_rhs = [this](int row_side, EntityType row_type,
360 EntitiesFieldData::EntData &row_data) {
362#ifndef NDEBUG
363 auto base = row_data.getBase();
364 if (base < 0 && base >= LASTBASE) {
365 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
366 "row base not set properly");
367 }
368#endif // NDEBUG
369
370 // get number of dofs on row
371 OP::nbRows = row_data.getIndices().size();
372 if (!OP::nbRows)
374 // get number of integration points
375 OP::nbIntegrationPts = OP::getGaussPts().size2();
376 // get row base functions
377 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
378 // resize and clear the right hand side vector
379 OP::locF.resize(OP::nbRows, false);
380 OP::locF.clear();
381 OP::locMat.resize(OP::nbRows, OP::nbRows, false);
382 OP::locMat.clear();
383 if (OP::nbRows) {
384 // integrate local vector
385 CHKERR this->iNtegrate(row_data);
386 // assemble local vector
387 CHKERR this->aSsemble(row_data);
388 }
390 };
391
392 switch (OP::opType) {
393 case OP::OPSPACE:
394 for (auto &bd : *brokenBaseSideData) {
395 fluxMatPtr =
396 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
397 faceSense = bd.getSense();
398 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
399 fluxMatPtr.reset();
400 faceSense = 0;
401 }
402 break;
403 default:
405 (std::string("wrong op type ") +
406 OpBaseDerivativesBase::OpTypeNames[OP::opType])
407 .c_str());
408 }
409
411 }
412
413protected:
414 boost::shared_ptr<MatrixDouble> fluxMatPtr;
415 int faceSense = 0;
416};
417
419
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)
430 : OpBrokenBaseCohesive(broken_base_side_data, ents_ptr), gcPtr(gc_ptr),
431 kappaPtr(kappa_ptr), kappaDeltaPtr(kappa_delta_ptr),
432 lambdaPtr(lambda_ptr), dissipationTag(dissipation_tags),
433 gradDissipationTag(grad_dissipation_tags), vec_dJdu(vec_dJ_dx) {}
434
437
438 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
439
440 auto nb_dofs = data.getIndices().size();
441 FTENSOR_INDEX(3, i);
442 FTENSOR_INDEX(3, J);
443
444 int nb_integration_pts = OP::getGaussPts().size2();
445
446 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
447 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
448 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
449 auto t_face_normal = getFTensor1NormalsAtGaussPts();
450
451 int nb_base_functions = data.getN().size2() / 3;
452 auto t_row_base_fun = data.getFTensor1N<3>();
453 auto t_w = OP::getFTensor0IntegrationWeight();
454
455 auto next = [&]() {
456 ++t_P;
457 ++t_face_normal;
458 ++t_kappa;
459 ++t_delta_kappa;
460 ++t_w;
461 };
462
463 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
465 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
466 FTensor::Tensor1<double, 3> t_normalized_normal;
467 t_normalized_normal(J) = t_normal(J);
468 t_normalized_normal.normalize();
470 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
471
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);
477 auto [teff, t_gap] = GriffithCohesiveLaw::calculateGap(
478 t_traction, t_normalized_normal, alpha, OpGetParameters::beta,
479 true);
480 FTENSOR_INDEX(3, i);
481 FTensor::Tensor1<double, 3> t_gap_double;
482 t_gap_double(i) = -t_gap(i) / 2.;
483 return t_gap_double;
484 };
485
486 auto assemble = [&](const FTensor::Tensor1<double, 3> &&t_gap) {
487 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
488 int bb = 0;
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);
492 ++t_nf;
493 ++t_row_base_fun;
494 }
495 for (; bb != nb_base_functions; ++bb)
496 ++t_row_base_fun;
497 };
498
499 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
500 *gcPtr));
501
502 next();
503 }
504
506 };
507
508protected:
509 boost::shared_ptr<MatrixDouble> uGammaPtr;
510 boost::shared_ptr<double> gcPtr;
511 boost::shared_ptr<VectorDouble> kappaPtr;
512 boost::shared_ptr<VectorDouble> kappaDeltaPtr;
513 boost::shared_ptr<std::array<MatrixDouble, 2>> lambdaPtr;
514 boost::shared_ptr<double> totalDissipation;
515 boost::shared_ptr<double> tatalDissipationGrad;
519};
520
522
525
528
529 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
530
531 auto nb_dofs = data.getIndices().size();
532 FTENSOR_INDEX(3, i);
533 FTENSOR_INDEX(3, j);
534 FTENSOR_INDEX(3, J);
535
536 int nb_integration_pts = OP::getGaussPts().size2();
537
538 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
539 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
540 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
541 auto t_face_normal = getFTensor1NormalsAtGaussPts();
542
543 int nb_base_functions = data.getN().size2() / 3;
544 auto t_row_base_fun = data.getFTensor1N<3>();
545 auto t_w = OP::getFTensor0IntegrationWeight();
546
547 auto next = [&]() {
548 ++t_P;
549 ++t_kappa;
550 ++t_delta_kappa;
551 ++t_face_normal;
552 ++t_w;
553 };
554
555 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
557 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
558 FTensor::Tensor1<double, 3> t_normalized_normal;
559 t_normalized_normal(J) = t_normal(J);
560 t_normalized_normal.normalize();
562 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
563
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);
570 t_traction, t_normalized_normal, alpha, OpGetParameters::beta,
571 true);
572 FTENSOR_INDEX(3, i);
573 FTENSOR_INDEX(3, j);
574 FTensor::Tensor2<double, 3, 3> t_dgap_double;
575 t_dgap_double(i, j) = -t_dgap(i, j) / 2.;
576 return t_dgap_double;
577 };
578
579 auto assemble = [&](const FTensor::Tensor2<double, 3, 3> &&t_dgap) {
580 int rr = 0;
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));
584 auto t_col_base_fun = data.getFTensor1N<3>(gg, 0);
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);
588 ++t_mat;
589 ++t_col_base_fun;
590 }
591 ++t_row_base_fun;
592 }
593 for (; rr != nb_base_functions; ++rr)
594 ++t_row_base_fun;
595 };
596
597 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
598 *gcPtr));
599
600 next();
601 }
602
604 };
605
608
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());
613 // assemble local matrix
614 CHKERR this->matSetValuesHook(this, data, data, this->locMat);
615
617 }
618
619private:
620};
621
623
626
629
630 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
631
632 FTENSOR_INDEX(3, i);
633 FTENSOR_INDEX(3, J);
634 FTENSOR_INDEX(3, K);
635
636 int nb_integration_pts = OP::getGaussPts().size2();
637
638 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
639 auto t_lambda = getFTensor2FromMat<3, 3>(lambdaPtr->at(get_sense_index()));
640 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
641 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
642 auto t_face_normal = getFTensor1NormalsAtGaussPts();
643 auto t_w = OP::getFTensor0IntegrationWeight();
644
645 auto next = [&]() {
646 ++t_P;
647 ++t_face_normal;
648 ++t_kappa;
649 ++t_delta_kappa;
650 ++t_lambda;
651 ++t_w;
652 };
653
654 double face_dissipation = 0.0;
655 double face_grad_dissipation = 0.0;
656 auto face_handle = OP::getFEEntityHandle();
657 CHKERR getMoab().tag_get_data(dissipationTag, &face_handle, 1,
658 &face_dissipation);
659 CHKERR getMoab().tag_get_data(gradDissipationTag, &face_handle, 1,
660 &face_grad_dissipation);
661
662 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
664 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
665 FTensor::Tensor1<double, 3> t_normalized_normal;
666 t_normalized_normal(J) = t_normal(J);
667 t_normalized_normal.normalize();
669 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
670
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);
676 t_traction, t_normalized_normal, OpGetParameters::beta);
678 delta_kappa, teff, kappa, gc, OpGetParameters::min_stiffness);
679 double m_grad =
681 delta_kappa, teff, kappa, gc, OpGetParameters::min_stiffness);
682 return boost::make_tuple(m, m_grad);
683 };
684
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;
690 double diff_alpha = GriffithCohesiveLaw::getDiffAlpha(
691 kappa_plus_delta, gc, OpGetParameters::min_stiffness);
692 auto [teff, t_gap] = GriffithCohesiveLaw::calculateGap(
693 t_traction, t_normalized_normal, diff_alpha, OpGetParameters::beta);
694 FTENSOR_INDEX(3, i);
695 FTensor::Tensor1<double, 3> t_gap_double;
696 t_gap_double(i) = -t_gap(i);
697 return t_gap_double;
698 };
699
700 auto [J, dJ] = dJ_dkappa(t_delta_kappa, t_traction, t_normalized_normal,
701 t_kappa, *gcPtr);
702 face_dissipation += t_w * J * t_normal.l2();
703 face_grad_dissipation += t_w * dJ * t_normal.l2();
704
705 auto t_dr = dr_kappa(t_delta_kappa, t_traction, t_normalized_normal,
706 t_kappa, *gcPtr);
708 t_l(i) = t_lambda(i, K) * t_normal(K);
709 face_grad_dissipation -= t_w * t_l(i) * t_dr(i);
710
711 next();
712 }
713
714 CHKERR getMoab().tag_set_data(dissipationTag, &face_handle, 1,
715 &face_dissipation);
716 CHKERR getMoab().tag_set_data(gradDissipationTag, &face_handle, 1,
717 &face_grad_dissipation);
718
719
721 };
722
727
728protected:
729};
730
732
735
738
739 FTENSOR_INDEX(3, i);
740 FTENSOR_INDEX(3, J);
741
742 int nb_integration_pts = OP::getGaussPts().size2();
743 auto nb_dofs = data.getIndices().size();
744
745 int nb_base_functions = data.getN().size2() / 3;
746 auto t_row_base_fun = data.getFTensor1N<3>();
747 auto t_w = OP::getFTensor0IntegrationWeight();
748
749 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
750 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
751 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
752 auto t_face_normal = getFTensor1NormalsAtGaussPts();
753
754 auto next = [&]() {
755 ++t_P;
756 ++t_face_normal;
757 ++t_kappa;
758 ++t_delta_kappa;
759 ++t_w;
760 };
761
762 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
764 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
765 FTensor::Tensor1<double, 3> t_normalized_normal;
766 t_normalized_normal(J) = t_normal(J);
767 t_normalized_normal.normalize();
769 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
770
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);
775 FTENSOR_INDEX(3, i);
776 FTensor::Tensor1<double, 3> t_traction_double;
777 t_traction_double(i) = t_traction(i);
778 auto t_dM =
780 t_traction_double, delta_kappa, kappa, t_normalized_normal, gc,
782 FTensor::Tensor1<double, 3> t_dJ_double;
783 t_dJ_double(i) = t_dM(i);
784 return t_dJ_double;
785 };
786
787 auto assemble = [&](const FTensor::Tensor1<double, 3> &&t_dJ) {
788
789 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
790 int bb = 0;
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);
794 ++t_nf;
795 ++t_row_base_fun;
796 }
797 for (; bb != nb_base_functions; ++bb)
798 ++t_row_base_fun;
799 };
800
801 assemble(dJ_dtraction(t_traction, t_normalized_normal, t_delta_kappa,
802 t_kappa, *gcPtr));
803
804 // cerr << "AAAA " << OP::locF << endl;
805 next();
806 }
807
809 };
810
813 return VecSetValues<AssemblyTypeSelector<A>>(vec_dJdu, data, OP::locF,
814 ADD_VALUES);
816 }
817
818protected:
819};
820
822
824
826
828 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
829 Tag tag, TagGetType tag_get_type,
830 boost::shared_ptr<VectorDouble> tag_data_ptr,
831 boost::shared_ptr<Range> ents_ptr = nullptr)
832 : OpBrokenBaseCohesive(broken_base_side_data, ents_ptr), tagHandle(tag),
833 tagGetType(tag_get_type), tagDataPtr(tag_data_ptr) {}
834
837
838 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
839 auto &v = *tagDataPtr;
840
841 switch (tagGetType) {
842 case TagSET:
843 break;
844 case TagGET:
845 v.resize(1);
846 v.clear();
847 break;
848 }
849
850 auto get_data = [&](auto &v) {
852
853 auto &moab = getMoab();
854 auto fe_ent = getFEEntityHandle();
855
856 int size;
857 double *data;
858 rval = moab.tag_get_by_ptr(tagHandle, &fe_ent, 1, (const void **)&data,
859 &size);
860 if (
861
862 rval == MB_SUCCESS && size > 0 && size != v.size()
863
864 ) {
865 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
866 "Inconsistent size of tag data");
867 } else {
868 if (rval != MB_SUCCESS || tagGetType == TagSET) {
869 int tag_size[1];
870 tag_size[0] = v.size();
871 void const *tag_data[] = {&v[0]};
872 CHKERR moab.tag_set_by_ptr(tagHandle, &fe_ent, 1, tag_data, tag_size);
873 } else {
874 CHKERR moab.tag_get_by_ptr(tagHandle, &fe_ent, 1,
875 (const void **)&data, &size);
876 std::copy(data, data + size, v.begin());
877 }
878 }
879
881 };
882
883 CHKERR get_data(v);
884
886 }
887
892
893private:
895 boost::shared_ptr<VectorDouble> tagDataPtr;
897};
898
900 EshelbianCore &ep,
901 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
902 SmartPetscObj<Vec> lambda_vec = SmartPetscObj<Vec>()) {
903
904 using EleOnSide =
906 using SideEleOp = EleOnSide::UserDataOperator;
907
908 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
909 pip, {HDIV, H1, L2}, ep.materialH1Positions, ep.frontAdjEdges);
910
911 auto domain_side_flux = [&](auto &pip) {
912 // flux
913 auto broken_data_ptr =
914 boost::make_shared<std::vector<BrokenBaseSideData>>();
916 broken_data_ptr));
917 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
919 ep.piolaStress, flux_mat_ptr));
920 pip.push_back(new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
921
922 return broken_data_ptr;
923 };
924
925 auto get_lambda = [&](auto &pip) {
926 boost::shared_ptr<std::array<MatrixDouble, 2>> array_lambda_ptr;
927 if (lambda_vec) {
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),
932 lambda_vec));
934 auto op = new OP(NOSPACE, OP::OPSPACE);
935 op->doWorkRhsHook =
936 [lambda_mat_ptr, array_lambda_ptr](
937 DataOperator *base_op_ptr, int side, EntityType type,
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;
943 };
944 array_lambda_ptr->at(get_sense_index()) = *lambda_mat_ptr;
946 };
947 pip.push_back(op);
948 }
949 return array_lambda_ptr;
950 };
951
952 return std::make_pair(domain_side_flux(pip), get_lambda(pip));
953};
954
956 EshelbianCore &ep,
957 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
958 boost::shared_ptr<Range> interface_range_ptr,
959 SmartPetscObj<Vec> lambda_vec = SmartPetscObj<Vec>()) {
960
961 auto &m_field = ep.mField;
962
963 using BoundaryEle =
965 using EleOnSide =
967 using SideEleOp = EleOnSide::UserDataOperator;
968 using BdyEleOp = BoundaryEle::UserDataOperator;
969
970 auto face_side = [&]() {
971 // First: Iterate over skeleton FEs adjacent to Domain FEs
972 // Note: BoundaryEle, i.e. uses skeleton interation rule
973 auto op_loop_skeleton_side =
975 interface_range_ptr, Sev::noisy);
976 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
977 return -1;
978 };
979 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
980 set_integration_at_front_face;
981
982 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
983 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
984 ep.frontAdjEdges);
985
986 return op_loop_skeleton_side;
987 };
988
989 auto op_loop_skeleton_side = face_side();
990
991 // Second: Iterate over domain FEs adjacent to skelton, particularly one
992 // domain element.
993 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
994 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
995 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
996 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
997 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
998 auto [broken_data_flux_ptr, lambda_ptr] = pushCohesiveOpsDomainImpl(
999 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
1000 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
1002 op_reset_broken_data->doWorkRhsHook =
1003 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
1004 EntityType type,
1006 broken_data_flux_ptr->resize(0);
1007 return 0;
1008 };
1009 op_loop_skeleton_side->getOpPtrVector().push_back(op_reset_broken_data);
1010 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
1011
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>();
1015
1016 op_loop_skeleton_side->getOpPtrVector().push_back(
1017 new OpGetParameters(gc_ptr));
1018 op_loop_skeleton_side->getOpPtrVector().push_back(
1019 new OpGetTag(broken_data_flux_ptr, get_kappa_tag(m_field.get_moab()),
1020 TagGetType::TagGET, kappa_ptr));
1021 op_loop_skeleton_side->getOpPtrVector().push_back(new OpGetTag(
1022 broken_data_flux_ptr, get_delta_kappa_tag(m_field.get_moab()),
1023 TagGetType::TagGET, kappa_delta_ptr));
1024
1025 return std::make_tuple(op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr,
1026 kappa_ptr, kappa_delta_ptr);
1027};
1028
1030 EshelbianCore &ep,
1031 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1032 boost::shared_ptr<Range> interface_range_ptr,
1033 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1035
1036 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
1037 kappa_delta_ptr] =
1038 pushCohesiveOpsImpl(ep, set_integration_at_front_face,
1039 interface_range_ptr);
1040
1041 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
1042 op_loop_skeleton_side->getOpPtrVector().push_back(
1044 u_gamma_ptr));
1045 op_loop_skeleton_side->getOpPtrVector().push_back(new OpCohesiveRhs(
1046 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
1047
1048 pip.push_back(op_loop_skeleton_side);
1049
1051};
1052
1054 EshelbianCore &ep,
1055 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1056 boost::shared_ptr<Range> interface_range_ptr,
1057 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1059
1060 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
1061 kappa_delta_ptr] =
1062 pushCohesiveOpsImpl(ep, set_integration_at_front_face,
1063 interface_range_ptr);
1064 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
1065 op_loop_skeleton_side->getOpPtrVector().push_back(
1067 u_gamma_ptr));
1068 op_loop_skeleton_side->getOpPtrVector().push_back(new OpCohesiveLhs_dPdP(
1069 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
1070
1071 pip.push_back(op_loop_skeleton_side);
1072
1074};
1075
1077 EshelbianCore &ep,
1078 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1079 SmartPetscObj<Vec> lambda_vec) {
1080 auto &m_field = ep.mField;
1081
1082 using EleOnSide =
1084 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1085 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1086 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1087 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
1088 auto [broken_data_flux_ptr, lambda_ptr] = pushCohesiveOpsDomainImpl(
1089 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
1090
1091 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
1093 op_reset_broken_data->doWorkRhsHook =
1094 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
1095 EntityType type,
1097 broken_data_flux_ptr->resize(0);
1098 return 0;
1099 };
1100 pip.push_back(op_reset_broken_data);
1101 pip.push_back(op_loop_domain_side);
1102
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);
1106
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>();
1110
1111 pip.push_back(new OpGetParameters(gc_ptr, Sev::noisy));
1112 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1113 get_kappa_tag(m_field.get_moab()),
1114 TagGetType::TagGET, kappa_ptr));
1115 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1116 get_delta_kappa_tag(m_field.get_moab()),
1117 TagGetType::TagGET, kappa_delta_ptr));
1118
1119 pip.push_back(new OpCohesive_dJ_dkappa(
1120 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr, lambda_ptr,
1121 tag_dissipation, tag_grad_dissipation));
1122
1123 return std::make_pair(tag_dissipation, tag_grad_dissipation);
1124}
1125
1127 EshelbianCore &ep,
1128 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1129 auto &m_field = ep.mField;
1130
1131 using EleOnSide =
1133 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1134 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1135 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1136 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
1137 auto [broken_data_flux_ptr, lambda_ptr] =
1138 pushCohesiveOpsDomainImpl(ep, op_loop_domain_side->getOpPtrVector());
1139
1140 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
1142 op_reset_broken_data->doWorkRhsHook =
1143 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
1144 EntityType type,
1146 broken_data_flux_ptr->resize(0);
1147 return 0;
1148 };
1149 pip.push_back(op_reset_broken_data);
1150 pip.push_back(op_loop_domain_side);
1151
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>();
1155
1156 pip.push_back(new OpGetParameters(gc_ptr, Sev::noisy));
1157 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1158 get_kappa_tag(m_field.get_moab()),
1159 TagGetType::TagGET, kappa_ptr));
1160 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1161 get_delta_kappa_tag(m_field.get_moab()),
1162 TagGetType::TagGET, kappa_delta_ptr));
1163 auto dJ_dx_vec = createDMVector(ep.dmElastic);
1164 pip.push_back(new OpCohesive_dJ_dP(broken_data_flux_ptr, gc_ptr, kappa_ptr,
1165 kappa_delta_ptr, lambda_ptr, Tag(), Tag(),
1166 dJ_dx_vec));
1167
1168 return dJ_dx_vec;
1169}
1170
1172 EshelbianCore &ep,
1173 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1174 SmartPetscObj<Vec> lambda_vec,
1175 CommInterface::EntitiesPetscVector &dissipation_vec,
1176 CommInterface::EntitiesPetscVector &grad_dissipation_vec) {
1178
1179 using BoundaryEle =
1181 using BdyEleOp = BoundaryEle::UserDataOperator;
1182
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(
1188 fe_ptr->getOpPtrVector(), {L2}, ep.materialH1Positions,
1189 ep.frontAdjEdges);
1190
1191 auto interface_face = [&](FEMethod *fe_method_ptr) {
1192 auto ent = fe_method_ptr->getFEEntityHandle();
1193 if (
1194
1195 ep.interfaceFaces->find(ent) != ep.interfaceFaces->end()
1196
1197 ) {
1198 return true;
1199 };
1200 return false;
1201 };
1202
1203 fe_ptr->exeTestHook = interface_face;
1204
1205 return fe_ptr;
1206 };
1207
1208 auto face_fe = get_face_ele();
1209 auto [tag_dissipation, tag_grad_dissipation] =
1210 pushCohesive_dJ_dkappa_Impl(ep, face_fe->getOpPtrVector(), lambda_vec);
1211
1212 constexpr double zero = 0.0;
1213 CHKERR ep.mField.get_moab().tag_clear_data(tag_dissipation,
1214 *(ep.interfaceFaces), &zero);
1215 CHKERR ep.mField.get_moab().tag_clear_data(tag_grad_dissipation,
1216 *(ep.interfaceFaces), &zero);
1219 ep.mField.get_moab(), dissipation_vec, tag_dissipation);
1221 ep.mField.get_moab(), grad_dissipation_vec, tag_grad_dissipation);
1222
1224}
1225
1227 EshelbianCore &ep,
1228 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1229 SmartPetscObj<KSP> ksp, SmartPetscObj<Vec> lambda_vec) {
1231
1232 using BoundaryEle =
1234 using BdyEleOp = BoundaryEle::UserDataOperator;
1235
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(
1241 fe_ptr->getOpPtrVector(), {L2}, ep.materialH1Positions,
1242 ep.frontAdjEdges);
1243
1244 auto interface_face = [&](FEMethod *fe_method_ptr) {
1245 auto ent = fe_method_ptr->getFEEntityHandle();
1246 if (
1247
1248 ep.interfaceFaces->find(ent) != ep.interfaceFaces->end()
1249
1250 ) {
1251 return true;
1252 };
1253 return false;
1254 };
1255
1256 fe_ptr->exeTestHook = interface_face;
1257
1258 return fe_ptr;
1259 };
1260
1261 auto face_fe = get_face_ele();
1262 auto dJ_dx = pushCohesive_dJ_dx_Impl(ep, face_fe->getOpPtrVector());
1264 ep.dmElastic, ep.skeletonElement, face_fe, 0, ep.mField.get_comm_size());
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);
1271 double dJ_dx_norm2;
1272 CHKERR VecNorm(dJ_dx, NORM_2, &dJ_dx_norm2);
1273 MOFEM_LOG("EP", Sev::inform)
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);
1278 } else {
1279 CHKERR KSPSolveTranspose(ksp, dJ_dx, lambda_vec);
1280 }
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);
1285 MOFEM_LOG("EP", Sev::inform)
1286 << "evaluateCohesiveLambdaImpl: Norm of lambda vector: " << lambda_norm2;
1287
1289}
1290
1295
1296 CHKERR TSSetFromOptions(ts);
1297 CHKERR TSSetStepNumber(ts, 0);
1298 CHKERR TSSetTime(ts, 0);
1299 CHKERR TSSetSolution(ts, x);
1300 double dt;
1301 CHKERR TSGetTimeStep(ts, &dt);
1302 MOFEM_LOG("EP", Sev::inform)
1303 << "evaluatePrimalProblemCohesiveImpl: Time step dt: " << dt;
1304 CHKERR TSSolve(ts, PETSC_NULLPTR);
1305 CHKERR TSSetTimeStep(ts, dt);
1306
1307 CHKERR DMoFEMMeshToLocalVector(ep.dmElastic, x, INSERT_VALUES,
1308 SCATTER_FORWARD);
1309 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
1310 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
1311
1312 double x_norm2;
1313 CHKERR VecNorm(x, NORM_2, &x_norm2);
1314 MOFEM_LOG("EP", Sev::inform)
1315 << "evaluatePrimalProblemCohesiveImpl: Norm of displacement vector: "
1316 << x_norm2;
1317
1319}
1320
1323 EshelbianCore *ep,
1324 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1325 SmartPetscObj<TS> time_solver)
1326 : ep_ptr(ep), setIntegrationAtFrontFace(set_integration_at_front_face),
1327 timeSolver(time_solver),
1328
1329 kspSolVec(createDMVector(ep->dmElastic)),
1330 lambdaVec(createDMVector(ep->dmElastic)),
1331 kappaVec(CommInterface::createEntitiesPetscVector(
1332 ep->mField.get_comm(), ep->mField.get_moab(),
1333 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1334 Sev::noisy)),
1336 ep->mField.get_comm(), ep->mField.get_moab(),
1337 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1338 Sev::noisy)),
1340 ep->mField.get_comm(), ep->mField.get_moab(),
1341 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1342 Sev::noisy)) {}
1343
1345 return vectorDuplicate(kappaVec.second);
1346 }
1347
1351
1355
1359
1360private:
1364
1371 PetscReal *f,
1372 Vec g, void *ctx);
1373};
1374
1375boost::shared_ptr<CohesiveTAOCtx> createCohesiveTAOCtx(
1376 EshelbianCore *ep_ptr,
1377 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1378 SmartPetscObj<TS> time_solver) {
1379 return boost::make_shared<CohesiveTAOCtxImpl>(
1380 ep_ptr, set_integration_at_front_face, time_solver);
1381}
1382
1384 PetscReal *f, Vec g,
1385 void *ctx) {
1386
1388 auto cohesive_ctx = static_cast<CohesiveTAOCtxImpl *>(ctx);
1389 auto &ep = *(cohesive_ctx->ep_ptr);
1390
1391#ifndef NDEBUG
1392 CHKERR VecView(delta_kappa, PETSC_VIEWER_STDOUT_WORLD);
1393#endif
1394 // Set delta_kappa values to the tag
1395 CHKERR VecCopy(delta_kappa, cohesive_ctx->kappaVec.second);
1396 CHKERR VecGhostUpdateBegin(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1397 SCATTER_FORWARD);
1398 CHKERR VecGhostUpdateEnd(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1399 SCATTER_FORWARD);
1401 ep.mField.get_moab(), cohesive_ctx->kappaVec,
1403
1404 // solve primal problem
1405 CHKERR evaluatePrimalProblemCohesiveImpl(ep, cohesive_ctx->timeSolver,
1406 cohesive_ctx->kspSolVec);
1407 // solve adjoint problem to get lambda
1408 auto ksp = snesGetKSP(tsGetSNES(cohesive_ctx->timeSolver));
1409 CHKERR evaluateCohesiveLambdaImpl(ep, cohesive_ctx->setIntegrationAtFrontFace,
1410 ksp, cohesive_ctx->lambdaVec);
1411 // evaluate dissipation and its gradient
1413 ep, cohesive_ctx->setIntegrationAtFrontFace, cohesive_ctx->lambdaVec,
1414 cohesive_ctx->dissipationVec, cohesive_ctx->gradDissipationVec);
1415
1416 CHKERR VecSum(cohesive_ctx->dissipationVec.second, f);
1417 CHKERR VecCopy(cohesive_ctx->gradDissipationVec.second, g);
1418
1419 MOFEM_LOG("EP", Sev::inform)
1420 << "Cohesive objective function (negative total dissipation): " << *f;
1421
1423}
1424
1433
1434}; // namespace EshelbianPlasticity
Eshelbian plasticity interface.
std::string type
#define FTENSOR_INDEX(DIM, I)
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
@ LASTBASE
Definition definitions.h:69
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define 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_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
double kappa
constexpr auto t_kd
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMoFEMLoopFiniteElementsUpAndLowRank(DM dm, const char fe_name[], MoFEM::FEMethod *method, int low_rank, int up_rank, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:557
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
FTensor::Index< 'i', SPACE_DIM > i
double dt
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
double tol
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
Definition Common.hpp:10
auto snesGetKSP(SNES snes)
auto tsGetSNES(TS ts)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
constexpr double g
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 > duplicateGradientVec() override
SmartPetscObj< Vec > duplicateKappaVec() override
CommInterface::EntitiesPetscVector & getKappaVec() override
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 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 T getTau(const T &k, double gc)
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 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
boost::shared_ptr< double > totalDissipation
boost::shared_ptr< std::array< MatrixDouble, 2 > > lambdaPtr
MoFEMErrorCode aSsemble(EntData &data)
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
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
Managing BitRefLevels.
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.
@ 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
BoundaryEle::UserDataOperator BdyEleOp