1188 PetscBool periodic_mode,
1189 PetscInt phase_step,
1190 PetscInt samples_before,
1191 PetscBool *has_reference_out,
1192 PetscReal *u_abs_l2_out,
1193 PetscReal *u_rel_l2_out,
1194 PetscReal *p_abs_l2_out,
1195 PetscReal *p_rel_l2_out,
1196 PetscReal *mean_speed_out,
1197 PetscReal *mean_speed_ref_out,
1198 PetscReal *mean_speed_abs_out,
1199 PetscReal *mean_speed_rel_out,
1200 PetscReal *mean_ke_out,
1201 PetscReal *mean_ke_ref_out,
1202 PetscReal *mean_ke_abs_out,
1203 PetscReal *mean_ke_rel_out)
1209 PetscReal current_pressure_mean = 0.0;
1210 PetscReal reference_pressure_mean = 0.0;
1213 PetscFunctionBeginUser;
1214 if (!simCtx || !has_reference_out || !u_abs_l2_out || !u_rel_l2_out || !p_abs_l2_out || !p_rel_l2_out ||
1215 !mean_speed_out || !mean_speed_ref_out || !mean_speed_abs_out || !mean_speed_rel_out ||
1216 !mean_ke_out || !mean_ke_ref_out || !mean_ke_abs_out || !mean_ke_rel_out) {
1217 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"ComputeDeterministicSolutionMetrics received a NULL output pointer.");
1220 *has_reference_out = periodic_mode
1223 phase_step < simCtx->solutionConvergencePeriodSteps &&
1225 : (PetscBool)(samples_before > 0);
1227 *u_abs_l2_out = 0.0;
1228 *u_rel_l2_out = 0.0;
1229 *p_abs_l2_out = 0.0;
1230 *p_rel_l2_out = 0.0;
1231 *mean_speed_out = 0.0;
1232 *mean_speed_ref_out = 0.0;
1233 *mean_speed_abs_out = 0.0;
1234 *mean_speed_rel_out = 0.0;
1236 *mean_ke_ref_out = 0.0;
1237 *mean_ke_abs_out = 0.0;
1238 *mean_ke_rel_out = 0.0;
1242 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1243 const DMDALocalInfo info = user[bi].
info;
1247 const PetscInt i_start = PetscMax(info.xs, 1), i_end = PetscMin(info.xs + info.xm, info.mx - 1);
1248 const PetscInt j_start = PetscMax(info.ys, 1), j_end = PetscMin(info.ys + info.ym, info.my - 1);
1249 const PetscInt k_start = PetscMax(info.zs, 1), k_end = PetscMin(info.zs + info.zm, info.mz - 1);
1251 Cmpnts ***ucat_ref = NULL;
1252 PetscReal ***pressure = NULL;
1253 PetscReal ***pressure_ref = NULL;
1254 PetscReal ***aj = NULL;
1255 PetscReal ***nvert = NULL;
1256 Vec ucat_reference_vec = NULL;
1257 Vec pressure_reference_vec = NULL;
1259 if (*has_reference_out) {
1260 if (periodic_mode) {
1264 ucat_reference_vec = user[bi].
Ucat_o;
1265 pressure_reference_vec = user[bi].
P_o;
1269 PetscCall(DMDAVecGetArrayRead(user[bi].fda, user[bi].Ucat, &ucat));
1270 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].P, &pressure));
1271 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Aj, &aj));
1272 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1273 if (*has_reference_out) {
1274 PetscCall(DMDAVecGetArrayRead(user[bi].fda, ucat_reference_vec, &ucat_ref));
1275 PetscCall(DMDAVecGetArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1278 for (PetscInt k = k_start; k < k_end; ++k) {
1279 for (PetscInt j = j_start; j < j_end; ++j) {
1280 for (PetscInt i = i_start; i < i_end; ++i) {
1281 PetscReal jac = aj[k][j][i];
1282 PetscReal cell_volume = 0.0;
1283 PetscReal speed = 0.0;
1287 if (PetscAbsReal(jac) <= 1.0e-14)
continue;
1289 cell_volume = 1.0 / jac;
1290 speed = PetscSqrtReal(ucat[k][j][i].x * ucat[k][j][i].x +
1291 ucat[k][j][i].y * ucat[k][j][i].y +
1292 ucat[k][j][i].z * ucat[k][j][i].z);
1293 ke = 0.5 * speed * speed;
1299 ucat[k][j][i].
y * ucat[k][j][i].
y +
1300 ucat[k][j][i].
z * ucat[k][j][i].
z) * cell_volume;
1302 if (*has_reference_out) {
1303 PetscReal ref_speed = PetscSqrtReal(ucat_ref[k][j][i].x * ucat_ref[k][j][i].x +
1304 ucat_ref[k][j][i].y * ucat_ref[k][j][i].y +
1305 ucat_ref[k][j][i].z * ucat_ref[k][j][i].z);
1306 PetscReal ref_ke = 0.5 * ref_speed * ref_speed;
1307 PetscReal dux = ucat[k][j][i].
x - ucat_ref[k][j][i].
x;
1308 PetscReal duy = ucat[k][j][i].
y - ucat_ref[k][j][i].
y;
1309 PetscReal duz = ucat[k][j][i].
z - ucat_ref[k][j][i].
z;
1313 local_pass1.
delta_u_norm_sq += (dux * dux + duy * duy + duz * duz) * cell_volume;
1321 if (*has_reference_out) {
1322 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1323 PetscCall(DMDAVecRestoreArrayRead(user[bi].fda, ucat_reference_vec, &ucat_ref));
1325 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1326 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Aj, &aj));
1327 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].P, &pressure));
1328 PetscCall(DMDAVecRestoreArrayRead(user[bi].fda, user[bi].Ucat, &ucat));
1331 PetscCallMPI(MPI_Allreduce(&local_pass1, &global_pass1,
1333 MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
1335 if (global_pass1.
fluid_volume <= 0.0) PetscFunctionReturn(0);
1340 if (!*has_reference_out) PetscFunctionReturn(0);
1343 *mean_speed_abs_out = PetscAbsReal(*mean_speed_out - *mean_speed_ref_out);
1346 *mean_ke_abs_out = PetscAbsReal(*mean_ke_out - *mean_ke_ref_out);
1352 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1353 const DMDALocalInfo info = user[bi].
info;
1357 const PetscInt i_start = PetscMax(info.xs, 1), i_end = PetscMin(info.xs + info.xm, info.mx - 1);
1358 const PetscInt j_start = PetscMax(info.ys, 1), j_end = PetscMin(info.ys + info.ym, info.my - 1);
1359 const PetscInt k_start = PetscMax(info.zs, 1), k_end = PetscMin(info.zs + info.zm, info.mz - 1);
1360 PetscReal ***pressure = NULL;
1361 PetscReal ***pressure_ref = NULL;
1362 PetscReal ***aj = NULL;
1363 PetscReal ***nvert = NULL;
1366 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].P, &pressure));
1367 PetscCall(DMDAVecGetArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1368 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Aj, &aj));
1369 PetscCall(DMDAVecGetArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1371 for (PetscInt k = k_start; k < k_end; ++k) {
1372 for (PetscInt j = j_start; j < j_end; ++j) {
1373 for (PetscInt i = i_start; i < i_end; ++i) {
1374 PetscReal jac = aj[k][j][i];
1375 PetscReal cell_volume = 0.0;
1376 PetscReal current_pressure = 0.0;
1377 PetscReal reference_pressure = 0.0;
1378 PetscReal delta_pressure = 0.0;
1381 if (PetscAbsReal(jac) <= 1.0e-14)
continue;
1383 cell_volume = 1.0 / jac;
1384 current_pressure = pressure[k][j][i] - current_pressure_mean;
1385 reference_pressure = pressure_ref[k][j][i] - reference_pressure_mean;
1386 delta_pressure = current_pressure - reference_pressure;
1394 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Nvert, &nvert));
1395 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].Aj, &aj));
1396 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, pressure_reference_vec, &pressure_ref));
1397 PetscCall(DMDAVecRestoreArrayRead(user[bi].da, user[bi].P, &pressure));
1400 PetscCallMPI(MPI_Allreduce(&local_pass2, &global_pass2,
1402 MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
1409 PetscFunctionReturn(0);
1546 PetscInt samples_available,
1547 PetscBool *has_reference_out,
1548 PetscReal *mean_speed_window_out,
1549 PetscReal *mean_speed_window_prev_out,
1550 PetscReal *mean_speed_window_abs_out,
1551 PetscReal *mean_speed_window_rel_out,
1552 PetscReal *mean_speed_rms_window_out,
1553 PetscReal *mean_speed_rms_window_prev_out,
1554 PetscReal *mean_speed_rms_window_abs_out,
1555 PetscReal *mean_speed_rms_window_rel_out,
1556 PetscReal *mean_ke_window_out,
1557 PetscReal *mean_ke_window_prev_out,
1558 PetscReal *mean_ke_window_abs_out,
1559 PetscReal *mean_ke_window_rel_out,
1560 PetscReal *mean_ke_rms_window_out,
1561 PetscReal *mean_ke_rms_window_prev_out,
1562 PetscReal *mean_ke_rms_window_abs_out,
1563 PetscReal *mean_ke_rms_window_rel_out)
1566 PetscInt history_capacity = 0;
1567 PetscReal speed_sum = 0.0;
1568 PetscReal speed_sum_sq = 0.0;
1569 PetscReal speed_prev_sum = 0.0;
1570 PetscReal speed_prev_sum_sq = 0.0;
1571 PetscReal ke_sum = 0.0;
1572 PetscReal ke_sum_sq = 0.0;
1573 PetscReal ke_prev_sum = 0.0;
1574 PetscReal ke_prev_sum_sq = 0.0;
1576 PetscFunctionBeginUser;
1577 if (!simCtx || !has_reference_out || !mean_speed_window_out || !mean_speed_window_prev_out ||
1578 !mean_speed_window_abs_out || !mean_speed_window_rel_out || !mean_speed_rms_window_out ||
1579 !mean_speed_rms_window_prev_out || !mean_speed_rms_window_abs_out || !mean_speed_rms_window_rel_out ||
1580 !mean_ke_window_out || !mean_ke_window_prev_out || !mean_ke_window_abs_out || !mean_ke_window_rel_out ||
1581 !mean_ke_rms_window_out || !mean_ke_rms_window_prev_out || !mean_ke_rms_window_abs_out ||
1582 !mean_ke_rms_window_rel_out) {
1583 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"ComputeStatisticalWindowMetrics received a NULL output pointer.");
1586 *has_reference_out = PETSC_FALSE;
1587 *mean_speed_window_out = 0.0;
1588 *mean_speed_window_prev_out = 0.0;
1589 *mean_speed_window_abs_out = 0.0;
1590 *mean_speed_window_rel_out = 0.0;
1591 *mean_speed_rms_window_out = 0.0;
1592 *mean_speed_rms_window_prev_out = 0.0;
1593 *mean_speed_rms_window_abs_out = 0.0;
1594 *mean_speed_rms_window_rel_out = 0.0;
1595 *mean_ke_window_out = 0.0;
1596 *mean_ke_window_prev_out = 0.0;
1597 *mean_ke_window_abs_out = 0.0;
1598 *mean_ke_window_rel_out = 0.0;
1599 *mean_ke_rms_window_out = 0.0;
1600 *mean_ke_rms_window_prev_out = 0.0;
1601 *mean_ke_rms_window_abs_out = 0.0;
1602 *mean_ke_rms_window_rel_out = 0.0;
1605 history_capacity = 2 * w;
1606 if (w <= 0 || samples_available < w) PetscFunctionReturn(0);
1608 for (PetscInt idx = 0; idx < w; ++idx) {
1617 speed_sum += speed_value;
1618 speed_sum_sq += speed_value * speed_value;
1620 ke_sum_sq += ke_value * ke_value;
1623 *mean_speed_window_out = speed_sum / (PetscReal)w;
1624 *mean_speed_rms_window_out = PetscSqrtReal(PetscMax(0.0, speed_sum_sq / (PetscReal)w -
1625 (*mean_speed_window_out) * (*mean_speed_window_out)));
1626 *mean_ke_window_out = ke_sum / (PetscReal)w;
1627 *mean_ke_rms_window_out = PetscSqrtReal(PetscMax(0.0, ke_sum_sq / (PetscReal)w -
1628 (*mean_ke_window_out) * (*mean_ke_window_out)));
1630 if (samples_available < 2 * w) PetscFunctionReturn(0);
1632 for (PetscInt idx = w; idx < 2 * w; ++idx) {
1641 speed_prev_sum += speed_value;
1642 speed_prev_sum_sq += speed_value * speed_value;
1643 ke_prev_sum += ke_value;
1644 ke_prev_sum_sq += ke_value * ke_value;
1647 *has_reference_out = PETSC_TRUE;
1648 *mean_speed_window_prev_out = speed_prev_sum / (PetscReal)w;
1649 *mean_speed_window_abs_out = PetscAbsReal(*mean_speed_window_out - *mean_speed_window_prev_out);
1651 *mean_speed_rms_window_prev_out = PetscSqrtReal(PetscMax(0.0, speed_prev_sum_sq / (PetscReal)w -
1652 (*mean_speed_window_prev_out) * (*mean_speed_window_prev_out)));
1653 *mean_speed_rms_window_abs_out = PetscAbsReal(*mean_speed_rms_window_out - *mean_speed_rms_window_prev_out);
1656 *mean_ke_window_prev_out = ke_prev_sum / (PetscReal)w;
1657 *mean_ke_window_abs_out = PetscAbsReal(*mean_ke_window_out - *mean_ke_window_prev_out);
1659 *mean_ke_rms_window_prev_out = PetscSqrtReal(PetscMax(0.0, ke_prev_sum_sq / (PetscReal)w -
1660 (*mean_ke_window_prev_out) * (*mean_ke_window_prev_out)));
1661 *mean_ke_rms_window_abs_out = PetscAbsReal(*mean_ke_rms_window_out - *mean_ke_rms_window_prev_out);
1664 PetscFunctionReturn(0);
1697 PetscMPIInt rank = 0;
1698 PetscBool has_reference = PETSC_FALSE;
1699 PetscInt phase_step = -1;
1700 PetscInt samples_before = 0;
1701 PetscReal u_abs_l2 = 0.0, u_rel_l2 = 0.0, p_abs_l2 = 0.0, p_rel_l2 = 0.0;
1702 PetscReal mean_speed = 0.0, mean_speed_reference = 0.0, mean_speed_abs_drift = 0.0, mean_speed_rel_drift = 0.0;
1703 PetscReal mean_ke = 0.0, mean_ke_reference = 0.0, mean_ke_abs_drift = 0.0, mean_ke_rel_drift = 0.0;
1704 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;
1705 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;
1706 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;
1707 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;
1709 PetscFunctionBeginUser;
1710 if (!simCtx) PetscFunctionReturn(0);
1721 &u_abs_l2, &u_rel_l2,
1722 &p_abs_l2, &p_rel_l2,
1723 &mean_speed, &mean_speed_reference,
1724 &mean_speed_abs_drift, &mean_speed_rel_drift,
1725 &mean_ke, &mean_ke_reference,
1726 &mean_ke_abs_drift, &mean_ke_rel_drift));
1732 &u_abs_l2, &u_rel_l2,
1733 &p_abs_l2, &p_rel_l2,
1734 &mean_speed, &mean_speed_reference,
1735 &mean_speed_abs_drift, &mean_speed_rel_drift,
1736 &mean_ke, &mean_ke_reference,
1737 &mean_ke_abs_drift, &mean_ke_rel_drift));
1744 &mean_speed_window, &mean_speed_window_prev,
1745 &mean_speed_window_abs_drift, &mean_speed_window_rel_drift,
1746 &mean_speed_rms_window, &mean_speed_rms_window_prev,
1747 &mean_speed_rms_window_abs_drift, &mean_speed_rms_window_rel_drift,
1748 &mean_ke_window, &mean_ke_window_prev,
1749 &mean_ke_window_abs_drift, &mean_ke_window_rel_drift,
1750 &mean_ke_rms_window, &mean_ke_rms_window_prev,
1751 &mean_ke_rms_window_abs_drift, &mean_ke_rms_window_rel_drift));
1754 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Unknown solution convergence mode %d.", (
int)simCtx->
solutionConvergenceMode);
1757 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1759 char log_path[PETSC_MAX_PATH_LEN + 32];
1763 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1764 f = fopen(log_path,
"a");
1766 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Cannot open solution convergence log: %s", log_path);
1769 if (ftell(f) == 0) {
1773 fprintf(f,
"==================== Solution Convergence Log [mode: %s] ====================\n", mode_str);
1775 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1776 "step",
"time",
"mode",
"ref",
1777 "u_abs_l2",
"u_rel_l2",
"p_abs_l2",
"p_rel_l2",
1778 "mean_speed",
"spd_ref",
"spd_abs",
"spd_rel",
1779 "mean_ke",
"ke_ref",
"ke_abs",
"ke_rel");
1780 fprintf(f,
"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1783 fprintf(f,
"==================== Solution Convergence Log [mode: %s | period_steps: %d] ====================\n",
1786 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-5s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1787 "step",
"time",
"mode",
"ref",
"ph",
"per",
1788 "u_abs_l2",
"u_rel_l2",
"p_abs_l2",
"p_rel_l2",
1789 "mean_speed",
"spd_ref",
"spd_abs",
"spd_rel",
1790 "mean_ke",
"ke_ref",
"ke_abs",
"ke_rel");
1791 fprintf(f,
"----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1794 fprintf(f,
"==================== Solution Convergence Log [mode: %s | window_steps: %d] ====================\n",
1797 fprintf(f,
"%-10s | %-18s | %-22s | %-3s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1798 "step",
"time",
"mode",
"ref",
"win",
1799 "mean_speed",
"mean_ke",
1800 "spd_win",
"spd_win_prev",
"spd_win_abs",
"spd_win_rel",
1801 "spd_rms_win",
"spd_rms_abs",
"spd_rms_rel",
1802 "ke_win",
"ke_win_prev",
"ke_win_abs",
"ke_win_rel",
1803 "ke_rms_win",
"ke_rms_abs",
"ke_rms_rel");
1804 fprintf(f,
"------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1810 fprintf(f,
"# Continuation from step %" PetscInt_FMT
"\n", simCtx->
StartStep);
1817 "%-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",
1818 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1819 (double)u_abs_l2, (
double)u_rel_l2, (double)p_abs_l2, (
double)p_rel_l2,
1820 (double)mean_speed, (
double)mean_speed_reference,
1821 (double)mean_speed_abs_drift, (
double)mean_speed_rel_drift,
1822 (double)mean_ke, (
double)mean_ke_reference,
1823 (double)mean_ke_abs_drift, (
double)mean_ke_rel_drift);
1827 "%-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",
1828 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1830 (double)u_abs_l2, (
double)u_rel_l2, (double)p_abs_l2, (
double)p_rel_l2,
1831 (double)mean_speed, (
double)mean_speed_reference,
1832 (double)mean_speed_abs_drift, (
double)mean_speed_rel_drift,
1833 (double)mean_ke, (
double)mean_ke_reference,
1834 (double)mean_ke_abs_drift, (
double)mean_ke_rel_drift);
1838 "%-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",
1839 (
int)simCtx->
step, (
double)simCtx->
ti, mode_str, has_reference ? 1 : 0,
1841 (
double)mean_speed, (double)mean_ke,
1842 (
double)mean_speed_window, (double)mean_speed_window_prev,
1843 (
double)mean_speed_window_abs_drift, (double)mean_speed_window_rel_drift,
1844 (
double)mean_speed_rms_window,
1845 (double)mean_speed_rms_window_abs_drift, (
double)mean_speed_rms_window_rel_drift,
1846 (double)mean_ke_window, (
double)mean_ke_window_prev,
1847 (double)mean_ke_window_abs_drift, (
double)mean_ke_window_rel_drift,
1848 (double)mean_ke_rms_window,
1849 (
double)mean_ke_rms_window_abs_drift, (double)mean_ke_rms_window_rel_drift);
1857 phase_step >= 0 && phase_step < simCtx->solutionConvergencePeriodSteps) {
1859 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
1860 PetscCall(VecCopy(user[bi].Ucat, user[bi].solutionConvergencePeriodicUcatRef[phase_step]));
1861 PetscCall(VecCopy(user[bi].P, user[bi].solutionConvergencePeriodicPRef[phase_step]));
1867 PetscFunctionReturn(0);
2589 const char *stage_name, DM dm,
2590 Vec vec_local, PetscInt dof,
2593 PetscErrorCode ierr;
2597 char dominant_dir =
'\0';
2599 PetscFunctionBeginUser;
2600 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2602 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
2603 PetscCheck(field_name != NULL && stage_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2604 "Field and stage labels cannot be NULL.");
2605 PetscCheck(dm != NULL && vec_local != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
2606 "Field '%s' has no available DM/local vector for anatomy logging.", field_name);
2607 PetscCheck(dof == 1 || dof == 3, PETSC_COMM_SELF, PETSC_ERR_SUP,
2608 "Field anatomy logging supports one- or three-component fields; '%s' has %d.",
2617 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
2619 ierr = PetscBarrier(NULL);
2620 PetscPrintf(PETSC_COMM_WORLD,
"\n--- Field Anatomy Log: [%s] | Stage: [%s] | Layout: [%s] ---\n", field_name, stage_name, data_layout);
2623 PetscInt im_phys = user->
IM;
2624 PetscInt jm_phys = user->
JM;
2625 PetscInt km_phys = user->
KM;
2628 PetscInt i_mid = (PetscInt)(info.xs + 0.5 * info.xm) - 1;
2629 PetscInt j_mid = (PetscInt)(info.ys + 0.5 * info.ym) - 1;
2630 PetscInt k_mid = (PetscInt)(info.zs + 0.5 * info.zm) - 1;
2639 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2644 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][0]) = ", rank, 0);
2645 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][0]);
2646 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);
2648 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][0]) = ", rank, 1);
2649 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][1]);
2650 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);
2652 if (info.xs + info.xm == info.mx) {
2653 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][%d]) = ", rank, im_phys - 1, im_phys - 2);
2654 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][im_phys - 1]);
2655 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);
2657 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][%d]) = ", rank, im_phys, im_phys - 2);
2658 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][j_mid][im_phys]);
2659 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);
2664 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][0][i]) = ", rank, 0);
2665 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][0][i_mid]);
2666 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);
2668 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][0][i]) = ", rank, 1);
2669 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][1][i_mid]);
2670 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);
2673 if (info.ys + info.ym == info.my) {
2674 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][%d][i]) = ", rank, jm_phys - 1, jm_phys - 2);
2675 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][jm_phys - 1][i_mid]);
2676 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);
2678 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][%d][i]) = ", rank, jm_phys, jm_phys - 2);
2679 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[k_mid][jm_phys][i_mid]);
2680 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);
2685 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[0][j][i]) = ", rank, 0);
2686 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[0][j_mid][i_mid]);
2687 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);
2688 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Value for Cell[0][j][i]) = ", rank, 1);
2689 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[1][j_mid][i_mid]);
2690 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);
2692 if (info.zs + info.zm == info.mz) {
2693 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Value for Cell[%d][j][i]) = ", rank, km_phys - 1, km_phys - 2);
2694 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[km_phys - 1][j_mid][i_mid]);
2695 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);
2696 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[%d][j][i]) = ", rank, km_phys, km_phys - 2);
2697 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"(%.5f)\n", ((
const PetscReal***)l_arr)[km_phys][j_mid][i_mid]);
2698 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);
2700 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2710 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2714 if (dominant_dir ==
'x') {
2715 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);
2716 }
else if (dominant_dir ==
'y' || dominant_dir ==
'z') {
2717 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);
2718 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);
2719 }
else if (dominant_dir ==
'm') {
2720 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);
2723 if (info.xs + info.xm == info.mx) {
2724 if (dominant_dir ==
'x') {
2725 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);
2726 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);
2727 }
else if (dominant_dir ==
'y' || dominant_dir ==
'z') {
2728 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);
2729 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);
2730 }
else if (dominant_dir ==
'm') {
2731 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);
2732 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);
2738 if (dominant_dir ==
'y') {
2739 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);
2740 }
else if (dominant_dir ==
'x' || dominant_dir ==
'z') {
2741 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);
2742 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);
2743 }
else if (dominant_dir ==
'm') {
2744 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);
2747 if (info.ys + info.ym == info.my) {
2748 if (dominant_dir ==
'y') {
2749 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);
2750 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);
2751 }
else if (dominant_dir ==
'x' || dominant_dir ==
'z') {
2752 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);
2753 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);
2754 }
else if (dominant_dir ==
'm') {
2755 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);
2756 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);
2762 if (dominant_dir ==
'z') {
2763 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);
2764 }
else if (dominant_dir ==
'x' || dominant_dir ==
'y') {
2765 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);
2766 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);
2767 }
else if (dominant_dir ==
'm') {
2768 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);
2771 if (info.zs + info.zm == info.mz) {
2772 if (dominant_dir ==
'z') {
2773 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);
2774 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);
2775 }
else if (dominant_dir ==
'x' || dominant_dir ==
'y') {
2776 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);
2777 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);
2778 }
else if (dominant_dir ==
'm') {
2779 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);
2780 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);
2784 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2791 const PetscReal ***l_arr;
2792 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2795 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, I-DIR]: Idx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[k_mid][j_mid][0]);
2796 if (info.xs + info.xm == info.mx) {
2797 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]);
2798 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]);
2801 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, J-DIR]: Jdx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[k_mid][0][i_mid]);
2802 if (info.ys + info.ym == info.my) {
2803 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]);
2804 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]);
2807 PetscSynchronizedPrintf(PETSC_COMM_WORLD,
"[Rank %d, K-DIR]: Kdx %2d (First Phys. Node) = %.5f\n", rank, 0, l_arr[0][j_mid][i_mid]);
2808 if (info.zs + info.zm == info.mz) {
2809 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]);
2810 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]);
2812 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2815 ierr = DMDAVecGetArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2819 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);
2821 if (info.xs + info.xm == info.mx) {
2822 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);
2823 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);
2827 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);
2829 if (info.ys + info.ym == info.my) {
2830 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);
2831 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);
2835 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);
2837 if(info.zs + info.zm == info.mz) {
2838 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);
2839 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);
2841 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (
void*)&l_arr); CHKERRQ(ierr);
2845 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
2846 "LOG_FIELD_ANATOMY encountered unsupported layout %d for field '%s'.",
2847 (
int)layout, field_name);
2850 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
2851 ierr = PetscBarrier(NULL);
2852 PetscFunctionReturn(0);
3058 PetscErrorCode ierr;
3061 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
3062 PetscInt lxs, lxe, lys, lye, lzs, lze;
3063 Vec reference_vec = NULL;
3064 PetscReal ***psi = NULL;
3065 PetscReal ***psi_ref = NULL;
3066 PetscReal ***aj = NULL;
3067 PetscReal ***count = NULL;
3068 PetscReal *particle_psi = NULL;
3069 PetscInt nlocal = 0;
3070 PetscReal local_l1 = 0.0, global_l1 = 0.0;
3071 PetscReal local_l2_sq = 0.0, global_l2_sq = 0.0;
3072 PetscReal local_linf = 0.0, global_linf = 0.0;
3073 PetscReal local_ref_l2_sq = 0.0, global_ref_l2_sq = 0.0;
3074 PetscReal local_grid_integral = 0.0, global_grid_integral = 0.0;
3075 PetscReal local_domain_volume = 0.0, global_domain_volume = 0.0;
3076 PetscReal local_particle_sum = 0.0, global_particle_sum = 0.0;
3077 PetscInt64 local_particle_count = 0, global_particle_count = 0;
3078 PetscInt64 local_cell_count = 0, global_cell_count = 0;
3079 PetscInt64 local_occupied_count = 0, global_occupied_count = 0;
3080 PetscReal particle_integral = 0.0;
3081 PetscReal occupancy_fraction = 0.0;
3082 PetscReal mean_particles_per_occupied_cell = 0.0;
3083 PetscReal l2_error = 0.0;
3084 PetscReal relative_l2_error = 0.0;
3086 PetscFunctionBeginUser;
3087 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
3090 PetscFunctionReturn(0);
3094 xs = info.xs; xe = info.xs + info.xm;
3095 ys = info.ys; ye = info.ys + info.ym;
3096 zs = info.zs; ze = info.zs + info.zm;
3097 mx = info.mx; my = info.my; mz = info.mz;
3098 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
3099 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
3100 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
3102 ierr = VecDuplicate(user->
Psi, &reference_vec); CHKERRQ(ierr);
3105 ierr = DMDAVecGetArrayRead(user->
da, user->
Psi, &psi); CHKERRQ(ierr);
3106 ierr = DMDAVecGetArrayRead(user->
da, reference_vec, &psi_ref); CHKERRQ(ierr);
3107 ierr = DMDAVecGetArrayRead(user->
da, user->
Aj, &aj); CHKERRQ(ierr);
3108 ierr = DMDAVecGetArrayRead(user->
da, user->
ParticleCount, &count); CHKERRQ(ierr);
3110 for (PetscInt k = lzs; k < lze; ++k) {
3111 for (PetscInt j = lys; j < lye; ++j) {
3112 for (PetscInt i = lxs; i < lxe; ++i) {
3113 const PetscReal cell_volume = (PetscAbsReal(aj[k][j][i]) > 1.0e-14) ? (1.0 / aj[k][j][i]) : 0.0;
3114 const PetscReal err = psi[k][j][i] - psi_ref[k][j][i];
3115 local_cell_count += 1;
3116 local_domain_volume += cell_volume;
3117 local_grid_integral += psi[k][j][i] * cell_volume;
3118 local_l1 += PetscAbsReal(err) * cell_volume;
3119 local_l2_sq += err * err * cell_volume;
3120 local_ref_l2_sq += psi_ref[k][j][i] * psi_ref[k][j][i] * cell_volume;
3121 local_linf = PetscMax(local_linf, PetscAbsReal(err));
3122 if (count[k][j][i] > 0.0) local_occupied_count += 1;
3127 ierr = DMDAVecRestoreArrayRead(user->
da, user->
ParticleCount, &count); CHKERRQ(ierr);
3128 ierr = DMDAVecRestoreArrayRead(user->
da, user->
Aj, &aj); CHKERRQ(ierr);
3129 ierr = DMDAVecRestoreArrayRead(user->
da, reference_vec, &psi_ref); CHKERRQ(ierr);
3130 ierr = DMDAVecRestoreArrayRead(user->
da, user->
Psi, &psi); CHKERRQ(ierr);
3131 ierr = VecDestroy(&reference_vec); CHKERRQ(ierr);
3133 ierr = DMSwarmGetLocalSize(user->
swarm, &nlocal); CHKERRQ(ierr);
3134 local_particle_count = (PetscInt64)nlocal;
3137 for (PetscInt p = 0; p < nlocal; ++p) local_particle_sum += particle_psi[p];
3141 ierr = MPI_Allreduce(&local_l1, &global_l1, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3142 ierr = MPI_Allreduce(&local_l2_sq, &global_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3143 ierr = MPI_Allreduce(&local_linf, &global_linf, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3144 ierr = MPI_Allreduce(&local_ref_l2_sq, &global_ref_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3145 ierr = MPI_Allreduce(&local_grid_integral, &global_grid_integral, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3146 ierr = MPI_Allreduce(&local_domain_volume, &global_domain_volume, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3147 ierr = MPI_Allreduce(&local_particle_sum, &global_particle_sum, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3148 ierr = MPI_Allreduce(&local_particle_count, &global_particle_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3149 ierr = MPI_Allreduce(&local_cell_count, &global_cell_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3150 ierr = MPI_Allreduce(&local_occupied_count, &global_occupied_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3152 l2_error = PetscSqrtReal(global_l2_sq);
3153 relative_l2_error = (global_ref_l2_sq > 0.0) ? (l2_error / PetscSqrtReal(global_ref_l2_sq)) : 0.0;
3154 occupancy_fraction = (global_cell_count > 0) ? ((PetscReal)global_occupied_count / (PetscReal)global_cell_count) : 0.0;
3155 mean_particles_per_occupied_cell =
3156 (global_occupied_count > 0) ? ((PetscReal)global_particle_count / (PetscReal)global_occupied_count) : 0.0;
3158 (global_particle_count > 0) ? (global_domain_volume * global_particle_sum / (PetscReal)global_particle_count) : 0.0;
3160 if (simCtx->
rank == 0) {
3161 char csv_path[PETSC_MAX_PATH_LEN + 32];
3163 ierr = PetscSNPrintf(csv_path,
sizeof(csv_path),
"%s/scatter_metrics.csv", simCtx->
analysis_dir); CHKERRQ(ierr);
3164 f = fopen(csv_path,
"a");
3166 if (ftell(f) == 0) {
3168 "step,time,total_particles,total_cells,occupied_cells,occupancy_fraction,"
3169 "mean_particles_per_occupied_cell,particle_integral,grid_integral,"
3170 "conservation_error_abs,L1_error,L2_error,Linf_error,relative_L2_error,"
3174 fprintf(f,
"# Continuation from step %" PetscInt_FMT
"\n", simCtx->
StartStep);
3176 PetscReal physical_time = 0.0;
3178 fprintf(f,
"%d,%.6e,%lld,%lld,%lld,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e\n",
3181 (
long long)global_particle_count,
3182 (
long long)global_cell_count,
3183 (
long long)global_occupied_count,
3184 (
double)occupancy_fraction,
3185 (
double)mean_particles_per_occupied_cell,
3186 (
double)particle_integral,
3187 (
double)global_grid_integral,
3188 (
double)PetscAbsReal(global_grid_integral - particle_integral),
3191 (
double)global_linf,
3192 (
double)relative_l2_error,
3193 (
double)physical_time);
3203 PetscFunctionReturn(0);