PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions
test_periodic_dev.c File Reference

Focused geometric-periodic boundary tests. More...

#include "test_support.h"
#include "Metric.h"
#include "Boundaries.h"
#include "walkingsearch.h"
#include "setup.h"
Include dependency graph for test_periodic_dev.c:

Go to the source code of this file.

Functions

static PetscErrorCode DestroyBoundaryHandler (BoundaryCondition **bc_ptr)
 Destroys one boundary-condition handler allocated by a periodic test.
 
static void MarkXPeriodic (UserCtx *user)
 Marks the x faces as periodic for periodic-transfer harnesses.
 
static void MarkYPeriodic (UserCtx *user)
 Marks the y faces as periodic for periodic-transfer harnesses.
 
static PetscErrorCode TestPeriodicConfigurationRequiresPairedFaces (void)
 Tests periodic configuration rejects an unpaired geometric periodic face.
 
static PetscErrorCode TestPeriodicGeometryStoresTranslation (void)
 Tests constant translational periodic geometry is accepted and stored.
 
static PetscErrorCode TestLocateParticleWrapsThroughPeriodicFace (void)
 Tests that a particle beyond either x-periodic face re-enters through the paired face, shifted by the seam translation.
 
static PetscErrorCode TestLocateParticleWrapsThroughOffAxisSeam (void)
 An off-axis seam: a rotated x-periodic grid validates the rotated translation and wraps by it.
 
static PetscErrorCode TestPeriodicGeometryStoresMixedTranslations (void)
 Tests mixed periodic directions are validated and stored independently.
 
static PetscErrorCode TestPeriodicGeometryRejectsVaryingTranslation (void)
 Tests non-translational seam geometry fails before metric construction.
 
static PetscErrorCode TestPeriodicFaceCenterCoordinateSynchronization (void)
 Tests face-center coordinates remain geometrically continuous across a periodic seam.
 
static PetscErrorCode TestPeriodicQuickStencilPreparation (void)
 Tests the dedicated QUICK outer-ghost repair for cell-centered inputs.
 
static PetscErrorCode TestPeriodicGeometricFactoryAssignment (void)
 Tests periodic geometric factory construction.
 
static PetscErrorCode TestApplyMetricsPeriodicBCsSynchronizesAj (void)
 Tests periodic metric transfer through the aggregate periodic-metrics helper.
 
static PetscErrorCode TestSynchronizePeriodicCellFieldsCopiesMixedAxes (void)
 Tests ordered cell-field synchronization across two periodic directions.
 
static PetscErrorCode TestSynchronizePeriodicFaceFieldsCopiesMixedAxes (void)
 Tests ordered persistent synchronization for an I-face scalar metric.
 
static PetscErrorCode TestSynchronizePeriodicStaggeredFieldsCopiesMixedAxes (void)
 Tests ordered persistent synchronization for component-staggered Ucont.
 
static PetscErrorCode TestFinalizePostProjectionCellFieldsMixedBoundaries (void)
 Tests mixed-boundary post-projection cell finalization and Ucont preservation.
 
static PetscErrorCode TestContra2CartPeriodicUcatFinalization (void)
 Verifies reconstructed Ucat periodic duplicates and local values are finalized.
 
int main (int argc, char **argv)
 Runs the focused geometric-periodic PETSc test binary.
 

Detailed Description

Focused geometric-periodic boundary tests.

Definition in file test_periodic_dev.c.

Function Documentation

◆ DestroyBoundaryHandler()

static PetscErrorCode DestroyBoundaryHandler ( BoundaryCondition **  bc_ptr)
static

Destroys one boundary-condition handler allocated by a periodic test.

Definition at line 16 of file test_periodic_dev.c.

17{
18 BoundaryCondition *bc = NULL;
19
20 PetscFunctionBeginUser;
21 if (!bc_ptr || !*bc_ptr) PetscFunctionReturn(0);
22
23 bc = *bc_ptr;
24 if (bc->Destroy) {
25 PetscCall(bc->Destroy(bc));
26 }
27 PetscCall(PetscFree(bc));
28 *bc_ptr = NULL;
29 PetscFunctionReturn(0);
30}
The "virtual table" struct for a boundary condition handler object.
Definition variables.h:403
PetscErrorCode(* Destroy)(BoundaryCondition *self)
Definition variables.h:412
Here is the caller graph for this function:

◆ MarkXPeriodic()

static void MarkXPeriodic ( UserCtx *  user)
static

Marks the x faces as periodic for periodic-transfer harnesses.

Definition at line 34 of file test_periodic_dev.c.

Here is the caller graph for this function:

◆ MarkYPeriodic()

static void MarkYPeriodic ( UserCtx *  user)
static

Marks the y faces as periodic for periodic-transfer harnesses.

Definition at line 46 of file test_periodic_dev.c.

Here is the caller graph for this function:

◆ TestPeriodicConfigurationRequiresPairedFaces()

static PetscErrorCode TestPeriodicConfigurationRequiresPairedFaces ( void  )
static

Tests periodic configuration rejects an unpaired geometric periodic face.

Definition at line 58 of file test_periodic_dev.c.

59{
60 SimCtx *simCtx = NULL;
61 UserCtx *user = NULL;
62 PetscErrorCode ierr_validate = 0;
63
64 PetscFunctionBeginUser;
65 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
68
69 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
70 ierr_validate = BoundarySystem_Validate(user);
71 PetscCall(PetscPopErrorHandler());
72
73 PetscCall(PicurvAssertBool((PetscBool)(ierr_validate != 0), "unpaired periodic faces should be rejected"));
74 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
75 PetscFunctionReturn(0);
76}
PetscErrorCode BoundarySystem_Validate(UserCtx *user)
(Public) Validates the consistency and compatibility of the parsed boundary condition system.
Definition Boundaries.c:817
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 PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
The master context for the entire simulation.
Definition variables.h:907
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1130
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicGeometryStoresTranslation()

static PetscErrorCode TestPeriodicGeometryStoresTranslation ( void  )
static

Tests constant translational periodic geometry is accepted and stored.

Definition at line 80 of file test_periodic_dev.c.

81{
82 SimCtx *simCtx = NULL;
83 UserCtx *user = NULL;
84 Vec gcoor = NULL;
85 const Cmpnts ***coor = NULL;
86 PetscReal expected_x = 0.0;
87
88 PetscFunctionBeginUser;
89 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
90 MarkXPeriodic(user);
91
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));
96
97 PetscCall(ValidatePeriodicGeometry(user));
98 PetscCall(PicurvAssertBool(user->periodic_translation_valid[0], "X-periodic translation should be marked valid"));
99 PetscCall(PicurvAssertBool((PetscBool)!user->periodic_translation_valid[1], "Y translation should remain invalid"));
100 PetscCall(PicurvAssertBool((PetscBool)!user->periodic_translation_valid[2], "Z translation should remain invalid"));
101 PetscCall(PicurvAssertRealNear(expected_x, user->periodic_translation[0].x, 1.0e-12, "stored X translation"));
102 PetscCall(PicurvAssertRealNear(0.0, user->periodic_translation[0].y, 1.0e-12, "stored X translation y component"));
103 PetscCall(PicurvAssertRealNear(0.0, user->periodic_translation[0].z, 1.0e-12, "stored X translation z component"));
104
105 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
106 PetscFunctionReturn(0);
107}
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
Definition grid.c:470
static void MarkXPeriodic(UserCtx *user)
Marks the x faces as periodic for periodic-transfer harnesses.
PetscErrorCode PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Asserts that two real values agree within tolerance.
PetscScalar x
Definition variables.h:122
PetscScalar z
Definition variables.h:122
DMDALocalInfo info
Definition variables.h:1142
PetscScalar y
Definition variables.h:122
Cmpnts periodic_translation[3]
Definition variables.h:1151
PetscBool periodic_translation_valid[3]
Definition variables.h:1152
A 3D point or vector with PetscScalar components.
Definition variables.h:121
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestLocateParticleWrapsThroughPeriodicFace()

static PetscErrorCode TestLocateParticleWrapsThroughPeriodicFace ( void  )
static

Tests that a particle beyond either x-periodic face re-enters through the paired face, shifted by the seam translation.

Definition at line 111 of file test_periodic_dev.c.

112{
113 SimCtx *simCtx = NULL;
114 UserCtx *user = NULL;
115 Particle particle;
117 Vec gcoor = NULL;
118 const Cmpnts ***coor = NULL;
119 PetscReal x0, y0, T, Ty, yc, zc;
120
121 PetscFunctionBeginUser;
122 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE));
123 MarkXPeriodic(user);
124 MarkYPeriodic(user);
125 PetscCall(ValidatePeriodicGeometry(user));
130 PetscCall(SetupDomainCellDecompositionMap(user));
132
133 /* Seam origin, translation, and the centre of the (., 1, 1) cell row in y and z. */
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));
141 T = user->periodic_translation[0].x;
142 Ty = user->periodic_translation[1].y;
143
144 /* Beyond -Xi out of cell 0: re-enters at the +Xi end. */
145 PetscCall(PetscMemzero(&particle, sizeof(particle)));
146 particle.PID = 51;
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;
149 PetscCall(LocateParticleOrFindMigrationTarget(user, &particle, &status));
150 PetscCall(PicurvAssertIntEqual(ACTIVE_AND_LOCATED, status, "a wrapped particle should be located"));
151 PetscCall(PicurvAssertRealNear(x0 + 0.99 * T, particle.loc.x, 1.0e-12, "x shifts forward by the seam translation"));
152 PetscCall(PicurvAssertIntEqual(user->IM - 2, particle.cell[0], "the particle lands in the last cell"));
153
154 /* Beyond +Xi out of the last cell: re-enters at the -Xi end. */
155 PetscCall(PetscMemzero(&particle, sizeof(particle)));
156 particle.PID = 52;
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;
159 PetscCall(LocateParticleOrFindMigrationTarget(user, &particle, &status));
160 PetscCall(PicurvAssertIntEqual(ACTIVE_AND_LOCATED, status, "a wrapped particle should be located"));
161 PetscCall(PicurvAssertRealNear(x0 + 0.01 * T, particle.loc.x, 1.0e-12, "x shifts back by the seam translation"));
162 PetscCall(PicurvAssertIntEqual(0, particle.cell[0], "the particle lands in the first cell"));
163
164 /* Beyond -Xi and -Eta out of the corner cell: both seams are crossed in one wrap step. */
165 PetscCall(PetscMemzero(&particle, sizeof(particle)));
166 particle.PID = 53;
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;
169 PetscCall(LocateParticleOrFindMigrationTarget(user, &particle, &status));
170 PetscCall(PicurvAssertIntEqual(ACTIVE_AND_LOCATED, status, "a corner-wrapped particle should be located"));
171 PetscCall(PicurvAssertRealNear(x0 + 0.99 * T, particle.loc.x, 1.0e-12, "x shifts forward at the corner"));
172 PetscCall(PicurvAssertRealNear(y0 + 0.99 * Ty, particle.loc.y, 1.0e-12, "y shifts forward at the corner"));
173 PetscCall(PicurvAssertIntEqual(user->IM - 2, particle.cell[0], "the corner particle lands in the last i cell"));
174 PetscCall(PicurvAssertIntEqual(user->JM - 2, particle.cell[1], "the corner particle lands in the last j cell"));
175 PetscCall(PicurvAssertIntEqual(4, (PetscInt)simCtx->searchMetrics.wrapCount, "one wrap per crossed periodic face"));
176
177 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
178 PetscFunctionReturn(0);
179}
PetscErrorCode SetupDomainCellDecompositionMap(UserCtx *user)
Creates and distributes a map of the domain's cell decomposition to all ranks.
Definition setup.c:3654
static void MarkYPeriodic(UserCtx *user)
Marks the y faces as periodic for periodic-transfer harnesses.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
PetscInt cell[3]
Definition variables.h:224
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Definition variables.h:163
@ NEEDS_LOCATION
Definition variables.h:164
@ ACTIVE_AND_LOCATED
Definition variables.h:165
PetscInt64 wrapCount
Definition variables.h:296
@ PARTICLE_BOUNDARY_WRAP
Periodic faces: the particle re-enters through the paired face.
Definition variables.h:351
PetscInt currentSettlementPass
Definition variables.h:297
Cmpnts loc
Definition variables.h:225
ParticleBoundaryPolicy particle_policy
What a particle crossing this face becomes (BC param particle_policy).
Definition variables.h:420
PetscInt JM
Definition variables.h:1144
SearchMetricsState searchMetrics
Definition variables.h:1058
PetscInt IM
Definition variables.h:1144
PetscInt64 PID
Definition variables.h:223
Defines a particle's core properties for Lagrangian tracking.
Definition variables.h:222
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestLocateParticleWrapsThroughOffAxisSeam()

static PetscErrorCode TestLocateParticleWrapsThroughOffAxisSeam ( void  )
static

An off-axis seam: a rotated x-periodic grid validates the rotated translation and wraps by it.

Rotates the grid 30 degrees about z, so the x seam translation gains a y component, then checks that the validated translation is the rotated one and that a particle beyond -Xi re-enters at the +Xi end shifted by it.

Definition at line 187 of file test_periodic_dev.c.

188{
189 SimCtx *simCtx = NULL;
190 UserCtx *user = NULL;
191 Particle particle;
193 Vec gcoor = NULL;
194 Cmpnts ***coor = NULL;
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;
198 Cmpnts p0;
199
200 PetscFunctionBeginUser;
201 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
202 MarkXPeriodic(user);
203 PetscCall(ValidatePeriodicGeometry(user));
204 T0 = user->periodic_translation[0].x;
205
206 /* Seam origin and the centre of the (., 1, 1) row, before rotation. */
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));
213
214 /* Rotate every node about the z axis through the origin. */
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;
223 }
224 PetscCall(DMDAVecRestoreArray(user->fda, gcoor, &coor));
225 PetscCall(UpdateLocalGhosts(user, FIELD_ID_COORDINATES)); /* As the grid builders refresh them */
226 PetscCall(MetricDestroyFacePlanes(user)); /* The grid moved: its search planes are rebuilt */
227 PetscCall(MetricComputeFacePlanes(user));
228 PetscCall(ValidatePeriodicGeometry(user));
229 PetscCall(PicurvAssertRealNear(c * T0, user->periodic_translation[0].x, 1.0e-12, "translation x is rotated"));
230 PetscCall(PicurvAssertRealNear(s * T0, user->periodic_translation[0].y, 1.0e-12, "translation gains a y component"));
231
234 PetscCall(SetupDomainCellDecompositionMap(user));
236
237 /* Beyond -Xi out of cell 0: re-enters at the +Xi end, shifted along the rotated translation. */
238 PetscCall(PetscMemzero(&particle, sizeof(particle)));
239 particle.PID = 54;
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;
243 PetscCall(LocateParticleOrFindMigrationTarget(user, &particle, &status));
244 PetscCall(PicurvAssertIntEqual(ACTIVE_AND_LOCATED, status, "a particle wrapped through an off-axis seam should be located"));
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"));
247 PetscCall(PicurvAssertIntEqual(user->IM - 2, particle.cell[0], "the particle lands in the last cell"));
248
249 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
250 PetscFunctionReturn(0);
251}
PetscErrorCode MetricDestroyFacePlanes(UserCtx *user)
Frees the face-plane fields MetricComputeFacePlanes() built, if any.
Definition Metric.c:301
PetscErrorCode MetricComputeFacePlanes(UserCtx *user)
Builds the block's particle face planes once, as catalogued per-face fields.
Definition Metric.c:136
@ FIELD_ID_COORDINATES
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Definition setup.c:2675
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicGeometryStoresMixedTranslations()

static PetscErrorCode TestPeriodicGeometryStoresMixedTranslations ( void  )
static

Tests mixed periodic directions are validated and stored independently.

Definition at line 255 of file test_periodic_dev.c.

256{
257 SimCtx *simCtx = NULL;
258 UserCtx *user = NULL;
259
260 PetscFunctionBeginUser;
261 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 6, 4, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE));
262 MarkXPeriodic(user);
263 MarkYPeriodic(user);
264
265 PetscCall(ValidatePeriodicGeometry(user));
266 PetscCall(PicurvAssertBool(user->periodic_translation_valid[0], "mixed-periodic X translation should be valid"));
267 PetscCall(PicurvAssertBool(user->periodic_translation_valid[1], "mixed-periodic Y translation should be valid"));
268 PetscCall(PicurvAssertBool((PetscBool)!user->periodic_translation_valid[2], "mixed-periodic Z translation should remain invalid"));
269 PetscCall(PicurvAssertBool((PetscBool)(PetscAbsReal(user->periodic_translation[0].x) > 0.0),
270 "mixed-periodic X translation should have nonzero x component"));
271 PetscCall(PicurvAssertBool((PetscBool)(PetscAbsReal(user->periodic_translation[1].y) > 0.0),
272 "mixed-periodic Y translation should have nonzero y component"));
273
274 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
275 PetscFunctionReturn(0);
276}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicGeometryRejectsVaryingTranslation()

static PetscErrorCode TestPeriodicGeometryRejectsVaryingTranslation ( void  )
static

Tests non-translational seam geometry fails before metric construction.

Definition at line 280 of file test_periodic_dev.c.

281{
282 SimCtx *simCtx = NULL;
283 UserCtx *user = NULL;
284 Vec gcoor = NULL;
285 Cmpnts ***coor = NULL;
286 PetscErrorCode ierr_validate = 0;
287
288 PetscFunctionBeginUser;
289 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
290 MarkXPeriodic(user);
291
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));
296 PetscCall(UpdateLocalGhosts(user, FIELD_ID_COORDINATES));
297
298 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
299 ierr_validate = ValidatePeriodicGeometry(user);
300 PetscCall(PetscPopErrorHandler());
301
302 PetscCall(PicurvAssertBool((PetscBool)(ierr_validate != 0), "varying seam translation should be rejected"));
303 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
304 PetscFunctionReturn(0);
305}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicFaceCenterCoordinateSynchronization()

static PetscErrorCode TestPeriodicFaceCenterCoordinateSynchronization ( void  )
static

Tests face-center coordinates remain geometrically continuous across a periodic seam.

Definition at line 310 of file test_periodic_dev.c.

311{
312 SimCtx *simCtx = NULL;
313 UserCtx *user = NULL;
314 Cmpnts ***centx = NULL;
315 const Cmpnts ***lcentx = NULL;
316 const FieldId fields[] = {FIELD_ID_CENTX};
317 PetscReal translation, spacing;
318
319 PetscFunctionBeginUser;
320 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 6, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
321 MarkXPeriodic(user);
322 PetscCall(ValidatePeriodicGeometry(user));
323 translation = user->periodic_translation[0].x;
324 spacing = translation / (PetscReal)(user->info.mx - 2);
325
326 PetscCall(DMDAVecGetArray(user->fda, user->Centx, &centx));
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};
331 }
332 }
333 }
334 PetscCall(DMDAVecRestoreArray(user->fda, user->Centx, &centx));
335
336 PetscCall(SynchronizePeriodicFaceFields(user, 'i', 1, fields));
337 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCentx, &lcentx));
338 PetscCall(PicurvAssertRealNear(-spacing, lcentx[2][2][-1].x, 1.0e-12,
339 "translated Centx negative adjacent ghost"));
340 PetscCall(PicurvAssertRealNear(0.0, lcentx[2][2][0].x, 1.0e-12,
341 "translated Centx negative endpoint"));
342 PetscCall(PicurvAssertRealNear(translation + spacing, lcentx[2][2][user->info.mx - 1].x, 1.0e-12,
343 "translated Centx positive endpoint"));
344 PetscCall(PicurvAssertRealNear(translation + 2.0 * spacing, lcentx[2][2][user->info.mx].x, 1.0e-12,
345 "translated Centx positive adjacent ghost"));
346 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCentx, &lcentx));
347
348 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
349 PetscFunctionReturn(0);
350}
PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent fields belonging to one face family.
FieldId
Compile-time identity for a catalogued Eulerian field.
@ FIELD_ID_CENTX
Vec Centx
Definition variables.h:1224
Vec lCentx
Definition variables.h:1225
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicQuickStencilPreparation()

static PetscErrorCode TestPeriodicQuickStencilPreparation ( void  )
static

Tests the dedicated QUICK outer-ghost repair for cell-centered inputs.

Definition at line 355 of file test_periodic_dev.c.

356{
357 SimCtx *simCtx = NULL;
358 UserCtx *user = NULL;
359 Cmpnts ***ucat = NULL;
360 PetscReal ***nvert = NULL;
361
362 PetscFunctionBeginUser;
363 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 6, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
364 MarkXPeriodic(user);
365
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;
373 }
374 }
375 }
376 PetscCall(DMDAVecRestoreArray(user->da, user->Nvert, &nvert));
377 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucat, &ucat));
378 PetscCall(UpdateLocalGhosts(user, FIELD_ID_UCAT));
379 PetscCall(UpdateLocalGhosts(user, FIELD_ID_NVERT));
380 PetscCall(PreparePeriodicQuickStencilFields(user, user->lUcat, user->lNvert));
381
382 PetscCall(DMDAVecGetArrayRead(user->fda, user->lUcat, &ucat));
383 PetscCall(DMDAVecGetArrayRead(user->da, user->lNvert, &nvert));
384 PetscCall(PicurvAssertRealNear(100.0 + user->info.mx - 3, ucat[2][2][-1].x, 1.0e-12,
385 "QUICK Ucat negative outer ghost"));
386 PetscCall(PicurvAssertRealNear(102.0, ucat[2][2][user->info.mx].x, 1.0e-12,
387 "QUICK Ucat positive outer ghost"));
388 PetscCall(PicurvAssertRealNear(400.0 + user->info.mx - 3, nvert[2][2][-1], 1.0e-12,
389 "QUICK Nvert negative outer ghost"));
390 PetscCall(PicurvAssertRealNear(402.0, nvert[2][2][user->info.mx], 1.0e-12,
391 "QUICK Nvert positive outer ghost"));
392 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lNvert, &nvert));
393 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lUcat, &ucat));
394
395 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
396 PetscFunctionReturn(0);
397}
PetscErrorCode PreparePeriodicQuickStencilFields(UserCtx *user, Vec local_vector_field, Vec local_scalar_field)
Repairs the outer adjacent periodic ghosts used by QUICK cell stencils.
@ FIELD_ID_NVERT
@ FIELD_ID_UCAT
Vec lNvert
Definition variables.h:1169
Vec lUcat
Definition variables.h:1169
Vec Nvert
Definition variables.h:1169
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestPeriodicGeometricFactoryAssignment()

static PetscErrorCode TestPeriodicGeometricFactoryAssignment ( void  )
static

Tests periodic geometric factory construction.

Definition at line 401 of file test_periodic_dev.c.

402{
403 BoundaryCondition *bc = NULL;
404
405 PetscFunctionBeginUser;
407 PetscCall(PicurvAssertBool((PetscBool)(bc != NULL), "periodic geometric factory should allocate a handler"));
408 PetscCall(PicurvAssertIntEqual(BC_PRIORITY_WALL, bc->priority, "periodic geometric handler priority"));
409 PetscCall(PicurvAssertBool((PetscBool)(bc->Apply == NULL), "periodic geometric handler should not expose Apply"));
410 PetscCall(PicurvAssertBool((PetscBool)(bc->Initialize == NULL), "periodic geometric handler should not expose Initialize"));
411 PetscCall(DestroyBoundaryHandler(&bc));
412 PetscFunctionReturn(0);
413}
PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr)
(Private) Creates and configures a specific BoundaryCondition handler object.
Definition Boundaries.c:726
PetscErrorCode(* Initialize)(BoundaryCondition *self, BCContext *ctx)
Definition variables.h:407
PetscErrorCode(* Apply)(BoundaryCondition *self, BCContext *ctx)
Definition variables.h:409
BCPriorityType priority
Definition variables.h:405
static PetscErrorCode DestroyBoundaryHandler(BoundaryCondition **bc_ptr)
Destroys one boundary-condition handler allocated by a periodic test.
@ BC_PRIORITY_WALL
Definition variables.h:377
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestApplyMetricsPeriodicBCsSynchronizesAj()

static PetscErrorCode TestApplyMetricsPeriodicBCsSynchronizesAj ( void  )
static

Tests periodic metric transfer through the aggregate periodic-metrics helper.

Definition at line 417 of file test_periodic_dev.c.

418{
419 SimCtx *simCtx = NULL;
420 UserCtx *user = NULL;
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;
426
427 PetscFunctionBeginUser;
428 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
429 MarkXPeriodic(user);
430 PetscCall(ValidatePeriodicGeometry(user));
431
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;
437 }
438 }
439 }
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));
449
450 PetscCall(ApplyMetricsPeriodicBCs(user));
451
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));
458
459 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
460 PetscFunctionReturn(0);
461}
PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user)
(Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundar...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestSynchronizePeriodicCellFieldsCopiesMixedAxes()

static PetscErrorCode TestSynchronizePeriodicCellFieldsCopiesMixedAxes ( void  )
static

Tests ordered cell-field synchronization across two periodic directions.

Definition at line 465 of file test_periodic_dev.c.

466{
467 SimCtx *simCtx = NULL;
468 UserCtx *user = NULL;
469 PetscReal ***p = NULL;
470 PetscReal ***cs = NULL;
471 PetscReal ***diffusivity = NULL;
472 Cmpnts ***ucat = NULL;
473 PetscInt mx, my;
475
476 PetscFunctionBeginUser;
477 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE));
478 MarkXPeriodic(user);
479 MarkYPeriodic(user);
480
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));
489
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);
498 p[k][j][i] = value;
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;
504 }
505 }
506 }
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));
511
512 PetscCall(SynchronizePeriodicCellFields(user, 7, fields));
513
514 mx = user->info.mx;
515 my = user->info.my;
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));
520 PetscCall(PicurvAssertRealNear((PetscReal)((mx - 2) + 20 + 200), p[2][2][0], 1.0e-12,
521 "x-periodic negative endpoint should copy the opposite interior value"));
522 PetscCall(PicurvAssertRealNear((PetscReal)(1 + 20 + 200), p[2][2][mx - 1], 1.0e-12,
523 "x-periodic positive endpoint should copy the leading interior value"));
524 PetscCall(PicurvAssertRealNear((PetscReal)(2 + 10 * (my - 2) + 200), p[2][0][2], 1.0e-12,
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));
538 PetscCall(PicurvAssertVecConstant(user->Nu_t, 5.0, 1.0e-12, "Nu_t should be accepted by periodic cell synchronization"));
539
540 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
541 PetscFunctionReturn(0);
542}
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
@ FIELD_ID_NU_T
@ FIELD_ID_PHI
@ FIELD_ID_CS
@ FIELD_ID_P
@ FIELD_ID_DIFFUSIVITY
PetscErrorCode PicurvAssertVecConstant(Vec vec, PetscScalar expected, PetscReal tol, const char *context)
Asserts that a PETSc vector is spatially constant within tolerance.
Vec lNu_t
Definition variables.h:1231
Vec Diffusivity
Definition variables.h:1172
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestSynchronizePeriodicFaceFieldsCopiesMixedAxes()

static PetscErrorCode TestSynchronizePeriodicFaceFieldsCopiesMixedAxes ( void  )
static

Tests ordered persistent synchronization for an I-face scalar metric.

Definition at line 547 of file test_periodic_dev.c.

548{
549 SimCtx *simCtx = NULL;
550 UserCtx *user = NULL;
551 PetscReal ***iaj = NULL;
552 Cmpnts ***csi = NULL;
553 const FieldId fields[] = {FIELD_ID_CSI, FIELD_ID_IAJ};
554 PetscInt mx, my;
555
556 PetscFunctionBeginUser;
557 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE));
558 MarkXPeriodic(user);
559 MarkYPeriodic(user);
560 mx = user->info.mx;
561 my = user->info.my;
562
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};
571 }
572 }
573 }
574 PetscCall(DMDAVecRestoreArray(user->da, user->IAj, &iaj));
575 PetscCall(DMDAVecRestoreArray(user->fda, user->Csi, &csi));
576
577 PetscCall(SynchronizePeriodicFaceFields(user, 'i', 2, fields));
578
579 PetscCall(DMDAVecGetArrayRead(user->da, user->IAj, &iaj));
580 PetscCall(DMDAVecGetArrayRead(user->fda, user->Csi, &csi));
581 PetscCall(PicurvAssertRealNear((PetscReal)(mx - 2 + 20 + 200), iaj[2][2][0], 1.0e-12,
582 "I-face negative seam should copy the opposite physical seam face"));
583 PetscCall(PicurvAssertRealNear((PetscReal)(1 + 20 + 200), iaj[2][2][mx - 1], 1.0e-12,
584 "I-face positive dummy should copy the leading physical face"));
585 PetscCall(PicurvAssertRealNear((PetscReal)(2 + 10 * (my - 2) + 200), iaj[2][0][2], 1.0e-12,
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));
593
594 PetscCall(DMDAVecGetArrayRead(user->da, user->lIAj, &iaj));
595 PetscCall(PicurvAssertRealNear((PetscReal)(mx - 3 + 20 + 200), iaj[2][2][-1], 1.0e-12,
596 "I-face negative adjacent ghost should be shifted to the prior face"));
597 PetscCall(PicurvAssertRealNear((PetscReal)(2 + 20 + 200), iaj[2][2][mx], 1.0e-12,
598 "I-face positive adjacent ghost should be shifted to the next face"));
599 PetscCall(PicurvAssertRealNear((PetscReal)(2 + 10 + 200), iaj[2][-1][2], 1.0e-12,
600 "I-face tangential ghosts should retain cell-style wraparound"));
601 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lIAj, &iaj));
602
603 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
604 PetscFunctionReturn(0);
605}
@ FIELD_ID_CSI
@ FIELD_ID_IAJ
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestSynchronizePeriodicStaggeredFieldsCopiesMixedAxes()

static PetscErrorCode TestSynchronizePeriodicStaggeredFieldsCopiesMixedAxes ( void  )
static

Tests ordered persistent synchronization for component-staggered Ucont.

Definition at line 610 of file test_periodic_dev.c.

611{
612 SimCtx *simCtx = NULL;
613 UserCtx *user = NULL;
614 Cmpnts ***ucont = NULL;
615 const FieldId fields[] = {FIELD_ID_UCONT};
616 PetscInt mx, my;
617
618 PetscFunctionBeginUser;
619 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE));
620 MarkXPeriodic(user);
621 MarkYPeriodic(user);
622 mx = user->info.mx;
623 my = user->info.my;
624
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};
631 }
632 }
633 }
634 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucont, &ucont));
635
636 PetscCall(SynchronizePeriodicStaggeredFields(user, 1, fields));
637
638 PetscCall(DMDAVecGetArrayRead(user->fda, user->Ucont, &ucont));
639 PetscCall(PicurvAssertRealNear((PetscReal)(mx - 2 + 20 + 1200), ucont[2][2][0].x, 1.0e-12,
640 "Ucont.x negative X seam should copy the opposite physical seam"));
641 PetscCall(PicurvAssertRealNear((PetscReal)(1 + 20 + 2200), ucont[2][2][mx - 1].y, 1.0e-12,
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));
648
649 PetscCall(DMDAVecGetArrayRead(user->fda, user->lUcont, &ucont));
650 PetscCall(PicurvAssertRealNear((PetscReal)(mx - 3 + 20 + 1200), ucont[2][2][-1].x, 1.0e-12,
651 "Ucont.x should use face-normal X ghost repair"));
652 PetscCall(PicurvAssertRealNear((PetscReal)(1 + 20 + 2200), ucont[2][2][-1].y, 1.0e-12,
653 "Ucont.y should retain cell-style wraparound tangentially in X"));
654 PetscCall(PicurvAssertRealNear((PetscReal)(2 + 20 + 1200), ucont[2][2][mx].x, 1.0e-12,
655 "Ucont.x positive adjacent ghost should use the next face"));
656 PetscCall(PicurvAssertRealNear((PetscReal)(mx - 2 + 20 + 2200), ucont[2][2][mx].y, 1.0e-12,
657 "Ucont.y positive X ghost should retain cell-style wraparound"));
658 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lUcont, &ucont));
659
660 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
661 PetscFunctionReturn(0);
662}
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
@ FIELD_ID_UCONT
Vec Ucont
Definition variables.h:1169
Vec lUcont
Definition variables.h:1169
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestFinalizePostProjectionCellFieldsMixedBoundaries()

static PetscErrorCode TestFinalizePostProjectionCellFieldsMixedBoundaries ( void  )
static

Tests mixed-boundary post-projection cell finalization and Ucont preservation.

Definition at line 667 of file test_periodic_dev.c.

668{
669 SimCtx *simCtx = NULL;
670 UserCtx *user = NULL;
671 Vec ucont_before = NULL;
672 Vec ucont_difference = NULL;
673 Cmpnts ***ucat = NULL;
674 Cmpnts ***ucont = NULL;
675 PetscReal ***p = NULL;
676 PetscReal difference_norm = 0.0;
677 PetscInt mx;
678
679 PetscFunctionBeginUser;
680 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx, &user, 4, 4, 4, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE));
681 MarkXPeriodic(user);
682 PetscCall(VecSet(user->Bcs.Ubcs, 0.0));
683
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;
697 p[k][j][i] = value;
698 }
699 }
700 }
701 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucat, &ucat));
702 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucont, &ucont));
703 PetscCall(DMDAVecRestoreArray(user->da, user->P, &p));
704
705 PetscCall(VecDuplicate(user->Ucont, &ucont_before));
706 PetscCall(VecDuplicate(user->Ucont, &ucont_difference));
707 PetscCall(VecCopy(user->Ucont, ucont_before));
708
709 PetscCall(FinalizePostProjectionCellFields(user));
710
711 PetscCall(VecWAXPY(ucont_difference, -1.0, user->Ucont, ucont_before));
712 PetscCall(VecNorm(ucont_difference, NORM_INFINITY, &difference_norm));
713 PetscCall(PicurvAssertRealNear(0.0, difference_norm, 1.0e-12,
714 "post-projection cell finalization must preserve mixed-boundary Ucont"));
715
716 mx = user->info.mx;
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"));
721 PetscCall(PicurvAssertRealNear((PetscReal)(-(2 + 10 + 200 + 1000)), ucat[2][0][2].x, 1.0e-12,
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"));
725 PetscCall(PicurvAssertRealNear((PetscReal)((mx - 2) + 20 + 200), p[2][2][0], 1.0e-12,
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));
729
730 PetscCall(VecDestroy(&ucont_difference));
731 PetscCall(VecDestroy(&ucont_before));
732 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
733 PetscFunctionReturn(0);
734}
PetscErrorCode FinalizePostProjectionCellFields(UserCtx *user)
Finalizes cell-centered fields after the projection step.
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
Definition variables.h:149
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestContra2CartPeriodicUcatFinalization()

static PetscErrorCode TestContra2CartPeriodicUcatFinalization ( void  )
static

Verifies reconstructed Ucat periodic duplicates and local values are finalized.

Definition at line 737 of file test_periodic_dev.c.

738{
739 SimCtx *simCtx=NULL; UserCtx *user=NULL; Cmpnts ***ucont=NULL,***ucat=NULL,***lucat=NULL;
740 const FieldId staggered_fields[] = {FIELD_ID_UCONT}, cell_fields[] = {FIELD_ID_UCAT};
741 PetscInt mx;
742 PetscFunctionBeginUser;
743 PetscCall(PicurvCreateMinimalContextsWithPeriodicity(&simCtx,&user,4,4,4,PETSC_TRUE,PETSC_FALSE,PETSC_FALSE));
744 MarkXPeriodic(user); mx=user->info.mx;
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));
750 PetscCall(SynchronizePeriodicStaggeredFields(user,1,staggered_fields));
751 PetscCall(VecSet(user->Ucat,-99.0));
752 PetscCall(Contra2Cart(user));
753 PetscCall(SynchronizePeriodicCellFields(user,1,cell_fields));
754 PetscCall(UpdateLocalGhosts(user, FIELD_ID_UCAT));
755
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));
764 PetscCall(PicurvDestroyMinimalContexts(&simCtx,&user));
765 PetscFunctionReturn(0);
766}
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
Definition setup.c:3459
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Runs the focused geometric-periodic PETSc test binary.

Definition at line 770 of file test_periodic_dev.c.

771{
772 PetscErrorCode ierr;
773 const PicurvTestCase cases[] = {
774 {"periodic-geometric-factory-assignment", TestPeriodicGeometricFactoryAssignment},
775 {"periodic-configuration-requires-paired-faces", TestPeriodicConfigurationRequiresPairedFaces},
776 {"periodic-geometry-stores-translation", TestPeriodicGeometryStoresTranslation},
777 {"periodic-geometry-stores-mixed-translations", TestPeriodicGeometryStoresMixedTranslations},
778 {"locate-particle-wraps-through-periodic-face", TestLocateParticleWrapsThroughPeriodicFace},
779 {"locate-particle-wraps-through-off-axis-seam", TestLocateParticleWrapsThroughOffAxisSeam},
780 {"periodic-geometry-rejects-varying-translation", TestPeriodicGeometryRejectsVaryingTranslation},
781 {"periodic-face-center-coordinate-synchronization", TestPeriodicFaceCenterCoordinateSynchronization},
782 {"periodic-quick-stencil-preparation", TestPeriodicQuickStencilPreparation},
783 {"apply-metrics-periodic-bcs-synchronizes-aj", TestApplyMetricsPeriodicBCsSynchronizesAj},
784 {"synchronize-periodic-cell-fields-copies-mixed-axes", TestSynchronizePeriodicCellFieldsCopiesMixedAxes},
785 {"synchronize-periodic-face-fields-copies-mixed-axes", TestSynchronizePeriodicFaceFieldsCopiesMixedAxes},
786 {"synchronize-periodic-staggered-fields-copies-mixed-axes", TestSynchronizePeriodicStaggeredFieldsCopiesMixedAxes},
787 {"finalize-post-projection-cell-fields-mixed-boundaries", TestFinalizePostProjectionCellFieldsMixedBoundaries},
788 {"contra2cart-periodic-ucat-finalization", TestContra2CartPeriodicUcatFinalization},
789 };
790
791 ierr = PetscInitialize(&argc, &argv, NULL, "PICurv geometric-periodic tests");
792 if (ierr) {
793 return (int)ierr;
794 }
795
796 ierr = PicurvRunTests("unit-periodic", cases, sizeof(cases) / sizeof(cases[0]));
797 if (ierr) {
798 PetscFinalize();
799 return (int)ierr;
800 }
801
802 ierr = PetscFinalize();
803 return (int)ierr;
804}
static PetscErrorCode TestContra2CartPeriodicUcatFinalization(void)
Verifies reconstructed Ucat periodic duplicates and local values are finalized.
static PetscErrorCode TestPeriodicGeometricFactoryAssignment(void)
Tests periodic geometric factory construction.
static PetscErrorCode TestPeriodicFaceCenterCoordinateSynchronization(void)
Tests face-center coordinates remain geometrically continuous across a periodic seam.
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 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 PetscErrorCode TestLocateParticleWrapsThroughOffAxisSeam(void)
An off-axis seam: a rotated x-periodic grid validates the rotated translation and wraps by it.
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.
Named test case descriptor consumed by PicurvRunTests.
Here is the call graph for this function: