PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
statistics_accumulator.h
Go to the documentation of this file.
1/**
2 * @file statistics_accumulator.h
3 * @brief Per-window PETSc accumulator storage and pointwise application.
4 *
5 * Holds the independent state each named window owns, and applies one accepted
6 * completed state to it, per
7 * @ref 60_Field_Statistics_Phase2_Implementation_Specification sections 5 and 13.
8 *
9 * Storage is allocated once by the vector factory and released once at teardown.
10 * Application is strictly pointwise: it reads a source field value at an owned
11 * point and updates that point's accumulator, so it performs no halo exchange and
12 * allocates nothing.
13 */
14
15#ifndef PICURV_STATISTICS_ACCUMULATOR_H
16#define PICURV_STATISTICS_ACCUMULATOR_H
17
18#include "variables.h"
19#include "statistics_window.h"
20
21/**
22 * @brief Independent accumulator state for one window on one block.
23 *
24 * Per-point occupancy is tracked separately from the field moments because the
25 * fluid mask can move: a point contributes only to the states in which it was
26 * valid, so its own count and weight are what normalize its moments.
27 *
28 * Every product is one vector carrying all of its components, not one vector per
29 * component. A symmetric second-order tensor is a single object: splitting it would
30 * cost six memory streams in the per-step accumulation loop instead of one cache
31 * line, and six collective gathers per checkpoint instead of one. Component counts
32 * that neither `da` nor `fda` provides are carried by a DM mirroring the block
33 * decomposition at that degree of freedom.
34 */
35typedef struct PicurvWindowStorage {
36 PetscInt field_count; /**< Fields accumulated. */
37 PetscInt covariance_count; /**< Covariance pairs accumulated. */
38 Vec count; /**< Per-point accepted sample count. */
39 Vec weight; /**< Per-point valid weight. */
40 Vec weight_sq; /**< Per-point squared-weight sum. */
41 Vec *mean; /**< One per field, matching that field's layout. */
42 Vec *m2; /**< One per field; NULL when no second moment was requested. */
43 Vec *cm; /**< One per covariance pair. */
45
46/** @brief Maximum stored length of a payload name, including the terminator. */
47#define PICURV_STATISTICS_PAYLOAD_NAME_LENGTH 96
48
49/**
50 * @brief One checkpointable accumulator vector, resolved by enumeration index.
51 *
52 * The enumeration order is the persistence contract: the manifest inventory, the
53 * checkpoint writer, and the restart reader all walk it identically, so a payload
54 * lands in the vector it came from without a separate lookup table.
55 */
56typedef struct {
57 char name[PICURV_STATISTICS_PAYLOAD_NAME_LENGTH]; /**< File basename, no extension. */
58 Vec vec; /**< Borrowed accumulator vector; never owned by the caller. */
59 PetscInt components; /**< Degrees of freedom the vector carries. */
60 const char *role; /**< Inventory role: occupancy, mean, second_moment, co_moment. */
61 const char *layout; /**< Catalog layout name for the inventory entry. */
63
64/**
65 * @brief Reports how many checkpointable vectors one window's storage holds.
66 * @param[in] storage Storage to measure.
67 * @param[out] count Payload count, including the three occupancy vectors.
68 * @return Zero on success, or `PETSC_ERR_ARG_NULL` for a null argument.
69 */
70PetscErrorCode PicurvWindowStoragePayloadCount(const PicurvWindowStorage *storage, PetscInt *count);
71
72/**
73 * @brief Resolves one enumerated payload of a window's storage.
74 *
75 * Names are derived from catalogued field names and fixed component suffixes, so
76 * they are stable across runs, rank counts, and configuration reorderings.
77 *
78 * @param[in] user Block context the storage belongs to.
79 * @param[in] definition Window definition naming the accumulated fields and pairs.
80 * @param[in] storage Storage to enumerate.
81 * @param[in] index Payload index in `[0, count)`.
82 * @param[out] payload Resolved payload; the vector is borrowed, not duplicated.
83 * @return Zero on success, or `PETSC_ERR_ARG_OUTOFRANGE` for an index outside the range.
84 */
85PetscErrorCode PicurvWindowStoragePayload(UserCtx *user, const PicurvWindowDefinition *definition,
86 const PicurvWindowStorage *storage, PetscInt index,
88
89/**
90 * @brief Resolves the DM carrying a given number of accumulator components.
91 *
92 * Component counts of one and three reuse the DMs the block already owns; six is
93 * carried by the symmetric-tensor DM created alongside them. Every one of these
94 * mirrors the block decomposition exactly, so a pointwise loop can read a source
95 * field and write an accumulator at the same index.
96 *
97 * @param[in] user Block context owning the DMs.
98 * @param[in] components Component count to place.
99 * @param[out] dm Resolved DM; borrowed, never destroyed by the caller.
100 * @return Zero on success, or `PETSC_ERR_ARG_OUTOFRANGE` for an unsupported count.
101 */
102PetscErrorCode PicurvStatisticsComponentDM(UserCtx *user, PetscInt components, DM *dm);
103
104/**
105 * @brief Reports how many symmetric product components a field's second moment needs.
106 * @param[in] dof Degree of freedom of the field.
107 * @param[out] count Component count: one for a scalar, six for a three-vector.
108 * @return Zero on success, or `PETSC_ERR_ARG_OUTOFRANGE` for an unsupported dof.
109 */
110PetscErrorCode PicurvProductComponentCount(PetscInt dof, PetscInt *count);
111
112/**
113 * @brief Reports how many components a covariance between two fields needs.
114 * @param[in] dof_a Degree of freedom of the first member.
115 * @param[in] dof_b Degree of freedom of the second member.
116 * @param[out] count Component count.
117 * @return Zero on success, or `PETSC_ERR_ARG_OUTOFRANGE` for an unsupported pairing.
118 */
119PetscErrorCode PicurvCovarianceComponentCount(PetscInt dof_a, PetscInt dof_b, PetscInt *count);
120
121/**
122 * @brief Allocates the accumulator state one window owns on one block.
123 *
124 * Every vector is duplicated from one the factory already built, so no new DM or
125 * layout decision is introduced.
126 *
127 * @param[in] user Block context supplying the source fields.
128 * @param[in] definition Window definition naming the requested fields and pairs.
129 * @param[out] storage Storage to populate; zeroed on entry.
130 * @return Zero on success, or a PETSc error for an unknown field or unsupported layout.
131 */
132PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition,
133 PicurvWindowStorage *storage);
134
135/**
136 * @brief Releases accumulator state previously created for one window.
137 * @param[in,out] storage Storage to release; safe to call on zeroed storage.
138 * @return Zero on success.
139 */
140PetscErrorCode PicurvWindowStorageDestroy(PicurvWindowStorage *storage);
141
142/** @brief Tolerance within which a negative variance is treated as floating-point noise. */
143#define PICURV_STATISTICS_VARIANCE_FLOOR 1.0e-12
144
145/** @brief One derived output field, resolved by enumeration index. */
146typedef struct {
147 char name[PICURV_STATISTICS_PAYLOAD_NAME_LENGTH]; /**< Output field name, window qualified. */
148 PetscInt components; /**< One or three. */
150
151/**
152 * @brief Reports how many derived fields a requested output set produces.
153 * @param[in] definition Window definition naming the accumulated fields and pairs.
154 * @param[in] storage Accumulator state the outputs are derived from.
155 * @param[in] outputs Comma-separated output kinds: mean, reynolds_stress, rms, tke, flux.
156 * @param[out] count Number of derived fields.
157 * @return Zero on success, or `PETSC_ERR_ARG_WRONG` for an unknown output kind.
158 */
159PetscErrorCode PicurvWindowDerivedCount(const PicurvWindowDefinition *definition,
160 const PicurvWindowStorage *storage,
161 const char *outputs, PetscInt *count);
162
163/**
164 * @brief Derives one output field from centered accumulator state.
165 *
166 * Normalizes in exactly one place: `R_ij = C_ij / W`, `RMS_i = sqrt(R_ii)`,
167 * `k = (R_xx + R_yy + R_zz) / 2`, and a flux is the co-moment over the same weight.
168 * Each uses the moment kernels rather than repeating the division, so the online and
169 * offline halves of the pipeline cannot disagree about what centered state means.
170 *
171 * A variance that comes out slightly negative through floating-point cancellation is
172 * clamped only where a square root would otherwise fail, and only within
173 * `PICURV_STATISTICS_VARIANCE_FLOOR`. Stored state is never modified.
174 *
175 * Points the window never sampled are left at zero rather than divided by a zero
176 * weight; the valid-fraction range reports how much of the domain that covers.
177 *
178 * @param[in] user Block context supplying the target domain.
179 * @param[in] definition Window definition.
180 * @param[in] storage Accumulator state to read.
181 * @param[in] outputs Comma-separated output kinds.
182 * @param[in] index Derived field index in `[0, count)`.
183 * @param[out] scalar_target Scalar destination, used when the field has one component.
184 * @param[out] vector_target Vector destination, used when the field has three.
185 * @param[out] field Resolved name and component count of the derived field.
186 * @return Zero on success, or a PETSc error.
187 */
188PetscErrorCode PicurvWindowDerive(UserCtx *user, const PicurvWindowDefinition *definition,
189 const PicurvWindowStorage *storage, const char *outputs,
190 PetscInt index, Vec scalar_target, Vec vector_target,
191 PicurvDerivedField *field);
192
193/**
194 * @brief Reports the spatial mean of a derived field over the points a window sampled.
195 *
196 * The average is taken over targeted points that actually accumulated weight, not
197 * over the whole vector. A derived field is zero everywhere outside the target
198 * domain and at any point the mask never admitted, and those zeros are absences
199 * rather than measurements: including them would scale the answer down by the
200 * fraction of the vector the window never covered.
201 *
202 * Performs a collective reduction, so callers use it for reporting rather than per
203 * point.
204 *
205 * @param[in] user Block context supplying the target domain.
206 * @param[in] definition Window definition naming the accumulated fields.
207 * @param[in] storage Accumulator state supplying per-point occupancy.
208 * @param[in] field Derived field to average, on the cell-centred scalar DM.
209 * @param[out] mean Spatial mean; zero when the window sampled no point.
210 * @return Zero on success, or a PETSc error.
211 */
212PetscErrorCode PicurvWindowSpatialMean(UserCtx *user, const PicurvWindowDefinition *definition,
213 const PicurvWindowStorage *storage, Vec field,
214 PetscReal *mean);
215
216/**
217 * @brief Reports the range of per-point valid fraction across a window's domain.
218 *
219 * A point contributes only to the states in which the mask accepted it, so with a
220 * moving immersed body different points carry different sample counts. The ratio of
221 * a point's own count to the window's accepted-sample count is its valid fraction,
222 * and the range of that ratio is the window's mask-health indicator: a minimum of
223 * one means every point saw every state, and a minimum of zero means some point
224 * contributed nothing at all.
225 *
226 * Performs a collective reduction, so callers gate it on an already-active reporting
227 * path rather than calling it every step.
228 *
229 * @param[in] user Block context supplying the target domain and mask.
230 * @param[in] definition Window definition naming the accumulated fields.
231 * @param[in] storage Accumulator state to inspect.
232 * @param[in] sample_count Accepted states the window has recorded.
233 * @param[out] minimum Smallest valid fraction; one when no point is targeted.
234 * @param[out] maximum Largest valid fraction; zero when no point is targeted.
235 * @return Zero on success, or a PETSc error.
236 */
237PetscErrorCode PicurvWindowValidFractionRange(UserCtx *user, const PicurvWindowDefinition *definition,
238 const PicurvWindowStorage *storage, PetscInt sample_count,
239 PetscReal *minimum, PetscReal *maximum);
240
241/**
242 * @brief Applies one accepted completed state to a window's accumulators.
243 *
244 * Iterates the pointwise target domain, skipping points the mask rejects, and
245 * updates each point's occupancy and every requested moment and co-moment through
246 * the centered kernels.
247 *
248 * @param[in] user Block context supplying the source fields.
249 * @param[in] definition Window definition.
250 * @param[in,out] storage Accumulator state to update.
251 * @param[in] weight Weight the window assigned to this state; must be positive.
252 * @return Zero on success, or a PETSc error.
253 */
254PetscErrorCode PicurvWindowAccumulate(UserCtx *user, const PicurvWindowDefinition *definition,
255 PicurvWindowStorage *storage, PetscReal weight);
256
257#endif /* PICURV_STATISTICS_ACCUMULATOR_H */
Vec weight
Per-point valid weight.
PetscInt components
Degrees of freedom the vector carries.
PetscInt components
One or three.
PetscErrorCode PicurvProductComponentCount(PetscInt dof, PetscInt *count)
Reports how many symmetric product components a field's second moment needs.
#define PICURV_STATISTICS_PAYLOAD_NAME_LENGTH
Maximum stored length of a payload name, including the terminator.
Vec weight_sq
Per-point squared-weight sum.
PetscInt field_count
Fields accumulated.
PetscInt covariance_count
Covariance pairs accumulated.
PetscErrorCode PicurvWindowDerive(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, const char *outputs, PetscInt index, Vec scalar_target, Vec vector_target, PicurvDerivedField *field)
Derives one output field from centered accumulator state.
Vec * mean
One per field, matching that field's layout.
Vec vec
Borrowed accumulator vector; never owned by the caller.
PetscErrorCode PicurvWindowDerivedCount(const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, const char *outputs, PetscInt *count)
Reports how many derived fields a requested output set produces.
PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage)
Allocates the accumulator state one window owns on one block.
PetscErrorCode PicurvCovarianceComponentCount(PetscInt dof_a, PetscInt dof_b, PetscInt *count)
Reports how many components a covariance between two fields needs.
PetscErrorCode PicurvWindowStoragePayload(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, PetscInt index, PicurvStatisticsPayload *payload)
Resolves one enumerated payload of a window's storage.
Vec * m2
One per field; NULL when no second moment was requested.
const char * role
Inventory role: occupancy, mean, second_moment, co_moment.
PetscErrorCode PicurvWindowValidFractionRange(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, PetscInt sample_count, PetscReal *minimum, PetscReal *maximum)
Reports the range of per-point valid fraction across a window's domain.
PetscErrorCode PicurvStatisticsComponentDM(UserCtx *user, PetscInt components, DM *dm)
Resolves the DM carrying a given number of accumulator components.
PetscErrorCode PicurvWindowSpatialMean(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, Vec field, PetscReal *mean)
Reports the spatial mean of a derived field over the points a window sampled.
Vec count
Per-point accepted sample count.
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.
const char * layout
Catalog layout name for the inventory entry.
PetscErrorCode PicurvWindowStoragePayloadCount(const PicurvWindowStorage *storage, PetscInt *count)
Reports how many checkpointable vectors one window's storage holds.
Vec * cm
One per covariance pair.
One derived output field, resolved by enumeration index.
One checkpointable accumulator vector, resolved by enumeration index.
Independent accumulator state for one window on one block.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
The scientifically immutable definition of one window.
Main header file for a complex fluid dynamics solver.
User-defined context containing data specific to a single computational grid level.
Definition variables.h:896