1093 PetscBool periodic_mode,
1094 PetscInt phase_step,
1095 PetscInt samples_before,
1096 PetscBool *has_reference_out,
1097 PetscReal *u_abs_l2_out,
1098 PetscReal *u_rel_l2_out,
1099 PetscReal *p_abs_l2_out,
1100 PetscReal *p_rel_l2_out,
1101 PetscReal *mean_speed_out,
1102 PetscReal *mean_speed_ref_out,
1103 PetscReal *mean_speed_abs_out,
1104 PetscReal *mean_speed_rel_out,
1105 PetscReal *mean_ke_out,
1106 PetscReal *mean_ke_ref_out,
1107 PetscReal *mean_ke_abs_out,
1108 PetscReal *mean_ke_rel_out)
1114 PetscReal current_pressure_mean = 0.0;
1115 PetscReal reference_pressure_mean = 0.0;
1118 PetscFunctionBeginUser;
1119 if (!simCtx || !has_reference_out || !u_abs_l2_out || !u_rel_l2_out || !p_abs_l2_out || !p_rel_l2_out ||
1120 !mean_speed_out || !mean_speed_ref_out || !mean_speed_abs_out || !mean_speed_rel_out ||
1121 !mean_ke_out || !mean_ke_ref_out || !mean_ke_abs_out || !mean_ke_rel_out) {
1122 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"ComputeDeterministicSolutionMetrics received a NULL output pointer.");
1125 *has_reference_out = periodic_mode
1128 phase_step < simCtx->solutionConvergencePeriodSteps &&
1130 : (PetscBool)(samples_before > 0);
1132 *u_abs_l2_out = 0.0;
1133 *u_rel_l2_out = 0.0;
1134 *p_abs_l2_out = 0.0;
1135 *p_rel_l2_out = 0.0;
1136 *mean_speed_out = 0.0;
1137 *mean_speed_ref_out = 0.0;
1138 *mean_speed_abs_out = 0.0;
1139 *mean_speed_rel_out = 0.0;
1141 *mean_ke_ref_out = 0.0;
1142 *mean_ke_abs_out = 0.0;
1143 *mean_ke_rel_out = 0.0;
1147 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1148 const DMDALocalInfo info = user[bi].
info;
1149 const PetscBool x_per = (PetscBool)(simCtx->
i_periodic != 0);
1150 const PetscBool y_per = (PetscBool)(simCtx->
j_periodic != 0);
1151 const PetscBool z_per = (PetscBool)(simCtx->
k_periodic != 0);
1152 const PetscInt i_end = (x_per && (info.xs + info.xm == info.mx)) ? info.mx - 1 : info.xs + info.xm;
1153 const PetscInt j_end = (y_per && (info.ys + info.ym == info.my)) ? info.my - 1 : info.ys + info.ym;
1154 const PetscInt k_end = (z_per && (info.zs + info.zm == info.mz)) ? info.mz - 1 : info.zs + info.zm;
1156 Cmpnts ***ucat_ref = NULL;
1157 PetscReal ***pressure = NULL;
1158 PetscReal ***pressure_ref = NULL;
1159 PetscReal ***aj = NULL;
1160 PetscReal ***nvert = NULL;
1161 Vec ucat_reference_vec = NULL;
1162 Vec pressure_reference_vec = NULL;
1164 if (*has_reference_out) {
1165 if (periodic_mode) {
1169 ucat_reference_vec = user[bi].
Ucat_o;
1170 pressure_reference_vec = user[bi].
P_o;
1174 PetscCall(DMDAVecGetArrayRead(user[bi].fda, user[bi].Ucat, &ucat));
1175 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].P, &pressure));
1176 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Aj, &aj));
1177 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1178 if (*has_reference_out) {
1179 PetscCall(DMDAVecGetArrayRead(user[bi].fda, ucat_reference_vec, &ucat_ref));
1180 PetscCall(DMDAVecGetArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1183 for (PetscInt k = info.zs; k < k_end; ++k) {
1184 for (PetscInt j = info.ys; j < j_end; ++j) {
1185 for (PetscInt i = info.xs; i < i_end; ++i) {
1186 PetscReal jac = aj[k][j][i];
1187 PetscReal cell_volume = 0.0;
1188 PetscReal speed = 0.0;
1192 if (PetscAbsReal(jac) <= 1.0e-14)
continue;
1194 cell_volume = 1.0 / jac;
1195 speed = PetscSqrtReal(ucat[k][j][i].x * ucat[k][j][i].x +
1196 ucat[k][j][i].y * ucat[k][j][i].y +
1197 ucat[k][j][i].z * ucat[k][j][i].z);
1198 ke = 0.5 * speed * speed;
1204 ucat[k][j][i].
y * ucat[k][j][i].
y +
1205 ucat[k][j][i].
z * ucat[k][j][i].
z) * cell_volume;
1207 if (*has_reference_out) {
1208 PetscReal ref_speed = PetscSqrtReal(ucat_ref[k][j][i].x * ucat_ref[k][j][i].x +
1209 ucat_ref[k][j][i].y * ucat_ref[k][j][i].y +
1210 ucat_ref[k][j][i].z * ucat_ref[k][j][i].z);
1211 PetscReal ref_ke = 0.5 * ref_speed * ref_speed;
1212 PetscReal dux = ucat[k][j][i].
x - ucat_ref[k][j][i].
x;
1213 PetscReal duy = ucat[k][j][i].
y - ucat_ref[k][j][i].
y;
1214 PetscReal duz = ucat[k][j][i].
z - ucat_ref[k][j][i].
z;
1218 local_pass1.
delta_u_norm_sq += (dux * dux + duy * duy + duz * duz) * cell_volume;
1226 if (*has_reference_out) {
1227 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1228 PetscCall(DMDAVecRestoreArrayRead(user[bi].fda, ucat_reference_vec, &ucat_ref));
1230 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1231 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Aj, &aj));
1232 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].P, &pressure));
1233 PetscCall(DMDAVecRestoreArrayRead(user[bi].fda, user[bi].Ucat, &ucat));
1236 PetscCallMPI(MPI_Allreduce(&local_pass1, &global_pass1,
1238 MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
1240 if (global_pass1.
fluid_volume <= 0.0) PetscFunctionReturn(0);
1245 if (!*has_reference_out) PetscFunctionReturn(0);
1248 *mean_speed_abs_out = PetscAbsReal(*mean_speed_out - *mean_speed_ref_out);
1251 *mean_ke_abs_out = PetscAbsReal(*mean_ke_out - *mean_ke_ref_out);
1257 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1258 const DMDALocalInfo info = user[bi].
info;
1259 const PetscBool x_per = (PetscBool)(simCtx->
i_periodic != 0);
1260 const PetscBool y_per = (PetscBool)(simCtx->
j_periodic != 0);
1261 const PetscBool z_per = (PetscBool)(simCtx->
k_periodic != 0);
1262 const PetscInt i_end = (x_per && (info.xs + info.xm == info.mx)) ? info.mx - 1 : info.xs + info.xm;
1263 const PetscInt j_end = (y_per && (info.ys + info.ym == info.my)) ? info.my - 1 : info.ys + info.ym;
1264 const PetscInt k_end = (z_per && (info.zs + info.zm == info.mz)) ? info.mz - 1 : info.zs + info.zm;
1265 PetscReal ***pressure = NULL;
1266 PetscReal ***pressure_ref = NULL;
1267 PetscReal ***aj = NULL;
1268 PetscReal ***nvert = NULL;
1271 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].P, &pressure));
1272 PetscCall(DMDAVecGetArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1273 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Aj, &aj));
1274 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1276 for (PetscInt k = info.zs; k < k_end; ++k) {
1277 for (PetscInt j = info.ys; j < j_end; ++j) {
1278 for (PetscInt i = info.xs; i < i_end; ++i) {
1279 PetscReal jac = aj[k][j][i];
1280 PetscReal cell_volume = 0.0;
1281 PetscReal current_pressure = 0.0;
1282 PetscReal reference_pressure = 0.0;
1283 PetscReal delta_pressure = 0.0;
1286 if (PetscAbsReal(jac) <= 1.0e-14)
continue;
1288 cell_volume = 1.0 / jac;
1289 current_pressure = pressure[k][j][i] - current_pressure_mean;
1290 reference_pressure = pressure_ref[k][j][i] - reference_pressure_mean;
1291 delta_pressure = current_pressure - reference_pressure;
1299 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1300 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Aj, &aj));
1301 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1302 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].P, &pressure));
1305 PetscCallMPI(MPI_Allreduce(&local_pass2, &global_pass2,
1307 MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
1314 PetscFunctionReturn(0);
1451 PetscInt samples_available,
1452 PetscBool *has_reference_out,
1453 PetscReal *mean_speed_window_out,
1454 PetscReal *mean_speed_window_prev_out,
1455 PetscReal *mean_speed_window_abs_out,
1456 PetscReal *mean_speed_window_rel_out,
1457 PetscReal *mean_speed_rms_window_out,
1458 PetscReal *mean_speed_rms_window_prev_out,
1459 PetscReal *mean_speed_rms_window_abs_out,
1460 PetscReal *mean_speed_rms_window_rel_out,
1461 PetscReal *mean_ke_window_out,
1462 PetscReal *mean_ke_window_prev_out,
1463 PetscReal *mean_ke_window_abs_out,
1464 PetscReal *mean_ke_window_rel_out,
1465 PetscReal *mean_ke_rms_window_out,
1466 PetscReal *mean_ke_rms_window_prev_out,
1467 PetscReal *mean_ke_rms_window_abs_out,
1468 PetscReal *mean_ke_rms_window_rel_out)
1471 PetscInt history_capacity = 0;
1472 PetscReal speed_sum = 0.0;
1473 PetscReal speed_sum_sq = 0.0;
1474 PetscReal speed_prev_sum = 0.0;
1475 PetscReal speed_prev_sum_sq = 0.0;
1476 PetscReal ke_sum = 0.0;
1477 PetscReal ke_sum_sq = 0.0;
1478 PetscReal ke_prev_sum = 0.0;
1479 PetscReal ke_prev_sum_sq = 0.0;
1481 PetscFunctionBeginUser;
1482 if (!simCtx || !has_reference_out || !mean_speed_window_out || !mean_speed_window_prev_out ||
1483 !mean_speed_window_abs_out || !mean_speed_window_rel_out || !mean_speed_rms_window_out ||
1484 !mean_speed_rms_window_prev_out || !mean_speed_rms_window_abs_out || !mean_speed_rms_window_rel_out ||
1485 !mean_ke_window_out || !mean_ke_window_prev_out || !mean_ke_window_abs_out || !mean_ke_window_rel_out ||
1486 !mean_ke_rms_window_out || !mean_ke_rms_window_prev_out || !mean_ke_rms_window_abs_out ||
1487 !mean_ke_rms_window_rel_out) {
1488 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"ComputeStatisticalWindowMetrics received a NULL output pointer.");
1491 *has_reference_out = PETSC_FALSE;
1492 *mean_speed_window_out = 0.0;
1493 *mean_speed_window_prev_out = 0.0;
1494 *mean_speed_window_abs_out = 0.0;
1495 *mean_speed_window_rel_out = 0.0;
1496 *mean_speed_rms_window_out = 0.0;
1497 *mean_speed_rms_window_prev_out = 0.0;
1498 *mean_speed_rms_window_abs_out = 0.0;
1499 *mean_speed_rms_window_rel_out = 0.0;
1500 *mean_ke_window_out = 0.0;
1501 *mean_ke_window_prev_out = 0.0;
1502 *mean_ke_window_abs_out = 0.0;
1503 *mean_ke_window_rel_out = 0.0;
1504 *mean_ke_rms_window_out = 0.0;
1505 *mean_ke_rms_window_prev_out = 0.0;
1506 *mean_ke_rms_window_abs_out = 0.0;
1507 *mean_ke_rms_window_rel_out = 0.0;
1510 history_capacity = 2 * w;
1511 if (w <= 0 || samples_available < w) PetscFunctionReturn(0);
1513 for (PetscInt idx = 0; idx < w; ++idx) {
1522 speed_sum += speed_value;
1523 speed_sum_sq += speed_value * speed_value;
1525 ke_sum_sq += ke_value * ke_value;
1528 *mean_speed_window_out = speed_sum / (PetscReal)w;
1529 *mean_speed_rms_window_out = PetscSqrtReal(PetscMax(0.0, speed_sum_sq / (PetscReal)w -
1530 (*mean_speed_window_out) * (*mean_speed_window_out)));
1531 *mean_ke_window_out = ke_sum / (PetscReal)w;
1532 *mean_ke_rms_window_out = PetscSqrtReal(PetscMax(0.0, ke_sum_sq / (PetscReal)w -
1533 (*mean_ke_window_out) * (*mean_ke_window_out)));
1535 if (samples_available < 2 * w) PetscFunctionReturn(0);
1537 for (PetscInt idx = w; idx < 2 * w; ++idx) {
1546 speed_prev_sum += speed_value;
1547 speed_prev_sum_sq += speed_value * speed_value;
1548 ke_prev_sum += ke_value;
1549 ke_prev_sum_sq += ke_value * ke_value;
1552 *has_reference_out = PETSC_TRUE;
1553 *mean_speed_window_prev_out = speed_prev_sum / (PetscReal)w;
1554 *mean_speed_window_abs_out = PetscAbsReal(*mean_speed_window_out - *mean_speed_window_prev_out);
1556 *mean_speed_rms_window_prev_out = PetscSqrtReal(PetscMax(0.0, speed_prev_sum_sq / (PetscReal)w -
1557 (*mean_speed_window_prev_out) * (*mean_speed_window_prev_out)));
1558 *mean_speed_rms_window_abs_out = PetscAbsReal(*mean_speed_rms_window_out - *mean_speed_rms_window_prev_out);
1561 *mean_ke_window_prev_out = ke_prev_sum / (PetscReal)w;
1562 *mean_ke_window_abs_out = PetscAbsReal(*mean_ke_window_out - *mean_ke_window_prev_out);
1564 *mean_ke_rms_window_prev_out = PetscSqrtReal(PetscMax(0.0, ke_prev_sum_sq / (PetscReal)w -
1565 (*mean_ke_window_prev_out) * (*mean_ke_window_prev_out)));
1566 *mean_ke_rms_window_abs_out = PetscAbsReal(*mean_ke_rms_window_out - *mean_ke_rms_window_prev_out);
1569 PetscFunctionReturn(0);
1602 PetscMPIInt rank = 0;
1603 PetscBool has_reference = PETSC_FALSE;
1604 PetscInt phase_step = -1;
1605 PetscInt samples_before = 0;
1606 PetscReal u_abs_l2 = 0.0, u_rel_l2 = 0.0, p_abs_l2 = 0.0, p_rel_l2 = 0.0;
1607 PetscReal mean_speed = 0.0, mean_speed_reference = 0.0, mean_speed_abs_drift = 0.0, mean_speed_rel_drift = 0.0;
1608 PetscReal mean_ke = 0.0, mean_ke_reference = 0.0, mean_ke_abs_drift = 0.0, mean_ke_rel_drift = 0.0;
1609 PetscReal mean_speed_window = 0.0, mean_speed_window_prev = 0.0, mean_speed_window_abs_drift = 0.0, mean_speed_window_rel_drift = 0.0;
1610 PetscReal mean_speed_rms_window = 0.0, mean_speed_rms_window_prev = 0.0, mean_speed_rms_window_abs_drift = 0.0, mean_speed_rms_window_rel_drift = 0.0;
1611 PetscReal mean_ke_window = 0.0, mean_ke_window_prev = 0.0, mean_ke_window_abs_drift = 0.0, mean_ke_window_rel_drift = 0.0;
1612 PetscReal mean_ke_rms_window = 0.0, mean_ke_rms_window_prev = 0.0, mean_ke_rms_window_abs_drift = 0.0, mean_ke_rms_window_rel_drift = 0.0;
1614 PetscFunctionBeginUser;
1615 if (!simCtx) PetscFunctionReturn(0);
1626 &u_abs_l2, &u_rel_l2,
1627 &p_abs_l2, &p_rel_l2,
1628 &mean_speed, &mean_speed_reference,
1629 &mean_speed_abs_drift, &mean_speed_rel_drift,
1630 &mean_ke, &mean_ke_reference,
1631 &mean_ke_abs_drift, &mean_ke_rel_drift));
1637 &u_abs_l2, &u_rel_l2,
1638 &p_abs_l2, &p_rel_l2,
1639 &mean_speed, &mean_speed_reference,
1640 &mean_speed_abs_drift, &mean_speed_rel_drift,
1641 &mean_ke, &mean_ke_reference,
1642 &mean_ke_abs_drift, &mean_ke_rel_drift));
1649 &mean_speed_window, &mean_speed_window_prev,
1650 &mean_speed_window_abs_drift, &mean_speed_window_rel_drift,
1651 &mean_speed_rms_window, &mean_speed_rms_window_prev,
1652 &mean_speed_rms_window_abs_drift, &mean_speed_rms_window_rel_drift,
1653 &mean_ke_window, &mean_ke_window_prev,
1654 &mean_ke_window_abs_drift, &mean_ke_window_rel_drift,
1655 &mean_ke_rms_window, &mean_ke_rms_window_prev,
1656 &mean_ke_rms_window_abs_drift, &mean_ke_rms_window_rel_drift));
1659 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Unknown solution convergence mode %d.", (
int)simCtx->
solutionConvergenceMode);
1662 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1664 char log_path[PETSC_MAX_PATH_LEN + 32];
1668 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1669 f = fopen(log_path,
"a");
1671 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Cannot open solution convergence log: %s", log_path);
1674 if (ftell(f) == 0) {
1678 fprintf(f,
"==================== Solution Convergence Log [mode: %s] ====================\n", mode_str);
1680 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1681 "step",
"time",
"mode",
"ref",
1682 "u_abs_l2",
"u_rel_l2",
"p_abs_l2",
"p_rel_l2",
1683 "mean_speed",
"spd_ref",
"spd_abs",
"spd_rel",
1684 "mean_ke",
"ke_ref",
"ke_abs",
"ke_rel");
1685 fprintf(f,
"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1688 fprintf(f,
"==================== Solution Convergence Log [mode: %s | period_steps: %d] ====================\n",
1691 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-5s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1692 "step",
"time",
"mode",
"ref",
"ph",
"per",
1693 "u_abs_l2",
"u_rel_l2",
"p_abs_l2",
"p_rel_l2",
1694 "mean_speed",
"spd_ref",
"spd_abs",
"spd_rel",
1695 "mean_ke",
"ke_ref",
"ke_abs",
"ke_rel");
1696 fprintf(f,
"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1699 fprintf(f,
"==================== Solution Convergence Log [mode: %s | window_steps: %d] ====================\n",
1702 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1703 "step",
"time",
"mode",
"ref",
"win",
1704 "mean_speed",
"mean_ke",
1705 "spd_win",
"spd_win_prev",
"spd_win_abs",
"spd_win_rel",
1706 "spd_rms_win",
"spd_rms_abs",
"spd_rms_rel",
1707 "ke_win",
"ke_win_prev",
"ke_win_abs",
"ke_win_rel",
1708 "ke_rms_win",
"ke_rms_abs",
"ke_rms_rel");
1709 fprintf(f,
"------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1715 fprintf(f,
"# Continuation from step %" PetscInt_FMT
"\n", simCtx->
StartStep);
1722 "%-10d | %-18.10e | %-22s | %-3d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1723 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1724 (double)u_abs_l2, (
double)u_rel_l2, (double)p_abs_l2, (
double)p_rel_l2,
1725 (double)mean_speed, (
double)mean_speed_reference,
1726 (double)mean_speed_abs_drift, (
double)mean_speed_rel_drift,
1727 (double)mean_ke, (
double)mean_ke_reference,
1728 (double)mean_ke_abs_drift, (
double)mean_ke_rel_drift);
1732 "%-10d | %-18.10e | %-22s | %-3d | %-5d | %-5d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1733 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1735 (double)u_abs_l2, (
double)u_rel_l2, (double)p_abs_l2, (
double)p_rel_l2,
1736 (double)mean_speed, (
double)mean_speed_reference,
1737 (double)mean_speed_abs_drift, (
double)mean_speed_rel_drift,
1738 (double)mean_ke, (
double)mean_ke_reference,
1739 (double)mean_ke_abs_drift, (
double)mean_ke_rel_drift);
1743 "%-10d | %-18.10e | %-22s | %-3d | %-5d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1744 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1746 (
double)mean_speed, (double)mean_ke,
1747 (
double)mean_speed_window, (double)mean_speed_window_prev,
1748 (
double)mean_speed_window_abs_drift, (double)mean_speed_window_rel_drift,
1749 (
double)mean_speed_rms_window,
1750 (double)mean_speed_rms_window_abs_drift, (
double)mean_speed_rms_window_rel_drift,
1751 (double)mean_ke_window, (
double)mean_ke_window_prev,
1752 (double)mean_ke_window_abs_drift, (
double)mean_ke_window_rel_drift,
1753 (double)mean_ke_rms_window,
1754 (
double)mean_ke_rms_window_abs_drift, (double)mean_ke_rms_window_rel_drift);
1762 phase_step >= 0 && phase_step < simCtx->solutionConvergencePeriodSteps) {
1764 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1765 PetscCall(VecCopy(user[bi].Ucat, user[bi].solutionConvergencePeriodicUcatRef[phase_step]));
1766 PetscCall(VecCopy(user[bi].P, user[bi].solutionConvergencePeriodicPRef[phase_step]));
1772 PetscFunctionReturn(0);
2480 const char *stage_name, DM dm,
2481 Vec vec_local, PetscInt dof,
2484 PetscErrorCode ierr;
2488 char dominant_dir =
'\0';
2490 PetscFunctionBeginUser;
2491 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2493 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
2494 PetscCheck(field_name != NULL && stage_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2495 "Field and stage labels cannot be NULL.");
2496 PetscCheck(dm != NULL && vec_local != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
2497 "Field '%s' has no available DM/local vector for anatomy logging.", field_name);
2498 PetscCheck(dof == 1 || dof == 3, PETSC_COMM_SELF, PETSC_ERR_SUP,
2499 "Field anatomy logging supports one- or three-component fields; '%s' has %d.",
2508 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
2510 ierr = PetscBarrier(NULL);
2511 PetscPrintf(PETSC_COMM_WORLD,
"\n--- Field Anatomy Log: [%s] | Stage: [%s] | Layout: [%s] ---\n", field_name, stage_name, data_layout);
2514 PetscInt im_phys = user->
IM;
2515 PetscInt jm_phys = user->
JM;
2516 PetscInt km_phys = user->
KM;
2519 PetscInt i_mid = (PetscInt)(info.xs + 0.5 * info.xm) - 1;
2520 PetscInt j_mid = (PetscInt)(info.ys + 0.5 * info.ym) - 1;
2521 PetscInt k_mid = (PetscInt)(info.zs + 0.5 * info.zm) - 1;
2530 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2535 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][0]) = ", rank, 0);
2536 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][0]);
2537 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][j_mid][0].x, ((
const Cmpnts***)l_arr)[k_mid][j_mid][0].y, ((
const Cmpnts***)l_arr)[k_mid][j_mid][0].z);
2539 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][0]) = ", rank, 1);
2540 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][1]);
2541 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][j_mid][1].x, ((
const Cmpnts***)l_arr)[k_mid][j_mid][1].y, ((
const Cmpnts***)l_arr)[k_mid][j_mid][1].z);
2543 if (info.xs + info.xm == info.mx) {
2544 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][%d]) = ", rank, im_phys - 1, im_phys - 2);
2545 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][im_phys - 1]);
2546 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].x, ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].y, ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].z);
2548 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][%d]) = ", rank, im_phys, im_phys - 2);
2549 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][im_phys]);
2550 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].x, ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].y, ((
const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].z);
2555 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][0][i]) = ", rank, 0);
2556 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][0][i_mid]);
2557 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][0][i_mid].x, ((
const Cmpnts***)l_arr)[k_mid][0][i_mid].y, ((
const Cmpnts***)l_arr)[k_mid][0][i_mid].z);
2559 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][0][i]) = ", rank, 1);
2560 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][1][i_mid]);
2561 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][1][i_mid].x, ((
const Cmpnts***)l_arr)[k_mid][1][i_mid].y, ((
const Cmpnts***)l_arr)[k_mid][1][i_mid].z);
2564 if (info.ys + info.ym == info.my) {
2565 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][%d][i]) = ", rank, jm_phys - 1, jm_phys - 2);
2566 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][jm_phys - 1][i_mid]);
2567 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].x, ((
const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].y, ((
const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].z);
2569 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][%d][i]) = ", rank, jm_phys, jm_phys - 2);
2570 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][jm_phys][i_mid]);
2571 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].x, ((
const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].y, ((
const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].z);
2576 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[0][j][i]) = ", rank, 0);
2577 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[0][j_mid][i_mid]);
2578 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[0][j_mid][i_mid].x, ((
const Cmpnts***)l_arr)[0][j_mid][i_mid].y, ((
const Cmpnts***)l_arr)[0][j_mid][i_mid].z);
2579 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Value for Cell[0][j][i]) = ", rank, 1);
2580 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[1][j_mid][i_mid]);
2581 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[1][j_mid][i_mid].x, ((
const Cmpnts***)l_arr)[1][j_mid][i_mid].y, ((
const Cmpnts***)l_arr)[1][j_mid][i_mid].z);
2583 if (info.zs + info.zm == info.mz) {
2584 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Value for Cell[%d][j][i]) = ", rank, km_phys - 1, km_phys - 2);
2585 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[km_phys - 1][j_mid][i_mid]);
2586 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].x, ((
const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].y, ((
const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].z);
2587 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[%d][j][i]) = ", rank, km_phys, km_phys - 2);
2588 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[km_phys][j_mid][i_mid]);
2589 else PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f, %.5f, %.5f)\n", ((
const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].x, ((
const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].y, ((
const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].z);
2591 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2601 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2605 if (dominant_dir ==
'x') {
2606 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (First Phys. X-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
2607 }
else if (dominant_dir ==
'y' || dominant_dir ==
'z') {
2608 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][0]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
2609 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][0]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[k_mid][j_mid][1].x, l_arr[k_mid][j_mid][1].y, l_arr[k_mid][j_mid][1].z);
2610 }
else if (dominant_dir ==
'm') {
2611 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: u-comp @ Idx %2d (1st X-Face) = %.5f\n", rank, 0, l_arr[k_mid][j_mid][0].x);
2614 if (info.xs + info.xm == info.mx) {
2615 if (dominant_dir ==
'x') {
2616 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Last Phys. X-Face) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys-1].y, l_arr[k_mid][j_mid][im_phys - 1].z);
2617 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
2618 }
else if (dominant_dir ==
'y' || dominant_dir ==
'z') {
2619 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][%d]) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, im_phys - 2, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys - 1].y, l_arr[k_mid][j_mid][im_phys-1].z);
2620 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][%d]) = (%.5f, %.5f, %.5f)\n", rank, im_phys, im_phys - 2, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
2621 }
else if (dominant_dir ==
'm') {
2622 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: u-comp @ Idx %2d (Last X-Face) = %.5f\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x);
2623 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: u-comp @ Idx %2d (Ghost Location) = %.5f\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x);
2629 if (dominant_dir ==
'y') {
2630 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (First Phys. Y-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
2631 }
else if (dominant_dir ==
'x' || dominant_dir ==
'z') {
2632 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][0][i]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
2633 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][0][i]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[k_mid][1][i_mid].x, l_arr[k_mid][1][i_mid].y, l_arr[k_mid][1][i_mid].z);
2634 }
else if (dominant_dir ==
'm') {
2635 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: v-comp @ Jdx %2d (1st Y-Face) = %.5f\n", rank, 0, l_arr[k_mid][0][i_mid].y);
2638 if (info.ys + info.ym == info.my) {
2639 if (dominant_dir ==
'y') {
2640 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Last Phys. Y-Face) = (%.5f, %.5f, %.5f)\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
2641 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
2642 }
else if (dominant_dir ==
'x' || dominant_dir ==
'z') {
2643 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][%d][i]) = (%.5f, %.5f, %.5f)\n", rank, jm_phys-1, jm_phys-2, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
2644 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][%d][i]) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, jm_phys-2, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
2645 }
else if (dominant_dir ==
'm') {
2646 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: v-comp @ Jdx %2d (Last Y-Face) = %.5f\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].y);
2647 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: v-comp @ Jdx %2d (Ghost Location) = %.5f\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].y);
2653 if (dominant_dir ==
'z') {
2654 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (First Phys. Z-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
2655 }
else if (dominant_dir ==
'x' || dominant_dir ==
'y') {
2656 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[0][j][i]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
2657 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Value for Cell[0][j][i]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[1][j_mid][i_mid].x, l_arr[1][j_mid][i_mid].y, l_arr[1][j_mid][i_mid].z);
2658 }
else if (dominant_dir ==
'm') {
2659 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: w-comp @ Idx %2d (1st Z-Face) = %.5f\n", rank, 0, l_arr[0][j_mid][i_mid].z);
2662 if (info.zs + info.zm == info.mz) {
2663 if (dominant_dir ==
'z') {
2664 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Idx %2d (Last Phys. Z-Face) = (%.5f, %.5f, %.5f)\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].x, l_arr[km_phys - 1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
2665 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Idx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
2666 }
else if (dominant_dir ==
'x' || dominant_dir ==
'y') {
2667 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Idx %2d (Value for Cell[%d][j][i]) = (%.5f, %.5f, %.5f)\n", rank, km_phys-1, km_phys-2, l_arr[km_phys-1][j_mid][i_mid].x, l_arr[km_phys-1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
2668 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Idx %2d (Ghost for Cell[%d][j][i]) = (%.5f, %.5f, %.5f)\n", rank, km_phys, km_phys-2, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
2669 }
else if (dominant_dir ==
'm') {
2670 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: w-comp @ Idx %2d (Last Z-Face) = %.5f\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].z);
2671 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: w-comp @ Idx %2d (Ghost Loc.) = %.5f\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].z);
2675 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2682 const PetscReal ***l_arr;
2683 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2686 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[k_mid][j_mid][0]);
2687 if (info.xs + info.xm == info.mx) {
2688 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Last Phys. Node) = %.5f\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1]);
2689 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Unused/Ghost Loc) = %.5f\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys]);
2692 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[k_mid][0][i_mid]);
2693 if (info.ys + info.ym == info.my) {
2694 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Last Phys. Node) = %.5f\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid]);
2695 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Unused/Ghost Loc) = %.5f\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid]);
2698 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[0][j_mid][i_mid]);
2699 if (info.zs + info.zm == info.mz) {
2700 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Last Phys. Node) = %.5f\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid]);
2701 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Unused/Ghost Loc) = %.5f\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid]);
2703 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2706 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2710 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
2712 if (info.xs + info.xm == info.mx) {
2713 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys - 1].y, l_arr[k_mid][j_mid][im_phys - 1].z);
2714 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
2718 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
2720 if (info.ys + info.ym == info.my) {
2721 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
2722 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
2726 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
2728 if(info.zs + info.zm == info.mz) {
2729 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].x, l_arr[km_phys - 1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
2730 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
2732 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2736 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
2737 "LOG_FIELD_ANATOMY encountered unsupported layout %d for field '%s'.",
2738 (
int)layout, field_name);
2741 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
2742 ierr = PetscBarrier(NULL);
2743 PetscFunctionReturn(0);
2946 PetscErrorCode ierr;
2949 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
2950 PetscInt lxs, lxe, lys, lye, lzs, lze;
2951 Vec reference_vec = NULL;
2952 PetscReal ***psi = NULL;
2953 PetscReal ***psi_ref = NULL;
2954 PetscReal ***aj = NULL;
2955 PetscReal ***count = NULL;
2956 PetscReal *particle_psi = NULL;
2957 PetscInt nlocal = 0;
2958 PetscReal local_l1 = 0.0, global_l1 = 0.0;
2959 PetscReal local_l2_sq = 0.0, global_l2_sq = 0.0;
2960 PetscReal local_linf = 0.0, global_linf = 0.0;
2961 PetscReal local_ref_l2_sq = 0.0, global_ref_l2_sq = 0.0;
2962 PetscReal local_grid_integral = 0.0, global_grid_integral = 0.0;
2963 PetscReal local_domain_volume = 0.0, global_domain_volume = 0.0;
2964 PetscReal local_particle_sum = 0.0, global_particle_sum = 0.0;
2965 PetscInt64 local_particle_count = 0, global_particle_count = 0;
2966 PetscInt64 local_cell_count = 0, global_cell_count = 0;
2967 PetscInt64 local_occupied_count = 0, global_occupied_count = 0;
2968 PetscReal particle_integral = 0.0;
2969 PetscReal occupancy_fraction = 0.0;
2970 PetscReal mean_particles_per_occupied_cell = 0.0;
2971 PetscReal l2_error = 0.0;
2972 PetscReal relative_l2_error = 0.0;
2974 PetscFunctionBeginUser;
2975 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
2978 PetscFunctionReturn(0);
2982 xs = info.xs; xe = info.xs + info.xm;
2983 ys = info.ys; ye = info.ys + info.ym;
2984 zs = info.zs; ze = info.zs + info.zm;
2985 mx = info.mx; my = info.my; mz = info.mz;
2986 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
2987 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
2988 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
2990 ierr = VecDuplicate(user->
Psi, &reference_vec); CHKERRQ(ierr);
2993 ierr = DMDAVecGetArrayRead(user->
da, user->
Psi, &psi); CHKERRQ(ierr);
2994 ierr = DMDAVecGetArrayRead(user->
da, reference_vec, &psi_ref); CHKERRQ(ierr);
2995 ierr = DMDAVecGetArrayRead(user->
da, user->
Aj, &aj); CHKERRQ(ierr);
2996 ierr = DMDAVecGetArrayRead(user->
da, user->
ParticleCount, &count); CHKERRQ(ierr);
2998 for (PetscInt k = lzs; k < lze; ++k) {
2999 for (PetscInt j = lys; j < lye; ++j) {
3000 for (PetscInt i = lxs; i < lxe; ++i) {
3001 const PetscReal cell_volume = (PetscAbsReal(aj[k][j][i]) > 1.0e-14) ? (1.0 / aj[k][j][i]) : 0.0;
3002 const PetscReal err = psi[k][j][i] - psi_ref[k][j][i];
3003 local_cell_count += 1;
3004 local_domain_volume += cell_volume;
3005 local_grid_integral += psi[k][j][i] * cell_volume;
3006 local_l1 += PetscAbsReal(err) * cell_volume;
3007 local_l2_sq += err * err * cell_volume;
3008 local_ref_l2_sq += psi_ref[k][j][i] * psi_ref[k][j][i] * cell_volume;
3009 local_linf = PetscMax(local_linf, PetscAbsReal(err));
3010 if (count[k][j][i] > 0.0) local_occupied_count += 1;
3015 ierr = DMDAVecRestoreArrayRead(user->
da, user->
ParticleCount, &count); CHKERRQ(ierr);
3016 ierr = DMDAVecRestoreArrayRead(user->
da, user->
Aj, &aj); CHKERRQ(ierr);
3017 ierr = DMDAVecRestoreArrayRead(user->
da, reference_vec, &psi_ref); CHKERRQ(ierr);
3018 ierr = DMDAVecRestoreArrayRead(user->
da, user->
Psi, &psi); CHKERRQ(ierr);
3019 ierr = VecDestroy(&reference_vec); CHKERRQ(ierr);
3021 ierr = DMSwarmGetLocalSize(user->
swarm, &nlocal); CHKERRQ(ierr);
3022 local_particle_count = (PetscInt64)nlocal;
3025 for (PetscInt p = 0; p < nlocal; ++p) local_particle_sum += particle_psi[p];
3029 ierr = MPI_Allreduce(&local_l1, &global_l1, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3030 ierr = MPI_Allreduce(&local_l2_sq, &global_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3031 ierr = MPI_Allreduce(&local_linf, &global_linf, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3032 ierr = MPI_Allreduce(&local_ref_l2_sq, &global_ref_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3033 ierr = MPI_Allreduce(&local_grid_integral, &global_grid_integral, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3034 ierr = MPI_Allreduce(&local_domain_volume, &global_domain_volume, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3035 ierr = MPI_Allreduce(&local_particle_sum, &global_particle_sum, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3036 ierr = MPI_Allreduce(&local_particle_count, &global_particle_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3037 ierr = MPI_Allreduce(&local_cell_count, &global_cell_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3038 ierr = MPI_Allreduce(&local_occupied_count, &global_occupied_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3040 l2_error = PetscSqrtReal(global_l2_sq);
3041 relative_l2_error = (global_ref_l2_sq > 0.0) ? (l2_error / PetscSqrtReal(global_ref_l2_sq)) : 0.0;
3042 occupancy_fraction = (global_cell_count > 0) ? ((PetscReal)global_occupied_count / (PetscReal)global_cell_count) : 0.0;
3043 mean_particles_per_occupied_cell =
3044 (global_occupied_count > 0) ? ((PetscReal)global_particle_count / (PetscReal)global_occupied_count) : 0.0;
3046 (global_particle_count > 0) ? (global_domain_volume * global_particle_sum / (PetscReal)global_particle_count) : 0.0;
3048 if (simCtx->
rank == 0) {
3049 char csv_path[PETSC_MAX_PATH_LEN + 32];
3051 ierr = PetscSNPrintf(csv_path,
sizeof(csv_path),
"%s/scatter_metrics.csv", simCtx->
log_dir); CHKERRQ(ierr);
3052 f = fopen(csv_path,
"a");
3054 if (ftell(f) == 0) {
3056 "step,time,total_particles,total_cells,occupied_cells,occupancy_fraction,"
3057 "mean_particles_per_occupied_cell,particle_integral,grid_integral,"
3058 "conservation_error_abs,L1_error,L2_error,Linf_error,relative_L2_error\n");
3061 fprintf(f,
"# Continuation from step %" PetscInt_FMT
"\n", simCtx->
StartStep);
3063 fprintf(f,
"%d,%.6e,%lld,%lld,%lld,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e\n",
3066 (
long long)global_particle_count,
3067 (
long long)global_cell_count,
3068 (
long long)global_occupied_count,
3069 (
double)occupancy_fraction,
3070 (
double)mean_particles_per_occupied_cell,
3071 (
double)particle_integral,
3072 (
double)global_grid_integral,
3073 (
double)PetscAbsReal(global_grid_integral - particle_integral),
3076 (
double)global_linf,
3077 (
double)relative_l2_error);
3087 PetscFunctionReturn(0);