18 PetscFunctionBeginUser;
19 PetscCheck(head != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"BC param list head cannot be NULL.");
20 PetscCall(PetscCalloc1(1, &
node));
21 PetscCall(PetscStrallocpy(key, &
node->key));
22 PetscCall(PetscStrallocpy(value, &
node->value));
24 cursor = &(*cursor)->
next;
27 PetscFunctionReturn(0);
36 PetscFunctionBeginUser;
37 if (!bc_ptr || !*bc_ptr) PetscFunctionReturn(0);
43 PetscCall(PetscFree(bc));
45 PetscFunctionReturn(0);
78 PetscErrorCode ierr_validate = 0;
80 PetscFunctionBeginUser;
85 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
87 PetscCall(PetscPopErrorHandler());
89 PetscCall(
PicurvAssertBool((PetscBool)(ierr_validate != 0),
"unpaired periodic faces should be rejected"));
91 PetscFunctionReturn(0);
101 const Cmpnts ***coor = NULL;
102 PetscReal expected_x = 0.0;
104 PetscFunctionBeginUser;
108 PetscCall(DMGetCoordinates(user->
da, &gcoor));
109 PetscCall(DMDAVecGetArrayRead(user->
fda, gcoor, &coor));
110 expected_x = coor[0][0][user->
info.mx - 2].
x - coor[0][0][0].
x;
111 PetscCall(DMDAVecRestoreArrayRead(user->
fda, gcoor, &coor));
122 PetscFunctionReturn(0);
132 PetscFunctionBeginUser;
142 "mixed-periodic X translation should have nonzero x component"));
144 "mixed-periodic Y translation should have nonzero y component"));
147 PetscFunctionReturn(0);
158 PetscErrorCode ierr_validate = 0;
160 PetscFunctionBeginUser;
164 PetscCall(DMGetCoordinates(user->
da, &gcoor));
165 PetscCall(DMDAVecGetArray(user->
fda, gcoor, &coor));
166 coor[1][1][user->
info.mx - 2].
y += 0.25;
167 PetscCall(DMDAVecRestoreArray(user->
fda, gcoor, &coor));
170 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
172 PetscCall(PetscPopErrorHandler());
174 PetscCall(
PicurvAssertBool((PetscBool)(ierr_validate != 0),
"varying seam translation should be rejected"));
176 PetscFunctionReturn(0);
187 const Cmpnts ***lcentx = NULL;
188 const char *fields[] = {
"Centx"};
189 PetscReal translation, spacing;
191 PetscFunctionBeginUser;
196 spacing = translation / (PetscReal)(user->
info.mx - 2);
198 PetscCall(DMDAVecGetArray(user->
fda, user->
Centx, ¢x));
199 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
200 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
201 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
202 centx[k][j][i] = (
Cmpnts){spacing * i, 2.0 + j, 3.0 + k};
206 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Centx, ¢x));
209 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lCentx, &lcentx));
211 "translated Centx negative adjacent ghost"));
213 "translated Centx negative endpoint"));
215 "translated Centx positive endpoint"));
217 "translated Centx positive adjacent ghost"));
218 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lCentx, &lcentx));
221 PetscFunctionReturn(0);
232 PetscReal ***nvert = NULL;
234 PetscFunctionBeginUser;
238 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
239 PetscCall(DMDAVecGetArray(user->
da, user->
Nvert, &nvert));
240 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
241 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
242 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
243 ucat[k][j][i] = (
Cmpnts){100.0 + i, 200.0 + i, 300.0 + i};
244 nvert[k][j][i] = 400.0 + i;
248 PetscCall(DMDAVecRestoreArray(user->
da, user->
Nvert, &nvert));
249 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
254 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcat, &ucat));
255 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert));
257 "QUICK Ucat negative outer ghost"));
259 "QUICK Ucat positive outer ghost"));
261 "QUICK Nvert negative outer ghost"));
263 "QUICK Nvert positive outer ghost"));
264 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert));
265 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcat, &ucat));
268 PetscFunctionReturn(0);
277 PetscFunctionBeginUser;
279 PetscCall(
PicurvAssertBool((PetscBool)(bc != NULL),
"periodic geometric factory should allocate a handler"));
281 PetscCall(
PicurvAssertBool((PetscBool)(bc->
Apply == NULL),
"periodic geometric handler should not expose Apply"));
284 PetscFunctionReturn(0);
294 PetscReal expected_neg_face = 0.0;
295 PetscReal expected_pos_face = 0.0;
296 PetscReal expected_neg_ghost = 0.0;
297 PetscReal expected_pos_ghost = 0.0;
299 PetscFunctionBeginUser;
303 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
304 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
305 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
306 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
307 ucont[k][j][i].
x = (PetscReal)i;
308 ucont[k][j][i].
y = 10.0 + (PetscReal)i;
309 ucont[k][j][i].
z = 20.0 + (PetscReal)i;
313 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
314 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
315 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
316 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
317 expected_neg_face = ucont[2][2][user->
info.mx - 2].
x;
318 expected_pos_face = ucont[2][2][1].
x;
319 expected_neg_ghost = ucont[2][2][user->
info.mx - 3].
x;
320 expected_pos_ghost = ucont[2][2][2].
x;
321 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
325 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
326 PetscCall(
PicurvAssertRealNear(expected_neg_face, ucont[2][2][0].x, 1.0e-12,
"NEG_X periodic face should copy from the opposite interior face"));
327 PetscCall(
PicurvAssertRealNear(expected_pos_face, ucont[2][2][user->
info.mx - 1].
x, 1.0e-12,
"POS_X periodic face should copy from the leading interior face"));
328 PetscCall(
PicurvAssertRealNear(expected_neg_ghost, ucont[2][2][-1].x, 1.0e-12,
"NEG_X ghost face should copy the second-to-last interior face"));
329 PetscCall(
PicurvAssertRealNear(expected_pos_ghost, ucont[2][2][user->
info.mx].
x, 1.0e-12,
"POS_X ghost face should copy the second interior face"));
330 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
333 PetscFunctionReturn(0);
342 PetscReal ***aj = NULL;
343 PetscReal expected_neg_face = 0.0;
344 PetscReal expected_pos_face = 0.0;
345 PetscReal expected_neg_ghost = 0.0;
346 PetscReal expected_pos_ghost = 0.0;
348 PetscFunctionBeginUser;
353 PetscCall(DMDAVecGetArray(user->
da, user->
Aj, &aj));
354 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
355 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
356 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
357 aj[k][j][i] = 100.0 + (PetscReal)i;
361 PetscCall(DMDAVecRestoreArray(user->
da, user->
Aj, &aj));
362 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
363 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
364 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
365 expected_neg_face = aj[2][2][user->
info.mx - 2];
366 expected_pos_face = aj[2][2][1];
367 expected_neg_ghost = expected_pos_face;
368 expected_pos_ghost = expected_neg_face;
369 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
373 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
374 PetscCall(
PicurvAssertRealNear(expected_neg_face, aj[2][2][0], 1.0e-12,
"NEG_X periodic metric face should copy from the opposite interior face"));
375 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"));
376 PetscCall(
PicurvAssertRealNear(expected_neg_ghost, aj[2][2][-1], 1.0e-12,
"cell-centered Aj negative ghost should retain PETSc wraparound"));
377 PetscCall(
PicurvAssertRealNear(expected_pos_ghost, aj[2][2][user->
info.mx], 1.0e-12,
"cell-centered Aj positive ghost should retain PETSc wraparound"));
378 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
381 PetscFunctionReturn(0);
390 PetscReal ***p = NULL;
391 PetscReal ***cs = NULL;
392 PetscReal ***diffusivity = NULL;
395 const char *fields[] = {
"Ucat",
"P",
"Phi",
"Nvert",
"Nu_t",
"CS",
"Diffusivity"};
397 PetscFunctionBeginUser;
402 PetscCall(DMCreateGlobalVector(user->
da, &user->
Nu_t));
403 PetscCall(DMCreateLocalVector(user->
da, &user->
lNu_t));
404 PetscCall(VecSet(user->
Nu_t, 5.0));
405 PetscCall(VecSet(user->
lNu_t, 0.0));
406 PetscCall(DMCreateGlobalVector(user->
da, &user->
CS));
407 PetscCall(DMCreateLocalVector(user->
da, &user->
lCs));
408 PetscCall(VecSet(user->
Phi, 3.0));
409 PetscCall(VecSet(user->
Nvert, 4.0));
411 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
412 PetscCall(DMDAVecGetArray(user->
da, user->
CS, &cs));
413 PetscCall(DMDAVecGetArray(user->
da, user->
Diffusivity, &diffusivity));
414 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
415 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
416 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
417 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
418 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
420 cs[k][j][i] = value + 4000.0;
421 diffusivity[k][j][i] = value + 5000.0;
422 ucat[k][j][i].
x = value + 1000.0;
423 ucat[k][j][i].
y = value + 2000.0;
424 ucat[k][j][i].
z = value + 3000.0;
428 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
429 PetscCall(DMDAVecRestoreArray(user->
da, user->
CS, &cs));
430 PetscCall(DMDAVecRestoreArray(user->
da, user->
Diffusivity, &diffusivity));
431 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
437 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
438 PetscCall(DMDAVecGetArrayRead(user->
da, user->
CS, &cs));
439 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Diffusivity, &diffusivity));
440 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
442 "x-periodic negative endpoint should copy the opposite interior value"));
444 "x-periodic positive endpoint should copy the leading interior value"));
446 "y-periodic negative endpoint should copy the opposite interior value"));
447 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 200), p[2][0][0], 1.0e-12,
448 "ordered synchronization should propagate the opposite periodic corner"));
449 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 1200), ucat[2][0][0].x, 1.0e-12,
450 "vector fields should use the same ordered periodic-corner protocol"));
451 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 4200), cs[2][0][0], 1.0e-12,
452 "CS should use the ordered periodic-corner protocol"));
453 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 10 * (my - 2) + 5200), diffusivity[2][0][0], 1.0e-12,
454 "Diffusivity should use the ordered periodic-corner protocol"));
455 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
456 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
CS, &cs));
457 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Diffusivity, &diffusivity));
458 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
462 PetscFunctionReturn(0);
472 PetscReal ***iaj = NULL;
474 const char *fields[] = {
"Csi",
"IAj"};
477 PetscFunctionBeginUser;
484 PetscCall(DMDAVecGetArray(user->
da, user->
IAj, &iaj));
485 PetscCall(DMDAVecGetArray(user->
fda, user->
Csi, &csi));
486 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
487 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
488 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
489 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
490 iaj[k][j][i] = value;
491 csi[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
495 PetscCall(DMDAVecRestoreArray(user->
da, user->
IAj, &iaj));
496 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Csi, &csi));
500 PetscCall(DMDAVecGetArrayRead(user->
da, user->
IAj, &iaj));
501 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Csi, &csi));
503 "I-face negative seam should copy the opposite physical seam face"));
505 "I-face positive dummy should copy the leading physical face"));
507 "I-face field should use cell-style synchronization tangentially"));
508 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 200), iaj[2][0][0], 1.0e-12,
509 "ordered face synchronization should propagate mixed-axis corners"));
510 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 1200), csi[2][0][0].x, 1.0e-12,
511 "vector I-face fields should use the same ordered synchronization"));
512 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
IAj, &iaj));
513 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Csi, &csi));
515 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lIAj, &iaj));
517 "I-face negative adjacent ghost should be shifted to the prior face"));
519 "I-face positive adjacent ghost should be shifted to the next face"));
521 "I-face tangential ghosts should retain cell-style wraparound"));
522 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lIAj, &iaj));
525 PetscFunctionReturn(0);
536 const char *fields[] = {
"Ucont"};
539 PetscFunctionBeginUser;
546 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
547 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
548 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
549 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++) {
550 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
551 ucont[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
555 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
559 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
561 "Ucont.x negative X seam should copy the opposite physical seam"));
563 "Ucont.y positive X dummy should copy the leading physical value"));
564 PetscCall(
PicurvAssertRealNear((PetscReal)(2 + 10 * (my - 2) + 3200), ucont[2][0][2].z, 1.0e-12,
565 "Ucont.z should synchronize tangentially in Y"));
566 PetscCall(
PicurvAssertRealNear((PetscReal)(mx - 2 + 10 * (my - 2) + 2200), ucont[2][0][0].y, 1.0e-12,
567 "ordered staggered synchronization should propagate mixed-axis corners"));
568 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
570 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
572 "Ucont.x should use face-normal X ghost repair"));
574 "Ucont.y should retain cell-style wraparound tangentially in X"));
576 "Ucont.x positive adjacent ghost should use the next face"));
578 "Ucont.y positive X ghost should retain cell-style wraparound"));
579 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
582 PetscFunctionReturn(0);
592 Vec ucont_before = NULL;
593 Vec ucont_difference = NULL;
596 PetscReal ***p = NULL;
597 PetscReal difference_norm = 0.0;
600 PetscFunctionBeginUser;
603 PetscCall(VecSet(user->
Bcs.
Ubcs, 0.0));
605 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
606 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
607 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
608 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
609 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
610 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
611 PetscReal value = (PetscReal)(i + 10 * j + 100 * k);
612 ucat[k][j][i].
x = value + 1000.0;
613 ucat[k][j][i].
y = value + 2000.0;
614 ucat[k][j][i].
z = value + 3000.0;
615 ucont[k][j][i].
x = value + 4000.0;
616 ucont[k][j][i].
y = value + 5000.0;
617 ucont[k][j][i].
z = value + 6000.0;
622 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
623 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
624 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
626 PetscCall(VecDuplicate(user->
Ucont, &ucont_before));
627 PetscCall(VecDuplicate(user->
Ucont, &ucont_difference));
628 PetscCall(VecCopy(user->
Ucont, ucont_before));
632 PetscCall(VecWAXPY(ucont_difference, -1.0, user->
Ucont, ucont_before));
633 PetscCall(VecNorm(ucont_difference, NORM_INFINITY, &difference_norm));
635 "post-projection cell finalization must preserve mixed-boundary Ucont"));
638 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
639 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
640 PetscCall(
PicurvAssertRealNear((PetscReal)((mx - 2) + 20 + 200 + 1000), ucat[2][2][0].x, 1.0e-12,
641 "mixed finalization should restore the negative x-periodic Ucat endpoint"));
643 "mixed finalization should extrapolate the non-periodic y dummy face"));
644 PetscCall(
PicurvAssertRealNear((PetscReal)(-((mx - 2) + 10 + 200 + 1000)), ucat[2][0][0].x, 1.0e-12,
645 "periodic synchronization should win at a mixed x-periodic/y-physical edge"));
647 "mixed finalization should restore the negative x-periodic pressure endpoint"));
648 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
649 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
651 PetscCall(VecDestroy(&ucont_difference));
652 PetscCall(VecDestroy(&ucont_before));
654 PetscFunctionReturn(0);
665 PetscReal dummy_inflow = 0.0;
666 PetscReal dummy_outflow = 0.0;
670 PetscFunctionBeginUser;
671 PetscCall(PetscMemzero(&ctx,
sizeof(ctx)));
674 PetscCall(VecSet(user->
Ucont, 1.0));
675 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
676 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
691 PetscCall(bc->
PreStep(bc, &ctx, &dummy_inflow, &dummy_outflow));
695 PetscCall(bc->
Apply(bc, &ctx));
696 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
697 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Bcs.
Uch, &uch));
698 PetscCall(
PicurvAssertRealNear(1.2, ucont[0][3][3].z, 1.0e-12,
"periodic driven trim should update the boundary face flux"));
699 PetscCall(
PicurvAssertRealNear(0.2, uch[0][3][3].z, 1.0e-12,
"periodic driven trim should be recorded in Uch"));
700 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
701 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Bcs.
Uch, &uch));
707 PetscFunctionReturn(0);
718 PetscErrorCode ierr_init = 0;
720 PetscFunctionBeginUser;
721 PetscCall(PetscMemzero(&ctx,
sizeof(ctx)));
731 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
733 PetscCall(PetscPopErrorHandler());
734 PetscCall(
PicurvAssertBool((PetscBool)(ierr_init != 0),
"periodic driven initialization should reject non-periodic faces"));
740 PetscFunctionReturn(0);
766 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv periodic development tests");
771 ierr =
PicurvRunTests(
"unit-periodic-dev", cases,
sizeof(cases) /
sizeof(cases[0]));
777 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 TransferPeriodicFaceField(UserCtx *user, const char *field_name)
(Primitive) Copies periodic data from the interior to the local ghost cell region for a single field.
PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user)
(Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundar...
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const char *field_names[])
Synchronizes persistent component-staggered vector fields.
PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const char *field_names[])
Synchronizes persistent fields belonging to one face family.
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 FinalizePostProjectionCellFields(UserCtx *user)
Finalizes cell-centered fields after the projection step.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const char *field_names[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
void FreeBC_ParamList(BC_Param *head)
Frees an entire linked list of boundary-condition parameters.
PetscErrorCode UpdateLocalGhosts(UserCtx *user, const char *fieldName)
Updates the local vector (including ghost points) from its corresponding global vector.
The "virtual table" struct for a boundary condition handler object.
PetscErrorCode(* PreStep)(BoundaryCondition *self, BCContext *ctx, PetscReal *local_inflow, PetscReal *local_outflow)
PetscErrorCode(* Destroy)(BoundaryCondition *self)
PetscErrorCode(* Initialize)(BoundaryCondition *self, BCContext *ctx)
PetscErrorCode(* Apply)(BoundaryCondition *self, BCContext *ctx)
static void MarkXPeriodic(UserCtx *user)
Marks the x faces as periodic for periodic-transfer harnesses.
static PetscErrorCode TestPeriodicDrivenConstantRejectsNonPeriodicFace(void)
Tests that the periodic driven handler rejects non-periodic faces during initialization.
static PetscErrorCode AppendBCParam(BC_Param **head, const char *key, const char *value)
Appends one key/value pair to a linked list of boundary-condition parameters.
static PetscErrorCode TestPeriodicGeometricFactoryAssignment(void)
Tests periodic geometric factory construction in the non-gating periodic harness.
static PetscErrorCode TestPeriodicFaceCenterCoordinateSynchronization(void)
Tests face-center coordinates remain geometrically continuous across a periodic seam.
int main(int argc, char **argv)
Runs the non-gating periodic development PETSc test binary.
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 TestTransferPeriodicFaceFieldCopiesXFaces(void)
Tests direct periodic face transfer on the staggered velocity field.
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 TestPeriodicDrivenConstantHandlerBehavior(void)
Tests periodic driven-flow controller initialization, sensing, and trim application.
PetscErrorCode PicurvCreateMinimalContexts(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz)
Builds minimal SimCtx and UserCtx fixtures for C unit tests.
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 PicurvPopulateIdentityMetrics(UserCtx *user)
Populates identity metric vectors on the minimal grid fixture.
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]
PetscReal targetVolumetricFlux
@ BC_HANDLER_PERIODIC_GEOMETRIC
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
BCHandlerType handler_type
PetscReal bulkVelocityCorrection
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
Cmpnts periodic_translation[3]
PetscBool periodic_translation_valid[3]
Vec Uch
Characteristic velocity for boundary conditions.
Provides execution context for a boundary condition handler.
A node in a linked list for storing key-value parameters from the bcs.dat file.
A 3D point or vector with PetscScalar components.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
A generic C-style linked list node for integers.