39 return offset + (PetscReal)(i + 10 * j + 100 * k);
47 PetscMPIInt rank = 0, size = 1;
48 PetscInt local_particles = 0;
49 PetscInt remainder = 0;
50 PetscInt global_particles = 0;
51 PetscInt remainder_min = 0, remainder_max = 0;
52 const PetscInt total_particles = 137;
54 PetscFunctionBeginUser;
55 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
56 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
57 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
62 total_particles / size + (((PetscInt)rank < remainder) ? 1 : 0),
64 "local particle share should match quotient+remainder policy"));
66 PetscCallMPI(MPI_Allreduce(&local_particles, &global_particles, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
67 PetscCall(
PicurvAssertIntEqual(total_particles, global_particles,
"distributed particle count must conserve total particles"));
69 PetscCallMPI(MPI_Allreduce(&remainder, &remainder_min, 1, MPIU_INT, MPI_MIN, PETSC_COMM_WORLD));
70 PetscCallMPI(MPI_Allreduce(&remainder, &remainder_max, 1, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD));
71 PetscCall(
PicurvAssertIntEqual(remainder_min, remainder_max,
"all ranks should report the same remainder"));
72 PetscFunctionReturn(0);
84 PetscMPIInt rank = 0, size = 1;
85 PetscReal global_min_x = 0.0;
86 PetscReal global_max_x = 0.0;
87 PetscReal expected_global_max_x = 0.0;
89 PetscFunctionBeginUser;
90 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
91 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
92 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
95 expected_global_max_x = ((PetscReal)(user->
IM - 1) / (PetscReal)user->
IM) + 1.0e-6;
99 PetscCall(
PicurvAssertBool((PetscBool)(boxes != NULL),
"all ranks should hold the gathered bounding-box table"));
101 for (PetscMPIInt r = 0; r < size; ++r) {
110 PetscCallMPI(MPI_Allreduce(&local_bbox.
min_coords.
x, &global_min_x, 1, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD));
111 PetscCallMPI(MPI_Allreduce(&local_bbox.
max_coords.
x, &global_max_x, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD));
112 PetscCall(
PicurvAssertBool((PetscBool)(global_min_x <= 0.0),
"global min x should include domain start"));
113 PetscCall(
PicurvAssertRealNear(expected_global_max_x, global_max_x, 1.0e-10,
"global max x should match the normalized physical-node domain end"));
117 PetscFunctionReturn(0);
127 PetscReal ***p = NULL;
128 PetscReal ***cs = NULL;
129 PetscReal ***diffusivity = NULL;
132 PetscInt xs, xe, ys, ye, zs, ze, mx;
134 PetscFunctionBeginUser;
138 "periodic cell synchronization test requires the x axis to be partitioned"));
139 PetscCall(DMCreateGlobalVector(user->
da, &user->
CS));
140 PetscCall(DMCreateLocalVector(user->
da, &user->
lCs));
143 xe = xs + user->
info.xm;
145 ye = ys + user->
info.ym;
147 ze = zs + user->
info.zm;
150 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
151 PetscCall(DMDAVecGetArray(user->
da, user->
CS, &cs));
152 PetscCall(DMDAVecGetArray(user->
da, user->
Diffusivity, &diffusivity));
153 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
154 for (PetscInt k = zs; k < ze; ++k) {
155 for (PetscInt j = ys; j < ye; ++j) {
156 for (PetscInt i = xs; i < xe; ++i) {
164 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
165 PetscCall(DMDAVecRestoreArray(user->
da, user->
CS, &cs));
166 PetscCall(DMDAVecRestoreArray(user->
da, user->
Diffusivity, &diffusivity));
167 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
171 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P, &p));
172 PetscCall(DMDAVecGetArrayRead(user->
da, user->
CS, &cs));
173 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Diffusivity, &diffusivity));
174 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucat, &ucat));
176 for (PetscInt k = zs; k < ze; ++k) {
177 for (PetscInt j = ys; j < ye; ++j) {
179 "distributed P negative endpoint should copy the opposite interior"));
181 "distributed CS negative endpoint should copy the opposite interior"));
183 "distributed Diffusivity negative endpoint should copy the opposite interior"));
185 "distributed Ucat negative endpoint should copy the opposite interior"));
190 for (PetscInt k = zs; k < ze; ++k) {
191 for (PetscInt j = ys; j < ye; ++j) {
193 "distributed P positive endpoint should copy the opposite interior"));
195 "distributed CS positive endpoint should copy the opposite interior"));
197 "distributed Diffusivity positive endpoint should copy the opposite interior"));
199 "distributed Ucat positive endpoint should copy the leading interior"));
203 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P, &p));
204 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
CS, &cs));
205 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Diffusivity, &diffusivity));
206 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucat, &ucat));
207 PetscCall(DMDAVecGetArrayRead(user->
fda,user->
lUcat,&ucat));
209 "distributed local Ucat negative ghost follows corrected global endpoint"));
211 "distributed local Ucat positive ghost follows corrected global endpoint"));
212 PetscCall(DMDAVecRestoreArrayRead(user->
fda,user->
lUcat,&ucat));
215 PetscFunctionReturn(0);
224 PetscReal expected_translation = 0.0;
226 PetscFunctionBeginUser;
230 "periodic geometry validation test requires the x axis to be partitioned"));
232 expected_translation = (PetscReal)(user->
info.mx - 2) / (PetscReal)user->
info.mx;
236 "distributed X-periodic translation should be marked valid"));
238 "distributed X-periodic translation"));
240 "distributed X-periodic translation y component"));
242 "distributed X-periodic translation z component"));
245 PetscFunctionReturn(0);
256 const Cmpnts ***lcentx = NULL;
258 PetscReal translation, spacing;
261 PetscFunctionBeginUser;
266 "face-center coordinate test requires the x axis to be partitioned"));
268 spacing = translation / (PetscReal)(user->
info.mx - 2);
270 xe = xs + user->
info.xm;
273 PetscCall(DMDAVecGetArray(user->
fda, user->
Centx, ¢x));
274 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++) {
275 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++) {
276 for (PetscInt i = xs; i < xe; i++) {
277 centx[k][j][i] = (
Cmpnts){spacing * i, 2.0 + j, 3.0 + k};
281 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Centx, ¢x));
284 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lCentx, &lcentx));
287 "distributed translated Centx negative adjacent ghost"));
289 "distributed translated Centx negative endpoint"));
293 "distributed translated Centx positive endpoint"));
295 "distributed translated Centx positive adjacent ghost"));
297 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lCentx, &lcentx));
300 PetscFunctionReturn(0);
309 PetscReal ***iaj = NULL;
311 PetscInt xs, xe, ys, ye, zs, ze, mx;
313 PetscFunctionBeginUser;
317 "periodic face synchronization test requires the x axis to be partitioned"));
319 xs = user->
info.xs; xe = xs + user->
info.xm;
320 ys = user->
info.ys; ye = ys + user->
info.ym;
321 zs = user->
info.zs; ze = zs + user->
info.zm;
324 PetscCall(DMDAVecGetArray(user->
da, user->
IAj, &iaj));
325 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) {
328 PetscCall(DMDAVecRestoreArray(user->
da, user->
IAj, &iaj));
332 PetscCall(DMDAVecGetArrayRead(user->
da, user->
IAj, &iaj));
334 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
336 "distributed I-face negative seam should copy the opposite physical seam"));
340 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
342 "distributed I-face positive dummy should copy the leading physical face"));
345 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
IAj, &iaj));
348 PetscFunctionReturn(0);
359 PetscInt xs, xe, ys, ye, zs, ze, mx;
361 PetscFunctionBeginUser;
365 "periodic staggered synchronization test requires the x axis to be partitioned"));
367 xs = user->
info.xs; xe = xs + user->
info.xm;
368 ys = user->
info.ys; ye = ys + user->
info.ym;
369 zs = user->
info.zs; ze = zs + user->
info.zm;
372 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
373 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) {
375 ucont[k][j][i] = (
Cmpnts){value + 1000.0, value + 2000.0, value + 3000.0};
377 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
381 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
383 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
386 "distributed Ucont.x negative seam"));
388 "distributed Ucont.y negative X endpoint"));
392 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
395 "distributed Ucont.y positive X dummy"));
397 "distributed Ucont.z positive X dummy"));
400 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
402 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
404 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
406 "distributed Ucont.x negative adjacent ghost repair"));
408 "distributed Ucont.y tangential X wraparound"));
412 for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) {
414 "distributed Ucont.x positive adjacent ghost repair"));
416 "distributed Ucont.y positive tangential X wraparound"));
419 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
422 PetscFunctionReturn(0);
433 PetscMPIInt rank = 0, size = 1;
434 PetscInt *cell_ids = NULL;
435 PetscReal *positions = NULL;
438 PetscFunctionBeginUser;
439 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
440 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
441 PetscCall(
PicurvAssertIntEqual(2, size,
"restart migration unit test expects exactly two MPI ranks"));
443 PetscCall(PetscMemzero(&my_cell_info,
sizeof(my_cell_info)));
450 PetscCallMPI(MPI_Allgather(&my_cell_info,
sizeof(
RankCellInfo), MPI_BYTE,
454 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
455 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
460 positions[0] = 0.875;
471 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
472 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
475 PetscCall(DMSwarmGetLocalSize(user->
swarm, &nlocal));
477 "restart migration should move the foreign particle onto the owning rank"));
480 PetscFunctionReturn(0);
495 PetscInt local = 0, global = 0, rank_count = 0;
496 PetscMPIInt size = 0;
497 const PetscInt n = 6;
498 const PetscInt cell = 5;
499 const PetscInt
node = 6;
501 PetscFunctionBeginUser;
502 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
509 "cell-centered global count must be decomposition independent"));
513 PetscCall(
PicurvAssertBool((PetscBool)(local >= 0),
"local point count must be non-negative"));
514 PetscCallMPI(MPI_Allreduce(&local, &rank_count, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
516 "summed local counts must equal the reduced global count"));
521 "I-face global count must be decomposition independent"));
526 "node-centered global count must be decomposition independent"));
532 PETSC_TRUE, PETSC_TRUE, PETSC_TRUE));
536 "fully periodic node-centered count must drop duplicates exactly once"));
538 PetscFunctionReturn(0);
557 Vec *reference = NULL;
558 char tmpdir[PETSC_MAX_PATH_LEN];
559 PetscInt payload_count = 0;
560 PetscMPIInt size = 0;
562 PetscFunctionBeginUser;
563 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
564 PetscCall(
PicurvAssertBool((PetscBool)(size >= 2),
"unit-mpi requires at least two MPI ranks"));
566 memset(&definition, 0,
sizeof(definition));
581 PetscCallMPI(MPI_Bcast(tmpdir,
sizeof(tmpdir), MPI_CHAR, 0, PETSC_COMM_WORLD));
585 PetscCall(VecSet(user->
Nvert, 0.0));
597 for (PetscInt s = 0; s < 4; ++s) {
598 PetscBool accepted = PETSC_FALSE;
599 PetscReal weight = 0.0;
600 PetscReal ***p = NULL;
602 const DMDALocalInfo info = user->
info;
604 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
605 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
606 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k)
607 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j)
608 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
609 const PetscReal tag = (PetscReal)(100 * k + 10 * j + i);
611 p[k][j][i] = tag + 0.25 * (PetscReal)s;
612 ucat[k][j][i].
x = tag;
613 ucat[k][j][i].
y = tag + 1.0 + (PetscReal)s;
614 ucat[k][j][i].
z = tag - 1.0;
616 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
617 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
627 PetscCall(PetscCalloc1((
size_t)payload_count, &reference));
628 for (PetscInt index = 0; index < payload_count; ++index) {
632 PetscCall(VecDuplicate(payload.
vec, &reference[index]));
633 PetscCall(VecCopy(payload.
vec, reference[index]));
634 PetscCall(VecZeroEntries(payload.
vec));
642 "physical-time weights survive on every rank"));
644 for (PetscInt index = 0; index < payload_count; ++index) {
646 PetscReal difference = 0.0;
650 PetscCall(VecAXPY(reference[index], -1.0, payload.
vec));
651 PetscCall(VecNorm(reference[index], NORM_INFINITY, &difference));
652 PetscCall(PetscSNPrintf(context,
sizeof(context),
653 "payload '%s' round trips exactly across %d ranks",
654 payload.
name, (
int)size));
656 PetscCall(VecDestroy(&reference[index]));
658 PetscCall(PetscFree(reference));
660 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
662 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
669 PetscFunctionReturn(0);
686 Vec numerator, denominator, ratio;
688 PetscReal ***num = NULL, ***den = NULL, ***out = NULL;
690 PetscInt xs, xe, ys, ye, zs, ze;
691 PetscReal sampled = 0.0;
692 PetscReal numerator_total = 0.0, denominator_total = 0.0;
693 const PetscBool all[3] = {PETSC_TRUE, PETSC_TRUE, PETSC_TRUE};
695 PetscFunctionBeginUser;
697 PetscCall(DMDAGetLocalInfo(user->
da, &info));
698 PetscCall(VecSet(user->
lNvert, 0.0));
699 PetscCall(VecSet(user->
lAj, 1.0));
701 xs = (info.xs == 0) ? 1 : info.xs;
702 ys = (info.ys == 0) ? 1 : info.ys;
703 zs = (info.zs == 0) ? 1 : info.zs;
704 xe = (info.xs + info.xm == info.mx) ? info.mx - 1 : info.xs + info.xm;
705 ye = (info.ys + info.ym == info.my) ? info.my - 1 : info.ys + info.ym;
706 ze = (info.zs + info.zm == info.mz) ? info.mz - 1 : info.zs + info.zm;
708 PetscCall(VecDuplicate(user->
lNvert, &numerator));
709 PetscCall(VecDuplicate(user->
lNvert, &denominator));
710 PetscCall(VecDuplicate(user->
lNvert, &ratio));
711 PetscCall(VecSet(numerator, 0.0));
712 PetscCall(VecSet(denominator, 0.0));
713 PetscCall(VecSet(ratio, 0.0));
717 PetscCall(DMDAVecGetArray(user->
da, numerator, &num));
718 PetscCall(DMDAVecGetArray(user->
da, denominator, &den));
719 for (PetscInt k = zs; k < ze; ++k)
720 for (PetscInt j = ys; j < ye; ++j)
721 for (PetscInt i = xs; i < xe; ++i) {
722 num[k][j][i] = (PetscReal)(i * j + k);
723 den[k][j][i] = (PetscReal)(i + 1);
725 PetscCall(DMDAVecRestoreArray(user->
da, numerator, &num));
726 PetscCall(DMDAVecRestoreArray(user->
da, denominator, &den));
731 PETSC_COMM_WORLD, ratio, NULL));
733 for (PetscInt k = 1; k < info.mz - 1; ++k)
734 for (PetscInt j = 1; j < info.my - 1; ++j)
735 for (PetscInt i = 1; i < info.mx - 1; ++i) {
736 numerator_total += (PetscReal)(i * j + k);
737 denominator_total += (PetscReal)(i + 1);
740 PetscCall(DMDAVecGetArray(user->
da, ratio, &out));
741 sampled = out[zs][ys][xs];
742 PetscCall(DMDAVecRestoreArray(user->
da, ratio, &out));
745 "the globally averaged ratio must match the serial sums "
746 "however the block is decomposed"));
748 PetscCall(VecDestroy(&numerator));
749 PetscCall(VecDestroy(&denominator));
750 PetscCall(VecDestroy(&ratio));
752 PetscFunctionReturn(0);
775 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv MPI-focused runtime tests");
780 ierr =
PicurvRunTests(
"unit-mpi", cases,
sizeof(cases) /
sizeof(cases[0]));
786 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.
PetscErrorCode PicurvSpatialRatioAverage(UserCtx *user, const SpatialTargetPlan *plan, Vec numerator, Vec denominator, Vec inclusion, const PetscBool average_direction[3], MPI_Comm comm, Vec ratio, PetscReal *scalar)
Averages two fields over a target domain and divides the results.
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 TestLESAveragingIsDecompositionIndependent(void)
Tests that LES coefficient averaging does not depend on the decomposition.
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.