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>;
374double LevelSet::get_velocity_potential<2>(
double x,
double y,
double z) {
375 return (x * x - 0.25) * (y * y - 0.25);
379 constexpr double xc = 0.1;
380 constexpr double yc = 0.;
381 constexpr double zc = 0.;
382 constexpr double r = 0.2;
383 return std::sqrt(pow(x - xc, 2) + pow(y - yc, 2) + pow(z - zc, 2)) - r;
391 if constexpr (
debug) {
398 maxPtr = boost::make_shared<double>(0);
415 boost::shared_ptr<MatrixDouble> l_ptr,
416 boost::shared_ptr<MatrixDouble> l_dot_ptr,
417 boost::shared_ptr<MatrixDouble> vel_ptr);
421 boost::shared_ptr<MatrixDouble>
lPtr;
428 boost::shared_ptr<MatrixDouble> vel_ptr);
438 boost::shared_ptr<FaceSideEle> side_fe_ptr);
444 boost::shared_ptr<FaceSideEle>
452 boost::shared_ptr<FaceSideEle> side_fe_ptr);
458 boost::shared_ptr<FaceSideEle>
464int main(
int argc,
char *argv[]) {
467 const char param_file[] =
"param_file.petsc";
473 moab::Core moab_core;
474 moab::Interface &moab = moab_core;
481 DMType dm_name =
"DMMOFEM";
485 auto core_log = logging::core::get();
511 simple->getAddSkeletonFE() =
true;
512 simple->getAddBoundaryFE() =
true;
519 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);
1337 boost::function<
MoFEMErrorCode(EntityHandle,
double)> add_error =
1338 [&](
auto fe_ent,
auto error) {
1341 CHKERR moab.tag_get_by_ptr(th_error, &fe_ent, 1,
1342 (
const void **)&e_ptr);
1345 EntityHandle parent;
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->getBitRefLevel().test(
1967 auto vel_ptr = boost::make_shared<MatrixDouble>();
1970 post_proc_fe->getOpPtrVector(), {L2});
1973 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1974 auto l_vec = boost::make_shared<VectorDouble>();
1975 post_proc_fe->getOpPtrVector().push_back(
1977 post_proc_fe->getOpPtrVector().push_back(
1981 post_proc_fe->getPostProcMesh(),
1983 post_proc_fe->getMapGaussPts(),
1993 return post_proc_fe;
1996 auto post_proc_fe = add_post_proc_fe();
1998 auto set_time_monitor = [&](
auto dm,
auto ts) {
1999 auto monitor_ptr = boost::make_shared<FEMethod>();
2001 monitor_ptr->preProcessHook = []() {
return 0; };
2002 monitor_ptr->operatorHook = []() {
return 0; };
2003 monitor_ptr->postProcessHook = [&]() {
2008 "Null pointer for post proc element");
2012 CHKERR post_proc_fe->writeFile(
2014 boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
".h5m");
2018 boost::shared_ptr<FEMethod> null;
2025 auto ts = pip->createTSIM(sub_dm);
2027 auto set_solution = [&](
auto ts) {
2036 auto monitor_pt = set_time_monitor(sub_dm, ts);
2037 CHKERR TSSetFromOptions(ts);
2045 auto ts_pre_step = [](TS ts) {
2051 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2053 auto get_norm = [&](
auto x) {
2055 CHKERR VecNorm(x, NORM_2, &nrm);
2059 auto set_solution = [&](
auto ts) {
2067 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
2068 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
2071 <<
"Problem " << prb_ptr->getName() <<
" solution vector norm "
2073 CHKERR TSSetSolution(ts, x);
2078 auto refine_and_project = [&](
auto ts) {
2096 ->removeDofsOnEntities(
"ADVECTION",
"L",
BitRefLevel().set(),
2102 auto ts_reset_theta = [&](
auto ts) {
2121 CHKERR refine_and_project(ts);
2122 CHKERR ts_reset_theta(ts);
2127 auto ts_post_step = [](TS ts) {
return 0; };
2129 CHKERR TSSetPreStep(ts, ts_pre_step);
2130 CHKERR TSSetPostStep(ts, ts_post_step);
2132 CHKERR TSSolve(ts, NULL);
2150 meshset_ptr->get_ptr(), 1);
2155 auto get_refined_elements_meshset = [&](
auto bit,
auto mask) {
2157 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
bit, mask,
FE_DIM, fe_ents);
2161 "get error handle");
2162 std::vector<double> errors(fe_ents.size());
2164 mField.
get_moab().tag_get_data(th_error, fe_ents, &*errors.begin()),
2166 auto it = std::max_element(errors.begin(), errors.end());
2168 MPI_Allreduce(&*it, &max, 1, MPI_DOUBLE, MPI_MAX,
mField.
get_comm());
2169 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Max error: " << max;
2170 auto threshold = wp.getThreshold(max);
2172 std::vector<EntityHandle> fe_to_refine;
2173 fe_to_refine.reserve(fe_ents.size());
2175 auto fe_it = fe_ents.begin();
2176 auto error_it = errors.begin();
2177 for (
auto i = 0;
i != fe_ents.size(); ++
i) {
2178 if (*error_it > threshold) {
2179 fe_to_refine.push_back(*fe_it);
2186 ents.insert_list(fe_to_refine.begin(), fe_to_refine.end());
2188 ents,
nullptr,
NOISY);
2190 auto get_neighbours_by_bridge_vertices = [&](
auto &&ents) {
2194 moab::Interface::UNION);
2199 ents = get_neighbours_by_bridge_vertices(ents);
2205 "add entities to meshset");
2207 (proc_str +
"_fe_to_refine.vtk").c_str(),
"VTK",
"",
2208 meshset_ptr->get_ptr(), 1);
2216 auto refine_mesh = [&](
auto l,
auto &&fe_to_refine) {
2222 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2225 fe_to_refine = intersect(level_ents, fe_to_refine);
2227 level_ents = subtract(level_ents, fe_to_refine);
2230 Range fe_to_refine_children;
2231 bit_mng->updateRangeByChildren(fe_to_refine, fe_to_refine_children);
2233 fe_to_refine_children = fe_to_refine_children.subset_by_dimension(
FE_DIM);
2234 level_ents.merge(fe_to_refine_children);
2236 auto fix_neighbour_level = [&](
auto ll) {
2239 auto level_ll = level_ents;
2244 CHKERR skin.find_skin(0, level_ll,
false, skin_edges);
2247 for (
auto lll = 0; lll <= ll; ++lll) {
2248 CHKERR bit_mng->updateRangeByParent(skin_edges, skin_parents);
2252 for (
auto lll = 0; lll <= ll - 2; ++lll) {
2253 bad_bit[lll] =
true;
2256 Range skin_adj_ents;
2258 skin_parents,
FE_DIM,
false, skin_adj_ents, moab::Interface::UNION);
2261 skin_adj_ents = intersect(skin_adj_ents, level_ents);
2262 if (!skin_adj_ents.empty()) {
2263 level_ents = subtract(level_ents, skin_adj_ents);
2264 Range skin_adj_ents_children;
2265 bit_mng->updateRangeByChildren(skin_adj_ents, skin_adj_ents_children);
2266 level_ents.merge(skin_adj_ents_children);
2271 CHKERR fix_neighbour_level(
l);
2277 for (
auto d = 0; d !=
FE_DIM; ++d) {
2280 level_ents.subset_by_dimension(
FE_DIM), level_ents,
true);
2283 level_ents.subset_by_dimension(
FE_DIM), d,
false, level_ents,
2284 moab::Interface::UNION);
2296 CHKERR bit_mng->writeBitLevelByDim(
2298 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_ref_mesh.vtk")
2307 auto set_skelton_bit = [&](
auto l) {
2312 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2316 Range level_edges_parents;
2317 CHKERR bit_mng->updateRangeByParent(level_edges, level_edges_parents);
2318 level_edges_parents = level_edges_parents.subset_by_dimension(
FE_DIM - 1);
2319 CHKERR bit_mng->filterEntitiesByRefLevel(
2323 auto parent_skeleton = intersect(level_edges, level_edges_parents);
2324 auto skeleton = subtract(level_edges, level_edges_parents);
2329 moab::Interface::UNION);
2337 CHKERR bit_mng->writeBitLevel(
2339 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_skeleton.vtk")
2347 Range level0_current;
2351 Range level0_aggregate;
2357 start_mask[s] =
true;
2358 CHKERR bit_mng->lambdaBitRefLevel(
2373 CHKERR wp.setBits(*
this, 0);
2374 CHKERR wp.runCalcs(*
this, 0);
2376 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Process level: " <<
l;
2377 CHKERR refine_mesh(
l + 1, get_refined_elements_meshset(
2379 CHKERR set_skelton_bit(
l + 1);
2380 CHKERR wp.setAggregateBit(*
this,
l + 1);
2381 CHKERR wp.setBits(*
this,
l + 1);
2382 CHKERR wp.runCalcs(*
this,
l + 1);
2396 auto lhs_fe = boost::make_shared<DomainEle>(
mField);
2397 auto rhs_fe_prj = boost::make_shared<DomainEle>(
mField);
2398 auto rhs_fe_current = boost::make_shared<DomainEle>(
mField);
2400 lhs_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2401 rhs_fe_prj->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2402 rhs_fe_current->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2417 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2420 CHKERR bit_mng->updateRangeByParent(prj_ents, prj_ents);
2422 current_ents = subtract(
2423 current_ents, prj_ents);
2425 auto test_mesh_bit = [&](
FEMethod *fe_ptr) {
2426 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2429 auto test_prj_bit = [&](
FEMethod *fe_ptr) {
2430 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2433 auto test_current_bit = [&](
FEMethod *fe_ptr) {
2434 return current_ents.find(fe_ptr->getFEEntityHandle()) != current_ents.end();
2437 lhs_fe->exeTestHook =
2439 rhs_fe_prj->exeTestHook =
2441 rhs_fe_current->exeTestHook =
2446 CHKERR prb_mng->removeDofsOnEntities(
2447 "DG_PROJECTION",
"L",
BitRefLevel().set(), remove_mask,
nullptr, 0,
2454 lhs_fe->getOpPtrVector().push_back(
2457 auto make_tensor_mat_to_vec_mat_op = [](
auto src_mat_ptr,
auto dst_mat_ptr) {
2459 op_ptr->doWorkRhsHook = [src_mat_ptr, dst_mat_ptr](
DataOperator *op_ptr,
2463 const auto nb_gauss_pts =
2464 static_cast<DomainEleOp *
>(op_ptr)->getGaussPts().size2();
2465 auto &src_mat = *src_mat_ptr;
2466 auto &dst_mat = *dst_mat_ptr;
2468 if (src_mat.size1() != nb_gauss_pts)
2470 "Wrong number of integration pts %zu != %zu", src_mat.size1(),
2472 if (src_mat.size2() !=
DIM1 *
DIM2)
2474 "Wrong tensor components layout %zu != %d", src_mat.size2(),
2477 dst_mat.resize(nb_gauss_pts,
DIM1 *
DIM2,
false);
2478 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg)
2479 for (
size_t dd = 0; dd !=
DIM1 *
DIM2; ++dd)
2480 dst_mat(gg, dd) = src_mat(gg, dd);
2487 auto set_prj_from_child = [&](
auto rhs_fe_prj) {
2489 rhs_fe_prj->getOpPtrVector(), {L2});
2492 auto l_tensor_mat = boost::make_shared<MatrixDouble>();
2493 auto l_vec_mat = boost::make_shared<MatrixDouble>();
2494 rhs_fe_prj->getOpPtrVector().push_back(
2496 rhs_fe_prj->getOpPtrVector().push_back(
2497 make_tensor_mat_to_vec_mat_op(l_tensor_mat, l_vec_mat));
2500 auto get_parent_this = [&]() {
2501 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2502 fe_parent_this->getOpPtrVector().push_back(
2504 return fe_parent_this;
2509 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2510 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2512 parents_elems_ptr_vec.emplace_back(
2513 boost::make_shared<DomainParentEle>(
mField));
2515 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2521 return parents_elems_ptr_vec[0];
2524 auto this_fe_ptr = get_parent_this();
2525 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2526 rhs_fe_prj->getOpPtrVector().push_back(
2533 auto set_prj_from_parent = [&](
auto rhs_fe_current) {
2536 auto l_tensor_mat = boost::make_shared<MatrixDouble>();
2537 auto l_vec_mat = boost::make_shared<MatrixDouble>();
2540 auto get_parent_this = [&]() {
2541 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2542 fe_parent_this->getOpPtrVector().push_back(
2544 fe_parent_this->getOpPtrVector().push_back(
2545 make_tensor_mat_to_vec_mat_op(l_tensor_mat, l_vec_mat));
2546 return fe_parent_this;
2550 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2551 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2553 parents_elems_ptr_vec.emplace_back(
2554 boost::make_shared<DomainParentEle>(
mField));
2556 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2562 return parents_elems_ptr_vec[0];
2565 auto this_fe_ptr = get_parent_this();
2566 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2569 reset_op_ptr->doWorkRhsHook = [&](
DataOperator *op_ptr, int, EntityType,
2572 static_cast<DomainEleOp *
>(op_ptr)->getGaussPts().size2(),
2577 rhs_fe_current->getOpPtrVector().push_back(reset_op_ptr);
2578 rhs_fe_current->getOpPtrVector().push_back(
2584 rhs_fe_current->getOpPtrVector().push_back(
2588 set_prj_from_child(rhs_fe_prj);
2589 set_prj_from_parent(rhs_fe_current);
2591 boost::shared_ptr<FEMethod> null_fe;
2594 lhs_fe, null_fe, null_fe);
2598 rhs_fe_current, null_fe, null_fe);
2600 CHKERR KSPSetDM(ksp, sub_dm);
2602 CHKERR KSPSetDM(ksp, sub_dm);
2603 CHKERR KSPSetFromOptions(ksp);
2610 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
2611 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
2615 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2617 auto post_proc = [&](
auto dm,
auto out_name,
auto th_error) {
2620 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
2621 post_proc_fe->setTagsToTransfer({th_error});
2622 post_proc_fe->exeTestHook = test_mesh_bit;
2624 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
2626 auto l_vec = boost::make_shared<VectorDouble>();
2627 auto l_grad_mat = boost::make_shared<MatrixDouble>();
2629 post_proc_fe->getOpPtrVector(), {L2});
2630 post_proc_fe->getOpPtrVector().push_back(
2632 post_proc_fe->getOpPtrVector().push_back(
2635 post_proc_fe->getOpPtrVector().push_back(
2639 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
2643 {{
"GradL", l_grad_mat}},
2652 post_proc_fe->writeFile(out_name);
2656 if constexpr (
debug)
2657 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
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