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.rho_ref = 2.0;
64 simCtx->scaling.P_ref = 2.0;
65
66 PetscCall(DMDAVecGetArray(user->da, user->P, &pressure));
67 PetscCall(DMDAVecGetArray(user->fda, user->Ucat, &velocity));
68 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k) {
69 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j) {
70 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i) {
71 pressure[k][j][i] = ScalarValue(i, j, k);
72 velocity[k][j][i] = (Cmpnts){1.0, 2.0, 3.0};
73 }
74 }
75 }
76 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucat, &velocity));
77 PetscCall(DMDAVecRestoreArray(user->da, user->P, &pressure));
78 PetscCall(VecSet(user->P_nodal, kSentinel));
79 PetscCall(VecSet(user->Ucat_nodal, kSentinel));
80 PetscCall(VecSet(user->Qcrit, kSentinel));
81
82 /* A dimensionalizing post-processor scales pressure as it is loaded, by rho U^2 = 2,
83 * before the pipeline runs; normalization is linear, so the expected values are
84 * the same whichever of the two is applied first. */
85 PetscCall(DimensionalizeField(user, "P"));
86 PetscCall(PetscStrncpy(
88 "NormalizeRelativeField:P;"
89 "CellToNodeAverage:P>P_nodal;CellToNodeAverage:Ucat>Ucat_nodal;"
90 "ComputeQCriterion",
91 sizeof(pps->process_pipeline)));
92 PetscCall(EulerianDataProcessingPipeline(user, pps));
93
94 PetscCall(DMDAVecGetArrayRead(user->da, user->P, &pressure_result));
95 PetscCall(DMDAVecGetArrayRead(user->da, user->P_nodal, &pressure_nodal));
96 PetscCall(DMDAVecGetArrayRead(user->fda, user->Ucat_nodal, &velocity_nodal));
97 PetscCall(DMDAVecGetArrayRead(user->da, user->Qcrit, &qcrit));
98 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k) {
99 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j) {
100 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i) {
101 const PetscBool physical_node =
102 (PetscBool)(i < user->info.mx - 1 && j < user->info.my - 1 &&
103 k < user->info.mz - 1);
104 const PetscBool q_point =
105 (PetscBool)(i >= 1 && i < user->info.mx - 1 &&
106 j >= 1 && j < user->info.my - 1 &&
107 k >= 1 && k < user->info.mz - 1);
108 const PetscReal expected_pressure = 2.0 * (ScalarValue(i, j, k) - 111.0);
109
110 pressure_error = PetscMax(
111 pressure_error,
112 PetscAbsReal(pressure_result[k][j][i] - expected_pressure));
113 if (physical_node) {
114 const PetscReal expected_nodal =
115 2.0 * (ScalarValue(i, j, k) + 55.5 - 111.0);
116
117 pressure_nodal_error = PetscMax(
118 pressure_nodal_error,
119 PetscAbsReal(pressure_nodal[k][j][i] - expected_nodal));
120 velocity_nodal_error = PetscMax(
121 velocity_nodal_error,
122 PetscAbsReal(velocity_nodal[k][j][i].x - 1.0));
123 velocity_nodal_error = PetscMax(
124 velocity_nodal_error,
125 PetscAbsReal(velocity_nodal[k][j][i].y - 2.0));
126 velocity_nodal_error = PetscMax(
127 velocity_nodal_error,
128 PetscAbsReal(velocity_nodal[k][j][i].z - 3.0));
129 ++local_physical_nodes;
130 } else {
131 pressure_nodal_error = PetscMax(
132 pressure_nodal_error,
133 PetscAbsReal(pressure_nodal[k][j][i] - kSentinel));
134 velocity_nodal_error = PetscMax(
135 velocity_nodal_error,
136 PetscAbsReal(velocity_nodal[k][j][i].x - kSentinel));
137 velocity_nodal_error = PetscMax(
138 velocity_nodal_error,
139 PetscAbsReal(velocity_nodal[k][j][i].y - kSentinel));
140 velocity_nodal_error = PetscMax(
141 velocity_nodal_error,
142 PetscAbsReal(velocity_nodal[k][j][i].z - kSentinel));
143 }
144 qcrit_error = PetscMax(
145 qcrit_error,
146 PetscAbsReal(qcrit[k][j][i] - (q_point ? 0.0 : kSentinel)));
147 if (q_point) ++local_q_points;
148 }
149 }
150 }
151 PetscCall(DMDAVecRestoreArrayRead(user->da, user->Qcrit, &qcrit));
152 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Ucat_nodal, &velocity_nodal));
153 PetscCall(DMDAVecRestoreArrayRead(user->da, user->P_nodal, &pressure_nodal));
154 PetscCall(DMDAVecRestoreArrayRead(user->da, user->P, &pressure_result));
155
156 PetscCallMPI(MPI_Allreduce(&local_physical_nodes, &global_physical_nodes, 1,
157 MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
158 PetscCallMPI(MPI_Allreduce(&local_q_points, &global_q_points, 1,
159 MPIU_INT, MPI_SUM, PETSC_COMM_WORLD));
160 PetscCall(PicurvAssertIntEqual(user->IM * user->JM * user->KM,
161 global_physical_nodes,
162 "the Eulerian pipeline must visit every physical node exactly once"));
163 PetscCall(PicurvAssertIntEqual((user->IM - 1) * (user->JM - 1) * (user->KM - 1),
164 global_q_points,
165 "Q-criterion must visit every interior cell exactly once"));
166 PetscCall(AssertGlobalError(pressure_error, 1.0e-12,
167 "pressure normalization and dimensionalization are decomposition independent"));
168 PetscCall(AssertGlobalError(pressure_nodal_error, 1.0e-12,
169 "scalar nodal averaging covers rank interfaces and physical boundaries"));
170 PetscCall(AssertGlobalError(velocity_nodal_error, 1.0e-12,
171 "vector nodal averaging covers rank interfaces and physical boundaries"));
172 PetscCall(AssertGlobalError(qcrit_error, 1.0e-12,
173 "Q-criterion covers the complete distributed interior"));
174
175 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
176 PetscFunctionReturn(0);
177}
PetscErrorCode DimensionalizeField(UserCtx *user, const char *field_name)
Scales a specified field from non-dimensional to dimensional units in-place.
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:1178
PetscInt KM
Definition variables.h:1087
PetscReal L_ref
Definition variables.h:848
PetscInt reference[3]
Definition variables.h:805
Vec Ucat_nodal
Definition variables.h:1179
Vec Qcrit
Definition variables.h:1180
ScalingCtx scaling
Definition variables.h:954
PetscInt JM
Definition variables.h:1087
char process_pipeline[1024]
Definition variables.h:774
DMDALocalInfo info
Definition variables.h:1085
PostProcessParams * pps
Definition variables.h:1057
PetscInt IM
Definition variables.h:1087
PetscReal P_ref
Definition variables.h:851
PetscReal rho_ref
Definition variables.h:850
PetscReal U_ref
Definition variables.h:849
A 3D point or vector with PetscScalar components.
Definition variables.h:121
Holds all configuration parameters for a post-processing run.
Definition variables.h:761
The master context for the entire simulation.
Definition variables.h:866
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1073
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 180 of file test_post_compute_mpi.c.

181{
182 SimCtx *simCtx = NULL;
183 UserCtx *user = NULL;
185 PetscMPIInt rank = 0, size = 1;
186 PetscInt source_local = 0;
187 PetscInt source_global = 0;
188 PetscInt post_local = 0;
189 PetscInt post_global = 0;
190 PetscInt offset = 0;
191 PetscScalar (*velocity)[3] = NULL;
192 const PetscScalar *ske = NULL;
193 PetscReal local_error = 0.0;
194 const PetscInt total_particles = 7;
195
196 PetscFunctionBeginUser;
197 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
198 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
199 source_local = total_particles / size + (rank < total_particles % size ? 1 : 0);
200 PetscCall(PetscMemzero(&pps, sizeof(pps)));
201 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
202 PetscCall(PicurvCreateSwarmPair(user, source_local, "unused"));
203 PetscCall(DMDestroy(&user->post_swarm));
204 PetscCall(PetscStrncpy(pps.particle_pipeline, "ComputeSpecificKE:velocity>ske",
205 sizeof(pps.particle_pipeline)));
206 PetscCall(SetupPostProcessSwarm(user, &pps));
207
208 if (size > 1) {
209 PetscCallMPI(MPI_Exscan(&source_local, &offset, 1, MPIU_INT, MPI_SUM,
210 PETSC_COMM_WORLD));
211 if (rank == 0) offset = 0;
212 }
213 PetscCall(DMSwarmGetField(user->swarm, "velocity", NULL, NULL, (void **)&velocity));
214 for (PetscInt p = 0; p < source_local; ++p) {
215 const PetscReal tag = (PetscReal)(offset + p + 1);
216
217 velocity[p][0] = tag;
218 velocity[p][1] = 2.0;
219 velocity[p][2] = -1.0;
220 }
221 PetscCall(DMSwarmRestoreField(user->swarm, "velocity", NULL, NULL,
222 (void **)&velocity));
223
224 PetscCall(ParticleDataProcessingPipeline(user, &pps));
225 PetscCall(DMSwarmGetLocalSize(user->swarm, &source_local));
226 PetscCall(DMSwarmGetSize(user->swarm, &source_global));
227 PetscCall(DMSwarmGetLocalSize(user->post_swarm, &post_local));
228 PetscCall(DMSwarmGetSize(user->post_swarm, &post_global));
229 PetscCall(PicurvAssertIntEqual(source_local, post_local,
230 "derived particle fields must share source local ownership"));
231 PetscCall(PicurvAssertIntEqual(source_global, post_global,
232 "derived and source swarms must have the same global size"));
233
234 PetscCall(DMSwarmGetField(user->post_swarm, "ske", NULL, NULL, (void **)&ske));
235 for (PetscInt p = 0; p < source_local; ++p) {
236 const PetscReal tag = (PetscReal)(offset + p + 1);
237 const PetscReal expected = 0.5 * (tag * tag + 5.0);
238
239 local_error = PetscMax(local_error,
240 PetscAbsReal(PetscRealPart(ske[p]) - expected));
241 }
242 PetscCall(DMSwarmRestoreField(user->post_swarm, "ske", NULL, NULL, (void **)&ske));
243 PetscCall(AssertGlobalError(local_error, 1.0e-12,
244 "specific kinetic energy must match every source particle"));
245
246 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
247 PetscFunctionReturn(0);
248}
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:1177
char particle_pipeline[1024]
Definition variables.h:777
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 251 of file test_post_compute_mpi.c.

252{
253 SimCtx *simCtx = NULL;
254 UserCtx *user = NULL;
255 PetscMPIInt rank = 0, size = 1;
256 const PetscInt targets[] = {7, 3, 9, 0};
257
258 PetscFunctionBeginUser;
259 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
260 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
261 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
262 PetscCall(PicurvCreateSwarmPair(user, 0, "unused"));
263
264 for (size_t target_index = 0;
265 target_index < sizeof(targets) / sizeof(targets[0]); ++target_index) {
266 PetscInt local = 0;
267 PetscInt global = 0;
268 const PetscInt target = targets[target_index];
269 const PetscInt expected_local =
270 target / size + (rank < target % size ? 1 : 0);
271
272 PetscCall(ResizeSwarmGlobally(user->swarm, target));
273 PetscCall(DMSwarmGetLocalSize(user->swarm, &local));
274 PetscCall(DMSwarmGetSize(user->swarm, &global));
275 PetscCall(PicurvAssertIntEqual(expected_local, local,
276 "global swarm resize must use balanced local sizes"));
277 PetscCall(PicurvAssertIntEqual(target, global,
278 "global swarm resize must conserve the requested total"));
279 }
280
281 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
282 PetscFunctionReturn(0);
283}
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 286 of file test_post_compute_mpi.c.

287{
288 SimCtx *simCtx = NULL;
289 UserCtx *user = NULL;
290 PicurvWindowDefinition definition;
291 PicurvWindow window;
292 PicurvWindowStorage storage;
293 PetscReal ***pressure = NULL;
294 const PetscReal ***nodal = NULL;
295 Vec result = NULL;
296 PetscInt components = 0;
297 PetscInt local_checked = 0;
298 PetscInt global_checked = 0;
299 PetscReal local_error = 0.0;
301
302 PetscFunctionBeginUser;
303 PetscCall(PetscMemzero(&definition, sizeof(definition)));
304 PetscCall(PetscStrncpy(definition.name, "analytic", sizeof(definition.name)));
307 definition.step_cadence = 1;
308 definition.field_count = 1;
309 definition.fields[0].field_id = FIELD_ID_P;
310
311 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 8, 6, 4));
312 PetscCall(VecSet(user->Nvert, 0.0));
313 PetscCall(PicurvWindowInit(&window, &definition));
314 PetscCall(PicurvWindowStorageCreate(user, &definition, &storage));
315 simCtx->fieldStatisticsEnabled = PETSC_TRUE;
316 simCtx->fieldStatisticsWindowCount = 1;
317 simCtx->fieldStatisticsWindows = &window;
318 user->fieldStatisticsStorage = &storage;
319
320 PetscCall(DMDAVecGetArray(user->da, user->P, &pressure));
321 for (PetscInt k = user->info.zs; k < user->info.zs + user->info.zm; ++k)
322 for (PetscInt j = user->info.ys; j < user->info.ys + user->info.ym; ++j)
323 for (PetscInt i = user->info.xs; i < user->info.xs + user->info.xm; ++i)
324 pressure[k][j][i] = ScalarValue(i, j, k);
325 PetscCall(DMDAVecRestoreArray(user->da, user->P, &pressure));
326 PetscCall(PicurvWindowAccumulate(user, &definition, &storage, 1.0));
327 PetscCall(ComputeWindowStatisticNodal(user, 0, "mean", 0, name, sizeof(name),
328 &result, &components));
329 PetscCall(PicurvAssertIntEqual(1, components,
330 "the pressure mean must derive as a scalar field"));
331 PetscCall(PicurvAssertBool((PetscBool)(result == user->PostScalarNodal),
332 "the pressure mean must use the scalar nodal staging vector"));
333
334 PetscCall(DMDAVecGetArrayRead(user->da, result, &nodal));
335 for (PetscInt k = PetscMax(user->info.zs, 1);
336 k < PetscMin(user->info.zs + user->info.zm, user->info.mz - 2); ++k) {
337 for (PetscInt j = PetscMax(user->info.ys, 1);
338 j < PetscMin(user->info.ys + user->info.ym, user->info.my - 2); ++j) {
339 for (PetscInt i = PetscMax(user->info.xs, 1);
340 i < PetscMin(user->info.xs + user->info.xm, user->info.mx - 2); ++i) {
341 local_error = PetscMax(
342 local_error,
343 PetscAbsReal(nodal[k][j][i] - (ScalarValue(i, j, k) + 55.5)));
344 ++local_checked;
345 }
346 }
347 }
348 PetscCall(DMDAVecRestoreArrayRead(user->da, result, &nodal));
349 PetscCallMPI(MPI_Allreduce(&local_checked, &global_checked, 1, MPIU_INT, MPI_SUM,
350 PETSC_COMM_WORLD));
351 PetscCall(PicurvAssertIntEqual((user->IM - 2) * (user->JM - 2) * (user->KM - 2),
352 global_checked,
353 "the derived mean must cover every fully resolved nodal point"));
354 PetscCall(AssertGlobalError(local_error, 1.0e-12,
355 "field-statistics nodal derivation must cross rank interfaces"));
356
357 simCtx->fieldStatisticsEnabled = PETSC_FALSE;
358 simCtx->fieldStatisticsWindowCount = 0;
359 simCtx->fieldStatisticsWindows = NULL;
360 user->fieldStatisticsStorage = NULL;
361 PetscCall(PicurvWindowStorageDestroy(&storage));
362 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
363 PetscFunctionReturn(0);
364}
@ 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:939
Vec PostScalarNodal
Definition variables.h:1133
PetscBool fieldStatisticsEnabled
Definition variables.h:938
struct PicurvWindow * fieldStatisticsWindows
Definition variables.h:940
struct PicurvWindowStorage * fieldStatisticsStorage
Definition variables.h:1136
Vec Nvert
Definition variables.h:1113
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 367 of file test_post_compute_mpi.c.

368{
369 PetscErrorCode ierr;
370 const PicurvTestCase cases[] = {
371 {"eulerian-pipeline-decomposition-independent", TestEulerianPipelineDecompositionIndependent},
372 {"particle-pipeline-matches-source-ownership", TestParticlePipelineMatchesSourceOwnership},
373 {"resize-swarm-globally-balanced", TestResizeSwarmGloballyBalanced},
374 {"field-statistics-derived-nodal-multi-rank", TestFieldStatisticsDerivedNodalMultiRank},
375 };
376
377 ierr = PetscInitialize(&argc, &argv, NULL,
378 "PICurv serial/MPI post-processing compute tests");
379 if (ierr) return (int)ierr;
380 ierr = PicurvRunTests("unit-post-compute-mpi", cases,
381 sizeof(cases) / sizeof(cases[0]));
382 if (ierr) {
383 PetscFinalize();
384 return (int)ierr;
385 }
386 ierr = PetscFinalize();
387 return (int)ierr;
388}
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.