20 PetscFunctionBeginUser;
21 if (!bc_ptr || !*bc_ptr) PetscFunctionReturn(0);
27 PetscCall(PetscFree(bc));
29 PetscFunctionReturn(0);
62 PetscErrorCode ierr_validate = 0;
64 PetscFunctionBeginUser;
69 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
71 PetscCall(PetscPopErrorHandler());
73 PetscCall(
PicurvAssertBool((PetscBool)(ierr_validate != 0),
"unpaired periodic faces should be rejected"));
75 PetscFunctionReturn(0);
85 const Cmpnts ***coor = NULL;
86 PetscReal expected_x = 0.0;
88 PetscFunctionBeginUser;
92 PetscCall(DMGetCoordinates(user->
da, &gcoor));
93 PetscCall(DMDAVecGetArrayRead(user->
fda, gcoor, &coor));
94 expected_x = coor[0][0][user->
info.mx - 2].
x - coor[0][0][0].
x;
95 PetscCall(DMDAVecRestoreArrayRead(user->
fda, gcoor, &coor));
106 PetscFunctionReturn(0);
118 const Cmpnts ***coor = NULL;
119 PetscReal x0, y0, T, Ty, yc, zc;
121 PetscFunctionBeginUser;
134 PetscCall(DMGetCoordinates(user->
da, &gcoor));
135 PetscCall(DMDAVecGetArrayRead(user->
fda, gcoor, &coor));
136 x0 = coor[0][0][0].
x;
137 y0 = coor[0][0][0].
y;
138 yc = 0.5 * (coor[1][1][0].
y + coor[1][2][0].
y);
139 zc = 0.5 * (coor[1][1][0].
z + coor[2][1][0].
z);
140 PetscCall(DMDAVecRestoreArrayRead(user->
fda, gcoor, &coor));
145 PetscCall(PetscMemzero(&particle,
sizeof(particle)));
147 particle.
cell[0] = 0; particle.
cell[1] = 1; particle.
cell[2] = 1;
148 particle.
loc.
x = x0 - 0.01 * T; particle.
loc.
y = yc; particle.
loc.
z = zc;
151 PetscCall(
PicurvAssertRealNear(x0 + 0.99 * T, particle.
loc.
x, 1.0e-12,
"x shifts forward by the seam translation"));
155 PetscCall(PetscMemzero(&particle,
sizeof(particle)));
157 particle.
cell[0] = user->
IM - 2; particle.
cell[1] = 1; particle.
cell[2] = 1;
158 particle.
loc.
x = x0 + 1.01 * T; particle.
loc.
y = yc; particle.
loc.
z = zc;
165 PetscCall(PetscMemzero(&particle,
sizeof(particle)));
167 particle.
cell[0] = 0; particle.
cell[1] = 0; particle.
cell[2] = 1;
168 particle.
loc.
x = x0 - 0.01 * T; particle.
loc.
y = y0 - 0.01 * Ty; particle.
loc.
z = zc;
178 PetscFunctionReturn(0);
195 const Cmpnts ***lcoor = NULL;
196 const PetscReal c = PetscCosReal(PETSC_PI / 6.0), s = PetscSinReal(PETSC_PI / 6.0);
197 PetscReal T0, x0, yc, zc;
200 PetscFunctionBeginUser;
207 PetscCall(DMGetCoordinatesLocal(user->
da, &gcoor));
208 PetscCall(DMDAVecGetArrayRead(user->
fda, gcoor, &lcoor));
209 x0 = lcoor[0][0][0].
x;
210 yc = 0.5 * (lcoor[1][1][0].
y + lcoor[1][2][0].
y);
211 zc = 0.5 * (lcoor[1][1][0].
z + lcoor[2][1][0].
z);
212 PetscCall(DMDAVecRestoreArrayRead(user->
fda, gcoor, &lcoor));
215 PetscCall(DMGetCoordinates(user->
da, &gcoor));
216 PetscCall(DMDAVecGetArray(user->
fda, gcoor, &coor));
217 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++)
218 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++)
219 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
220 const Cmpnts q = coor[k][j][i];
221 coor[k][j][i].
x = c * q.
x - s * q.
y;
222 coor[k][j][i].
y = s * q.
x + c * q.
y;
224 PetscCall(DMDAVecRestoreArray(user->
fda, gcoor, &coor));
238 PetscCall(PetscMemzero(&particle,
sizeof(particle)));
240 particle.
cell[0] = 0; particle.
cell[1] = 1; particle.
cell[2] = 1;
241 p0.
x = x0 - 0.01 * T0; p0.
y = yc; p0.
z = zc;
242 particle.
loc.
x = c * p0.
x - s * p0.
y; particle.
loc.
y = s * p0.
x + c * p0.
y; particle.
loc.
z = p0.
z;
245 PetscCall(
PicurvAssertRealNear(c * (p0.
x + T0) - s * p0.
y, particle.
loc.
x, 1.0e-12,
"x shifts along the rotated translation"));
246 PetscCall(
PicurvAssertRealNear(s * (p0.
x + T0) + c * p0.
y, particle.
loc.
y, 1.0e-12,
"y shifts along the rotated translation"));
250 PetscFunctionReturn(0);
260 PetscFunctionBeginUser;
270 "mixed-periodic X translation should have nonzero x component"));
272 "mixed-periodic Y translation should have nonzero y component"));
275 PetscFunctionReturn(0);
286 PetscErrorCode ierr_validate = 0;
288 PetscFunctionBeginUser;
292 PetscCall(DMGetCoordinates(user->
da, &gcoor));
293 PetscCall(DMDAVecGetArray(user->
fda, gcoor, &coor));
294 coor[1][1][user->
info.mx - 2].
y += 0.25;
295 PetscCall(DMDAVecRestoreArray(user->
fda, gcoor, &coor));
298 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
300 PetscCall(PetscPopErrorHandler());
302 PetscCall(
PicurvAssertBool((PetscBool)(ierr_validate != 0),
"varying seam translation should be rejected"));
304 PetscFunctionReturn(0);
315 const Cmpnts ***lcentx = NULL;
317 PetscReal translation, spacing;
319 PetscFunctionBeginUser;
324 spacing = translation / (PetscReal)(user->
info.mx - 2);
326 PetscCall(DMDAVecGetArray(user->
fda, user->
Centx, ¢x));
327 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
328 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
329 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
330 centx[k][j][i] = (
Cmpnts){spacing * i, 2.0 + j, 3.0 + k};
334 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Centx, ¢x));
337 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lCentx, &lcentx));
339 "translated Centx negative adjacent ghost"));
341 "translated Centx negative endpoint"));
343 "translated Centx positive endpoint"));
345 "translated Centx positive adjacent ghost"));
346 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lCentx, &lcentx));
349 PetscFunctionReturn(0);
360 PetscReal ***nvert = NULL;
362 PetscFunctionBeginUser;
366 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
367 PetscCall(DMDAVecGetArray(user->
da, user->
Nvert, &nvert));
368 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
369 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
370 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
371 ucat[k][j][i] = (
Cmpnts){100.0 + i, 200.0 + i, 300.0 + i};
372 nvert[k][j][i] = 400.0 + i;
376 PetscCall(DMDAVecRestoreArray(user->
da, user->
Nvert, &nvert));
377 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
382 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcat, &ucat));
383 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert));
385 "QUICK Ucat negative outer ghost"));
387 "QUICK Ucat positive outer ghost"));
389 "QUICK Nvert negative outer ghost"));
391 "QUICK Nvert positive outer ghost"));
392 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert));
393 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcat, &ucat));
396 PetscFunctionReturn(0);
405 PetscFunctionBeginUser;
407 PetscCall(
PicurvAssertBool((PetscBool)(bc != NULL),
"periodic geometric factory should allocate a handler"));
409 PetscCall(
PicurvAssertBool((PetscBool)(bc->
Apply == NULL),
"periodic geometric handler should not expose Apply"));
412 PetscFunctionReturn(0);
421 PetscReal ***aj = NULL;
422 PetscReal expected_neg_face = 0.0;
423 PetscReal expected_pos_face = 0.0;
424 PetscReal expected_neg_ghost = 0.0;
425 PetscReal expected_pos_ghost = 0.0;
427 PetscFunctionBeginUser;
432 PetscCall(DMDAVecGetArray(user->
da, user->
Aj, &aj));
433 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
434 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
435 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
436 aj[k][j][i] = 100.0 + (PetscReal)i;
440 PetscCall(DMDAVecRestoreArray(user->
da, user->
Aj, &aj));
441 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
442 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
443 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
444 expected_neg_face = aj[2][2][user->
info.mx - 2];
445 expected_pos_face = aj[2][2][1];
446 expected_neg_ghost = expected_pos_face;
447 expected_pos_ghost = expected_neg_face;
448 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
452 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
453 PetscCall(
PicurvAssertRealNear(expected_neg_face, aj[2][2][0], 1.0e-12,
"NEG_X periodic metric face should copy from the opposite interior face"));
454 PetscCall(
PicurvAssertRealNear(expected_pos_face, aj[2][2][user->
info.mx - 1], 1.0e-12,
"POS_X periodic metric face should copy from the leading interior face"));
455 PetscCall(
PicurvAssertRealNear(expected_neg_ghost, aj[2][2][-1], 1.0e-12,
"cell-centered Aj negative ghost should retain PETSc wraparound"));
456 PetscCall(
PicurvAssertRealNear(expected_pos_ghost, aj[2][2][user->
info.mx], 1.0e-12,
"cell-centered Aj positive ghost should retain PETSc wraparound"));
457 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
460 PetscFunctionReturn(0);
469 PetscReal ***p = NULL;
470 PetscReal ***cs = NULL;
471 PetscReal ***diffusivity = NULL;
476 PetscFunctionBeginUser;
481 PetscCall(DMCreateGlobalVector(user->
da, &user->
Nu_t));
482 PetscCall(DMCreateLocalVector(user->
da, &user->
lNu_t));
483 PetscCall(VecSet(user->
Nu_t, 5.0));
484 PetscCall(VecSet(user->
lNu_t, 0.0));
485 PetscCall(DMCreateGlobalVector(user->
da, &user->
CS));
486 PetscCall(DMCreateLocalVector(user->
da, &user->
lCs));
487 PetscCall(VecSet(user->
Phi, 3.0));
488 PetscCall(VecSet(user->
Nvert, 4.0));
490 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
491 PetscCall(DMDAVecGetArray(user->
da, user->
CS, &cs));
492 PetscCall(DMDAVecGetArray(user->
da, user->
Diffusivity, &diffusivity));
493 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
494 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
495 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
496 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
497 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
499 cs[k][j][i] = value + 4000.0;
500 diffusivity[k][j][i] = value + 5000.0;
501 ucat[k][j][i].
x = value + 1000.0;
502 ucat[k][j][i].
y = value + 2000.0;
503 ucat[k][j][i].
z = value + 3000.0;
507 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
508 PetscCall(DMDAVecRestoreArray(user->
da, user->
CS, &cs));
509 PetscCall(DMDAVecRestoreArray(user->
da, user->
Diffusivity, &diffusivity));
510 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
516 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
517 PetscCall(DMDAVecGetArrayRead(user->
da, user->
CS, &cs));
518 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Diffusivity, &diffusivity));
519 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
521 "x-periodic negative endpoint should copy the opposite interior value"));
523 "x-periodic positive endpoint should copy the leading interior value"));
525 "y-periodic negative endpoint should copy the opposite interior value"));
526 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 200), p[2][0][0], 1.0e-12,
527 "ordered synchronization should propagate the opposite periodic corner"));
528 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 1200), ucat[2][0][0].x, 1.0e-12,
529 "vector fields should use the same ordered periodic-corner protocol"));
530 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 4200), cs[2][0][0], 1.0e-12,
531 "CS should use the ordered periodic-corner protocol"));
532 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 5200), diffusivity[2][0][0], 1.0e-12,
533 "Diffusivity should use the ordered periodic-corner protocol"));
534 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
535 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
CS, &cs));
536 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Diffusivity, &diffusivity));
537 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
541 PetscFunctionReturn(0);
551 PetscReal ***iaj = NULL;
556 PetscFunctionBeginUser;
563 PetscCall(DMDAVecGetArray(user->
da, user->
IAj, &iaj));
564 PetscCall(DMDAVecGetArray(user->
fda, user->
Csi, &csi));
565 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
566 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
567 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
568 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
569 iaj[k][j][i] = value;
570 csi[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
574 PetscCall(DMDAVecRestoreArray(user->
da, user->
IAj, &iaj));
575 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Csi, &csi));
579 PetscCall(DMDAVecGetArrayRead(user->
da, user->
IAj, &iaj));
580 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Csi, &csi));
582 "I-face negative seam should copy the opposite physical seam face"));
584 "I-face positive dummy should copy the leading physical face"));
586 "I-face field should use cell-style synchronization tangentially"));
587 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 200), iaj[2][0][0], 1.0e-12,
588 "ordered face synchronization should propagate mixed-axis corners"));
589 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 1200), csi[2][0][0].x, 1.0e-12,
590 "vector I-face fields should use the same ordered synchronization"));
591 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
IAj, &iaj));
592 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Csi, &csi));
594 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lIAj, &iaj));
596 "I-face negative adjacent ghost should be shifted to the prior face"));
598 "I-face positive adjacent ghost should be shifted to the next face"));
600 "I-face tangential ghosts should retain cell-style wraparound"));
601 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lIAj, &iaj));
604 PetscFunctionReturn(0);
618 PetscFunctionBeginUser;
625 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
626 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
627 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
628 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
629 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
630 ucont[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
634 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
638 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
640 "Ucont.x negative X seam should copy the opposite physical seam"));
642 "Ucont.y positive X dummy should copy the leading physical value"));
643 PetscCall(
PicurvAssertRealNear((PetscReal)(2 + 10 * (my - 2) + 3200), ucont[2][0][2].z, 1.0e-12,
644 "Ucont.z should synchronize tangentially in Y"));
645 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 2200), ucont[2][0][0].y, 1.0e-12,
646 "ordered staggered synchronization should propagate mixed-axis corners"));
647 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
649 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
651 "Ucont.x should use face-normal X ghost repair"));
653 "Ucont.y should retain cell-style wraparound tangentially in X"));
655 "Ucont.x positive adjacent ghost should use the next face"));
657 "Ucont.y positive X ghost should retain cell-style wraparound"));
658 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
661 PetscFunctionReturn(0);
671 Vec ucont_before = NULL;
672 Vec ucont_difference = NULL;
675 PetscReal ***p = NULL;
676 PetscReal difference_norm = 0.0;
679 PetscFunctionBeginUser;
682 PetscCall(VecSet(user->
Bcs.
Ubcs, 0.0));
684 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
685 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
686 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
687 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
688 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
689 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
690 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
691 ucat[k][j][i].
x = value + 1000.0;
692 ucat[k][j][i].
y = value + 2000.0;
693 ucat[k][j][i].
z = value + 3000.0;
694 ucont[k][j][i].
x = value + 4000.0;
695 ucont[k][j][i].
y = value + 5000.0;
696 ucont[k][j][i].
z = value + 6000.0;
701 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
702 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
703 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
705 PetscCall(VecDuplicate(user->
Ucont, &ucont_before));
706 PetscCall(VecDuplicate(user->
Ucont, &ucont_difference));
707 PetscCall(VecCopy(user->
Ucont, ucont_before));
711 PetscCall(VecWAXPY(ucont_difference, -1.0, user->
Ucont, ucont_before));
712 PetscCall(VecNorm(ucont_difference, NORM_INFINITY, &difference_norm));
714 "post-projection cell finalization must preserve mixed-boundary Ucont"));
717 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
718 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
719 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 20 + 200 + 1000), ucat[2][2][0].x, 1.0e-12,
720 "mixed finalization should restore the negative x-periodic Ucat endpoint"));
722 "mixed finalization should extrapolate the non-periodic y dummy face"));
723 PetscCall(
PicurvAssertRealNear((PetscReal)(-((mx - 2) + 10 + 200 + 1000)), ucat[2][0][0].x, 1.0e-12,
724 "periodic synchronization should win at a mixed x-periodic/y-physical edge"));
726 "mixed finalization should restore the negative x-periodic pressure endpoint"));
727 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
728 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
730 PetscCall(VecDestroy(&ucont_difference));
731 PetscCall(VecDestroy(&ucont_before));
733 PetscFunctionReturn(0);
742 PetscFunctionBeginUser;
745 PetscCall(VecSet(user->
Ucont,0.0));
746 PetscCall(DMDAVecGetArray(user->
fda,user->
Ucont,&ucont));
747 for(PetscInt k=1;k<user->
info.mz-1;k++)
for(PetscInt j=1;j<user->
info.my-1;j++)
748 for(PetscInt i=1;i<mx-1;i++) ucont[k][j][i].x=(PetscReal)i;
749 PetscCall(DMDAVecRestoreArray(user->
fda,user->
Ucont,&ucont));
751 PetscCall(VecSet(user->
Ucat,-99.0));
756 PetscCall(DMDAVecGetArrayRead(user->
fda,user->
Ucat,&ucat));
757 PetscCall(
PicurvAssertRealNear(ucat[2][2][mx-2].x,ucat[2][2][0].x,1e-12,
"negative Ucat duplicate follows opposite independent cell"));
758 PetscCall(
PicurvAssertRealNear(ucat[2][2][1].x,ucat[2][2][mx-1].x,1e-12,
"positive Ucat duplicate follows leading independent cell"));
759 PetscCall(DMDAVecGetArrayRead(user->
fda,user->
lUcat,&lucat));
760 PetscCall(
PicurvAssertRealNear(ucat[2][2][0].x,lucat[2][2][0].x,1e-12,
"local negative Ucat endpoint matches corrected global"));
761 PetscCall(
PicurvAssertRealNear(ucat[2][2][mx-1].x,lucat[2][2][mx-1].x,1e-12,
"local positive Ucat endpoint matches corrected global"));
762 PetscCall(DMDAVecRestoreArrayRead(user->
fda,user->
lUcat,&lucat));
763 PetscCall(DMDAVecRestoreArrayRead(user->
fda,user->
Ucat,&ucat));
765 PetscFunctionReturn(0);
791 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv geometric-periodic tests");
796 ierr =
PicurvRunTests(
"unit-periodic", cases,
sizeof(cases) /
sizeof(cases[0]));
802 ierr = PetscFinalize();
PetscErrorCode PreparePeriodicQuickStencilFields(UserCtx *user, Vec local_vector_field, Vec local_scalar_field)
Repairs the outer adjacent periodic ghosts used by QUICK cell stencils.
PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user)
(Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundar...
PetscErrorCode BoundarySystem_Validate(UserCtx *user)
(Public) Validates the consistency and compatibility of the parsed boundary condition system.
PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr)
(Private) Creates and configures a specific BoundaryCondition handler object.
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
PetscErrorCode FinalizePostProjectionCellFields(UserCtx *user)
Finalizes cell-centered fields after the projection step.
PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent fields belonging to one face family.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
PetscErrorCode MetricDestroyFacePlanes(UserCtx *user)
Frees the face-plane fields MetricComputeFacePlanes() built, if any.
PetscErrorCode MetricComputeFacePlanes(UserCtx *user)
Builds the block's particle face planes once, as catalogued per-face fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
PetscErrorCode SetupDomainCellDecompositionMap(UserCtx *user)
Creates and distributes a map of the domain's cell decomposition to all ranks.
The "virtual table" struct for a boundary condition handler object.
PetscErrorCode(* Destroy)(BoundaryCondition *self)
PetscErrorCode(* Initialize)(BoundaryCondition *self, BCContext *ctx)
PetscErrorCode(* Apply)(BoundaryCondition *self, BCContext *ctx)
static PetscErrorCode TestContra2CartPeriodicUcatFinalization(void)
Verifies reconstructed Ucat periodic duplicates and local values are finalized.
static void MarkXPeriodic(UserCtx *user)
Marks the x faces as periodic for periodic-transfer harnesses.
static PetscErrorCode TestPeriodicGeometricFactoryAssignment(void)
Tests periodic geometric factory construction.
static PetscErrorCode TestPeriodicFaceCenterCoordinateSynchronization(void)
Tests face-center coordinates remain geometrically continuous across a periodic seam.
int main(int argc, char **argv)
Runs the focused geometric-periodic PETSc test binary.
static PetscErrorCode TestLocateParticleWrapsThroughPeriodicFace(void)
Tests that a particle beyond either x-periodic face re-enters through the paired face,...
static PetscErrorCode TestPeriodicGeometryStoresTranslation(void)
Tests constant translational periodic geometry is accepted and stored.
static PetscErrorCode TestSynchronizePeriodicFaceFieldsCopiesMixedAxes(void)
Tests ordered persistent synchronization for an I-face scalar metric.
static PetscErrorCode TestFinalizePostProjectionCellFieldsMixedBoundaries(void)
Tests mixed-boundary post-projection cell finalization and Ucont preservation.
static PetscErrorCode TestPeriodicConfigurationRequiresPairedFaces(void)
Tests periodic configuration rejects an unpaired geometric periodic face.
static PetscErrorCode TestPeriodicQuickStencilPreparation(void)
Tests the dedicated QUICK outer-ghost repair for cell-centered inputs.
static PetscErrorCode TestSynchronizePeriodicCellFieldsCopiesMixedAxes(void)
Tests ordered cell-field synchronization across two periodic directions.
static PetscErrorCode TestPeriodicGeometryRejectsVaryingTranslation(void)
Tests non-translational seam geometry fails before metric construction.
static PetscErrorCode TestSynchronizePeriodicStaggeredFieldsCopiesMixedAxes(void)
Tests ordered persistent synchronization for component-staggered Ucont.
static PetscErrorCode DestroyBoundaryHandler(BoundaryCondition **bc_ptr)
Destroys one boundary-condition handler allocated by a periodic test.
static PetscErrorCode TestPeriodicGeometryStoresMixedTranslations(void)
Tests mixed periodic directions are validated and stored independently.
static PetscErrorCode TestApplyMetricsPeriodicBCsSynchronizesAj(void)
Tests periodic metric transfer through the aggregate periodic-metrics helper.
static void MarkYPeriodic(UserCtx *user)
Marks the y faces as periodic for periodic-transfer harnesses.
static PetscErrorCode TestLocateParticleWrapsThroughOffAxisSeam(void)
An off-axis seam: a rotated x-periodic grid validates the rotated translation and wraps by it.
PetscErrorCode PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Asserts that two real values agree within tolerance.
PetscErrorCode PicurvDestroyMinimalContexts(SimCtx **simCtx_ptr, UserCtx **user_ptr)
Destroys minimal SimCtx/UserCtx fixtures and all owned PETSc objects.
PetscErrorCode PicurvCreateMinimalContextsWithPeriodicity(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz, PetscBool x_periodic, PetscBool y_periodic, PetscBool z_periodic)
Builds minimal SimCtx and UserCtx fixtures for C unit tests with configurable periodicity.
PetscErrorCode PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
Runs a named C test suite and prints pass/fail progress markers.
PetscErrorCode PicurvAssertVecConstant(Vec vec, PetscScalar expected, PetscReal tol, const char *context)
Asserts that a PETSc vector is spatially constant within tolerance.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
BoundaryFaceConfig boundary_faces[6]
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
@ PARTICLE_BOUNDARY_WRAP
Periodic faces: the particle re-enters through the paired face.
@ BC_HANDLER_PERIODIC_GEOMETRIC
BCHandlerType handler_type
PetscInt currentSettlementPass
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
ParticleBoundaryPolicy particle_policy
What a particle crossing this face becomes (BC param particle_policy).
SearchMetricsState searchMetrics
Cmpnts periodic_translation[3]
PetscBool periodic_translation_valid[3]
A 3D point or vector with PetscScalar components.
Defines a particle's core properties for Lagrangian tracking.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
Header file for particle location functions using the walking search algorithm.
PetscErrorCode LocateParticleOrFindMigrationTarget(UserCtx *user, Particle *particle, ParticleLocationStatus *status_out)
Locates a particle's host cell or identifies its migration target using a robust walk search.