38 return offset + (PetscReal)(i + 10 * j + 100 * k);
46 PetscMPIInt rank = 0, size = 1;
47 PetscInt local_particles = 0;
48 PetscInt remainder = 0;
49 PetscInt global_particles = 0;
50 PetscInt remainder_min = 0, remainder_max = 0;
51 const PetscInt total_particles = 137;
53 PetscFunctionBeginUser;
54 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
55 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
56 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
61 total_particles / size + (((PetscInt)rank < remainder) ? 1 : 0),
63 "local particle share should match quotient+remainder policy"));
65 PetscCallMPI(MPI_Allreduce(&local_particles, &global_particles, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
66 PetscCall(
PicurvAssertIntEqual(total_particles, global_particles,
"distributed particle count must conserve total particles"));
68 PetscCallMPI(MPI_Allreduce(&remainder, &remainder_min, 1, MPIU_INT, MPI_MIN, PETSC_COMM_WORLD));
69 PetscCallMPI(MPI_Allreduce(&remainder, &remainder_max, 1, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD));
70 PetscCall(
PicurvAssertIntEqual(remainder_min, remainder_max,
"all ranks should report the same remainder"));
71 PetscFunctionReturn(0);
83 PetscMPIInt rank = 0, size = 1;
84 PetscReal global_min_x = 0.0;
85 PetscReal global_max_x = 0.0;
86 PetscReal expected_global_max_x = 0.0;
88 PetscFunctionBeginUser;
89 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
90 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
91 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
94 expected_global_max_x = ((PetscReal)(user->
IM - 1) / (PetscReal)user->
IM) + 1.0e-6;
98 PetscCall(
PicurvAssertBool((PetscBool)(boxes != NULL),
"all ranks should hold the gathered bounding-box table"));
100 for (PetscMPIInt r = 0; r < size; ++r) {
109 PetscCallMPI(MPI_Allreduce(&local_bbox.
min_coords.
x, &global_min_x, 1, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD));
110 PetscCallMPI(MPI_Allreduce(&local_bbox.
max_coords.
x, &global_max_x, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD));
111 PetscCall(
PicurvAssertBool((PetscBool)(global_min_x <= 0.0),
"global min x should include domain start"));
112 PetscCall(
PicurvAssertRealNear(expected_global_max_x, global_max_x, 1.0e-10,
"global max x should match the normalized physical-node domain end"));
116 PetscFunctionReturn(0);
126 PetscReal ***p = NULL;
127 PetscReal ***cs = NULL;
128 PetscReal ***diffusivity = NULL;
131 PetscInt xs, xe, ys, ye, zs, ze, mx;
133 PetscFunctionBeginUser;
137 "periodic cell synchronization test requires the x axis to be partitioned"));
138 PetscCall(DMCreateGlobalVector(user->
da, &user->
CS));
139 PetscCall(DMCreateLocalVector(user->
da, &user->
lCs));
142 xe = xs + user->
info.xm;
144 ye = ys + user->
info.ym;
146 ze = zs + user->
info.zm;
149 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
150 PetscCall(DMDAVecGetArray(user->
da, user->
CS, &cs));
151 PetscCall(DMDAVecGetArray(user->
da, user->
Diffusivity, &diffusivity));
152 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
153 for (PetscInt k = zs; k < ze; ++k) {
154 for (PetscInt j = ys; j < ye; ++j) {
155 for (PetscInt i = xs; i < xe; ++i) {
163 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
164 PetscCall(DMDAVecRestoreArray(user->
da, user->
CS, &cs));
165 PetscCall(DMDAVecRestoreArray(user->
da, user->
Diffusivity, &diffusivity));
166 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
170 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
171 PetscCall(DMDAVecGetArrayRead(user->
da, user->
CS, &cs));
172 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Diffusivity, &diffusivity));
173 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
175 for (PetscInt k = zs; k < ze; ++k) {
176 for (PetscInt j = ys; j < ye; ++j) {
178 "distributed P negative endpoint should copy the opposite interior"));
180 "distributed CS negative endpoint should copy the opposite interior"));
182 "distributed Diffusivity negative endpoint should copy the opposite interior"));
184 "distributed Ucat negative endpoint should copy the opposite interior"));
189 for (PetscInt k = zs; k < ze; ++k) {
190 for (PetscInt j = ys; j < ye; ++j) {
192 "distributed P positive endpoint should copy the opposite interior"));
194 "distributed CS positive endpoint should copy the opposite interior"));
196 "distributed Diffusivity positive endpoint should copy the opposite interior"));
198 "distributed Ucat positive endpoint should copy the leading interior"));
202 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
203 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
CS, &cs));
204 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Diffusivity, &diffusivity));
205 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
206 PetscCall(DMDAVecGetArrayRead(user->
fda,user->
lUcat,&ucat));
208 "distributed local Ucat negative ghost follows corrected global endpoint"));
210 "distributed local Ucat positive ghost follows corrected global endpoint"));
211 PetscCall(DMDAVecRestoreArrayRead(user->
fda,user->
lUcat,&ucat));
214 PetscFunctionReturn(0);
223 PetscReal expected_translation = 0.0;
225 PetscFunctionBeginUser;
229 "periodic geometry validation test requires the x axis to be partitioned"));
231 expected_translation = (PetscReal)(user->
info.mx - 2) / (PetscReal)user->
info.mx;
235 "distributed X-periodic translation should be marked valid"));
237 "distributed X-periodic translation"));
239 "distributed X-periodic translation y component"));
241 "distributed X-periodic translation z component"));
244 PetscFunctionReturn(0);
255 const Cmpnts ***lcentx = NULL;
257 PetscReal translation, spacing;
260 PetscFunctionBeginUser;
265 "face-center coordinate test requires the x axis to be partitioned"));
267 spacing = translation / (PetscReal)(user->
info.mx - 2);
269 xe = xs + user->
info.xm;
272 PetscCall(DMDAVecGetArray(user->
fda, user->
Centx, ¢x));
273 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
274 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
275 for (PetscInt i = xs; i < xe; i++) {
276 centx[k][j][i] = (
Cmpnts){spacing * i, 2.0 + j, 3.0 + k};
280 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Centx, ¢x));
283 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lCentx, &lcentx));
286 "distributed translated Centx negative adjacent ghost"));
288 "distributed translated Centx negative endpoint"));
292 "distributed translated Centx positive endpoint"));
294 "distributed translated Centx positive adjacent ghost"));
296 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lCentx, &lcentx));
299 PetscFunctionReturn(0);
308 PetscReal ***iaj = NULL;
310 PetscInt xs, xe, ys, ye, zs, ze, mx;
312 PetscFunctionBeginUser;
316 "periodic face synchronization test requires the x axis to be partitioned"));
318 xs = user->
info.xs; xe = xs + user->
info.xm;
319 ys = user->
info.ys; ye = ys + user->
info.ym;
320 zs = user->
info.zs; ze = zs + user->
info.zm;
323 PetscCall(DMDAVecGetArray(user->
da, user->
IAj, &iaj));
324 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) {
327 PetscCall(DMDAVecRestoreArray(user->
da, user->
IAj, &iaj));
331 PetscCall(DMDAVecGetArrayRead(user->
da, user->
IAj, &iaj));
333 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
335 "distributed I-face negative seam should copy the opposite physical seam"));
339 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
341 "distributed I-face positive dummy should copy the leading physical face"));
344 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
IAj, &iaj));
347 PetscFunctionReturn(0);
358 PetscInt xs, xe, ys, ye, zs, ze, mx;
360 PetscFunctionBeginUser;
364 "periodic staggered synchronization test requires the x axis to be partitioned"));
366 xs = user->
info.xs; xe = xs + user->
info.xm;
367 ys = user->
info.ys; ye = ys + user->
info.ym;
368 zs = user->
info.zs; ze = zs + user->
info.zm;
371 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
372 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) {
374 ucont[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
376 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
380 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
382 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
385 "distributed Ucont.x negative seam"));
387 "distributed Ucont.y negative X endpoint"));
391 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
394 "distributed Ucont.y positive X dummy"));
396 "distributed Ucont.z positive X dummy"));
399 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
401 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
403 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
405 "distributed Ucont.x negative adjacent ghost repair"));
407 "distributed Ucont.y tangential X wraparound"));
411 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
413 "distributed Ucont.x positive adjacent ghost repair"));
415 "distributed Ucont.y positive tangential X wraparound"));
418 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
421 PetscFunctionReturn(0);
432 PetscMPIInt rank = 0, size = 1;
433 PetscInt *cell_ids = NULL;
434 PetscReal *positions = NULL;
437 PetscFunctionBeginUser;
438 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
439 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
440 PetscCall(
PicurvAssertIntEqual(2, size,
"restart migration unit test expects exactly two MPI ranks"));
442 PetscCall(PetscMemzero(&my_cell_info,
sizeof(my_cell_info)));
449 PetscCallMPI(MPI_Allgather(&my_cell_info,
sizeof(
RankCellInfo), MPI_BYTE,
453 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
454 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
459 positions[0] = 0.875;
470 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
471 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
474 PetscCall(DMSwarmGetLocalSize(user->
swarm, &nlocal));
476 "restart migration should move the foreign particle onto the owning rank"));
479 PetscFunctionReturn(0);
494 PetscInt local = 0, global = 0, rank_count = 0;
495 PetscMPIInt size = 0;
496 const PetscInt n = 6;
497 const PetscInt cell = 5;
498 const PetscInt
node = 6;
500 PetscFunctionBeginUser;
501 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
508 "cell-centered global count must be decomposition independent"));
512 PetscCall(
PicurvAssertBool((PetscBool)(local >= 0),
"local point count must be non-negative"));
513 PetscCallMPI(MPI_Allreduce(&local, &rank_count, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
515 "summed local counts must equal the reduced global count"));
520 "I-face global count must be decomposition independent"));
525 "node-centered global count must be decomposition independent"));
531 PETSC_TRUE, PETSC_TRUE, PETSC_TRUE));
535 "fully periodic node-centered count must drop duplicates exactly once"));
537 PetscFunctionReturn(0);
556 Vec *reference = NULL;
557 char tmpdir[PETSC_MAX_PATH_LEN];
558 PetscInt payload_count = 0;
559 PetscMPIInt size = 0;
561 PetscFunctionBeginUser;
562 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
563 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
565 memset(&definition, 0,
sizeof(definition));
580 PetscCallMPI(MPI_Bcast(tmpdir,
sizeof(tmpdir), MPI_CHAR, 0, PETSC_COMM_WORLD));
584 PetscCall(VecSet(user->
Nvert, 0.0));
596 for (PetscInt s = 0; s < 4; ++s) {
597 PetscBool accepted = PETSC_FALSE;
598 PetscReal weight = 0.0;
599 PetscReal ***p = NULL;
601 const DMDALocalInfo info = user->
info;
603 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
604 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
605 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k)
606 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j)
607 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
608 const PetscReal tag = (PetscReal)(100 * k + 10 * j + i);
610 p[k][j][i] = tag + 0.25 * (PetscReal)s;
611 ucat[k][j][i].
x = tag;
612 ucat[k][j][i].
y = tag + 1.0 + (PetscReal)s;
613 ucat[k][j][i].
z = tag - 1.0;
615 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
616 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
626 PetscCall(PetscCalloc1((
size_t)payload_count, &reference));
627 for (PetscInt index = 0; index < payload_count; ++index) {
631 PetscCall(VecDuplicate(payload.
vec, &reference[index]));
632 PetscCall(VecCopy(payload.
vec, reference[index]));
633 PetscCall(VecZeroEntries(payload.
vec));
641 "physical-time weights survive on every rank"));
643 for (PetscInt index = 0; index < payload_count; ++index) {
645 PetscReal difference = 0.0;
649 PetscCall(VecAXPY(reference[index], -1.0, payload.
vec));
650 PetscCall(VecNorm(reference[index], NORM_INFINITY, &difference));
651 PetscCall(PetscSNPrintf(context,
sizeof(context),
652 "payload '%s' round trips exactly across %d ranks",
653 payload.
name, (
int)size));
655 PetscCall(VecDestroy(&reference[index]));
657 PetscCall(PetscFree(reference));
659 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
661 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
668 PetscFunctionReturn(0);
690 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv MPI-focused runtime tests");
695 ierr =
PicurvRunTests(
"unit-mpi", cases,
sizeof(cases) /
sizeof(cases[0]));
701 ierr = PetscFinalize();
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent fields belonging to one face family.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
Header file for Particle Motion and migration related functions.
PetscErrorCode MigrateRestartParticlesUsingCellID(UserCtx *user)
Fast-path migration for restart particles using preloaded Cell IDs.
Header file for Particle Swarm management functions.
PetscErrorCode DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
Distributes particles evenly across MPI processes, handling any remainders.
Authoritative identities and storage metadata for persistent Eulerian fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
Public interface for grid, solver, and metric setup routines.
PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist)
Broadcasts the bounding box information collected on rank 0 to all other ranks.
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
PetscErrorCode ComputeLocalBoundingBox(UserCtx *user, BoundingBox *localBBox)
Computes the local bounding box of the grid on the current process.
PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes)
Gathers local bounding boxes from all MPI processes to rank 0.
Public interface for data input/output routines.
PetscErrorCode RestoreFieldStatisticsState(SimCtx *simCtx, PetscInt ti)
Restores field-statistics window state and accumulators from a checkpoint.
PetscErrorCode WriteCheckpointBundle(SimCtx *simCtx, const char *reason)
Write and atomically publish one complete checkpoint bundle.
PetscErrorCode GetOwnedCellRange(const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
Determines the global starting index and number of CELLS owned by the current processor in a specifie...
Per-window PETSc accumulator storage and pointwise application.
Vec vec
Borrowed accumulator vector; never owned by the caller.
PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage)
Allocates the accumulator state one window owns on one block.
PetscErrorCode PicurvWindowStoragePayload(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, PetscInt index, PicurvStatisticsPayload *payload)
Resolves one enumerated payload of a window's storage.
char name[96]
File basename, no extension.
PetscErrorCode PicurvWindowAccumulate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage, PetscReal weight)
Applies one accepted completed state to a window's accumulators.
PetscErrorCode PicurvWindowStorageDestroy(PicurvWindowStorage *storage)
Releases accumulator state previously created for one window.
PetscErrorCode PicurvWindowStoragePayloadCount(const PicurvWindowStorage *storage, PetscInt *count)
Reports how many checkpointable vectors one window's storage holds.
One checkpointable accumulator vector, resolved by enumeration index.
Independent accumulator state for one window on one block.
Spatial target resolution for the field-statistics pipeline.
@ PICURV_STATISTICS_MASK_FLUID
PetscErrorCode SpatialTargetPlanLocalPointCount(const SpatialTargetPlan *plan, PetscInt *count)
Counts the points this rank contributes.
PetscErrorCode SpatialTargetPlanGlobalPointCount(const SpatialTargetPlan *plan, MPI_Comm comm, PetscInt *count)
Counts the points contributed across a communicator.
PetscErrorCode SpatialTargetPlanCreate(UserCtx *user, FieldId field_id, PicurvStatisticsMask mask, SpatialTargetPlan *plan)
Resolves the iteration domain for one field on one block.
Resolved iteration domain for one field on one block.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
PetscInt first
First member; must also appear in the field list.
PicurvWindowFieldRequest fields[16]
PicurvCadenceKind cadence_kind
PetscInt step_cadence
Used when cadence_kind is step; must be positive.
#define PICURV_WINDOW_NAME_LENGTH
Maximum stored length of a window name, including the terminator.
PetscErrorCode PicurvWindowInit(PicurvWindow *window, const PicurvWindowDefinition *definition)
Validates a definition and initializes a window to the pending state.
PetscErrorCode PicurvWindowOfferState(PicurvWindow *window, PetscInt step, PetscReal time, PetscBool *accepted, PetscReal *weight)
Offers one completed state to a window and reports the decision.
PetscBool want_second
Also keep the centered second moment.
PetscInt second
Second member; must also appear in the field list.
PicurvWindowCovarianceRequest covariances[16]
PetscInt covariance_count
PetscInt field_id
Catalogued Eulerian field identity.
@ PICURV_WEIGHTING_PHYSICAL_TIME
Weight is the represented interval.
@ PICURV_CADENCE_STEP
Every n completed steps from activation.
PicurvWeighting weighting
Runtime state of one window.
The scientifically immutable definition of one window.
static void MarkXPeriodic(UserCtx *user)
Marks both x boundary faces as geometric periodic boundaries.
static PetscErrorCode TestSpatialTargetIsDecompositionIndependent(void)
Spatial target domains must not depend on how ranks divide the block.
static PetscErrorCode TestPeriodicFaceCenterCoordinatesMultiRank(void)
Tests translated face-center ghosts when the periodic axis is partitioned.
int main(int argc, char **argv)
Runs the unit-mpi PETSc test binary.
static PetscErrorCode TestPeriodicFaceFieldSynchronizationMultiRank(void)
Tests persistent I-face synchronization across an MPI-partitioned seam.
static PetscErrorCode TestRestartCellIdMigrationMovesParticleToOwner(void)
Tests restart fast-path migration using preloaded cell ownership metadata.
static PetscErrorCode TestPeriodicGeometryValidationMultiRank(void)
Tests periodic seam translation discovery when seam nodes are on different ranks.
static PetscErrorCode TestStatisticsCheckpointRoundTripMultiRank(void)
Statistics payloads must survive a checkpoint round trip under decomposition.
static PetscErrorCode TestPeriodicStaggeredFieldSynchronizationMultiRank(void)
Tests persistent Ucont synchronization across an MPI-partitioned seam.
static PetscReal PeriodicScalarValue(PetscInt i, PetscInt j, PetscInt k, PetscReal offset)
Returns a deterministic scalar value for periodic-transfer assertions.
static PetscErrorCode TestPeriodicCellFieldSynchronizationMultiRank(void)
Tests distributed synchronization of persistent cell-centered scalar fields.
static PetscErrorCode TestDistributeParticlesCollectiveConsistency(void)
Tests collective particle distribution consistency across MPI ranks.
static PetscErrorCode TestBoundingBoxCollectivesMultiRank(void)
Tests multi-rank bounding-box gather and broadcast helpers.
PetscErrorCode PicurvMakeTempDir(char *path, size_t path_len)
Creates a unique temporary directory for one test case.
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 PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
PetscErrorCode PicurvPopulateIdentityMetrics(UserCtx *user)
Populates identity metric vectors on the minimal grid fixture.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
PetscErrorCode PicurvRemoveTempDir(const char *path)
Recursively removes a temporary directory created by PicurvMakeTempDir.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
PetscInt fieldStatisticsWindowCount
BoundaryFaceConfig boundary_faces[6]
@ BC_HANDLER_PERIODIC_GEOMETRIC
BCHandlerType handler_type
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
char output_dir[PETSC_MAX_PATH_LEN]
PetscBool fieldStatisticsEnabled
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
RankCellInfo * RankCellInfoMap
struct PicurvWindow * fieldStatisticsWindows
struct PicurvWindowStorage * fieldStatisticsStorage
Cmpnts periodic_translation[3]
PetscBool periodic_translation_valid[3]
char restart_dir[PETSC_MAX_PATH_LEN]
PetscBool fieldStatisticsContinue
Defines a 3D axis-aligned bounding box.
A 3D point or vector with PetscScalar components.
A lean struct to hold the global cell ownership range for a single MPI rank.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
A generic C-style linked list node for integers.