PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
test_post_compute_mpi.c
Go to the documentation of this file.
1/**
2 * @file test_post_compute_mpi.c
3 * @brief Decomposition-independent regression tests for post-processing compute.
4 */
5
6#include "test_support.h"
7
8#include "postprocessor.h"
10#include "statistics_window.h"
11
12static const PetscReal kSentinel = -9876.5;
13
14/** @brief Analytic scalar field used to expose misplaced or missing grid points. */
15static PetscReal ScalarValue(PetscInt i, PetscInt j, PetscInt k)
16{
17 return (PetscReal)(i + 10 * j + 100 * k);
18}
19
20/** @brief Requires every rank's maximum error to be within tolerance. */
21static PetscErrorCode AssertGlobalError(PetscReal local_error, PetscReal tolerance,
22 const char *context)
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}
32
33/** @brief Exercises every Eulerian transformation currently dispatched by the pipeline. */
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}
178
179/** @brief Verifies the production-created derived swarm mirrors source ownership. */
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}
249
250/** @brief Checks that global resizing produces one balanced global population. */
251static PetscErrorCode TestResizeSwarmGloballyBalanced(void)
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}
284
285/** @brief Exercises accumulator-to-derived-nodal field statistics across ownership boundaries. */
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}
365
366/** @brief Runs the serial/MPI post-processing compute regression suite. */
367int main(int argc, char **argv)
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}
PetscErrorCode ResizeSwarmGlobally(DM swarm, PetscInt N_target)
Resizes a swarm collectively to a target global particle count.
@ FIELD_ID_P
PetscErrorCode DimensionalizeField(UserCtx *user, const char *field_name)
Scales a specified field from non-dimensional to dimensional units in-place.
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.
PetscErrorCode EulerianDataProcessingPipeline(UserCtx *user, PostProcessParams *pps)
Parses the processing pipeline string and executes the requested kernels.
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.
Per-window PETSc accumulator storage and pointwise application.
#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.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
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.
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 const PetscReal kSentinel
static PetscReal ScalarValue(PetscInt i, PetscInt j, PetscInt k)
Analytic scalar field used to expose misplaced or missing grid points.
int main(int argc, char **argv)
Runs the serial/MPI post-processing compute regression suite.
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.
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 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 PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
PetscInt fieldStatisticsWindowCount
Definition variables.h:939
Vec P_nodal
Definition variables.h:1178
PetscInt KM
Definition variables.h:1087
PetscReal L_ref
Definition variables.h:848
DM post_swarm
Definition variables.h:1177
PetscInt reference[3]
Definition variables.h:805
Vec Ucat_nodal
Definition variables.h:1179
Vec PostScalarNodal
Definition variables.h:1133
PetscBool fieldStatisticsEnabled
Definition variables.h:938
Vec Qcrit
Definition variables.h:1180
struct PicurvWindow * fieldStatisticsWindows
Definition variables.h:940
char particle_pipeline[1024]
Definition variables.h:777
ScalingCtx scaling
Definition variables.h:954
PetscInt JM
Definition variables.h:1087
char process_pipeline[1024]
Definition variables.h:774
struct PicurvWindowStorage * fieldStatisticsStorage
Definition variables.h:1136
DMDALocalInfo info
Definition variables.h:1085
PostProcessParams * pps
Definition variables.h:1057
PetscInt IM
Definition variables.h:1087
Vec Nvert
Definition variables.h:1113
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