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);
629 PetscFunctionBeginUser;
640 PetscFunctionReturn(0);
647 PetscBool px, PetscBool py, PetscBool pz,
BCType bc)
649 PetscFunctionBeginUser;
657 (*simCtx)->dt = 0.1; (*simCtx)->step = 1; (*simCtx)->StartStep = 0;
658 (*simCtx)->ren = 1.0; (*simCtx)->les = 0; (*simCtx)->rans = 0;
659 (*simCtx)->central = 0; (*simCtx)->invicid = 0; (*simCtx)->block_number = 1;
660 (*simCtx)->TwoD = 0; (*simCtx)->clark = 0;
663 if (!(*user)->lNu_t) PetscCall(DMCreateLocalVector((*user)->da, &(*user)->lNu_t));
668 PetscFunctionReturn(0);
674 const PetscBool p = (PetscBool)(bc ==
PERIODIC);
675 PetscFunctionBeginUser;
677 PetscFunctionReturn(0);
684 PetscFunctionBeginUser;
695 PetscFunctionReturn(0);
702 PetscFunctionBeginUser;
710 PetscFunctionReturn(0);
717 PetscFunctionBeginUser;
725 PetscFunctionReturn(0);
732 PetscFunctionBeginUser;
740 PetscFunctionReturn(0);
747 PetscFunctionBeginUser;
753 PetscFunctionReturn(0);
760 PetscFunctionBeginUser;
767 PetscFunctionReturn(0);
774 PetscFunctionBeginUser;
784 PetscFunctionReturn(0);
791 PetscReal n_ucont_0, n_ucat_0, n_nvert_0, n_ucont_1, n_ucat_1, n_nvert_1;
792 PetscFunctionBeginUser;
797 PetscCall(VecNorm(user->
lUcont, NORM_2, &n_ucont_0));
798 PetscCall(VecNorm(user->
lUcat, NORM_2, &n_ucat_0));
799 PetscCall(VecNorm(user->
lNvert, NORM_2, &n_nvert_0));
801 PetscCall(VecNorm(user->
lUcont, NORM_2, &n_ucont_1));
802 PetscCall(VecNorm(user->
lUcat, NORM_2, &n_ucat_1));
803 PetscCall(VecNorm(user->
lNvert, NORM_2, &n_nvert_1));
809 PetscFunctionReturn(0);
820 const PetscReal sx = dy*dz, sy = dx*dz, sz = dx*dy, aj = 1.0/(dx*dy*dz);
825 PetscFunctionBeginUser;
826 for (
int t = 0; t < 4; ++t) {
832 PetscFunctionReturn(0);
845 PetscInt gxs, gys, gzs, gxm, gym, gzm;
846 PetscFunctionBeginUser;
847 PetscCall(DMDAGetGhostCorners(fda, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
848 PetscCall(DMDAVecGetArray(fda, lvec, &a));
849 for (PetscInt k = gzs; k < gzs+gzm; ++k)
850 for (PetscInt j = gys; j < gys+gym; ++j)
851 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; }
852 PetscCall(DMDAVecRestoreArray(fda, lvec, &a));
853 PetscFunctionReturn(0);
866 PetscInt gxs, gys, gzs, gxm, gym, gzm;
867 PetscFunctionBeginUser;
868 PetscCall(DMDAGetGhostCorners(fda, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
869 PetscCall(DMDAVecGetArray(fda, lvec, &a));
870 for (PetscInt k = gzs; k < gzs+gzm; ++k)
871 for (PetscInt j = gys; j < gys+gym; ++j)
872 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; }
873 PetscCall(DMDAVecRestoreArray(fda, lvec, &a));
874 PetscFunctionReturn(0);
882 PetscFunctionBeginUser;
889 PetscFunctionReturn(0);
896 PetscFunctionBeginUser;
904 PetscFunctionReturn(0);
911 const PetscInt offs[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
912 PetscFunctionBeginUser;
913 for (
int d = 0; d < 3; ++d) {
917 4+offs[d][0], 4+offs[d][1], 4+offs[d][2], 1.0));
931 PetscFunctionReturn(0);
939 PetscFunctionBeginUser;
956 PetscFunctionReturn(0);
963 PetscErrorCode e1 = 0, e2 = 0;
964 PetscFunctionBeginUser;
968 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
970 PetscCall(PetscPopErrorHandler());
971 PetscCall(
PicurvAssertBool((PetscBool)(e1 != 0),
"block_number<=0 rejected"));
974 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
976 PetscCall(PetscPopErrorHandler());
977 PetscCall(
PicurvAssertBool((PetscBool)(e2 != 0),
"non-finite inverse-Jacobian rejected"));
980 PetscFunctionReturn(0);
987 PetscFunctionBeginUser;
995 PetscFunctionReturn(0);
1002 PetscFunctionBeginUser;
1016 PetscFunctionReturn(0);
1023 PetscFunctionBeginUser;
1033 PetscFunctionReturn(0);
1040 Vec ucont0, ucat0, nvert0, nut0, aj0;
1042 PetscFunctionBeginUser;
1048 PetscCall(VecDuplicate(user->
lUcont, &ucont0)); PetscCall(VecCopy(user->
lUcont, ucont0));
1049 PetscCall(VecDuplicate(user->
lUcat, &ucat0)); PetscCall(VecCopy(user->
lUcat, ucat0));
1050 PetscCall(VecDuplicate(user->
lNvert, &nvert0)); PetscCall(VecCopy(user->
lNvert, nvert0));
1051 PetscCall(VecDuplicate(user->
lNu_t, &nut0)); PetscCall(VecCopy(user->
lNu_t, nut0));
1052 PetscCall(VecDuplicate(user->
lAj, &aj0)); PetscCall(VecCopy(user->
lAj, aj0));
1055 PetscCall(VecEqual(user->
lUcat, ucat0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lUcat bit-identical"));
1057 PetscCall(VecEqual(user->
lNu_t, nut0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lNu_t bit-identical"));
1058 PetscCall(VecEqual(user->
lAj, aj0, &eq)); PetscCall(
PicurvAssertBool(eq,
"lAj bit-identical"));
1059 PetscCall(VecDestroy(&ucont0)); PetscCall(VecDestroy(&ucat0)); PetscCall(VecDestroy(&nvert0));
1060 PetscCall(VecDestroy(&nut0)); PetscCall(VecDestroy(&aj0));
1062 PetscFunctionReturn(0);
1071 const PetscInt mx = 9, my = 9, mz = 9;
1072 PetscFunctionBeginUser;
1074 PetscCall(DMDAVecGetArray(user->
da, user->
lNvert, &nvert));
1076 PetscCall(
PicurvAssertIntEqual(0x7,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,0),
"all rows active (periodic interior)"));
1077 PetscCall(
PicurvAssertIntEqual(0x6,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,1),
"TwoD=1 clears xi row"));
1078 PetscCall(
PicurvAssertIntEqual(0x5,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,2),
"TwoD=2 clears eta row"));
1079 PetscCall(
PicurvAssertIntEqual(0x3,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,3),
"TwoD=3 clears zeta row"));
1081 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"));
1084 PetscCall(DMDAVecRestoreArray(user->
da, user->
lNvert, &nvert));
1085 PetscCall(DMDAVecGetArray(user->
da, user->
lNvert, &nvert));
1086 PetscCall(
PicurvAssertIntEqual(0,
MomCellActiveRows(nvert,4,4,4,mx,my,mz,PETSC_FALSE,PETSC_FALSE,PETSC_FALSE,0),
"solid cell -> all rows inactive"));
1087 PetscCall(DMDAVecRestoreArray(user->
da, user->
lNvert, &nvert));
1089 PetscFunctionReturn(0);
1096 PetscErrorCode e_bad = 0; PetscBool eq;
1098 PetscFunctionBeginUser;
1101 PetscCall(VecDuplicate(user->
lAj, &aj_good)); PetscCall(VecCopy(user->
lAj, aj_good));
1104 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
1106 PetscCall(PetscPopErrorHandler());
1107 PetscCall(
PicurvAssertBool((PetscBool)(e_bad != 0),
"bad metric triggers error"));
1110 PetscCall(VecCopy(aj_good, user->
lAj));
1111 PetscCall(VecEqual(user->
lAj, aj_good, &eq));
1112 PetscCall(
PicurvAssertBool(eq,
"lAj usable after error (arrays were restored)"));
1117 PetscCall(VecDestroy(&aj_good));
1119 PetscFunctionReturn(0);
1127 Vec Rhs, ref; PetscReal dt, nrm;
1128 PetscFunctionBeginUser;
1131 PetscCall(VecSet(user->
Ucont, 2.0));
1132 PetscCall(VecSet(user->
Ucont_o, 1.0));
1133 PetscCall(VecSet(user->
Ucont_rm1, 0.5));
1134 PetscCall(VecDuplicate(user->
Ucont, &Rhs));
1135 PetscCall(VecDuplicate(user->
Ucont, &ref));
1142 PetscCall(VecSet(Rhs, 3.0));
1143 PetscCall(VecAXPY(Rhs, -a0/dt, user->
Ucont));
1144 PetscCall(VecAXPY(Rhs, +2.0/dt, user->
Ucont_o));
1145 PetscCall(VecAXPY(Rhs, -0.5/dt, user->
Ucont_rm1));
1147 PetscCall(VecSet(ref, -9.5));
1148 PetscCall(VecAXPY(ref, -1.0, Rhs)); PetscCall(VecNorm(ref, NORM_INFINITY, &nrm));
1156 PetscCall(VecSet(Rhs, 3.0));
1157 PetscCall(VecAXPY(Rhs, -a0/dt, user->
Ucont));
1158 PetscCall(VecAXPY(Rhs, +1.0/dt, user->
Ucont_o));
1160 PetscCall(VecSet(ref, -7.0));
1161 PetscCall(VecAXPY(ref, -1.0, Rhs)); PetscCall(VecNorm(ref, NORM_INFINITY, &nrm));
1164 PetscCall(VecDestroy(&Rhs)); PetscCall(VecDestroy(&ref));
1166 PetscFunctionReturn(0);
1175 PetscErrorCode ierr;
1209 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv solver utility tests");
1214 ierr =
PicurvRunTests(
"unit-solver", cases,
sizeof(cases) /
sizeof(cases[0]));
1220 ierr = PetscFinalize();
PetscErrorCode SetAnalyticalScalarFieldOnParticles(UserCtx *user, const char *swarm_field_name)
Writes the configured verification scalar profile onto a particle swarm scalar field.
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 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.
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]
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 / ν)