953 {
955
956
957
958
959
964
965
966
967 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
968 auto fe_domain_rhs = pip_mng->getDomainRhsFE();
969 auto fe_bdy_lhs = pip_mng->getBoundaryLhsFE();
970 auto fe_bdy_rhs = pip_mng->getBoundaryRhsFE();
971
972 pip_mng->getDomainLhsFE().reset();
973 pip_mng->getDomainRhsFE().reset();
974 pip_mng->getBoundaryLhsFE().reset();
975 pip_mng->getBoundaryRhsFE().reset();
976
977 using UDO = ForcesAndSourcesCore::UserDataOperator;
978
979
980 auto add_parent_field_domain = [&](
auto fe,
auto op,
auto field,
auto bit) {
983
984 [&]() {
985 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
987 return fe_parent;
988 },
989
991 };
992
993
994 auto add_parent_field_bdy = [&](
auto fe,
auto op,
auto field,
auto bit) {
997
998 [&]() {
999 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1001 return fe_parent;
1002 },
1003
1005 };
1006
1007
1008
1009 auto create_run_parent_op = [&](auto parent_fe_ptr, auto this_fe_ptr,
1010 auto fe_bit) {
1011 auto parent_mask = fe_bit;
1012 parent_mask.flip();
1015 Sev::inform);
1016 };
1017
1018
1019 auto get_parents_vel_fe_ptr = [&](auto this_fe_ptr, auto fe_bit) {
1020 std::vector<boost::shared_ptr<DomianParentEle>> parents_elems_ptr_vec;
1022 parents_elems_ptr_vec.emplace_back(
1023 boost::make_shared<DomianParentEle>(
mField));
1025 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
1026 create_run_parent_op(parents_elems_ptr_vec[
l], this_fe_ptr, fe_bit));
1027 }
1028 return parents_elems_ptr_vec[0];
1029 };
1030
1031
1032 auto solve_projection = [&](auto exe_test) {
1034
1035 auto set_domain_rhs = [&](auto fe) {
1037 auto &pip = fe->getOpPtrVector();
1038
1039 auto u_ptr = boost::make_shared<MatrixDouble>();
1040 auto p_ptr = boost::make_shared<VectorDouble>();
1041 auto h_ptr = boost::make_shared<VectorDouble>();
1042 auto g_ptr = boost::make_shared<VectorDouble>();
1043
1044 auto eval_fe_ptr = boost::make_shared<DomianParentEle>(
mField);
1045 {
1046 auto &pip = eval_fe_ptr->getOpPtrVector();
1050
1051 [&]() {
1052 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1054 return fe_parent;
1055 },
1056
1058
1059
1060 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"U",
1063 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"P",
1066 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"H",
1069 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"G",
1072 }
1073 auto parent_eval_fe_ptr =
1075 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1077
1078 auto assemble_fe_ptr = boost::make_shared<DomianParentEle>(
mField);
1079 {
1080 auto &pip = assemble_fe_ptr->getOpPtrVector();
1084
1085 [&]() {
1086 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1088 return fe_parent;
1089 },
1090
1092 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"U",
1095 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"P",
1098 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"H",
1101 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"G",
1104 }
1105 auto parent_assemble_fe_ptr =
1107 pip.push_back(create_run_parent_op(
1109
1111 };
1112
1113 auto set_domain_lhs = [&](auto fe) {
1115
1116 auto &pip = fe->getOpPtrVector();
1117
1119
1122
1123 [&]() {
1124 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1126 return fe_parent;
1127 },
1128
1130
1131
1132
1133 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"U",
1135 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"U",
1138 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"P",
1140 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"P",
1143 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"H",
1145 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"H",
1148 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"G",
1150 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"G",
1153
1155 };
1156
1157 auto set_bdy_rhs = [&](auto fe) {
1159 auto &pip = fe->getOpPtrVector();
1160
1161 auto l_ptr = boost::make_shared<VectorDouble>();
1162
1163 auto eval_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1164 {
1165 auto &pip = eval_fe_ptr->getOpPtrVector();
1168
1169 [&]() {
1170 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1172 return fe_parent;
1173 },
1174
1176
1177
1178 CHKERR add_parent_field_bdy(eval_fe_ptr, UDO::OPROW,
"L",
1181 }
1182 auto parent_eval_fe_ptr =
1184 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1186
1187 auto assemble_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1188 {
1189 auto &pip = assemble_fe_ptr->getOpPtrVector();
1192
1193 [&]() {
1194 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1196 return fe_parent;
1197 },
1198
1200
1202 OpLSize(boost::shared_ptr<VectorDouble> l_ptr)
1206 if (lPtr->size() != getGaussPts().size2()) {
1207 lPtr->resize(getGaussPts().size2());
1208 lPtr->clear();
1209 }
1211 }
1212
1213 private:
1214 boost::shared_ptr<VectorDouble> lPtr;
1215 };
1216
1217 pip.push_back(new OpLSize(l_ptr));
1218
1219 CHKERR add_parent_field_bdy(assemble_fe_ptr, UDO::OPROW,
"L",
1222 }
1223 auto parent_assemble_fe_ptr =
1225 pip.push_back(create_run_parent_op(
1227
1229 };
1230
1231 auto set_bdy_lhs = [&](auto fe) {
1233
1234 auto &pip = fe->getOpPtrVector();
1235
1238
1239 [&]() {
1240 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1242 return fe_parent;
1243 },
1244
1246
1247
1248
1249 CHKERR add_parent_field_bdy(fe, UDO::OPROW,
"L",
1251 CHKERR add_parent_field_bdy(fe, UDO::OPCOL,
"L",
1254
1256 };
1257
1259 auto level_ents_ptr = boost::make_shared<Range>();
1262
1263 auto get_prj_ents = [&]() {
1268 auto common_ents = intersect(prj_mesh, *level_ents_ptr);
1269 prj_mesh = subtract(unite(*level_ents_ptr, prj_mesh), common_ents)
1271
1272 return prj_mesh;
1273 };
1274
1275 auto prj_ents = get_prj_ents();
1276
1278
1279 auto rebuild = [&]() {
1282
1283 std::vector<std::string> fields{"U", "P", "H", "G", "L"};
1284 std::map<std::string, boost::shared_ptr<Range>> range_maps{
1285
1286 {"U", level_ents_ptr},
1287 {"P", level_ents_ptr},
1288 {"H", level_ents_ptr},
1289 {"G", level_ents_ptr},
1290 {"L", level_ents_ptr}
1291
1292 };
1293
1295 simple->getProblemName(), PETSC_TRUE,
1296 &range_maps, &range_maps);
1297
1298
1299 CHKERR prb_mng->partitionFiniteElements(
"SUB_SOLVER",
true, 0,
1301
1302 CHKERR prb_mng->partitionGhostDofsOnDistributedMesh(
"SUB_SOLVER");
1303
1305 };
1306
1307 MOFEM_LOG(
"FS", Sev::verbose) <<
"Create projection problem";
1308
1310
1311 auto dm =
simple->getDM();
1312 DM subdm;
1314 CHKERR DMSetType(subdm,
"DMMOFEM");
1317 }
1318
1319 MOFEM_LOG(
"FS", Sev::inform) <<
"Nothing to project";
1320
1322 };
1323
1324 auto create_dummy_dm = [&]() {
1327 simple->getProblemName().c_str(),
1329 "create dummy dm");
1330 return dummy_dm;
1331 };
1332
1333 auto subdm = create_subdm();
1334 if (subdm) {
1335
1336 pip_mng->getDomainRhsFE().reset();
1337 pip_mng->getDomainLhsFE().reset();
1338 pip_mng->getBoundaryRhsFE().reset();
1339 pip_mng->getBoundaryLhsFE().reset();
1344 pip_mng->getDomainLhsFE()->exeTestHook = exe_test;
1345 pip_mng->getDomainRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1347 };
1348 pip_mng->getBoundaryLhsFE()->exeTestHook = exe_test;
1349 pip_mng->getBoundaryRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1351 };
1352
1353 CHKERR set_domain_rhs(pip_mng->getCastDomainRhsFE());
1354 CHKERR set_domain_lhs(pip_mng->getCastDomainLhsFE());
1355 CHKERR set_bdy_rhs(pip_mng->getCastBoundaryRhsFE());
1356 CHKERR set_bdy_lhs(pip_mng->getCastBoundaryLhsFE());
1357
1360
1361 auto ksp = pip_mng->createKSP(subdm);
1362 CHKERR KSPSetFromOptions(ksp);
1364
1365
1366 auto get_norm = [&](auto x) {
1367 double nrm;
1368 CHKERR VecNorm(x, NORM_2, &nrm);
1369 return nrm;
1370 };
1371
1372
1373
1374
1375 auto zero_dofs = [](boost::shared_ptr<FieldEntity> ent_ptr) {
1377 for (
auto &
v : ent_ptr->getEntFieldData()) {
1379 }
1381 };
1382
1383 auto solve = [&](
auto S) {
1385 CHKERR VecZeroEntries(S);
1387 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
1388 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
1390 CHKERR VecGhostUpdateBegin(S, INSERT_VALUES, SCATTER_FORWARD);
1391 CHKERR VecGhostUpdateEnd(S, INSERT_VALUES, SCATTER_FORWARD);
1392
1393
1394
1396 };
1397
1398 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection";
1400
1403 auto dummy_dm = create_dummy_dm();
1404
1405
1406
1407
1408 auto apply_restrict = [&]() {
1409 auto get_is = [](
auto v) {
1410 IS iy;
1411 auto create = [&]() {
1415 CHKERR VecGetOwnershipRange(
v, &ystart, NULL);
1416 CHKERR ISCreateStride(PETSC_COMM_SELF,
n, ystart, 1, &iy);
1418 };
1421 };
1422
1423 auto iy = get_is(glob_x);
1425
1427 DMSubDomainRestrict(
simple->getDM(), s, PETSC_NULLPTR, dummy_dm),
1428 "restrict");
1429 Vec X0, Xdot;
1431 "get X0");
1433 DMGetNamedGlobalVector(dummy_dm, "TSTheta_Xdot", &Xdot),
1434 "get Xdot");
1435
1436 auto forward_ghost = [](
auto g) {
1438 CHKERR VecGhostUpdateBegin(
g, INSERT_VALUES, SCATTER_FORWARD);
1439 CHKERR VecGhostUpdateEnd(
g, INSERT_VALUES, SCATTER_FORWARD);
1441 };
1442
1445
1446 if constexpr (
debug) {
1448 << "Reverse restrict: X0 " << get_norm(X0) << " Xdot "
1449 << get_norm(Xdot);
1450 }
1451
1452 return std::vector<Vec>{X0, Xdot};
1453 };
1454
1455 auto ts_solver_vecs = apply_restrict();
1456
1457 if (ts_solver_vecs.size()) {
1458
1459 for (
auto v : ts_solver_vecs) {
1460 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection vector";
1461
1463 SCATTER_REVERSE);
1465
1466 for (auto f : {"U", "P", "H", "G", "L"}) {
1467 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1468 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1469 }
1470
1472 SCATTER_REVERSE);
1474 SCATTER_FORWARD);
1475
1476 MOFEM_LOG(
"FS", Sev::inform) <<
"Norm V " << get_norm(
v);
1477 }
1478
1479 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_X0",
1480 &ts_solver_vecs[0]);
1481 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_Xdot",
1482 &ts_solver_vecs[1]);
1483 }
1484
1485 for (auto f : {"U", "P", "H", "G", "L"}) {
1486 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1487 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1488 }
1490 }
1491
1493 };
1494
1495
1496 auto post_proc = [&](auto exe_test) {
1498 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(
mField);
1499 auto &pip = post_proc_fe->getOpPtrVector();
1500 post_proc_fe->exeTestHook = exe_test;
1501
1503
1506
1507 [&]() {
1508 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1511 fe_parent->getOpPtrVector(), {H1});
1512 return fe_parent;
1513 },
1514
1516
1518
1519 auto u_ptr = boost::make_shared<MatrixDouble>();
1520 auto p_ptr = boost::make_shared<VectorDouble>();
1521 auto h_ptr = boost::make_shared<VectorDouble>();
1522 auto g_ptr = boost::make_shared<VectorDouble>();
1523
1524 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"U",
1527 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"P",
1530 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"H",
1533 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"G",
1536
1537 post_proc_fe->getOpPtrVector().push_back(
1538
1539 new OpPPMap(post_proc_fe->getPostProcMesh(),
1540 post_proc_fe->getMapGaussPts(),
1541
1542 {{"P", p_ptr}, {"H", h_ptr}, {"G", g_ptr}},
1543
1544 {{"U", u_ptr}},
1545
1546 {},
1547
1548 {}
1549
1550 )
1551
1552 );
1553
1554 auto dm =
simple->getDM();
1556 CHKERR post_proc_fe->writeFile(
"out_projection.h5m");
1557
1559 };
1560
1563 });
1564
1565 if constexpr (
debug) {
1568 });
1569 }
1570
1571 fe_domain_lhs.swap(pip_mng->getDomainLhsFE());
1572 fe_domain_rhs.swap(pip_mng->getDomainRhsFE());
1573 fe_bdy_lhs.swap(pip_mng->getBoundaryLhsFE());
1574 fe_bdy_rhs.swap(pip_mng->getBoundaryRhsFE());
1575
1577}
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, U_FIELD_DIM > OpDomainMassU
FormsIntegrators< BoundaryEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, 1 > OpBoundaryMassL
OpDomainMassH OpDomainMassG
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpBaseTimesVector< BASE_DIM, SPACE_DIM, 1 > OpDomainAssembleVector
auto get_skin_projection_bit
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, 1 > OpDomainMassH
FormsIntegrators< BoundaryEleOp >::Assembly< A >::LinearForm< I >::OpBaseTimesScalar< BASE_DIM > OpBoundaryAssembleScalar
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
MoFEMErrorCode buildSubProblem(const std::string out_name, const std::vector< std::string > &fields_row, const std::vector< std::string > &fields_col, const std::string main_problem, const bool square_matrix=true, const map< std::string, boost::shared_ptr< Range > > *entityMapRow=nullptr, const map< std::string, boost::shared_ptr< Range > > *entityMapCol=nullptr, int verb=VERBOSE)
build sub problem
const double n
refractive index of diffusive medium
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVecScatter(Vec x, IS ix, Vec y, IS iy)
Create a Vec Scatter object.
static PetscErrorCode solve(Mat mat, Vec x, Vec y)
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
Data on single entity (This is passed as argument to DataOperator::doWork)
Operator to execute finite element instance on parent element. This operator is typically used to pro...
Problem manager is used to build and partition problems.