PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
statistics_target.h
Go to the documentation of this file.
1/**
2 * @file statistics_target.h
3 * @brief Spatial target resolution for the field-statistics pipeline.
4 *
5 * Implements the pointwise identity mapping described in @ref p58_target_sec. The
6 * abstraction exists with only that one mapping so later spatial bins, profiles,
7 * regions, and surfaces extend it rather than retrofit it; see
8 * @ref 60_Field_Statistics_Planned_Extensions.
9 *
10 * The central responsibility is producing an iteration domain that excludes two
11 * distinct categories which @ref 56_Field_Identity_and_Layout_Catalog section 4
12 * warns must not be conflated:
13 *
14 * 1. PETSc/MPI halo entries created by DMDA decomposition, and
15 * 2. solver-layout boundary, dummy, or duplicate-periodic indices, which exist
16 * even on a single MPI rank.
17 *
18 * Nothing here resolves field identity or layout metadata itself; that comes
19 * from the typed catalog through `FieldGetDescriptor`.
20 */
21
22#ifndef PICURV_STATISTICS_TARGET_H
23#define PICURV_STATISTICS_TARGET_H
24
25#include "variables.h"
26#include "field_catalog.h"
27
28/** @brief Threshold below which a cell counts as fluid for the default mask. */
29#define PICURV_STATISTICS_FLUID_THRESHOLD 0.1
30
31/** @brief Spatial mapping kind. Only the pointwise identity is implemented. */
35
36/** @brief Point-eligibility mask. Only the fluid mask is implemented. */
40
41/**
42 * @brief Resolved iteration domain for one field on one block.
43 *
44 * Bounds are half-open `[start, end)` in DMDA index order `(i, j, k)` and are
45 * already intersected with this rank's owned range, so iterating them touches
46 * neither halo storage nor layout boundary/dummy/duplicate-periodic indices.
47 * An empty domain on a rank is represented by `end[d] <= start[d]`.
48 */
49typedef struct {
50 PicurvTargetKind kind; /**< Spatial mapping; always pointwise. */
51 PicurvStatisticsMask mask; /**< Point-eligibility mask. */
52 const FieldDescriptor *descriptor; /**< Catalog metadata for the targeted field. */
53 PetscInt start[3]; /**< Inclusive start per dimension (i, j, k). */
54 PetscInt end[3]; /**< Exclusive end per dimension (i, j, k). */
56
57/**
58 * @brief Reports whether a layout is node-like in one dimension.
59 *
60 * Node-like dimensions carry one more physical entry than cell-like dimensions,
61 * because they sit on grid lines rather than between them. `I_FACE` is node-like
62 * in i and cell-like in j and k, and correspondingly for the other face
63 * families.
64 *
65 * @param[in] layout Catalog layout.
66 * @param[in] dim Dimension index: 0 for i, 1 for j, 2 for k.
67 * @param[out] node_like Resolved classification.
68 * @return Zero on success, or `PETSC_ERR_ARG_OUTOFRANGE` for an invalid
69 * dimension, or `PETSC_ERR_ARG_WRONGSTATE` for a component-staggered
70 * layout, whose components do not share one classification.
71 */
72PetscErrorCode PicurvLayoutDimensionIsNodeLike(FieldLayout layout, PetscInt dim, PetscBool *node_like);
73
74/**
75 * @brief Resolves the iteration domain for one field on one block.
76 *
77 * Rejects component-staggered fields, whose x, y, and z components live on
78 * different face families and therefore cannot share a single pointwise domain.
79 * Configured statistics request only cell-centered fields, but the plan resolves
80 * node and face layouts correctly so later phases inherit a verified contract.
81 *
82 * @param[in] user Block context supplying the DMDA layout and periodicity.
83 * @param[in] field_id Catalogued field to target.
84 * @param[in] mask Point-eligibility mask.
85 * @param[out] plan Resolved plan.
86 * @return Zero on success, or a PETSc error for a null argument, an unknown
87 * field, or an unsupported layout.
88 */
89PetscErrorCode SpatialTargetPlanCreate(UserCtx *user, FieldId field_id,
91
92/**
93 * @brief Counts the points this rank contributes.
94 * @param[in] plan Resolved plan.
95 * @param[out] count Local point count; zero for an empty domain.
96 * @return Zero on success, or `PETSC_ERR_ARG_NULL` for a null argument.
97 */
98PetscErrorCode SpatialTargetPlanLocalPointCount(const SpatialTargetPlan *plan, PetscInt *count);
99
100/**
101 * @brief Counts the points contributed across a communicator.
102 *
103 * The result is decomposition independent: it depends only on the layout,
104 * global dimensions, and periodicity, never on how ranks divide the domain.
105 *
106 * @param[in] plan Resolved plan.
107 * @param[in] comm Communicator to reduce over.
108 * @param[out] count Global point count.
109 * @return Zero on success, or `PETSC_ERR_ARG_NULL` for a null argument.
110 */
111PetscErrorCode SpatialTargetPlanGlobalPointCount(const SpatialTargetPlan *plan, MPI_Comm comm, PetscInt *count);
112
113/**
114 * @brief Reports whether a point passes the plan's mask.
115 *
116 * Because `Nvert` changes when immersed bodies move, the mask is treated as
117 * potentially moving: callers accumulate a per-point valid count and weight
118 * rather than assuming a point contributes to every accepted state.
119 *
120 * @param[in] plan Resolved plan.
121 * @param[in] nvert_value Node-blanking value at the point.
122 * @return `PETSC_TRUE` when the point is eligible.
123 */
124PetscBool SpatialTargetPlanMaskAllows(const SpatialTargetPlan *plan, PetscReal nvert_value);
125
126/** @brief Largest reduction buffer a directional average will allocate, in entries. */
127#define PICURV_SPATIAL_AVERAGE_MAX_BUFFER 4000000
128
129/**
130 * @brief Averages two fields over a target domain and divides the results.
131 *
132 * Computes `ratio = <numerator> / <denominator>`, where each average is taken
133 * separately over the points the plan admits, and then divides. The order matters:
134 * the mean of the pointwise quotients is a different number from the quotient of the
135 * means, and several callers need the second one. The LES dynamic procedure is one,
136 * because Lilly's least-squares closure is defined that way.
137 *
138 * `average_direction` selects which logical directions collapse into the average.
139 * Selecting none makes the operation pointwise, which lets a caller express a local
140 * and an averaged formulation through one code path rather than two. Selecting all
141 * three yields one number for the whole domain. Selecting a subset retains a profile
142 * along the directions left out — averaging over xi and zeta on a plane channel, for
143 * example, leaves a wall-normal profile.
144 *
145 * Weighting is the caller's, not this function's: scale @p numerator and
146 * @p denominator by whatever weight the average should carry before calling. A
147 * caller wanting a volume-weighted average multiplies both by the cell volume; a
148 * caller wanting each admitted point to count once passes them unscaled.
149 *
150 * The reduction runs over @p comm, so a result is independent of how the domain is
151 * decomposed across ranks. The plan already excludes PETSc halo storage and the
152 * solver's boundary, dummy, and duplicate-periodic indices, so no physical point is
153 * counted twice.
154 *
155 * @param[in] user Block context supplying the DMDA and the solid mask.
156 * @param[in] plan Resolved iteration domain, from `SpatialTargetPlanCreate()`.
157 * @param[in] numerator Ghosted local field to average in the numerator.
158 * @param[in] denominator Ghosted local field to average in the denominator, or NULL
159 * to divide by the number of admitted points.
160 * @param[in] inclusion Optional second mask: points where this field is not
161 * positive are skipped. Use it to exclude points that hold a
162 * zero meaning "never measured" rather than a measurement.
163 * NULL applies the plan's mask alone.
164 * @param[in] average_direction Directions to average over, in `(xi, eta, zeta)` order.
165 * @param[in] comm Communicator to reduce over.
166 * @param[out] ratio Ghosted local field receiving the quotient, or NULL when only
167 * the scalar is wanted. Zero wherever the averaged denominator
168 * underflows.
169 * @param[out] scalar Receives the single averaged value, or NULL. Valid only when
170 * every direction is averaged, since otherwise there is no
171 * single value to report.
172 * @return Zero on success, `PETSC_ERR_ARG_OUTOFRANGE` when the retained directions
173 * would need an unreasonably large reduction buffer, or
174 * `PETSC_ERR_ARG_WRONGSTATE` when a scalar is requested from a result that
175 * still varies in space.
176 */
177PetscErrorCode PicurvSpatialRatioAverage(UserCtx *user, const SpatialTargetPlan *plan,
178 Vec numerator, Vec denominator, Vec inclusion,
179 const PetscBool average_direction[3], MPI_Comm comm,
180 Vec ratio, PetscReal *scalar);
181
182#endif /* PICURV_STATISTICS_TARGET_H */
Authoritative identities and storage metadata for persistent Eulerian fields.
FieldLayout
Logical storage topology of a field.
FieldId
Compile-time identity for a catalogued Eulerian field.
Immutable metadata for one field identity.
PetscBool SpatialTargetPlanMaskAllows(const SpatialTargetPlan *plan, PetscReal nvert_value)
Reports whether a point passes the plan's mask.
PicurvTargetKind kind
Spatial mapping; always pointwise.
PicurvTargetKind
Spatial mapping kind.
@ PICURV_TARGET_POINTWISE
PicurvStatisticsMask
Point-eligibility mask.
@ 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.
PetscErrorCode PicurvLayoutDimensionIsNodeLike(FieldLayout layout, PetscInt dim, PetscBool *node_like)
Reports whether a layout is node-like in one dimension.
const FieldDescriptor * descriptor
Catalog metadata for the targeted field.
PicurvStatisticsMask mask
Point-eligibility mask.
Resolved iteration domain for one field on one block.
Main header file for a complex fluid dynamics solver.
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1073