PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Functions
walkingsearch.h File Reference

Header file for particle location functions using the walking search algorithm. More...

#include <petsc.h>
#include <stdbool.h>
#include <math.h>
#include "variables.h"
#include "logging.h"
#include "setup.h"
Include dependency graph for walkingsearch.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

PetscErrorCode GetCellCharacteristicSize (const Cell *cell, PetscReal *cellSize)
 Estimates a characteristic length of the cell for threshold scaling.
 
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 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 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 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.
 
PetscErrorCode RetrieveCurrentCell (UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
 Retrieves the coordinates of the eight vertices of the current cell.
 
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 LocateParticleInGrid (UserCtx *user, Particle *particle)
 Locates the grid cell containing a particle using a walking 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 FindOwnerOfCell (UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscMPIInt *owner_rank)
 Finds the MPI rank that owns a given global cell index.
 
PetscErrorCode LocateParticleOrFindMigrationTarget (UserCtx *user, Particle *particle, ParticleLocationStatus *status_out)
 Locates a particle's host cell or identifies its migration target using a robust walk search.
 
PetscErrorCode ReportSearchOutcome (const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
 Logs the final outcome of the particle location search.
 
PetscErrorCode UpdateCellIndicesBasedOnDistances (PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz)
 Updates the cell indices based on the signed distances to each face.
 

Detailed Description

Header file for particle location functions using the walking search algorithm.

This file contains declarations of functions that implement the walking search algorithm to locate particles within a computational grid. It includes functions for computing distances to cell faces, determining particle positions relative to cells, and updating traversal parameters.

Definition in file walkingsearch.h.

Function Documentation

◆ GetCellCharacteristicSize()

PetscErrorCode GetCellCharacteristicSize ( const Cell cell,
PetscReal *  cellSize 
)

Estimates a characteristic length of the cell for threshold scaling.

For a hexahedral cell with vertices cell->vertices[0..7], we approximate the cell size by some measure—e.g. average edge length or diagonal.

Parameters
[in]cellA pointer to the Cell structure
[out]cellSizeA pointer to a PetscReal where the characteristic size is stored.
Returns
PetscErrorCode 0 on success, non-zero on failure.

Estimates a characteristic length of the cell for threshold scaling.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
GetCellCharacteristicSize()

Definition at line 22 of file walkingsearch.c.

23{
24 PetscErrorCode ierr = 0;
25 PetscFunctionBeginUser;
27 if (!cell || !cellSize) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
28 "GetCellCharacteristicSize: Null pointer(s).");
29
30 // A simple approach: compute the average of the distances between
31 // all pairs of adjacent vertices that share an edge. That gives
32 // a typical measure of cell dimension. For a uniform grid, you
33 // could do something simpler.
34
35 PetscInt edges[12][2] = {
36 {0,1},{1,2},{2,3},{3,0}, // bottom face edges
37 {4,5},{5,6},{6,7},{7,4}, // top face edges
38 {0,7},{1,6},{2,5},{3,4} // vertical edges
39 };
40
41 PetscReal totalEdgeLen = 0.0;
42 for (PetscInt i=0; i<12; i++) {
43 PetscInt vA = edges[i][0];
44 PetscInt vB = edges[i][1];
45 Cmpnts A = cell->vertices[vA];
46 Cmpnts B = cell->vertices[vB];
47 PetscReal dx = B.x - A.x;
48 PetscReal dy = B.y - A.y;
49 PetscReal dz = B.z - A.z;
50 PetscReal edgeLen = sqrt(dx*dx + dy*dy + dz*dz);
51 totalEdgeLen += edgeLen;
52 }
53
54 // Average edge length
55 *cellSize = totalEdgeLen / 12.0;
56
58 PetscFunctionReturn(ierr);
59}
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:859
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:850
PetscScalar x
Definition variables.h:103
PetscScalar z
Definition variables.h:103
PetscScalar y
Definition variables.h:103
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Definition variables.h:178
A 3D point or vector with PetscScalar components.
Definition variables.h:102
Here is the caller graph for this function:

◆ ComputeSignedDistanceToPlane()

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.

This function calculates the signed distance from a given point p_target to the plane approximating a quadrilateral face defined by points v1, v2, v3, and v4. The plane's initial normal is determined using two edge vectors emanating from v1 (i.e., v2-v1 and v4-v1).

Normal Orientation: The initial normal's orientation is checked against the cell's interior. A vector from the face centroid to the cell centroid (vec_face_to_cell_centroid) is computed. If the dot product of the initial normal and vec_face_to_cell_centroid is positive, it means the initial normal is pointing towards the cell's interior (it's an inward normal relative to the cell). In this case, the normal is flipped to ensure it points outward.

Signed Distance Convention: The signed distance is the projection of the vector from p_target to the face's centroid onto the (now guaranteed) outward-pointing plane's normal vector.

  • d_signed < 0: p_target is "outside" and "beyond" the face, in the direction of the outward normal. This is the primary case indicating the particle has crossed this face.
  • d_signed > 0: p_target is "outside" but "behind" the face (on the same side as the cell interior relative to this face plane).
  • d_signed = 0: p_target is on the face plane (within threshold).
Parameters
[in]v1First vertex defining the face (used as origin for initial normal calculation).
[in]v2Second vertex defining the face (used for first edge vector: v2-v1).
[in]v3Third vertex defining the face (used for face centroid calculation).
[in]v4Fourth vertex defining the face (used for second edge vector: v4-v1).
[in]cell_centroidThe centroid of the 8-vertex cell to which this face belongs.
[in]p_targetThe point from which the distance to the plane is calculated.
[out]d_signedPointer to store the computed signed distance.
[in]thresholdThe threshold below which the absolute distance is considered zero.
Note
  • The order of vertices v1, v2, v3, v4 is used for calculating the face centroid. The order of v1, v2, v4 is used for the initial normal calculation.
  • The cell_centroid is crucial for robustly determining the outward direction of the normal.
Returns
PetscErrorCode Returns 0 on success, PETSC_ERR_ARG_NULL if d_signed is NULL, or PETSC_ERR_USER if a degenerate plane (near-zero normal) is detected.

Computes the signed distance from a point to the plane approximating a quadrilateral face.

Local to this translation unit.

Definition at line 68 of file walkingsearch.c.

71{
72 PetscErrorCode ierr = 0;
73 PetscMPIInt rank;
74
75 PetscFunctionBeginUser;
77
78 if (d_signed == NULL) {
79 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
80 LOG_ALLOW(LOCAL, LOG_ERROR, "Output pointer 'd_signed' is NULL on rank %d.\n", rank);
81 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer 'd_signed' must not be NULL.");
82 }
83
84 LOG_ALLOW(LOCAL, LOG_VERBOSE, "Target point: (%.6e, %.6e, %.6e)\n", p_target.x, p_target.y, p_target.z);
85 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Cell Centroid: (%.6e, %.6e, %.6e)\n", cell_centroid.x, cell_centroid.y, cell_centroid.z);
86 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Face Vertices:\n");
87 LOG_ALLOW(LOCAL, LOG_VERBOSE, " v1: (%.6e, %.6e, %.6e)\n", v1.x, v1.y, v1.z);
88 LOG_ALLOW(LOCAL, LOG_VERBOSE, " v2: (%.6e, %.6e, %.6e)\n", v2.x, v2.y, v2.z);
89 LOG_ALLOW(LOCAL, LOG_VERBOSE, " v3: (%.6e, %.6e, %.6e)\n", v3.x, v3.y, v3.z);
90 LOG_ALLOW(LOCAL, LOG_VERBOSE, " v4: (%.6e, %.6e, %.6e)\n", v4.x, v4.y, v4.z);
91
92 // --- Calculate Edge Vectors for Initial Normal Computation ---
93 PetscReal edge1_x = v2.x - v1.x;
94 PetscReal edge1_y = v2.y - v1.y;
95 PetscReal edge1_z = v2.z - v1.z;
96
97 PetscReal edge2_x = v4.x - v1.x;
98 PetscReal edge2_y = v4.y - v1.y;
99 PetscReal edge2_z = v4.z - v1.z;
100 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Edge1 (v2-v1): (%.6e, %.6e, %.6e)\n", edge1_x, edge1_y, edge1_z);
101 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Edge2 (v4-v1): (%.6e, %.6e, %.6e)\n", edge2_x, edge2_y, edge2_z);
102
103 // --- Compute Initial Normal Vector (Cross Product: edge1 x edge2) ---
104 PetscReal normal_x_initial = edge1_y * edge2_z - edge1_z * edge2_y;
105 PetscReal normal_y_initial = edge1_z * edge2_x - edge1_x * edge2_z;
106 PetscReal normal_z_initial = edge1_x * edge2_y - edge1_y * edge2_x;
107 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Initial Raw Normal (edge1 x edge2): (%.6e, %.6e, %.6e)\n", normal_x_initial, normal_y_initial, normal_z_initial);
108
109 PetscReal normal_magnitude = sqrt(normal_x_initial * normal_x_initial +
110 normal_y_initial * normal_y_initial +
111 normal_z_initial * normal_z_initial);
112 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Initial Normal Magnitude: %.6e\n", normal_magnitude);
113
114 if (normal_magnitude < 1.0e-12) {
115 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
117 "Degenerate plane detected on rank %d. Normal magnitude (%.3e) is too small.\n",
118 rank, normal_magnitude);
119 LOG_ALLOW(LOCAL, LOG_ERROR, " Offending vertices for normal: v1(%.3e,%.3e,%.3e), v2(%.3e,%.3e,%.3e), v4(%.3e,%.3e,%.3e)\n",
120 v1.x,v1.y,v1.z, v2.x,v2.y,v2.z, v4.x,v4.y,v4.z);
121 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Degenerate plane detected (normal vector is near zero).");
122 }
123
124 // --- Calculate the Centroid of the Four Face Vertices (v1, v2, v3, v4) ---
125 PetscReal face_centroid_x = 0.25 * (v1.x + v2.x + v3.x + v4.x);
126 PetscReal face_centroid_y = 0.25 * (v1.y + v2.y + v3.y + v4.y);
127 PetscReal face_centroid_z = 0.25 * (v1.z + v2.z + v3.z + v4.z);
128 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Face Centroid: (%.6e, %.6e, %.6e)\n", face_centroid_x, face_centroid_y, face_centroid_z);
129
130 // --- Orient the Normal to Point Outward from the Cell ---
131 // Vector from face centroid to cell centroid
132 PetscReal vec_fc_to_cc_x = cell_centroid.x - face_centroid_x;
133 PetscReal vec_fc_to_cc_y = cell_centroid.y - face_centroid_y;
134 PetscReal vec_fc_to_cc_z = cell_centroid.z - face_centroid_z;
135 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Vec (FaceCentroid -> CellCentroid): (%.6e, %.6e, %.6e)\n", vec_fc_to_cc_x, vec_fc_to_cc_y, vec_fc_to_cc_z);
136
137 // Dot product of initial normal with vector from face centroid to cell centroid
138 PetscReal dot_prod_orientation = normal_x_initial * vec_fc_to_cc_x +
139 normal_y_initial * vec_fc_to_cc_y +
140 normal_z_initial * vec_fc_to_cc_z;
141 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Dot Product for Orientation (N_initial . Vec_FC_to_CC): %.6e\n", dot_prod_orientation);
142
143 PetscReal normal_x = normal_x_initial;
144 PetscReal normal_y = normal_y_initial;
145 PetscReal normal_z = normal_z_initial;
146
147 // If dot_prod_orientation > 0, initial normal points towards cell interior, so flip it.
148 if (dot_prod_orientation > 1.0e-9) { // Use a small epsilon to avoid issues if dot product is extremely close to zero
149 normal_x = -normal_x_initial;
150 normal_y = -normal_y_initial;
151 normal_z = -normal_z_initial;
152 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Initial normal was inward (dot_prod > 0). Flipped normal.\n");
153 } else if (dot_prod_orientation == 0.0 && normal_magnitude > 1e-12) {
154 // This case is ambiguous or face plane contains cell centroid.
155 // This might happen for highly symmetric cells or if face_centroid IS cell_centroid (e.g. 2D cell).
156 // For now, we keep the original normal direction based on v1,v2,v4 ordering.
157 // A more robust solution for this edge case might be needed if it occurs often.
158 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
159 LOG_ALLOW(LOCAL, LOG_WARNING, "Rank %d: Dot product for normal orientation is zero. Normal direction might be ambiguous. Keeping initial normal direction from (v2-v1)x(v4-v1).\n", rank);
160 }
161 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Oriented Raw Normal: (%.6e, %.6e, %.6e)\n", normal_x, normal_y, normal_z);
162
163
164 // --- Normalize the (Now Outward-Pointing) Normal Vector ---
165 // Note: normal_magnitude was calculated from initial normal.
166 // If we flipped, magnitude is the same.
167 normal_x /= normal_magnitude;
168 normal_y /= normal_magnitude;
169 normal_z /= normal_magnitude;
170 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Normalized Outward Normal: (%.6f, %.6f, %.6f)\n", normal_x, normal_y, normal_z);
171
172
173 // --- Compute Vector from Target Point to Face Centroid ---
174 PetscReal vec_p_to_fc_x = face_centroid_x - p_target.x;
175 PetscReal vec_p_to_fc_y = face_centroid_y - p_target.y;
176 PetscReal vec_p_to_fc_z = face_centroid_z - p_target.z;
177
178 // --- Compute Signed Distance ---
179 *d_signed = vec_p_to_fc_x * normal_x +
180 vec_p_to_fc_y * normal_y +
181 vec_p_to_fc_z * normal_z;
182
183 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Raw Signed Distance (using outward normal): %.15e\n", *d_signed);
184
185 // --- Apply Threshold ---
186 if (fabs(*d_signed) < threshold) {
187 LOG_ALLOW(LOCAL, LOG_VERBOSE, " Distance %.15e is less than threshold %.1e. Setting to 0.0.\n", *d_signed, threshold);
188 *d_signed = 0.0;
189 }
190
191 LOG_ALLOW(LOCAL, LOG_VERBOSE, "Final Signed Distance: %.15e\n", *d_signed);
192
194 PetscFunctionReturn(0);
195}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:29
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34
Here is the caller graph for this function:

◆ CalculateDistancesToCellFaces()

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.

This function calculates the signed distances from a specified point p to each of the six faces of a cubic cell. The cell is defined by its eight vertices, and the distances are stored in the memory location pointed to by d.

Parameters
[in]pThe target point in 3D space.
[in]cellPointer to a Cell structure that defines the cubic cell via its vertices.
[out]dA pointer to an array of six PetscReal values where the computed signed distances will be stored.
[in]thresholdA PetscReal value that specifies the minimum distance below which a computed distance is considered to be zero.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Computes the signed distances from a point to each face of a cubic cell.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
CalculateDistancesToCellFaces()

Definition at line 206 of file walkingsearch.c.

207{
208 PetscErrorCode ierr;
209 PetscFunctionBeginUser;
211
212 // Validate that the 'cell' pointer is not NULL to prevent dereferencing a null pointer.
213 if (cell == NULL) {
214 LOG_ALLOW(LOCAL,LOG_ERROR, "'cell' is NULL.\n");
215 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "'cell' is NULL.");
216 }
217
218 // Validate that the 'd' pointer is not NULL to ensure there is memory allocated for distance storage.
219 if (d == NULL) {
220 LOG_ALLOW(LOCAL,LOG_ERROR, "'d' is NULL.\n");
221 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "'d' is NULL.");
222 }
223
224 // Compute the centroid of the entire cell
225 Cmpnts cell_centroid = {0.0, 0.0, 0.0};
226 for (int i = 0; i < 8; ++i) {
227 cell_centroid.x += cell->vertices[i].x;
228 cell_centroid.y += cell->vertices[i].y;
229 cell_centroid.z += cell->vertices[i].z;
230 }
231 cell_centroid.x /= 8.0;
232 cell_centroid.y /= 8.0;
233 cell_centroid.z /= 8.0;
234
235 LOG_ALLOW(LOCAL,LOG_DEBUG, "Cell Centroid: (%.6e, %.6e, %.6e)\n",
236 cell_centroid.x, cell_centroid.y, cell_centroid.z);
237
238
239 // Compute the signed distance from point 'p' to the BACK face of the cell.
240 // The BACK face is defined by vertices 0, 3, 2, and 1, with its normal vector pointing in the -z direction.
242 cell->vertices[0], // Vertex 0
243 cell->vertices[3], // Vertex 3
244 cell->vertices[2], // Vertex 2
245 cell->vertices[1], // Vertex 1
246 cell_centroid, // Cell centroid
247 p, // Target point
248 &d[BACK], // Storage location for the BACK face distance
249 threshold // Threshold for zero distance
250 ); CHKERRQ(ierr);
251
252 // Compute the signed distance from point 'p' to the FRONT face of the cell.
253 // The FRONT face is defined by vertices 4, 7, 6, and 5, with its normal vector pointing in the +z direction.
255 cell->vertices[4], // Vertex 4
256 cell->vertices[7], // Vertex 7
257 cell->vertices[6], // Vertex 6
258 cell->vertices[5], // Vertex 5
259 cell_centroid, // Cell centroid
260 p, // Target point
261 &d[FRONT], // Storage location for the FRONT face distance
262 threshold // Threshold for zero distance
263 ); CHKERRQ(ierr);
264
265 // Compute the signed distance from point 'p' to the BOTTOM face of the cell.
266 // The BOTTOM face is defined by vertices 0, 1, 6, and 7, with its normal vector pointing in the -y direction.
268 cell->vertices[0], // Vertex 0
269 cell->vertices[1], // Vertex 1
270 cell->vertices[6], // Vertex 6
271 cell->vertices[7], // Vertex 7
272 cell_centroid, // Cell centroid
273 p, // Target point
274 &d[BOTTOM], // Storage location for the BOTTOM face distance
275 threshold // Threshold for zero distance
276 ); CHKERRQ(ierr);
277
278 // Compute the signed distance from point 'p' to the TOP face of the cell.
279 // The TOP face is defined by vertices 3, 4, 5, and 2, with its normal vector pointing in the +y direction.
281 cell->vertices[3], // Vertex 3
282 cell->vertices[4], // Vertex 4
283 cell->vertices[5], // Vertex 5
284 cell->vertices[2], // Vertex 2
285 cell_centroid, // Cell centroid
286 p, // Target point
287 &d[TOP], // Storage location for the TOP face distance
288 threshold // Threshold for zero distance
289 ); CHKERRQ(ierr);
290
291 // Compute the signed distance from point 'p' to the LEFT face of the cell.
292 // The LEFT face is defined by vertices 0, 7, 4, and 3, with its normal vector pointing in the -x direction.
294 cell->vertices[0], // Vertex 0
295 cell->vertices[7], // Vertex 7
296 cell->vertices[4], // Vertex 4
297 cell->vertices[3], // Vertex 3
298 cell_centroid, // Cell centroid
299 p, // Target point
300 &d[LEFT], // Storage location for the LEFT face distance
301 threshold // Threshold for zero distance
302 ); CHKERRQ(ierr);
303
304 // Compute the signed distance from point 'p' to the RIGHT face of the cell.
305 // The RIGHT face is defined by vertices 1, 2, 5, and 6, with its normal vector pointing in the +x direction.
307 cell->vertices[1], // Vertex 1
308 cell->vertices[2], // Vertex 2
309 cell->vertices[5], // Vertex 5
310 cell->vertices[6], // Vertex 6
311 cell_centroid, // Cell centroid
312 p, // Target point
313 &d[RIGHT], // Storage location for the RIGHT face distance
314 threshold // Threshold for zero distance
315 ); CHKERRQ(ierr);
316
317 LOG_ALLOW(LOCAL, LOG_DEBUG, "Populated d: "
318 "d[LEFT=%d]=%.3e, d[RIGHT=%d]=%.3e, d[BOTTOM=%d]=%.3e, "
319 "d[TOP=%d]=%.3e, d[FRONT=%d]=%.3e, d[BACK=%d]=%.3e\n",
320 LEFT, d[LEFT], RIGHT, d[RIGHT], BOTTOM, d[BOTTOM],
321 TOP, d[TOP], FRONT, d[FRONT], BACK, d[BACK]);
322 LOG_ALLOW(LOCAL, LOG_DEBUG, "Raw d: "
323 "[%.3e, %.3e, %.3e, %.3e, %.3e, %.3e]\n",
324 d[0], d[1], d[2], d[3], d[4], d[5]);
325
327 PetscFunctionReturn(0); // Indicate successful execution of the function.
328}
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
@ TOP
Definition variables.h:147
@ FRONT
Definition variables.h:147
@ BOTTOM
Definition variables.h:147
@ BACK
Definition variables.h:147
@ LEFT
Definition variables.h:147
@ RIGHT
Definition variables.h:147
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)
Internal helper implementation: ComputeSignedDistanceToPlane().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DeterminePointPosition()

PetscErrorCode DeterminePointPosition ( PetscReal *  d,
PetscInt *  result 
)

Classifies a point based on precomputed face distances.

Given an array of six distances d[NUM_FACES] from the point to each face of a hexahedral cell, this function determines: 0 => inside 1 => on a single face 2 => on an edge (2 faces = 0) 3 => on a corner (3+ faces = 0) -1 => outside

Parameters
[in]dArray of six face distances.
[out]resultPointer to an integer classification: {0,1,2,3,-1}.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Classifies a point based on precomputed face distances.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
DeterminePointPosition()

Definition at line 338 of file walkingsearch.c.

339{
340
341 PetscFunctionBeginUser;
343 // Validate input pointers
344 if (d == NULL) {
345 LOG_ALLOW(LOCAL,LOG_ERROR, "'d' is NULL.\n");
346 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input parameter 'd' is NULL.");
347 }
348 if (result == NULL) {
349 LOG_ALLOW(LOCAL,LOG_ERROR, "'result' is NULL.\n");
350 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output parameter 'result' is NULL.");
351 }
352
353 // Initialize flags
354 PetscBool isInside = PETSC_TRUE;
355 PetscBool isOnBoundary = PETSC_FALSE;
356 PetscInt IntersectionCount = 0; // Counts the number of intersections of the point with various planes of the cell.
357
358 // Analyze distances to determine position
359 for(int i = 0; i < NUM_FACES; i++) {
360 if(d[i] < 0.0) {
361 isInside = PETSC_FALSE; // Point is outside in at least one direction
362 }
363 if(d[i] == 0.0) {
364 isOnBoundary = PETSC_TRUE; // Point is exactly at least one face
365 IntersectionCount++;
366 }
367 }
368
369 // Set the result based on flags
370 if(isInside && isOnBoundary) {
371 if(IntersectionCount == 1){
372 *result = 1; // on face
373 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Particle is on a face of the cell.\n");
374 }
375 else if(IntersectionCount == 2){
376 *result = 2; // on edge
377 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Particle is on an edge of the cell.\n");
378 }
379 else if(IntersectionCount >= 3){
380 *result = 3; // on corner
381 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Particle is on a corner of the cell.\n");
382 }
383 }
384 else if(isInside) {
385 *result = 0; // Inside the cell
386 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Particle is inside the cell.\n");
387 }
388 else {
389 *result = -1; // Outside the cell
390 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Particle is outside the cell.\n");
391 }
392
394 PetscFunctionReturn(0); // Indicate successful execution
395}
@ NUM_FACES
Definition variables.h:147
Here is the caller graph for this function:

◆ GetCellVerticesFromGrid()

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.

This function populates the cell structure with the coordinates of the eight vertices of a hexahedral cell given its grid indices (idx, idy, idz).

Parameters
[in]coorPointer to a 3D array of Cmpnts structures representing the grid coordinates.
[in]idxThe i-index of the cell.
[in]idyThe j-index of the cell.
[in]idzThe k-index of the cell.
[out]cellPointer to a Cell structure to store the cell's vertices.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Retrieves the coordinates of the eight vertices of a cell based on grid indices.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
GetCellVerticesFromGrid()

Definition at line 405 of file walkingsearch.c.

407{
408
409 PetscFunctionBeginUser;
411 // Validate input pointers
412 if (coor == NULL) {
413 LOG_ALLOW(LOCAL,LOG_ERROR, "'coor' is NULL.\n");
414 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input array 'coor' is NULL.");
415 }
416 if (cell == NULL) {
417 LOG_ALLOW(LOCAL,LOG_ERROR, "'cell' is NULL.\n");
418 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output parameter 'cell' is NULL.");
419 }
420
421 // Assign vertices based on grid indices matching the figure
422 // Vertex numbering follows the convention depicted in the figure
423 cell->vertices[0] = coor[idz][idy][idx]; // Vertex 0: (i, j, k)
424 cell->vertices[1] = coor[idz][idy][idx+1]; // Vertex 1: (i+1, j, k)
425 cell->vertices[2] = coor[idz][idy+1][idx+1]; // Vertex 2: (i+1, j+1, k)
426 cell->vertices[3] = coor[idz][idy+1][idx]; // Vertex 3: (i, j+1, k)
427 cell->vertices[4] = coor[idz+1][idy+1][idx]; // Vertex 4: (i, j+1, k+1)
428 cell->vertices[5] = coor[idz+1][idy+1][idx+1]; // Vertex 5: (i+1, j+1, k+1)
429 cell->vertices[6] = coor[idz+1][idy][idx+1]; // Vertex 6: (i+1, j, k+1)
430 cell->vertices[7] = coor[idz+1][idy][idx]; // Vertex 7: (i, j, k+1)
431
432 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Retrieved vertices for cell (%d, %d, %d).\n", idx, idy, idz);
433
435 PetscFunctionReturn(0); // Indicate successful execution
436}
Here is the caller graph for this function:

◆ InitializeTraversalParameters()

PetscErrorCode InitializeTraversalParameters ( UserCtx user,
Particle particle,
PetscInt *  idx,
PetscInt *  idy,
PetscInt *  idz,
PetscInt *  traversal_steps 
)

Initializes traversal parameters for locating a particle.

This function sets the initial cell indices based on the local grid boundaries and initializes the traversal step counter.

Parameters
[in]userPointer to the user-defined context containing grid information.
[in]particlePointer to the Particle structure containing its location.
[out]idxPointer to store the initial i-index of the cell.
[out]idyPointer to store the initial j-index of the cell.
[out]idzPointer to store the initial k-index of the cell.
[out]traversal_stepsPointer to store the initial traversal step count.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Initializes traversal parameters for locating a particle.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
InitializeTraversalParameters()

Definition at line 446 of file walkingsearch.c.

447{
448 PetscErrorCode ierr;
449 DMDALocalInfo info;
450
451 PetscFunctionBeginUser;
453
454 // Validate input pointers
455 if (user == NULL || particle == NULL || idx == NULL || idy == NULL || idz == NULL || traversal_steps == NULL) {
456 LOG_ALLOW(LOCAL,LOG_ERROR, "One or more input pointers are NULL.\n");
457 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "One or more input pointers are NULL.");
458 }
459
460 // Get grid information (needed for fallback start and potentially validation)
461 ierr = DMDAGetLocalInfo(user->da, &info); CHKERRQ(ierr);
462
463 // --- Check if the particle has a valid previous cell ID ---
464 // Assuming particle->cell stores the *global* indices
465 if (particle->cell[0] >= 0 && particle->cell[1] >= 0 && particle->cell[2] >= 0) {
466
467 // It sees a valid cell ID exists.
468 // Before using it, it explicitly checks if this cell is accessible.
469 PetscBool is_handoff_cell_valid;
470 ierr = CheckCellWithinLocalGrid(user, particle->cell[0], particle->cell[1], particle->cell[2], &is_handoff_cell_valid); CHKERRQ(ierr);
471
472 if (is_handoff_cell_valid) {
473 // FAST PATH: The check passed. The cell is safe. Use it.
474 *idx = particle->cell[0];
475 *idy = particle->cell[1];
476 *idz = particle->cell[2];
477
478 LOG_ALLOW(LOCAL,LOG_DEBUG, "Particle %lld has previous cell (%d, %d, %d). Starting search there.\n",
479 (long long)particle->PID, *idx, *idy, *idz); // Cast id to long long for printing PetscInt64
480
481 } else {
482 // SAFE FALLBACK: The check failed! The handoff cell is NOT safe.
483 // Discard the unsafe handoff cell and revert to starting at the
484 // guaranteed-safe local corner.
485 *idx = info.xs;
486 *idy = info.ys;
487 *idz = info.zs;
488 }
489 } else {
490 // No valid previous cell ID (e.g., -1,-1,-1 or first time).
491 // IMPROVED: Use distance-based multi-seed approach to find the closest strategic cell.
492 // Sample the 6 face centers + volume center (7 total candidates) and start from the closest.
493
494 Cmpnts ***cent;
495
496 // Get local cell center array (lCent)
497 // For cell (i,j,k), the center is at cent[k+1][j+1][i+1]
498 ierr = DMDAVecGetArrayRead(user->fda, user->lCent, &cent); CHKERRQ(ierr);
499
500 // Define 7 strategic sampling points: 6 face centers + 1 volume center
501 PetscInt candidates[7][3];
502 const char* candidate_names[7] = {"X-min face", "X-max face", "Y-min face",
503 "Y-max face", "Z-min face", "Z-max face", "Volume center"};
504
505 // Calculate middle indices for each dimension
506 PetscInt mid_i = info.xs + (info.xm - 1) / 2;
507 PetscInt mid_j = info.ys + (info.ym - 1) / 2;
508 PetscInt mid_k = info.zs + (info.zm - 1) / 2;
509 PetscInt max_i = info.xs + info.xm - 2;
510 PetscInt max_j = info.ys + info.ym - 2;
511 PetscInt max_k = info.zs + info.zm - 2;
512
513 // Clamp max indices to ensure valid cells
514 if (max_i < info.xs) max_i = info.xs;
515 if (max_j < info.ys) max_j = info.ys;
516 if (max_k < info.zs) max_k = info.zs;
517
518 // X-min face center (i=min, j=mid, k=mid)
519 candidates[0][0] = info.xs; candidates[0][1] = mid_j; candidates[0][2] = mid_k;
520 // X-max face center (i=max, j=mid, k=mid)
521 candidates[1][0] = max_i; candidates[1][1] = mid_j; candidates[1][2] = mid_k;
522 // Y-min face center (i=mid, j=min, k=mid)
523 candidates[2][0] = mid_i; candidates[2][1] = info.ys; candidates[2][2] = mid_k;
524 // Y-max face center (i=mid, j=max, k=mid)
525 candidates[3][0] = mid_i; candidates[3][1] = max_j; candidates[3][2] = mid_k;
526 // Z-min face center (i=mid, j=mid, k=min)
527 candidates[4][0] = mid_i; candidates[4][1] = mid_j; candidates[4][2] = info.zs;
528 // Z-max face center (i=mid, j=mid, k=max)
529 candidates[5][0] = mid_i; candidates[5][1] = mid_j; candidates[5][2] = max_k;
530 // Volume center (i=mid, j=mid, k=mid)
531 candidates[6][0] = mid_i; candidates[6][1] = mid_j; candidates[6][2] = mid_k;
532
533 // Find the closest candidate cell
534 PetscReal min_distance = PETSC_MAX_REAL;
535 PetscInt best_candidate = 6; // Default to volume center
536
537 for (PetscInt i = 0; i < 7; i++) {
538 PetscInt ci = candidates[i][0];
539 PetscInt cj = candidates[i][1];
540 PetscInt ck = candidates[i][2];
541
542 // Get cell center coordinates: cent[k+1][j+1][i+1] for cell (i,j,k)
543 Cmpnts cell_center = cent[ck+1][cj+1][ci+1];
544
545 // Calculate Euclidean distance from particle to cell center
546 PetscReal dx = particle->loc.x - cell_center.x;
547 PetscReal dy = particle->loc.y - cell_center.y;
548 PetscReal dz = particle->loc.z - cell_center.z;
549 PetscReal distance = sqrt(dx*dx + dy*dy + dz*dz);
550
551 LOG_ALLOW(LOCAL, LOG_DEBUG, " Candidate %d (%s) at cell (%d,%d,%d): center=(%.3e,%.3e,%.3e), distance=%.3e\n",
552 i, candidate_names[i], ci, cj, ck, cell_center.x, cell_center.y, cell_center.z, distance);
553
554 if (distance < min_distance) {
555 min_distance = distance;
556 best_candidate = i;
557 *idx = ci;
558 *idy = cj;
559 *idz = ck;
560 }
561 }
562
563 // Restore array
564 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCent, &cent); CHKERRQ(ierr);
565
566 LOG_ALLOW(LOCAL, LOG_INFO, "Particle %lld has no valid previous cell. Multi-seed search selected %s at cell (%d,%d,%d) with distance %.3e.\n",
567 (long long)particle->PID, candidate_names[best_candidate], *idx, *idy, *idz, min_distance);
568 }
569
570 // Initialize traversal step counter
571 *traversal_steps = 0;
572
573 // Log the chosen starting point
574 LOG_ALLOW(LOCAL,LOG_INFO, "Traversal for particle %lld initialized to start at cell (%d, %d, %d).\n",
575 (long long)particle->PID, *idx, *idy, *idz);
576
578 PetscFunctionReturn(0);
579}
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
Vec lCent
Definition variables.h:974
PetscInt cell[3]
Definition variables.h:184
Cmpnts loc
Definition variables.h:185
PetscInt64 PID
Definition variables.h:183
PetscErrorCode CheckCellWithinLocalGrid(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, PetscBool *is_within)
Implementation of CheckCellWithinLocalGrid().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckCellWithinLocalGrid()

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.

Parameters
[in]userPointer to the user-defined context containing grid information.
[in]idxThe i-index of the current cell.
[in]idyThe j-index of the current cell.
[in]idzThe k-index of the current cell.
[out]is_withinPointer to a PetscBool that will be set to PETSC_TRUE if within bounds, else PETSC_FALSE.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Checks if the current cell indices are within the local grid boundaries.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
CheckCellWithinLocalGrid()

Definition at line 590 of file walkingsearch.c.

591{
592 PetscErrorCode ierr;
593 DMDALocalInfo info_nodes; // Node information from the DMDA that defines ghost regions (user->fda)
594
595 PetscFunctionBeginUser; // Assuming this is part of your PETSc style
597
598 // Validate inputs
599 if (user == NULL || is_within == NULL) {
600 LOG_ALLOW(LOCAL, LOG_ERROR, "Input pointer is NULL.\n");
601 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input pointer is NULL in CheckCellWithinLocalGrid.");
602 }
603 if (user->fda == NULL) {
604 LOG_ALLOW(LOCAL, LOG_ERROR, "user->fda is NULL.Cannot get ghost info.\n");
605 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "user->fda is NULL. Cannot get ghost info.");
606 }
607
608 // Get node info from user->fda (this DMDA has the ghost layer information for nodes)
609 ierr = DMDAGetLocalInfo(user->fda, &info_nodes); CHKERRQ(ierr);
610
611 // Determine the range of GLOBAL CELL INDICES that are covered by this rank's ghosted NODAL region.
612 // A cell C(i,j,k) has origin node N(i,j,k).
613 // The ghosted nodal region starts at global node index info_nodes.gxs and has info_nodes.gxm nodes.
614
615 // Global starting index of the first cell whose origin node is within the ghosted nodal region.
616 PetscInt gxs_cell_global_start = info_nodes.gxs;
617 PetscInt gys_cell_global_start = info_nodes.gys;
618 PetscInt gzs_cell_global_start = info_nodes.gzs;
619
620 // Number of cells that can be formed starting from nodes within the ghosted nodal region.
621 // If there are N ghosted nodes (info_nodes.gxm), they can be origins for N-1 cells.
622 PetscInt gxm_cell_local_count = (info_nodes.gxm > 0) ? info_nodes.gxm - 1 : 0;
623 PetscInt gym_cell_local_count = (info_nodes.gym > 0) ? info_nodes.gym - 1 : 0;
624 PetscInt gzm_cell_local_count = (info_nodes.gzm > 0) ? info_nodes.gzm - 1 : 0;
625
626 // Global exclusive end index for cells whose origins are in the ghosted nodal region.
627 PetscInt gxe_cell_global_end_exclusive = gxs_cell_global_start + gxm_cell_local_count;
628 PetscInt gye_cell_global_end_exclusive = gys_cell_global_start + gym_cell_local_count;
629 PetscInt gze_cell_global_end_exclusive = gzs_cell_global_start + gzm_cell_local_count;
630
631 // Check if the given global cell index (idx, idy, idz) falls within this range.
632 // This means the origin node of cell (idx,idy,idz) is within the rank's accessible ghosted node region,
633 // and that node can indeed serve as a cell origin (i.e., it's not the very last node in the ghosted region).
634 if (idx >= gxs_cell_global_start && idx < gxe_cell_global_end_exclusive &&
635 idy >= gys_cell_global_start && idy < gye_cell_global_end_exclusive &&
636 idz >= gzs_cell_global_start && idz < gze_cell_global_end_exclusive) {
637 *is_within = PETSC_TRUE;
638 } else {
639 *is_within = PETSC_FALSE;
640 }
641
642 LOG_ALLOW(LOCAL, LOG_DEBUG, "Cell (origin node glob idx) (%d, %d, %d) is %s the ghosted local grid (covered cell origins x:[%d..%d), y:[%d..%d), z:[%d..%d)).\n",
643 idx, idy, idz, (*is_within) ? "within" : "outside",
644 gxs_cell_global_start, gxe_cell_global_end_exclusive,
645 gys_cell_global_start, gye_cell_global_end_exclusive,
646 gzs_cell_global_start, gze_cell_global_end_exclusive);
647
649 PetscFunctionReturn(0);
650}
Here is the caller graph for this function:

◆ RetrieveCurrentCell()

PetscErrorCode RetrieveCurrentCell ( UserCtx user,
PetscInt  idx,
PetscInt  idy,
PetscInt  idz,
Cell cell 
)

Retrieves the coordinates of the eight vertices of the current cell.

Parameters
[in]userPointer to the user-defined context containing grid information.
[in]idxThe i-index of the current cell.
[in]idyThe j-index of the current cell.
[in]idzThe k-index of the current cell.
[out]cellPointer to a Cell structure to store the cell's vertices.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Retrieves the coordinates of the eight vertices of the current cell.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
RetrieveCurrentCell()

Definition at line 660 of file walkingsearch.c.

661{
662 PetscErrorCode ierr;
663 Vec Coor;
664 Cmpnts ***coor_array;
665 PetscMPIInt rank;
666 DMDALocalInfo info_nodes;
667
668 PetscFunctionBeginUser;
670
671 // Validate input pointers
672 if (user == NULL || cell == NULL) {
673 LOG_ALLOW(LOCAL,LOG_ERROR, "One or more input pointers are NULL.\n");
674 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "One or more input pointers are NULL.");
675 }
676
677 // Get local coordinates
678 ierr = DMGetCoordinatesLocal(user->da, &Coor); CHKERRQ(ierr);
679 ierr = DMDAVecGetArrayRead(user->fda, Coor, &coor_array); CHKERRQ(ierr);
680
681 // Get the local grid information FOR THE GHOSTED ARRAY from user->fda
682 // This info contains the mapping between global and local indices.
683 ierr = DMDAGetLocalInfo(user->fda, &info_nodes); CHKERRQ(ierr);
684
685 PetscInt idx_local = idx; // - info_nodes.gxs;
686 PetscInt idy_local = idy; // - info_nodes.gys;
687 PetscInt idz_local = idz; // - info_nodes.gzs;
688
689 LOG_ALLOW(LOCAL,LOG_VERBOSE," [Rank %d] Getting vertex coordinates for cell: %d,%d,%d whose local coordinates are %d,%d,%d.\n",rank,idx,idy,idz,idx_local,idy_local,idz_local);
690
691 // Get the current cell's vertices
692 ierr = GetCellVerticesFromGrid(coor_array, idx_local, idy_local, idz_local, cell); CHKERRQ(ierr);
693
694 // Restore array
695 ierr = DMDAVecRestoreArrayRead(user->fda, Coor, &coor_array); CHKERRQ(ierr);
696
697 // Get MPI rank for debugging
698 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
699
700 // Debug: Print cell vertices
701 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Cell (%d, %d, %d) vertices \n", idx, idy, idz);
702 ierr = LOG_CELL_VERTICES(cell, rank); CHKERRQ(ierr);
703
705 PetscFunctionReturn(0);
706}
PetscErrorCode LOG_CELL_VERTICES(const Cell *cell, PetscMPIInt rank)
Prints the coordinates of a cell's vertices.
Definition logging.c:208
PetscErrorCode GetCellVerticesFromGrid(Cmpnts ***coor, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Implementation of GetCellVerticesFromGrid().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ EvaluateParticlePosition()

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.

This function evaluates whether a particle located at a specific point p in 3D space is positioned inside the cell, on the boundary of the cell, or outside the cell. The determination is based on the signed distances from the particle to each of the six faces of the cell. The function utilizes the computed distances to ascertain the particle's position with respect to the cell boundaries, considering a threshold to account for floating-point precision.

Parameters
[in]cellA pointer to a Cell structure that defines the cubic cell via its vertices. The cell's geometry is essential for accurately computing the distances to each face.
[in]dA pointer to an array of six PetscReal values that store the signed distances from the particle to each face of the cell. These distances are typically computed using the CalculateDistancesToCellFaces function.
[in]pThe location of the particle in 3D space, represented by the Cmpnts structure. This point is the reference for distance calculations to the cell's faces.
[out]positionA pointer to an integer that will be set based on the particle's position relative to the cell:
  • 0: The particle is inside the cell.
  • 1: The particle is on the boundary of the cell.
  • -1: The particle is outside the cell.
[in]thresholdA PetscReal value that defines the minimum distance below which a computed distance is considered to be zero. This threshold helps in mitigating inaccuracies due to floating-point arithmetic, especially when determining if the particle lies exactly on the boundary.
Returns
PetscErrorCode Returns 0 if the function executes successfully. If an error occurs, a non-zero error code is returned, indicating the type of failure.
Note
  • It is assumed that the d array has been properly allocated and contains valid distance measurements before calling this function.
  • The function relies on CalculateDistancesToCellFaces to accurately compute the signed distances to each face. Any inaccuracies in distance calculations can affect the determination of the particle's position.
  • The threshold parameter should be chosen based on the specific precision requirements of the application to balance between sensitivity and robustness against floating-point errors.
  • The function includes a debug statement that prints the face distances, which can be useful for verifying the correctness of distance computations during development or troubleshooting.

Determines the spatial relationship of a particle relative to a cubic cell.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
EvaluateParticlePosition()

Definition at line 716 of file walkingsearch.c.

717{
718 PetscErrorCode ierr;
719 PetscReal cellSize;
720 PetscReal cellThreshold;
721 PetscFunctionBeginUser;
723
724 // Validate input pointers to ensure they are not NULL, preventing potential segmentation faults.
725 if (cell == NULL || position == NULL) {
726 LOG_ALLOW(LOCAL,LOG_ERROR, "One or more input pointers are NULL.\n");
727 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "One or more input pointers are NULL.");
728 }
729
730 // Compute a local cell size
731 ierr = GetCellCharacteristicSize(cell, &cellSize); CHKERRQ(ierr);
732
733 // scale base threshold by cell size (ex: if threshold = 1e-6 and cell size = 0.01, cellThreshold = 1e-8)
734 cellThreshold = threshold*cellSize;
735
736 // Invoke the function to calculate signed distances from the particle to each face of the cell.
737 // The distances are stored in the array pointed to by 'd'.
738 ierr = CalculateDistancesToCellFaces(p, cell, d, cellThreshold); CHKERRQ(ierr);
739 CHKERRQ(ierr); // Check for errors in distance calculation.
740
741
742 // Catch degenerate-plane error manually:
743 if (ierr == PETSC_ERR_USER) {
745 "Skipping cell due to degenerate face.\n");
746 // We can set *position = -1 here
747 *position = -1; // treat as outside
749 return 0; // not a fatal error, just skip
750 } else {
751 CHKERRQ(ierr);
752 }
753
754
755 // Debugging output: Print the computed distances to each face for verification purposes.
756 LOG_ALLOW(LOCAL,LOG_DEBUG, "Face Distances:\n");
758 CHKERRQ(ierr); // Check for errors in printing distances.
759
760 // Determine the particle's position relative to the cell based on the computed distances.
761 // The function sets the value pointed to by 'position' accordingly:
762 // 0 for inside, 1 (2 or 3) for on the boundary, and -1 for outside.
763 ierr = DeterminePointPosition(d,position);
764 CHKERRQ(ierr); // Check for errors in position determination.
765
767 PetscFunctionReturn(0); // Indicate successful execution of the function.
768}
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:186
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:87
PetscErrorCode LOG_FACE_DISTANCES(PetscReal *d)
Prints the signed distances to each face of the cell.
Definition logging.c:233
PetscErrorCode GetCellCharacteristicSize(const Cell *cell, PetscReal *cellSize)
Implementation of GetCellCharacteristicSize().
PetscErrorCode CalculateDistancesToCellFaces(const Cmpnts p, const Cell *cell, PetscReal *d, const PetscReal threshold)
Implementation of CalculateDistancesToCellFaces().
PetscErrorCode DeterminePointPosition(PetscReal *d, PetscInt *result)
Implementation of DeterminePointPosition().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LocateParticleInGrid()

PetscErrorCode LocateParticleInGrid ( UserCtx user,
Particle particle 
)

Locates the grid cell containing a particle using a walking search.

This function implements a walking search algorithm to find the specific cell (identified by global indices i, j, k) that encloses the particle's physical location (particle->loc).

The search starts from an initial guess cell (either the particle's previously known cell or the corner of the local process domain) and iteratively steps to adjacent cells based on the signed distances from the particle to the faces of the current cell.

Upon successful location (position == 0), the particle's cell field is updated with the found indices (i,j,k), and the corresponding interpolation weights are calculated and stored using the distances (d) relative to the final cell.

Handles particles exactly on cell boundaries by attempting a tie-breaker if the search gets stuck oscillating between adjacent cells due to the boundary condition.

Parameters
[in]userPointer to the UserCtx structure containing grid information (DMDA, coordinates) and domain boundaries.
[in,out]particlePointer to the Particle structure. Its loc field provides the target position. On successful return, its cell and weights fields are updated. On failure, cell is set to {-1, -1, -1} and weights to {0.0, 0.0, 0.0}.
Returns
PetscErrorCode 0 on success. Non-zero error codes may indicate issues during coordinate access, distance calculation, or other internal errors. A return code of 0 does not guarantee the particle was found; check particle->cell[0] >= 0 afterward.
Note
Relies on helper functions like InitializeTraversalParameters, CheckCellWithinLocalGrid, RetrieveCurrentCell, EvaluateParticlePosition, UpdateCellIndicesBasedOnDistances, UpdateParticleWeights, and FinalizeTraversal.
Warning
Ensure particle->loc is set correctly before calling.
The function may fail to find the particle if it lies outside the domain accessible by the current process (including ghost cells) or if MAX_TRAVERSAL steps are exceeded.

◆ FinalizeTraversal()

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.

This function prints the outcome of the traversal, indicating whether the particle was found within a cell or not, and updates the particle's cell indices accordingly.

Parameters
[in]userPointer to the user-defined context containing grid information.
[out]particlePointer to the Particle structure to update with cell indices.
[in]traversal_stepsThe number of traversal steps taken.
[in]cell_foundFlag indicating whether the particle was found within a cell.
[in]idxThe i-index of the found cell.
[in]idyThe j-index of the found cell.
[in]idzThe k-index of the found cell.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Finalizes the traversal by reporting the results.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
FinalizeTraversal()

Definition at line 867 of file walkingsearch.c.

868{
869 PetscFunctionBeginUser;
870 // Validate input pointers
871 if (user == NULL || particle == NULL) {
872 LOG_ALLOW(LOCAL,LOG_ERROR, "One or more input pointers are NULL.\n");
873 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "One or more input pointers are NULL.");
874 }
875
876 if (cell_found) {
877 LOG_ALLOW(LOCAL,LOG_INFO, "Particle located in cell (%d, %d, %d) after %d traversal steps.\n",
878 idx, idy, idz, traversal_steps);
879 }
880 else {
881 LOG_ALLOW(LOCAL,LOG_WARNING, "Particle could not be located within the grid after %d traversal steps.\n", (PetscInt)traversal_steps);
882 particle->cell[0] = -1;
883 particle->cell[1] = -1;
884 particle->cell[2] = -1;
885 }
886
887 LOG_ALLOW(LOCAL, LOG_INFO, "Completed final traversal sync across all ranks.\n");
888
889
891 PetscFunctionReturn(0);
892}

◆ FindOwnerOfCell()

PetscErrorCode FindOwnerOfCell ( UserCtx user,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscMPIInt *  owner_rank 
)

Finds the MPI rank that owns a given global cell index.

This function performs a linear search through the pre-computed decomposition map (user->RankCellInfoMap) to determine which process is responsible for the cell with global indices (i, j, k). It is the definitive method for resolving cell ownership in the "Walk and Handoff" migration algorithm.

If the provided indices are outside the range of any rank (e.g., negative or beyond the global domain), the function will not find an owner and owner_rank will be set to -1.

Parameters
[in]userPointer to the UserCtx structure, which must contain the initialized RankCellInfoMap and num_ranks.
[in]iGlobal i-index of the cell to find.
[in]jGlobal j-index of the cell to find.
[in]kGlobal k-index of the cell to find.
[out]owner_rankPointer to a PetscMPIInt where the resulting owner rank will be stored. It is set to -1 if no owner is found.
Returns
PetscErrorCode 0 on success, or a non-zero PETSc error code on failure.

Finds the MPI rank that owns a given global cell index.

Local to this translation unit.

Definition at line 900 of file walkingsearch.c.

901{
902 PetscErrorCode ierr;
903 PetscMPIInt size;
904
905 PetscFunctionBeginUser;
906
908
909 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
910
911 // --- 1. Input Validation ---
912 if (!user || !user->RankCellInfoMap) {
913 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "UserCtx or RankCellInfoMap is not initialized in FindOwnerOfCell.");
914 }
915 if (!owner_rank) {
916 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer owner_rank is NULL in FindOwnerOfCell.");
917 }
918
919 // --- 2. Linear Search through the Decomposition Map ---
920 // Initialize to a "not found" state.
921 *owner_rank = -1;
922
923 // Loop through the map, which contains the ownership info for every rank 'r'.
924 for (PetscMPIInt r = 0; r < size; ++r) {
925 const RankCellInfo *info = &user->RankCellInfoMap[r];
926
927 // A rank owns a cell if the cell's index is within its start (inclusive)
928 // and end (exclusive) range for all three dimensions.
929 if ((i >= info->xs_cell && i < info->xs_cell + info->xm_cell) &&
930 (j >= info->ys_cell && j < info->ys_cell + info->ym_cell) &&
931 (k >= info->zs_cell && k < info->zs_cell + info->zm_cell))
932 {
933 *owner_rank = r; // We found the owner.
934 break; // The search is over, exit the loop.
935 }
936 }
937
938 // --- 3. Logging for Diagnostics ---
939 // This is extremely useful for debugging particle migration issues.
940 if (*owner_rank == -1) {
941 LOG_ALLOW(LOCAL, LOG_DEBUG, "No owner found for global cell (%d, %d, %d). It is likely outside the domain.\n", i, j, k);
942 } else {
943 LOG_ALLOW(LOCAL, LOG_DEBUG, "Owner of cell (%d, %d, %d) is Rank %d.\n", i, j, k, *owner_rank);
944 }
945
947 PetscFunctionReturn(0);
948}
PetscInt ys_cell
Definition variables.h:204
PetscInt xs_cell
Definition variables.h:204
PetscInt zm_cell
Definition variables.h:205
PetscInt zs_cell
Definition variables.h:204
PetscInt xm_cell
Definition variables.h:205
RankCellInfo * RankCellInfoMap
Definition variables.h:995
PetscInt ym_cell
Definition variables.h:205
A lean struct to hold the global cell ownership range for a single MPI rank.
Definition variables.h:203
Here is the caller graph for this function:

◆ LocateParticleOrFindMigrationTarget()

PetscErrorCode LocateParticleOrFindMigrationTarget ( UserCtx user,
Particle particle,
ParticleLocationStatus status_out 
)

Locates a particle's host cell or identifies its migration target using a robust walk search.

This is the core search engine. It starts from a guess cell and walks through the grid. It returns a definitive, actionable status indicating the outcome:

  • ACTIVE_AND_LOCATED: The particle was found in a cell on the current rank.
  • MIGRATING_OUT: The particle was found to belong to another rank. particle->destination_rank is set.
  • LOST: The search failed to find the particle within the global domain.

This function is globally aware and can walk across MPI rank boundaries. It contains robust checks for global domain boundaries and a tie-breaker for numerically "stuck" particles on cell faces.

Parameters
[in]userPointer to the UserCtx containing all grid and domain info.
[in,out]particlePointer to the Particle struct. Its fields are updated based on the search outcome.
[out]status_outThe final, actionable status of the particle after the search.
Returns
PetscErrorCode 0 on success, or a non-zero PETSc error code on failure.
Note
Testing status: This function is exercised indirectly by the orchestrator tests, but direct branch pinning for boundary clamp, ghost-region handoff, tie-breaker, LOST, and MIGRATING_OUT outcomes is still part of the next-gap test backlog.

Locates a particle's host cell or identifies its migration target using a robust walk search.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
LocateParticleOrFindMigrationTarget()

Definition at line 959 of file walkingsearch.c.

962{
963 PetscErrorCode ierr;
964 PetscMPIInt rank;
965
966 // --- Search State Variables ---
967 PetscInt idx, idy, idz; // Current search cell global indices
968 PetscInt traversal_steps; // Counter to prevent infinite loops
969 PetscBool search_concluded = PETSC_FALSE; // Flag to terminate the main while loop
970
971 // --- Oscillation/Stuck Loop Detection Variables ---
972 PetscInt repeatedIndexCount = 0;
973 PetscInt prevIdx = PETSC_MIN_INT, prevIdy = PETSC_MIN_INT, prevIdz = PETSC_MIN_INT;
974 PetscInt last_position_result = -999;
975
976 PetscFunctionBeginUser;
978 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
979 if (user && user->simCtx) {
983 }
984 }
985
986 // --- 1. Initialize the Search ---
987 ierr = InitializeTraversalParameters(user, particle, &idx, &idy, &idz, &traversal_steps); CHKERRQ(ierr);
988
989 LOG_ALLOW(LOCAL,LOG_VERBOSE, " The Threshold for considering a particle to be at a face is %.16f.\n",DISTANCE_THRESHOLD);
990
991 LOG_ALLOW(LOCAL,LOG_TRACE," [PID %lld]Traversal Initiated at : i = %d, j = %d, k = %d.\n",(long long)particle->PID,idx,idy,idz);
992
993 // --- 2. Main Walking Search Loop ---
994 while (!search_concluded && traversal_steps < MAX_TRAVERSAL) {
995 traversal_steps++;
996
997 // --- 2a. GLOBAL Domain Boundary Check ---
998 // IMPROVED: Instead of failing immediately when hitting a boundary, clamp the indices
999 // to the boundary and continue searching. This allows the search to explore other
1000 // directions that might lead to the particle.
1001 PetscBool hit_boundary = PETSC_FALSE;
1002 if (idx < 0) {
1003 idx = 0;
1004 hit_boundary = PETSC_TRUE;
1006 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global i-min boundary, clamped to idx=0.\n", (long long)particle->PID);
1007 }
1008 if (idx >= (user->IM - 1)) {
1009 idx = user->IM - 2;
1010 hit_boundary = PETSC_TRUE;
1012 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global i-max boundary, clamped to idx=%d.\n", (long long)particle->PID, idx);
1013 }
1014 if (idy < 0) {
1015 idy = 0;
1016 hit_boundary = PETSC_TRUE;
1018 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global j-min boundary, clamped to idy=0.\n", (long long)particle->PID);
1019 }
1020 if (idy >= (user->JM - 1)) {
1021 idy = user->JM - 2;
1022 hit_boundary = PETSC_TRUE;
1024 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global j-max boundary, clamped to idy=%d.\n", (long long)particle->PID, idy);
1025 }
1026 if (idz < 0) {
1027 idz = 0;
1028 hit_boundary = PETSC_TRUE;
1030 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global k-min boundary, clamped to idz=0.\n", (long long)particle->PID);
1031 }
1032 if (idz >= (user->KM - 1)) {
1033 idz = user->KM - 2;
1034 hit_boundary = PETSC_TRUE;
1036 LOG_ALLOW(LOCAL, LOG_DEBUG, "[PID %lld]: Hit global k-max boundary, clamped to idz=%d.\n", (long long)particle->PID, idz);
1037 }
1038
1039 if (hit_boundary) {
1040 LOG_ALLOW(LOCAL, LOG_INFO, "[PID %lld]: Hit GLOBAL domain boundary. Clamped to boundary cell (%d,%d,%d) and continuing search.\n",
1041 (long long)particle->PID, idx, idy, idz);
1042 }
1043
1044 // --- 2b. LOCAL GHOST REGION CHECK (PREVENTS SEGV) ---
1045 // Before trying to access cell data, check if we have it.
1046 PetscBool is_cell_local;
1047 ierr = CheckCellWithinLocalGrid(user, idx, idy, idz, &is_cell_local); CHKERRQ(ierr);
1048 if (!is_cell_local) {
1049 // We have walked outside the local rank's ghost region.
1050 // This definitively means the particle belongs to another rank.
1051 // Conclude the search here; the current (idx,idy,idz) is the handoff cell.
1052 LOG_ALLOW(LOCAL, LOG_INFO, "[PID %lld]: Walked outside local ghost region to cell (%d,%d,%d). Concluding search for handoff.\n",
1053 (long long)particle->PID, idx, idy, idz);
1054 search_concluded = PETSC_TRUE;
1055 continue; // Skip the rest of the loop; proceed to finalization.
1056 }
1057
1058 // --- 2c. Stuck Loop Detection & Enhanced Tie-Breaker ---
1059 if (idx == prevIdx && idy == prevIdy && idz == prevIdz) {
1060 repeatedIndexCount++;
1061 if (repeatedIndexCount > REPEAT_COUNT_THRESHOLD) {
1062 // Only apply tie-breaker if we are stuck for the right reason (on a boundary)
1063 if (last_position_result >= 1) {
1065 LOG_ALLOW(LOCAL, LOG_WARNING, "[PID %lld]: Stuck on boundary of cell (%d,%d,%d) for %d steps. Applying enhanced tie-breaker.\n",
1066 (long long)particle->PID, idx, idy, idz, repeatedIndexCount);
1067
1068 // Re-evaluate at the stuck cell to get definitive weights
1069 Cell final_cell;
1070 PetscReal final_d[NUM_FACES];
1071 PetscInt final_position; // Dummy variable
1072
1073 ierr = RetrieveCurrentCell(user, idx, idy, idz, &final_cell); CHKERRQ(ierr);
1074 ierr = EvaluateParticlePosition(&final_cell, final_d, particle->loc, &final_position, DISTANCE_THRESHOLD);
1075
1076 if (ierr == 0) { // If evaluation succeeded
1077 ierr = UpdateParticleWeights(final_d, particle); CHKERRQ(ierr);
1078 search_concluded = PETSC_TRUE; // Conclude search, accepting this cell.
1079 } else { // Evaluation failed (e.g., degenerate cell)
1080 LOG_ALLOW(LOCAL, LOG_ERROR, "[PID %lld]: Tie-breaker failed during final evaluation at cell (%d,%d,%d). Search fails.\n",
1081 (long long)particle->PID, idx, idy, idz);
1082 idx = -1; // Invalidate result
1083 search_concluded = PETSC_TRUE;
1084 }
1085 } else { // Stuck for the wrong reason (not on a boundary)
1086 LOG_ALLOW(LOCAL, LOG_ERROR, "[PID %lld]: Search is stuck at cell (%d,%d,%d) but not on a boundary. This indicates a logic error. Failing search.\n",
1087 (long long)particle->PID, idx, idy, idz);
1088 idx = -1; // Invalidate result
1089 search_concluded = PETSC_TRUE;
1090 }
1091 if(search_concluded) continue;
1092 }
1093 } else {
1094 repeatedIndexCount = 0;
1095 }
1096 prevIdx = idx; prevIdy = idy; prevIdz = idz;
1097
1098 // --- 2d. Geometric Evaluation ---
1099 Cell current_cell;
1100 PetscReal distances[NUM_FACES];
1101 PetscInt position_in_cell;
1102
1103 ierr = RetrieveCurrentCell(user, idx, idy, idz, &current_cell); CHKERRQ(ierr);
1104 ierr = EvaluateParticlePosition(&current_cell, distances, particle->loc, &position_in_cell, DISTANCE_THRESHOLD); CHKERRQ(ierr);
1105 last_position_result = position_in_cell;
1106
1107 // --- 2e. Decision Making ---
1108 if (position_in_cell >= 0) { // Particle is INSIDE or ON THE BOUNDARY
1109 search_concluded = PETSC_TRUE;
1110 ierr = UpdateParticleWeights(distances, particle); CHKERRQ(ierr);
1111 } else { // Particle is OUTSIDE
1112 ierr = UpdateCellIndicesBasedOnDistances(distances, &idx, &idy, &idz); CHKERRQ(ierr);
1113 }
1114 }
1115
1116 user->simCtx->searchMetrics.traversalStepsSum += traversal_steps;
1118 traversal_steps);
1119
1120 // --- 3. Finalize and Determine Actionable Status ---
1121 if (idx == -1 || (!search_concluded && traversal_steps >= MAX_TRAVERSAL)) {
1122 if (idx != -1) {
1124 LOG_ALLOW(LOCAL, LOG_ERROR, "[PID %lld]: Search FAILED, exceeded MAX_TRAVERSAL limit of %d.\n",
1125 (long long)particle->PID, MAX_TRAVERSAL);
1126 }
1127 *status_out = LOST;
1128 particle->cell[0] = -1; particle->cell[1] = -1; particle->cell[2] = -1;
1129 } else {
1130 // Search succeeded in finding a candidate cell, now determine its owner.
1131 PetscMPIInt owner_rank;
1132 ierr = FindOwnerOfCell(user, idx, idy, idz, &owner_rank); CHKERRQ(ierr);
1133
1134 LOG_ALLOW(LOCAL,LOG_TRACE," [PID %ld] Owner rank : %d.\n",particle->PID,owner_rank);
1135
1136 // Always update the particle's cell index. It's a good guess for the receiving rank.
1137 particle->cell[0] = idx; particle->cell[1] = idy; particle->cell[2] = idz;
1138
1139 if (owner_rank == rank) {
1140 *status_out = ACTIVE_AND_LOCATED;
1141 } else if (owner_rank != -1) {
1142 // Particle belongs to another rank. Return the direct, actionable status.
1143 *status_out = MIGRATING_OUT;
1144 particle->destination_rank = owner_rank;
1145 } else { // Found a valid index, but no owner in the map.
1146 *status_out = LOST;
1147 particle->cell[0] = -1; particle->cell[1] = -1; particle->cell[2] = -1;
1148 }
1149 }
1150
1151 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d][PID %ld] Search complete.\n",rank,particle->PID);
1152
1153 // --- 4. Report the Final Outcome ---
1154 ierr = ReportSearchOutcome(particle, *status_out, traversal_steps); CHKERRQ(ierr);
1155
1157 PetscFunctionReturn(0);
1158}
PetscErrorCode UpdateParticleWeights(PetscReal *d, Particle *particle)
Updates a particle's interpolation weights based on distances to cell faces.
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:33
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:909
@ LOST
Definition variables.h:141
@ ACTIVE_AND_LOCATED
Definition variables.h:139
@ MIGRATING_OUT
Definition variables.h:140
PetscInt64 boundaryClampCount
Definition variables.h:248
PetscInt KM
Definition variables.h:920
PetscInt64 traversalStepsSum
Definition variables.h:243
PetscInt currentSettlementPass
Definition variables.h:252
PetscInt64 reSearchCount
Definition variables.h:244
PetscMPIInt destination_rank
Definition variables.h:189
PetscInt64 maxTraversalSteps
Definition variables.h:245
PetscInt JM
Definition variables.h:920
SearchMetricsState searchMetrics
Definition variables.h:840
PetscInt IM
Definition variables.h:920
PetscInt64 searchAttempts
Definition variables.h:239
PetscInt64 tieBreakCount
Definition variables.h:247
PetscInt64 maxTraversalFailCount
Definition variables.h:246
Defines the vertices of a single hexahedral grid cell.
Definition variables.h:177
#define DISTANCE_THRESHOLD
#define MAX_TRAVERSAL
PetscErrorCode EvaluateParticlePosition(const Cell *cell, PetscReal *d, const Cmpnts p, PetscInt *position, const PetscReal threshold)
Implementation of EvaluateParticlePosition().
PetscErrorCode ReportSearchOutcome(const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
Implementation of ReportSearchOutcome().
#define REPEAT_COUNT_THRESHOLD
PetscErrorCode UpdateCellIndicesBasedOnDistances(PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz)
Internal helper implementation: UpdateCellIndicesBasedOnDistances().
PetscErrorCode FindOwnerOfCell(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscMPIInt *owner_rank)
Internal helper implementation: FindOwnerOfCell().
PetscErrorCode RetrieveCurrentCell(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Implementation of RetrieveCurrentCell().
PetscErrorCode InitializeTraversalParameters(UserCtx *user, Particle *particle, PetscInt *idx, PetscInt *idy, PetscInt *idz, PetscInt *traversal_steps)
Implementation of InitializeTraversalParameters().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReportSearchOutcome()

PetscErrorCode ReportSearchOutcome ( const Particle particle,
ParticleLocationStatus  status,
PetscInt  traversal_steps 
)

Logs the final outcome of the particle location search.

Parameters
particleParticle whose location attempt has completed.
statusFinal locate/migration status assigned to the particle.
traversal_stepsNumber of cell-to-cell traversal steps attempted.
Returns
PetscErrorCode 0 on success.

Logs the final outcome of the particle location search.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/walkingsearch.h.

See also
ReportSearchOutcome()

Definition at line 1169 of file walkingsearch.c.

1172{
1173 PetscFunctionBeginUser;
1175 switch (status) {
1176 case ACTIVE_AND_LOCATED:
1177 LOG_ALLOW(LOCAL, LOG_INFO, "Search SUCCESS [PID %lld]: Located in global cell (%d, %d, %d) after %d steps.\n",
1178 (long long)particle->PID, particle->cell[0], particle->cell[1], particle->cell[2], traversal_steps);
1179 break;
1180 case MIGRATING_OUT:
1181 LOG_ALLOW(LOCAL, LOG_INFO, "Search SUCCESS [PID %lld]: Identified for migration to Rank %d. Handoff cell is (%d, %d, %d) after %d steps.\n",
1182 (long long)particle->PID, particle->destination_rank, particle->cell[0], particle->cell[1], particle->cell[2], traversal_steps);
1183 break;
1184 case LOST:
1185 LOG_ALLOW(LOCAL, LOG_WARNING, "Search FAILED [PID %lld]: Particle is LOST after %d steps.\n",
1186 (long long)particle->PID, traversal_steps);
1187 break;
1188 default:
1189 LOG_ALLOW(LOCAL, LOG_WARNING, "Search ended with unexpected status %d for PID %lld.\n", status, (long long)particle->PID);
1190 break;
1191 }
1193 PetscFunctionReturn(0);
1194}
Here is the caller graph for this function:

◆ UpdateCellIndicesBasedOnDistances()

PetscErrorCode UpdateCellIndicesBasedOnDistances ( PetscReal  d[NUM_FACES],
PetscInt *  idx,
PetscInt *  idy,
PetscInt *  idz 
)

Updates the cell indices based on the signed distances to each face.

This function modifies the cell indices (idx, idy, idz) to move towards the direction where the particle is likely to be located, based on positive distances indicating that the particle is outside in that particular direction.

Parameters
[in]dAn array of six PetscReal values representing the signed distances to each face:
  • d[LEFT]: Left Face
  • d[RIGHT]: Right Face
  • d[BOTTOM]: Bottom Face
  • d[TOP]: Top Face
  • d[FRONT]: Front Face
  • d[BACK]: Back Face
[out]idxPointer to the i-index of the cell to be updated.
[out]idyPointer to the j-index of the cell to be updated.
[out]idzPointer to the k-index of the cell to be updated.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Updates the cell indices based on the signed distances to each face.

Local to this translation unit.

Definition at line 776 of file walkingsearch.c.

777{
778
779 PetscFunctionBeginUser;
781 /*
782 PetscInt cxm,cxs; // maximum & minimum cell ID in x
783 PetscInt cym,cys; // maximum & minimum cell ID in y
784 PetscInt czm,czs; // maximum & minimum cell ID in z
785
786 cxs = info->xs; cxm = cxs + info->xm - 2;
787 cys = info->ys; cym = cys + info->ym - 2;
788 czs = info->zs; czm = czs + info->zm - 2;
789 */
790
791 // LOG_ALLOW(LOCAL, LOG_DEBUG, "Received d: "
792 // "d[LEFT=%d]=%.3e, d[RIGHT=%d]=%.3e, d[BOTTOM=%d]=%.3e, "
793 // "d[TOP=%d]=%.3e, d[FRONT=%d]=%.3e, d[BACK=%d]=%.3e\n",
794 // LEFT, d[LEFT], RIGHT, d[RIGHT], BOTTOM, d[BOTTOM],
795 // TOP, d[TOP], FRONT, d[FRONT], BACK, d[BACK]);
796 // LOG_ALLOW(LOCAL, LOG_DEBUG, "Raw d: "
797 // "[%.3e, %.3e, %.3e, %.3e, %.3e, %.3e]\n",
798 // d[0], d[1], d[2], d[3], d[4], d[5]);
799
800 // Validate input pointers
801 if (d == NULL) {
802 LOG_ALLOW(LOCAL,LOG_ERROR, "'d' is NULL.\n");
803 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input array 'd' is NULL.");
804 }
805 if (idx == NULL || idy == NULL || idz == NULL) {
806 LOG_ALLOW(LOCAL,LOG_ERROR, "One or more index pointers are NULL.\n");
807 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "One or more index pointers are NULL.");
808 }
809
810 // Debug: Print current face distances
811 LOG_ALLOW(LOCAL,LOG_DEBUG, "Current Face Distances:\n");
813
814 // Update k-direction based on FRONT and BACK distances
815 if (d[FRONT] < 0.0) {
816 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[FRONT] < 0.0, incrementing idz.\n");
817 (*idz) += 1;
818 }
819 else if(d[BACK] < 0.0){
820 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[BACK] < 0.0, decrementing idz.\n");
821 (*idz) -= 1;
822 }
823
824 // Update i-direction based on LEFT and RIGHT distances
825 if (d[LEFT] < 0.0) {
826 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[LEFT] < 0.0, decrementing idx.\n");
827 (*idx) -= 1;
828 }
829 else if (d[RIGHT] < 0.0) {
830 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[RIGHT] < 0.0, incrementing idx.\n");
831 (*idx) += 1;
832 }
833
834 // Update j-direction based on BOTTOM and TOP distances
835 if (d[BOTTOM] < 0.0) {
836 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[BOTTOM] < 0.0, decrementing idy.\n");
837 (*idy) -= 1;
838 }
839 else if (d[TOP] < 0.0) {
840 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Condition met: d[TOP] < 0.0, incrementing idy.\n");
841 (*idy) += 1;
842 }
843
844 /*
845 // The 'cell' corners you can reference go from [xs .. xs+xm-1], but
846 // to form a valid cell in x, you need (idx+1) in range, so max is (xs+xm-2).
847 *idx = PetscMax(cxs, PetscMin(*idx, cxm));
848 *idy = PetscMax(cys, PetscMin(*idy, cym));
849 *idz = PetscMax(czs, PetscMin(*idz, czm));
850 */
851
852 LOG_ALLOW(LOCAL,LOG_DEBUG, "Updated Indices - idx, idy, idz: %d, %d, %d\n", *idx, *idy, *idz);
853
855 PetscFunctionReturn(0); // Indicate successful execution
856}
Here is the call graph for this function:
Here is the caller graph for this function: