996 {
1000
1001 auto dm =
simple->getDM();
1004
1005 auto set_section_monitor = [&](auto solver) {
1007 SNES snes;
1008 CHKERR TSGetSNES(solver, &snes);
1009 CHKERR SNESMonitorSet(snes,
1012 (void *)(snes_ctx_ptr.get()), nullptr);
1014 };
1015
1016 auto create_post_process_element = [&]() {
1017 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
1018
1019 auto block_params = boost::make_shared<BlockedParameters>();
1020 auto mD_ptr = block_params->getDPtr();
1022 "MAT_FLUID", block_params, Sev::verbose);
1024 post_proc_fe->getOpPtrVector(), {H1, HDIV});
1025
1026 auto mat_grad_ptr = boost::make_shared<MatrixDouble>();
1027 auto mat_strain_ptr = boost::make_shared<MatrixDouble>();
1028 auto mat_stress_ptr = boost::make_shared<MatrixDouble>();
1029
1030 auto p_ptr = boost::make_shared<VectorDouble>();
1031 auto mat_flux_ptr = boost::make_shared<MatrixDouble>();
1032
1033 post_proc_fe->getOpPtrVector().push_back(
1035 post_proc_fe->getOpPtrVector().push_back(
1037
1038 auto u_ptr = boost::make_shared<MatrixDouble>();
1039 post_proc_fe->getOpPtrVector().push_back(
1041 post_proc_fe->getOpPtrVector().push_back(
1043 mat_grad_ptr));
1044 post_proc_fe->getOpPtrVector().push_back(
1046 post_proc_fe->getOpPtrVector().push_back(
1048 mat_strain_ptr, mat_stress_ptr, mD_ptr));
1049
1051
1052 post_proc_fe->getOpPtrVector().push_back(
1053
1055
1056 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1057
1058 {{"P", p_ptr}},
1059
1060 {{"U", u_ptr}, {"FLUX", mat_flux_ptr}},
1061
1062 {},
1063
1064 {{"STRAIN", mat_strain_ptr}, {"STRESS", mat_stress_ptr}}
1065
1066 )
1067
1068 );
1069
1070 return post_proc_fe;
1071 };
1072
1073 auto create_creaction_fe = [&]() {
1074 auto fe_ptr = boost::make_shared<DomainEle>(
mField);
1075 fe_ptr->getRuleHook = [](
int,
int,
int o) {
return 2 * o; };
1076
1077 auto &pip = fe_ptr->getOpPtrVector();
1078
1079 auto block_params = boost::make_shared<BlockedParameters>();
1080 auto mD_ptr = block_params->getDPtr();
1082 Sev::verbose);
1084
1085 auto u_grad_ptr = boost::make_shared<MatrixDouble>();
1086 auto strain_ptr = boost::make_shared<MatrixDouble>();
1087 auto stress_ptr = boost::make_shared<MatrixDouble>();
1088
1090 "U", u_grad_ptr));
1092
1093
1095 strain_ptr, stress_ptr, mD_ptr));
1097
1098 fe_ptr->postProcessHook =
1100
1101 return fe_ptr;
1102 };
1103
1104 auto monitor_ptr = boost::make_shared<FEMethod>();
1105 auto post_proc_fe = create_post_process_element();
1107 auto rections_fe = create_creaction_fe();
1108
1109 auto set_time_monitor = [&](auto dm, auto solver) {
1111 monitor_ptr->preProcessHook = [&]() {
1113
1115
1117 post_proc_fe,
1118 monitor_ptr->getCacheWeakPtr());
1119 CHKERR post_proc_fe->writeFile(
1120 "out_" + boost::lexical_cast<std::string>(monitor_ptr->ts_step) +
1121 ".h5m");
1122 }
1123
1124 rections_fe->f = res;
1126 rections_fe,
1127 monitor_ptr->getCacheWeakPtr());
1128
1129 CHKERR VecAssemblyBegin(res);
1130 CHKERR VecAssemblyEnd(res);
1131 double nrm;
1132 CHKERR VecNorm(res, NORM_2, &nrm);
1134 << "Residual norm " << nrm << " at time step "
1135 << monitor_ptr->ts_step;
1136
1137 struct AtomTestResult {
1138 bool fail = false;
1139 std::string msg = "";
1140 };
1141
1142 AtomTestResult atom_test_result;
1143
1144 auto fail_atom_test = [&atom_test_result](const std::string &msg) {
1145 if (!atom_test_result.fail) {
1146 atom_test_result.fail = true;
1147 atom_test_result.msg = msg;
1148 }
1149 };
1150
1151
1152 struct AtomTestData {
1153 double expected = 0.0;
1155 };
1156
1157
1159
1161 ->evalFEAtThePoint<SPACE_DIM>(
1166
1168 auto eval_num_vec =
1170 CHKERR VecZeroEntries(eval_num_vec);
1172 CHKERR VecSetValue(eval_num_vec, 0, 1, ADD_VALUES);
1173 }
1174 CHKERR VecAssemblyBegin(eval_num_vec);
1175 CHKERR VecAssemblyEnd(eval_num_vec);
1176
1177 double eval_num;
1178 CHKERR VecSum(eval_num_vec, &eval_num);
1179 if (!(int)eval_num) {
1180 fail_atom_test(
1181 "did not find elements to evaluate the field, check the "
1182 "coordinates");
1183 }
1184 }
1185
1186 if (
atom_test && fabs(monitor_ptr->ts_t - 0.1) < 1e-12 &&
1192 << "Eval point P: " << t_pressure;
1193 double pressure = 0.0;
1194
1196 auto t_flux = getFTensor1FromMat<SPACE_DIM>(*
fluxFieldPtr);
1197 auto flux_mag = sqrt(t_flux(
i) * t_flux(
i));
1199 << "Eval point FLUX magnitude: " << flux_mag;
1200 double flux = 0.0;
1201
1202 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*
dispFieldPtr);
1203 auto disp_mag = sqrt(t_disp(
i) * t_disp(
i));
1205 << "Eval point U magnitude: " << disp_mag;
1206 double disp = 0.0;
1207
1208 auto t_strain = getFTensor2SymmetricFromMat<SPACE_DIM>(*
strainFieldPtr);
1209 auto t_strain_trace = t_strain(
i,
i);
1211 << "Eval point trace of strain: " << t_strain_trace;
1212 double strain = 0.0;
1213
1214 double von_mises_stress;
1215 auto getVonMisesStress = [&](auto t_stress) {
1217 von_mises_stress = std::sqrt(
1218 0.5 *
1219 ((t_stress(0, 0) - t_stress(1, 1)) *
1220 (t_stress(0, 0) - t_stress(1, 1)) +
1221 (
SPACE_DIM == 3 ? (t_stress(1, 1) - t_stress(2, 2)) *
1222 (t_stress(1, 1) - t_stress(2, 2))
1223 : 0) +
1224 (
SPACE_DIM == 3 ? (t_stress(2, 2) - t_stress(0, 0)) *
1225 (t_stress(2, 2) - t_stress(0, 0))
1226 : 0) +
1227 6 * (t_stress(0, 1) * t_stress(0, 1) +
1228 (
SPACE_DIM == 3 ? t_stress(1, 2) * t_stress(1, 2) : 0) +
1229 (
SPACE_DIM == 3 ? t_stress(2, 0) * t_stress(2, 0) : 0))));
1231 };
1232 auto t_stress =
1234 CHKERR getVonMisesStress(t_stress);
1236 << "Eval point von Mises Stress: " << von_mises_stress;
1237 double stress = 0.0;
1238
1240 case 1:
1241 pressure = 0.0002681;
1242 flux = 0.0001734;
1243 disp = 0.0009;
1244 strain = 0.0009;
1245 stress = 53.037;
1246 break;
1247
1248 case 2:
1249 pressure = 0.0063046;
1250 flux = 0.000093771;
1251 disp = 0.000859577;
1252 strain = 0.0009;
1253 stress = 75.00;
1254 break;
1255
1256 case 3:
1257 pressure = 0.31473;
1258 flux = 0.0009216;
1259 disp = 0.0135;
1260 strain = 0.036392;
1261 stress = 356.956;
1262 break;
1263
1264 default:
1265 fail_atom_test("unknown atom test number");
1266 }
1267 if (fabs(t_pressure + pressure) > 1e-4) {
1268 fail_atom_test("wrong pressure value");
1269 }
1270 if (fabs(flux_mag - flux) > 1e-6) {
1271 fail_atom_test("wrong flux value");
1272 }
1273 if (fabs(disp_mag - disp) > 1e-2) {
1274 fail_atom_test("wrong displacement value");
1275 }
1276 if (fabs(t_strain_trace + strain) > 1e-3) {
1277 fail_atom_test("wrong strain value");
1278 }
1279 if (fabs(von_mises_stress - stress) > 1e-2) {
1280 fail_atom_test("wrong stress value");
1281 }
1282 }
1283
1284 auto current_time_step = monitor_ptr->ts_step;
1285 PetscReal current_time;
1286 CHKERR TSGetTime(solver, ¤t_time);
1287
1289
1301 <<
"Eval point elasticity matrix: " << *
mDPtr;
1302 }
1304 }
1305
1306 int fail_flag = atom_test_result.fail ? 1 : 0;
1307 MPI_Allreduce(MPI_IN_PLACE, &fail_flag, 1, MPI_INT, MPI_MAX,
mField.
get_comm());
1308
1309 if (fail_flag) {
1310 const int root = 0;
1311 const int MAX_MSG = 512;
1312
1313 char msg_buf[MAX_MSG];
1314 msg_buf[0] = '\0';
1315
1316 if (atom_test_result.fail) {
1317 std::snprintf(msg_buf, MAX_MSG, "%s", atom_test_result.msg.c_str());
1318 }
1320 int send_rank = atom_test_result.fail ? my_rank : INT_MAX;
1321 MPI_Allreduce(MPI_IN_PLACE, &send_rank, 1, MPI_INT, MPI_MIN,
mField.
get_comm());
1322 MPI_Bcast(msg_buf, MAX_MSG, MPI_CHAR, send_rank,
mField.
get_comm());
1323
1324 if (my_rank == root) {
1326 "atom test %d failed: %s",
atom_test, msg_buf);
1327 }
1328
1330 "Atom test failed");
1331 }
1332
1334 };
1335
1336 auto null = boost::shared_ptr<FEMethod>();
1338 monitor_ptr, null);
1340 };
1341
1342 auto set_fieldsplit_preconditioner = [&](auto solver) {
1344
1345 SNES snes;
1346 CHKERR TSGetSNES(solver, &snes);
1347 KSP ksp;
1348 CHKERR SNESGetKSP(snes, &ksp);
1349 PC pc;
1350 CHKERR KSPGetPC(ksp, &pc);
1351 PetscBool is_pcfs = PETSC_FALSE;
1352 PetscObjectTypeCompare((PetscObject)pc, PCFIELDSPLIT, &is_pcfs);
1353
1354
1355 if (is_pcfs == PETSC_TRUE) {
1358 auto name_prb =
simple->getProblemName();
1359
1361 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb,
ROW,
"U", 0,
1364 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb,
ROW,
"FLUX", 0, 0,
1365 is_flux);
1367 CHKERR is_mng->isCreateProblemFieldAndRank(name_prb,
ROW,
"P", 0, 0,
1368 is_P);
1369 IS is_tmp;
1370 CHKERR ISExpand(is_P, is_flux, &is_tmp);
1372
1373 auto is_all_bc = bc_mng->getBlockIS(name_prb, "FLUIDFLUX", "FLUX", 0, 0);
1374 int is_all_bc_size;
1375 CHKERR ISGetSize(is_all_bc, &is_all_bc_size);
1377 << "Field split block size " << is_all_bc_size;
1378 if (is_all_bc_size) {
1379 IS is_tmp2;
1380 CHKERR ISDifference(is_Flux, is_all_bc, &is_tmp2);
1382 CHKERR PCFieldSplitSetIS(pc, PETSC_NULLPTR,
1383 is_all_bc);
1384 }
1385
1388 CHKERR PCFieldSplitSetIS(pc, PETSC_NULLPTR, is_Flux);
1389 CHKERR PCFieldSplitSetIS(pc, PETSC_NULLPTR, is_u);
1390 }
1391
1393 };
1394
1395 auto pre_proc_ptr = boost::make_shared<FEMethod>();
1396 auto post_proc_rhs_ptr = boost::make_shared<FEMethod>();
1397 auto post_proc_lhs_ptr = boost::make_shared<FEMethod>();
1398 auto time_scale = boost::make_shared<TimeScale>();
1399
1400 auto get_bc_hook_rhs = [this, pre_proc_ptr, time_scale]() {
1402 {time_scale}, false);
1403 return hook;
1404 };
1405
1406 auto get_post_proc_hook_rhs = [this, post_proc_rhs_ptr]() {
1409 mField, post_proc_rhs_ptr,
nullptr, Sev::verbose)();
1411 mField, post_proc_rhs_ptr, 1.)();
1413 };
1414 auto get_post_proc_hook_lhs = [this, post_proc_lhs_ptr]() {
1416 post_proc_lhs_ptr, 1.);
1417 };
1418
1419 pre_proc_ptr->preProcessHook = get_bc_hook_rhs();
1420 post_proc_rhs_ptr->postProcessHook = get_post_proc_hook_rhs;
1421 post_proc_lhs_ptr->postProcessHook = get_post_proc_hook_lhs();
1422
1424 ts_ctx_ptr->getPreProcessIFunction().push_front(pre_proc_ptr);
1425 ts_ctx_ptr->getPreProcessIJacobian().push_front(pre_proc_ptr);
1426 ts_ctx_ptr->getPostProcessIFunction().push_back(post_proc_rhs_ptr);
1427 ts_ctx_ptr->getPostProcessIJacobian().push_back(post_proc_lhs_ptr);
1428
1430 CHKERR TSSetIJacobian(solver,
B,
B, PETSC_NULLPTR, PETSC_NULLPTR);
1432 CHKERR TSSetSolution(solver,
D);
1433 CHKERR TSSetFromOptions(solver);
1434
1435 CHKERR set_section_monitor(solver);
1436 CHKERR set_fieldsplit_preconditioner(solver);
1437 CHKERR set_time_monitor(dm, solver);
1438
1440 CHKERR TSSolve(solver, NULL);
1441
1443}
@ MOFEM_ATOM_TEST_INVALID
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
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)
Get smart vector from DM.
auto createDMMatrix(DM dm)
Get smart matrix from DM.
SmartPetscObj< TS > createTSIM(SmartPetscObj< DM > dm=nullptr)
Create TS (time) implicit solver.
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.
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
MoFEMErrorCode MoFEMSNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, SnesCtx *ctx)
Sens monitor printing residual field by field.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
Class (Function) to enforce essential constrains on the left hand side diagonal.
Class (Function) to enforce essential constrains on the right hand side diagonal.
Class (Function) to calculate residual side diagonal.
Class (Function) to enforce essential constrains.
Section manager is used to create indexes and sections.
Post post-proc data at points from hash maps.
intrusive_ptr for managing petsc objects