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);
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);
1743 ksp,
"level set initial field");
1744 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
1745 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
1749 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
1753 std::vector<Tag> tags{th_error};
1755 "PARALLEL=WRITE_PART", &fe_meshset, 1,
1756 &*tags.begin(), tags.size());
1759 auto post_proc = [&](
auto dm,
auto out_name,
auto th_error) {
1762 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
1763 post_proc_fe->setTagsToTransfer({th_error});
1764 post_proc_fe->exeTestHook = test_bit_ele;
1766 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1769 auto l_vec = boost::make_shared<VectorDouble>();
1770 auto l_grad_mat = boost::make_shared<MatrixDouble>();
1772 post_proc_fe->getOpPtrVector(), {L2});
1773 post_proc_fe->getOpPtrVector().push_back(
1775 post_proc_fe->getOpPtrVector().push_back(
1778 post_proc_fe->getOpPtrVector().push_back(
1782 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1786 {{
"GradL", l_grad_mat}},
1795 post_proc_fe->writeFile(out_name);
1799 if constexpr (
debug)
1800 CHKERR post_proc(sub_dm,
"initial_level_set.h5m", th_error);
1808 boost::function<
double(
double,
double,
double)> vel_fun) {
1817 boost::shared_ptr<FEMethod> lhs_fe = boost::make_shared<DomainEle>(
mField);
1818 boost::shared_ptr<FEMethod> rhs_fe = boost::make_shared<DomainEle>(
mField);
1819 auto swap_fe = [&]() {
1820 lhs_fe.swap(pip->getDomainLhsFE());
1821 rhs_fe.swap(pip->getDomainRhsFE());
1825 pip->setDomainLhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1826 pip->setDomainRhsIntegrationRule([](
int,
int,
int o) {
return 3 * o; });
1839 CHKERR prb_mng->removeDofsOnEntities(
"VELOCITY_PROJECTION",
"V",
1842 auto test_bit = [&](
FEMethod *fe_ptr) {
1843 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(0);
1845 pip->getDomainLhsFE()->exeTestHook = test_bit;
1846 pip->getDomainRhsFE()->exeTestHook = test_bit;
1849 {potential_velocity_space});
1851 {potential_velocity_space});
1853 pip->getOpDomainLhsPipeline().push_back(
new OpMassVV(
"V",
"V"));
1854 pip->getOpDomainRhsPipeline().push_back(
new OpSourceV(
"V", vel_fun));
1856 auto ksp = pip->createKSP(sub_dm);
1866 ksp,
"level set initial velocity");
1867 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
1868 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
1871 auto post_proc = [&](
auto dm,
auto out_name) {
1874 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
1875 post_proc_fe->exeTestHook = test_bit;
1877 if constexpr (
FE_DIM == 2) {
1880 post_proc_fe->getOpPtrVector(), {potential_velocity_space});
1884 auto potential_vec = boost::make_shared<VectorDouble>();
1885 auto velocity_mat = boost::make_shared<MatrixDouble>();
1887 post_proc_fe->getOpPtrVector().push_back(
1889 post_proc_fe->getOpPtrVector().push_back(
1893 post_proc_fe->getOpPtrVector().push_back(
1897 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1899 {{
"VelocityPotential", potential_vec}},
1901 {{
"Velocity", velocity_mat}},
1909 "3d case not implemented");
1914 post_proc_fe->writeFile(out_name);
1918 if constexpr (
debug)
1919 CHKERR post_proc(sub_dm,
"initial_velocity_potential.h5m");
1954 auto add_post_proc_fe = [&]() {
1955 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
1960 "Error", 1, MB_TYPE_DOUBLE, th_error, MB_TAG_CREAT | MB_TAG_SPARSE,
1962 post_proc_fe->setTagsToTransfer({th_error});
1964 post_proc_fe->exeTestHook = [&](
FEMethod *fe_ptr) {
1965 return fe_ptr->numeredEntFiniteElementPtr &&
1966 fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
1972 auto vel_ptr = boost::make_shared<MatrixDouble>();
1975 post_proc_fe->getOpPtrVector(), {L2});
1978 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
1979 auto l_vec = boost::make_shared<VectorDouble>();
1980 post_proc_fe->getOpPtrVector().push_back(
1982 post_proc_fe->getOpPtrVector().push_back(
1986 post_proc_fe->getPostProcMesh(),
1988 post_proc_fe->getMapGaussPts(),
1998 return post_proc_fe;
2001 auto post_proc_fe = add_post_proc_fe();
2003 auto set_time_monitor = [&](
auto dm,
auto ts) {
2004 auto monitor_ptr = boost::make_shared<FEMethod>();
2006 monitor_ptr->preProcessHook = []() {
return 0; };
2007 monitor_ptr->operatorHook = []() {
return 0; };
2008 monitor_ptr->postProcessHook = [dm,
simple, post_proc_fe, monitor_ptr]()
mutable {
2013 "Null pointer for post proc element");
2017 CHKERR post_proc_fe->writeFile(
2019 boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
".h5m");
2023 boost::shared_ptr<FEMethod> null;
2030 auto ts = pip->createTSIM(sub_dm);
2032 auto set_solution = [&](
auto ts) {
2042 auto monitor_pt = set_time_monitor(sub_dm, ts);
2043 CHKERR TSSetFromOptions(ts);
2051 auto ts_pre_step = [](TS ts) {
2057 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2059 auto get_norm = [&](
auto x) {
2061 CHKERR VecNorm(x, NORM_2, &nrm);
2065 auto set_solution = [&](
auto ts) {
2081 <<
"Problem " << prb_ptr->getName() <<
" solution vector norm "
2088 auto refine_and_project = [&](
auto ts) {
2106 ->removeDofsOnEntities(
"ADVECTION",
"L",
BitRefLevel().set(),
2112 auto ts_reset_theta = [&](
auto ts) {
2131 CHKERR refine_and_project(ts);
2132 CHKERR ts_reset_theta(ts);
2137 auto ts_post_step = [](TS ts) {
return 0; };
2139 CHKERR TSSetPreStep(ts, ts_pre_step);
2140 CHKERR TSSetPostStep(ts, ts_post_step);
2142 CHKERR TSSolve(ts, NULL);
2146 PetscReal expected_time;
2147 CHKERR TSGetTime(ts, &expected_time);
2149 ts, expected_time, {1e-12, 1e-12},
"level set advection");
2169 meshset_ptr->get_ptr(), 1);
2174 auto get_refined_elements_meshset = [&](
auto bit,
auto mask) {
2176 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
bit, mask,
FE_DIM, fe_ents);
2180 "get error handle");
2181 std::vector<double> errors(fe_ents.size());
2183 mField.
get_moab().tag_get_data(th_error, fe_ents, &*errors.begin()),
2185 auto it = std::max_element(errors.begin(), errors.end());
2187 MPI_Allreduce(&*it, &max, 1, MPI_DOUBLE, MPI_MAX,
mField.
get_comm());
2188 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Max error: " << max;
2189 auto threshold = wp.getThreshold(max);
2191 std::vector<EntityHandle> fe_to_refine;
2192 fe_to_refine.reserve(fe_ents.size());
2194 auto fe_it = fe_ents.begin();
2195 auto error_it = errors.begin();
2196 for (
auto i = 0;
i != fe_ents.size(); ++
i) {
2197 if (*error_it > threshold) {
2198 fe_to_refine.push_back(*fe_it);
2205 ents.insert_list(fe_to_refine.begin(), fe_to_refine.end());
2207 ents,
nullptr,
NOISY);
2209 auto get_neighbours_by_bridge_vertices = [&](
auto &&ents) {
2213 moab::Interface::UNION);
2218 ents = get_neighbours_by_bridge_vertices(ents);
2224 "add entities to meshset");
2226 (proc_str +
"_fe_to_refine.vtk").c_str(),
"VTK",
"",
2227 meshset_ptr->get_ptr(), 1);
2235 auto refine_mesh = [&](
auto l,
auto &&fe_to_refine) {
2241 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2244 fe_to_refine = intersect(level_ents, fe_to_refine);
2246 level_ents = subtract(level_ents, fe_to_refine);
2249 Range fe_to_refine_children;
2250 bit_mng->updateRangeByChildren(fe_to_refine, fe_to_refine_children);
2252 fe_to_refine_children = fe_to_refine_children.subset_by_dimension(
FE_DIM);
2253 level_ents.merge(fe_to_refine_children);
2255 auto fix_neighbour_level = [&](
auto ll) {
2258 auto level_ll = level_ents;
2263 CHKERR skin.find_skin(0, level_ll,
false, skin_edges);
2266 for (
auto lll = 0; lll <= ll; ++lll) {
2267 CHKERR bit_mng->updateRangeByParent(skin_edges, skin_parents);
2271 for (
auto lll = 0; lll <= ll - 2; ++lll) {
2272 bad_bit[lll] =
true;
2275 Range skin_adj_ents;
2277 skin_parents,
FE_DIM,
false, skin_adj_ents, moab::Interface::UNION);
2280 skin_adj_ents = intersect(skin_adj_ents, level_ents);
2281 if (!skin_adj_ents.empty()) {
2282 level_ents = subtract(level_ents, skin_adj_ents);
2283 Range skin_adj_ents_children;
2284 bit_mng->updateRangeByChildren(skin_adj_ents, skin_adj_ents_children);
2285 level_ents.merge(skin_adj_ents_children);
2290 CHKERR fix_neighbour_level(
l);
2296 for (
auto d = 0; d !=
FE_DIM; ++d) {
2299 level_ents.subset_by_dimension(
FE_DIM), level_ents,
true);
2302 level_ents.subset_by_dimension(
FE_DIM), d,
false, level_ents,
2303 moab::Interface::UNION);
2315 CHKERR bit_mng->writeBitLevelByDim(
2317 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_ref_mesh.vtk")
2326 auto set_skelton_bit = [&](
auto l) {
2331 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2335 Range level_edges_parents;
2336 CHKERR bit_mng->updateRangeByParent(level_edges, level_edges_parents);
2337 level_edges_parents = level_edges_parents.subset_by_dimension(
FE_DIM - 1);
2338 CHKERR bit_mng->filterEntitiesByRefLevel(
2342 auto parent_skeleton = intersect(level_edges, level_edges_parents);
2343 auto skeleton = subtract(level_edges, level_edges_parents);
2348 moab::Interface::UNION);
2356 CHKERR bit_mng->writeBitLevel(
2358 (boost::lexical_cast<std::string>(
l) +
"_" + proc_str +
"_skeleton.vtk")
2366 Range level0_current;
2370 Range level0_aggregate;
2376 start_mask[s] =
true;
2377 CHKERR bit_mng->lambdaBitRefLevel(
2392 CHKERR wp.setBits(*
this, 0);
2393 CHKERR wp.runCalcs(*
this, 0);
2395 MOFEM_LOG(
"WORLD", Sev::inform) <<
"Process level: " <<
l;
2396 CHKERR refine_mesh(
l + 1, get_refined_elements_meshset(
2398 CHKERR set_skelton_bit(
l + 1);
2399 CHKERR wp.setAggregateBit(*
this,
l + 1);
2400 CHKERR wp.setBits(*
this,
l + 1);
2401 CHKERR wp.runCalcs(*
this,
l + 1);
2415 auto lhs_fe = boost::make_shared<DomainEle>(
mField);
2416 auto rhs_fe_prj = boost::make_shared<DomainEle>(
mField);
2417 auto rhs_fe_current = boost::make_shared<DomainEle>(
mField);
2419 lhs_fe->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2420 rhs_fe_prj->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2421 rhs_fe_current->getRuleHook = [](int, int,
int o) {
return 3 * o; };
2436 CHKERR bit_mng->getEntitiesByDimAndRefLevel(
2439 CHKERR bit_mng->updateRangeByParent(prj_ents, prj_ents);
2441 current_ents = subtract(
2442 current_ents, prj_ents);
2444 auto test_mesh_bit = [&](
FEMethod *fe_ptr) {
2445 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2448 auto test_prj_bit = [&](
FEMethod *fe_ptr) {
2449 return fe_ptr->numeredEntFiniteElementPtr->getBitRefLevel().test(
2452 auto test_current_bit = [&](
FEMethod *fe_ptr) {
2453 return current_ents.find(fe_ptr->getFEEntityHandle()) != current_ents.end();
2456 lhs_fe->exeTestHook =
2458 rhs_fe_prj->exeTestHook =
2460 rhs_fe_current->exeTestHook =
2465 CHKERR prb_mng->removeDofsOnEntities(
2466 "DG_PROJECTION",
"L",
BitRefLevel().set(), remove_mask,
nullptr, 0,
2473 lhs_fe->getOpPtrVector().push_back(
2477 auto set_prj_from_child = [&](
auto rhs_fe_prj) {
2479 rhs_fe_prj->getOpPtrVector(), {L2});
2482 auto l_mat = boost::make_shared<MatrixDouble>();
2483 rhs_fe_prj->getOpPtrVector().push_back(
2487 auto get_parent_this = [&]() {
2488 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2489 fe_parent_this->getOpPtrVector().push_back(
new OpScalarFieldL(
"L", l_mat));
2490 return fe_parent_this;
2495 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2496 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2498 parents_elems_ptr_vec.emplace_back(
2499 boost::make_shared<DomainParentEle>(
mField));
2501 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2507 return parents_elems_ptr_vec[0];
2510 auto this_fe_ptr = get_parent_this();
2511 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2512 rhs_fe_prj->getOpPtrVector().push_back(
2519 auto set_prj_from_parent = [&](
auto rhs_fe_current) {
2522 auto l_mat = boost::make_shared<MatrixDouble>();
2525 auto get_parent_this = [&]() {
2526 auto fe_parent_this = boost::make_shared<DomainParentEle>(
mField);
2527 fe_parent_this->getOpPtrVector().push_back(
2529 return fe_parent_this;
2533 auto get_parents_fe_ptr = [&](
auto this_fe_ptr) {
2534 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
2536 parents_elems_ptr_vec.emplace_back(
2537 boost::make_shared<DomainParentEle>(
mField));
2539 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
2545 return parents_elems_ptr_vec[0];
2548 auto this_fe_ptr = get_parent_this();
2549 auto parent_fe_ptr = get_parents_fe_ptr(this_fe_ptr);
2552 reset_op_ptr->doWorkRhsHook = [&](
DataOperator *op_ptr, int, EntityType,
2554 l_mat->resize(
static_cast<DomainEleOp *
>(op_ptr)->getGaussPts().size2(),
2559 rhs_fe_current->getOpPtrVector().push_back(reset_op_ptr);
2560 rhs_fe_current->getOpPtrVector().push_back(
2566 rhs_fe_current->getOpPtrVector().push_back(
new OpScalarFieldL(
"L", l_mat));
2569 set_prj_from_child(rhs_fe_prj);
2570 set_prj_from_parent(rhs_fe_current);
2572 boost::shared_ptr<FEMethod> null_fe;
2575 lhs_fe, null_fe, null_fe);
2579 rhs_fe_current, null_fe, null_fe);
2592 ksp,
"level set DG projection");
2593 CHKERR VecGhostUpdateBegin(
L, INSERT_VALUES, SCATTER_FORWARD);
2594 CHKERR VecGhostUpdateEnd(
L, INSERT_VALUES, SCATTER_FORWARD);
2598 MOFEM_LOG(
"LevelSet", Sev::inform) <<
"Error indicator " << error;
2600 auto post_proc = [&](
auto dm,
auto out_name,
auto th_error) {
2603 boost::make_shared<PostProcBrokenMeshInMoab<DomainEle>>(
mField);
2604 post_proc_fe->setTagsToTransfer({th_error});
2605 post_proc_fe->exeTestHook = test_mesh_bit;
2607 if constexpr (
DIM1 == 1 &&
DIM2 == 1) {
2609 auto l_vec = boost::make_shared<VectorDouble>();
2610 auto l_grad_mat = boost::make_shared<MatrixDouble>();
2612 post_proc_fe->getOpPtrVector(), {L2});
2613 post_proc_fe->getOpPtrVector().push_back(
2615 post_proc_fe->getOpPtrVector().push_back(
2618 post_proc_fe->getOpPtrVector().push_back(
2622 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
2626 {{
"GradL", l_grad_mat}},
2635 post_proc_fe->writeFile(out_name);
2639 if constexpr (
debug)
2640 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
#define EXECUTABLE_DIMENSION
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)
Integrate grad-grad operator.
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)
Class dedicated to integrate operator.
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.