PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
grid.h
Go to the documentation of this file.
1// in include/grid.h
2
3#ifndef GRID_H
4#define GRID_H
5
6#include "variables.h" // Essential for SimulationContext and UserCtx definitions
7#include "logging.h" // Logging macros and definitions
8#include "io.h"
9#include "setup.h" // For SetDMDAProcLayout
10#include "AnalyticalSolutions.h" // For SetAnalyticalGridInfo
11/**
12 * @file grid.h
13 * @brief Public interface for grid, solver, and metric setup routines.
14 */
15
16/**
17 * @brief Orchestrates the parsing and setting of grid dimensions for all blocks.
18 *
19 * This function serves as the high-level entry point for defining the geometric
20 * properties of each grid block in the simulation. It iterates through every
21 * block defined by `simCtx->block_number`.
22 *
23 * For each block, it performs two key actions:
24 * 1. It explicitly sets the block's index (`_this`) in the corresponding `UserCtx`
25 * struct for the finest multigrid level. This makes the context "self-aware".
26 * 2. It calls a helper function (`ParseAndSetGridInputs`) to handle the detailed
27 * work of parsing options or files to populate the rest of the geometric
28 * properties for that specific block (e.g., `IM`, `Min_X`, `rx`).
29 *
30 * @param simCtx The master SimCtx, which contains the number of blocks and the
31 * UserCtx hierarchy to be configured.
32 * @return PetscErrorCode 0 on success, or a PETSc error code on failure.
33 */
34PetscErrorCode DefineAllGridDimensions(SimCtx *simCtx);
35
36/**
37 * @brief Orchestrates the creation of DMDA objects for every block and multigrid level.
38 *
39 * This function systematically builds the entire DMDA hierarchy. It first
40 * calculates the dimensions (IM, JM, KM) for all coarse grids based on the
41 * finest grid's dimensions and the semi-coarsening flags. It then iterates
42 * from the coarsest to the finest level, calling a powerful helper function
43 * (`InitializeSingleGridDM`) to create the DMs for each block, ensuring that
44 * finer grids are properly aligned with their coarser parents for multigrid efficiency.
45 *
46 * @param simCtx The master SimCtx, containing the configured UserCtx hierarchy.
47 * @return PetscErrorCode 0 on success, or a PETSc error code on failure.
48 */
49PetscErrorCode InitializeAllGridDMs(SimCtx *simCtx);
50
51/**
52 * @brief Orchestrates the assignment of physical coordinates to all DMDA objects.
53 *
54 * This function manages the entire process of populating the coordinate vectors
55 * for every DMDA across all multigrid levels and blocks. It follows a two-part
56 * strategy that is essential for multigrid methods:
57 *
58 * 1. **Populate Finest Level:** It first loops through each block and calls a
59 * helper (`SetFinestLevelCoordinates`) to set the physical coordinates for
60 * the highest-resolution grid (the finest multigrid level).
61 * 2. **Restrict to Coarser Levels:** It then iterates downwards from the finest
62 * level, calling a helper (`RestrictCoordinates`) to copy the coordinate
63 * values from the fine grid nodes to their corresponding parent nodes on the
64 * coarser grids. This ensures all levels represent the exact same geometry.
65 *
66 * @param simCtx The master SimCtx, containing the configured UserCtx hierarchy.
67 * @return PetscErrorCode 0 on success, or a PETSc error code on failure.
68 */
69PetscErrorCode AssignAllGridCoordinates(SimCtx *simCtx);
70
71/**
72 * @brief Validates that configured geometric periodic seams match by translation.
73 *
74 * Each active periodic direction is checked independently using the physical nodal
75 * coordinates. On success, the constant seam translation is stored in the UserCtx.
76 *
77 * @param user Grid/block context with assigned coordinates and boundary configuration.
78 * @return PetscErrorCode 0 on success, or a user-input error for unsupported geometry.
79 */
80PetscErrorCode ValidatePeriodicGeometry(UserCtx *user);
81
82
83/**
84 * @brief Computes the local bounding box of the grid on the current process.
85 *
86 * This function calculates the minimum and maximum coordinates of the local grid points owned
87 * by the current MPI process and stores the computed bounding box in the provided structure.
88 *
89 * @param[in] user Pointer to the user-defined context containing grid information.
90 * @param[out] localBBox Pointer to the BoundingBox structure to store the computed bounding box.
91 *
92 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
93 */
94PetscErrorCode ComputeLocalBoundingBox(UserCtx *user, BoundingBox *localBBox);
95
96/**
97 * @brief Gathers local bounding boxes from all MPI processes to rank 0.
98 *
99 * This function computes the local bounding box on each process, then collects all local
100 * bounding boxes on the root process (rank 0) using MPI. The result is stored in an array
101 * of BoundingBox structures on rank 0.
102 *
103 * @param[in] user Pointer to the user-defined context containing grid information.
104 * @param[out] allBBoxes Pointer to a pointer where the array of gathered bounding boxes
105 * will be stored on rank 0. The caller on rank 0 must free this array.
106 *
107 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
108 */
109PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes);
110
111/**
112 * @brief Broadcasts the bounding box information collected on rank 0 to all other ranks.
113 *
114 * This function assumes that `GatherAllBoundingBoxes()` was previously called, so `bboxlist`
115 * is allocated and populated on rank 0. All other ranks will allocate memory for `bboxlist`,
116 * and this function will use MPI_Bcast to distribute the bounding box data to them.
117 *
118 * @param[in] user Pointer to the UserCtx structure. (Currently unused in this function, but kept for consistency.)
119 * @param[in,out] bboxlist Pointer to the array of BoundingBoxes. On rank 0, this should point to
120 * a valid array of size 'size' (where size is the number of MPI ranks).
121 * On non-root ranks, this function will allocate memory for `bboxlist`.
122 *
123 * @return PetscErrorCode Returns 0 on success, non-zero on MPI or PETSc-related errors.
124 */
125PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist);
126
127/**
128 * @brief Calculates the center and area of the primary INLET face.
129 *
130 * This function identifies the primary INLET face from the boundary face
131 * configurations, computes its geometric center and total area using a
132 * generic utility function, and stores these results in the simulation context.
133 *
134 * @param user Pointer to the UserCtx containing boundary face information.
135 * @return PetscErrorCode
136 */
137PetscErrorCode CalculateInletProperties(UserCtx *user);
138
139/**
140 * @brief Calculates the center and area of the primary OUTLET face.
141 *
142 * This function identifies the primary OUTLET face from the boundary face
143 * configurations, computes its geometric center and total area using a
144 * generic utility function, and stores these results in the simulation context.
145 * @param user Pointer to the UserCtx containing boundary face information.
146 * @return PetscErrorCode
147 */
148PetscErrorCode CalculateOutletProperties(UserCtx *user);
149
150/**
151 * @brief Calculates the geometric center and total area of a specified boundary face.
152 *
153 * This function computes two key properties of a boundary face in the computational domain:
154 * 1. **Geometric Center**: The average (x,y,z) position of all physical nodes on the face
155 * 2. **Total Area**: The sum of face area vector magnitudes from all non-solid cells adjacent to the face
156 *
157 * @section architecture Indexing Architecture
158 *
159 * The solver uses different indexing conventions for different field types:
160 *
161 * **Node-Centered Fields (Coordinates):**
162 * - Direct indexing: Node n stored at coor[n]
163 * - For mx=26: Physical nodes [0-24], Dummy at [25]
164 * - For mz=98: Physical nodes [0-96], Dummy at [97]
165 *
166 * **Face-Centered Fields (Metrics: csi, eta, zet):**
167 * - Direct indexing: Face n stored at csi/eta/zet[n]
168 * - For mx=26: Physical faces [0-24], Dummy at [25]
169 * - For mz=98: Physical faces [0-96], Dummy at [97]
170 * - Face at index k bounds cells k-1 and k
171 *
172 * **Cell-Centered Fields (nvert):**
173 * - Shifted indexing: Physical cell c stored at nvert[c+1]
174 * - For mx=26 (25 cells): Cell 0→nvert[1], Cell 23→nvert[24]
175 * - For mz=98 (96 cells): Cell 0→nvert[1], Cell 95→nvert[96]
176 * - nvert[0] and nvert[mx-1] are ghost values
177 *
178 * @section face_geometry Face-to-Index Mapping
179 *
180 * Example for a domain with mx=26, my=26, mz=98:
181 *
182 * | Face ID | Node Index | Face Metric | Adjacent Cell (shifted) | Physical Extent |
183 * |---------------|------------|------------------|-------------------------|-----------------|
184 * | BC_FACE_NEG_X | i=0 | csi[k][j][0] | nvert[k][j][1] (Cell 0) | j∈[0,24], k∈[0,96] |
185 * | BC_FACE_POS_X | i=24 | csi[k][j][24] | nvert[k][j][24] (Cell 23)| j∈[0,24], k∈[0,96] |
186 * | BC_FACE_NEG_Y | j=0 | eta[k][0][i] | nvert[k][1][i] (Cell 0) | i∈[0,24], k∈[0,96] |
187 * | BC_FACE_POS_Y | j=24 | eta[k][24][i] | nvert[k][24][i] (Cell 23)| i∈[0,24], k∈[0,96] |
188 * | BC_FACE_NEG_Z | k=0 | zet[0][j][i] | nvert[1][j][i] (Cell 0) | i∈[0,24], j∈[0,24] |
189 * | BC_FACE_POS_Z | k=96 | zet[96][j][i] | nvert[96][j][i] (Cell 95)| i∈[0,24], j∈[0,24] |
190 *
191 * @section algorithm Algorithm
192 *
193 * The function performs two separate computations with different loop bounds:
194 *
195 * **1. Center Calculation (uses ALL physical nodes):**
196 * - Loop over all physical nodes on the face (excluding dummy indices)
197 * - Accumulate coordinate sums: Σx, Σy, Σz
198 * - Count number of nodes
199 * - Average: center = (Σx/n, Σy/n, Σz/n)
200 *
201 * **2. Area Calculation (uses INTERIOR cells only):**
202 * - Loop over interior cell range to avoid accessing ghost values in nvert
203 * - For each face adjacent to a fluid cell (nvert < 0.1):
204 * - Compute area magnitude: |csi/eta/zet| = √(x² + y² + z²)
205 * - Accumulate to total area
206 *
207 * @section loop_bounds Loop Bound Details
208 *
209 * **Why different bounds for center vs. area?**
210 *
211 * For BC_FACE_NEG_X at i=0 with my=26, mz=98:
212 *
213 * *Center calculation (coordinates):*
214 * - j ∈ [ys, j_max): Includes j=[0,24] (25 nodes), excludes dummy at j=25
215 * - k ∈ [zs, k_max): Includes k=[0,96] (97 nodes), excludes dummy at k=97
216 * - Total: 25 × 97 = 2,425 nodes
217 *
218 * *Area calculation (nvert checks):*
219 * - j ∈ [lys, lye): j=[1,24] (24 values), excludes boundaries
220 * - k ∈ [lzs, lze): k=[1,96] (96 values), excludes boundaries
221 * - Why restricted?
222 * - At j=0: nvert[k][0][1] is ghost (no cell at j=-1)
223 * - At j=25: nvert[k][25][1] is ghost (no cell at j=24, index 25 is dummy)
224 * - At k=0: nvert[0][j][1] is ghost (no cell at k=-1)
225 * - At k=97: nvert[97][j][1] is ghost (no cell at k=96, index 97 is dummy)
226 * - Total: 24 × 96 = 2,304 interior cells adjacent to face
227 *
228 * @section area_formulas Area Calculation Formulas
229 *
230 * Face area contributions are computed from metric tensor magnitudes:
231 * - **i-faces (±Xi)**: Area = |csi| = √(csi_x² + csi_y² + csi_z²)
232 * - **j-faces (±Eta)**: Area = |eta| = √(eta_x² + eta_y² + eta_z²)
233 * - **k-faces (±Zeta)**: Area = |zet| = √(zet_x² + zet_y² + zet_z²)
234 *
235 * @param[in] user Pointer to UserCtx containing grid info, DMs, and field vectors
236 * @param[in] face_id Enum identifying which boundary face to analyze (BC_FACE_NEG_X, etc.)
237 * @param[out] face_center Pointer to Cmpnts structure to store computed geometric center (x,y,z)
238 * @param[out] face_area Pointer to PetscReal to store computed total face area
239 *
240 * @return PetscErrorCode Returns 0 on success, non-zero PETSc error code on failure
241 *
242 * @note This function uses MPI_Allreduce, so it must be called collectively by all ranks
243 * @note Only ranks that own the specified boundary face contribute to the calculation
244 * @note Center calculation includes ALL physical nodes on the face
245 * @note Area calculation ONLY includes faces adjacent to fluid cells (nvert < 0.1)
246 * @note Dummy/unused indices (e.g., k=97, j=25 for standard test case) are excluded
247 *
248 * @warning Assumes grid and field arrays have been properly initialized
249 * @warning Incorrect face_id values will result in zero contribution from all ranks
250 *
251 * @see CanRankServiceFace() for determining rank ownership of boundary faces
252 * @see BCFace enum for valid face_id values
253 * @see LOG_FIELD_ANATOMY() for debugging field indexing
254 *
255 * @par Example Usage:
256 * @code
257 * Cmpnts inlet_center;
258 * PetscReal inlet_area;
259 * ierr = CalculateFaceCenterAndArea(user, BC_FACE_NEG_Z, &inlet_center, &inlet_area);
260 * PetscPrintf(PETSC_COMM_WORLD, "Inlet center: (%.4f, %.4f, %.4f), Area: %.6f\n",
261 * inlet_center.x, inlet_center.y, inlet_center.z, inlet_area);
262 * @endcode
263 */
264PetscErrorCode CalculateFaceCenterAndArea(UserCtx *user, BCFace face_id,
265 Cmpnts *face_center, PetscReal *face_area);
266
267#endif // GRID_H
PetscErrorCode DefineAllGridDimensions(SimCtx *simCtx)
Orchestrates the parsing and setting of grid dimensions for all blocks.
Definition grid.c:57
PetscErrorCode CalculateOutletProperties(UserCtx *user)
Calculates the center and area of the primary OUTLET face.
Definition grid.c:1119
PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist)
Broadcasts the bounding box information collected on rank 0 to all other ranks.
Definition grid.c:1016
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
Definition grid.c:380
PetscErrorCode CalculateFaceCenterAndArea(UserCtx *user, BCFace face_id, Cmpnts *face_center, PetscReal *face_area)
Calculates the geometric center and total area of a specified boundary face.
Definition grid.c:1162
PetscErrorCode InitializeAllGridDMs(SimCtx *simCtx)
Orchestrates the creation of DMDA objects for every block and multigrid level.
Definition grid.c:235
PetscErrorCode AssignAllGridCoordinates(SimCtx *simCtx)
Orchestrates the assignment of physical coordinates to all DMDA objects.
Definition grid.c:317
PetscErrorCode ComputeLocalBoundingBox(UserCtx *user, BoundingBox *localBBox)
Computes the local bounding box of the grid on the current process.
Definition grid.c:812
PetscErrorCode CalculateInletProperties(UserCtx *user)
Calculates the center and area of the primary INLET face.
Definition grid.c:1066
PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes)
Gathers local bounding boxes from all MPI processes to rank 0.
Definition grid.c:954
Public interface for data input/output routines.
Logging utilities and macros for PETSc-based applications.
Main header file for a complex fluid dynamics solver.
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:259
Defines a 3D axis-aligned bounding box.
Definition variables.h:169
A 3D point or vector with PetscScalar components.
Definition variables.h:100
The master context for the entire simulation.
Definition variables.h:684
User-defined context containing data specific to a single computational grid level.
Definition variables.h:876