PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
statistics_target.c
Go to the documentation of this file.
1/**
2 * @file statistics_target.c
3 * @brief Spatial target resolution for the field-statistics pipeline.
4 *
5 * Full API contract is documented with the declarations in
6 * `include/statistics_target.h`.
7 */
8
9#include "statistics_target.h"
10
11/**
12 * @brief Implementation of \ref PicurvLayoutDimensionIsNodeLike().
13 * @see PicurvLayoutDimensionIsNodeLike()
14 */
15PetscErrorCode PicurvLayoutDimensionIsNodeLike(FieldLayout layout, PetscInt dim, PetscBool *node_like)
16{
17 PetscFunctionBeginUser;
18 PetscCheck(node_like != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
19 "Classification output is required.");
20 PetscCheck(dim >= 0 && dim < 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
21 "Dimension must be 0, 1, or 2; got %" PetscInt_FMT ".", dim);
22
23 switch (layout) {
25 *node_like = PETSC_TRUE;
26 break;
28 *node_like = PETSC_FALSE;
29 break;
31 *node_like = (PetscBool)(dim == 0);
32 break;
34 *node_like = (PetscBool)(dim == 1);
35 break;
37 *node_like = (PetscBool)(dim == 2);
38 break;
40 /* x, y, and z live on I-, J-, and K-faces respectively, so no single
41 * classification describes the packed vector. */
42 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
43 "Component-staggered layout has no single per-dimension classification.");
44 default:
45 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
46 "Unknown field layout %d.", (int)layout);
47 }
48 PetscFunctionReturn(0);
49}
50
51/**
52 * @brief Internal helper: resolves the layout-valid index span for one dimension.
53 * @details Local to this translation unit.
54 *
55 * The DMDA carries one extra high-side slot beyond the physical grid, and the
56 * solver's shifted convention places boundary/dummy values at index zero. Under
57 * periodicity the repair algorithms in `Boundaries.c` write index `0` and index
58 * `size-1` from the opposite side, so both are dependent duplicates and the
59 * independent span starts at one in every layout.
60 */
61static void ResolveLayoutSpan(PetscBool node_like, PetscBool periodic, PetscInt size,
62 PetscInt *lo, PetscInt *hi_exclusive)
63{
64 /* Node-like and non-periodic is the only case whose first physical entry
65 * sits at index zero; everywhere else index zero is a boundary, dummy, or
66 * periodic duplicate. */
67 *lo = (node_like && !periodic) ? 0 : 1;
68 /* The final slot is the DMDA's extra non-physical entry under every layout. */
69 *hi_exclusive = size - 1;
70}
71
72/**
73 * @brief Implementation of \ref SpatialTargetPlanCreate().
74 * @see SpatialTargetPlanCreate()
75 */
76PetscErrorCode SpatialTargetPlanCreate(UserCtx *user, FieldId field_id,
78{
79 const FieldDescriptor *descriptor = NULL;
80 const DMDALocalInfo *info = NULL;
81 SimCtx *simCtx = NULL;
82 PetscInt owned_start[3];
83 PetscInt owned_end[3];
84 PetscInt global_size[3];
85 PetscBool periodic[3];
86
87 PetscFunctionBeginUser;
88 PetscCheck(user != NULL && plan != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
89 "Block context and plan output are required.");
90 PetscCheck(mask == PICURV_STATISTICS_MASK_FLUID, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
91 "Only the fluid mask is implemented.");
92 simCtx = user->simCtx;
93 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
94 "Block context must carry a simulation context.");
95
96 PetscCall(FieldGetDescriptor(field_id, &descriptor));
97 PetscCheck(descriptor->layout != FIELD_LAYOUT_COMPONENT_STAGGERED,
98 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
99 "Field '%s' is component-staggered; its components live on different face "
100 "families and cannot share one pointwise target domain.",
101 descriptor->canonical_name);
102
103 info = &user->info;
104 owned_start[0] = info->xs; owned_end[0] = info->xs + info->xm; global_size[0] = info->mx;
105 owned_start[1] = info->ys; owned_end[1] = info->ys + info->ym; global_size[1] = info->my;
106 owned_start[2] = info->zs; owned_end[2] = info->zs + info->zm; global_size[2] = info->mz;
107 /* The simCtx flags are authoritative here because they are what selects
108 * DM_BOUNDARY_PERIODIC when the DMDA is built, and therefore what decides
109 * whether the end planes are wrapped duplicates. */
110 periodic[0] = (PetscBool)(simCtx->i_periodic != 0);
111 periodic[1] = (PetscBool)(simCtx->j_periodic != 0);
112 periodic[2] = (PetscBool)(simCtx->k_periodic != 0);
113
115 plan->mask = mask;
116 plan->descriptor = descriptor;
117
118 for (PetscInt dim = 0; dim < 3; ++dim) {
119 PetscBool node_like = PETSC_FALSE;
120 PetscInt layout_lo = 0;
121 PetscInt layout_hi = 0;
122
123 PetscCall(PicurvLayoutDimensionIsNodeLike(descriptor->layout, dim, &node_like));
124 ResolveLayoutSpan(node_like, periodic[dim], global_size[dim], &layout_lo, &layout_hi);
125
126 /* Intersect the layout-valid span with this rank's owned range: the
127 * first exclusion removes solver-layout indices, the second removes
128 * PETSc halo storage. */
129 plan->start[dim] = PetscMax(owned_start[dim], layout_lo);
130 plan->end[dim] = PetscMin(owned_end[dim], layout_hi);
131 if (plan->end[dim] < plan->start[dim]) plan->end[dim] = plan->start[dim];
132 }
133 PetscFunctionReturn(0);
134}
135
136/**
137 * @brief Implementation of \ref SpatialTargetPlanLocalPointCount().
138 * @see SpatialTargetPlanLocalPointCount()
139 */
140PetscErrorCode SpatialTargetPlanLocalPointCount(const SpatialTargetPlan *plan, PetscInt *count)
141{
142 PetscInt total = 1;
143
144 PetscFunctionBeginUser;
145 PetscCheck(plan != NULL && count != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
146 "Plan and count output are required.");
147 for (PetscInt dim = 0; dim < 3; ++dim) {
148 const PetscInt extent = plan->end[dim] - plan->start[dim];
149 if (extent <= 0) { *count = 0; PetscFunctionReturn(0); }
150 total *= extent;
151 }
152 *count = total;
153 PetscFunctionReturn(0);
154}
155
156/**
157 * @brief Implementation of \ref SpatialTargetPlanGlobalPointCount().
158 * @see SpatialTargetPlanGlobalPointCount()
159 */
160PetscErrorCode SpatialTargetPlanGlobalPointCount(const SpatialTargetPlan *plan, MPI_Comm comm, PetscInt *count)
161{
162 PetscInt local = 0;
163
164 PetscFunctionBeginUser;
165 PetscCheck(plan != NULL && count != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
166 "Plan and count output are required.");
167 PetscCall(SpatialTargetPlanLocalPointCount(plan, &local));
168 PetscCallMPI(MPI_Allreduce(&local, count, 1, MPIU_INT, MPI_SUM, comm));
169 PetscFunctionReturn(0);
170}
171
172/**
173 * @brief Implementation of \ref SpatialTargetPlanMaskAllows().
174 * @see SpatialTargetPlanMaskAllows()
175 */
176PetscBool SpatialTargetPlanMaskAllows(const SpatialTargetPlan *plan, PetscReal nvert_value)
177{
178 if (plan == NULL) return PETSC_FALSE;
179 return (PetscBool)(nvert_value < PICURV_STATISTICS_FLUID_THRESHOLD);
180}
FieldLayout layout
FieldLayout
Logical storage topology of a field.
@ FIELD_LAYOUT_K_FACE
@ FIELD_LAYOUT_I_FACE
@ FIELD_LAYOUT_CELL_CENTERED
@ FIELD_LAYOUT_COMPONENT_STAGGERED
@ FIELD_LAYOUT_NODE_CENTERED
@ FIELD_LAYOUT_J_FACE
const char * canonical_name
PetscErrorCode FieldGetDescriptor(FieldId field_id, const FieldDescriptor **descriptor)
Return immutable metadata for a valid field identifier.
FieldId
Compile-time identity for a catalogued Eulerian field.
Immutable metadata for one field identity.
PetscBool SpatialTargetPlanMaskAllows(const SpatialTargetPlan *plan, PetscReal nvert_value)
Implementation of SpatialTargetPlanMaskAllows().
static void ResolveLayoutSpan(PetscBool node_like, PetscBool periodic, PetscInt size, PetscInt *lo, PetscInt *hi_exclusive)
Internal helper: resolves the layout-valid index span for one dimension.
PetscErrorCode SpatialTargetPlanLocalPointCount(const SpatialTargetPlan *plan, PetscInt *count)
Implementation of SpatialTargetPlanLocalPointCount().
PetscErrorCode SpatialTargetPlanGlobalPointCount(const SpatialTargetPlan *plan, MPI_Comm comm, PetscInt *count)
Implementation of SpatialTargetPlanGlobalPointCount().
PetscErrorCode SpatialTargetPlanCreate(UserCtx *user, FieldId field_id, PicurvStatisticsMask mask, SpatialTargetPlan *plan)
Implementation of SpatialTargetPlanCreate().
PetscErrorCode PicurvLayoutDimensionIsNodeLike(FieldLayout layout, PetscInt dim, PetscBool *node_like)
Implementation of PicurvLayoutDimensionIsNodeLike().
Spatial target resolution for the field-statistics pipeline.
#define PICURV_STATISTICS_FLUID_THRESHOLD
Threshold below which a cell counts as fluid for the default mask.
PicurvTargetKind kind
Spatial mapping; always pointwise in Phase 2.
@ PICURV_TARGET_POINTWISE
PicurvStatisticsMask
Point-eligibility mask.
@ PICURV_STATISTICS_MASK_FLUID
PetscInt end[3]
Exclusive end per dimension (i, j, k).
PetscInt start[3]
Inclusive start per dimension (i, j, k).
const FieldDescriptor * descriptor
Catalog metadata for the targeted field.
PicurvStatisticsMask mask
Point-eligibility mask.
Resolved iteration domain for one field on one block.
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:899
PetscInt k_periodic
Definition variables.h:791
PetscInt i_periodic
Definition variables.h:791
DMDALocalInfo info
Definition variables.h:908
PetscInt j_periodic
Definition variables.h:791
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