14static char help[] =
"...\n\n";
34 IntegrationType::GAUSS;
89 std::array<VectorInt, 2>
91 std::array<VectorInt, 2>
119 template <
int FE_DIM>
130 static double get_level_set(
const double x,
const double y,
const double z);
175 boost::shared_ptr<FaceSideEle>
176 getSideFE(boost::shared_ptr<SideData> side_data_ptr);
209 boost::function<
double(
double,
double,
double)> level_fun =
219 boost::function<
double(
double,
double,
double)> vel_fun =
220 get_velocity_potential<FE_DIM>);
295 ->synchroniseEntities(level);
304 return 0.05 * (*maxPtr);
329 ->synchroniseEntities(level);
356 G>::OpSource<1, DIM1 * DIM2>;
360 G>::OpSource<potential_velocity_field_dim, potential_velocity_field_dim>;
362 G>::OpBaseTimesVector<1, DIM1 * DIM2, 1>;
375double LevelSet::get_velocity_potential<2>(
double x,
double y,
double z) {
376 return (x * x - 0.25) * (y * y - 0.25);
380 constexpr double xc = 0.1;
381 constexpr double yc = 0.;
382 constexpr double zc = 0.;
383 constexpr double r = 0.2;
384 return std::sqrt(pow(x - xc, 2) + pow(y - yc, 2) + pow(z - zc, 2)) - r;
392 if constexpr (
debug) {
399 maxPtr = boost::make_shared<double>(0);
416 boost::shared_ptr<MatrixDouble> l_ptr,
417 boost::shared_ptr<MatrixDouble> l_dot_ptr,
418 boost::shared_ptr<MatrixDouble> vel_ptr);
422 boost::shared_ptr<MatrixDouble>
lPtr;
429 boost::shared_ptr<MatrixDouble> vel_ptr);
439 boost::shared_ptr<FaceSideEle> side_fe_ptr);
445 boost::shared_ptr<FaceSideEle>
453 boost::shared_ptr<FaceSideEle> side_fe_ptr);
459 boost::shared_ptr<FaceSideEle>
465int main(
int argc,
char *argv[]) {
468 const char param_file[] =
"param_file.petsc";
474 moab::Core moab_core;
475 moab::Interface &moab = moab_core;
482 DMType dm_name =
"DMMOFEM";
486 auto core_log = logging::core::get();
512 simple->getAddSkeletonFE() =
true;
513 simple->getAddBoundaryFE() =
true;
520 auto set_problem_bit = [&]() {
524 start_mask[s] =
true;
544 if constexpr (
debug) {
546 CHKERR bit_mng->writeBitLevelByDim(
548 (proc_str +
"level_base.vtk").c_str(),
"VTK",
"");
584 boost::shared_ptr<MatrixDouble> l_ptr,
585 boost::shared_ptr<MatrixDouble> l_dot_ptr,
586 boost::shared_ptr<MatrixDouble> vel_ptr)
588 lPtr(l_ptr), lDotPtr(l_dot_ptr), velPtr(vel_ptr) {}
591 boost::shared_ptr<MatrixDouble> vel_ptr)
599 boost::shared_ptr<SideData> side_data_ptr,
600 boost::shared_ptr<FaceSideEle> side_fe_ptr)
602 sideDataPtr(side_data_ptr), sideFEPtr(side_fe_ptr) {}
605 boost::shared_ptr<SideData> side_data_ptr,
606 boost::shared_ptr<FaceSideEle> side_fe_ptr)
608 sideDataPtr(side_data_ptr), sideFEPtr(side_fe_ptr) {}
613 const auto nb_int_points = getGaussPts().size2();
614 const auto nb_dofs = data.
getIndices().size();
615 const auto nb_base_func = data.
getN().size2();
617 auto t_l = getFTensor2FromMat<DIM1, DIM2>(*lPtr);
618 auto t_l_dot = getFTensor2FromMat<DIM1, DIM2>(*lDotPtr);
619 auto t_vel = getFTensor1FromMat<SPACE_DIM>(*velPtr);
624 auto t_w = getFTensor0IntegrationWeight();
625 for (
auto gg = 0; gg != nb_int_points; ++gg) {
626 const auto alpha = t_w * getMeasure();
628 t_res0(
I,
J) = alpha * t_l_dot(
I,
J);
630 t_res1(
i,
I,
J) = (alpha * t_l(
I,
J)) * t_vel(
i);
636 auto &nf = this->locF;
637 auto t_nf = getFTensor2FromPtr<DIM1, DIM2>(&*nf.begin());
640 for (; rr != nb_dofs; ++rr) {
641 t_nf(
I,
J) += t_res0(
I,
J) * t_base - t_res1(
i,
I,
J) * t_diff_base(
i);
646 for (; rr < nb_base_func; ++rr) {
659 const auto nb_int_points = getGaussPts().size2();
660 const auto nb_base_func = row_data.
getN().size2();
661 const auto nb_row_dofs = row_data.
getIndices().size();
662 const auto nb_col_dofs = col_data.
getIndices().size();
664 auto t_vel = getFTensor1FromMat<SPACE_DIM>(*velPtr);
669 auto t_w = getFTensor0IntegrationWeight();
670 for (
auto gg = 0; gg != nb_int_points; ++gg) {
671 const auto alpha = t_w * getMeasure();
672 const auto beta = alpha * getTSa();
675 auto &mat = this->locMat;
678 for (; rr != nb_row_dofs; ++rr) {
680 auto t_mat = getFTensor2FromPtr<DIM1, DIM2>(&mat(rr *
DIM1, 0));
681 for (
int cc = 0; cc != nb_col_dofs; ++cc) {
683 (beta * t_row_base - alpha * (t_row_diff_base(
i) * t_vel(
i))) *
691 for (; rr < nb_base_func; ++rr) {
708 CHKERR loopSideFaces(
"dFE", *sideFEPtr);
709 const auto in_the_loop =
710 sideFEPtr->nInTheLoop;
712 auto not_side = [](
auto s) {
718 &*base_mat.data().begin());
721 if (in_the_loop > 0) {
724 auto t_normal = getFTensor1Normal();
725 const auto nb_gauss_pts = getGaussPts().size2();
730 const auto nb_rows = sideDataPtr->indicesRowSideMap[s0].size();
734 resSkelton.resize(nb_rows,
false);
738 const auto opposite_s0 = not_side(s0);
739 const auto sense_row = sideDataPtr->senseMap[s0];
741 const auto opposite_sense_row = sideDataPtr->senseMap[opposite_s0];
742 if (sense_row * opposite_sense_row > 0)
744 "Should be opposite sign");
748 const auto nb_row_base_functions =
749 sideDataPtr->rowBaseSideMap[s0].size2();
751 auto t_w = getFTensor0IntegrationWeight();
753 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
LEFT_SIDE]),
754 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
RIGHT_SIDE]));
756 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
LEFT_SIDE]),
757 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
RIGHT_SIDE]));
760 for (
auto &t_l : arr_t_l)
762 for (
auto &t_vel : arr_t_vel)
767 if (nb_gauss_pts != sideDataPtr->rowBaseSideMap[s0].size1())
769 "Inconsistent number of DOFs");
772 auto t_row_base =
get_ntensor(sideDataPtr->rowBaseSideMap[s0]);
773 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
776 const auto dot = sense_row * (t_normal(
i) * t_vel(
i));
777 const auto l_upwind_side = (dot > 0) ? s0 : opposite_s0;
778 const auto l_upwind = arr_t_l[l_upwind_side];
780 t_res(
I,
J) = t_w * dot * l_upwind(
I,
J);
784 auto t_res_skeleton =
785 getFTensor2FromPtr<DIM1, DIM2>(&*resSkelton.data().begin());
787 for (; rr != nb_rows; ++rr) {
788 t_res_skeleton(
I,
J) += t_row_base * t_res(
I,
J);
792 for (; rr < nb_row_base_functions; ++rr) {
797 CHKERR ::VecSetValues(getTSf(),
798 sideDataPtr->indicesRowSideMap[s0].size(),
799 &*sideDataPtr->indicesRowSideMap[s0].begin(),
800 &*resSkelton.begin(), ADD_VALUES);
814 CHKERR loopSideFaces(
"dFE", *sideFEPtr);
815 const auto in_the_loop =
816 sideFEPtr->nInTheLoop;
818 auto not_side = [](
auto s) {
824 &*base_mat.data().begin());
827 if (in_the_loop > 0) {
830 auto t_normal = getFTensor1Normal();
831 const auto nb_gauss_pts = getGaussPts().size2();
836 const auto nb_rows = sideDataPtr->indicesRowSideMap[s0].size();
841 const auto opposite_s0 = not_side(s0);
842 const auto sense_row = sideDataPtr->senseMap[s0];
845 const auto nb_row_base_functions =
846 sideDataPtr->rowBaseSideMap[s0].size2();
851 const auto nb_cols = sideDataPtr->indicesColSideMap[s1].size();
854 matSkeleton.resize(nb_rows, nb_cols,
false);
857 auto t_w = getFTensor0IntegrationWeight();
859 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
LEFT_SIDE]),
860 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
RIGHT_SIDE]));
863 for (
auto &t_vel : arr_t_vel)
867 auto t_row_base =
get_ntensor(sideDataPtr->rowBaseSideMap[s0]);
868 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
872 const auto dot = sense_row * (t_normal(
i) * t_vel(
i));
873 const auto l_upwind_side = (dot > 0) ? s0 : opposite_s0;
875 t_res(
I,
J) = t_w * dot;
879 if (s1 == l_upwind_side) {
880 for (; rr != nb_rows; ++rr) {
881 auto get_ntensor = [](
auto &base_mat,
auto gg,
auto bb) {
882 double *ptr = &base_mat(gg, bb);
886 get_ntensor(sideDataPtr->colBaseSideMap[s1], gg, 0);
888 auto t_mat_skeleton =
889 getFTensor2FromPtr<DIM1, DIM2>(&matSkeleton(rr *
DIM1, 0));
891 t_res_row(
I,
J) = t_res(
I,
J) * t_row_base;
894 for (
size_t cc = 0; cc != nb_cols; ++cc) {
895 t_mat_skeleton(
I,
J) += t_res_row(
I,
J) * t_col_base;
901 for (; rr < nb_row_base_functions; ++rr) {
906 CHKERR ::MatSetValues(getTSB(),
907 sideDataPtr->indicesRowSideMap[s0].size(),
908 &*sideDataPtr->indicesRowSideMap[s0].begin(),
909 sideDataPtr->indicesColSideMap[s1].size(),
910 &*sideDataPtr->indicesColSideMap[s1].begin(),
911 &*matSkeleton.data().begin(), ADD_VALUES);
921 auto get_parent_vel_this = [&]() {
922 auto parent_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
924 parent_fe_ptr->getOpPtrVector(), {potential_velocity_space});
925 parent_fe_ptr->getOpPtrVector().push_back(
928 return parent_fe_ptr;
931 auto get_parents_vel_fe_ptr = [&](
auto this_fe_ptr) {
932 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
934 parents_elems_ptr_vec.emplace_back(
935 boost::make_shared<DomainParentEle>(
mField));
937 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
942 return parents_elems_ptr_vec[0];
945 auto this_fe_ptr = get_parent_vel_this();
946 auto parent_fe_ptr = get_parents_vel_fe_ptr(this_fe_ptr);
958 pip->getOpDomainRhsPipeline().clear();
960 pip->setDomainLhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
961 pip->setDomainRhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
963 pip->getDomainLhsFE()->exeTestHook = [&](
FEMethod *fe_ptr) {
964 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
967 pip->getDomainRhsFE()->exeTestHook = [&](
FEMethod *fe_ptr) {
968 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
972 auto l_ptr = boost::make_shared<MatrixDouble>();
973 auto l_dot_ptr = boost::make_shared<MatrixDouble>();
974 auto vel_ptr = boost::make_shared<MatrixDouble>();
979 pip->getOpDomainRhsPipeline().push_back(
981 pip->getOpDomainRhsPipeline().push_back(
983 pip->getOpDomainRhsPipeline().push_back(
989 pip->getOpDomainLhsPipeline().push_back(
new OpLhsDomain(
"L", vel_ptr));
994boost::shared_ptr<FaceSideEle>
998 auto l_ptr = boost::make_shared<MatrixDouble>();
999 auto vel_ptr = boost::make_shared<MatrixDouble>();
1002 OpSideData(boost::shared_ptr<SideData> side_data_ptr)
1004 sideDataPtr(side_data_ptr) {
1005 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE],
false);
1006 for (
auto t = moab::CN::TypeDimensionMap[
FE_DIM].first;
1007 t <= moab::CN::TypeDimensionMap[
FE_DIM].second; ++
t)
1008 doEntities[
t] =
true;
1012 MoFEMErrorCode doWork(
int row_side,
int col_side, EntityType row_type,
1013 EntityType col_type,
EntData &row_data,
1016 if ((CN::Dimension(row_type) ==
FE_DIM) &&
1017 (CN::Dimension(col_type) ==
FE_DIM)) {
1019 auto reset = [&](
auto nb_in_loop) {
1020 sideDataPtr->feSideHandle[nb_in_loop] = 0;
1021 sideDataPtr->indicesRowSideMap[nb_in_loop].clear();
1022 sideDataPtr->indicesColSideMap[nb_in_loop].clear();
1023 sideDataPtr->rowBaseSideMap[nb_in_loop].clear();
1024 sideDataPtr->colBaseSideMap[nb_in_loop].clear();
1025 sideDataPtr->senseMap[nb_in_loop] = 0;
1028 const auto nb_in_loop = getFEMethod()->nInTheLoop;
1029 if (nb_in_loop == 0)
1030 for (
auto s : {0, 1})
1033 sideDataPtr->currentFESide = nb_in_loop;
1034 sideDataPtr->senseMap[nb_in_loop] = getSkeletonSense();
1044 boost::shared_ptr<SideData> sideDataPtr;
1049 OpSideDataOnParent(boost::shared_ptr<SideData> side_data_ptr,
1050 boost::shared_ptr<MatrixDouble> l_ptr,
1051 boost::shared_ptr<MatrixDouble> vel_ptr)
1053 sideDataPtr(side_data_ptr), lPtr(l_ptr), velPtr(vel_ptr) {
1054 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE],
false);
1055 for (
auto t = moab::CN::TypeDimensionMap[
FE_DIM].first;
1056 t <= moab::CN::TypeDimensionMap[
FE_DIM].second; ++
t)
1057 doEntities[
t] =
true;
1061 MoFEMErrorCode doWork(
int row_side,
int col_side, EntityType row_type,
1062 EntityType col_type,
EntData &row_data,
1066 if ((CN::Dimension(row_type) ==
FE_DIM) &&
1067 (CN::Dimension(col_type) ==
FE_DIM)) {
1068 const auto nb_in_loop = sideDataPtr->currentFESide;
1069 sideDataPtr->feSideHandle[nb_in_loop] = getFEEntityHandle();
1070 sideDataPtr->indicesRowSideMap[nb_in_loop] = row_data.
getIndices();
1071 sideDataPtr->indicesColSideMap[nb_in_loop] = col_data.
getIndices();
1072 sideDataPtr->rowBaseSideMap[nb_in_loop] = row_data.
getN();
1073 sideDataPtr->colBaseSideMap[nb_in_loop] = col_data.
getN();
1074 (sideDataPtr->lVec)[nb_in_loop] = *lPtr;
1075 (sideDataPtr->velMat)[nb_in_loop] = *velPtr;
1078 if ((sideDataPtr->lVec)[nb_in_loop].size1() !=
1079 (sideDataPtr->velMat)[nb_in_loop].size1())
1081 "Wrong number of integaration pts %zu != %zu",
1082 (sideDataPtr->lVec)[nb_in_loop].size1(),
1083 (sideDataPtr->velMat)[nb_in_loop].size1());
1084 if ((sideDataPtr->velMat)[nb_in_loop].size2() !=
SPACE_DIM)
1086 "Wrong size of velocity vector size = %zu",
1087 (sideDataPtr->velMat)[nb_in_loop].size2());
1091 (sideDataPtr->lVec)[1] = sideDataPtr->lVec[0];
1092 (sideDataPtr->velMat)[1] = (sideDataPtr->velMat)[0];
1095 if (sideDataPtr->rowBaseSideMap[0].size1() !=
1096 sideDataPtr->rowBaseSideMap[1].size1()) {
1098 "Wrong number of integration pt %zu != %zu",
1099 sideDataPtr->rowBaseSideMap[0].size1(),
1100 sideDataPtr->rowBaseSideMap[1].size1());
1102 if (sideDataPtr->colBaseSideMap[0].size1() !=
1103 sideDataPtr->colBaseSideMap[1].size1()) {
1105 "Wrong number of integration pt");
1118 boost::shared_ptr<SideData> sideDataPtr;
1119 boost::shared_ptr<MatrixDouble> lPtr;
1120 boost::shared_ptr<MatrixDouble> velPtr;
1124 auto get_parent_this = [&]() {
1125 auto parent_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1127 parent_fe_ptr->getOpPtrVector(), {L2});
1128 parent_fe_ptr->getOpPtrVector().push_back(
1130 parent_fe_ptr->getOpPtrVector().push_back(
1131 new OpSideDataOnParent(side_data_ptr, l_ptr, vel_ptr));
1132 return parent_fe_ptr;
1135 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
1136 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
1138 parents_elems_ptr_vec.emplace_back(
1139 boost::make_shared<DomainParentEle>(
mField));
1141 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
1146 return parents_elems_ptr_vec[0];
1151 auto get_side_fe_ptr = [&]() {
1152 auto side_fe_ptr = boost::make_shared<FaceSideEle>(
mField);
1154 auto this_fe_ptr = get_parent_this();
1155 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
1157 side_fe_ptr->getOpPtrVector().push_back(
new OpSideData(side_data_ptr));
1159 side_fe_ptr->getOpPtrVector().push_back(
1167 return get_side_fe_ptr();
1175 pip->getOpSkeletonRhsPipeline().clear();
1177 pip->setSkeletonLhsIntegrationRule([](
int,
int,
int o) {
return 18; });
1178 pip->setSkeletonRhsIntegrationRule([](
int,
int,
int o) {
return 18; });
1180 pip->getSkeletonLhsFE()->exeTestHook = [&](
FEMethod *fe_ptr) {
1181 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1184 pip->getSkeletonRhsFE()->exeTestHook = [&](
FEMethod *fe_ptr) {
1185 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1189 auto side_data_ptr = boost::make_shared<SideData>();
1190 auto side_fe_ptr =
getSideFE(side_data_ptr);
1192 pip->getOpSkeletonRhsPipeline().push_back(
1194 pip->getOpSkeletonLhsPipeline().push_back(
1204 OpErrorSkel(boost::shared_ptr<FaceSideEle> side_fe_ptr,
1205 boost::shared_ptr<SideData> side_data_ptr,
1208 sideFEPtr(side_fe_ptr), sideDataPtr(side_data_ptr),
1209 errorSumPtr(error_sum_ptr), thError(th_error) {}
1215 CHKERR loopSideFaces(
"dFE", *sideFEPtr);
1217 auto nb_gauss_pts = getGaussPts().size2();
1222 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
LEFT_SIDE]),
1223 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
RIGHT_SIDE]));
1225 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
LEFT_SIDE]),
1226 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
RIGHT_SIDE]));
1229 for (
auto &t_l : arr_t_l)
1231 for (
auto &t_vel : arr_t_vel)
1236 auto t_w = getFTensor0IntegrationWeight();
1237 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
1240 e += t_w * getMeasure() * t_diff(
I,
J) * t_diff(
I,
J);
1246 moab::Interface &moab =
1247 getNumeredEntFiniteElementPtr()->getBasicDataPtr()->moab;
1248 const void *tags_ptr[2];
1249 CHKERR moab.tag_get_by_ptr(thError, sideDataPtr->feSideHandle.data(), 2,
1251 for (
auto ff : {0, 1}) {
1252 *((
double *)tags_ptr[ff]) += e;
1254 CHKERR VecSetValue(errorSumPtr, 0, e, ADD_VALUES);
1261 boost::shared_ptr<FaceSideEle> sideFEPtr;
1262 boost::shared_ptr<SideData> sideDataPtr;
1273 MB_TAG_CREAT | MB_TAG_SPARSE,
1276 auto clear_tags = [&]() {
1285 auto evaluate_error = [&]() {
1287 auto skel_fe = boost::make_shared<BoundaryEle>(
mField);
1288 skel_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
1289 auto side_data_ptr = boost::make_shared<SideData>();
1290 auto side_fe_ptr =
getSideFE(side_data_ptr);
1291 skel_fe->getOpPtrVector().push_back(
1292 new OpErrorSkel(side_fe_ptr, side_data_ptr, error_sum_ptr, th_error));
1295 skel_fe->exeTestHook = [&](
FEMethod *fe_ptr) {
1296 return fe_ptr->numeredEntFiniteElementPtr->
getBitRefLevel().test(
1301 simple->getSkeletonFEName(), skel_fe);
1306 auto assemble_and_sum = [](
auto vec) {
1314 auto propagate_error_to_parents = [&]() {
1318 auto fe_ptr = boost::make_shared<FEMethod>();
1319 fe_ptr->exeTestHook = [&](
FEMethod *fe_ptr) {
1320 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1324 fe_ptr->preProcessHook = []() {
return 0; };
1325 fe_ptr->postProcessHook = []() {
return 0; };
1326 fe_ptr->operatorHook = [&]() {
1329 auto fe_ent = fe_ptr->numeredEntFiniteElementPtr->getEnt();
1330 auto parent = fe_ptr->numeredEntFiniteElementPtr->getParentEnt();
1331 auto th_parent = fe_ptr->numeredEntFiniteElementPtr->getBasicDataPtr()
1332 ->th_RefParentHandle;
1335 CHKERR moab.tag_get_data(th_error, &fe_ent, 1, &error);
1338 [&](
auto fe_ent,
auto error) {
1341 CHKERR moab.tag_get_by_ptr(th_error, &fe_ent, 1,
1342 (
const void **)&e_ptr);
1346 CHKERR moab.tag_get_data(th_parent, &fe_ent, 1, &parent);
1347 if (parent != fe_ent && parent)
1348 CHKERR add_error(parent, *e_ptr);
1353 CHKERR add_error(parent, error);
1368 return std::make_tuple(assemble_and_sum(error_sum_ptr), th_error);
1386 DivergenceVol(boost::shared_ptr<MatrixDouble> l_ptr,
1387 boost::shared_ptr<MatrixDouble> vel_ptr,
1389 :
DomainEleOp(
"L", DomainEleOp::OPROW), lPtr(l_ptr), velPtr(vel_ptr),
1394 const auto nb_dofs = data.
getIndices().size();
1396 const auto nb_gauss_pts = getGaussPts().size2();
1397 const auto t_w = getFTensor0IntegrationWeight();
1399 auto t_l = getFTensor2FromMat<DIM1, DIM2>(*lPtr);
1400 auto t_vel = getFTensor1FromMat<SPACE_DIM>(*velPtr);
1402 for (
auto gg = 0; gg != nb_gauss_pts; ++gg) {
1403 for (
int rr = 0; rr != nb_dofs; ++rr) {
1404 div += getMeasure() * t_w * t_l(
I,
I) * (t_diff(
i) * t_vel(
i));
1411 CHKERR VecSetValue(divVec, 0, div, ADD_VALUES);
1417 boost::shared_ptr<MatrixDouble> lPtr;
1418 boost::shared_ptr<MatrixDouble> velPtr;
1427 DivergenceSkeleton(boost::shared_ptr<SideData> side_data_ptr,
1428 boost::shared_ptr<FaceSideEle> side_fe_ptr,
1431 sideDataPtr(side_data_ptr), sideFEPtr(side_fe_ptr), divVec(div_vec) {}
1438 &*base_mat.data().begin());
1441 auto not_side = [](
auto s) {
1446 CHKERR loopSideFaces(
"dFE", *sideFEPtr);
1447 const auto in_the_loop =
1448 sideFEPtr->nInTheLoop;
1450 auto t_normal = getFTensor1Normal();
1451 const auto nb_gauss_pts = getGaussPts().size2();
1453 const auto nb_dofs = sideDataPtr->indicesRowSideMap[s0].size();
1455 auto t_base =
get_ntensor(sideDataPtr->rowBaseSideMap[s0]);
1456 auto nb_row_base_functions = sideDataPtr->rowBaseSideMap[s0].size2();
1457 auto side_sense = sideDataPtr->senseMap[s0];
1458 auto opposite_s0 = not_side(s0);
1461 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
LEFT_SIDE]),
1462 getFTensor2FromMat<DIM1, DIM2>(sideDataPtr->lVec[
RIGHT_SIDE]));
1464 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
LEFT_SIDE]),
1465 getFTensor1FromMat<SPACE_DIM>(sideDataPtr->velMat[
RIGHT_SIDE]));
1468 for (
auto &t_l : arr_t_l)
1470 for (
auto &t_vel : arr_t_vel)
1476 auto t_w = getFTensor0IntegrationWeight();
1477 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
1481 const auto dot = (t_normal(
i) * t_vel(
i)) * side_sense;
1482 const auto l_upwind_side = (dot > 0) ? s0 : opposite_s0;
1483 const auto l_upwind =
1484 arr_t_l[l_upwind_side];
1488 auto res = t_w * l_upwind(
I,
I) * dot;
1492 for (; rr != nb_dofs; ++rr) {
1493 div += t_base * res;
1496 for (; rr < nb_row_base_functions; ++rr) {
1500 CHKERR VecSetValue(divVec, 0, div, ADD_VALUES);
1510 boost::shared_ptr<SideData> sideDataPtr;
1511 boost::shared_ptr<FaceSideEle> sideFEPtr;
1512 boost::shared_ptr<MatrixDouble> velPtr;
1516 auto vol_fe = boost::make_shared<DomainEle>(
mField);
1517 auto skel_fe = boost::make_shared<BoundaryEle>(
mField);
1519 vol_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
1520 skel_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
1525 auto l_ptr = boost::make_shared<MatrixDouble>();
1526 auto vel_ptr = boost::make_shared<MatrixDouble>();
1527 auto side_data_ptr = boost::make_shared<SideData>();
1528 auto side_fe_ptr =
getSideFE(side_data_ptr);
1532 vol_fe->getOpPtrVector().push_back(
1535 vol_fe->getOpPtrVector().push_back(
1536 new DivergenceVol(l_ptr, vel_ptr, div_vol_vec));
1538 skel_fe->getOpPtrVector().push_back(
1539 new DivergenceSkeleton(side_data_ptr, side_fe_ptr, div_skel_vec));
1551 [](
double x,
double y,
double) {
return x - y; });
1553 [](
double x,
double y,
double) {
return x - y; });
1555 vol_fe->exeTestHook = [&](
FEMethod *fe_ptr) {
1556 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1559 skel_fe->exeTestHook = [&](
FEMethod *fe_ptr) {
1560 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1568 auto assemble_and_sum = [](
auto vec) {
1576 auto div_vol = assemble_and_sum(div_vol_vec);
1577 auto div_skel = assemble_and_sum(div_skel_vec);
1579 auto eps = std::abs((div_vol - div_skel) / (div_vol + div_skel));
1581 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Testing divergence volume: " << div_vol;
1582 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Testing divergence skeleton: " << div_skel
1583 <<
" relative difference: " <<
eps;
1585 constexpr double eps_err = 1e-6;
1588 "No consistency between skeleton integral and volume integral");
1606 auto post_proc = [&](
auto dm,
auto f_res,
auto out_name) {
1609 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
1611 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1614 auto l_vec = boost::make_shared<VectorDouble>();
1615 post_proc_fe->getOpPtrVector().push_back(
1618 post_proc_fe->getOpPtrVector().push_back(
1622 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1635 post_proc_fe->writeFile(out_name);
1639 constexpr double eps = 1e-4;
1642 opt->setRandomFields(
simple->getDM(), {{
"L", {-1, 1}}, {
"V", {-1, 1}}});
1643 auto dot_x = opt->setRandomFields(
simple->getDM(), {{
"L", {-1, 1}}});
1644 auto diff_x = opt->setRandomFields(
simple->getDM(), {{
"L", {-1, 1}}});
1646 auto test_domain_ops = [&](
auto fe_name,
auto lhs_pipeline,
1647 auto rhs_pipeline) {
1650 auto diff_res = opt->checkCentralFiniteDifference(
1651 simple->getDM(), fe_name, rhs_pipeline, lhs_pipeline, x, dot_x,
1654 if constexpr (
debug) {
1658 CHKERR post_proc(
simple->getDM(), diff_res,
"tangent_op_error.h5m");
1664 CHKERR VecNorm(diff_res, NORM_2, &fnorm);
1666 "Test consistency of tangent matrix %3.4e", fnorm);
1668 constexpr double err = 1e-9;
1671 "Norm of directional derivative too large err = %3.4e", fnorm);
1676 CHKERR test_domain_ops(
simple->getDomainFEName(), pip->getDomainLhsFE(),
1677 pip->getDomainRhsFE());
1678 CHKERR test_domain_ops(
simple->getSkeletonFEName(), pip->getSkeletonLhsFE(),
1679 pip->getSkeletonRhsFE());
1685 boost::function<
double(
double,
double,
double)> level_fun) {
1694 boost::shared_ptr<FEMethod> lhs_fe = boost::make_shared<DomainEle>(
mField);
1695 boost::shared_ptr<FEMethod> rhs_fe = boost::make_shared<DomainEle>(
mField);
1696 auto swap_fe = [&]() {
1697 lhs_fe.swap(pip->getDomainLhsFE());
1698 rhs_fe.swap(pip->getDomainRhsFE());
1702 pip->setDomainLhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1703 pip->setDomainRhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1715 CHKERR prb_mng->removeDofsOnEntities(
"LEVELSET_POJECTION",
"L",
1717 auto test_bit_ele = [&](
FEMethod *fe_ptr) {
1718 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1721 pip->getDomainLhsFE()->exeTestHook = test_bit_ele;
1722 pip->getDomainRhsFE()->exeTestHook = test_bit_ele;
1728 pip->getOpDomainLhsPipeline().push_back(
new OpMassLL(
"L",
"L"));
1729 pip->getOpDomainRhsPipeline().push_back(
new OpSourceL(
"L", level_fun));
1733 auto ksp = pip->createKSP(sub_dm);
1734 CHKERR KSPSetDM(ksp, sub_dm);
1735 CHKERR KSPSetFromOptions(ksp);
1742 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
1743 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
1747 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
1751 std::vector<Tag> tags{th_error};
1753 "PARALLEL=WRITE_PART", &fe_meshset, 1,
1754 &*tags.begin(), tags.size());
1757 auto post_proc = [&](
auto dm,
auto out_name,
auto th_error) {
1760 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
1761 post_proc_fe->setTagsToTransfer({th_error});
1762 post_proc_fe->exeTestHook = test_bit_ele;
1764 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1767 auto l_vec = boost::make_shared<VectorDouble>();
1768 auto l_grad_mat = boost::make_shared<MatrixDouble>();
1770 post_proc_fe->getOpPtrVector(), {L2});
1771 post_proc_fe->getOpPtrVector().push_back(
1773 post_proc_fe->getOpPtrVector().push_back(
1776 post_proc_fe->getOpPtrVector().push_back(
1780 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1784 {{
"GradL", l_grad_mat}},
1793 post_proc_fe->writeFile(out_name);
1797 if constexpr (
debug)
1798 CHKERR post_proc(sub_dm,
"initial_level_set.h5m", th_error);
1806 boost::function<
double(
double,
double,
double)> vel_fun) {
1815 boost::shared_ptr<FEMethod> lhs_fe = boost::make_shared<DomainEle>(
mField);
1816 boost::shared_ptr<FEMethod> rhs_fe = boost::make_shared<DomainEle>(
mField);
1817 auto swap_fe = [&]() {
1818 lhs_fe.swap(pip->getDomainLhsFE());
1819 rhs_fe.swap(pip->getDomainRhsFE());
1823 pip->setDomainLhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1824 pip->setDomainRhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1837 CHKERR prb_mng->removeDofsOnEntities(
"VELOCITY_PROJECTION",
"V",
1840 auto test_bit = [&](
FEMethod *fe_ptr) {
1841 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(0);
1843 pip->getDomainLhsFE()->exeTestHook = test_bit;
1844 pip->getDomainRhsFE()->exeTestHook = test_bit;
1847 {potential_velocity_space});
1849 {potential_velocity_space});
1851 pip->getOpDomainLhsPipeline().push_back(
new OpMassVV(
"V",
"V"));
1852 pip->getOpDomainRhsPipeline().push_back(
new OpSourceV(
"V", vel_fun));
1854 auto ksp = pip->createKSP(sub_dm);
1855 CHKERR KSPSetDM(ksp, sub_dm);
1856 CHKERR KSPSetFromOptions(ksp);
1863 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
1864 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
1867 auto post_proc = [&](
auto dm,
auto out_name) {
1870 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
1871 post_proc_fe->exeTestHook = test_bit;
1873 if constexpr (
FE_DIM == 2) {
1876 post_proc_fe->getOpPtrVector(), {potential_velocity_space});
1880 auto potential_vec = boost::make_shared<VectorDouble>();
1881 auto velocity_mat = boost::make_shared<MatrixDouble>();
1883 post_proc_fe->getOpPtrVector().push_back(
1885 post_proc_fe->getOpPtrVector().push_back(
1889 post_proc_fe->getOpPtrVector().push_back(
1893 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1895 {{
"VelocityPotential", potential_vec}},
1897 {{
"Velocity", velocity_mat}},
1905 "3d case not implemented");
1910 post_proc_fe->writeFile(out_name);
1914 if constexpr (
debug)
1915 CHKERR post_proc(sub_dm,
"initial_velocity_potential.h5m");
1950 auto add_post_proc_fe = [&]() {
1951 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
1956 "Error", 1, MB_TYPE_DOUBLE, th_error, MB_TAG_CREAT | MB_TAG_SPARSE,
1958 post_proc_fe->setTagsToTransfer({th_error});
1960 post_proc_fe->exeTestHook = [&](
FEMethod *fe_ptr) {
1961 return fe_ptr->numeredEntFiniteElementPtr &&
1962 fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1968 auto vel_ptr = boost::make_shared<MatrixDouble>();
1971 post_proc_fe->getOpPtrVector(), {L2});
1974 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1975 auto l_vec = boost::make_shared<VectorDouble>();
1976 post_proc_fe->getOpPtrVector().push_back(
1978 post_proc_fe->getOpPtrVector().push_back(
1982 post_proc_fe->getPostProcMesh(),
1984 post_proc_fe->getMapGaussPts(),
1994 return post_proc_fe;
1997 auto post_proc_fe = add_post_proc_fe();
1999 auto set_time_monitor = [&](
auto dm,
auto ts) {
2000 auto monitor_ptr = boost::make_shared<FEMethod>();
2002 monitor_ptr->preProcessHook = []() {
return 0; };
2003 monitor_ptr->operatorHook = []() {
return 0; };
2004 monitor_ptr->postProcessHook = [dm,
simple, post_proc_fe, monitor_ptr]()
mutable {
2009 "Null pointer for post proc element");
2013 CHKERR post_proc_fe->writeFile(
2015 boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
".h5m");
2019 boost::shared_ptr<FEMethod> null;
2026 auto ts = pip->createTSIM(sub_dm);
2028 auto set_solution = [&](
auto ts) {
2038 auto monitor_pt = set_time_monitor(sub_dm, ts);
2039 CHKERR TSSetFromOptions(ts);
2047 auto ts_pre_step = [](TS ts) {
2053 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2055 auto get_norm = [&](
auto x) {
2057 CHKERR VecNorm(x, NORM_2, &nrm);
2061 auto set_solution = [&](
auto ts) {
2077 <<
"Problem " << prb_ptr->getName() <<
" solution vector norm "
2084 auto refine_and_project = [&](
auto ts) {
2102 ->removeDofsOnEntities(
"ADVECTION",
"L",
BitRefLevel().set(),
2108 auto ts_reset_theta = [&](
auto ts) {
2127 CHKERR refine_and_project(ts);
2128 CHKERR ts_reset_theta(ts);
2133 auto ts_post_step = [](TS ts) {
return 0; };
2135 CHKERR TSSetPreStep(ts, ts_pre_step);
2136 CHKERR TSSetPostStep(ts, ts_post_step);
2138 CHKERR TSSolve(ts, NULL);
2151 [[maybe_unused]]
auto save_range = [&](
const std::string name,
2157 meshset_ptr->get_ptr(), 1);
2162 auto get_refined_elements_meshset = [&](
auto bit,
auto mask) {
2164 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
bit, mask,
FE_DIM, fe_ents);
2168 "get error handle");
2169 std::vector<double> errors(fe_ents.size());
2171 mField.
get_moab().tag_get_data(th_error, fe_ents, &*errors.begin()),
2173 auto it = std::max_element(errors.begin(), errors.end());
2175 MPI_Allreduce(&*it, &max, 1, MPI_DOUBLE, MPI_MAX,
mField.
get_comm());
2176 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Max error: " << max;
2177 auto threshold = wp.getThreshold(max);
2179 std::vector<EntityHandle> fe_to_refine;
2180 fe_to_refine.reserve(fe_ents.size());
2182 auto fe_it = fe_ents.begin();
2183 auto error_it = errors.begin();
2184 for (
auto i = 0;
i != fe_ents.size(); ++
i) {
2185 if (*error_it > threshold) {
2186 fe_to_refine.push_back(*fe_it);
2193 ents.insert_list(fe_to_refine.begin(), fe_to_refine.end());
2195 ents,
nullptr,
NOISY);
2197 auto get_neighbours_by_bridge_vertices = [&](
auto &&ents) {
2201 moab::Interface::UNION);
2206 ents = get_neighbours_by_bridge_vertices(ents);
2212 "add entities to meshset");
2214 (proc_str +
"_fe_to_refine.vtk").c_str(),
"VTK",
"",
2215 meshset_ptr->get_ptr(), 1);
2223 auto refine_mesh = [&](
auto l,
auto &&fe_to_refine) {
2229 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2232 fe_to_refine = intersect(level_ents, fe_to_refine);
2234 level_ents = subtract(level_ents, fe_to_refine);
2237 Range fe_to_refine_children;
2238 bit_mng->updateRangeByChildren(fe_to_refine, fe_to_refine_children);
2240 fe_to_refine_children = fe_to_refine_children.subset_by_dimension(
FE_DIM);
2241 level_ents.merge(fe_to_refine_children);
2243 auto fix_neighbour_level = [&](
auto ll) {
2246 auto level_ll = level_ents;
2251 CHKERR skin.find_skin(0, level_ll,
false, skin_edges);
2254 for (
auto lll = 0; lll <= ll; ++lll) {
2255 CHKERR bit_mng->updateRangeByParent(skin_edges, skin_parents);
2259 for (
auto lll = 0; lll <= ll - 2; ++lll) {
2260 bad_bit[lll] =
true;
2263 Range skin_adj_ents;
2265 skin_parents,
FE_DIM,
false, skin_adj_ents, moab::Interface::UNION);
2268 skin_adj_ents = intersect(skin_adj_ents, level_ents);
2269 if (!skin_adj_ents.empty()) {
2270 level_ents = subtract(level_ents, skin_adj_ents);
2271 Range skin_adj_ents_children;
2272 bit_mng->updateRangeByChildren(skin_adj_ents, skin_adj_ents_children);
2273 level_ents.merge(skin_adj_ents_children);
2278 CHKERR fix_neighbour_level(
l);
2284 for (
auto d = 0; d !=
FE_DIM; ++d) {
2287 level_ents.subset_by_dimension(
FE_DIM), level_ents,
true);
2290 level_ents.subset_by_dimension(
FE_DIM), d,
false, level_ents,
2291 moab::Interface::UNION);
2303 CHKERR bit_mng->writeBitLevelByDim(
2305 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_ref_mesh.vtk")
2314 auto set_skelton_bit = [&](
auto l) {
2319 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2323 Range level_edges_parents;
2324 CHKERR bit_mng->updateRangeByParent(level_edges, level_edges_parents);
2325 level_edges_parents = level_edges_parents.subset_by_dimension(
FE_DIM - 1);
2326 CHKERR bit_mng->filterEntitiesByRefLevel(
2330 auto parent_skeleton = intersect(level_edges, level_edges_parents);
2331 auto skeleton = subtract(level_edges, level_edges_parents);
2336 moab::Interface::UNION);
2344 CHKERR bit_mng->writeBitLevel(
2346 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_skeleton.vtk")
2354 Range level0_current;
2358 Range level0_aggregate;
2364 start_mask[s] =
true;
2365 CHKERR bit_mng->lambdaBitRefLevel(
2380 CHKERR wp.setBits(*
this, 0);
2381 CHKERR wp.runCalcs(*
this, 0);
2383 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Process level: " <<
l;
2384 CHKERR refine_mesh(
l + 1, get_refined_elements_meshset(
2386 CHKERR set_skelton_bit(
l + 1);
2387 CHKERR wp.setAggregateBit(*
this,
l + 1);
2388 CHKERR wp.setBits(*
this,
l + 1);
2389 CHKERR wp.runCalcs(*
this,
l + 1);
2403 auto lhs_fe = boost::make_shared<DomainEle>(
mField);
2404 auto rhs_fe_prj = boost::make_shared<DomainEle>(
mField);
2405 auto rhs_fe_current = boost::make_shared<DomainEle>(
mField);
2407 lhs_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2408 rhs_fe_prj->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2409 rhs_fe_current->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2424 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2427 CHKERR bit_mng->updateRangeByParent(prj_ents, prj_ents);
2429 current_ents = subtract(
2430 current_ents, prj_ents);
2432 auto test_mesh_bit = [&](
FEMethod *fe_ptr) {
2433 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2436 auto test_prj_bit = [&](
FEMethod *fe_ptr) {
2437 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2440 auto test_current_bit = [&](
FEMethod *fe_ptr) {
2441 return current_ents.find(fe_ptr->getFEEntityHandle()) != current_ents.end();
2444 lhs_fe->exeTestHook =
2446 rhs_fe_prj->exeTestHook =
2448 rhs_fe_current->exeTestHook =
2453 CHKERR prb_mng->removeDofsOnEntities(
2454 "DG_PROJECTION",
"L",
BitRefLevel().set(), remove_mask,
nullptr, 0,
2461 lhs_fe->getOpPtrVector().push_back(
2465 auto set_prj_from_child = [&](
auto rhs_fe_prj) {
2467 rhs_fe_prj->getOpPtrVector(), {L2});
2470 auto l_mat = boost::make_shared<MatrixDouble>();
2471 rhs_fe_prj->getOpPtrVector().push_back(
2475 auto get_parent_this = [&]() {
2476 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2477 fe_parent_this->getOpPtrVector().push_back(
new OpScalarFieldL(
"L", l_mat));
2478 return fe_parent_this;
2483 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2484 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2486 parents_elems_ptr_vec.emplace_back(
2487 boost::make_shared<DomainParentEle>(
mField));
2489 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2495 return parents_elems_ptr_vec[0];
2498 auto this_fe_ptr = get_parent_this();
2499 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2500 rhs_fe_prj->getOpPtrVector().push_back(
2507 auto set_prj_from_parent = [&](
auto rhs_fe_current) {
2510 auto l_mat = boost::make_shared<MatrixDouble>();
2513 auto get_parent_this = [&]() {
2514 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2515 fe_parent_this->getOpPtrVector().push_back(
2517 return fe_parent_this;
2521 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2522 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2524 parents_elems_ptr_vec.emplace_back(
2525 boost::make_shared<DomainParentEle>(
mField));
2527 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2533 return parents_elems_ptr_vec[0];
2536 auto this_fe_ptr = get_parent_this();
2537 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2540 reset_op_ptr->doWorkRhsHook = [&](
DataOperator *op_ptr, int, EntityType,
2542 l_mat->resize(
static_cast<DomainEleOp *
>(op_ptr)->getGaussPts().size2(),
2547 rhs_fe_current->getOpPtrVector().push_back(reset_op_ptr);
2548 rhs_fe_current->getOpPtrVector().push_back(
2554 rhs_fe_current->getOpPtrVector().push_back(
new OpScalarFieldL(
"L", l_mat));
2557 set_prj_from_child(rhs_fe_prj);
2558 set_prj_from_parent(rhs_fe_current);
2560 boost::shared_ptr<FEMethod> null_fe;
2563 lhs_fe, null_fe, null_fe);
2567 rhs_fe_current, null_fe, null_fe);
2569 CHKERR KSPSetDM(ksp, sub_dm);
2571 CHKERR KSPSetDM(ksp, sub_dm);
2572 CHKERR KSPSetFromOptions(ksp);
2579 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
2580 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
2584 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2586 auto post_proc = [&](
auto dm,
auto out_name,
auto th_error) {
2589 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
2590 post_proc_fe->setTagsToTransfer({th_error});
2591 post_proc_fe->exeTestHook = test_mesh_bit;
2593 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
2595 auto l_vec = boost::make_shared<VectorDouble>();
2596 auto l_grad_mat = boost::make_shared<MatrixDouble>();
2598 post_proc_fe->getOpPtrVector(), {L2});
2599 post_proc_fe->getOpPtrVector().push_back(
2601 post_proc_fe->getOpPtrVector().push_back(
2604 post_proc_fe->getOpPtrVector().push_back(
2608 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
2612 {{
"GradL", l_grad_mat}},
2621 post_proc_fe->writeFile(out_name);
2625 if constexpr (
debug)
2626 CHKERR post_proc(sub_dm,
"dg_projection.h5m", th_error);
#define MOFEM_LOG_C(channel, severity, format,...)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
ElementsAndOps< SPACE_DIM >::DomainParentEle DomainParentEle
DomainEle::UserDataOperator DomainEleOp
Finire element operator type.
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
BoundaryEle::UserDataOperator BoundaryEleOp
#define CATCH_ERRORS
Catch errors.
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
FieldSpace
approximation spaces
@ L2
field with C-1 continuity
@ HCURL
field with continuous tangents
#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_ATOM_TEST_INVALID
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
PetscErrorCode DMMoFEMKSPSetComputeRHS(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set KSP right hand side evaluation function
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
auto createDMMatrix(DM dm)
Get smart matrix from DM.
PetscErrorCode DMSubDMSetUp_MoFEM(DM subdm)
PetscErrorCode DMMoFEMKSPSetComputeOperators(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
Set KSP operators and push mofem finite element methods.
boost::ptr_deque< UserDataOperator > & getOpDomainLhsPipeline()
Get the Op Domain Lhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpSkeletonLhsPipeline()
Get the Op Skeleton Lhs Pipeline object.
virtual EntityHandle get_finite_element_meshset(const std::string name) const =0
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
FTensor::Index< 'i', SPACE_DIM > i
constexpr int FE_DIM
[Define dimension]
constexpr int skeleton_bit
skeleton elements bit
FTensor::Index< 'I', DIM1 > I
FTensor::Index< 'j', SPACE_DIM > j
constexpr int current_bit
dofs bit used to do calculations
constexpr FieldSpace potential_velocity_space
FTensor::Index< 'k', SPACE_DIM > k
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
FaceSideEle::UserDataOperator FaceSideEleOp
constexpr int aggregate_projection_bit
all bits for projection problem
PipelineManager::ElementsAndOpsByDim< FE_DIM >::FaceSideEle FaceSideEle
DomainEle::UserDataOperator DomainEleOp
LevelSet * level_set_raw_ptr
constexpr int aggregate_bit
all bits for advection problem
constexpr int projection_bit
constexpr IntegrationType G
constexpr size_t potential_velocity_field_dim
FTensor::Index< 'l', 3 > l
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
implementation of Data Operators for Forces and Sources
auto createKSP(MPI_Comm comm)
PetscErrorCode DMMoFEMTSSetMonitor(DM dm, TS ts, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
Set Monitor To TS solver.
PetscErrorCode TsSetIJacobian(TS ts, PetscReal t, Vec u, Vec u_t, PetscReal a, Mat A, Mat B, void *ctx)
Set function evaluating jacobian in TS solver.
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
constexpr auto make_array(Arg &&...arg)
Create Array.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
auto getProblemPtr(DM dm)
get problem pointer from DM
constexpr IntegrationType I
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
auto get_ntensor(T &base_mat)
constexpr double t
plate stiffness
constexpr auto field_name
OpBaseImpl< PETSC, EdgeEleOp > OpBase
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
OpLhsDomain(const std::string field_name, boost::shared_ptr< MatrixDouble > vel_ptr)
MoFEMErrorCode iNtegrate(EntData &row_data, EntData &col_data)
boost::shared_ptr< MatrixDouble > velPtr
boost::shared_ptr< FaceSideEle > sideFEPtr
pointer to element to get data on edge/face sides
boost::shared_ptr< SideData > sideDataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
OpLhsSkeleton(boost::shared_ptr< SideData > side_data_ptr, boost::shared_ptr< FaceSideEle > side_fe_ptr)
boost::shared_ptr< MatrixDouble > lPtr
MoFEMErrorCode iNtegrate(EntData &data)
boost::shared_ptr< MatrixDouble > velPtr
OpRhsDomain(const std::string field_name, boost::shared_ptr< MatrixDouble > l_ptr, boost::shared_ptr< MatrixDouble > l_dot_ptr, boost::shared_ptr< MatrixDouble > vel_ptr)
boost::shared_ptr< MatrixDouble > lDotPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
boost::shared_ptr< SideData > sideDataPtr
OpRhsSkeleton(boost::shared_ptr< SideData > side_data_ptr, boost::shared_ptr< FaceSideEle > side_fe_ptr)
boost::shared_ptr< FaceSideEle > sideFEPtr
pointer to element to get data on edge/face sides
data structure carrying information on skeleton on both sides.
std::array< VectorInt, 2 > indicesColSideMap
indices on columns for left hand-side
std::array< EntityHandle, 2 > feSideHandle
int currentFESide
current side counter
std::array< MatrixDouble, 2 > colBaseSideMap
std::array< MatrixDouble, 2 > rowBaseSideMap
std::array< VectorInt, 2 > indicesRowSideMap
indices on rows for left hand-side
std::array< int, 2 > senseMap
Use peculated errors on all levels while mesh projection.
WrapperClassErrorProjection(boost::shared_ptr< double > max_ptr)
MoFEMErrorCode runCalcs(LevelSet &level_set, int l)
Run calculations.
MoFEMErrorCode setBits(LevelSet &level_set, int l)
Set bit ref level to problem.
double getThreshold(const double max)
MoFEMErrorCode setAggregateBit(LevelSet &level_set, int l)
Add bit to current element, so it aggregate all previious current elements.
boost::shared_ptr< double > maxPtr
Used to execute inital mesh approximation while mesh refinement.
double getThreshold(const double max)
MoFEMErrorCode setAggregateBit(LevelSet &level_set, int l)
Add bit to current element, so it aggregate all previious current elements.
boost::shared_ptr< double > maxPtr
MoFEMErrorCode setBits(LevelSet &level_set, int l)
Set bit ref level to problem.
WrapperClassInitalSolution(boost::shared_ptr< double > max_ptr)
MoFEMErrorCode runCalcs(LevelSet &level_set, int l)
Run calculations.
Wrapper executing stages while mesh refinement.
virtual double getThreshold(const double max)=0
virtual MoFEMErrorCode runCalcs(LevelSet &level_set, int l)=0
Run calculations.
virtual MoFEMErrorCode setAggregateBit(LevelSet &level_set, int l)=0
Add bit to current element, so it aggregate all previious current elements.
virtual MoFEMErrorCode setBits(LevelSet &level_set, int l)=0
Set bit ref level to problem.
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< G >::OpMass< potential_velocity_field_dim, potential_velocity_field_dim > OpMassVV
MoFEM::Interface & mField
integrate skeleton operators on khs
MoFEMErrorCode solveAdvection()
solve advection problem
boost::shared_ptr< double > maxPtr
std::array< MatrixDouble, 2 > MatSideArray
MoFEMErrorCode readMesh()
read mesh
MoFEMErrorCode setUpProblem()
create fields, and set approximation order
MoFEMErrorCode initialiseFieldLevelSet(boost::function< double(double, double, double)> level_fun=get_level_set)
initialise field set
boost::shared_ptr< FaceSideEle > getSideFE(boost::shared_ptr< SideData > side_data_ptr)
create side element to assemble data from sides
MoFEMErrorCode pushOpDomain()
push operators to integrate operators on domain
MoFEMErrorCode runProblem()
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< G >::OpSource< 1, DIM1 *DIM2 > OpSourceL
LevelSet(MoFEM::Interface &m_field)
static double get_velocity_potential(double x, double y, double z)
advection velocity field
MoFEMErrorCode pushOpSkeleton()
push operator to integrate on skeleton
MoFEMErrorCode testOp()
test consistency between tangent matrix and the right hand side vectors
MoFEMErrorCode dgProjection(const int prj_bit=projection_bit)
dg level set projection
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< G >::OpMass< 1, DIM1 *DIM2 > OpMassLL
static double get_level_set(const double x, const double y, const double z)
inital level set, i.e. advected field
MoFEMErrorCode refineMesh(WrapperClass &&wp)
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< G >::OpBaseTimesVector< 1, DIM1 *DIM2, 1 > OpScalarFieldL
ForcesAndSourcesCore::UserDataOperator * getZeroLevelVelOp(boost::shared_ptr< MatrixDouble > vel_ptr)
Get operator calculating velocity on coarse mesh.
std::tuple< double, Tag > evaluateError()
evaluate error
MoFEMErrorCode testSideFE()
test integration side elements
SmartPetscObj< Vec > tsSolutionVec
MoFEMErrorCode initialiseFieldVelocity(boost::function< double(double, double, double)> vel_fun=get_velocity_potential< FE_DIM >)
initialise potential velocity field
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< G >::OpSource< potential_velocity_field_dim, potential_velocity_field_dim > OpSourceV
Add operators pushing bases from local to physical configuration.
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
base operator to do operations at Gauss Pt. level
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
Structure for user loop methods on finite elements.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
Calculate curl of vector field.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Get time direvarive values at integration pts for tensor field rank 2, i.e. matrix field.
Get values at integration pts for tensor field rank 2, i.e. matrix field.
Post post-proc data at points from hash maps.
Operator to execute finite element instance on parent element. This operator is typically used to pro...
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...
Template struct for dimension-specific finite element types.
PipelineManager interface.
Problem manager is used to build and partition problems.
Simple interface for fast problem set-up.
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
const std::string getBoundaryFEName() const
Get the Boundary FE Name.
const std::string getSkeletonFEName() const
Get the Skeleton FE Name.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
const std::string getDomainFEName() const
Get the Domain FE Name.
BitRefLevel & getBitRefLevel()
Get the BitRefLevel.
intrusive_ptr for managing petsc objects
Interface for Time Stepping (TS) solver.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
#define EXECUTABLE_DIMENSION