PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
walkingsearch.h
Go to the documentation of this file.
1/**
2 * @file walkingsearch.h
3 * @brief Header file for particle location functions using the walking search algorithm.
4 *
5 * This file contains declarations of functions that implement the walking search algorithm
6 * to locate particles within a computational grid. It includes functions for computing
7 * distances to cell faces, determining particle positions relative to cells, and updating
8 * traversal parameters.
9 */
10
11#ifndef WALKINGSEARCH_H
12#define WALKINGSEARCH_H
13
14// Include necessary headers
15#include <petsc.h>
16#include <stdbool.h>
17#include <math.h>
18#include "variables.h" // Common type definitions
19#include "logging.h" // Logging macros and definitions
20#include "setup.h" // utility functions
21
22// --------------------- Function Declarations ---------------------
23
24/**
25 * @brief Estimates a characteristic length of the cell for threshold scaling.
26 *
27 * For a hexahedral cell with vertices cell->vertices[0..7], we approximate
28 * the cell size by some measure—e.g. average edge length or diagonal.
29 * @param[in] cell A pointer to the Cell structure
30 * @param[out] cellSize A pointer to a PetscReal where the characteristic size is stored.
31 *
32 * @return PetscErrorCode 0 on success, non-zero on failure.
33 */
34 PetscErrorCode GetCellCharacteristicSize(const Cell *cell, PetscReal *cellSize);
35
36/**
37 * @brief Computes the signed distance from a point to the plane approximating a quadrilateral face.
38 *
39 * This function calculates the signed distance from a given point `p_target` to the plane
40 * approximating a quadrilateral face defined by points `v1`, `v2`, `v3`, and `v4`.
41 * The plane's initial normal is determined using two edge vectors emanating from `v1`
42 * (i.e., `v2-v1` and `v4-v1`).
43 *
44 * **Normal Orientation:**
45 * The initial normal's orientation is checked against the cell's interior.
46 * A vector from the face centroid to the cell centroid (`vec_face_to_cell_centroid`) is computed.
47 * If the dot product of the initial normal and `vec_face_to_cell_centroid` is positive,
48 * it means the initial normal is pointing towards the cell's interior (it's an inward normal
49 * relative to the cell). In this case, the normal is flipped to ensure it points outward.
50 *
51 * **Signed Distance Convention:**
52 * The signed distance is the projection of the vector from `p_target` to the face's centroid
53 * onto the (now guaranteed) outward-pointing plane's normal vector.
54 * - `d_signed < 0`: `p_target` is "outside" and "beyond" the face, in the direction of the outward normal.
55 * This is the primary case indicating the particle has crossed this face.
56 * - `d_signed > 0`: `p_target` is "outside" but "behind" the face (on the same side as the cell interior
57 * relative to this face plane).
58 * - `d_signed = 0`: `p_target` is on the face plane (within threshold).
59 *
60 * @param[in] v1 First vertex defining the face (used as origin for initial normal calculation).
61 * @param[in] v2 Second vertex defining the face (used for first edge vector: v2-v1).
62 * @param[in] v3 Third vertex defining the face (used for face centroid calculation).
63 * @param[in] v4 Fourth vertex defining the face (used for second edge vector: v4-v1).
64 * @param[in] cell_centroid The centroid of the 8-vertex cell to which this face belongs.
65 * @param[in] p_target The point from which the distance to the plane is calculated.
66 * @param[out] d_signed Pointer to store the computed signed distance.
67 * @param[in] threshold The threshold below which the absolute distance is considered zero.
68 *
69 * @note
70 * - The order of vertices `v1, v2, v3, v4` is used for calculating the face centroid.
71 * The order of `v1, v2, v4` is used for the initial normal calculation.
72 * - The `cell_centroid` is crucial for robustly determining the outward direction of the normal.
73 *
74 * @return PetscErrorCode Returns 0 on success, PETSC_ERR_ARG_NULL if `d_signed` is NULL,
75 * or PETSC_ERR_USER if a degenerate plane (near-zero normal) is detected.
76 */
77PetscErrorCode ComputeSignedDistanceToPlane(const Cmpnts v1, const Cmpnts v2, const Cmpnts v3, const Cmpnts v4,
78 const Cmpnts cell_centroid,const Cmpnts p_target,
79 PetscReal *d_signed, const PetscReal threshold);
80
81/**
82 * @brief Computes the signed distances from a point to each face of a cubic cell.
83 *
84 * This function calculates the signed distances from a specified point `p` to each of the six
85 * faces of a cubic cell. The cell is defined by its eight vertices, and the distances are
86 * stored in the memory location pointed to by `d`.
87 *
88 * @param[in] p The target point in 3D space.
89 * @param[in] cell Pointer to a `Cell` structure that defines the cubic cell via its vertices.
90 * @param[out] d A pointer to an array of six `PetscReal` values where the computed signed distances will be stored.
91 * @param[in] threshold A `PetscReal` value that specifies the minimum distance below which a computed distance is considered to be zero.
92 *
93 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
94 */
95PetscErrorCode CalculateDistancesToCellFaces(const Cmpnts p, const Cell *cell, PetscReal *d, const PetscReal threshold);
96
97/**
98 * @brief Classifies a point based on precomputed face distances.
99 *
100 * Given an array of six distances d[NUM_FACES] from the point to each face
101 * of a hexahedral cell, this function determines:
102 * 0 => inside
103 * 1 => on a single face
104 * 2 => on an edge (2 faces = 0)
105 * 3 => on a corner (3+ faces = 0)
106 * -1 => outside
107 *
108 * @param[in] d Array of six face distances.
109 * @param[out] result Pointer to an integer classification: {0,1,2,3,-1}.
110 *
111 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
112 */
113 PetscErrorCode DeterminePointPosition(PetscReal *d, PetscInt *result);
114
115/**
116 * @brief Retrieves the coordinates of the eight vertices of a cell based on grid indices.
117 *
118 * This function populates the `cell` structure with the coordinates of the eight vertices
119 * of a hexahedral cell given its grid indices `(idx, idy, idz)`.
120 *
121 * @param[in] coor Pointer to a 3D array of `Cmpnts` structures representing the grid coordinates.
122 * @param[in] idx The i-index of the cell.
123 * @param[in] idy The j-index of the cell.
124 * @param[in] idz The k-index of the cell.
125 * @param[out] cell Pointer to a `Cell` structure to store the cell's vertices.
126 *
127 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
128 */
129PetscErrorCode GetCellVerticesFromGrid(Cmpnts ***coor, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell);
130
131/**
132 * @brief Initializes traversal parameters for locating a particle.
133 *
134 * This function sets the initial cell indices based on the local grid boundaries
135 * and initializes the traversal step counter.
136 *
137 * @param[in] user Pointer to the user-defined context containing grid information.
138 * @param[in] particle Pointer to the Particle structure containing its location.
139 * @param[out] idx Pointer to store the initial i-index of the cell.
140 * @param[out] idy Pointer to store the initial j-index of the cell.
141 * @param[out] idz Pointer to store the initial k-index of the cell.
142 * @param[out] traversal_steps Pointer to store the initial traversal step count.
143 *
144 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
145 */
146PetscErrorCode InitializeTraversalParameters(UserCtx *user, Particle *particle, PetscInt *idx, PetscInt *idy, PetscInt *idz, PetscInt *traversal_steps);
147
148/**
149 * @brief Checks if the current cell indices are within the local grid boundaries.
150 *
151 * @param[in] user Pointer to the user-defined context containing grid information.
152 * @param[in] idx The i-index of the current cell.
153 * @param[in] idy The j-index of the current cell.
154 * @param[in] idz The k-index of the current cell.
155 * @param[out] is_within Pointer to a PetscBool that will be set to PETSC_TRUE if within bounds, else PETSC_FALSE.
156 *
157 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
158 */
159PetscErrorCode CheckCellWithinLocalGrid(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, PetscBool *is_within);
160
161/**
162 * @brief Retrieves the coordinates of the eight vertices of the current cell.
163 *
164 * @param[in] user Pointer to the user-defined context containing grid information.
165 * @param[in] idx The i-index of the current cell.
166 * @param[in] idy The j-index of the current cell.
167 * @param[in] idz The k-index of the current cell.
168 * @param[out] cell Pointer to a Cell structure to store the cell's vertices.
169 *
170 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
171 */
172PetscErrorCode RetrieveCurrentCell(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell);
173
174/**
175 * @brief Determines the spatial relationship of a particle relative to a cubic cell.
176 *
177 * This function evaluates whether a particle located at a specific point `p` in 3D space
178 * is positioned inside the cell, on the boundary of the cell, or outside the cell. The
179 * determination is based on the signed distances from the particle to each of the six
180 * faces of the cell. The function utilizes the computed distances to ascertain the particle's
181 * position with respect to the cell boundaries, considering a threshold to account for
182 * floating-point precision.
183 *
184 * @param[in] cell A pointer to a `Cell` structure that defines the cubic cell via its
185 * vertices. The cell's geometry is essential for accurately computing
186 * the distances to each face.
187 * @param[in] d A pointer to an array of six `PetscReal` values that store the
188 * signed distances from the particle to each face of the cell. These
189 * distances are typically computed using the `CalculateDistancesToCellFaces`
190 * function.
191 * @param[in] p The location of the particle in 3D space, represented by the `Cmpnts`
192 * structure. This point is the reference for distance calculations to the
193 * cell's faces.
194 * @param[out] position A pointer to an integer that will be set based on the particle's position
195 * relative to the cell:
196 * - `0`: The particle is inside the cell.
197 * - `1`: The particle is on the boundary of the cell.
198 * - `-1`: The particle is outside the cell.
199 * @param[in] threshold A `PetscReal` value that defines the minimum distance below which a
200 * computed distance is considered to be zero. This threshold helps in
201 * mitigating inaccuracies due to floating-point arithmetic, especially
202 * when determining if the particle lies exactly on the boundary.
203 *
204 * @return PetscErrorCode Returns `0` if the function executes successfully. If an error occurs,
205 * a non-zero error code is returned, indicating the type of failure.
206 *
207 * @note
208 * - It is assumed that the `d` array has been properly allocated and contains valid distance
209 * measurements before calling this function.
210 * - The function relies on `CalculateDistancesToCellFaces` to accurately compute the signed
211 * distances to each face. Any inaccuracies in distance calculations can affect the
212 * determination of the particle's position.
213 * - The `threshold` parameter should be chosen based on the specific precision requirements
214 * of the application to balance between sensitivity and robustness against floating-point
215 * errors.
216 * - The function includes a debug statement that prints the face distances, which can be useful
217 * for verifying the correctness of distance computations during development or troubleshooting.
218 */
219 PetscErrorCode EvaluateParticlePosition(const Cell *cell, PetscReal *d, const Cmpnts p, PetscInt *position, const PetscReal threshold);
220
221/**
222 * @brief Locates the grid cell containing a particle using a walking search.
223 * @ingroup ParticleLocation
224 *
225 * This function implements a walking search algorithm to find the specific cell
226 * (identified by global indices i, j, k) that encloses the particle's physical
227 * location (`particle->loc`).
228 *
229 * The search starts from an initial guess cell (either the particle's previously known
230 * cell or the corner of the local process domain) and iteratively steps to adjacent
231 * cells based on the signed distances from the particle to the faces of the current
232 * cell.
233 *
234 * Upon successful location (`position == 0`), the particle's `cell` field is updated
235 * with the found indices (i,j,k), and the corresponding interpolation `weights`
236 * are calculated and stored using the distances (`d`) relative to the final cell.
237 *
238 * Handles particles exactly on cell boundaries by attempting a tie-breaker if the
239 * search gets stuck oscillating between adjacent cells due to the boundary condition.
240 *
241 * @param[in] user Pointer to the UserCtx structure containing grid information (DMDA, coordinates)
242 * and domain boundaries.
243 * @param[in,out] particle Pointer to the Particle structure. Its `loc` field provides the
244 * target position. On successful return, its `cell` and `weights`
245 * fields are updated. On failure, `cell` is set to `{-1, -1, -1}`
246 * and `weights` to `{0.0, 0.0, 0.0}`.
247 *
248 * @return PetscErrorCode 0 on success. Non-zero error codes may indicate issues during
249 * coordinate access, distance calculation, or other internal errors.
250 * A return code of 0 does not guarantee the particle was found;
251 * check `particle->cell[0] >= 0` afterward.
252 *
253 * @note Relies on helper functions like `InitializeTraversalParameters`, `CheckCellWithinLocalGrid`,
254 * `RetrieveCurrentCell`, `EvaluateParticlePosition`, `UpdateCellIndicesBasedOnDistances`,
255 * `UpdateParticleWeights`, and `FinalizeTraversal`.
256 * @warning Ensure `particle->loc` is set correctly before calling.
257 * @warning The function may fail to find the particle if it lies outside the domain accessible
258 * by the current process (including ghost cells) or if `MAX_TRAVERSAL` steps are exceeded.
259 */
260PetscErrorCode LocateParticleInGrid(UserCtx *user, Particle *particle);
261
262/**
263 * @brief Updates the cell indices based on the signed distances to each face.
264 *
265 * This function modifies the cell indices (`idx`, `idy`, `idz`) to move towards the direction
266 * where the particle is likely to be located, based on positive distances indicating
267 * that the particle is outside in that particular direction.
268 *
269 * @param[in] d An array of six `PetscReal` values representing the signed distances to each face:
270 * - d[LEFT]: Left Face
271 * - d[RIGHT]: Right Face
272 * - d[BOTTOM]: Bottom Face
273 * - d[TOP]: Top Face
274 * - d[FRONT]: Front Face
275 * - d[BACK]: Back Face
276 * @param[out] idx Pointer to the i-index of the cell to be updated.
277 * @param[out] idy Pointer to the j-index of the cell to be updated.
278 * @param[out] idz Pointer to the k-index of the cell to be updated.
279 * @param[in] info DMDALocalInfo structure that holds local & global domain bounds.
280 *
281 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
282 */
283PetscErrorCode UpdateCellIndicesBasedOnDistances( PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz, DMDALocalInfo *info);
284
285
286/**
287 * @brief Finalizes the traversal by reporting the results.
288 *
289 * This function prints the outcome of the traversal, indicating whether the particle
290 * was found within a cell or not, and updates the particle's cell indices accordingly.
291 *
292 * @param[in] user Pointer to the user-defined context containing grid information.
293 * @param[out] particle Pointer to the Particle structure to update with cell indices.
294 * @param[in] traversal_steps The number of traversal steps taken.
295 * @param[in] cell_found Flag indicating whether the particle was found within a cell.
296 * @param[in] idx The i-index of the found cell.
297 * @param[in] idy The j-index of the found cell.
298 * @param[in] idz The k-index of the found cell.
299 *
300 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
301 */
302PetscErrorCode FinalizeTraversal(UserCtx *user, Particle *particle, PetscInt traversal_steps, PetscBool cell_found, PetscInt idx, PetscInt idy, PetscInt idz);
303
304
305/**
306 * @brief Finds the MPI rank that owns a given global cell index.
307 * @ingroup DomainInfo
308 *
309 * This function performs a linear search through the pre-computed decomposition map
310 * (`user->RankCellInfoMap`) to determine which process is responsible for the cell
311 * with global indices (i, j, k). It is the definitive method for resolving cell
312 * ownership in the "Walk and Handoff" migration algorithm.
313 *
314 * If the provided indices are outside the range of any rank (e.g., negative or
315 * beyond the global domain), the function will not find an owner and `owner_rank`
316 * will be set to -1.
317 *
318 * @param[in] user Pointer to the UserCtx structure, which must contain the
319 * initialized `RankCellInfoMap` and `num_ranks`.
320 * @param[in] i Global i-index of the cell to find.
321 * @param[in] j Global j-index of the cell to find.
322 * @param[in] k Global k-index of the cell to find.
323 * @param[out] owner_rank Pointer to a `PetscMPIInt` where the resulting owner rank will
324 * be stored. It is set to -1 if no owner is found.
325 *
326 * @return PetscErrorCode 0 on success, or a non-zero PETSc error code on failure.
327 */
328PetscErrorCode FindOwnerOfCell(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscMPIInt *owner_rank);
329
330/**
331 * @brief Locates a particle's host cell or identifies its migration target using a robust walk search.
332 * @ingroup ParticleLocation
333 *
334 * This is the core search engine. It starts from a guess cell and walks through
335 * the grid. It returns a definitive, actionable status indicating the outcome:
336 * - `ACTIVE_AND_LOCATED`: The particle was found in a cell on the current rank.
337 * - `MIGRATING_OUT`: The particle was found to belong to another rank. `particle->destination_rank` is set.
338 * - `LOST`: The search failed to find the particle within the global domain.
339 *
340 * This function is globally aware and can walk across MPI rank boundaries. It contains
341 * robust checks for global domain boundaries and a tie-breaker for numerically "stuck"
342 * particles on cell faces.
343 *
344 * @param[in] user Pointer to the UserCtx containing all grid and domain info.
345 * @param[in,out] particle Pointer to the Particle struct. Its fields are updated based
346 * on the search outcome.
347 * @param[out] status_out The final, actionable status of the particle after the search.
348 *
349 * @return PetscErrorCode 0 on success, or a non-zero PETSc error code on failure.
350 */
352 Particle *particle,
353 ParticleLocationStatus *status_out);
354
355/**
356 * @brief Logs the final outcome of the particle location search.
357 */
358PetscErrorCode ReportSearchOutcome(const Particle *particle,
360 PetscInt traversal_steps);
361
362/**
363 * @brief Updates the cell indices based on the signed distances to each face.
364 *
365 * This function modifies the cell indices (`idx`, `idy`, `idz`) to move towards the direction
366 * where the particle is likely to be located, based on positive distances indicating
367 * that the particle is outside in that particular direction.
368 *
369 * @param[in] d An array of six `PetscReal` values representing the signed distances to each face:
370 * - d[LEFT]: Left Face
371 * - d[RIGHT]: Right Face
372 * - d[BOTTOM]: Bottom Face
373 * - d[TOP]: Top Face
374 * - d[FRONT]: Front Face
375 * - d[BACK]: Back Face
376 * @param[out] idx Pointer to the i-index of the cell to be updated.
377 * @param[out] idy Pointer to the j-index of the cell to be updated.
378 * @param[out] idz Pointer to the k-index of the cell to be updated.
379 * @param[in] info DMDALocalInfo structure that holds local & global domain bounds.
380 *
381 * @return PetscErrorCode Returns 0 on success, non-zero on failure.
382 */
383PetscErrorCode UpdateCellIndicesBasedOnDistancesTEST( PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz);
384
385#endif // WALKINGSEARCH_H
Logging utilities and macros for PETSc-based applications.
Main header file for a complex fluid dynamics solver.
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Definition variables.h:134
@ NUM_FACES
Definition variables.h:144
Defines the vertices of a single hexahedral grid cell.
Definition variables.h:159
A 3D point or vector with PetscScalar components.
Definition variables.h:99
Defines a particle's core properties for Lagrangian tracking.
Definition variables.h:164
User-defined context containing data specific to a single computational grid level.
Definition variables.h:630
PetscErrorCode LocateParticleOrFindMigrationTarget_TEST(UserCtx *user, Particle *particle, ParticleLocationStatus *status_out)
Locates a particle's host cell or identifies its migration target using a robust walk search.
PetscErrorCode FinalizeTraversal(UserCtx *user, Particle *particle, PetscInt traversal_steps, PetscBool cell_found, PetscInt idx, PetscInt idy, PetscInt idz)
Finalizes the traversal by reporting the results.
PetscErrorCode GetCellCharacteristicSize(const Cell *cell, PetscReal *cellSize)
Estimates a characteristic length of the cell for threshold scaling.
PetscErrorCode EvaluateParticlePosition(const Cell *cell, PetscReal *d, const Cmpnts p, PetscInt *position, const PetscReal threshold)
Determines the spatial relationship of a particle relative to a cubic cell.
PetscErrorCode ComputeSignedDistanceToPlane(const Cmpnts v1, const Cmpnts v2, const Cmpnts v3, const Cmpnts v4, const Cmpnts cell_centroid, const Cmpnts p_target, PetscReal *d_signed, const PetscReal threshold)
Computes the signed distance from a point to the plane approximating a quadrilateral face.
PetscErrorCode ReportSearchOutcome(const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
Logs the final outcome of the particle location search.
PetscErrorCode CalculateDistancesToCellFaces(const Cmpnts p, const Cell *cell, PetscReal *d, const PetscReal threshold)
Computes the signed distances from a point to each face of a cubic cell.
PetscErrorCode DeterminePointPosition(PetscReal *d, PetscInt *result)
Classifies a point based on precomputed face distances.
PetscErrorCode UpdateCellIndicesBasedOnDistances(PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz, DMDALocalInfo *info)
Updates the cell indices based on the signed distances to each face.
PetscErrorCode FindOwnerOfCell(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscMPIInt *owner_rank)
Finds the MPI rank that owns a given global cell index.
PetscErrorCode LocateParticleInGrid(UserCtx *user, Particle *particle)
Locates the grid cell containing a particle using a walking search.
PetscErrorCode RetrieveCurrentCell(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Retrieves the coordinates of the eight vertices of the current cell.
PetscErrorCode GetCellVerticesFromGrid(Cmpnts ***coor, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Retrieves the coordinates of the eight vertices of a cell based on grid indices.
PetscErrorCode UpdateCellIndicesBasedOnDistancesTEST(PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz)
Updates the cell indices based on the signed distances to each face.
PetscErrorCode InitializeTraversalParameters(UserCtx *user, Particle *particle, PetscInt *idx, PetscInt *idy, PetscInt *idz, PetscInt *traversal_steps)
Initializes traversal parameters for locating a particle.
PetscErrorCode CheckCellWithinLocalGrid(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, PetscBool *is_within)
Checks if the current cell indices are within the local grid boundaries.