21 double values[3][3][3];
22 double weights[3][3][3];
24 PetscFunctionBeginUser;
25 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
26 for (PetscInt k = 0; k < 3; ++k) {
27 for (PetscInt j = 0; j < 3; ++j) {
28 for (PetscInt i = 0; i < 3; ++i) {
29 values[k][j][i] = 2.0;
30 weights[k][j][i] = 1.0;
37 "Simpson-rule filter should preserve a constant field"));
41 "box filter should preserve a constant field"));
43 for (PetscInt k = 0; k < 3; ++k) {
44 for (PetscInt j = 0; j < 3; ++j) {
45 for (PetscInt i = 0; i < 3; ++i) {
46 weights[k][j][i] = 0.0;
51 "box filter should return zero when all weights are zero"));
52 PetscFunctionReturn(0);
62 PetscErrorCode ierr_grid = 0;
63 PetscErrorCode ierr_non_square = 0;
65 PetscFunctionBeginUser;
68 "TGV3D should require custom geometry"));
70 "ZERO_FLOW should not require custom geometry"));
73 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
75 PetscCall(PetscPopErrorHandler());
77 "SetAnalyticalGridInfo should reject analytical types without custom geometry"));
81 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
83 PetscCall(PetscPopErrorHandler());
85 "TGV3D multi-block setup should reject non-square block counts"));
95 PetscCall(
PicurvAssertRealNear(PETSC_PI, user->
Min_X, 1.0e-12,
"TGV3D multi-block xmin should reflect the block column"));
96 PetscCall(
PicurvAssertRealNear(2.0 * PETSC_PI, user->
Max_X, 1.0e-12,
"TGV3D multi-block xmax should reflect the block column"));
98 PetscCall(
PicurvAssertRealNear(2.0 * PETSC_PI, user->
Max_Y, 1.0e-12,
"TGV3D multi-block ymax should reflect the block row"));
99 PetscCall(
PicurvAssertRealNear(2.0 * PETSC_PI, user->
Max_Z, 1.0e-12,
"TGV3D multi-block zmax should span the full domain"));
103 PetscFunctionReturn(0);
114 PetscReal value = 0.0;
115 PetscReal ***target_arr = NULL;
116 PetscReal *positions = NULL;
117 PetscReal *psi = NULL;
119 PetscFunctionBeginUser;
133 "constant scalar profile should evaluate to the configured value"));
135 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
136 positions[0] = 0.1; positions[1] = 0.2; positions[2] = 0.3;
137 positions[3] = 0.8; positions[4] = 0.6; positions[5] = 0.4;
138 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
141 PetscCall(DMSwarmGetField(user->
swarm,
"Psi", NULL, NULL, (
void **)&psi));
143 "SetAnalyticalScalarFieldOnParticles should overwrite the first particle scalar"));
145 "SetAnalyticalScalarFieldOnParticles should overwrite the second particle scalar"));
146 PetscCall(DMSwarmRestoreField(user->
swarm,
"Psi", NULL, NULL, (
void **)&psi));
155 "linear-x scalar profile should evaluate phi0 + slope_x * x"));
157 PetscCall(VecDuplicate(user->
Psi, &target));
159 PetscCall(DMDAVecGetArrayRead(user->
da, target, &target_arr));
161 "cell-center scalar fill should use the physical x center coordinate"));
162 PetscCall(DMDAVecRestoreArrayRead(user->
da, target, &target_arr));
163 PetscCall(VecDestroy(&target));
174 "sin-product scalar profile should peak at pi/2 in each coordinate"));
177 PetscFunctionReturn(0);
187 PetscErrorCode ierr_unknown = 0;
191 PetscFunctionBeginUser;
193 PetscCall(VecSet(user->
Ucat, 3.0));
194 PetscCall(VecSet(user->
P, 5.0));
195 PetscCall(VecSet(user->
Bcs.
Ubcs, 7.0));
207 Cmpnts ***l_csi, ***l_eta, ***l_zet;
209 PetscCall(DMDAGetLocalInfo(user->
fda, &linfo));
210 PetscCall(DMDAVecGetArray(user->
fda, user->
lCsi, &l_csi));
211 PetscCall(DMDAVecGetArray(user->
fda, user->
lEta, &l_eta));
212 PetscCall(DMDAVecGetArray(user->
fda, user->
lZet, &l_zet));
213 for (PetscInt k = linfo.zs; k < linfo.zs + linfo.zm; k++)
214 for (PetscInt j = linfo.ys; j < linfo.ys + linfo.ym; j++)
215 for (PetscInt i = linfo.xs; i < linfo.xs + linfo.xm; i++) {
216 l_csi[k][j][i] = (
Cmpnts){1.0, 0.0, 0.0};
217 l_eta[k][j][i] = (
Cmpnts){0.0, 1.0, 0.0};
218 l_zet[k][j][i] = (
Cmpnts){0.0, 0.0, 1.0};
220 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lZet, &l_zet));
221 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lEta, &l_eta));
222 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lCsi, &l_csi));
233 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
234 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
235 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Bcs.
Ubcs, &ubcs));
236 PetscCall(
PicurvAssertRealNear(1.25, ucat[1][1][1].x, 1.0e-12,
"UNIFORM_FLOW should impose the configured x velocity"));
237 PetscCall(
PicurvAssertRealNear(-0.5, ucat[1][1][1].y, 1.0e-12,
"UNIFORM_FLOW should impose the configured y velocity"));
238 PetscCall(
PicurvAssertRealNear(0.75, ucat[1][1][1].z, 1.0e-12,
"UNIFORM_FLOW should impose the configured z velocity"));
239 PetscCall(
PicurvAssertRealNear(1.25, ucont[1][1][1].x, 1.0e-12,
"UNIFORM_FLOW should set contravariant x flux (identity metric)"));
240 PetscCall(
PicurvAssertRealNear(-0.5, ucont[1][1][1].y, 1.0e-12,
"UNIFORM_FLOW should set contravariant y flux (identity metric)"));
241 PetscCall(
PicurvAssertRealNear(0.75, ucont[1][1][1].z, 1.0e-12,
"UNIFORM_FLOW should set contravariant z flux (identity metric)"));
242 PetscCall(
PicurvAssertRealNear(1.25, ubcs[0][1][1].x, 1.0e-12,
"UNIFORM_FLOW should populate boundary x velocity"));
243 PetscCall(
PicurvAssertRealNear(-0.5, ubcs[0][1][1].y, 1.0e-12,
"UNIFORM_FLOW should populate boundary y velocity"));
244 PetscCall(
PicurvAssertRealNear(0.75, ubcs[0][1][1].z, 1.0e-12,
"UNIFORM_FLOW should populate boundary z velocity"));
245 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Bcs.
Ubcs, &ubcs));
246 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
247 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
250 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
252 PetscCall(PetscPopErrorHandler());
254 "AnalyticalSolutionEngine should reject unknown analytical type strings"));
257 PetscFunctionReturn(0);
272 PetscReal ***p = NULL;
273 const PetscReal vel_decay = PetscExpReal(-0.5);
275 PetscFunctionBeginUser;
281 PetscCall(DMDAVecGetArray(user->
fda, user->
Cent, ¢));
282 PetscCall(DMDAVecGetArray(user->
fda, user->
lCentx, ¢_x));
283 PetscCall(DMDAVecGetArray(user->
fda, user->
lCenty, ¢_y));
284 PetscCall(DMDAVecGetArray(user->
fda, user->
lCentz, ¢_z));
285 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
286 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
287 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
288 cent[k][j][i].
x = 0.0;
289 cent[k][j][i].
y = 0.0;
290 cent[k][j][i].
z = 0.0;
291 cent_x[k][j][i] = cent[k][j][i];
292 cent_y[k][j][i] = cent[k][j][i];
293 cent_z[k][j][i] = cent[k][j][i];
297 cent[1][1][1].
x = 0.5 * PETSC_PI;
298 cent[1][1][1].
y = 0.0;
299 cent[1][1][1].
z = 0.0;
300 cent[1][2][1].
x = 0.0;
301 cent[1][2][1].
y = 0.5 * PETSC_PI;
302 cent[1][2][1].
z = 0.0;
303 cent_z[0][1][1].
x = 0.5 * PETSC_PI;
304 cent_z[0][1][1].
y = 0.0;
305 cent_z[0][1][1].
z = 0.0;
306 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lCentz, ¢_z));
307 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lCenty, ¢_y));
308 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lCentx, ¢_x));
309 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Cent, ¢));
313 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
314 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Bcs.
Ubcs, &ubcs));
315 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
316 PetscCall(
PicurvAssertRealNear(vel_decay, ucat[1][1][1].x, 1.0e-12,
"TGV sample should set the expected interior x velocity"));
317 PetscCall(
PicurvAssertRealNear(0.0, ucat[1][1][1].y, 1.0e-12,
"TGV sample should keep the paired interior y velocity at zero"));
318 PetscCall(
PicurvAssertRealNear(-vel_decay, ucat[1][2][1].y, 1.0e-12,
"TGV sample should set the expected interior y velocity"));
319 PetscCall(
PicurvAssertRealNear(0.0, p[1][1][1], 1.0e-12,
"Chosen TGV sample should produce zero pressure"));
320 PetscCall(
PicurvAssertRealNear(vel_decay, ubcs[0][1][1].x, 1.0e-12,
"TGV sample should set the expected boundary x velocity"));
321 PetscCall(
PicurvAssertRealNear(0.0, ubcs[0][1][1].y, 1.0e-12,
"TGV boundary sample should keep the paired y velocity at zero"));
322 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
323 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Bcs.
Ubcs, &ubcs));
324 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
327 PetscFunctionReturn(0);
337 PetscReal *data = NULL;
338 const PetscReal vel_decay = PetscExpReal(-0.5);
340 PetscFunctionBeginUser;
341 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
346 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 6, &tempVec));
347 PetscCall(VecGetArray(tempVec, &data));
348 data[0] = 0.5 * PETSC_PI; data[1] = 0.0; data[2] = 0.0;
349 data[3] = 0.0; data[4] = 0.5 * PETSC_PI; data[5] = 0.0;
350 PetscCall(VecRestoreArray(tempVec, &data));
353 PetscCall(VecGetArray(tempVec, &data));
355 "TGV3D particle dispatch should populate the x velocity at x=pi/2"));
357 "TGV3D particle dispatch should leave the first particle y velocity at zero"));
359 "TGV3D particle dispatch should leave the first particle z velocity at zero"));
361 "TGV3D particle dispatch should leave the second particle x velocity at zero"));
363 "TGV3D particle dispatch should populate the y velocity at y=pi/2"));
365 "TGV3D particle dispatch should leave the second particle z velocity at zero"));
366 PetscCall(VecRestoreArray(tempVec, &data));
369 PetscCall(VecGetArray(tempVec, &data));
373 PetscCall(VecRestoreArray(tempVec, &data));
375 PetscCall(VecGetArray(tempVec, &data));
377 "Non-TGV particle dispatch should leave the vector untouched"));
379 "Non-TGV particle dispatch should preserve the y component"));
381 "Non-TGV particle dispatch should preserve the z component"));
382 PetscCall(VecRestoreArray(tempVec, &data));
389 PetscCall(VecGetArray(tempVec, &data));
391 "UNIFORM_FLOW particle dispatch should populate the x velocity"));
393 "UNIFORM_FLOW particle dispatch should populate the y velocity"));
395 "UNIFORM_FLOW particle dispatch should populate the z velocity"));
397 "UNIFORM_FLOW particle dispatch should use the same x velocity for each particle"));
399 "UNIFORM_FLOW particle dispatch should use the same y velocity for each particle"));
401 "UNIFORM_FLOW particle dispatch should use the same z velocity for each particle"));
402 PetscCall(VecRestoreArray(tempVec, &data));
404 PetscCall(VecDestroy(&tempVec));
405 PetscFunctionReturn(0);
416 PetscReal ***
nu_t = NULL;
417 const PetscReal expected_nu_t = 0.25 * PetscSqrtReal(2.0);
419 PetscFunctionBeginUser;
421 PetscCall(DMCreateGlobalVector(user->
da, &user->
Nu_t));
422 PetscCall(DMCreateLocalVector(user->
da, &user->
lNu_t));
423 PetscCall(DMCreateGlobalVector(user->
da, &user->
CS));
424 PetscCall(DMCreateLocalVector(user->
da, &user->
lCs));
426 PetscCall(VecSet(user->
Aj, 1.0));
427 PetscCall(VecSet(user->
Nu_t, 0.0));
428 PetscCall(VecSet(user->
CS, 0.5));
429 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
430 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
431 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
432 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
433 ucat[k][j][i].
x = (PetscReal)i;
434 ucat[k][j][i].
y = 0.0;
435 ucat[k][j][i].
z = 0.0;
439 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
440 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
441 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
442 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
443 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
444 PetscCall(DMGlobalToLocalBegin(user->
da, user->
CS, INSERT_VALUES, user->
lCs));
445 PetscCall(DMGlobalToLocalEnd(user->
da, user->
CS, INSERT_VALUES, user->
lCs));
448 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Nu_t, &
nu_t));
450 "linear velocity field should yield deterministic LES eddy viscosity"));
452 "boundary cells should remain untouched by the interior LES loop"));
453 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Nu_t, &
nu_t));
455 PetscCall(VecDestroy(&user->
CS));
456 PetscCall(VecDestroy(&user->
lCs));
458 PetscFunctionReturn(0);
468 PetscErrorCode ierr_flow = 0;
470 PetscFunctionBeginUser;
474 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
476 PetscCall(PetscPopErrorHandler());
478 "FlowSolver should reject unsupported momentum solver selectors"));
481 PetscFunctionReturn(0);
497 PetscFunctionBeginUser;
499 PetscCall(VecDuplicate(user->
Ucont, &rct));
500 PetscCall(VecZeroEntries(rct));
512 PetscCall(VecSet(user->
Nvert, 0.0));
513 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Nvert, INSERT_VALUES, user->
lNvert));
514 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Nvert, INSERT_VALUES, user->
lNvert));
515 PetscCall(DMDAVecGetArray(user->
fda, user->
lCsi, &l_csi));
516 PetscCall(DMDAVecGetArray(user->
fda, user->
lEta, &l_eta));
517 PetscCall(DMDAVecGetArray(user->
fda, user->
lZet, &l_zet));
518 l_csi[1][1][1].
x = 1.0; l_csi[1][1][1].
y = 0.0; l_csi[1][1][1].
z = 0.0;
519 l_eta[1][1][1].
x = 0.0; l_eta[1][1][1].
y = 1.0; l_eta[1][1][1].
z = 0.0;
520 l_zet[1][1][1].
x = 0.0; l_zet[1][1][1].
y = 0.0; l_zet[1][1][1].
z = 1.0;
521 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lZet, &l_zet));
522 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lEta, &l_eta));
523 PetscCall(DMDAVecRestoreArray(user->
fda, user->
lCsi, &l_csi));
526 PetscCall(DMDAVecGetArrayRead(user->
fda, rct, &rct_arr));
528 "driven flow source should update the controller magnitude"));
530 "driven flow source should leave the y component unchanged"));
532 "driven flow source should leave the z component unchanged"));
533 PetscCall(DMDAVecRestoreArrayRead(user->
fda, rct, &rct_arr));
535 PetscCall(VecDestroy(&rct));
537 PetscFunctionReturn(0);
571 PetscInt gxs, gys, gzs, gxm, gym, gzm;
572 PetscFunctionBeginUser;
573 PetscCall(DMDAGetGhostCorners(fda, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
574 PetscCall(DMDAVecGetArray(fda, lvec, &a));
575 for (PetscInt k = gzs; k < gzs+gzm; ++k)
576 for (PetscInt j = gys; j < gys+gym; ++j)
577 for (PetscInt i = gxs; i < gxs+gxm; ++i) { a[k][j][i].
x = x; a[k][j][i].
y = y; a[k][j][i].
z = z; }
578 PetscCall(DMDAVecRestoreArray(fda, lvec, &a));
579 PetscFunctionReturn(0);
592 PetscInt gxs, gys, gzs, gxm, gym, gzm;
593 PetscFunctionBeginUser;
594 PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
595 PetscCall(DMDAVecGetArray(da, lvec, &a));
596 for (PetscInt k = gzs; k < gzs+gzm; ++k)
597 for (PetscInt j = gys; j < gys+gym; ++j)
598 for (PetscInt i = gxs; i < gxs+gxm; ++i) a[k][j][i] = v;
599 PetscCall(DMDAVecRestoreArray(da, lvec, &a));
600 PetscFunctionReturn(0);
614 PetscInt gxs, gys, gzs, gxm, gym, gzm;
615 PetscFunctionBeginUser;
616 PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
617 PetscCall(DMDAVecGetArray(da, lvec, &a));
619 if (ci >= gxs && ci < gxs+gxm && cj >= gys && cj < gys+gym && ck >= gzs && ck < gzs+gzm)
621 PetscCall(DMDAVecRestoreArray(da, lvec, &a));
622 PetscFunctionReturn(0);
630 PetscFunctionBeginUser;
647 "restored history enables BDF2 at restart setup"));
650 "restored history enables BDF2 on first restart solve"));
652 PetscFunctionReturn(0);
659 PetscBool px, PetscBool py, PetscBool pz,
BCType bc)
661 PetscFunctionBeginUser;
669 (*simCtx)->dt = 0.1; (*simCtx)->step = 1; (*simCtx)->StartStep = 0;
670 (*simCtx)->ren = 1.0; (*simCtx)->les = 0; (*simCtx)->rans = 0;
671 (*simCtx)->central = 0; (*simCtx)->invicid = 0; (*simCtx)->block_number = 1;
672 (*simCtx)->TwoD = 0; (*simCtx)->clark = 0;
675 if (!(*user)->lNu_t) PetscCall(DMCreateLocalVector((*user)->da, &(*user)->lNu_t));
680 PetscFunctionReturn(0);
686 const PetscBool p = (PetscBool)(bc ==
PERIODIC);
687 PetscFunctionBeginUser;
689 PetscFunctionReturn(0);
696 PetscFunctionBeginUser;
707 PetscFunctionReturn(0);
714 PetscFunctionBeginUser;
722 PetscFunctionReturn(0);
729 PetscFunctionBeginUser;
737 PetscFunctionReturn(0);
744 PetscFunctionBeginUser;
752 PetscFunctionReturn(0);
759 PetscFunctionBeginUser;
765 PetscFunctionReturn(0);
772 PetscFunctionBeginUser;
779 PetscFunctionReturn(0);
786 PetscFunctionBeginUser;
796 PetscFunctionReturn(0);
803 PetscReal n_ucont_0, n_ucat_0, n_nvert_0, n_ucont_1, n_ucat_1, n_nvert_1;
804 PetscFunctionBeginUser;
809 PetscCall(VecNorm(user->
lUcont, NORM_2, &n_ucont_0));
810 PetscCall(VecNorm(user->
lUcat, NORM_2, &n_ucat_0));
811 PetscCall(VecNorm(user->
lNvert, NORM_2, &n_nvert_0));
813 PetscCall(VecNorm(user->
lUcont, NORM_2, &n_ucont_1));
814 PetscCall(VecNorm(user->
lUcat, NORM_2, &n_ucat_1));
815 PetscCall(VecNorm(user->
lNvert, NORM_2, &n_nvert_1));
821 PetscFunctionReturn(0);
832 const PetscReal sx = dy*dz, sy = dx*dz, sz = dx*dy, aj = 1.0/(dx*dy*dz);
837 PetscFunctionBeginUser;
838 for (
int t = 0; t < 4; ++t) {
844 PetscFunctionReturn(0);
857 PetscInt gxs, gys, gzs, gxm, gym, gzm;
858 PetscFunctionBeginUser;
859 PetscCall(DMDAGetGhostCorners(fda, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
860 PetscCall(DMDAVecGetArray(fda, lvec, &a));
861 for (PetscInt k = gzs; k < gzs+gzm; ++k)
862 for (PetscInt j = gys; j < gys+gym; ++j)
863 for (PetscInt i = gxs; i < gxs+gxm; ++i) { a[k][j][i].
x = slope*i; a[k][j][i].
y = 0; a[k][j][i].
z = 0; }
864 PetscCall(DMDAVecRestoreArray(fda, lvec, &a));
865 PetscFunctionReturn(0);
878 PetscInt gxs, gys, gzs, gxm, gym, gzm;
879 PetscFunctionBeginUser;
880 PetscCall(DMDAGetGhostCorners(fda, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
881 PetscCall(DMDAVecGetArray(fda, lvec, &a));
882 for (PetscInt k = gzs; k < gzs+gzm; ++k)
883 for (PetscInt j = gys; j < gys+gym; ++j)
884 for (PetscInt i = gxs; i < gxs+gxm; ++i) { a[k][j][i].
x = gamma*j; a[k][j][i].
y = 0; a[k][j][i].
z = 0; }
885 PetscCall(DMDAVecRestoreArray(fda, lvec, &a));
886 PetscFunctionReturn(0);
894 PetscFunctionBeginUser;
901 PetscFunctionReturn(0);
908 PetscFunctionBeginUser;
916 PetscFunctionReturn(0);
923 const PetscInt offs[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
924 PetscFunctionBeginUser;
925 for (
int d = 0; d < 3; ++d) {
929 4+offs[d][0], 4+offs[d][1], 4+offs[d][2], 1.0));
943 PetscFunctionReturn(0);
951 PetscFunctionBeginUser;
968 PetscFunctionReturn(0);
975 PetscErrorCode e1 = 0, e2 = 0;
976 PetscFunctionBeginUser;
980 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
982 PetscCall(PetscPopErrorHandler());
983 PetscCall(
PicurvAssertBool((PetscBool)(e1 != 0),
"block_number<=0 rejected"));
986 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
988 PetscCall(PetscPopErrorHandler());
989 PetscCall(
PicurvAssertBool((PetscBool)(e2 != 0),
"non-finite inverse-Jacobian rejected"));
992 PetscFunctionReturn(0);
999 PetscFunctionBeginUser;
1007 PetscFunctionReturn(0);
1014 PetscFunctionBeginUser;
1028 PetscFunctionReturn(0);
1035 PetscFunctionBeginUser;
1045 PetscFunctionReturn(0);
1052 Vec ucont0, ucat0, nvert0, nut0, aj0;
1054 PetscFunctionBeginUser;
1060 PetscCall(VecDuplicate(user->
lUcont, &ucont0)); PetscCall(VecCopy(user->
lUcont, ucont0));
1061 PetscCall(VecDuplicate(user->
lUcat, &ucat0)); PetscCall(VecCopy(user->
lUcat, ucat0));
1062 PetscCall(VecDuplicate(user->
lNvert, &nvert0)); PetscCall(VecCopy(user->
lNvert, nvert0));
1063 PetscCall(VecDuplicate(user->
lNu_t, &nut0)); PetscCall(VecCopy(user->
lNu_t, nut0));
1064 PetscCall(VecDuplicate(user->
lAj, &aj0)); PetscCall(VecCopy(user->
lAj, aj0));
1067 PetscCall(VecEqual(user->
lUcat, ucat0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lUcat bit-identical"));
1069 PetscCall(VecEqual(user->
lNu_t, nut0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lNu_t bit-identical"));
1070 PetscCall(VecEqual(user->
lAj, aj0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lAj bit-identical"));
1071 PetscCall(VecDestroy(&ucont0)); PetscCall(VecDestroy(&ucat0)); PetscCall(VecDestroy(&nvert0));
1072 PetscCall(VecDestroy(&nut0)); PetscCall(VecDestroy(&aj0));
1074 PetscFunctionReturn(0);
1083 const PetscInt mx = 9, my = 9, mz = 9;
1084 PetscFunctionBeginUser;
1086 PetscCall(DMDAVecGetArray(user->
da, user->
lNvert, &nvert));
1088 PetscCall(
PicurvAssertIntEqual(0x7,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,0),
"all rows active (periodic interior)"));
1089 PetscCall(
PicurvAssertIntEqual(0x6,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,1),
"TwoD=1 clears xi row"));
1090 PetscCall(
PicurvAssertIntEqual(0x5,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,2),
"TwoD=2 clears eta row"));
1091 PetscCall(
PicurvAssertIntEqual(0x3,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,3),
"TwoD=3 clears zeta row"));
1093 PetscCall(
PicurvAssertIntEqual(0x6,
MomCellActiveRows(nvert,4,4,mx-2,mx,my,mz,PETSC_TRUE,PETSC_FALSE,PETSC_FALSE,0),
"pos non-periodic xi face clears xi row"));
1096 PetscCall(DMDAVecRestoreArray(user->
da, user->
lNvert, &nvert));
1097 PetscCall(DMDAVecGetArray(user->
da, user->
lNvert, &nvert));
1098 PetscCall(
PicurvAssertIntEqual(0,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,0),
"solid cell -> all rows inactive"));
1099 PetscCall(DMDAVecRestoreArray(user->
da, user->
lNvert, &nvert));
1101 PetscFunctionReturn(0);
1108 PetscErrorCode e_bad = 0; PetscBool eq;
1110 PetscFunctionBeginUser;
1113 PetscCall(VecDuplicate(user->
lAj, &aj_good)); PetscCall(VecCopy(user->
lAj, aj_good));
1116 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
1118 PetscCall(PetscPopErrorHandler());
1119 PetscCall(
PicurvAssertBool((PetscBool)(e_bad != 0),
"bad metric triggers error"));
1122 PetscCall(VecCopy(aj_good, user->
lAj));
1123 PetscCall(VecEqual(user->
lAj, aj_good, &eq));
1124 PetscCall(
PicurvAssertBool(eq,
"lAj usable after error (arrays were restored)"));
1129 PetscCall(VecDestroy(&aj_good));
1131 PetscFunctionReturn(0);
1139 Vec Rhs, ref; PetscReal dt, nrm;
1140 PetscFunctionBeginUser;
1143 PetscCall(VecSet(user->
Ucont, 2.0));
1144 PetscCall(VecSet(user->
Ucont_o, 1.0));
1145 PetscCall(VecSet(user->
Ucont_rm1, 0.5));
1146 PetscCall(VecDuplicate(user->
Ucont, &Rhs));
1147 PetscCall(VecDuplicate(user->
Ucont, &ref));
1154 PetscCall(VecSet(Rhs, 3.0));
1155 PetscCall(VecAXPY(Rhs, -a0/dt, user->
Ucont));
1156 PetscCall(VecAXPY(Rhs, +2.0/dt, user->
Ucont_o));
1157 PetscCall(VecAXPY(Rhs, -0.5/dt, user->
Ucont_rm1));
1159 PetscCall(VecSet(ref, -9.5));
1160 PetscCall(VecAXPY(ref, -1.0, Rhs)); PetscCall(VecNorm(ref, NORM_INFINITY, &nrm));
1168 PetscCall(VecSet(Rhs, 3.0));
1169 PetscCall(VecAXPY(Rhs, -a0/dt, user->
Ucont));
1170 PetscCall(VecAXPY(Rhs, +1.0/dt, user->
Ucont_o));
1172 PetscCall(VecSet(ref, -7.0));
1173 PetscCall(VecAXPY(ref, -1.0, Rhs)); PetscCall(VecNorm(ref, NORM_INFINITY, &nrm));
1176 PetscCall(VecDestroy(&Rhs)); PetscCall(VecDestroy(&ref));
1178 PetscFunctionReturn(0);
1187 PetscErrorCode ierr;
1221 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv solver utility tests");
1226 ierr =
PicurvRunTests(
"unit-solver", cases,
sizeof(cases) /
sizeof(cases[0]));
1232 ierr = PetscFinalize();
PetscErrorCode EvaluateAnalyticalScalarProfile(const SimCtx *simCtx, PetscReal x, PetscReal y, PetscReal z, PetscReal t, PetscReal *value)
Evaluates the configured verification scalar profile at one physical point.
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters(UserCtx *user, Vec targetVec)
Writes the configured verification scalar profile at physical cell centers into a scalar Vec.
PetscErrorCode SetAnalyticalScalarFieldOnParticles(UserCtx *user, ParticleFieldId particle_field_id)
Writes the configured verification scalar profile onto a particle swarm scalar field.
PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
Dispatches to the appropriate analytical solution function based on simulation settings.
PetscBool AnalyticalTypeRequiresCustomGeometry(const char *analytical_type)
Reports whether an analytical type requires custom geometry/decomposition logic.
PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
Applies the analytical solution to particle velocity vector.
PetscErrorCode SetAnalyticalGridInfo(UserCtx *user)
Sets the grid domain and resolution for analytical solution cases.
Momentum source terms added to the contravariant RHS.
PetscErrorCode ComputeDrivenChannelFlowSource(UserCtx *user, Vec Rct)
Applies a momentum source term to drive flow in a periodic channel or pipe.
double ApplyLESTestFilter(const SimCtx *simCtx, double values[3][3][3], double weights[3][3][3])
Applies a numerical "test filter" to a 3x3x3 stencil of data points.
PetscErrorCode ComputeEddyViscosityLES(UserCtx *user)
Computes the turbulent eddy viscosity (Nu_t) for the LES model.
@ MOM_STAB_LIMITER_VISCOSITY
PetscBool MomentumUsesBDF2(SimCtx *simCtx)
Returns whether the current physical step uses the BDF2 discretization.
PetscReal MomentumBDFCoefficient(SimCtx *simCtx)
Returns the BDF physical-time coefficient a0 for the current step.
PetscInt MomCellActiveRows(PetscReal ***nvert, PetscInt k, PetscInt j, PetscInt i, PetscInt mx, PetscInt my, PetscInt mz, PetscBool np_x1, PetscBool np_y1, PetscBool np_z1, PetscInt twoD)
Active staggered-momentum row mask for a cell (exposed for unit testing).
PetscErrorCode ComputeMomentumStabilityEstimate(UserCtx *user, PetscInt block_number, PetscReal dt, MomStabCandidate candidate, MomStabilityReport *rep)
Compute the momentum pseudo-time stability estimate (shadow/diagnostic).
Diagnostic report produced by ComputeMomentumStabilityEstimate().
PetscErrorCode FlowSolver(SimCtx *simCtx)
Orchestrates a single time step of the Eulerian fluid solver.
static PetscErrorCode TestAnalyticalSolutionEngineTaylorGreenSamples(void)
Tests exact Taylor-Green samples on selected Eulerian interior and boundary points.
static PetscErrorCode TestMomentumStabilityWallSuppression(void)
static PetscErrorCode MomSetLocalScalarCell(DM da, Vec lvec, PetscInt ci, PetscInt cj, PetscInt ck, PetscReal v)
Sets a single local-scalar cell value (e.g.
static PetscErrorCode TestMomentumActiveRowsHelper(void)
static PetscErrorCode TestComputeEddyViscosityLESDeterministicField(void)
Tests deterministic LES eddy-viscosity computation on a linear velocity field.
static PetscErrorCode TestFlowSolverRejectsUnsupportedMomentumSolverType(void)
Tests FlowSolver guardrails for unsupported momentum solver selections.
static PetscErrorCode TestMomentumStabilityOneSidedDirections(void)
int main(int argc, char **argv)
Runs the unit-solver PETSc test binary.
static PetscErrorCode TestMomentumStabilityReadOnly(void)
static PetscErrorCode TestMomentumStabilityOneSidedViscous(void)
static PetscErrorCode MomSetCartesianMetrics(UserCtx *user, PetscReal dx, PetscReal dy, PetscReal dz)
Sets uniform Cartesian metrics for spacing (dx,dy,dz) on all cell and face arrays.
static PetscErrorCode TestAnalyticalScalarVerificationHelpers(void)
Tests analytical scalar verification helper routines.
static PetscErrorCode TestMomentumStabilityReadOnlyExact(void)
static PetscErrorCode TestMomentumStabilityErrorReentry(void)
static PetscErrorCode TestMomentumStabilityActiveRowMask(void)
static PetscErrorCode TestMomentumStabilityCandidateDShear(void)
static PetscErrorCode TestMomentumStabilityViscousLongitudinal(void)
static PetscErrorCode MomMakeUnitGrid(SimCtx **simCtx, UserCtx **user, PetscInt n, BCType bc)
static PetscErrorCode TestMomentumStabilityCandidateBCDivergence(void)
static PetscErrorCode TestDrivenChannelFlowSource(void)
Tests driven-channel flow source-term evaluation.
static PetscErrorCode MomFillLocalCmpnts(DM fda, Vec lvec, PetscReal x, PetscReal y, PetscReal z)
Fills a local Cmpnts vector (ghosts included) with a uniform vector value.
static PetscErrorCode TestMomentumStabilityViscousScalesWithNu(void)
static PetscErrorCode TestMomentumStabilityAnisotropicViscous(void)
static PetscErrorCode TestAnalyticalGeometrySelection(void)
Tests analytical geometry selection for supported analytical solutions.
static PetscErrorCode TestMomentumBDFCoefficient(void)
static PetscErrorCode TestMomentumStabilityCenteredConvection(void)
static PetscErrorCode TestMomentumStabilityDirectionalQuick(void)
static PetscErrorCode TestAnalyticalSolutionForParticlesDispatch(void)
Tests particle analytical-solution dispatch for TGV3D, UNIFORM_FLOW, and non-analytical no-op paths.
static PetscErrorCode MomMakeUnitGridP(SimCtx **simCtx, UserCtx **user, PetscInt n, PetscBool px, PetscBool py, PetscBool pz, BCType bc)
static PetscErrorCode TestMomentumBDFResidualCombination(void)
static void MomSetAllBC(UserCtx *user, BCType t)
Sets the mathematical BC type on all six faces of a test UserCtx.
static PetscErrorCode MomFillLocalScalar(DM da, Vec lvec, PetscReal v)
Fills a local scalar vector (ghosts included) with a uniform value.
static PetscErrorCode TestLESTestFilterPaths(void)
Tests LES test-filter helper paths for representative cases.
static PetscErrorCode MomFillUcatShearY(DM fda, Vec lvec, PetscReal gamma)
Fills lUcat as a linear shear u=(gamma*j,0,0) so |grad u|_inf = gamma.
static PetscErrorCode TestMomentumStabilityQuickBoundary(void)
static PetscErrorCode TestMomentumStabilityLESEddyViscosity(void)
static PetscErrorCode TestMomentumStabilityQuickInterior(void)
static PetscErrorCode TestAnalyticalSolutionEngineDispatch(void)
Tests analytical solution engine ZERO_FLOW, UNIFORM_FLOW, and unknown-type dispatch.
static PetscErrorCode MomFillUcontXRamp(DM fda, Vec lvec, PetscReal slope)
Fills lUcont.x as a linear ramp slope*i (nonzero discrete contravariant divergence).
static PetscErrorCode TestMomentumStabilityValidation(void)
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 PicurvCreateSwarmPair(UserCtx *user, PetscInt nlocal, const char *post_field_name)
Creates matched solver and post-processing swarms for tests.
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.
BCType
Defines the general mathematical/physical Category of a boundary.
BoundaryFaceConfig boundary_faces[6]
PetscReal forceScalingFactor
@ 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...
MomentumSolverType
Enumerator to identify the implemented momentum solver strategies.
VerificationScalarConfig verificationScalar
Cmpnts AnalyticalUniformVelocity
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
PetscBool restartHistoryAvailable
MomentumSolverType mom_solver_type
PetscReal drivingForceMagnitude
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.
double nu_t(double yplus)
Computes turbulent eddy viscosity ratio (ν_t / ν)