112 DMBoundaryType xperiod = (simCtx->
i_periodic) ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE;
113 DMBoundaryType yperiod = (simCtx->
j_periodic) ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE;
114 DMBoundaryType zperiod = (simCtx->
k_periodic) ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE;
117 PetscInt *lx = NULL, *ly = NULL, *lz = NULL;
120 PetscFunctionBeginUser;
128 DMDAGetInfo(coarse_user->
da, NULL, NULL, NULL, NULL, &m, &n, &p, NULL, NULL, NULL, NULL, NULL, NULL);
132 PetscInt *lx_contrib, *ly_contrib, *lz_contrib;
133 ierr = PetscMalloc3(m, &lx_contrib, n, &ly_contrib, p, &lz_contrib); CHKERRQ(ierr);
134 ierr = PetscMemzero(lx_contrib, m *
sizeof(PetscInt)); CHKERRQ(ierr);
135 ierr = PetscMemzero(ly_contrib, n *
sizeof(PetscInt)); CHKERRQ(ierr);
136 ierr = PetscMemzero(lz_contrib, p *
sizeof(PetscInt)); CHKERRQ(ierr);
139 DMDAGetLocalInfo(coarse_user->
da, &info);
140 PetscInt xs = info.xs, xe = info.xs + info.xm, mx = info.mx;
141 PetscInt ys = info.ys, ye = info.ys + info.ym, my = info.my;
142 PetscInt zs = info.zs, ze = info.zs + info.zm, mz = info.mz;
145 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
146 PetscInt proc_i = rank % m;
147 PetscInt proc_j = (rank / m) % n;
148 PetscInt proc_k = rank / (m * n);
151 if (user->
isc) lx_contrib[proc_i] = (xe - xs);
153 if (m == 1) lx_contrib[0] = user->
IM + 1;
154 else if (xs == 0) lx_contrib[0] = 2 * xe - 1;
155 else if (xe == mx) lx_contrib[proc_i] = user->
IM + 1 - (2 * xs - 1);
156 else lx_contrib[proc_i] = (xe - xs) * 2;
160 if (user->
jsc) ly_contrib[proc_j] = (ye - ys);
162 if (n == 1) ly_contrib[0] = user->
JM + 1;
163 else if (ys == 0) ly_contrib[0] = 2 * ye - 1;
164 else if (ye == my) ly_contrib[proc_j] = user->
JM + 1 - (2 * ys - 1);
165 else ly_contrib[proc_j] = (ye - ys) * 2;
169 if (user->
ksc) lz_contrib[proc_k] = (ze - zs);
171 if (p == 1) lz_contrib[0] = user->
KM + 1;
172 else if (zs == 0) lz_contrib[0] = 2 * ze - 1;
173 else if (ze == mz) lz_contrib[proc_k] = user->
KM + 1 - (2 * zs - 1);
174 else lz_contrib[proc_k] = (ze - zs) * 2;
176 LOG_ALLOW_SYNC(
LOCAL,
LOG_VERBOSE,
"Rank %d: Calculated this rank's node contribution to fine grid: lx=%d, ly=%d, lz=%d\n", simCtx->
rank, lx_contrib[proc_i], ly_contrib[proc_j], lz_contrib[proc_k]);
179 ierr = PetscMalloc3(m, &lx, n, &ly, p, &lz); CHKERRQ(ierr);
180 ierr = MPI_Allreduce(lx_contrib, lx, m, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
181 ierr = MPI_Allreduce(ly_contrib, ly, n, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
182 ierr = MPI_Allreduce(lz_contrib, lz, p, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
184 ierr = PetscFree3(lx_contrib, ly_contrib, lz_contrib); CHKERRQ(ierr);
199 m = n = p = PETSC_DECIDE;
207 ierr = DMDACreate3d(PETSC_COMM_WORLD, xperiod, yperiod, zperiod, DMDA_STENCIL_BOX,
208 user->
IM + 1, user->
JM + 1, user->
KM + 1,
210 1, stencil_width, lx, ly, lz, &user->
da); CHKERRQ(ierr);
213 ierr = PetscFree3(lx, ly, lz); CHKERRQ(ierr);
217 ierr = DMSetUp(user->
da); CHKERRQ(ierr);
218 ierr = DMGetCoordinateDM(user->
da, &user->
fda); CHKERRQ(ierr);
219 ierr = DMDASetUniformCoordinates(user->
da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0); CHKERRQ(ierr);
220 ierr = DMDAGetLocalInfo(user->
da, &user->
info); CHKERRQ(ierr);
225 PetscFunctionReturn(0);
384 const char axis_names[3] = {
'X',
'Y',
'Z'};
385 const Cmpnts ***coor = NULL;
389 PetscFunctionBeginUser;
390 PetscCall(DMDAGetLocalInfo(user->
da, &info));
391 PetscCall(DMGetCoordinatesLocal(user->
da, &lcoor));
392 PetscCheck(lcoor != NULL, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
393 "Cannot validate periodic geometry before local coordinates are assigned.");
394 for (PetscInt axis = 0; axis < 3; axis++) {
395 const PetscBool neg_periodic =
397 const PetscBool pos_periodic =
399 PetscReal local_min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
400 PetscReal local_max[3] = {-PETSC_MAX_REAL, -PETSC_MAX_REAL, -PETSC_MAX_REAL};
401 PetscReal global_min[3], global_max[3];
402 PetscInt local_count = 0, global_count = 0;
406 if (!neg_periodic && !pos_periodic)
continue;
408 PetscCheck(neg_periodic && pos_periodic, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT,
409 "Periodic geometry in the %c direction requires paired negative and positive faces.",
411 const PetscInt axis_size = axis == 0 ? info.mx : (axis == 1 ? info.my : info.mz);
412 PetscCheck(axis_size >= 5, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT,
413 "%c-periodic geometry on block %d level %d requires at least four physical "
414 "nodes in that direction; found %d.",
417 PetscCall(DMDAVecGetArrayRead(user->
fda, lcoor, &coor));
418 if (axis == 0 && info.xs == 0) {
419 for (PetscInt k = PetscMax(info.zs, 0); k < PetscMin(info.zs + info.zm, info.mz - 1); k++) {
420 for (PetscInt j = PetscMax(info.ys, 0); j < PetscMin(info.ys + info.ym, info.my - 1); j++) {
422 coor[k][j][-2].
x - coor[k][j][0].
x,
423 coor[k][j][-2].
y - coor[k][j][0].
y,
424 coor[k][j][-2].
z - coor[k][j][0].
z
426 for (PetscInt c = 0; c < 3; c++) {
433 }
else if (axis == 1 && info.ys == 0) {
434 for (PetscInt k = PetscMax(info.zs, 0); k < PetscMin(info.zs + info.zm, info.mz - 1); k++) {
435 for (PetscInt i = PetscMax(info.xs, 0); i < PetscMin(info.xs + info.xm, info.mx - 1); i++) {
437 coor[k][-2][i].
x - coor[k][0][i].
x,
438 coor[k][-2][i].
y - coor[k][0][i].
y,
439 coor[k][-2][i].
z - coor[k][0][i].
z
441 for (PetscInt c = 0; c < 3; c++) {
448 }
else if (axis == 2 && info.zs == 0) {
449 for (PetscInt j = PetscMax(info.ys, 0); j < PetscMin(info.ys + info.ym, info.my - 1); j++) {
450 for (PetscInt i = PetscMax(info.xs, 0); i < PetscMin(info.xs + info.xm, info.mx - 1); i++) {
452 coor[-2][j][i].
x - coor[0][j][i].
x,
453 coor[-2][j][i].
y - coor[0][j][i].
y,
454 coor[-2][j][i].
z - coor[0][j][i].
z
456 for (PetscInt c = 0; c < 3; c++) {
464 PetscCall(DMDAVecRestoreArrayRead(user->
fda, lcoor, &coor));
466 PetscCallMPI(MPI_Allreduce(local_min, global_min, 3, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD));
467 PetscCallMPI(MPI_Allreduce(local_max, global_max, 3, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD));
468 PetscCallMPI(MPI_Allreduce(&local_count, &global_count, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
469 PetscCheck(global_count > 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
470 "No physical seam nodes were available to validate %c-periodic geometry.",
473 PetscReal translation[3];
474 PetscReal scale = 1.0;
475 PetscReal max_mismatch = 0.0;
476 for (PetscInt c = 0; c < 3; c++) {
477 translation[c] = 0.5 * (global_min[c] + global_max[c]);
478 scale = PetscMax(scale, PetscAbsReal(translation[c]));
479 max_mismatch = PetscMax(max_mismatch, global_max[c] - global_min[c]);
481 const PetscReal tolerance = 1.0e-9 * scale + 100.0 * PETSC_MACHINE_EPSILON;
482 const PetscReal magnitude = PetscSqrtReal(
483 PetscSqr(translation[0]) + PetscSqr(translation[1]) + PetscSqr(translation[2]));
485 PetscCheck(max_mismatch <= tolerance, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT,
486 "Unsupported %c-periodic geometry on block %d level %d: opposite physical "
487 "surfaces are not related by one constant translation. Maximum component "
488 "mismatch is %.12e (tolerance %.12e).",
490 (
double)max_mismatch, (
double)tolerance);
491 PetscCheck(magnitude > tolerance, PETSC_COMM_WORLD, PETSC_ERR_USER_INPUT,
492 "Unsupported %c-periodic geometry on block %d level %d: seam translation "
493 "magnitude %.12e is zero or too small.",
494 axis_names[axis], user->
_this, user->
thislevel, (
double)magnitude);
497 (
Cmpnts){translation[0], translation[1], translation[2]};
500 "Validated %c-periodic geometry for block %d level %d with translation "
501 "(%.12e, %.12e, %.12e).\n",
503 (
double)translation[0], (
double)translation[1], (
double)translation[2]);
506 PetscFunctionReturn(0);
662 PetscMPIInt rank = simCtx->
rank;
663 PetscInt block_index = user->
_this;
664 PetscInt IM = user->
IM, JM = user->
JM, KM = user->
KM;
668 PetscReal *gc = NULL;
670 PetscFunctionBeginUser;
675 simCtx->
rank, block_index);
679 PetscInt n_nodes = (IM) * (JM) * (KM);
680 ierr = PetscMalloc1(3 * n_nodes, &gc); CHKERRQ(ierr);
684 if (!fd) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Recieved a NULL file handle.\n");
687 for (PetscInt k = 0; k < KM; k++) {
688 for (PetscInt j = 0; j < JM; j++) {
689 for (PetscInt i = 0; i < IM; i++) {
690 PetscInt base_index = 3 * ((k * (JM) + j) * (IM) + i);
691 if (fscanf(fd,
"%le %le %le\n", &gc[base_index], &gc[base_index + 1], &gc[base_index + 2]) != 3) {
692 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Error reading coordinates for node (i,j,k)=(%d,%d,%d) in block %d", i, j, k, block_index);
701 ierr = MPI_Bcast(gc, 3 * n_nodes, MPIU_REAL, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
704 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
705 ierr = DMGetCoordinates(user->
da, &gCoor); CHKERRQ(ierr);
706 ierr = VecSet(gCoor, 0.0); CHKERRQ(ierr);
707 ierr = DMDAVecGetArray(user->
fda, gCoor, &coor); CHKERRQ(ierr);
709 for (PetscInt k = info.zs; k < info.zs + info.zm; k++) {
710 for (PetscInt j = info.ys; j < info.ys + info.ym; j++) {
711 for (PetscInt i = info.xs; i < info.xs + info.xm; i++) {
712 if(k< KM && j < JM && i < IM){
713 PetscInt base_idx = 3 * ((k * (JM) + j) * (IM) + i);
714 coor[k][j][i].
x = gc[base_idx];
715 coor[k][j][i].
y = gc[base_idx + 1];
716 coor[k][j][i].
z = gc[base_idx + 2];
723 ierr = DMDAVecRestoreArray(user->
fda, gCoor, &coor); CHKERRQ(ierr);
724 ierr = PetscFree(gc); CHKERRQ(ierr);
728 PetscFunctionReturn(0);
740 Vec c_gCoor, f_lCoor;
743 DMDALocalInfo c_info;
746 PetscFunctionBeginUser;
753 ierr = DMDAGetLocalInfo(coarse_user->
da, &c_info); CHKERRQ(ierr);
755 ierr = DMGetCoordinates(coarse_user->
da, &c_gCoor); CHKERRQ(ierr);
756 ierr = DMGetCoordinatesLocal(fine_user->
da, &f_lCoor); CHKERRQ(ierr);
758 ierr = VecSet(c_gCoor, 0.0); CHKERRQ(ierr);
759 ierr = DMDAVecGetArray(coarse_user->
fda, c_gCoor, &c_coor); CHKERRQ(ierr);
760 ierr = DMDAVecGetArrayRead(fine_user->
fda, f_lCoor, &f_coor); CHKERRQ(ierr);
763 PetscInt xs = c_info.xs, xe = c_info.xs + c_info.xm;
764 PetscInt ys = c_info.ys, ye = c_info.ys + c_info.ym;
765 PetscInt zs = c_info.zs, ze = c_info.zs + c_info.zm;
768 PetscInt mx = c_info.mx, my = c_info.my, mz = c_info.mz;
777 for (PetscInt k = zs; k < ze; k++) {
778 for (PetscInt j = ys; j < ye; j++) {
779 for (PetscInt i = xs; i < xe; i++) {
782 ih = coarse_user->
isc ? i : 2 * i;
783 jh = coarse_user->
jsc ? j : 2 * j;
784 kh = coarse_user->
ksc ? k : 2 * k;
788 c_coor[k][j][i] = f_coor[kh][jh][ih];
793 ierr = DMDAVecRestoreArray(coarse_user->
fda, c_gCoor, &c_coor); CHKERRQ(ierr);
794 ierr = DMDAVecRestoreArrayRead(fine_user->
fda, f_lCoor, &f_coor); CHKERRQ(ierr);
801 PetscFunctionReturn(0);
1163 Cmpnts *face_center, PetscReal *face_area)
1165 PetscErrorCode ierr;
1171 PetscReal local_sum[3] = {0.0, 0.0, 0.0};
1172 PetscReal localAreaSum = 0.0;
1173 PetscCount local_n_points = 0;
1178 PetscReal global_sum[3] = {0.0, 0.0, 0.0};
1179 PetscReal globalAreaSum = 0.0;
1180 PetscCount global_n_points = 0;
1188 PetscInt xs = info.xs, xe = info.xs + info.xm;
1189 PetscInt ys = info.ys, ye = info.ys + info.ym;
1190 PetscInt zs = info.zs, ze = info.zs + info.zm;
1193 PetscInt mx = info.mx, my = info.my, mz = info.mz;
1194 PetscInt IM = user->
IM;
1195 PetscInt JM = user->
JM;
1196 PetscInt KM = user->
KM;
1202 PetscInt lxs = xs;
if(xs == 0) lxs = xs + 1;
1203 PetscInt lxe = xe;
if(xe == mx) lxe = xe - 1;
1204 PetscInt lys = ys;
if(ys == 0) lys = ys + 1;
1205 PetscInt lye = ye;
if(ye == my) lye = ye - 1;
1206 PetscInt lzs = zs;
if(zs == 0) lzs = zs + 1;
1207 PetscInt lze = ze;
if(ze == mz) lze = ze - 1;
1213 PetscInt i_max = (xe == mx) ? mx - 1 : xe;
1214 PetscInt j_max = (ye == my) ? my - 1 : ye;
1215 PetscInt k_max = (ze == mz) ? mz - 1 : ze;
1222 Cmpnts ***csi, ***eta, ***zet;
1225 PetscFunctionBeginUser;
1231 PetscBool owns_face = PETSC_FALSE;
1237 ierr = DMGetCoordinatesLocal(user->
da, &lCoor); CHKERRQ(ierr);
1238 ierr = DMDAVecGetArrayRead(user->
fda, lCoor, &coor); CHKERRQ(ierr);
1239 ierr = DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert); CHKERRQ(ierr);
1240 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
1241 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
1242 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
1259 for (PetscInt k = zs; k < k_max; k++) {
1260 for (PetscInt j = ys; j < j_max; j++) {
1262 local_sum[0] += coor[k][j][i].
x;
1263 local_sum[1] += coor[k][j][i].
y;
1264 local_sum[2] += coor[k][j][i].
z;
1272 for (PetscInt k = lzs; k < lze; k++) {
1273 for (PetscInt j = lys; j < lye; j++) {
1277 if (nvert[k][j][i+1] < 0.1) {
1280 localAreaSum += sqrt(csi[k][j][i].x * csi[k][j][i].x +
1281 csi[k][j][i].y * csi[k][j][i].y +
1282 csi[k][j][i].z * csi[k][j][i].z);
1294 PetscInt i = mx - 2;
1297 for (PetscInt k = zs; k < k_max; k++) {
1298 for (PetscInt j = ys; j < j_max; j++) {
1299 local_sum[0] += coor[k][j][i].
x;
1300 local_sum[1] += coor[k][j][i].
y;
1301 local_sum[2] += coor[k][j][i].
z;
1307 for (PetscInt k = lzs; k < lze; k++) {
1308 for (PetscInt j = lys; j < lye; j++) {
1312 if (nvert[k][j][i] < 0.1) {
1314 localAreaSum += sqrt(csi[k][j][i].x * csi[k][j][i].x +
1315 csi[k][j][i].y * csi[k][j][i].y +
1316 csi[k][j][i].z * csi[k][j][i].z);
1332 for (PetscInt k = zs; k < k_max; k++) {
1333 for (PetscInt i = xs; i < i_max; i++) {
1334 local_sum[0] += coor[k][j][i].
x;
1335 local_sum[1] += coor[k][j][i].
y;
1336 local_sum[2] += coor[k][j][i].
z;
1343 for (PetscInt k = lzs; k < lze; k++) {
1344 for (PetscInt i = lxs; i < lxe; i++) {
1346 if (nvert[k][j+1][i] < 0.1) {
1348 localAreaSum += sqrt(eta[k][j][i].x * eta[k][j][i].x +
1349 eta[k][j][i].y * eta[k][j][i].y +
1350 eta[k][j][i].z * eta[k][j][i].z);
1362 PetscInt j = my - 2;
1365 for (PetscInt k = zs; k < k_max; k++) {
1366 for (PetscInt i = xs; i < i_max; i++) {
1367 local_sum[0] += coor[k][j][i].
x;
1368 local_sum[1] += coor[k][j][i].
y;
1369 local_sum[2] += coor[k][j][i].
z;
1375 for (PetscInt k = lzs; k < lze; k++) {
1376 for (PetscInt i = lxs; i < lxe; i++) {
1378 if (nvert[k][j][i] < 0.1) {
1380 localAreaSum += sqrt(eta[k][j][i].x * eta[k][j][i].x +
1381 eta[k][j][i].y * eta[k][j][i].y +
1382 eta[k][j][i].z * eta[k][j][i].z);
1398 for (PetscInt j = ys; j < j_max; j++) {
1399 for (PetscInt i = xs; i < i_max; i++) {
1400 local_sum[0] += coor[k][j][i].
x;
1401 local_sum[1] += coor[k][j][i].
y;
1402 local_sum[2] += coor[k][j][i].
z;
1409 for (PetscInt j = lys; j < lye; j++) {
1410 for (PetscInt i = lxs; i < lxe; i++) {
1413 if (nvert[k+1][j][i] < 0.1) {
1415 localAreaSum += sqrt(zet[k][j][i].x * zet[k][j][i].x +
1416 zet[k][j][i].y * zet[k][j][i].y +
1417 zet[k][j][i].z * zet[k][j][i].z);
1429 PetscInt k = mz - 2;
1433 for (PetscInt j = ys; j < j_max; j++) {
1434 for (PetscInt i = xs; i < i_max; i++) {
1435 local_sum[0] += coor[k][j][i].
x;
1436 local_sum[1] += coor[k][j][i].
y;
1437 local_sum[2] += coor[k][j][i].
z;
1444 for (PetscInt j = lys; j < lye; j++) {
1445 for (PetscInt i = lxs; i < lxe; i++) {
1448 if (nvert[k][j][i] < 0.1) {
1450 localAreaSum += sqrt(zet[k][j][i].x * zet[k][j][i].x +
1451 zet[k][j][i].y * zet[k][j][i].y +
1452 zet[k][j][i].z * zet[k][j][i].z);
1460 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
1461 "Unknown face_id %d in CalculateFaceCenterAndArea", face_id);
1467 ierr = DMDAVecRestoreArrayRead(user->
fda, lCoor, &coor); CHKERRQ(ierr);
1468 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert); CHKERRQ(ierr);
1469 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
1470 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
1471 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
1477 ierr = MPI_Allreduce(local_sum, global_sum, 3, MPI_DOUBLE, MPI_SUM,
1478 PETSC_COMM_WORLD); CHKERRQ(ierr);
1481 ierr = MPI_Allreduce(&local_n_points, &global_n_points, 1, MPI_COUNT, MPI_SUM,
1482 PETSC_COMM_WORLD); CHKERRQ(ierr);
1485 ierr = MPI_Allreduce(&localAreaSum, &globalAreaSum, 1, MPI_DOUBLE, MPI_SUM,
1486 PETSC_COMM_WORLD); CHKERRQ(ierr);
1491 if (global_n_points > 0) {
1492 face_center->
x = global_sum[0] / global_n_points;
1493 face_center->
y = global_sum[1] / global_n_points;
1494 face_center->
z = global_sum[2] / global_n_points;
1496 "Calculated center for Face %s: (x=%.4f, y=%.4f, z=%.4f) from %lld nodes\n",
1498 face_center->
x, face_center->
y, face_center->
z,
1499 (
long long)global_n_points);
1503 "WARNING: Face %s identified but no grid points found. Center not calculated.\n",
1505 face_center->
x = face_center->
y = face_center->
z = 0.0;
1511 *face_area = globalAreaSum;
1513 "Calculated area for Face %s: Area=%.6f\n",
1516 PetscFunctionReturn(0);