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

Decomposition-independent regression tests for post-processing compute. More...

#include "test_support.h"
#include "postprocessor.h"
#include "statistics_accumulator.h"
#include "statistics_window.h"
Include dependency graph for test_post_compute_mpi.c:

Go to the source code of this file.

Functions

static PetscReal ScalarValue (PetscInt i, PetscInt j, PetscInt k)
 Analytic scalar field used to expose misplaced or missing grid points.
 
static PetscErrorCode AssertGlobalError (PetscReal local_error, PetscReal tolerance, const char *context)
 Requires every rank's maximum error to be within tolerance.
 
static PetscErrorCode TestEulerianPipelineDecompositionIndependent (void)
 Exercises every Eulerian transformation currently dispatched by the pipeline.
 
static PetscErrorCode TestParticlePipelineMatchesSourceOwnership (void)
 Verifies the production-created derived swarm mirrors source ownership.
 
static PetscErrorCode TestResizeSwarmGloballyBalanced (void)
 Checks that global resizing produces one balanced global population.
 
static PetscErrorCode TestFieldStatisticsDerivedNodalMultiRank (void)
 Exercises accumulator-to-derived-nodal field statistics across ownership boundaries.
 
int main (int argc, char **argv)
 Runs the serial/MPI post-processing compute regression suite.
 

Variables

static const PetscReal kSentinel = -9876.5
 

Detailed Description

Decomposition-independent regression tests for post-processing compute.

Definition in file test_post_compute_mpi.c.

Function Documentation

◆ ScalarValue()

static PetscReal ScalarValue ( PetscInt  i,
PetscInt  j,
PetscInt  k 
)
static

Analytic scalar field used to expose misplaced or missing grid points.

Definition at line 15 of file test_post_compute_mpi.c.

16{
17 return (PetscReal)(i + 10 * j + 100 * k);
18}
Here is the caller graph for this function:

◆ AssertGlobalError()

static PetscErrorCode AssertGlobalError ( PetscReal  local_error,
PetscReal  tolerance,
const char *  context 
)
static

Requires every rank's maximum error to be within tolerance.

Definition at line 21 of file test_post_compute_mpi.c.

23{
24 PetscReal global_error = 0.0;
25
26 PetscFunctionBeginUser;
27 PetscCallMPI(MPI_Allreduce(&local_error, &global_error, 1, MPIU_REAL, MPI_MAX,
28 PETSC_COMM_WORLD));
29 PetscCall(PicurvAssertBool((PetscBool)(global_error <= tolerance), context));
30 PetscFunctionReturn(0);
31}
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestEulerianPipelineDecompositionIndependent()

static PetscErrorCode TestEulerianPipelineDecompositionIndependent ( void  )
static

Exercises every Eulerian transformation currently dispatched by the pipeline.

Definition at line 34 of file test_post_compute_mpi.c.

35{
36 SimCtx *simCtx = NULL;
37 UserCtx *user = NULL;
38 PostProcessParams *pps = NULL;
39 PetscReal ***pressure = NULL;
40 Cmpnts ***velocity = NULL;
41 const PetscReal ***pressure_result = NULL;
42 const PetscReal ***pressure_nodal = NULL;
43 const PetscReal ***qcrit = NULL;
44 const Cmpnts ***velocity_nodal = NULL;
45 PetscReal pressure_error = 0.0;
46 PetscReal pressure_nodal_error = 0.0;
47 PetscReal velocity_nodal_error = 0.0;
48 PetscReal qcrit_error = 0.0;
49 PetscInt local_physical_nodes = 0;
50 PetscInt global_physical_nodes = 0;
51 PetscInt local_q_points = 0;
52 PetscInt global_q_points = 0;
53
54 PetscFunctionBeginUser;
55 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 8, 6, 4));
56 PetscCall(PetscCalloc1(1, &simCtx->pps));
57 pps = simCtx->pps;
58 pps->reference[0] = 1;
59 pps->reference[1] = 1;
60 pps->reference[2] = 1;
61 simCtx->scaling.L_ref = 1.0;
62 simCtx->scaling.U_ref = 1.0;
63 simCtx->scaling.P_ref = 2.0;
64
65 PetscCall(DMDAVecGetArray(user->da, user->P, &pressure));
66 PetscCall(DMDAVecGetArray(user->fda, user->Ucat, &velocity));
67 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k) {
68 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j) {
69 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i) {
70 pressure[k][j][i] = ScalarValue(i, j, k);
71 velocity[k][j][i] = (Cmpnts){1.0, 2.0, 3.0};
72 }
73 }
74 }
75 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucat, &velocity));
76 PetscCall(DMDAVecRestoreArray(user->da, user->P, &pressure));
77 PetscCall(VecSet(user->P_nodal, kSentinel));
78 PetscCall(VecSet(user->Ucat_nodal, kSentinel));
79 PetscCall(VecSet(user->Qcrit, kSentinel));
80
81 PetscCall(PetscStrncpy(
83 "NormalizeRelativeField:P;DimensionalizeAllLoadedFields;"
84 "CellToNodeAverage:P>P_nodal;CellToNodeAverage:Ucat>Ucat_nodal;"
85 "ComputeQCriterion",
86 sizeof(pps->process_pipeline)));
87 PetscCall(EulerianDataProcessingPipeline(user, pps));
88
89 PetscCall(DMDAVecGetArrayRead(user->da, user->P, &pressure_result));
90 PetscCall(DMDAVecGetArrayRead(user->da, user->P_nodal, &pressure_nodal));
91 PetscCall(DMDAVecGetArrayRead(user->fda, user->Ucat_nodal, &velocity_nodal));
92 PetscCall(DMDAVecGetArrayRead(user->da, user->Qcrit, &qcrit));
93 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k) {
94 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j) {
95 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i) {
96 const PetscBool physical_node =
97 (PetscBool)(i < user->info.mx - 1 && j < user->info.my - 1 &&
98 k < user->info.mz - 1);
99 const PetscBool q_point =
100 (PetscBool)(i >= 1 && i < user->info.mx - 1 &&
101 j >= 1 && j < user->info.my - 1 &&
102 k >= 1 && k < user->info.mz - 1);
103 const PetscReal expected_pressure = 2.0 * (ScalarValue(i, j, k) - 111.0);
104
105 pressure_error = PetscMax(
106 pressure_error,
107 PetscAbsReal(pressure_result[k][j][i] - expected_pressure));
108 if (physical_node) {
109 const PetscReal expected_nodal =
110 2.0 * (ScalarValue(i, j, k) + 55.5 - 111.0);
111
112 pressure_nodal_error = PetscMax(
113 pressure_nodal_error,
114 PetscAbsReal(pressure_nodal[k][j][i] - expected_nodal));
115 velocity_nodal_error = PetscMax(
116 velocity_nodal_error,
117 PetscAbsReal(velocity_nodal[k][j][i].x - 1.0));
118 velocity_nodal_error = PetscMax(
119 velocity_nodal_error,
120 PetscAbsReal(velocity_nodal[k][j][i].y - 2.0));
121 velocity_nodal_error = PetscMax(
122 velocity_nodal_error,
123 PetscAbsReal(velocity_nodal[k][j][i].z - 3.0));
124 ++local_physical_nodes;
125 } else {
126 pressure_nodal_error = PetscMax(
127 pressure_nodal_error,
128 PetscAbsReal(pressure_nodal[k][j][i] - kSentinel));
129 velocity_nodal_error = PetscMax(
130 velocity_nodal_error,
131 PetscAbsReal(velocity_nodal[k][j][i].x - kSentinel));
132 velocity_nodal_error = PetscMax(
133 velocity_nodal_error,
134 PetscAbsReal(velocity_nodal[k][j][i].y - kSentinel));
135 velocity_nodal_error = PetscMax(
136 velocity_nodal_error,
137 PetscAbsReal(velocity_nodal[k][j][i].z - kSentinel));
138 }
139 qcrit_error = PetscMax(
140 qcrit_error,
141 PetscAbsReal(qcrit[k][j][i] - (q_point ? 0.0 : kSentinel)));
142 if (q_point) ++local_q_points;
143 }
144 }
145 }
146 PetscCall(DMDAVecRestoreArrayRead(user->da, user->Qcrit, &qcrit));
147 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Ucat_nodal, &velocity_nodal));
148 PetscCall(DMDAVecRestoreArrayRead(user->da, user->P_nodal, &pressure_nodal));
149 PetscCall(DMDAVecRestoreArrayRead(user->da, user->P, &pressure_result));
150
151 PetscCallMPI(MPI_Allreduce(&local_physical_nodes, &global_physical_nodes, 1,
152 MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
153 PetscCallMPI(MPI_Allreduce(&local_q_points, &global_q_points, 1,
154 MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
155 PetscCall(PicurvAssertIntEqual(user->IM * user->JM * user->KM,
156 global_physical_nodes,
157 "the Eulerian pipeline must visit every physical node exactly once"));
158 PetscCall(PicurvAssertIntEqual((user->IM - 1) * (user->JM - 1) * (user->KM - 1),
159 global_q_points,
160 "Q-criterion must visit every interior cell exactly once"));
161 PetscCall(AssertGlobalError(pressure_error, 1.0e-12,
162 "pressure normalization and dimensionalization are decomposition independent"));
163 PetscCall(AssertGlobalError(pressure_nodal_error, 1.0e-12,
164 "scalar nodal averaging covers rank interfaces and physical boundaries"));
165 PetscCall(AssertGlobalError(velocity_nodal_error, 1.0e-12,
166 "vector nodal averaging covers rank interfaces and physical boundaries"));
167 PetscCall(AssertGlobalError(qcrit_error, 1.0e-12,
168 "Q-criterion covers the complete distributed interior"));
169
170 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
171 PetscFunctionReturn(0);
172}
PetscErrorCode EulerianDataProcessingPipeline(UserCtx *user, PostProcessParams *pps)
Parses the processing pipeline string and executes the requested kernels.
static const PetscReal kSentinel
static PetscReal ScalarValue(PetscInt i, PetscInt j, PetscInt k)
Analytic scalar field used to expose misplaced or missing grid points.
static PetscErrorCode AssertGlobalError(PetscReal local_error, PetscReal tolerance, const char *context)
Requires every rank's maximum error to be within tolerance.
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 PicurvDestroyMinimalContexts(SimCtx **simCtx_ptr, UserCtx **user_ptr)
Destroys minimal SimCtx/UserCtx fixtures and all owned PETSc objects.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
Vec P_nodal
Definition variables.h:991
PetscInt KM
Definition variables.h:910
PetscReal L_ref
Definition variables.h:677
PetscInt reference[3]
Definition variables.h:634
Vec Ucat_nodal
Definition variables.h:992
Vec Qcrit
Definition variables.h:993
Vec Ucat
Definition variables.h:929
ScalingCtx scaling
Definition variables.h:785
PetscInt JM
Definition variables.h:910
char process_pipeline[1024]
Definition variables.h:607
DMDALocalInfo info
Definition variables.h:908
PostProcessParams * pps
Definition variables.h:880
PetscInt IM
Definition variables.h:910
PetscReal P_ref
Definition variables.h:680
PetscReal U_ref
Definition variables.h:678
A 3D point or vector with PetscScalar components.
Definition variables.h:102
Holds all configuration parameters for a post-processing run.
Definition variables.h:596
The master context for the entire simulation.
Definition variables.h:695
User-defined context containing data specific to a single computational grid level.
Definition variables.h:896
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestParticlePipelineMatchesSourceOwnership()

static PetscErrorCode TestParticlePipelineMatchesSourceOwnership ( void  )
static

Verifies the production-created derived swarm mirrors source ownership.

Definition at line 175 of file test_post_compute_mpi.c.

176{
177 SimCtx *simCtx = NULL;
178 UserCtx *user = NULL;
180 PetscMPIInt rank = 0, size = 1;
181 PetscInt source_local = 0;
182 PetscInt source_global = 0;
183 PetscInt post_local = 0;
184 PetscInt post_global = 0;
185 PetscInt offset = 0;
186 PetscScalar (*velocity)[3] = NULL;
187 const PetscScalar *ske = NULL;
188 PetscReal local_error = 0.0;
189 const PetscInt total_particles = 7;
190
191 PetscFunctionBeginUser;
192 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
193 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
194 source_local = total_particles / size + (rank < total_particles % size ? 1 : 0);
195 PetscCall(PetscMemzero(&pps, sizeof(pps)));
196 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
197 PetscCall(PicurvCreateSwarmPair(user, source_local, "unused"));
198 PetscCall(DMDestroy(&user->post_swarm));
199 PetscCall(PetscStrncpy(pps.particle_pipeline, "ComputeSpecificKE:velocity>ske",
200 sizeof(pps.particle_pipeline)));
201 PetscCall(SetupPostProcessSwarm(user, &pps));
202
203 if (size > 1) {
204 PetscCallMPI(MPI_Exscan(&source_local, &offset, 1, MPIU_INT, MPI_SUM,
205 PETSC_COMM_WORLD));
206 if (rank == 0) offset = 0;
207 }
208 PetscCall(DMSwarmGetField(user->swarm, "velocity", NULL, NULL, (void **)&velocity));
209 for (PetscInt p = 0; p < source_local; ++p) {
210 const PetscReal tag = (PetscReal)(offset + p + 1);
211
212 velocity[p][0] = tag;
213 velocity[p][1] = 2.0;
214 velocity[p][2] = -1.0;
215 }
216 PetscCall(DMSwarmRestoreField(user->swarm, "velocity", NULL, NULL,
217 (void **)&velocity));
218
219 PetscCall(ParticleDataProcessingPipeline(user, &pps));
220 PetscCall(DMSwarmGetLocalSize(user->swarm, &source_local));
221 PetscCall(DMSwarmGetSize(user->swarm, &source_global));
222 PetscCall(DMSwarmGetLocalSize(user->post_swarm, &post_local));
223 PetscCall(DMSwarmGetSize(user->post_swarm, &post_global));
224 PetscCall(PicurvAssertIntEqual(source_local, post_local,
225 "derived particle fields must share source local ownership"));
226 PetscCall(PicurvAssertIntEqual(source_global, post_global,
227 "derived and source swarms must have the same global size"));
228
229 PetscCall(DMSwarmGetField(user->post_swarm, "ske", NULL, NULL, (void **)&ske));
230 for (PetscInt p = 0; p < source_local; ++p) {
231 const PetscReal tag = (PetscReal)(offset + p + 1);
232 const PetscReal expected = 0.5 * (tag * tag + 5.0);
233
234 local_error = PetscMax(local_error,
235 PetscAbsReal(PetscRealPart(ske[p]) - expected));
236 }
237 PetscCall(DMSwarmRestoreField(user->post_swarm, "ske", NULL, NULL, (void **)&ske));
238 PetscCall(AssertGlobalError(local_error, 1.0e-12,
239 "specific kinetic energy must match every source particle"));
240
241 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
242 PetscFunctionReturn(0);
243}
PetscErrorCode ParticleDataProcessingPipeline(UserCtx *user, PostProcessParams *pps)
Parses and executes the particle pipeline using a robust two-pass approach.
PetscErrorCode SetupPostProcessSwarm(UserCtx *user, PostProcessParams *pps)
Creates a new, dedicated DMSwarm for post-processing tasks.
PetscErrorCode PicurvCreateSwarmPair(UserCtx *user, PetscInt nlocal, const char *post_field_name)
Creates matched solver and post-processing swarms for tests.
DM post_swarm
Definition variables.h:990
char particle_pipeline[1024]
Definition variables.h:610
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestResizeSwarmGloballyBalanced()

static PetscErrorCode TestResizeSwarmGloballyBalanced ( void  )
static

Checks that global resizing produces one balanced global population.

Definition at line 246 of file test_post_compute_mpi.c.

247{
248 SimCtx *simCtx = NULL;
249 UserCtx *user = NULL;
250 PetscMPIInt rank = 0, size = 1;
251 const PetscInt targets[] = {7, 3, 9, 0};
252
253 PetscFunctionBeginUser;
254 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
255 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
256 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
257 PetscCall(PicurvCreateSwarmPair(user, 0, "unused"));
258
259 for (size_t target_index = 0;
260 target_index < sizeof(targets) / sizeof(targets[0]); ++target_index) {
261 PetscInt local = 0;
262 PetscInt global = 0;
263 const PetscInt target = targets[target_index];
264 const PetscInt expected_local =
265 target / size + (rank < target % size ? 1 : 0);
266
267 PetscCall(ResizeSwarmGlobally(user->swarm, target));
268 PetscCall(DMSwarmGetLocalSize(user->swarm, &local));
269 PetscCall(DMSwarmGetSize(user->swarm, &global));
270 PetscCall(PicurvAssertIntEqual(expected_local, local,
271 "global swarm resize must use balanced local sizes"));
272 PetscCall(PicurvAssertIntEqual(target, global,
273 "global swarm resize must conserve the requested total"));
274 }
275
276 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
277 PetscFunctionReturn(0);
278}
PetscErrorCode ResizeSwarmGlobally(DM swarm, PetscInt N_target)
Resizes a swarm collectively to a target global particle count.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestFieldStatisticsDerivedNodalMultiRank()

static PetscErrorCode TestFieldStatisticsDerivedNodalMultiRank ( void  )
static

Exercises accumulator-to-derived-nodal field statistics across ownership boundaries.

Definition at line 281 of file test_post_compute_mpi.c.

282{
283 SimCtx *simCtx = NULL;
284 UserCtx *user = NULL;
285 PicurvWindowDefinition definition;
286 PicurvWindow window;
287 PicurvWindowStorage storage;
288 PetscReal ***pressure = NULL;
289 const PetscReal ***nodal = NULL;
290 Vec result = NULL;
291 PetscInt components = 0;
292 PetscInt local_checked = 0;
293 PetscInt global_checked = 0;
294 PetscReal local_error = 0.0;
296
297 PetscFunctionBeginUser;
298 PetscCall(PetscMemzero(&definition, sizeof(definition)));
299 PetscCall(PetscStrncpy(definition.name, "analytic", sizeof(definition.name)));
302 definition.step_cadence = 1;
303 definition.field_count = 1;
304 definition.fields[0].field_id = FIELD_ID_P;
305
306 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 8, 6, 4));
307 PetscCall(VecSet(user->Nvert, 0.0));
308 PetscCall(PicurvWindowInit(&window, &definition));
309 PetscCall(PicurvWindowStorageCreate(user, &definition, &storage));
310 simCtx->fieldStatisticsEnabled = PETSC_TRUE;
311 simCtx->fieldStatisticsWindowCount = 1;
312 simCtx->fieldStatisticsWindows = &window;
313 user->fieldStatisticsStorage = &storage;
314
315 PetscCall(DMDAVecGetArray(user->da, user->P, &pressure));
316 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k)
317 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j)
318 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i)
319 pressure[k][j][i] = ScalarValue(i, j, k);
320 PetscCall(DMDAVecRestoreArray(user->da, user->P, &pressure));
321 PetscCall(PicurvWindowAccumulate(user, &definition, &storage, 1.0));
322 PetscCall(ComputeWindowStatisticNodal(user, 0, "mean", 0, name, sizeof(name),
323 &result, &components));
324 PetscCall(PicurvAssertIntEqual(1, components,
325 "the pressure mean must derive as a scalar field"));
326 PetscCall(PicurvAssertBool((PetscBool)(result == user->PostScalarNodal),
327 "the pressure mean must use the scalar nodal staging vector"));
328
329 PetscCall(DMDAVecGetArrayRead(user->da, result, &nodal));
330 for (PetscInt k = PetscMax(user->info.zs, 1);
331 k < PetscMin(user->info.zs + user->info.zm, user->info.mz - 2); ++k) {
332 for (PetscInt j = PetscMax(user->info.ys, 1);
333 j < PetscMin(user->info.ys + user->info.ym, user->info.my - 2); ++j) {
334 for (PetscInt i = PetscMax(user->info.xs, 1);
335 i < PetscMin(user->info.xs + user->info.xm, user->info.mx - 2); ++i) {
336 local_error = PetscMax(
337 local_error,
338 PetscAbsReal(nodal[k][j][i] - (ScalarValue(i, j, k) + 55.5)));
339 ++local_checked;
340 }
341 }
342 }
343 PetscCall(DMDAVecRestoreArrayRead(user->da, result, &nodal));
344 PetscCallMPI(MPI_Allreduce(&local_checked, &global_checked, 1, MPIU_INT, MPI_SUM,
345 PETSC_COMM_WORLD));
346 PetscCall(PicurvAssertIntEqual((user->IM - 2) * (user->JM - 2) * (user->KM - 2),
347 global_checked,
348 "the derived mean must cover every fully resolved nodal point"));
349 PetscCall(AssertGlobalError(local_error, 1.0e-12,
350 "field-statistics nodal derivation must cross rank interfaces"));
351
352 simCtx->fieldStatisticsEnabled = PETSC_FALSE;
353 simCtx->fieldStatisticsWindowCount = 0;
354 simCtx->fieldStatisticsWindows = NULL;
355 user->fieldStatisticsStorage = NULL;
356 PetscCall(PicurvWindowStorageDestroy(&storage));
357 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
358 PetscFunctionReturn(0);
359}
@ FIELD_ID_P
PetscErrorCode ComputeWindowStatisticNodal(UserCtx *user, PetscInt window_index, const char *outputs, PetscInt output_index, char *out_name, size_t name_size, Vec *out_vec, PetscInt *out_components)
Derives one accumulated statistic and converts it to nodal values.
#define PICURV_STATISTICS_PAYLOAD_NAME_LENGTH
Maximum stored length of a payload name, including the terminator.
PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage)
Allocates the accumulator state one window owns on one block.
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.
Independent accumulator state for one window on one block.
PicurvWindowFieldRequest fields[16]
PicurvCadenceKind cadence_kind
PetscInt step_cadence
Used when cadence_kind is step; must be positive.
PetscErrorCode PicurvWindowInit(PicurvWindow *window, const PicurvWindowDefinition *definition)
Validates a definition and initializes a window to the pending state.
PetscInt field_id
Catalogued Eulerian field identity.
@ PICURV_WEIGHTING_SAMPLE
Equal weight per accepted state.
@ PICURV_CADENCE_STEP
Every n completed steps from activation.
Runtime state of one window.
The scientifically immutable definition of one window.
PetscInt fieldStatisticsWindowCount
Definition variables.h:770
Vec PostScalarNodal
Definition variables.h:949
PetscBool fieldStatisticsEnabled
Definition variables.h:769
struct PicurvWindow * fieldStatisticsWindows
Definition variables.h:771
struct PicurvWindowStorage * fieldStatisticsStorage
Definition variables.h:952
Vec Nvert
Definition variables.h:929
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 serial/MPI post-processing compute regression suite.

Definition at line 362 of file test_post_compute_mpi.c.

363{
364 PetscErrorCode ierr;
365 const PicurvTestCase cases[] = {
366 {"eulerian-pipeline-decomposition-independent", TestEulerianPipelineDecompositionIndependent},
367 {"particle-pipeline-matches-source-ownership", TestParticlePipelineMatchesSourceOwnership},
368 {"resize-swarm-globally-balanced", TestResizeSwarmGloballyBalanced},
369 {"field-statistics-derived-nodal-multi-rank", TestFieldStatisticsDerivedNodalMultiRank},
370 };
371
372 ierr = PetscInitialize(&argc, &argv, NULL,
373 "PICurv serial/MPI post-processing compute tests");
374 if (ierr) return (int)ierr;
375 ierr = PicurvRunTests("unit-post-compute-mpi", cases,
376 sizeof(cases) / sizeof(cases[0]));
377 if (ierr) {
378 PetscFinalize();
379 return (int)ierr;
380 }
381 ierr = PetscFinalize();
382 return (int)ierr;
383}
static PetscErrorCode TestResizeSwarmGloballyBalanced(void)
Checks that global resizing produces one balanced global population.
static PetscErrorCode TestFieldStatisticsDerivedNodalMultiRank(void)
Exercises accumulator-to-derived-nodal field statistics across ownership boundaries.
static PetscErrorCode TestParticlePipelineMatchesSourceOwnership(void)
Verifies the production-created derived swarm mirrors source ownership.
static PetscErrorCode TestEulerianPipelineDecompositionIndependent(void)
Exercises every Eulerian transformation currently dispatched by the pipeline.
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:

Variable Documentation

◆ kSentinel

const PetscReal kSentinel = -9876.5
static

Definition at line 12 of file test_post_compute_mpi.c.