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, EntityType,
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:
376 (std::string("wrong op type ") +
377 OpBaseDerivativesBase::OpTypeNames[static_cast<unsigned char>(
378 OP::opType)])
379 .c_str());
380 }
381
383}
384
385template <int FIELD_DIM, IntegrationType I, typename OpBrokenBase>
387
388template <int FIELD_DIM, typename OpBrokenBase>
390 : public OpBrokenBase {
391
393
395 const std::string row_field,
396 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
397 boost::shared_ptr<double> beta_ptr, const bool assmb_transpose,
398 const bool only_transpose, boost::shared_ptr<Range> ents_ptr = nullptr)
399 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
400 ents_ptr),
401 scalarBetaPtr(beta_ptr) {}
402
404 const std::string row_field,
405 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
406 double beta, const bool assmb_transpose, const bool only_transpose,
407 boost::shared_ptr<Range> ents_ptr = nullptr)
408 : OpBrokenSpaceConstrainImpl(row_field, broken_base_side_data,
409 boost::make_shared<double>(beta),
410 assmb_transpose, only_transpose, ents_ptr) {}
411
412protected:
413 boost::shared_ptr<double> scalarBetaPtr;
416};
417
418template <int FIELD_DIM, typename OpBase>
421 EntitiesFieldData::EntData &col_data) {
423
424 auto nb_row_dofs = row_data.getIndices().size();
425 auto nb_col_dofs = col_data.getIndices().size();
426 if (!nb_row_dofs || !nb_col_dofs)
428
430 FTENSOR_INDEX(3, J);
431
432 auto t_w = this->getFTensor0IntegrationWeight();
433 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
434 size_t nb_base_functions = col_data.getN().size2() / 3;
435
436#ifndef NDEBUG
437 if (nb_row_dofs % FIELD_DIM != 0 || nb_col_dofs % FIELD_DIM != 0) {
438 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
439 "number of dofs not divisible by field dimension");
440 }
441 if (nb_row_dofs > row_data.getN().size2() * FIELD_DIM ||
442 nb_col_dofs > col_data.getN().size2() * FIELD_DIM) {
443 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
444 "number of dofs exceeds number of base functions");
445 }
446#endif // NDEBUG
447
448 auto t_col_base = col_data.getFTensor1N<3>();
449
450 double triangle_scale = 1.0;
451 if (OP::getFEType() == MBTRI)
452 triangle_scale = 0.5;
453
454 if (scalarBetaPtr)
455 triangle_scale *= *scalarBetaPtr;
456
457 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
458 int cc = 0;
459 for (; cc != nb_col_dofs / FIELD_DIM; cc++) {
460 auto t_row_base = row_data.getFTensor0N(gg, 0);
461 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
462 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc) +=
463 (triangle_scale * (t_w * t_row_base)) *
464 (t_normal(J) * t_col_base(J));
465 ++t_row_base;
466 }
467
468 ++t_col_base;
469 }
470
471 for (; cc < nb_base_functions; ++cc)
472 ++t_col_base;
473
474 ++t_w;
475 ++t_normal;
476 }
477
478 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
479 for (auto cc = 0; cc != nb_col_dofs / FIELD_DIM; ++cc) {
480 for (auto dd = 1; dd < FIELD_DIM; ++dd) {
481 OP::locMat(FIELD_DIM * rr + dd, FIELD_DIM * cc + dd) =
482 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc);
483 }
484 }
485 }
486
487
489}
490
491template <int FIELD_DIM, IntegrationType I, typename OpBase>
493
494template <int FIELD_DIM, IntegrationType I, typename OpBase>
496
497template <int FIELD_DIM, typename OpBrokenBase>
499 : public OpBrokenBase {
500
502
504 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
505 boost::shared_ptr<MatrixDouble> lagrange_ptr,
506 boost::shared_ptr<double> beta_ptr,
507 boost::shared_ptr<Range> ents_ptr = nullptr)
508 : OP(broken_base_side_data, ents_ptr), scalarBetaPtr(beta_ptr),
509 lagrangePtr(lagrange_ptr) {}
510
512 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
513 boost::shared_ptr<MatrixDouble> lagrange_ptr, double beta,
514 boost::shared_ptr<Range> ents_ptr = nullptr)
515 : OpBrokenSpaceConstrainDFluxImpl(broken_base_side_data, lagrange_ptr,
516 boost::make_shared<double>(beta),
517 ents_ptr) {}
518
519private:
521
522 boost::shared_ptr<double> scalarBetaPtr;
523 boost::shared_ptr<MatrixDouble> lagrangePtr;
524};
525
526template <int FIELD_DIM, typename OpBase>
529 EntitiesFieldData::EntData &row_data) {
531
533 auto get_lagrange_at_pts =
535 *lagrangePtr, OpBase::nbIntegrationPts);
536
538 FTENSOR_INDEX(3, J);
539
540 auto t_w = this->getFTensor0IntegrationWeight();
541 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
542 auto t_lagrange_at_pts = get_lagrange_at_pts();
543
544 auto t_row_base = row_data.getFTensor1N<3>();
545 auto nb_base_functions = row_data.getN().size2() / 3;
546
547 double triangle_scale = 1.0;
548 if (OP::getFEType() == MBTRI)
549 triangle_scale = 0.5;
550
551 if (scalarBetaPtr)
552 triangle_scale *= *scalarBetaPtr;
553
554 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
555 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
556 size_t rr = 0;
557 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
558 t_vec(i) += (triangle_scale * t_w * (t_row_base(J) * t_normal(J))) *
559 t_lagrange_at_pts(i);
560 ++t_row_base;
561 ++t_vec;
562 }
563 for (; rr < nb_base_functions; ++rr)
564 ++t_row_base;
565 ++t_w;
566 ++t_normal;
567 ++t_lagrange_at_pts;
568 }
569
571}
572
573template <int FIELD_DIM, typename OpBase>
575 : public OpBase {
576
577 using OP = OpBase;
578
580 const std::string row_field,
581 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
582 boost::shared_ptr<double> beta_ptr,
583 boost::shared_ptr<Range> ents_ptr = nullptr)
584 : OpBase(row_field, row_field, OpBase::OPROW, ents_ptr),
585 brokenSideDataPtr(broken_side_data_ptr), scalarBetaPtr(beta_ptr) {}
586
588 const std::string row_field,
589 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
590 double beta, boost::shared_ptr<Range> ents_ptr = nullptr)
591 : OpBrokenSpaceConstrainDHybridImpl(row_field, broken_side_data_ptr,
592 boost::make_shared<double>(beta),
593 ents_ptr) {}
594
595private:
596 boost::shared_ptr<double> scalarBetaPtr;
597 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
598 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
599};
600
601template <int FIELD_DIM, typename OpBase>
604 EntitiesFieldData::EntData &row_data) {
606
608 FTENSOR_INDEX(3, J);
609
610 OP::locF.resize(row_data.getIndices().size(), false);
611 OP::locF.clear();
612
613 double triangle_scale = 1.0;
614 if (OP::getFEType() == MBTRI)
615 triangle_scale = 0.5;
616
617 if (scalarBetaPtr)
618 triangle_scale *= *scalarBetaPtr;
619
620 for (auto &bd : *brokenSideDataPtr) {
621 auto t_w = this->getFTensor0IntegrationWeight();
622 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
623 auto t_row_base = row_data.getFTensor0N();
624 auto t_flux = getFTensor2FromMat<FIELD_DIM, 3>(bd.getFlux());
625 auto nb_base_functions = row_data.getN().size2() / 3;
626 auto sense = bd.getSense();
627 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
628 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
629 size_t rr = 0;
630 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
631 t_vec(i) += (triangle_scale * sense * t_w) * t_row_base * t_normal(J) *
632 t_flux(i, J);
633 ++t_row_base;
634 ++t_vec;
635 }
636 for (; rr < nb_base_functions; ++rr)
637 ++t_row_base;
638 ++t_w;
639 ++t_normal;
640 ++t_flux;
641 }
642 }
643
645}
646
647template <int FIELD_DIM, IntegrationType I, typename OpBase>
649
650template <int FIELD_DIM, IntegrationType I, typename OpBase>
652
653template <typename OpBrokenBase> struct OpBrokenTopoBase : public OpBrokenBase {
655
656protected:
657
659 const std::string row_field,
660 boost::shared_ptr<MatrixDouble> tangent1_diff_ptr,
661 boost::shared_ptr<MatrixDouble> tangent2_diff_ptr,
662 SmartPetscObj<Vec> assemble_vec, Tag th,
663 boost::shared_ptr<Range> ents_ptr = nullptr)
664 : OP(row_field, row_field, OP::OPROW, ents_ptr),
665 tangent1DiffPtr(tangent1_diff_ptr),
666 tangent2DiffPtr(tangent2_diff_ptr), assembleVec(assemble_vec),
667 thGradTag(th) {}
668
671 if (!this->timeScalingFun.empty())
672 this->locF *= this->timeScalingFun(this->getFEMethod()->ts_t);
673 if (!this->feScalingFun.empty())
674 this->locF *= this->feScalingFun(this->getFEMethod());
675 if (assembleVec) {
676 auto *vec_ptr = this->locF.data().data();
677 const auto nb_dofs = row_data.getIndices().size();
678 auto *ind_ptr = row_data.getIndices().data().data();
679 return VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
680 }
681 if (thGradTag) {
682 const auto field_ents = row_data.getFieldEntities();
683 std::vector<EntityHandle> ents(field_ents.size());
684 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
685 [](const auto *fe) { return fe->getEnt(); });
686 if (field_ents.empty())
688 if (type_from_handle(ents[0]) != MBVERTEX)
690 auto &moab = this->getMoab();
691 VectorDouble topo_values(this->locF.size());
692 CHKERR moab.tag_get_data(thGradTag, ents.data(), ents.size(),
693 topo_values.data().data());
694 topo_values += this->locF;
695 CHKERR moab.tag_set_data(thGradTag, ents.data(), ents.size(),
696 topo_values.data().data());
697 }
699 }
700
701 boost::shared_ptr<MatrixDouble> tangent1DiffPtr;
702 boost::shared_ptr<MatrixDouble> tangent2DiffPtr;
705};
706
707template <typename OpBase>
709 : public OpBrokenTopoBase<OpBase> {
710
712
714 const std::string row_field,
715 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
716 boost::shared_ptr<MatrixDouble> lamgrange_ptr,
717 boost::shared_ptr<MatrixDouble> tangent1_ptr,
718 boost::shared_ptr<MatrixDouble> tangent2_ptr,
719 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
720 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
721 boost::shared_ptr<Range> ents_ptr = nullptr)
722 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
723 brokenSideDataPtr(broken_side_data_ptr), lagrangePtr(lamgrange_ptr),
724 scalarBetaPtr(beta_ptr), dJPtr(dJ_ptr) {}
725
726private:
727 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
728 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
729 boost::shared_ptr<MatrixDouble> lagrangePtr;
730 boost::shared_ptr<double> scalarBetaPtr;
731 boost::shared_ptr<double> dJPtr;
732};
733
734template <typename OpBase>
737 EntitiesFieldData::EntData &row_data) {
739
740 // That is used for testing the H(div) contravariant Piola trace P.n dA
741 // invariance with respect to material map variations. The variation of the
742 // normal is cancelled by the variation of bd.getVarFlux()
743
745 auto get_lagrange_at_pts =
746 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
747 *lagrangePtr, OpBase::nbIntegrationPts);
748
749 FTENSOR_INDEX(3, J);
750 FTENSOR_INDEX(3, i);
751 FTENSOR_INDEX(3, j);
752 FTENSOR_INDEX(3, k);
753
754 auto get_ftensor1 = [](MatrixDouble &m) {
756 &m(0, 0), &m(0, 1), &m(0, 2));
757 };
758
759 double triangle_scale = 1.0;
760 if (OP::getFEType() == MBTRI)
761 triangle_scale = 0.5;
762
763 double d_loc_J = 0.0;
764
765 for (auto &bd : *brokenSideDataPtr) {
766 auto sense = bd.getSense();
767
768 if (dJPtr) {
769 auto t_w = this->getFTensor0IntegrationWeight();
770 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
771 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
772 auto t_lagrange_at_pts = get_lagrange_at_pts();
773 auto t_adjoint_lambda = getFTensor2FromMat<3, 3>(bd.getVarFlux());
774
775 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
776 FTensor::Tensor1<double, 3> t_tmp_normal;
777 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
778 d_loc_J += (sense * triangle_scale * t_w) *
779 (t_lagrange_at_pts(i) *
780 (t_adjoint_lambda(i, J) * t_tmp_normal(J)));
781 ++t_w;
782 ++t_t1;
783 ++t_t2;
784 ++t_lagrange_at_pts;
785 ++t_adjoint_lambda;
786 }
787 }
788 }
789
790 // The H(div) contravariant Piola trace P.n dA is material-map invariant.
791 // The normal variation is cancelled by the variation of bd.getVarFlux().
792 if (dJPtr) {
793 if (scalarBetaPtr)
794 d_loc_J *= *scalarBetaPtr;
795 *dJPtr += d_loc_J;
796 }
797
799}
800
801template <typename OpBase>
803 : public OpBrokenTopoBase<OpBase> {
804
806
808 const std::string row_field,
809 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
810 boost::shared_ptr<MatrixDouble> adjoint_hybrid_ptr,
811 boost::shared_ptr<MatrixDouble> tangent1_ptr,
812 boost::shared_ptr<MatrixDouble> tangent2_ptr,
813 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
814 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
815 boost::shared_ptr<Range> ents_ptr = nullptr)
816 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
817 brokenSideDataPtr(broken_side_data_ptr),
818 adjointHybridPtr(adjoint_hybrid_ptr), scalarBetaPtr(beta_ptr),
819 dJPtr(dJ_ptr) {}
820
821private:
822 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
823 boost::shared_ptr<MatrixDouble> adjointHybridPtr;
824 boost::shared_ptr<double> scalarBetaPtr;
825 boost::shared_ptr<double> dJPtr;
826 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
827};
828
829template <typename OpBase>
831 3, GAUSS, OpBase>::iNtegrate(EntitiesFieldData::EntData &row_data) {
833
835 auto get_adjoint_lambda_at_pts =
836 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
837 *adjointHybridPtr, OpBase::nbIntegrationPts);
838
839 FTENSOR_INDEX(3, i);
840 FTENSOR_INDEX(3, j);
841 FTENSOR_INDEX(3, k);
842 FTENSOR_INDEX(3, J);
843
844 OP::locF.resize(row_data.getIndices().size(), false);
845 OP::locF.clear();
846
847 auto get_ftensor1 = [](MatrixDouble &m) {
849 &m(0, 0), &m(0, 1), &m(0, 2));
850 };
851
852 double d_loc_J = 0;
853
854 double triangle_scale = 1.0;
855 if (OP::getFEType() == MBTRI)
856 triangle_scale = 0.5;
857
858 for (auto &bd : *brokenSideDataPtr) {
859 auto sense = bd.getSense();
860
861 // This is used for testing the H(div) contravariant Piola trace P.n dA invariance
862 // with respect to material map variations. The variation of the normal is
863 // cancelled by the variation of bd.getFlux() in the adjoint lambda at pts
864
865 if (dJPtr) {
866 auto t_w = this->getFTensor0IntegrationWeight();
867 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
868 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
869 auto t_flux = getFTensor2FromMat<3, 3>(bd.getFlux());
870 auto t_adjoint_lambda_at_pts = get_adjoint_lambda_at_pts();
871 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
872 FTensor::Tensor1<double, 3> t_tmp_normal;
873 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
874 d_loc_J +=
875 (sense * triangle_scale * t_w) *
876 (t_adjoint_lambda_at_pts(i) * (t_flux(i, J) * t_tmp_normal(J)));
877 ++t_w;
878 ++t_t1;
879 ++t_t2;
880 ++t_flux;
881 ++t_adjoint_lambda_at_pts;
882 }
883 }
884 }
885
886 // The L2 hybrid multiplier is not material-map transformed, while the H(div)
887 // contravariant Piola trace P.n dA is invariant.
888 if (dJPtr) {
889 if (scalarBetaPtr)
890 d_loc_J *= *scalarBetaPtr;
891 *dJPtr += d_loc_J;
892 }
893
895}
896
897} // namespace MoFEM
898
899#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