v0.16.3
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
94 const std::string field_name,
95 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data);
96
98 const std::string field_name,
99 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data);
100
101 MoFEMErrorCode doWork(int row_side, EntityType row_type,
103
104private:
105 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
106};
107
108template <typename OpBase>
111 const std::string field_name,
112 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data)
113 : OP(field_name, field_name, op_type),
114 brokenBaseSideData(broken_base_side_data) {}
115
116template <typename OpBase>
118 const std::string field_name,
119 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data)
122 broken_base_side_data) {}
123
124template <typename OpBase>
126OpGetBrokenBaseSideData<OpBase>::doWork(int row_side, EntityType row_type,
127 EntitiesFieldData::EntData &row_data) {
129 brokenBaseSideData->resize(OP::getLoopSize());
130
131 const auto n_in_the_loop = OP::getNinTheLoop();
132 const auto face_sense = OP::getSkeletonSense();
133
134#ifndef NDEBUG
135 if (face_sense != -1 && face_sense != 1)
136 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "face sense not set");
137#endif // NDEBUG
138
139 auto set_data = [&](auto &side_data) {
140 side_data.getSide() = row_side;
141 side_data.getType() = row_type;
142 side_data.getSense() = face_sense;
143 side_data.getData().sEnse = row_data.sEnse;
144 side_data.getData().sPace = row_data.sPace;
145 side_data.getData().bAse = row_data.bAse;
146 side_data.getData().iNdices = row_data.iNdices;
147 side_data.getData().localIndices = row_data.localIndices;
148 side_data.getData().dOfs = row_data.dOfs;
149 side_data.getData().fieldEntities = row_data.fieldEntities;
150 side_data.getData().fieldData = row_data.fieldData;
151 };
152
153 auto set_base = [&](auto &side_data) {
154 auto base = side_data.getData().getBase();
155 for (auto dd = 0; dd != BaseDerivatives::LastDerivative; ++dd) {
156 for (auto bb = 0; bb != LASTBASE; ++bb) {
157 side_data.getData().baseFunctionsAndBaseDerivatives[dd][bb].reset();
158 }
159 if (auto base_ptr = row_data.getNSharedPtr(
160 base, static_cast<BaseDerivatives>(dd))) {
161 side_data.getData().baseFunctionsAndBaseDerivatives[dd][base] =
162 boost::make_shared<MatrixDouble>(*base_ptr);
163 }
164 }
165 };
166
167 set_data((*brokenBaseSideData)[n_in_the_loop]);
168 set_base((*brokenBaseSideData)[n_in_the_loop]);
169
171}
172
173template <typename OpBase> struct OpSetFlux : public OpBase {
174
175 using OP = OpBase;
176
177 OpSetFlux(
178 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
179 boost::shared_ptr<MatrixDouble> flux_ptr);
180
181 MoFEMErrorCode doWork(int row_side, EntityType row_type,
183
184private:
185 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
186 boost::shared_ptr<MatrixDouble> fluxPtr;
187};
188
189template <typename OpBase>
191 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
192 boost::shared_ptr<MatrixDouble> flux_ptr)
193 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data),
194 fluxPtr(flux_ptr) {}
195
196template <typename OpBase>
200 auto swap_flux = [&](auto &side_data) { side_data.getFlux().swap(*fluxPtr); };
201 swap_flux((*brokenBaseSideData)[OP::getNinTheLoop()]);
203}
204template <typename OpBase> struct OpSetVarFlux : public OpBase {
205
206 using OP = OpBase;
207
209 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
210 boost::shared_ptr<MatrixDouble> flux_var_ptr);
211
212 MoFEMErrorCode doWork(int row_side, EntityType row_type,
214
215private:
216 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
217 boost::shared_ptr<MatrixDouble> fluxVarPtr;
218};
219
220template <typename OpBase>
222 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
223 boost::shared_ptr<MatrixDouble> flux_var_ptr)
224 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data),
225 fluxVarPtr(flux_var_ptr) {}
226
227template <typename OpBase>
231 auto swap_flux = [&](auto &side_data) {
232 side_data.getVarFlux().swap(*fluxVarPtr);
233 };
234 swap_flux((*brokenBaseSideData)[OP::getNinTheLoop()]);
236}
237
238
239template <typename OpBase> struct OpBrokenBaseImpl : public OpBase {
240
241 using OP = OpBase;
242
244 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
245 boost::shared_ptr<Range> ents_ptr = nullptr)
246 : OP(NOSPACE, OP::OPSPACE), brokenBaseSideData(broken_base_side_data) {
247 OP::entsPtr = ents_ptr;
248 OP::assembleTranspose = false;
249 OP::onlyTranspose = false;
250 OP::sYmm = false;
251 }
252
254 const std::string row_field,
255 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
256 const bool assmb_transpose, const bool only_transpose,
257 boost::shared_ptr<Range> ents_ptr = nullptr)
258 : OP(row_field, row_field, OP::OPROW, ents_ptr),
259 brokenBaseSideData(broken_base_side_data) {
260 OP::entsPtr = ents_ptr;
261 OP::assembleTranspose = assmb_transpose;
262 OP::onlyTranspose = only_transpose;
263 OP::sYmm = false;
264 }
265
266 MoFEMErrorCode doWork(int row_side, EntityType row_type,
268
269protected:
270 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenBaseSideData;
271};
272
273template <typename OpBase>
275OpBrokenBaseImpl<OpBase>::doWork(int row_side, EntityType row_type,
276 EntitiesFieldData::EntData &row_data) {
278
279 if (OP::entsPtr) {
280 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
282 }
283
284#ifndef NDEBUG
285 if (!brokenBaseSideData) {
286 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not set");
287 }
288#endif // NDEBUG
289
290 auto do_work_rhs = [this](int, EntityType,
291 EntitiesFieldData::EntData &row_data, int sense) {
293 // get number of dofs on row
294 OP::nbRows = row_data.getIndices().size();
295 if (!OP::nbRows)
297 // get number of integration points
298 OP::nbIntegrationPts = OP::getGaussPts().size2();
299 // get row base functions
300 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
301 // resize and clear the right hand side vector
302 OP::locF.resize(OP::nbRows, false);
303 OP::locF.clear();
304 // integrate local vector
305 CHKERR this->iNtegrate(row_data);
306 // assemble local vector
307 OP::locF *= sense;
308 CHKERR this->aSsemble(row_data);
310 };
311
312 auto do_work_lhs = [this](int row_side, int col_side, EntityType row_type,
313 EntityType col_type,
315 EntitiesFieldData::EntData &col_data, int sense) {
317
318 auto check_if_assemble_transpose = [&] {
319 if (this->sYmm) {
320 if (OP::rowSide != OP::colSide || OP::rowType != OP::colType)
321 return true;
322 else
323 return false;
324 } else if (OP::assembleTranspose) {
325 return true;
326 }
327 return false;
328 };
329
330 OP::rowSide = row_side;
331 OP::rowType = row_type;
332 OP::colSide = col_side;
333 OP::colType = col_type;
334 OP::nbCols = col_data.getIndices().size();
335 OP::locMat.resize(OP::nbRows, OP::nbCols, false);
336 OP::locMat.clear();
337 CHKERR this->iNtegrate(row_data, col_data);
338 OP::locMat *= sense;
339 CHKERR this->aSsemble(row_data, col_data, check_if_assemble_transpose());
341 };
342
343 switch (OP::opType) {
344 case OP::OPROW:
345
346 OP::nbRows = row_data.getIndices().size();
347 if (!OP::nbRows)
349 OP::nbIntegrationPts = OP::getGaussPts().size2();
350 OP::nbRowBaseFunctions = OP::getNbOfBaseFunctions(row_data);
351
352 if (!OP::nbRows)
354
355 for (auto &bd : *brokenBaseSideData) {
356
357#ifndef NDEBUG
358 if (!bd.getData().getNSharedPtr(bd.getData().getBase())) {
359 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
360 "base functions not set");
361 }
362#endif
363
364 CHKERR do_work_lhs(
365
366 // side
367 row_side, bd.getSide(),
368
369 // type
370 row_type, bd.getType(),
371
372 // row_data
373 row_data, bd.getData(),
374
375 // sense
376 bd.getSense()
377
378 );
379 }
380
381 break;
382 case OP::OPSPACE:
383 for (auto &bd : *brokenBaseSideData) {
384 CHKERR do_work_rhs(bd.getSide(), bd.getType(), bd.getData(),
385 bd.getSense());
386 }
387 break;
388 default:
391 (std::string("wrong op type ") +
392 OpBaseDerivativesBase::OpTypeNames[static_cast<unsigned char>(
393 OP::opType)])
394 .c_str());
395 }
396
398}
399
400template <int FIELD_DIM, IntegrationType I, typename OpBrokenBase>
402
403template <int FIELD_DIM, typename OpBrokenBase>
405 : public OpBrokenBase {
406
408
410 const std::string row_field,
411 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
412 boost::shared_ptr<double> beta_ptr, const bool assmb_transpose,
413 const bool only_transpose, boost::shared_ptr<Range> ents_ptr = nullptr)
414 : OP(row_field, broken_base_side_data, assmb_transpose, only_transpose,
415 ents_ptr),
416 scalarBetaPtr(beta_ptr) {}
417
419 const std::string row_field,
420 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
421 double beta, const bool assmb_transpose, const bool only_transpose,
422 boost::shared_ptr<Range> ents_ptr = nullptr)
423 : OpBrokenSpaceConstrainImpl(row_field, broken_base_side_data,
424 boost::make_shared<double>(beta),
425 assmb_transpose, only_transpose, ents_ptr) {}
426
427protected:
428 boost::shared_ptr<double> scalarBetaPtr;
431};
432
433template <int FIELD_DIM, typename OpBase>
436 EntitiesFieldData::EntData &col_data) {
438
439 auto nb_row_dofs = row_data.getIndices().size();
440 auto nb_col_dofs = col_data.getIndices().size();
441 if (!nb_row_dofs || !nb_col_dofs)
443
445 FTENSOR_INDEX(3, J);
446
447 auto t_w = this->getFTensor0IntegrationWeight();
448 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
449 size_t nb_base_functions = col_data.getN().size2() / 3;
450
451#ifndef NDEBUG
452 if (nb_row_dofs % FIELD_DIM != 0 || nb_col_dofs % FIELD_DIM != 0) {
453 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
454 "number of dofs not divisible by field dimension");
455 }
456 if (nb_row_dofs > row_data.getN().size2() * FIELD_DIM ||
457 nb_col_dofs > col_data.getN().size2() * FIELD_DIM) {
458 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
459 "number of dofs exceeds number of base functions");
460 }
461#endif // NDEBUG
462
463 auto t_col_base = col_data.getFTensor1N<3>();
464
465 double triangle_scale = 1.0;
466 if (OP::getFEType() == MBTRI)
467 triangle_scale = 0.5;
468
469 if (scalarBetaPtr)
470 triangle_scale *= *scalarBetaPtr;
471
472 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
473 int cc = 0;
474 for (; cc != nb_col_dofs / FIELD_DIM; cc++) {
475 auto t_row_base = row_data.getFTensor0N(gg, 0);
476 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
477 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc) +=
478 (triangle_scale * (t_w * t_row_base)) *
479 (t_normal(J) * t_col_base(J));
480 ++t_row_base;
481 }
482
483 ++t_col_base;
484 }
485
486 for (; cc < nb_base_functions; ++cc)
487 ++t_col_base;
488
489 ++t_w;
490 ++t_normal;
491 }
492
493 for (auto rr = 0; rr != nb_row_dofs / FIELD_DIM; ++rr) {
494 for (auto cc = 0; cc != nb_col_dofs / FIELD_DIM; ++cc) {
495 for (auto dd = 1; dd < FIELD_DIM; ++dd) {
496 OP::locMat(FIELD_DIM * rr + dd, FIELD_DIM * cc + dd) =
497 OP::locMat(FIELD_DIM * rr, FIELD_DIM * cc);
498 }
499 }
500 }
501
502
504}
505
506template <int FIELD_DIM, IntegrationType I, typename OpBase>
508
509template <int FIELD_DIM, IntegrationType I, typename OpBase>
511
512template <int FIELD_DIM, typename OpBrokenBase>
514 : public OpBrokenBase {
515
517
519 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
520 boost::shared_ptr<MatrixDouble> lagrange_ptr,
521 boost::shared_ptr<double> beta_ptr,
522 boost::shared_ptr<Range> ents_ptr = nullptr)
523 : OP(broken_base_side_data, ents_ptr), scalarBetaPtr(beta_ptr),
524 lagrangePtr(lagrange_ptr) {}
525
527 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
528 boost::shared_ptr<MatrixDouble> lagrange_ptr, double beta,
529 boost::shared_ptr<Range> ents_ptr = nullptr)
530 : OpBrokenSpaceConstrainDFluxImpl(broken_base_side_data, lagrange_ptr,
531 boost::make_shared<double>(beta),
532 ents_ptr) {}
533
534private:
536
537 boost::shared_ptr<double> scalarBetaPtr;
538 boost::shared_ptr<MatrixDouble> lagrangePtr;
539};
540
541template <int FIELD_DIM, typename OpBase>
544 EntitiesFieldData::EntData &row_data) {
546
548 auto get_lagrange_at_pts =
550 *lagrangePtr, OpBase::nbIntegrationPts);
551
553 FTENSOR_INDEX(3, J);
554
555 auto t_w = this->getFTensor0IntegrationWeight();
556 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
557 auto t_lagrange_at_pts = get_lagrange_at_pts();
558
559 auto t_row_base = row_data.getFTensor1N<3>();
560 auto nb_base_functions = row_data.getN().size2() / 3;
561
562 double triangle_scale = 1.0;
563 if (OP::getFEType() == MBTRI)
564 triangle_scale = 0.5;
565
566 if (scalarBetaPtr)
567 triangle_scale *= *scalarBetaPtr;
568
569 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
570 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
571 size_t rr = 0;
572 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
573 t_vec(i) += (triangle_scale * t_w * (t_row_base(J) * t_normal(J))) *
574 t_lagrange_at_pts(i);
575 ++t_row_base;
576 ++t_vec;
577 }
578 for (; rr < nb_base_functions; ++rr)
579 ++t_row_base;
580 ++t_w;
581 ++t_normal;
582 ++t_lagrange_at_pts;
583 }
584
586}
587
588template <int FIELD_DIM, typename OpBase>
590 : public OpBase {
591
592 using OP = OpBase;
593
595 const std::string row_field,
596 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
597 boost::shared_ptr<double> beta_ptr,
598 boost::shared_ptr<Range> ents_ptr = nullptr)
599 : OpBase(row_field, row_field, OpBase::OPROW, ents_ptr),
600 brokenSideDataPtr(broken_side_data_ptr), scalarBetaPtr(beta_ptr) {}
601
603 const std::string row_field,
604 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
605 double beta, boost::shared_ptr<Range> ents_ptr = nullptr)
606 : OpBrokenSpaceConstrainDHybridImpl(row_field, broken_side_data_ptr,
607 boost::make_shared<double>(beta),
608 ents_ptr) {}
609
610private:
611 boost::shared_ptr<double> scalarBetaPtr;
612 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
613 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
614};
615
616template <int FIELD_DIM, typename OpBase>
619 EntitiesFieldData::EntData &row_data) {
621
623 FTENSOR_INDEX(3, J);
624
625 OP::locF.resize(row_data.getIndices().size(), false);
626 OP::locF.clear();
627
628 double triangle_scale = 1.0;
629 if (OP::getFEType() == MBTRI)
630 triangle_scale = 0.5;
631
632 if (scalarBetaPtr)
633 triangle_scale *= *scalarBetaPtr;
634
635 for (auto &bd : *brokenSideDataPtr) {
636 auto t_w = this->getFTensor0IntegrationWeight();
637 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
638 auto t_row_base = row_data.getFTensor0N();
639 auto t_flux = getFTensor2FromMat<FIELD_DIM, 3>(bd.getFlux());
640 auto nb_base_functions = row_data.getN().size2() / 3;
641 auto sense = bd.getSense();
642 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
643 auto t_vec = getFTensor1FromPtr<FIELD_DIM>(&*OP::locF.data().begin());
644 size_t rr = 0;
645 for (; rr != row_data.getIndices().size() / FIELD_DIM; ++rr) {
646 t_vec(i) += (triangle_scale * sense * t_w) * t_row_base * t_normal(J) *
647 t_flux(i, J);
648 ++t_row_base;
649 ++t_vec;
650 }
651 for (; rr < nb_base_functions; ++rr)
652 ++t_row_base;
653 ++t_w;
654 ++t_normal;
655 ++t_flux;
656 }
657 }
658
660}
661
662template <int FIELD_DIM, IntegrationType I, typename OpBase>
664
665template <int FIELD_DIM, IntegrationType I, typename OpBase>
667
668template <typename OpBrokenBase> struct OpBrokenTopoBase : public OpBrokenBase {
670
671protected:
672
674 const std::string row_field,
675 boost::shared_ptr<MatrixDouble> tangent1_diff_ptr,
676 boost::shared_ptr<MatrixDouble> tangent2_diff_ptr,
677 SmartPetscObj<Vec> assemble_vec, Tag th,
678 boost::shared_ptr<Range> ents_ptr = nullptr)
679 : OP(row_field, row_field, OP::OPROW, ents_ptr),
680 tangent1DiffPtr(tangent1_diff_ptr),
681 tangent2DiffPtr(tangent2_diff_ptr), assembleVec(assemble_vec),
682 thGradTag(th) {}
683
686 if (!this->timeScalingFun.empty())
687 this->locF *= this->timeScalingFun(this->getFEMethod()->ts_t);
688 if (!this->feScalingFun.empty())
689 this->locF *= this->feScalingFun(this->getFEMethod());
690 if (assembleVec) {
691 auto *vec_ptr = this->locF.data().data();
692 const auto nb_dofs = row_data.getIndices().size();
693 auto *ind_ptr = row_data.getIndices().data().data();
694 return VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
695 }
696 if (thGradTag) {
697 const auto field_ents = row_data.getFieldEntities();
698 std::vector<EntityHandle> ents(field_ents.size());
699 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
700 [](const auto *fe) { return fe->getEnt(); });
701 if (field_ents.empty())
703 if (type_from_handle(ents[0]) != MBVERTEX)
705 auto &moab = this->getMoab();
706 VectorDouble topo_values(this->locF.size());
707 CHKERR moab.tag_get_data(thGradTag, ents.data(), ents.size(),
708 topo_values.data().data());
709 topo_values += this->locF;
710 CHKERR moab.tag_set_data(thGradTag, ents.data(), ents.size(),
711 topo_values.data().data());
712 }
714 }
715
716 boost::shared_ptr<MatrixDouble> tangent1DiffPtr;
717 boost::shared_ptr<MatrixDouble> tangent2DiffPtr;
720};
721
722template <typename OpBase>
724 : public OpBrokenTopoBase<OpBase> {
725
727
729 const std::string row_field,
730 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
731 boost::shared_ptr<MatrixDouble> lamgrange_ptr,
732 boost::shared_ptr<MatrixDouble> tangent1_ptr,
733 boost::shared_ptr<MatrixDouble> tangent2_ptr,
734 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
735 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
736 boost::shared_ptr<Range> ents_ptr = nullptr)
737 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
738 brokenSideDataPtr(broken_side_data_ptr), lagrangePtr(lamgrange_ptr),
739 scalarBetaPtr(beta_ptr), dJPtr(dJ_ptr) {}
740
741private:
742 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
743 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
744 boost::shared_ptr<MatrixDouble> lagrangePtr;
745 boost::shared_ptr<double> scalarBetaPtr;
746 boost::shared_ptr<double> dJPtr;
747};
748
749template <typename OpBase>
752 EntitiesFieldData::EntData &row_data) {
754
755 // That is used for testing the H(div) contravariant Piola trace P.n dA
756 // invariance with respect to material map variations. The variation of the
757 // normal is cancelled by the variation of bd.getVarFlux()
758
760 auto get_lagrange_at_pts =
761 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
762 *lagrangePtr, OpBase::nbIntegrationPts);
763
764 FTENSOR_INDEX(3, J);
765 FTENSOR_INDEX(3, i);
766 FTENSOR_INDEX(3, j);
767 FTENSOR_INDEX(3, k);
768
769 auto get_ftensor1 = [](MatrixDouble &m) {
771 &m(0, 0), &m(0, 1), &m(0, 2));
772 };
773
774 double triangle_scale = 1.0;
775 if (OP::getFEType() == MBTRI)
776 triangle_scale = 0.5;
777
778 double d_loc_J = 0.0;
779
780 for (auto &bd : *brokenSideDataPtr) {
781 auto sense = bd.getSense();
782
783 if (dJPtr) {
784 auto t_w = this->getFTensor0IntegrationWeight();
785 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
786 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
787 auto t_lagrange_at_pts = get_lagrange_at_pts();
788 auto t_adjoint_lambda = getFTensor2FromMat<3, 3>(bd.getVarFlux());
789
790 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
791 FTensor::Tensor1<double, 3> t_tmp_normal;
792 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
793 d_loc_J += (sense * triangle_scale * t_w) *
794 (t_lagrange_at_pts(i) *
795 (t_adjoint_lambda(i, J) * t_tmp_normal(J)));
796 ++t_w;
797 ++t_t1;
798 ++t_t2;
799 ++t_lagrange_at_pts;
800 ++t_adjoint_lambda;
801 }
802 }
803 }
804
805 // The H(div) contravariant Piola trace P.n dA is material-map invariant.
806 // The normal variation is cancelled by the variation of bd.getVarFlux().
807 if (dJPtr) {
808 if (scalarBetaPtr)
809 d_loc_J *= *scalarBetaPtr;
810 *dJPtr += d_loc_J;
811 }
812
814}
815
816template <typename OpBase>
818 : public OpBrokenTopoBase<OpBase> {
819
821
823 const std::string row_field,
824 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
825 boost::shared_ptr<MatrixDouble> adjoint_hybrid_ptr,
826 boost::shared_ptr<MatrixDouble> tangent1_ptr,
827 boost::shared_ptr<MatrixDouble> tangent2_ptr,
828 boost::shared_ptr<double> beta_ptr, SmartPetscObj<Vec> assemble_vec,
829 Tag th, boost::shared_ptr<double> dJ_ptr = nullptr,
830 boost::shared_ptr<Range> ents_ptr = nullptr)
831 : OP(row_field, tangent1_ptr, tangent2_ptr, assemble_vec, th, ents_ptr),
832 brokenSideDataPtr(broken_side_data_ptr),
833 adjointHybridPtr(adjoint_hybrid_ptr), scalarBetaPtr(beta_ptr),
834 dJPtr(dJ_ptr) {}
835
836private:
837 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
838 boost::shared_ptr<MatrixDouble> adjointHybridPtr;
839 boost::shared_ptr<double> scalarBetaPtr;
840 boost::shared_ptr<double> dJPtr;
841 MoFEMErrorCode iNtegrate(EntitiesFieldData::EntData &row_data);
842};
843
844template <typename OpBase>
846 3, GAUSS, OpBase>::iNtegrate(EntitiesFieldData::EntData &row_data) {
848
850 auto get_adjoint_lambda_at_pts =
851 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::get(
852 *adjointHybridPtr, OpBase::nbIntegrationPts);
853
854 FTENSOR_INDEX(3, i);
855 FTENSOR_INDEX(3, j);
856 FTENSOR_INDEX(3, k);
857 FTENSOR_INDEX(3, J);
858
859 OP::locF.resize(row_data.getIndices().size(), false);
860 OP::locF.clear();
861
862 auto get_ftensor1 = [](MatrixDouble &m) {
864 &m(0, 0), &m(0, 1), &m(0, 2));
865 };
866
867 double d_loc_J = 0;
868
869 double triangle_scale = 1.0;
870 if (OP::getFEType() == MBTRI)
871 triangle_scale = 0.5;
872
873 for (auto &bd : *brokenSideDataPtr) {
874 auto sense = bd.getSense();
875
876 // This is used for testing the H(div) contravariant Piola trace P.n dA invariance
877 // with respect to material map variations. The variation of the normal is
878 // cancelled by the variation of bd.getFlux() in the adjoint lambda at pts
879
880 if (dJPtr) {
881 auto t_w = this->getFTensor0IntegrationWeight();
882 auto t_t1 = get_ftensor1(*this->tangent1DiffPtr);
883 auto t_t2 = get_ftensor1(*this->tangent2DiffPtr);
884 auto t_flux = getFTensor2FromMat<3, 3>(bd.getFlux());
885 auto t_adjoint_lambda_at_pts = get_adjoint_lambda_at_pts();
886 for (size_t gg = 0; gg != OpBase::nbIntegrationPts; ++gg) {
887 FTensor::Tensor1<double, 3> t_tmp_normal;
888 t_tmp_normal(j) = FTensor::levi_civita(i, j, k) * t_t1(k) * t_t2(i);
889 d_loc_J +=
890 (sense * triangle_scale * t_w) *
891 (t_adjoint_lambda_at_pts(i) * (t_flux(i, J) * t_tmp_normal(J)));
892 ++t_w;
893 ++t_t1;
894 ++t_t2;
895 ++t_flux;
896 ++t_adjoint_lambda_at_pts;
897 }
898 }
899 }
900
901 // The L2 hybrid multiplier is not material-map transformed, while the H(div)
902 // contravariant Piola trace P.n dA is invariant.
903 if (dJPtr) {
904 if (scalarBetaPtr)
905 d_loc_J *= *scalarBetaPtr;
906 *dJPtr += d_loc_J;
907 }
908
910}
911
912} // namespace MoFEM
913
914#endif // __FORMSBROKENSPACECONSTRAINTIMPL_HPP__
std::string type
PetscInt size
#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.
virtual boost::shared_ptr< MatrixDouble > & getNSharedPtr(const FieldApproximationBase base, const BaseDerivatives derivative)
Get shared pointer to base functions with derivatives.
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.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
FieldApproximationBase bAse
Field approximation base.
OpType
Controls loop over entities on element.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
structure to get information from mofem into EntitiesFieldData
typename EleOp::OpType OpType
boost::shared_ptr< Range > entsPtr
Entities on which element is run.
int nbIntegrationPts
number of integration points
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenBaseSideData
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)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
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 ForcesAndSourcesCore::UserDataOperator::OpType op_type, 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