v0.15.5
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>
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> static T getDiffAlpha(const T &kappa, double gc) {
51 T tau = getTau(kappa, gc);
52 T diff_tau = getDiffTau(tau, kappa, gc);
53 return (tau - kappa * diff_tau) / (tau * tau);
54 }
55
56 template <typename T> static auto invTau(const T &tau, double Gf) {
57 const T z = (2.0 * Gf * Gf) / (pi * tau * tau);
58 return T(0.5) * boost::math::lambert_w(z, 0); // k=0 == principal branch
59 }
60
61 template <typename T>
62 static auto calculateY(const T t_eff, const T &kappa, double gc) {
63 T diff_alpha = getDiffAlpha(kappa, gc);
64 return 0.5 * t_eff * t_eff * diff_alpha;
65 }
66
67 template <typename T>
68 static auto calculateDissipation(const T &delta_kappa, const T t_eff,
69 const T &kappa, double gc) {
70 T Y = calculateY(t_eff, kappa + delta_kappa, gc);
71 return Y * delta_kappa;
72 }
73
74 template <typename T>
75 static auto calculateDissipationSurplus(const T &delta_kappa, const T t_eff,
76 const T &kappa, double gc) {
77 T M = calculateY(t_eff, kappa + delta_kappa, gc) -
78 getTau(kappa + delta_kappa, gc);
79 return -M * delta_kappa;
80 }
81
82 template <typename T>
83 static auto calculateDissipationSurplusDiffKappa(const T &delta_kappa,
84 const T &t_eff,
85 const T &kappa, double gc) {
86
87 std::complex<T> cpx_delta = delta_kappa;
88 std::complex<T> cpx_t_eff = t_eff;
89 std::complex<T> cpx_kappa = kappa;
90 cpx_delta += eps * 1i;
91 std::complex<T> cpx_M =
92 calculateDissipationSurplus(cpx_delta, cpx_t_eff, cpx_kappa, gc);
93 return cpx_M.imag() / eps;
94 }
95
96 template <typename T>
98 const FTensor::Tensor1<T, 3> &t_traction, const T &delta_kappa,
99 const T &kappa, FTensor::Tensor1<double, 3> &t_n_normalize, double gc,
100 double beta) {
101 FTENSOR_INDEX(3, i);
102 FTensor::Tensor1<double, 3> t_diff_traction;
103 std::complex<T> cpx_delta = delta_kappa;
104 std::complex<T> cpx_kappa = kappa;
105 FTensor::Tensor1<std::complex<T>, 3> t_cpx_traction;
106 for (auto jj = 0; jj != 3; ++jj) {
107 t_cpx_traction(i) = t_traction(i);
108 t_cpx_traction(jj) += eps * 1i;
109 std::complex<T> cpx_teff =
110 calculateEffectiveTraction(t_cpx_traction, t_n_normalize, beta);
111 std::complex<T> cpx_M =
112 calculateDissipationSurplus(cpx_delta, cpx_teff, cpx_kappa, gc);
113 t_diff_traction(jj) = cpx_M.imag() / eps;
114 }
115 return t_diff_traction;
116 }
117
118 template <typename T>
119 static auto calculateGap(const FTensor::Tensor1<T, 3> &t_traction,
120 FTensor::Tensor1<double, 3> &t_n_normalize,
121 double alpha, double beta) {
122 FTENSOR_INDEX(3, i);
123 FTENSOR_INDEX(3, j);
124 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
126 t_P(i, j) = t_n_normalize(i) * t_n_normalize(j);
128 t_Q(i, j) = t_kd(i, j) - t_P(i, j);
129 FTensor::Tensor1<T, 3> t_normal;
130 t_normal(i) = t_P(i, j) * t_traction(j);
131 FTensor::Tensor1<T, 3> t_tangential;
132 t_tangential(i) = t_Q(i, j) * t_traction(j);
133 T teff = (t_n_normalize(i) * t_normal(i) / 2.) +
134 std::sqrt((t_normal(i) * t_normal(i)) / 2. +
135 (1. / beta) * t_tangential(i) * t_tangential(i));
137 t_gap(i) = alpha * (
138
139 (teff * (t_n_normalize(j) * t_P(j, i))) +
140 t_normal(j) * t_P(j, i) +
141 (1. / beta) * t_tangential(j) * t_Q(j, i)
142
143 );
144 return std::make_pair(teff, t_gap);
145 }
146
147 template <typename T>
148 static auto
150 FTensor::Tensor1<double, 3> &t_n_normalize,
151 double alpha, double beta) {
152 FTENSOR_INDEX(3, i);
154 FTensor::Tensor1<std::complex<T>, 3> t_cpx_delta;
155 FTensor::Tensor1<std::complex<T>, 3> t_cpx_traction;
156 for (auto jj = 0; jj != 3; ++jj) {
157 t_cpx_traction(i) = t_traction(i);
158 t_cpx_traction(jj) += eps * 1i;
159 auto [teff_cpx, t_cpx_gap] =
160 calculateGap(t_cpx_traction, t_n_normalize, alpha, beta);
161 for (auto ii = 0; ii != 3; ++ii) {
162 auto v = t_cpx_gap(ii).imag();
163 t_dgap(ii, jj) = v / eps;
164 }
165 }
166 return t_dgap;
167 }
168
169 template <typename T>
170 static auto
172 FTensor::Tensor1<double, 3> &t_n_normalize,
173 double beta) {
174 auto [teff, t_gap] = calculateGap(t_traction, t_n_normalize, 1.0, beta);
175 return teff;
176 }
177};
178
180 OpGetParameters(boost::shared_ptr<double> gc_ptr, Sev severity = Sev::inform)
182 gcPtr(gc_ptr), logSev(severity) {
183 CHK_THROW_MESSAGE(getOptions(), "Failed to get EshelbianCohesive options");
184 }
185
186 MoFEMErrorCode doWork(int row_side, EntityType row_type,
187 EntitiesFieldData::EntData &row_data) {
189 *gcPtr = defaultGc;
191 }
192
193 static inline double strength = -1;
194 static inline double min_kappa = 1e-12;
195 static inline double min_stiffness = 1e-2;
196 static inline double kappa0 = 1;
197 static inline double beta = 1;
198
199private:
202
203 PetscOptionsBegin(PETSC_COMM_WORLD, "interface_", "", "none");
204
205 CHKERR PetscOptionsScalar("-gc", "Griffith energy release rate", "",
206 defaultGc, &defaultGc, PETSC_NULLPTR);
207 CHKERR PetscOptionsScalar("-min_stiffness", "Minimal interface stiffness",
208 "", min_stiffness, &min_stiffness, PETSC_NULLPTR);
209 CHKERR PetscOptionsScalar("-strength", "Strength of interface", "",
210 strength, &strength, PETSC_NULLPTR);
211 CHKERR PetscOptionsScalar("-min_kappa",
212 "Minimal kappa to avoid singularity", "",
213 min_kappa, &min_kappa, PETSC_NULLPTR);
214 CHKERR PetscOptionsScalar("-kappa0", "Characteristic length kappa0", "",
215 kappa0, &kappa0, PETSC_NULLPTR);
216 CHKERR PetscOptionsScalar("-beta", "Cohesive tangential coupling", "",
217 beta, &beta, PETSC_NULLPTR);
218
219 PetscOptionsEnd();
220
221 MOFEM_LOG("EP", logSev)
222 << "Interface Griffith energy release rate Gc -interface_gc = "
223 << defaultGc;
224 MOFEM_LOG("EP", logSev)
225 << "Interface min stiffness -interface_min_stiffness = "
226 << min_stiffness;
227 MOFEM_LOG("EP", logSev)
228 << "Interface strength -interface_strength = " << strength;
229 MOFEM_LOG("EP", logSev)
230 << "Interface minimal kappa -interface_min_kappa = " << min_kappa;
231 MOFEM_LOG("EP", logSev)
232 << "Interface characteristic length kappa0 -interface_kappa0 = "
233 << kappa0;
234
235 if (strength > 0) {
236 double kappa_strength =
237 GriffithCohesiveLaw::invTau(static_cast<double>(strength), defaultGc);
238 min_kappa = std::max(min_kappa, kappa_strength);
239 MOFEM_LOG("EP", logSev)
240 << "Adjusted interface min kappa to capture strength = " << min_kappa;
241 }
242
244 }
245
246 double defaultGc = 1.0;
247 boost::shared_ptr<double> gcPtr;
249};
250
251
252static Tag get_variable_tag(moab::Interface &moab, std::string tag_name) {
253 Tag tag;
254 const int def_size = 1;
255 rval =
256 moab.tag_get_handle(tag_name.c_str(), def_size, MB_TYPE_DOUBLE, tag,
257 MB_TAG_CREAT | MB_TAG_VARLEN | MB_TAG_SPARSE, NULL);
258 if (rval == MB_ALREADY_ALLOCATED)
259 rval = MB_SUCCESS;
260 CHK_MOAB_THROW(rval, "Failed to get tag " + tag_name);
261 return tag;
262}
263
264static Tag get_tag(moab::Interface &moab, std::string tag_name, int size) {
265 Tag tag;
266 rval = moab.tag_get_handle(tag_name.c_str(), size, MB_TYPE_DOUBLE, tag,
267 MB_TAG_CREAT | MB_TAG_SPARSE, NULL);
268 if (rval == MB_ALREADY_ALLOCATED)
269 rval = MB_SUCCESS;
270 CHK_MOAB_THROW(rval, "Failed to get tag " + tag_name);
271 return tag;
272};
273
274Tag get_kappa_tag(moab::Interface &moab) {
275 return get_tag(moab, "KAPPA", 1);
276}
277
278Tag get_delta_kappa_tag(moab::Interface &moab) {
279 return get_tag(moab, "DELTA_KAPPA", 1);
280}
281
283 : public FormsIntegrators<FaceElementForcesAndSourcesCore::
284 UserDataOperator>::Assembly<A>::OpBrokenBase {
285
286 using OP =
288 Assembly<A>::OpBrokenBase;
290 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_flux_data_ptr,
291 boost::shared_ptr<Range> ents_ptr = nullptr)
292 : OP(broken_flux_data_ptr, ents_ptr) {}
293
294 MoFEMErrorCode doWork(int row_side, EntityType row_type,
295 EntitiesFieldData::EntData &row_data) {
296
298
299 if (OP::entsPtr) {
300 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
302 }
303
304#ifndef NDEBUG
305 if (!brokenBaseSideData) {
306 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
307 }
308#endif // NDEBUG
309
310 auto do_work_rhs = [this](int row_side, EntityType row_type,
311 EntitiesFieldData::EntData &row_data) {
313#ifndef NDEBUG
314 auto base = row_data.getBase();
315 if (base < 0 && base >= LASTBASE) {
316 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
317 "row base not set properly");
318 }
319#endif // NDEBUG
320
321 // get number of dofs on row
322 OP::nbRows = row_data.getIndices().size();
323 if (!OP::nbRows)
325 // get number of integration points
326 OP::nbIntegrationPts = OP::getGaussPts().size2();
327 // get row base functions
328 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
329 // resize and clear the right hand side vector
330 OP::locF.resize(OP::nbRows, false);
331 OP::locF.clear();
332 OP::locMat.resize(OP::nbRows, OP::nbRows, false);
333 OP::locMat.clear();
334 if (OP::nbRows) {
335 // integrate local vector
336 CHKERR this->iNtegrate(row_data);
337 // assemble local vector
338 CHKERR this->aSsemble(row_data);
339 }
341 };
342
343 switch (OP::opType) {
344 case OP::OPSPACE:
345 for (auto &bd : *brokenBaseSideData) {
346 fluxMatPtr =
347 boost::shared_ptr<MatrixDouble>(brokenBaseSideData, &bd.getFlux());
348 faceSense = bd.getSense();
349 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData());
350 fluxMatPtr.reset();
351 faceSense = 0;
352 }
353 break;
354 default:
356 (std::string("wrong op type ") +
357 OpBaseDerivativesBase::OpTypeNames[OP::opType])
358 .c_str());
359 }
360
362 }
363
364protected:
365 boost::shared_ptr<MatrixDouble> fluxMatPtr;
366 int faceSense = 0;
367};
368
370
373 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
374 boost::shared_ptr<double> gc_ptr,
375 boost::shared_ptr<VectorDouble> kappa_ptr,
376 boost::shared_ptr<VectorDouble> kappa_delta_ptr,
377 boost::shared_ptr<std::array<MatrixDouble, 2>> lambda_ptr = nullptr,
378 Tag dissipation_tags = Tag(), Tag grad_dissipation_tags = Tag(),
380 boost::shared_ptr<Range> ents_ptr = nullptr)
381 : OpBrokenBaseCohesive(broken_base_side_data, ents_ptr), gcPtr(gc_ptr),
382 kappaPtr(kappa_ptr), kappaDeltaPtr(kappa_delta_ptr),
383 lambdaPtr(lambda_ptr), dissipationTag(dissipation_tags),
384 gradDissipationTag(grad_dissipation_tags), vec_dJdu(vec_dJ_dx) {}
385
388
389 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
390
391 auto nb_dofs = data.getIndices().size();
392 FTENSOR_INDEX(3, i);
393 FTENSOR_INDEX(3, J);
394
395 int nb_integration_pts = OP::getGaussPts().size2();
396
397 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
398 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
399 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
400 auto t_face_normal = getFTensor1NormalsAtGaussPts();
401
402 int nb_base_functions = data.getN().size2() / 3;
403 auto t_row_base_fun = data.getFTensor1N<3>();
404 auto t_w = OP::getFTensor0IntegrationWeight();
405
406 auto next = [&]() {
407 ++t_P;
408 ++t_face_normal;
409 ++t_kappa;
410 ++t_delta_kappa;
411 ++t_w;
412 };
413
414 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
416 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
417 FTensor::Tensor1<double, 3> t_normalized_normal;
418 t_normalized_normal(J) = t_normal(J);
419 t_normalized_normal.normalize();
421 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
422
423 auto fracture = [this](auto &t_traction, auto &t_normalized_normal,
424 auto &t_kappa, auto &t_delta_kappa, auto gc) {
425 double kappa = static_cast<double>(t_kappa + t_delta_kappa);
428 auto [teff, t_gap] = GriffithCohesiveLaw::calculateGap(
429 t_traction, t_normalized_normal, alpha, OpGetParameters::beta);
430 FTENSOR_INDEX(3, i);
431 FTensor::Tensor1<double, 3> t_gap_double;
432 t_gap_double(i) = -t_gap(i);
433 return t_gap_double;
434 };
435
436 auto assemble = [&](const FTensor::Tensor1<double, 3> &&t_gap) {
437 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
438 int bb = 0;
439 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
440 double row_base = t_w * (t_row_base_fun(J) * t_normal(J));
441 t_nf(i) += row_base * t_gap(i);
442 ++t_nf;
443 ++t_row_base_fun;
444 }
445 for (; bb != nb_base_functions; ++bb)
446 ++t_row_base_fun;
447 };
448
449 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
450 *gcPtr));
451
452 next();
453 }
454
456 };
457
458protected:
459 boost::shared_ptr<MatrixDouble> uGammaPtr;
460 boost::shared_ptr<double> gcPtr;
461 boost::shared_ptr<VectorDouble> kappaPtr;
462 boost::shared_ptr<VectorDouble> kappaDeltaPtr;
463 boost::shared_ptr<std::array<MatrixDouble, 2>> lambdaPtr;
464 boost::shared_ptr<double> totalDissipation;
465 boost::shared_ptr<double> tatalDissipationGrad;
469};
470
472
475
478
479 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
480
481 auto nb_dofs = data.getIndices().size();
482 FTENSOR_INDEX(3, i);
483 FTENSOR_INDEX(3, j);
484 FTENSOR_INDEX(3, J);
485
486 int nb_integration_pts = OP::getGaussPts().size2();
487
488 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
489 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
490 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
491 auto t_face_normal = getFTensor1NormalsAtGaussPts();
492
493 int nb_base_functions = data.getN().size2() / 3;
494 auto t_row_base_fun = data.getFTensor1N<3>();
495 auto t_w = OP::getFTensor0IntegrationWeight();
496
497 auto next = [&]() {
498 ++t_P;
499 ++t_kappa;
500 ++t_delta_kappa;
501 ++t_face_normal;
502 ++t_w;
503 };
504
505 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
507 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
508 FTensor::Tensor1<double, 3> t_normalized_normal;
509 t_normalized_normal(J) = t_normal(J);
510 t_normalized_normal.normalize();
512 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
513
514 auto fracture = [this](auto &t_traction, auto &t_normalized_normal,
515 auto &t_kappa, auto &t_delta_kappa, auto gc) {
516 double kappa = static_cast<double>(t_kappa + t_delta_kappa);
520 t_traction, t_normalized_normal, alpha, OpGetParameters::beta);
521 FTENSOR_INDEX(3, i);
522 FTENSOR_INDEX(3, j);
523 FTensor::Tensor2<double, 3, 3> t_dgap_double;
524 t_dgap_double(i, j) = -t_dgap(i, j);
525 return t_dgap_double;
526 };
527
528 auto assemble = [&](const FTensor::Tensor2<double, 3, 3> &&t_dgap) {
529 int rr = 0;
530 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
531 auto t_mat = getFTensor2FromArray<3, 3, 3>(OP::locMat, 3 * rr);
532 double row_base = t_w * (t_row_base_fun(J) * t_normal(J));
533 auto t_col_base_fun = data.getFTensor1N<3>(gg, 0);
534 for (int cc = 0; cc != nb_dofs / SPACE_DIM; ++cc) {
535 double col_base = t_col_base_fun(J) * t_normalized_normal(J);
536 t_mat(i, j) += (row_base * col_base) * t_dgap(i, j);
537 ++t_mat;
538 ++t_col_base_fun;
539 }
540 ++t_row_base_fun;
541 }
542 for (; rr != nb_base_functions; ++rr)
543 ++t_row_base_fun;
544 };
545
546 assemble(fracture(t_traction, t_normalized_normal, t_kappa, t_delta_kappa,
547 *gcPtr));
548
549 next();
550 }
551
553 };
554
557
558 if (!this->timeScalingFun.empty())
559 this->locMat *= this->timeScalingFun(this->getFEMethod()->ts_t);
560 if (!this->feScalingFun.empty())
561 this->locMat *= this->feScalingFun(this->getFEMethod());
562 // assemble local matrix
563 CHKERR this->matSetValuesHook(this, data, data, this->locMat);
564
566 }
567
568private:
569};
570
572
575
578
579 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
580
581 FTENSOR_INDEX(3, i);
582 FTENSOR_INDEX(3, J);
583 FTENSOR_INDEX(3, K);
584
585 int nb_integration_pts = OP::getGaussPts().size2();
586
587 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
588 auto t_lambda = getFTensor2FromMat<3, 3>(lambdaPtr->at(get_sense_index()));
589 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
590 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
591 auto t_face_normal = getFTensor1NormalsAtGaussPts();
592 auto t_w = OP::getFTensor0IntegrationWeight();
593
594 auto next = [&]() {
595 ++t_P;
596 ++t_face_normal;
597 ++t_kappa;
598 ++t_delta_kappa;
599 ++t_lambda;
600 ++t_w;
601 };
602
603 double face_dissipation = 0.0;
604 double face_grad_dissipation = 0.0;
605 auto face_handle = OP::getFEEntityHandle();
606 CHKERR getMoab().tag_get_data(dissipationTag, &face_handle, 1,
607 &face_dissipation);
608 CHKERR getMoab().tag_get_data(gradDissipationTag, &face_handle, 1,
609 &face_grad_dissipation);
610
611 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
613 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
614 FTensor::Tensor1<double, 3> t_normalized_normal;
615 t_normalized_normal(J) = t_normal(J);
616 t_normalized_normal.normalize();
618 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
619
620 auto dJ_dkappa = [](auto &t_delta_kappa, auto &t_traction,
621 auto &t_normalized_normal, auto &t_kappa, auto gc) {
622 double kappa = static_cast<double>(t_kappa);
623 double delta_kappa = static_cast<double>(t_delta_kappa);
625 t_traction, t_normalized_normal, OpGetParameters::beta);
627 delta_kappa, teff, kappa, gc);
628 double m_grad =
630 delta_kappa, teff, kappa, gc);
631 return boost::make_tuple(m, m_grad);
632 };
633
634 auto dr_kappa = [](auto &t_delta_kappa, auto &t_traction,
635 auto &t_normalized_normal, auto &t_kappa, auto gc) {
636 double kappa = static_cast<double>(t_kappa);
637 double delta_kappa = static_cast<double>(t_delta_kappa);
638 double kappa_plus_delta = kappa + delta_kappa;
639 double diff_alpha =
640 GriffithCohesiveLaw::getDiffAlpha(kappa_plus_delta, gc);
641 auto [teff, t_gap] = GriffithCohesiveLaw::calculateGap(
642 t_traction, t_normalized_normal, diff_alpha, OpGetParameters::beta);
643 FTENSOR_INDEX(3, i);
644 FTensor::Tensor1<double, 3> t_gap_double;
645 t_gap_double(i) = -t_gap(i);
646 return t_gap_double;
647 };
648
649 auto [J, dJ] = dJ_dkappa(t_delta_kappa, t_traction, t_normalized_normal,
650 t_kappa, *gcPtr);
651 face_dissipation += t_w * J * t_normal.l2();
652 face_grad_dissipation += t_w * dJ * t_normal.l2();
653
654 auto t_dr = dr_kappa(t_delta_kappa, t_traction, t_normalized_normal,
655 t_kappa, *gcPtr);
657 t_l(i) = t_lambda(i, K) * t_normal(K);
658 face_grad_dissipation -= t_w * t_l(i) * t_dr(i);
659
660 next();
661 }
662
663 CHKERR getMoab().tag_set_data(dissipationTag, &face_handle, 1,
664 &face_dissipation);
665 CHKERR getMoab().tag_set_data(gradDissipationTag, &face_handle, 1,
666 &face_grad_dissipation);
667
668
670 };
671
676
677protected:
678};
679
681
684
687
688 FTENSOR_INDEX(3, i);
689 FTENSOR_INDEX(3, J);
690
691 int nb_integration_pts = OP::getGaussPts().size2();
692 auto nb_dofs = data.getIndices().size();
693
694 int nb_base_functions = data.getN().size2() / 3;
695 auto t_row_base_fun = data.getFTensor1N<3>();
696 auto t_w = OP::getFTensor0IntegrationWeight();
697
698 auto t_P = getFTensor2FromMat<3, 3>(*(OP::fluxMatPtr));
699 auto t_kappa = getFTensor0FromVec<0>(*kappaPtr);
700 auto t_delta_kappa = getFTensor0FromVec<0>(*kappaDeltaPtr);
701 auto t_face_normal = getFTensor1NormalsAtGaussPts();
702
703 auto next = [&]() {
704 ++t_P;
705 ++t_face_normal;
706 ++t_kappa;
707 ++t_delta_kappa;
708 ++t_w;
709 };
710
711 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
713 t_normal(J) = t_face_normal(J) * (faceSense / 2.);
714 FTensor::Tensor1<double, 3> t_normalized_normal;
715 t_normalized_normal(J) = t_normal(J);
716 t_normalized_normal.normalize();
718 t_traction(i) = t_P(i, J) * t_normalized_normal(J);
719
720 auto dJ_dtraction = [](auto &t_traction, auto &t_normalized_normal,
721 auto &t_delta_kappa, auto &t_kappa, auto gc) {
722 double kappa = static_cast<double>(t_kappa);
723 double delta_kappa = static_cast<double>(t_delta_kappa);
724 FTENSOR_INDEX(3, i);
725 FTensor::Tensor1<double, 3> t_traction_double;
726 t_traction_double(i) = t_traction(i);
727 auto t_dM =
729 t_traction_double, delta_kappa, kappa, t_normalized_normal, gc,
731 FTensor::Tensor1<double, 3> t_dJ_double;
732 t_dJ_double(i) = t_dM(i);
733 return t_dJ_double;
734 };
735
736 auto assemble = [&](const FTensor::Tensor1<double, 3> &&t_dJ) {
737
738 auto t_nf = getFTensor1FromPtr<3>(&*OP::locF.begin());
739 int bb = 0;
740 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
741 double row_base = t_w * (t_row_base_fun(J) * t_normal(J));
742 t_nf(i) += row_base * t_dJ(i);
743 ++t_nf;
744 ++t_row_base_fun;
745 }
746 for (; bb != nb_base_functions; ++bb)
747 ++t_row_base_fun;
748 };
749
750 assemble(dJ_dtraction(t_traction, t_normalized_normal, t_delta_kappa,
751 t_kappa, *gcPtr));
752
753 // cerr << "AAAA " << OP::locF << endl;
754 next();
755 }
756
758 };
759
762 return VecSetValues<AssemblyTypeSelector<A>>(vec_dJdu, data, OP::locF,
763 ADD_VALUES);
765 }
766
767protected:
768};
769
771
773
775
777 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
778 Tag tag, TagGetType tag_get_type,
779 boost::shared_ptr<VectorDouble> tag_data_ptr,
780 boost::shared_ptr<Range> ents_ptr = nullptr)
781 : OpBrokenBaseCohesive(broken_base_side_data, ents_ptr), tagHandle(tag),
782 tagGetType(tag_get_type), tagDataPtr(tag_data_ptr) {}
783
786
787 auto get_sense_index = [this]() { return (faceSense == 1) ? 0 : 1; };
788 auto &v = *tagDataPtr;
789
790 switch (tagGetType) {
791 case TagSET:
792 break;
793 case TagGET:
794 v.resize(1);
795 v.clear();
796 break;
797 }
798
799 auto get_data = [&](auto &v) {
801
802 auto &moab = getMoab();
803 auto fe_ent = getFEEntityHandle();
804
805 int size;
806 double *data;
807 rval = moab.tag_get_by_ptr(tagHandle, &fe_ent, 1, (const void **)&data,
808 &size);
809 if (
810
811 rval == MB_SUCCESS && size > 0 && size != v.size()
812
813 ) {
814 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
815 "Inconsistent size of tag data");
816 } else {
817 if (rval != MB_SUCCESS || tagGetType == TagSET) {
818 int tag_size[1];
819 tag_size[0] = v.size();
820 void const *tag_data[] = {&v[0]};
821 CHKERR moab.tag_set_by_ptr(tagHandle, &fe_ent, 1, tag_data, tag_size);
822 } else {
823 CHKERR moab.tag_get_by_ptr(tagHandle, &fe_ent, 1,
824 (const void **)&data, &size);
825 std::copy(data, data + size, v.begin());
826 }
827 }
828
830 };
831
832 CHKERR get_data(v);
833
835 }
836
841
842private:
844 boost::shared_ptr<VectorDouble> tagDataPtr;
846};
847
849 EshelbianCore &ep,
850 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
851 SmartPetscObj<Vec> lambda_vec = SmartPetscObj<Vec>()) {
852
853 using EleOnSide =
855 using SideEleOp = EleOnSide::UserDataOperator;
856
857 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
858 pip, {HDIV, H1, L2}, ep.materialH1Positions, ep.frontAdjEdges);
859
860 auto domain_side_flux = [&](auto &pip) {
861 // flux
862 auto broken_data_ptr =
863 boost::make_shared<std::vector<BrokenBaseSideData>>();
865 broken_data_ptr));
866 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
868 ep.piolaStress, flux_mat_ptr));
869 pip.push_back(new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
870
871 return broken_data_ptr;
872 };
873
874 auto get_lambda = [&](auto &pip) {
875 boost::shared_ptr<std::array<MatrixDouble, 2>> array_lambda_ptr;
876 if (lambda_vec) {
877 array_lambda_ptr = boost::make_shared<std::array<MatrixDouble, 2>>();
878 auto lambda_mat_ptr = boost::make_shared<MatrixDouble>();
880 ep.piolaStress, lambda_mat_ptr, boost::make_shared<double>(1.0),
881 lambda_vec));
883 auto op = new OP(NOSPACE, OP::OPSPACE);
884 op->doWorkRhsHook =
885 [lambda_mat_ptr, array_lambda_ptr](
886 DataOperator *base_op_ptr, int side, EntityType type,
889 auto op_ptr = static_cast<OP *>(base_op_ptr);
890 auto get_sense_index = [op_ptr]() {
891 return (op_ptr->getSkeletonSense() == 1) ? 0 : 1;
892 };
893 array_lambda_ptr->at(get_sense_index()) = *lambda_mat_ptr;
895 };
896 pip.push_back(op);
897 }
898 return array_lambda_ptr;
899 };
900
901 return std::make_pair(domain_side_flux(pip), get_lambda(pip));
902};
903
905 EshelbianCore &ep,
906 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
907 boost::shared_ptr<Range> interface_range_ptr,
908 SmartPetscObj<Vec> lambda_vec = SmartPetscObj<Vec>()) {
909
910 auto &m_field = ep.mField;
911
912 using BoundaryEle =
914 using EleOnSide =
916 using SideEleOp = EleOnSide::UserDataOperator;
917 using BdyEleOp = BoundaryEle::UserDataOperator;
918
919 auto face_side = [&]() {
920 // First: Iterate over skeleton FEs adjacent to Domain FEs
921 // Note: BoundaryEle, i.e. uses skeleton interation rule
922 auto op_loop_skeleton_side =
924 interface_range_ptr, Sev::noisy);
925 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
926 return -1;
927 };
928 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
929 set_integration_at_front_face;
930
931 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
932 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
933 ep.frontAdjEdges);
934
935 return op_loop_skeleton_side;
936 };
937
938 auto op_loop_skeleton_side = face_side();
939
940 // Second: Iterate over domain FEs adjacent to skelton, particularly one
941 // domain element.
942 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
943 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
944 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
945 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
946 boost::make_shared<CGGUserPolynomialBase>();
947 auto [broken_data_flux_ptr, lambda_ptr] = pushCohesiveOpsDomainImpl(
948 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
949 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
951 op_reset_broken_data->doWorkRhsHook =
952 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
953 EntityType type,
955 broken_data_flux_ptr->resize(0);
956 return 0;
957 };
958 op_loop_skeleton_side->getOpPtrVector().push_back(op_reset_broken_data);
959 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
960
961 auto kappa_ptr = boost::make_shared<VectorDouble>();
962 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
963 auto gc_ptr = boost::make_shared<double>();
964
965 op_loop_skeleton_side->getOpPtrVector().push_back(
966 new OpGetParameters(gc_ptr));
967 op_loop_skeleton_side->getOpPtrVector().push_back(
968 new OpGetTag(broken_data_flux_ptr, get_kappa_tag(m_field.get_moab()),
969 TagGetType::TagGET, kappa_ptr));
970 op_loop_skeleton_side->getOpPtrVector().push_back(new OpGetTag(
971 broken_data_flux_ptr, get_delta_kappa_tag(m_field.get_moab()),
972 TagGetType::TagGET, kappa_delta_ptr));
973
974 return std::make_tuple(op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr,
975 kappa_ptr, kappa_delta_ptr);
976};
977
979 EshelbianCore &ep,
980 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
981 boost::shared_ptr<Range> interface_range_ptr,
982 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
984
985 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
986 kappa_delta_ptr] =
987 pushCohesiveOpsImpl(ep, set_integration_at_front_face,
988 interface_range_ptr);
989
990 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
991 op_loop_skeleton_side->getOpPtrVector().push_back(
993 u_gamma_ptr));
994 op_loop_skeleton_side->getOpPtrVector().push_back(new OpCohesiveRhs(
995 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
996
997 pip.push_back(op_loop_skeleton_side);
998
1000};
1001
1003 EshelbianCore &ep,
1004 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1005 boost::shared_ptr<Range> interface_range_ptr,
1006 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1008
1009 auto [op_loop_skeleton_side, broken_data_flux_ptr, gc_ptr, kappa_ptr,
1010 kappa_delta_ptr] =
1011 pushCohesiveOpsImpl(ep, set_integration_at_front_face,
1012 interface_range_ptr);
1013 auto u_gamma_ptr = boost::make_shared<MatrixDouble>();
1014 op_loop_skeleton_side->getOpPtrVector().push_back(
1016 u_gamma_ptr));
1017 op_loop_skeleton_side->getOpPtrVector().push_back(new OpCohesiveLhs_dPdP(
1018 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr));
1019
1020 pip.push_back(op_loop_skeleton_side);
1021
1023};
1024
1026 EshelbianCore &ep,
1027 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip,
1028 SmartPetscObj<Vec> lambda_vec) {
1029 auto &m_field = ep.mField;
1030
1031 using EleOnSide =
1033 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1034 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1035 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1036 boost::make_shared<CGGUserPolynomialBase>();
1037 auto [broken_data_flux_ptr, lambda_ptr] = pushCohesiveOpsDomainImpl(
1038 ep, op_loop_domain_side->getOpPtrVector(), lambda_vec);
1039
1040 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
1042 op_reset_broken_data->doWorkRhsHook =
1043 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
1044 EntityType type,
1046 broken_data_flux_ptr->resize(0);
1047 return 0;
1048 };
1049 pip.push_back(op_reset_broken_data);
1050 pip.push_back(op_loop_domain_side);
1051
1052 auto tag_dissipation = get_tag(m_field.get_moab(), "COHESIVE_DISSIPATION", 1);
1053 auto tag_grad_dissipation =
1054 get_tag(m_field.get_moab(), "COHESIVE_DISSIPATION_GRAD", 1);
1055
1056 auto kappa_ptr = boost::make_shared<VectorDouble>();
1057 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
1058 auto gc_ptr = boost::make_shared<double>();
1059
1060 pip.push_back(new OpGetParameters(gc_ptr, Sev::noisy));
1061 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1062 get_kappa_tag(m_field.get_moab()),
1063 TagGetType::TagGET, kappa_ptr));
1064 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1065 get_delta_kappa_tag(m_field.get_moab()),
1066 TagGetType::TagGET, kappa_delta_ptr));
1067
1068 pip.push_back(new OpCohesive_dJ_dkappa(
1069 broken_data_flux_ptr, gc_ptr, kappa_ptr, kappa_delta_ptr, lambda_ptr,
1070 tag_dissipation, tag_grad_dissipation));
1071
1072 return std::make_pair(tag_dissipation, tag_grad_dissipation);
1073}
1074
1076 EshelbianCore &ep,
1077 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pip) {
1078 auto &m_field = ep.mField;
1079
1080 using EleOnSide =
1082 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
1083 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
1084 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
1085 boost::make_shared<CGGUserPolynomialBase>();
1086 auto [broken_data_flux_ptr, lambda_ptr] =
1087 pushCohesiveOpsDomainImpl(ep, op_loop_domain_side->getOpPtrVector());
1088
1089 auto op_reset_broken_data = new ForcesAndSourcesCore::UserDataOperator(
1091 op_reset_broken_data->doWorkRhsHook =
1092 [broken_data_flux_ptr](DataOperator *base_op_ptr, int side,
1093 EntityType type,
1095 broken_data_flux_ptr->resize(0);
1096 return 0;
1097 };
1098 pip.push_back(op_reset_broken_data);
1099 pip.push_back(op_loop_domain_side);
1100
1101 auto kappa_ptr = boost::make_shared<VectorDouble>();
1102 auto kappa_delta_ptr = boost::make_shared<VectorDouble>();
1103 auto gc_ptr = boost::make_shared<double>();
1104
1105 pip.push_back(new OpGetParameters(gc_ptr, Sev::noisy));
1106 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1107 get_kappa_tag(m_field.get_moab()),
1108 TagGetType::TagGET, kappa_ptr));
1109 pip.push_back(new OpGetTag(broken_data_flux_ptr,
1110 get_delta_kappa_tag(m_field.get_moab()),
1111 TagGetType::TagGET, kappa_delta_ptr));
1112 auto dJ_dx_vec = createDMVector(ep.dmElastic);
1113 pip.push_back(new OpCohesive_dJ_dP(broken_data_flux_ptr, gc_ptr, kappa_ptr,
1114 kappa_delta_ptr, lambda_ptr, Tag(), Tag(),
1115 dJ_dx_vec));
1116
1117 return dJ_dx_vec;
1118}
1119
1121 EshelbianCore &ep,
1122 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1123 SmartPetscObj<Vec> lambda_vec,
1124 CommInterface::EntitiesPetscVector &dissipation_vec,
1125 CommInterface::EntitiesPetscVector &grad_dissipation_vec) {
1127
1128 using BoundaryEle =
1130 using BdyEleOp = BoundaryEle::UserDataOperator;
1131
1132 auto get_face_ele = [&]() {
1133 auto fe_ptr = boost::make_shared<BoundaryEle>(ep.mField);
1134 fe_ptr->getRuleHook = [](int, int, int) { return -1; };
1135 fe_ptr->setRuleHook = set_integration_at_front_face;
1136 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
1137 fe_ptr->getOpPtrVector(), {L2}, ep.materialH1Positions,
1138 ep.frontAdjEdges);
1139
1140 auto interface_face = [&](FEMethod *fe_method_ptr) {
1141 auto ent = fe_method_ptr->getFEEntityHandle();
1142 if (
1143
1144 ep.interfaceFaces->find(ent) != ep.interfaceFaces->end()
1145
1146 ) {
1147 return true;
1148 };
1149 return false;
1150 };
1151
1152 fe_ptr->exeTestHook = interface_face;
1153
1154 return fe_ptr;
1155 };
1156
1157 auto face_fe = get_face_ele();
1158 auto [tag_dissipation, tag_grad_dissipation] =
1159 pushCohesive_dJ_dkappa_Impl(ep, face_fe->getOpPtrVector(), lambda_vec);
1160
1161 constexpr double zero = 0.0;
1162 CHKERR ep.mField.get_moab().tag_clear_data(tag_dissipation,
1163 *(ep.interfaceFaces), &zero);
1164 CHKERR ep.mField.get_moab().tag_clear_data(tag_grad_dissipation,
1165 *(ep.interfaceFaces), &zero);
1168 ep.mField.get_moab(), dissipation_vec, tag_dissipation);
1170 ep.mField.get_moab(), grad_dissipation_vec, tag_grad_dissipation);
1171
1173}
1174
1176 EshelbianCore &ep,
1177 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1178 SmartPetscObj<KSP> ksp, SmartPetscObj<Vec> lambda_vec) {
1180
1181 using BoundaryEle =
1183 using BdyEleOp = BoundaryEle::UserDataOperator;
1184
1185 auto get_face_ele = [&]() {
1186 auto fe_ptr = boost::make_shared<BoundaryEle>(ep.mField);
1187 fe_ptr->getRuleHook = [](int, int, int) { return -1; };
1188 fe_ptr->setRuleHook = set_integration_at_front_face;
1189 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
1190 fe_ptr->getOpPtrVector(), {L2}, ep.materialH1Positions,
1191 ep.frontAdjEdges);
1192
1193 auto interface_face = [&](FEMethod *fe_method_ptr) {
1194 auto ent = fe_method_ptr->getFEEntityHandle();
1195 if (
1196
1197 ep.interfaceFaces->find(ent) != ep.interfaceFaces->end()
1198
1199 ) {
1200 return true;
1201 };
1202 return false;
1203 };
1204
1205 fe_ptr->exeTestHook = interface_face;
1206
1207 return fe_ptr;
1208 };
1209
1210 auto face_fe = get_face_ele();
1211 auto dJ_dx = pushCohesive_dJ_dx_Impl(ep, face_fe->getOpPtrVector());
1213 ep.dmElastic, ep.skeletonElement, face_fe, 0, ep.mField.get_comm_size());
1214 CHKERR VecAssemblyBegin(dJ_dx);
1215 CHKERR VecAssemblyEnd(dJ_dx);
1216 CHKERR VecGhostUpdateBegin(dJ_dx, ADD_VALUES, SCATTER_REVERSE);
1217 CHKERR VecGhostUpdateEnd(dJ_dx, ADD_VALUES, SCATTER_REVERSE);
1218 CHKERR VecGhostUpdateBegin(dJ_dx, INSERT_VALUES, SCATTER_FORWARD);
1219 CHKERR VecGhostUpdateEnd(dJ_dx, INSERT_VALUES, SCATTER_FORWARD);
1220 double dJ_dx_norm2;
1221 CHKERR VecNorm(dJ_dx, NORM_2, &dJ_dx_norm2);
1222 MOFEM_LOG("EP", Sev::inform)
1223 << "evaluateCohesiveLambdaImpl: Norm of dJ/dx vector: " << dJ_dx_norm2;
1224 constexpr double tol = 1e-16;
1225 if (dJ_dx_norm2 < tol) {
1226 CHKERR VecZeroEntries(lambda_vec);
1227 } else {
1228 CHKERR KSPSolveTranspose(ksp, dJ_dx, lambda_vec);
1229 }
1230 CHKERR VecGhostUpdateBegin(lambda_vec, INSERT_VALUES, SCATTER_FORWARD);
1231 CHKERR VecGhostUpdateEnd(lambda_vec, INSERT_VALUES, SCATTER_FORWARD);
1232 double lambda_norm2;
1233 CHKERR VecNorm(lambda_vec, NORM_2, &lambda_norm2);
1234 MOFEM_LOG("EP", Sev::inform)
1235 << "evaluateCohesiveLambdaImpl: Norm of lambda vector: " << lambda_norm2;
1236
1238}
1239
1244
1245 CHKERR TSSetFromOptions(ts);
1246 CHKERR TSSetStepNumber(ts, 0);
1247 CHKERR TSSetTime(ts, 0);
1248 CHKERR TSSetSolution(ts, x);
1249 double dt;
1250 CHKERR TSGetTimeStep(ts, &dt);
1251 MOFEM_LOG("EP", Sev::inform)
1252 << "evaluatePrimalProblemCohesiveImpl: Time step dt: " << dt;
1253 CHKERR TSSolve(ts, PETSC_NULLPTR);
1254 CHKERR TSSetTimeStep(ts, dt);
1255
1256 CHKERR DMoFEMMeshToLocalVector(ep.dmElastic, x, INSERT_VALUES,
1257 SCATTER_FORWARD);
1258 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
1259 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
1260
1261 double x_norm2;
1262 CHKERR VecNorm(x, NORM_2, &x_norm2);
1263 MOFEM_LOG("EP", Sev::inform)
1264 << "evaluatePrimalProblemCohesiveImpl: Norm of displacement vector: "
1265 << x_norm2;
1266
1268}
1269
1272 EshelbianCore *ep,
1273 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1274 SmartPetscObj<TS> time_solver)
1275 : ep_ptr(ep), setIntegrationAtFrontFace(set_integration_at_front_face),
1276 timeSolver(time_solver),
1277
1278 kspSolVec(createDMVector(ep->dmElastic)),
1279 lambdaVec(createDMVector(ep->dmElastic)),
1280 kappaVec(CommInterface::createEntitiesPetscVector(
1281 ep->mField.get_comm(), ep->mField.get_moab(),
1282 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1283 Sev::noisy)),
1285 ep->mField.get_comm(), ep->mField.get_moab(),
1286 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1287 Sev::noisy)),
1289 ep->mField.get_comm(), ep->mField.get_moab(),
1290 [&ep](Range r) { return intersect(*(ep->interfaceFaces), r); }, 1,
1291 Sev::noisy)) {}
1292
1294 return vectorDuplicate(kappaVec.second);
1295 }
1296
1300
1304
1308
1309private:
1313
1320 PetscReal *f,
1321 Vec g, void *ctx);
1322};
1323
1324boost::shared_ptr<CohesiveTAOCtx> createCohesiveTAOCtx(
1325 EshelbianCore *ep_ptr,
1326 ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face,
1327 SmartPetscObj<TS> time_solver) {
1328 return boost::make_shared<CohesiveTAOCtxImpl>(
1329 ep_ptr, set_integration_at_front_face, time_solver);
1330}
1331
1333 PetscReal *f, Vec g,
1334 void *ctx) {
1335
1337 auto cohesive_ctx = static_cast<CohesiveTAOCtxImpl *>(ctx);
1338 auto &ep = *(cohesive_ctx->ep_ptr);
1339
1340#ifndef NDEBUG
1341 CHKERR VecView(delta_kappa, PETSC_VIEWER_STDOUT_WORLD);
1342#endif
1343 // Set delta_kappa values to the tag
1344 CHKERR VecCopy(delta_kappa, cohesive_ctx->kappaVec.second);
1345 CHKERR VecGhostUpdateBegin(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1346 SCATTER_FORWARD);
1347 CHKERR VecGhostUpdateEnd(cohesive_ctx->kappaVec.second, INSERT_VALUES,
1348 SCATTER_FORWARD);
1350 ep.mField.get_moab(), cohesive_ctx->kappaVec,
1352
1353 // solve primal problem
1354 CHKERR evaluatePrimalProblemCohesiveImpl(ep, cohesive_ctx->timeSolver,
1355 cohesive_ctx->kspSolVec);
1356 // solve adjoint problem to get lambda
1357 auto ksp = snesGetKSP(tsGetSNES(cohesive_ctx->timeSolver));
1358 CHKERR evaluateCohesiveLambdaImpl(ep, cohesive_ctx->setIntegrationAtFrontFace,
1359 ksp, cohesive_ctx->lambdaVec);
1360 // evaluate dissipation and its gradient
1362 ep, cohesive_ctx->setIntegrationAtFrontFace, cohesive_ctx->lambdaVec,
1363 cohesive_ctx->dissipationVec, cohesive_ctx->gradDissipationVec);
1364
1365 CHKERR VecSum(cohesive_ctx->dissipationVec.second, f);
1366 CHKERR VecCopy(cohesive_ctx->gradDissipationVec.second, g);
1367
1368 MOFEM_LOG("EP", Sev::inform)
1369 << "Cohesive objective function (negative total dissipation): " << *f;
1370
1372}
1373
1381
1382}; // namespace EshelbianPlasticity
Eshelbian plasticity interface.
#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)
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)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
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
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 Tag get_variable_tag(moab::Interface &moab, std::string tag_name)
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)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data)
auto tsGetSNES(TS ts)
MoFEM::OpBrokenTopoBase OP
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
tools::promote_args< ArgumentType, int >::type lambert_w(const ArgumentType &z)
Definition lambert_w.hpp:40
constexpr double g
FTensor::Index< 'm', 3 > m
boost::shared_ptr< Range > frontAdjEdges
const std::string skeletonElement
MoFEM::Interface & mField
const std::string materialH1Positions
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 auto calculateDissipationSurplus(const T &delta_kappa, const T t_eff, const T &kappa, double gc)
static T getAlpha(const T &kappa, double gc, double min_stiffness)
static auto invTau(const T &tau, double Gf)
static auto getDiffTau(const T &tau, const T &kappa, double gc)
static auto calculateGap(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double alpha, double beta)
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)
static auto calculateEffectiveTraction(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double beta)
static auto calculateY(const T t_eff, const T &kappa, double gc)
static auto calculateDissipationSurplusDiffKappa(const T &delta_kappa, const T &t_eff, const T &kappa, double gc)
static T getTau(const T &k, double gc)
static T getDiffAlpha(const T &kappa, double gc)
static auto calculateDissipation(const T &delta_kappa, const T t_eff, const T &kappa, double gc)
static auto calculateDiffGapDTraction(const FTensor::Tensor1< T, 3 > &t_traction, FTensor::Tensor1< double, 3 > &t_n_normalize, double alpha, double beta)
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)
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....
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > 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 double precision 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
double tol