v0.15.0
Loading...
Searching...
No Matches
EshelbianInterface.hpp
Go to the documentation of this file.
1/**
2 * @file EshelbianInterface.hpp
3 * @author your name (you@domain.com)
4 * @brief
5 * @version 0.1
6 * @date 2025-11-20
7 *
8 * @copyright Copyright (c) 2025
9 *
10 */
11
13#include "MoFEM.hpp"
14
15#ifndef ESHELBIANINTERFACE_HPP
16 #define ESHELBIANINTERFACE_HPP
17
18namespace EshelbianPlasticity {
19
21 OpGetTagData(boost::shared_ptr<DataAtIntegrationPts> data_ptr, Tag th,
22 boost::shared_ptr<Range> ents_ptr)
23 : UserDataOperator(NOSPACE, OPSPACE), dataAtPts(data_ptr), tagHandle(th),
24 entsPtr(ents_ptr) {}
25 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
27 auto fe_handle = getFEEntityHandle();
28 if (entsPtr->contains(fe_handle) == false) {
30 }
31 auto nb_gauss_pts = getGaussPts().size2();
32 auto data_ptr = dataAtPts->getTagData(tagHandle);
33 auto &moab = m_field.getMoab();
34 const void *tag_data[] = {nullptr};
35 const void tag_sizes[] = {0};
36 CHKERR moab.tag_get_by_ptr(tagHandle, &fe_handle, 1, tag_data, tag_sizes);
37 if (tag_sizes[0] % nb_gauss_pts != 0) {
38 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
39 "Tag length not compatible with number of gauss pts");
40 }
41 data_ptr->resize(tag_sizes[0] / nb_gauss_pts, nb_gauss_pts, false);
42 std::copy(static_cast<const double *>(tag_data[0]),
43 static_cast<const double *>(tag_data[0]) + tag_sizes[0],
44 data_ptr->data().begin());
46 }
47
48private:
49 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
51 boost::shared_ptr<Range> entsPtr;
52};
53
55 OpSetTagData(boost::shared_ptr<DataAtIntegrationPts> data_ptr, Tag th,
56 boost::shared_ptr<Range> ents_ptr)
57 : UserDataOperator(NOSPACE, OPSPACE), dataAtPts(data_ptr), tagHandle(th),
58 entsPtr(ents_ptr) {}
59 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
61 auto fe_handle = getFEEntityHandle();
62 if (entsPtr->contains(fe_handle) == false) {
64 }
65 auto data_ptr = dataAtPts->getTagData(tagHandle);
66 auto &moab = m_field.getMoab();
67 int tag_length = data_ptr->data().size();
68 CHKERR moab.tag_set_by_ptr(tagHandle, &fe_handle, 1,
69 data_ptr->data().data(), tag_length);
71 }
72
73private:
74 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
76 boost::shared_ptr<Range> entsPtr;
77};
78
80 virtual MatrixDouble &
81 getGapAtPts(boost::shared_ptr<DataAtIntegrationPts> data_ptr, ,
82 MatrixDouble &normalsAtGaussPts, int sense) = 0;
83 virtual MatrixDouble &
84 getInvStiffnessAtPts(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
85 MatrixDouble &normalsAtGaussPts, int sense) = 0;
86};
87
89
90 MatrixDouble &getGapAtPts(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
91 MatrixDouble &normalsAtGaussPts, int sense) {
92
93 auto impl = [&]() {
95 FTENSOR_INDEX(3, i);
96 FTENSOR_INDEX(3, J);
97
98 auto nb_gauss_pts = data_ptr->approxPAtPts.size2();
99 auto t_approx_P = getFTensor2FromMat<3, 3>(data_ptr->approxPAtPts);
100 double *ptr = normalsAtGaussPts().data().data();
101 FTensor::Tensor1<FTensor::PackPtr<double *, 3>, 3> t_normal(ptr, &ptr[1],
102 &ptr[2]);
103 gapAtPts.resize(3, nb_gauss_pts, false);
104 auto t_delta_gap = getFTensor2FromMat<3, 3>(gapAtPts);
105 for (size_t gp = 0; gp < nb_gauss_pts; ++gp) {
106 auto nrm2 = t_normal.l2();
107 t_traction(i) = t_approx_P(i, J) * (sense * t_normal(J) / nrm2);
108 t_gap(i) = t_traction(i) * (h / E);
109 ++t_approx_P;
110 ++t_normal;
111 ++t_gap;
112 }
113
115 };
116
117 CHK_THROW_MESSAGE(impl(), "Error in ExponentialGriffithReleaseData");
118
119 return gapAtPts;
120 }
121
122 MatrixDouble &
123 getInvStiffnessAtPts(boost::shared_ptr<DataAtIntegrationPts> data_ptr,
124 MatrixDouble &normalsAtGaussPts, int sense) {
126 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
127 auto nb_gauss_pts = data_ptr->approxPAtPts.size2();
128 double *ptr = normalsAtGaussPts().data().data();
129 FTensor::Tensor1<FTensor::PackPtr<double *, 3>, 3> t_normal(ptr, &ptr[1],
130 &ptr[2]);
131 invStiffnessAtPts.resize(3, 3 * nb_gauss_pts, false);
132 auto t_inv_D = getFTensor2FromMat<3, 3>(invStiffnessAtPts);
133 for (size_t gp = 0; gp < nb_gauss_pts; ++gp) {
134 t_inv_D(i, j) = t_kd(i, j) * (h / E);
135 ++t_inv_D;
136 }
138 }
139
140protected:
141 double Gc; //< Griffith energy release rate
142 double E; //< Young modulus
143 double h; //< Characteristic length
144 double ft; //< Tensile strength
145
146 MatrixDouble invStiffnessAtPts;
147 MatrixDouble gapAtPts;
148};
149
150struct OpInterfaceRhs : public FormsIntegrators<FaceUserDataOperator>::Assembly<
151 PETSC>::OpBrokenBase {
152
153 using OP = typename FormsIntegrators<FaceUserDataOperator>::Assembly<
154 PETSC>::OpBrokenBase;
155
157 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
158 std::string row_field, boost::shared_ptr<DataAtIntegrationPts> data_ptr,
159 boost::shared_ptr<CrackInterface> release_data_ptr,
160 boost::shared_ptr<Range> ents_ptr = nullptr)
161 : OP(broken_base_side_data, ents_ptr), dataAtPts(data_ptr),
162 releaseDataPtr(release_data_ptr) {}
163
164 MoFEMErrorCode doWork(int row_side, EntityType row_type,
165 EntitiesFieldData::EntData &row_data) {
166
168
169 if (OP::entsPtr) {
170 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
172 }
173
174 #ifndef NDEBUG
175 if (!brokenBaseSideData) {
176 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
177 }
178 #endif // NDEBUG
179
180 auto do_work_rhs = [this](int row_side, EntityType row_type,
181 EntitiesFieldData::EntData &row_data, int sense) {
183 // get number of dofs on row
184 OP::nbRows = row_data.getIndices().size();
185 if (!OP::nbRows)
187 // get number of integration points
188 OP::nbIntegrationPts = OP::getGaussPts().size2();
189 // get row base functions
190 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
191 // resize and clear the right hand side vector
192 OP::locF.resize(OP::nbRows, false);
193 OP::locF.clear();
194 // integrate local vector
195 this->rowSense = bd.getSense();
196 CHKERR this->iNtegrate(row_data);
197 // assemble local vector
198 CHKERR this->aSsemble(row_data);
200 };
201
202 switch (OP::opType) {
203 case OP::OPROW:
204 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
205 "LHS not implemented for OpEvalExponentialGriffithReleaseRhs");
206 break;
207 case OP::OPSPACE:
208 for (auto &bd : *brokenBaseSideData) {
209 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData(),
210 bd.getSense());
211 }
212 break;
213 default:
215 (std::string("wrong op type ") +
216 OpBaseDerivativesBase::OpTypeNames[OP::opType])
217 .c_str());
218 }
219
221 };
222
223protected:
224 MoFEMErrorCode iNtegrate(EntData &data) {
226
229
230 auto nb_gauss_pts = getGaussPts().size2();
231 int nb_dofs = data.getIndices().size();
232 OP::locF.resize(nb_dofs, false);
233 OP::locF.clear();
234
235 auto &gap_map = releaseDataPtr->getGapAtPts(
236 dataAtPts, getNormalsAtGaussPts(), rowSense);
237 t_delta_gap = getFTensor1FromMat<3>(gap_map);
238
239 auto area = OP::getMeasure();
240 auto t_w = OP::getFTensor0IntegrationWeight();
241 auto t_normal = getFTensor1NormalsAtGaussPts();
242 auto t_row_base = data.getFTensor1N<3>();
243 auto sense = bd.getSense();
244
245 for (auto gp = 0; gp < nb_gauss_pts; ++gp) {
246 double alpha = t_w / 2.;
247 int bb = 0;
248 auto t_rhs = getFTensor1FromPtr<3>(OP::locF.data().data());
249 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
250 t_rhs(i) +=
251 alpha * (t_row_base(J) * (rowSense * t_normal(J))) * t_delta_gap(i);
252 ++t_rhs;
253 ++t_row_base;
254 }
255 ++t_w;
256 ++t_normal;
257 ++t_delta_gap;
258 }
259
261 }
262
263 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
264 boost::shared_ptr<CrackInterface> releaseDataPtr;
266};
267
268struct OpInterfaceLhs : public FormsIntegrators<FaceUserDataOperator>::Assembly<
269 PETSC>::OpBrokenBase {
270
271 using OP = typename FormsIntegrators<FaceUserDataOperator>::Assembly<
272 PETSC>::OpBrokenBase;
273
275 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
276 std::string row_field, std::string col_field,
277 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
278 boost::shared_ptr<CrackInteface> release_data_ptr,
279 boost::shared_ptr<Range> ents_ptr = nullptr)
280 : OP(broken_base_side_data, ents_ptr), dataAtPts(data_ptr),
281 releaseDataPtr(release_data_ptr) {}
282
283 MoFEMErrorCode doWork(int row_side, EntityType row_type,
284 EntitiesFieldData::EntData &row_data) {
286
287 if (OP::entsPtr) {
288 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
290 }
291
292 #ifndef NDEBUG
293 if (!brokenBaseSideData) {
294 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
295 }
296 #endif // NDEBUG
297
298 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
299 EntityType col_type,
300 EntitiesFieldData::EntData &row_data,
301 EntitiesFieldData::EntData &col_data,
302 int row_sense, int col_sense) {
304
305 auto check_if_assemble_transpose = [&] {
306 if (this->sYmm) {
307 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
308 return true;
309 else
310 return false;
311 } else if (OP::assembleTranspose) {
312 return true;
313 }
314 return false;
315 };
316
317 OP::rowSide = row_side;
318 OP::rowType = row_type;
319 OP::colSide = col_side;
320 OP::colType = col_type;
321 OP::nbCols = col_data.getIndices().size();
322 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
323 OP::locMat.clear();
324 rowSense = row_sense;
325 colSense = col_sense;
326 CHKERR this->iNtegrate(row_data, col_data);
327 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
329 };
330
331 switch (OP::opType) {
332 case OP::OPSPACE:
333
334 for (auto &bd : *brokenBaseSideData) {
335
336 #ifndef NDEBUG
337 if (bd.getData().getSpace() != HDIV &&
338 bd.getData().getSpace() != HCURL) {
339 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "%s",
340 (std::string("Expect Hdiv or Hcurl space but received ") +
341 FieldSpaceNames[bd.getData().getSpace()])
342 .c_str());
343 }
344 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
345 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
346 "base functions not set");
347 }
348 #endif
349
350 // Iterate over diagonal. Both sides of interface are coupled by
351 // Lagrange multiplier.
352 CHKERR do_work_lhs(
353
354 // side
355 bd.getSide(), bd.getSide(),
356
357 // type
358 bd.getType(), bd.getType(),
359
360 // row_data
361 bd.getData(), bd.getData(),
362
363 // row sense
364 bd.getSense(),
365
366 // col sense
367 bd.getSense()
368
369 );
370 }
371
372 break;
373 case OP::OPROW:
374 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
375 "Op LHS is done by OP space");
376 break;
377 default:
379 (std::string("wrong op type ") +
380 OpBaseDerivativesBase::OpTypeNames[OP::opType])
381 .c_str());
382 }
383
385 };
386
387protected:
388 MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data) {
390
394
395 auto nb_gauss_pts = getGaussPts().size2();
396 int nb_row_dofs = row_data.getIndices().size();
397 int nb_col_dofs = col_data.getIndices().size();
398 OP::locMat.resize(nb_row_dofs, nb_col_dofs, false);
399 OP::locMat.clear();
400
401 auto &stiffens_map = releaseDataPtr->getInvStiffnessAtPts(
402 dataAtPts, normalsAtGaussPts, sense);
403 t_inv_D = getFTensor2FromMat<3, 3>(stiffens_map);
404
405 auto t_w = OP::getFTensor0IntegrationWeight();
406 auto t_row_base = row_data.getFTensor1N<3>();
407 for (auto gp = 0; gp < nb_gauss_pts; ++gp) {
408 double alpha = t_w / 2.;
409 auto nrm2 = t_normal.l2();
410 int rr = 0;
411 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
412 auto t_row = t_row_base(J) * (rowSense * t_normal(J));
413 auto t_col_base = col_data.getFTensor1N<3>(gg, 0);
414 auto t_mat = getFTensor2FromMat<3, 3, 3>(OP::locMat(rr * 3, 0));
415 for (int cc = 0; cc != nb_dofs / SPACE_DIM; ++cc) {
416 auto t_col = t_col_base(J) * ((colSense * t_normal(J)) / nrm2);
417 t_mat(i, j) += (alpha * (t_row * t_col)) * t_inv_D(i, j);
418 ++t_col_base;
419 ++t_mat;
420 }
421 ++t_row_base;
422 }
423 ++t_w;
424 ++t_inv_D;
425 }
426
428 }
429
430 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
431 boost::shared_ptr<CrackInterface> releaseDataPtr;
434};
435
436} // namespace EshelbianPlasticity
437
438#endif // ESHELBIANINTERFACE_HPP
#define FTENSOR_INDEX(DIM, I)
constexpr int SPACE_DIM
[Define dimension]
Kronecker Delta class.
#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()
@ NOSPACE
Definition definitions.h:83
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
static const char *const FieldSpaceNames[]
Definition definitions.h:92
#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.
constexpr auto t_kd
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'j', 3 > j
virtual MatrixDouble & getInvStiffnessAtPts(boost::shared_ptr< DataAtIntegrationPts > data_ptr, MatrixDouble &normalsAtGaussPts, int sense)=0
virtual MatrixDouble & getGapAtPts(boost::shared_ptr< DataAtIntegrationPts > data_ptr,, MatrixDouble &normalsAtGaussPts, int sense)=0
MatrixDouble & getGapAtPts(boost::shared_ptr< DataAtIntegrationPts > data_ptr, MatrixDouble &normalsAtGaussPts, int sense)
MatrixDouble & getInvStiffnessAtPts(boost::shared_ptr< DataAtIntegrationPts > data_ptr, MatrixDouble &normalsAtGaussPts, int sense)
OpGetTagData(boost::shared_ptr< DataAtIntegrationPts > data_ptr, Tag th, boost::shared_ptr< Range > ents_ptr)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > entsPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
boost::shared_ptr< CrackInterface > releaseDataPtr
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
OpInterfaceLhs(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, std::string row_field, std::string col_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< CrackInteface > release_data_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
MoFEMErrorCode iNtegrate(EntData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
OpInterfaceRhs(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, std::string row_field, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< CrackInterface > release_data_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
boost::shared_ptr< CrackInterface > releaseDataPtr
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > entsPtr
OpSetTagData(boost::shared_ptr< DataAtIntegrationPts > data_ptr, Tag th, boost::shared_ptr< Range > ents_ptr)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Data on single entity (This is passed as argument to DataOperator::doWork)
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.