v0.16.0
Loading...
Searching...
No Matches
FormsBrokenSpaceConstraintImpl.hpp
Go to the documentation of this file.
1/**
2 * @file FormsBrokenSpaceConstraintImpl.hpp
3 * @brief Integrator for broken space constraints
4 * @date 2024-07-01
5 *
6 * @copyright Copyright (c) 2024
7 *
8 */
9
10#ifndef __FORMSBROKENSPACECONSTRAINTIMPL_HPP__
11#define __FORMSBROKENSPACECONSTRAINTIMPL_HPP__
12
13namespace MoFEM {
14
15/**
16 * @brief Operator for broken loop side
17 *
18 * That is used follow pattern,
19 *
20 * First: Iterate over skeleton FEs adjacent to Domain FEs
21 * Note: BoundaryEle, i.e. uses skeleton interation rule
22 *
23 * ans then
24 *
25 * Iterate over domain FEs adjacent to skelton, particularly one
26 * domain element.
27 *
28 * You use this to integrate over skelton, but field which is on adjacent domain
29 * element.
30 *
31 * @tparam E
32 */
33template <typename E> struct OpBrokenLoopSide : public OpLoopSide<E> {
34
36 using OpLoopSide<E>::OpLoopSide;
37
38 MoFEMErrorCode doWork(int side, EntityType type,
41
42 auto prev_side_fe_ptr = OP::getSidePtrFE();
43 if (OP::sideFEName == prev_side_fe_ptr->getFEName()) {
44 auto prev_fe_uid =
45 prev_side_fe_ptr->numeredEntFiniteElementPtr->getFEUId();
47 CHKERR OP::sideFEPtr->setSideFEPtr(OP::getPtrFE());
48 CHKERR OP::sideFEPtr->copyBasicMethod(*OP::getFEMethod());
49 CHKERR OP::sideFEPtr->copyPetscData(*OP::getFEMethod());
53 OP::sideFEPtr->cacheWeakPtr = prev_side_fe_ptr->cacheWeakPtr;
54 OP::sideFEPtr->loopSize = 1;
55 CHKERR OP::sideFEPtr->preProcess();
56 OP::sideFEPtr->nInTheLoop = 0;
57 OP::sideFEPtr->numeredEntFiniteElementPtr =
58 prev_side_fe_ptr->numeredEntFiniteElementPtr;
60 CHKERR OP::sideFEPtr->postProcess();
61 } else {
62 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
63 "sideFEName is different");
64 }
65
67 };
68};
69
72 inline auto &getSense() { return eleSense; }
73 inline auto &getSide() { return eleSide; }
74 inline auto &getType() { return eleType; }
75 inline auto &getData() { return entData; }
76 inline auto &getFlux() { return fluxMat; }
77 inline auto &getVarFlux() { return fluxVarMat; }
78
79private:
80 int eleSense = 0;
81 int eleSide = 1;
82 EntityType eleType = MBENTITYSET;
86};
87
88template <typename OpBase> struct OpGetBrokenBaseSideData : public OpBase {
89
90 using OP = OpBase;
91
93 const std::string field_name,
94 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data);
95
96 MoFEMErrorCode doWork(int row_side, EntityType row_type,
98
99private:
100 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
101};
102
103template <typename OpBase>
105 const std::string field_name,
106 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data)
107 : OP(field_name, field_name, OP::OPROW),
108 brokenBaseSideData(broken_base_side_data) {}
109
110template <typename OpBase>
112OpGetBrokenBaseSideData<OpBase>::doWork(int row_side, EntityType row_type,
113 EntitiesFieldData::EntData &row_data) {
115 brokenBaseSideData->resize(OP::getLoopSize());
116
117 const auto n_in_the_loop = OP::getNinTheLoop();
118 const auto face_sense = OP::getSkeletonSense();
119
120#ifndef NDEBUG
121 if (face_sense != -1 && face_sense != 1)
122 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "face sense not set");
123#endif // NDEBUG
124
125 auto set_data = [&](auto &side_data) {
126 side_data.getSide() = row_side;
127 side_data.getType() = row_type;
128 side_data.getSense() = face_sense;
129 side_data.getData().sEnse = row_data.sEnse;
130 side_data.getData().sPace = row_data.sPace;
131 side_data.getData().bAse = row_data.bAse;
132 side_data.getData().iNdices = row_data.iNdices;
133 side_data.getData().localIndices = row_data.localIndices;
134 side_data.getData().dOfs = row_data.dOfs;
135 side_data.getData().fieldEntities = row_data.fieldEntities;
136 side_data.getData().fieldData = row_data.fieldData;
137 };
138
139 auto set_base = [&](auto &side_data) {
140 auto base = side_data.getData().getBase();
141 for (auto dd = 0; dd != BaseDerivatives::LastDerivative; ++dd) {
142 for (auto bb = 0; bb != LASTBASE; ++bb) {
143 side_data.getData().baseFunctionsAndBaseDerivatives[dd][bb].reset();
144 }
145 if (auto base_ptr = row_data.baseFunctionsAndBaseDerivatives[dd][base]) {
146 side_data.getData().baseFunctionsAndBaseDerivatives[dd][base] =
147 boost::make_shared<MatrixDouble>(*base_ptr);
148 }
149 }
150 };
151
152 set_data((*brokenBaseSideData)[n_in_the_loop]);
153 set_base((*brokenBaseSideData)[n_in_the_loop]);
154
156}
157
158template <typename OpBase> struct OpSetFlux : public OpBase {
159
160 using OP = OpBase;
161
162 OpSetFlux(
163 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
164 boost::shared_ptr<MatrixDouble> flux_ptr);
165
166 MoFEMErrorCode doWork(int row_side, EntityType row_type,
168
169private:
170 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
171 boost::shared_ptr<MatrixDouble> fluxPtr;
172};
173
174template <typename OpBase>
176 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
177 boost::shared_ptr<MatrixDouble> flux_ptr)
178 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data),
179 fluxPtr(flux_ptr) {}
180
181template <typename OpBase>
185 auto swap_flux = [&](auto &side_data) { side_data.getFlux().swap(*fluxPtr); };
186 swap_flux((*brokenBaseSideData)[OP::getNinTheLoop()]);
188}
189template <typename OpBase> struct OpSetVarFlux : public OpBase {
190
191 using OP = OpBase;
192
194 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
195 boost::shared_ptr<MatrixDouble> flux_var_ptr);
196
197 MoFEMErrorCode doWork(int row_side, EntityType row_type,
199
200private:
201 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
202 boost::shared_ptr<MatrixDouble> fluxVarPtr;
203};
204
205template <typename OpBase>
207 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
208 boost::shared_ptr<MatrixDouble> flux_var_ptr)
209 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data),
210 fluxVarPtr(flux_var_ptr) {}
211
212template <typename OpBase>
216 auto swap_flux = [&](auto &side_data) {
217 side_data.getVarFlux().swap(*fluxVarPtr);
218 };
219 swap_flux((*brokenBaseSideData)[OP::getNinTheLoop()]);
221}
222
223
224template <typename OpBase> struct OpBrokenBaseImpl : public OpBase {
225
226 using OP = OpBase;
227
229 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
230 boost::shared_ptr<Range> ents_ptr = nullptr)
231 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data) {
232 OP::entsPtr = ents_ptr;
233 OP::assembleTranspose = false;
234 OP::onlyTranspose = false;
235 OP::sYmm = false;
236 }
237
239 const std::string row_field,
240 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
241 const bool assmb_transpose, const bool only_transpose,
242 boost::shared_ptr<Range> ents_ptr = nullptr)
243 : OP(row_field, row_field, OP::OPROW, ents_ptr),
244 brokenBaseSideData(broken_base_side_data) {
245 OP::entsPtr = ents_ptr;
246 OP::assembleTranspose = assmb_transpose;
247 OP::onlyTranspose = only_transpose;
248 OP::sYmm = false;
249 }
250
251 MoFEMErrorCode doWork(int row_side, EntityType row_type,
253
254protected:
255 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
256};
257
258template <typename OpBase>
260OpBrokenBaseImpl<OpBase>::doWork(int row_side, EntityType row_type,
261 EntitiesFieldData::EntData &row_data) {
263
264 if (OP::entsPtr) {
265 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
267 }
268
269#ifndef NDEBUG
270 if (!brokenBaseSideData) {
271 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
272 }
273#endif // NDEBUG
274
275 auto do_work_rhs = [this](int row_side, EntityType row_type,
276 EntitiesFieldData::EntData &row_data, int sense) {
278 // get number of dofs on row
279 OP::nbRows = row_data.getIndices().size();
280 if (!OP::nbRows)
282 // get number of integration points
283 OP::nbIntegrationPts = OP::getGaussPts().size2();
284 // get row base functions
285 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
286 // resize and clear the right hand side vector
287 OP::locF.resize(OP::nbRows, false);
288 OP::locF.clear();
289 // integrate local vector
290 CHKERR this->iNtegrate(row_data);
291 // assemble local vector
292 OP::locF *= sense;
293 CHKERR this->aSsemble(row_data);
295 };
296
297 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
298 EntityType col_type,
300 EntitiesFieldData::EntData &col_data, int sense) {
302
303 auto check_if_assemble_transpose = [&] {
304 if (this->sYmm) {
305 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
306 return true;
307 else
308 return false;
309 } else if (OP::assembleTranspose) {
310 return true;
311 }
312 return false;
313 };
314
315 OP::rowSide = row_side;
316 OP::rowType = row_type;
317 OP::colSide = col_side;
318 OP::colType = col_type;
319 OP::nbCols = col_data.getIndices().size();
320 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
321 OP::locMat.clear();
322 CHKERR this->iNtegrate(row_data, col_data);
323 OP::locMat *= sense;
324 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
326 };
327
328 switch (OP::opType) {
329 case OP::OPROW:
330
331 OP::nbRows = row_data.getIndices().size();
332 if (!OP::nbRows)
334 OP::nbIntegrationPts = OP::getGaussPts().size2();
335 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
336
337 if (!OP::nbRows)
339
340 for (auto &bd : *brokenBaseSideData) {
341
342#ifndef NDEBUG
343 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
344 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
345 "base functions not set");
346 }
347#endif
348
349 CHKERR do_work_lhs(
350
351 // side
352 row_side, bd.getSide(),
353
354 // type
355 row_type, bd.getType(),
356
357 // row_data
358 row_data, bd.getData(),
359
360 // sense
361 bd.getSense()
362
363 );
364 }
365
366 break;
367 case OP::OPSPACE:
368 for (auto &bd : *brokenBaseSideData) {
369 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData(),
370 bd.getSense());
371 }
372 break;
373 default:
375 (std::string("wrong op type ") +
377 .c_str());
378 }
379
381}
382
383template <int FIELD_DIM, IntegrationType I, typename OpBrokenBase>
385
386template <int FIELD_DIM, typename OpBrokenBase>
388 : public OpBrokenBase {
389
391
393 const std::string row_field,
394 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
395 boost::shared_ptr<double> beta_ptr, const bool assmb_transpose,
396 const bool only_transpose, boost::shared_ptr<Range> ents_ptr = nullptr)
397 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
398 ents_ptr),
399 scalarBetaPtr(beta_ptr) {}
400
402 const std::string row_field,
403 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
404 double beta, const bool assmb_transpose, const bool only_transpose,
405 boost::shared_ptr<Range> ents_ptr = nullptr)
406 : OpBrokenSpaceConstrainImpl(row_field, broken_base_side_data,
407 boost::make_shared<double>(beta),
408 assmb_transpose, only_transpose, ents_ptr) {}
409
410protected:
411 boost::shared_ptr<double> scalarBetaPtr;
414};
415
416template <int FIELD_DIM, typename OpBase>
419 EntitiesFieldData::EntData &col_data) {
421
422 auto nb_row_dofs = row_data.getIndices().size();
423 auto nb_col_dofs = col_data.getIndices().size();
424 if (!nb_row_dofs || !nb_col_dofs)
426
428 FTENSOR_INDEX(3, J);
429
430 auto t_w = this->getFTensor0IntegrationWeight();
431 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
432 size_t nb_base_functions = col_data.getN().size2() / 3;
433
434#ifndef NDEBUG
435 if (nb_row_dofs % FIELD_DIM != 0 || nb_col_dofs % FIELD_DIM != 0) {
436 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
437 "number of dofs not divisible by field dimension");
438 }
439 if (nb_row_dofs > row_data.getN().size2() * FIELD_DIM ||
440 nb_col_dofs > col_data.getN().size2() * FIELD_DIM) {
441 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
442 "number of dofs exceeds number of base functions");
443 }
444#endif // NDEBUG
445
446 auto t_col_base = col_data.getFTensor1N<3>();
447
448 double triangle_scale = 1.0;
449 if (OP::getFEType() == MBTRI)
450 triangle_scale = 0.5;
451
452 if (scalarBetaPtr)
453 triangle_scale *= *scalarBetaPtr;
454
455 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
456 int cc = 0;
457 for (; cc != nb_col_dofs / FIELD_DIM; cc++) {
458 auto t_row_base = row_data.getFTensor0N(gg, 0);
459 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
460 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc) +=
461 (triangle_scale * (t_w * t_row_base)) *
462 (t_normal(J) * t_col_base(J));
463 ++t_row_base;
464 }
465
466 ++t_col_base;
467 }
468
469 for (; cc < nb_base_functions; ++cc)
470 ++t_col_base;
471
472 ++t_w;
473 ++t_normal;
474 }
475
476 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
477 for (auto cc = 0; cc != nb_col_dofs / FIELD_DIM; ++cc) {
478 for (auto dd = 1; dd < FIELD_DIM; ++dd) {
479 OP::locMat(FIELD_DIM * rr + dd, FIELD_DIM * cc + dd) =
480 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc);
481 }
482 }
483 }
484
485
487}
488
489template <int FIELD_DIM, IntegrationType I, typename OpBase>
491
492template <int FIELD_DIM, IntegrationType I, typename OpBase>
494
495template <int FIELD_DIM, typename OpBrokenBase>
497 : public OpBrokenBase {
498
500
502 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
503 boost::shared_ptr<MatrixDouble> lagrange_ptr,
504 boost::shared_ptr<double> beta_ptr,
505 boost::shared_ptr<Range> ents_ptr = nullptr)
506 : OP(broken_base_side_data, ents_ptr), scalarBetaPtr(beta_ptr),
507 lagrangePtr(lagrange_ptr) {}
508
510 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
511 boost::shared_ptr<MatrixDouble> lagrange_ptr, double beta,
512 boost::shared_ptr<Range> ents_ptr = nullptr)
513 : OpBrokenSpaceConstrainDFluxImpl(broken_base_side_data, lagrange_ptr,
514 boost::make_shared<double>(beta),
515 ents_ptr) {}
516
517private:
519
520 boost::shared_ptr<double> scalarBetaPtr;
521 boost::shared_ptr<MatrixDouble> lagrangePtr;
522};
523
524template <int FIELD_DIM, typename OpBase>
527 EntitiesFieldData::EntData &row_data) {
529
531 auto get_lagrange_at_pts =
533 *lagrangePtr, OpBase::nbIntegrationPts);
534
536 FTENSOR_INDEX(3, J);
537
538 auto t_w = this->getFTensor0IntegrationWeight();
539 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
540 auto t_lagrange_at_pts = get_lagrange_at_pts();
541
542 auto t_row_base = row_data.getFTensor1N<3>();
543 auto nb_base_functions = row_data.getN().size2() / 3;
544
545 double triangle_scale = 1.0;
546 if (OP::getFEType() == MBTRI)
547 triangle_scale = 0.5;
548
549 if (scalarBetaPtr)
550 triangle_scale *= *scalarBetaPtr;
551
552 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
553 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
554 size_t rr = 0;
555 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
556 t_vec(i) += (triangle_scale * t_w * (t_row_base(J) * t_normal(J))) *
557 t_lagrange_at_pts(i);
558 ++t_row_base;
559 ++t_vec;
560 }
561 for (; rr < nb_base_functions; ++rr)
562 ++t_row_base;
563 ++t_w;
564 ++t_normal;
565 ++t_lagrange_at_pts;
566 }
567
569}
570
571template <int FIELD_DIM, typename OpBase>
573 : public OpBase {
574
575 using OP = OpBase;
576
578 const std::string row_field,
579 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
580 boost::shared_ptr<double> beta_ptr,
581 boost::shared_ptr<Range> ents_ptr = nullptr)
582 : OpBase(row_field, row_field, OpBase::OPROW, ents_ptr),
583 brokenSideDataPtr(broken_side_data_ptr), scalarBetaPtr(beta_ptr) {}
584
586 const std::string row_field,
587 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
588 double beta, boost::shared_ptr<Range> ents_ptr = nullptr)
589 : OpBrokenSpaceConstrainDHybridImpl(row_field, broken_side_data_ptr,
590 boost::make_shared<double>(beta),
591 ents_ptr) {}
592
593private:
594 boost::shared_ptr<double> scalarBetaPtr;
595 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
596 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
597};
598
599template <int FIELD_DIM, typename OpBase>
602 EntitiesFieldData::EntData &row_data) {
604
606 FTENSOR_INDEX(3, J);
607
608 OP::locF.resize(row_data.getIndices().size(), false);
609 OP::locF.clear();
610
611 double triangle_scale = 1.0;
612 if (OP::getFEType() == MBTRI)
613 triangle_scale = 0.5;
614
615 if (scalarBetaPtr)
616 triangle_scale *= *scalarBetaPtr;
617
618 for (auto &bd : *brokenSideDataPtr) {
619 auto t_w = this->getFTensor0IntegrationWeight();
620 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
621 auto t_row_base = row_data.getFTensor0N();
622 auto t_flux = getFTensor2FromMat<FIELD_DIM, 3>(bd.getFlux());
623 auto nb_base_functions = row_data.getN().size2() / 3;
624 auto sense = bd.getSense();
625 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
626 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
627 size_t rr = 0;
628 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
629 t_vec(i) += (triangle_scale * sense * t_w) * t_row_base * t_normal(J) *
630 t_flux(i, J);
631 ++t_row_base;
632 ++t_vec;
633 }
634 for (; rr < nb_base_functions; ++rr)
635 ++t_row_base;
636 ++t_w;
637 ++t_normal;
638 ++t_flux;
639 }
640 }
641
643}
644
645template <int FIELD_DIM, IntegrationType I, typename OpBase>
647
648template <int FIELD_DIM, IntegrationType I, typename OpBase>
650
651template <typename OpBrokenBase> struct OpBrokenTopoBase : public OpBrokenBase {
653
654protected:
655
657 const std::string row_field,
658 boost::shared_ptr<MatrixDouble> tangent1_diff_ptr,
659 boost::shared_ptr<MatrixDouble> tangent2_diff_ptr,
660 SmartPetscObj<Vec> assemble_vec, Tag th,
661 boost::shared_ptr<Range> ents_ptr = nullptr)
662 : OP(row_field, row_field, OP::OPROW, ents_ptr),
663 tangent1DiffPtr(tangent1_diff_ptr),
664 tangent2DiffPtr(tangent2_diff_ptr), assembleVec(assemble_vec),
665 thGradTag(th) {}
666
669 if (!this->timeScalingFun.empty())
670 this->locF *= this->timeScalingFun(this->getFEMethod()->ts_t);
671 if (!this->feScalingFun.empty())
672 this->locF *= this->feScalingFun(this->getFEMethod());
673 if (assembleVec) {
674 auto *vec_ptr = this->locF.data().data();
675 const auto nb_dofs = row_data.getIndices().size();
676 auto *ind_ptr = row_data.getIndices().data().data();
677 return VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
678 }
679 if (thGradTag) {
680 const auto field_ents = row_data.getFieldEntities();
681 std::vector<EntityHandle> ents(field_ents.size());
682 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
683 [](const auto *fe) { return fe->getEnt(); });
684 if (field_ents.empty())
686 if (type_from_handle(ents[0]) != MBVERTEX)
688 auto &moab = this->getMoab();
689 VectorDouble topo_values(this->locF.size());
690 CHKERR moab.tag_get_data(thGradTag, ents.data(), ents.size(),
691 topo_values.data().data());
692 topo_values += this->locF;
693 CHKERR moab.tag_set_data(thGradTag, ents.data(), ents.size(),
694 topo_values.data().data());
695 }
697 }
698
699 boost::shared_ptr<MatrixDouble> tangent1DiffPtr;
700 boost::shared_ptr<MatrixDouble> tangent2DiffPtr;
703};
704
705template <typename OpBase>
707 : public OpBrokenTopoBase<OpBase> {
708
710
712 const std::string row_field,
713 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
714 boost::shared_ptr<MatrixDouble> lamgrange_ptr,
715 boost::shared_ptr<MatrixDouble> tangent1_ptr,
716 boost::shared_ptr<MatrixDouble> tangent2_ptr,
717 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
718 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
719 boost::shared_ptr<Range> ents_ptr = nullptr)
720 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
721 brokenSideDataPtr(broken_side_data_ptr), lagrangePtr(lamgrange_ptr),
722 scalarBetaPtr(beta_ptr), dJPtr(dJ_ptr) {}
723
724private:
725 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
726 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
727 boost::shared_ptr<MatrixDouble> lagrangePtr;
728 boost::shared_ptr<double> scalarBetaPtr;
729 boost::shared_ptr<double> dJPtr;
730};
731
732template <typename OpBase>
735 EntitiesFieldData::EntData &row_data) {
737
738 // That is used for testing the H(div) contravariant Piola trace P.n dA
739 // invariance with respect to material map variations. The variation of the
740 // normal is cancelled by the variation of bd.getVarFlux()
741
743 auto get_lagrange_at_pts =
744 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
745 *lagrangePtr, OpBase::nbIntegrationPts);
746
747 FTENSOR_INDEX(3, J);
748 FTENSOR_INDEX(3, i);
749 FTENSOR_INDEX(3, j);
750 FTENSOR_INDEX(3, k);
751
752 auto get_ftensor1 = [](MatrixDouble &m) {
754 &m(0, 0), &m(0, 1), &m(0, 2));
755 };
756
757 double triangle_scale = 1.0;
758 if (OP::getFEType() == MBTRI)
759 triangle_scale = 0.5;
760
761 double d_loc_J = 0.0;
762
763 for (auto &bd : *brokenSideDataPtr) {
764 auto sense = bd.getSense();
765
766 if (dJPtr) {
767 auto t_w = this->getFTensor0IntegrationWeight();
768 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
769 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
770 auto t_lagrange_at_pts = get_lagrange_at_pts();
771 auto t_adjoint_lambda = getFTensor2FromMat<3, 3>(bd.getVarFlux());
772
773 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
774 FTensor::Tensor1<double, 3> t_tmp_normal;
775 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
776 d_loc_J += (sense * triangle_scale * t_w) *
777 (t_lagrange_at_pts(i) *
778 (t_adjoint_lambda(i, J) * t_tmp_normal(J)));
779 ++t_w;
780 ++t_t1;
781 ++t_t2;
782 ++t_lagrange_at_pts;
783 ++t_adjoint_lambda;
784 }
785 }
786 }
787
788 // The H(div) contravariant Piola trace P.n dA is material-map invariant.
789 // The normal variation is cancelled by the variation of bd.getVarFlux().
790 if (dJPtr) {
791 if (scalarBetaPtr)
792 d_loc_J *= *scalarBetaPtr;
793 *dJPtr += d_loc_J;
794 }
795
797}
798
799template <typename OpBase>
801 : public OpBrokenTopoBase<OpBase> {
802
804
806 const std::string row_field,
807 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
808 boost::shared_ptr<MatrixDouble> adjoint_hybrid_ptr,
809 boost::shared_ptr<MatrixDouble> tangent1_ptr,
810 boost::shared_ptr<MatrixDouble> tangent2_ptr,
811 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
812 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
813 boost::shared_ptr<Range> ents_ptr = nullptr)
814 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
815 brokenSideDataPtr(broken_side_data_ptr),
816 adjointHybridPtr(adjoint_hybrid_ptr), scalarBetaPtr(beta_ptr),
817 dJPtr(dJ_ptr) {}
818
819private:
820 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
821 boost::shared_ptr<MatrixDouble> adjointHybridPtr;
822 boost::shared_ptr<double> scalarBetaPtr;
823 boost::shared_ptr<double> dJPtr;
824 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
825};
826
827template <typename OpBase>
829 3, GAUSS, OpBase>::iNtegrate(EntitiesFieldData::EntData &row_data) {
831
833 auto get_adjoint_lambda_at_pts =
834 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
835 *adjointHybridPtr, OpBase::nbIntegrationPts);
836
837 FTENSOR_INDEX(3, i);
838 FTENSOR_INDEX(3, j);
839 FTENSOR_INDEX(3, k);
840 FTENSOR_INDEX(3, J);
841
842 OP::locF.resize(row_data.getIndices().size(), false);
843 OP::locF.clear();
844
845 auto get_ftensor1 = [](MatrixDouble &m) {
847 &m(0, 0), &m(0, 1), &m(0, 2));
848 };
849
850 double d_loc_J = 0;
851
852 double triangle_scale = 1.0;
853 if (OP::getFEType() == MBTRI)
854 triangle_scale = 0.5;
855
856 for (auto &bd : *brokenSideDataPtr) {
857 auto sense = bd.getSense();
858
859 // This is used for testing the H(div) contravariant Piola trace P.n dA invariance
860 // with respect to material map variations. The variation of the normal is
861 // cancelled by the variation of bd.getFlux() in the adjoint lambda at pts
862
863 if (dJPtr) {
864 auto t_w = this->getFTensor0IntegrationWeight();
865 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
866 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
867 auto t_flux = getFTensor2FromMat<3, 3>(bd.getFlux());
868 auto t_adjoint_lambda_at_pts = get_adjoint_lambda_at_pts();
869 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
870 FTensor::Tensor1<double, 3> t_tmp_normal;
871 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
872 d_loc_J +=
873 (sense * triangle_scale * t_w) *
874 (t_adjoint_lambda_at_pts(i) * (t_flux(i, J) * t_tmp_normal(J)));
875 ++t_w;
876 ++t_t1;
877 ++t_t2;
878 ++t_flux;
879 ++t_adjoint_lambda_at_pts;
880 }
881 }
882 }
883
884 // The L2 hybrid multiplier is not material-map transformed, while the H(div)
885 // contravariant Piola trace P.n dA is invariant.
886 if (dJPtr) {
887 if (scalarBetaPtr)
888 d_loc_J *= *scalarBetaPtr;
889 *dJPtr += d_loc_J;
890 }
891
893}
894
895} // namespace MoFEM
896
897#endif // __FORMSBROKENSPACECONSTRAINTIMPL_HPP__
std::string type
#define FTENSOR_INDEX(DIM, I)
constexpr int FIELD_DIM
@ LASTBASE
Definition definitions.h:69
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ NOSPACE
Definition definitions.h:83
#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.
@ GAUSS
Gaussian quadrature integration.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition ddTensor0.hpp:33
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
constexpr auto field_name
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Definition radiation.cpp:29
FTensor::Index< 'm', 3 > m
Data on single entity (This is passed as argument to DataOperator::doWork)
int sEnse
Entity sense (orientation)
VectorDouble fieldData
Field data on entity.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
VectorInt localIndices
Local indices on entity.
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
VectorInt iNdices
Global indices on entity.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
virtual int getSense() const
Get entity sense for conforming approximation fields.
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
VectorFieldEntities fieldEntities
Field entities.
std::array< std::array< boost::shared_ptr< MatrixDouble >, LASTBASE >, LastDerivative > baseFunctionsAndBaseDerivatives
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
FieldApproximationBase bAse
Field approximation base.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
boost::shared_ptr< Range > entsPtr
Entities on which element is run.
int nbIntegrationPts
number of integration points
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideData
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpBrokenBaseImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, const bool assmb_transpose, const bool only_transpose, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenBaseImpl(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< Range > ents_ptr=nullptr)
Operator for broken loop side.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data)
OpBrokenSpaceConstrainDFluxImpl(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > lagrange_ptr, boost::shared_ptr< double > beta_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenSpaceConstrainDFluxImpl(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > lagrange_ptr, double beta, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenSpaceConstrainDHybridImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< double > beta_ptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenSpaceConstrainDHybridImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, double beta, boost::shared_ptr< Range > ents_ptr=nullptr)
OpBrokenSpaceConstrainImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< double > beta_ptr, const bool assmb_transpose, const bool only_transpose, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
OpBrokenSpaceConstrainImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, double beta, const bool assmb_transpose, const bool only_transpose, boost::shared_ptr< Range > ents_ptr=nullptr)
boost::shared_ptr< MatrixDouble > tangent2DiffPtr
boost::shared_ptr< MatrixDouble > tangent1DiffPtr
MoFEMErrorCode aSsemble(EntitiesFieldData::EntData &row_data)
OpBrokenTopoBase(const std::string row_field, boost::shared_ptr< MatrixDouble > tangent1_diff_ptr, boost::shared_ptr< MatrixDouble > tangent2_diff_ptr, SmartPetscObj< Vec > assemble_vec, Tag th, boost::shared_ptr< Range > ents_ptr=nullptr)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideData
OpGetBrokenBaseSideData(const std::string field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data)
Element used to execute operators on side of the element.
const std::string sideFEName
boost::shared_ptr< E > sideFEPtr
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
OpSetFlux(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > flux_ptr)
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideData
boost::shared_ptr< MatrixDouble > fluxPtr
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
boost::shared_ptr< MatrixDouble > fluxVarPtr
OpSetVarFlux(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< MatrixDouble > flux_var_ptr)
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideData
OpTopoDerivativeBrokenSpaceConstrainDFluxImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< MatrixDouble > lamgrange_ptr, boost::shared_ptr< MatrixDouble > tangent1_ptr, boost::shared_ptr< MatrixDouble > tangent2_ptr, boost::shared_ptr< double > beta_ptr, SmartPetscObj< Vec > assemble_vec, Tag th, boost::shared_ptr< double > dJ_ptr=nullptr, boost::shared_ptr< Range > ents_ptr=nullptr)
OpTopoDerivativeBrokenSpaceConstrainDHybridImpl(const std::string row_field, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< MatrixDouble > adjoint_hybrid_ptr, boost::shared_ptr< MatrixDouble > tangent1_ptr, boost::shared_ptr< MatrixDouble > tangent2_ptr, boost::shared_ptr< double > beta_ptr, SmartPetscObj< Vec > assemble_vec, Tag th, boost::shared_ptr< double > dJ_ptr=nullptr, boost::shared_ptr< Range > ents_ptr=nullptr)
intrusive_ptr for managing petsc objects