PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
walkingsearch.c File Reference
#include "walkingsearch.h"
#include "logging.h"
#include <petsc.h>
#include <stdbool.h>
#include <math.h>
Include dependency graph for walkingsearch.c:

Go to the source code of this file.

Macros

#define MAX_TRAVERSAL   1000
 
#define DISTANCE_THRESHOLD   1e-11
 
#define REPEAT_COUNT_THRESHOLD   5
 

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 GLOBAL CELL indices are within the LOCAL GHOSTED grid boundaries accessible by this MPI process.
 
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 UpdateCellIndicesBasedOnDistancesTEST (PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz)
 Updates the cell indices based on the signed distances to each face.
 
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_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 ReportSearchOutcome (const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
 Logs the final outcome of the particle location search.
 

Macro Definition Documentation

◆ MAX_TRAVERSAL

#define MAX_TRAVERSAL   1000

Definition at line 10 of file walkingsearch.c.

◆ DISTANCE_THRESHOLD

#define DISTANCE_THRESHOLD   1e-11

Definition at line 11 of file walkingsearch.c.

◆ REPEAT_COUNT_THRESHOLD

#define REPEAT_COUNT_THRESHOLD   5

Definition at line 12 of file walkingsearch.c.

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.

Definition at line 25 of file walkingsearch.c.

26{
27 PetscErrorCode ierr = 0;
28 if (!cell || !cellSize) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
29 "GetCellCharacteristicSize: Null pointer(s).");
30
31 // A simple approach: compute the average of the distances between
32 // all pairs of adjacent vertices that share an edge. That gives
33 // a typical measure of cell dimension. For a uniform grid, you
34 // could do something simpler.
35
36 PetscInt edges[12][2] = {
37 {0,1},{1,2},{2,3},{3,0}, // bottom face edges
38 {4,5},{5,6},{6,7},{7,4}, // top face edges
39 {0,7},{1,6},{2,5},{3,4} // vertical edges
40 };
41
42 PetscReal totalEdgeLen = 0.0;
43 for (PetscInt i=0; i<12; i++) {
44 PetscInt vA = edges[i][0];
45 PetscInt vB = edges[i][1];
46 Cmpnts A = cell->vertices[vA];
47 Cmpnts B = cell->vertices[vB];
48 PetscReal dx = B.x - A.x;
49 PetscReal dy = B.y - A.y;
50 PetscReal dz = B.z - A.z;
51 PetscReal edgeLen = sqrt(dx*dx + dy*dy + dz*dz);
52 totalEdgeLen += edgeLen;
53 }
54
55 // Average edge length
56 *cellSize = totalEdgeLen / 12.0;
57
58 return ierr;
59}
PetscScalar x
Definition variables.h:100
PetscScalar z
Definition variables.h:100
PetscScalar y
Definition variables.h:100
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Definition variables.h:160
A 3D point or vector with PetscScalar components.
Definition variables.h:99
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.

Definition at line 102 of file walkingsearch.c.

105{
106 PetscErrorCode ierr = 0;
107 PetscMPIInt rank;
108
109 PetscFunctionBeginUser;
110
111 if (d_signed == NULL) {
112 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
113 LOG_ALLOW(LOCAL, LOG_ERROR, "ComputeSignedDistanceToPlane - Output pointer 'd_signed' is NULL on rank %d.\n", rank);
114 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer 'd_signed' must not be NULL.");
115 }
116
117 LOG_ALLOW(LOCAL, LOG_DEBUG, "ComputeSignedDistanceToPlane - Target point: (%.6e, %.6e, %.6e)\n", p_target.x, p_target.y, p_target.z);
118 LOG_ALLOW(LOCAL, LOG_DEBUG, " Cell Centroid: (%.6e, %.6e, %.6e)\n", cell_centroid.x, cell_centroid.y, cell_centroid.z);
119 LOG_ALLOW(LOCAL, LOG_DEBUG, " Face Vertices:\n");
120 LOG_ALLOW(LOCAL, LOG_DEBUG, " v1: (%.6e, %.6e, %.6e)\n", v1.x, v1.y, v1.z);
121 LOG_ALLOW(LOCAL, LOG_DEBUG, " v2: (%.6e, %.6e, %.6e)\n", v2.x, v2.y, v2.z);
122 LOG_ALLOW(LOCAL, LOG_DEBUG, " v3: (%.6e, %.6e, %.6e)\n", v3.x, v3.y, v3.z);
123 LOG_ALLOW(LOCAL, LOG_DEBUG, " v4: (%.6e, %.6e, %.6e)\n", v4.x, v4.y, v4.z);
124
125 // --- Calculate Edge Vectors for Initial Normal Computation ---
126 PetscReal edge1_x = v2.x - v1.x;
127 PetscReal edge1_y = v2.y - v1.y;
128 PetscReal edge1_z = v2.z - v1.z;
129
130 PetscReal edge2_x = v4.x - v1.x;
131 PetscReal edge2_y = v4.y - v1.y;
132 PetscReal edge2_z = v4.z - v1.z;
133 LOG_ALLOW(LOCAL, LOG_DEBUG, " Edge1 (v2-v1): (%.6e, %.6e, %.6e)\n", edge1_x, edge1_y, edge1_z);
134 LOG_ALLOW(LOCAL, LOG_DEBUG, " Edge2 (v4-v1): (%.6e, %.6e, %.6e)\n", edge2_x, edge2_y, edge2_z);
135
136 // --- Compute Initial Normal Vector (Cross Product: edge1 x edge2) ---
137 PetscReal normal_x_initial = edge1_y * edge2_z - edge1_z * edge2_y;
138 PetscReal normal_y_initial = edge1_z * edge2_x - edge1_x * edge2_z;
139 PetscReal normal_z_initial = edge1_x * edge2_y - edge1_y * edge2_x;
140 LOG_ALLOW(LOCAL, LOG_DEBUG, " Initial Raw Normal (edge1 x edge2): (%.6e, %.6e, %.6e)\n", normal_x_initial, normal_y_initial, normal_z_initial);
141
142 PetscReal normal_magnitude = sqrt(normal_x_initial * normal_x_initial +
143 normal_y_initial * normal_y_initial +
144 normal_z_initial * normal_z_initial);
145 LOG_ALLOW(LOCAL, LOG_DEBUG, " Initial Normal Magnitude: %.6e\n", normal_magnitude);
146
147 if (normal_magnitude < 1.0e-12) {
148 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
150 "ComputeSignedDistanceToPlane - Degenerate plane detected on rank %d. Normal magnitude (%.3e) is too small.\n",
151 rank, normal_magnitude);
152 LOG_ALLOW(LOCAL, LOG_ERROR, " Offending vertices for normal: v1(%.3e,%.3e,%.3e), v2(%.3e,%.3e,%.3e), v4(%.3e,%.3e,%.3e)\n",
153 v1.x,v1.y,v1.z, v2.x,v2.y,v2.z, v4.x,v4.y,v4.z);
154 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Degenerate plane detected (normal vector is near zero).");
155 }
156
157 // --- Calculate the Centroid of the Four Face Vertices (v1, v2, v3, v4) ---
158 PetscReal face_centroid_x = 0.25 * (v1.x + v2.x + v3.x + v4.x);
159 PetscReal face_centroid_y = 0.25 * (v1.y + v2.y + v3.y + v4.y);
160 PetscReal face_centroid_z = 0.25 * (v1.z + v2.z + v3.z + v4.z);
161 LOG_ALLOW(LOCAL, LOG_DEBUG, " Face Centroid: (%.6e, %.6e, %.6e)\n", face_centroid_x, face_centroid_y, face_centroid_z);
162
163 // --- Orient the Normal to Point Outward from the Cell ---
164 // Vector from face centroid to cell centroid
165 PetscReal vec_fc_to_cc_x = cell_centroid.x - face_centroid_x;
166 PetscReal vec_fc_to_cc_y = cell_centroid.y - face_centroid_y;
167 PetscReal vec_fc_to_cc_z = cell_centroid.z - face_centroid_z;
168 LOG_ALLOW(LOCAL, LOG_DEBUG, " Vec (FaceCentroid -> CellCentroid): (%.6e, %.6e, %.6e)\n", vec_fc_to_cc_x, vec_fc_to_cc_y, vec_fc_to_cc_z);
169
170 // Dot product of initial normal with vector from face centroid to cell centroid
171 PetscReal dot_prod_orientation = normal_x_initial * vec_fc_to_cc_x +
172 normal_y_initial * vec_fc_to_cc_y +
173 normal_z_initial * vec_fc_to_cc_z;
174 LOG_ALLOW(LOCAL, LOG_DEBUG, " Dot Product for Orientation (N_initial . Vec_FC_to_CC): %.6e\n", dot_prod_orientation);
175
176 PetscReal normal_x = normal_x_initial;
177 PetscReal normal_y = normal_y_initial;
178 PetscReal normal_z = normal_z_initial;
179
180 // If dot_prod_orientation > 0, initial normal points towards cell interior, so flip it.
181 if (dot_prod_orientation > 1.0e-9) { // Use a small epsilon to avoid issues if dot product is extremely close to zero
182 normal_x = -normal_x_initial;
183 normal_y = -normal_y_initial;
184 normal_z = -normal_z_initial;
185 LOG_ALLOW(LOCAL, LOG_DEBUG, " Initial normal was inward (dot_prod > 0). Flipped normal.\n");
186 } else if (dot_prod_orientation == 0.0 && normal_magnitude > 1e-12) {
187 // This case is ambiguous or face plane contains cell centroid.
188 // This might happen for highly symmetric cells or if face_centroid IS cell_centroid (e.g. 2D cell).
189 // For now, we keep the original normal direction based on v1,v2,v4 ordering.
190 // A more robust solution for this edge case might be needed if it occurs often.
191 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
192 LOG_ALLOW(LOCAL, LOG_WARNING, "ComputeSignedDistanceToPlane - 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);
193 }
194 LOG_ALLOW(LOCAL, LOG_DEBUG, " Oriented Raw Normal: (%.6e, %.6e, %.6e)\n", normal_x, normal_y, normal_z);
195
196
197 // --- Normalize the (Now Outward-Pointing) Normal Vector ---
198 // Note: normal_magnitude was calculated from initial normal.
199 // If we flipped, magnitude is the same.
200 normal_x /= normal_magnitude;
201 normal_y /= normal_magnitude;
202 normal_z /= normal_magnitude;
203 LOG_ALLOW(LOCAL, LOG_DEBUG, " Normalized Outward Normal: (%.6f, %.6f, %.6f)\n", normal_x, normal_y, normal_z);
204
205
206 // --- Compute Vector from Target Point to Face Centroid ---
207 PetscReal vec_p_to_fc_x = face_centroid_x - p_target.x;
208 PetscReal vec_p_to_fc_y = face_centroid_y - p_target.y;
209 PetscReal vec_p_to_fc_z = face_centroid_z - p_target.z;
210
211 // --- Compute Signed Distance ---
212 *d_signed = vec_p_to_fc_x * normal_x +
213 vec_p_to_fc_y * normal_y +
214 vec_p_to_fc_z * normal_z;
215
216 LOG_ALLOW(LOCAL, LOG_DEBUG, " Raw Signed Distance (using outward normal): %.15e\n", *d_signed);
217
218 // --- Apply Threshold ---
219 if (fabs(*d_signed) < threshold) {
220 LOG_ALLOW(LOCAL, LOG_DEBUG, " Distance %.15e is less than threshold %.1e. Setting to 0.0.\n", *d_signed, threshold);
221 *d_signed = 0.0;
222 }
223
224 LOG_ALLOW(LOCAL, LOG_DEBUG, "ComputeSignedDistanceToPlane - Final Signed Distance: %.15e\n", *d_signed);
225
226 PetscFunctionReturn(0);
227}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:44
#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:207
@ 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_DEBUG
Detailed debugging information.
Definition logging.h:33
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. Each distance corresponds to a specific face of the cell, as enumerated by the Face enumeration. A threshold value is used to determine when a distance should be considered effectively zero, accounting for floating-point precision limitations.

Parameters
[in]pThe target point in 3D space for which distances to the cell's faces are to be calculated. Represented by the Cmpnts structure.
[in]cellA pointer to a Cell structure that defines the cubic cell via its eight vertices. The vertices must be ordered consistently to ensure correct normal directions for each face.
[out]dA pointer to an array of six PetscReal values where the computed signed distances will be stored. Each index in the array corresponds to a specific face as defined by the Face enumeration:
  • d[LEFT]: Distance to the Left Face of the cell.
  • d[RIGHT]: Distance to the Right Face of the cell.
  • d[BOTTOM]: Distance to the Bottom Face of the cell.
  • d[TOP]: Distance to the Top Face of the cell.
  • d[FRONT]: Distance to the Front Face of the cell.
  • d[BACK]: Distance to the Back Face of the cell.
[in]thresholdA PetscReal value that specifies the minimum distance below which a computed distance is considered to be zero. This helps in mitigating issues arising from floating-point arithmetic inaccuracies.
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
  • The vertices of the cell must be ordered in a counter-clockwise manner when viewed from outside the cell. This ordering ensures that the normal vectors computed for each face point outward, which is essential for correctly determining the sign of the distances.
  • All four vertices defining a face must lie on a non-degenerate (i.e., non-flat) plane. Degenerate planes can lead to undefined normal vectors and incorrect distance calculations.
  • The threshold parameter provides flexibility in handling cases where the point p is extremely close to a face, allowing the user to define what constitutes "close enough" to be treated as zero distance based on the specific requirements of their application.

Definition at line 271 of file walkingsearch.c.

272{
273 PetscErrorCode ierr;
274 // Validate that the 'cell' pointer is not NULL to prevent dereferencing a null pointer.
275 if (cell == NULL) {
276 LOG_ALLOW(LOCAL,LOG_ERROR, "CalculateDistancesToCellFaces - 'cell' is NULL.\n");
277 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "CalculateDistancesToCellFaces - 'cell' is NULL.");
278 }
279
280 // Validate that the 'd' pointer is not NULL to ensure there is memory allocated for distance storage.
281 if (d == NULL) {
282 LOG_ALLOW(LOCAL,LOG_ERROR, "CalculateDistancesToCellFaces - 'd' is NULL.\n");
283 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "CalculateDistancesToCellFaces - 'd' is NULL.");
284 }
285
286 // Compute the centroid of the entire cell
287 Cmpnts cell_centroid = {0.0, 0.0, 0.0};
288 for (int i = 0; i < 8; ++i) {
289 cell_centroid.x += cell->vertices[i].x;
290 cell_centroid.y += cell->vertices[i].y;
291 cell_centroid.z += cell->vertices[i].z;
292 }
293 cell_centroid.x /= 8.0;
294 cell_centroid.y /= 8.0;
295 cell_centroid.z /= 8.0;
296
297 LOG_ALLOW(LOCAL,LOG_DEBUG, "CalculateDistancesToCellFaces - Cell Centroid: (%.6e, %.6e, %.6e)\n",
298 cell_centroid.x, cell_centroid.y, cell_centroid.z);
299
300
301 // Compute the signed distance from point 'p' to the BACK face of the cell.
302 // The BACK face is defined by vertices 0, 3, 2, and 1, with its normal vector pointing in the -z direction.
304 cell->vertices[0], // Vertex 0
305 cell->vertices[3], // Vertex 3
306 cell->vertices[2], // Vertex 2
307 cell->vertices[1], // Vertex 1
308 cell_centroid, // Cell centroid
309 p, // Target point
310 &d[BACK], // Storage location for the BACK face distance
311 threshold // Threshold for zero distance
312 ); CHKERRQ(ierr);
313
314 // Compute the signed distance from point 'p' to the FRONT face of the cell.
315 // The FRONT face is defined by vertices 4, 7, 6, and 5, with its normal vector pointing in the +z direction.
317 cell->vertices[4], // Vertex 4
318 cell->vertices[7], // Vertex 7
319 cell->vertices[6], // Vertex 6
320 cell->vertices[5], // Vertex 5
321 cell_centroid, // Cell centroid
322 p, // Target point
323 &d[FRONT], // Storage location for the FRONT face distance
324 threshold // Threshold for zero distance
325 ); CHKERRQ(ierr);
326
327 // Compute the signed distance from point 'p' to the BOTTOM face of the cell.
328 // The BOTTOM face is defined by vertices 0, 1, 6, and 7, with its normal vector pointing in the -y direction.
330 cell->vertices[0], // Vertex 0
331 cell->vertices[1], // Vertex 1
332 cell->vertices[6], // Vertex 6
333 cell->vertices[7], // Vertex 7
334 cell_centroid, // Cell centroid
335 p, // Target point
336 &d[BOTTOM], // Storage location for the BOTTOM face distance
337 threshold // Threshold for zero distance
338 ); CHKERRQ(ierr);
339
340 // Compute the signed distance from point 'p' to the TOP face of the cell.
341 // The TOP face is defined by vertices 3, 4, 5, and 2, with its normal vector pointing in the +y direction.
343 cell->vertices[3], // Vertex 3
344 cell->vertices[4], // Vertex 4
345 cell->vertices[5], // Vertex 5
346 cell->vertices[2], // Vertex 2
347 cell_centroid, // Cell centroid
348 p, // Target point
349 &d[TOP], // Storage location for the TOP face distance
350 threshold // Threshold for zero distance
351 ); CHKERRQ(ierr);
352
353 // Compute the signed distance from point 'p' to the LEFT face of the cell.
354 // The LEFT face is defined by vertices 0, 7, 4, and 3, with its normal vector pointing in the -x direction.
356 cell->vertices[0], // Vertex 0
357 cell->vertices[7], // Vertex 7
358 cell->vertices[4], // Vertex 4
359 cell->vertices[3], // Vertex 3
360 cell_centroid, // Cell centroid
361 p, // Target point
362 &d[LEFT], // Storage location for the LEFT face distance
363 threshold // Threshold for zero distance
364 ); CHKERRQ(ierr);
365
366 // Compute the signed distance from point 'p' to the RIGHT face of the cell.
367 // The RIGHT face is defined by vertices 1, 2, 5, and 6, with its normal vector pointing in the +x direction.
369 cell->vertices[1], // Vertex 1
370 cell->vertices[2], // Vertex 2
371 cell->vertices[5], // Vertex 5
372 cell->vertices[6], // Vertex 6
373 cell_centroid, // Cell centroid
374 p, // Target point
375 &d[RIGHT], // Storage location for the RIGHT face distance
376 threshold // Threshold for zero distance
377 ); CHKERRQ(ierr);
378
379 LOG_ALLOW(LOCAL, LOG_DEBUG, "CalculateDistancesToCellFaces - Populated d: "
380 "d[LEFT=%d]=%.3e, d[RIGHT=%d]=%.3e, d[BOTTOM=%d]=%.3e, "
381 "d[TOP=%d]=%.3e, d[FRONT=%d]=%.3e, d[BACK=%d]=%.3e\n",
382 LEFT, d[LEFT], RIGHT, d[RIGHT], BOTTOM, d[BOTTOM],
383 TOP, d[TOP], FRONT, d[FRONT], BACK, d[BACK]);
384 LOG_ALLOW(LOCAL, LOG_DEBUG, "CalculateDistancesToCellFaces - Raw d: "
385 "[%.3e, %.3e, %.3e, %.3e, %.3e, %.3e]\n",
386 d[0], d[1], d[2], d[3], d[4], d[5]);
387
388 return 0; // Indicate successful execution of the function.
389}
@ TOP
Definition variables.h:144
@ FRONT
Definition variables.h:144
@ BOTTOM
Definition variables.h:144
@ BACK
Definition variables.h:144
@ LEFT
Definition variables.h:144
@ RIGHT
Definition variables.h:144
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.
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.

Definition at line 407 of file walkingsearch.c.

408{
409
410
411 // Validate input pointers
412 if (d == NULL) {
413 LOG_ALLOW(LOCAL,LOG_ERROR, "DeterminePointPosition - 'd' is NULL.\n");
414 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "DeterminePointPosition - Input parameter 'd' is NULL.");
415 }
416 if (result == NULL) {
417 LOG_ALLOW(LOCAL,LOG_ERROR, "DeterminePointPosition - 'result' is NULL.\n");
418 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "DeterminePointPosition - Output parameter 'result' is NULL.");
419 }
420
421 // Initialize flags
422 PetscBool isInside = PETSC_TRUE;
423 PetscBool isOnBoundary = PETSC_FALSE;
424 PetscInt IntersectionCount = 0; // Counts the number of intersections of the point with various planes of the cell.
425
426 // Analyze distances to determine position
427 for(int i = 0; i < NUM_FACES; i++) {
428 if(d[i] < 0.0) {
429 isInside = PETSC_FALSE; // Point is outside in at least one direction
430 }
431 if(d[i] == 0.0) {
432 isOnBoundary = PETSC_TRUE; // Point is exactly at least one face
433 IntersectionCount++;
434 }
435 }
436
437 // Set the result based on flags
438 if(isInside) {
439 *result = 0; // Inside the cell
440 LOG_ALLOW(LOCAL,LOG_DEBUG, "DeterminePointPosition - Particle is inside the cell.\n");
441 }
442 else if(isOnBoundary) {
443 if(IntersectionCount == 1){
444 *result = 1; // on face
445 LOG_ALLOW(LOCAL,LOG_DEBUG, "DeterminePointPosition - Particle is on a face of the cell.\n");
446 }
447 else if(IntersectionCount == 2){
448 *result = 2; // on edge
449 LOG_ALLOW(LOCAL,LOG_DEBUG, "DeterminePointPosition - Particle is on an edge of the cell.\n");
450 }
451 else if(IntersectionCount >= 3){
452 *result = 3; // on corner
453 LOG_ALLOW(LOCAL,LOG_DEBUG, "DeterminePointPosition - Particle is on a corner of the cell.\n");
454 }
455 }
456 else {
457 *result = -1; // Outside the cell
458 LOG_ALLOW(LOCAL,LOG_DEBUG, "DeterminePointPosition - Particle is outside the cell.\n");
459 }
460
461 return 0; // Indicate successful execution
462}
@ NUM_FACES
Definition variables.h:144
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). The vertex numbering follows the convention depicted in the provided figure:

(i,j+1,k)
3---------------------------2(i+1,j+1,k)
/| /|
/ | / |
/ | / |
/ | / |
/ | / |
/ | / |
/ | / |
4-------|------------------5 |
| | | |
|(i,j+1,k+1) | |
| | | |
| 0-------------------|-------1 (i+1,j,k)
| / | /
| / | /
| / | /
| / | /
| / | /
| / | /
| / |/
7---------------------------6
(i,j,k+1) (i+1,j,k+1)

Vertex Numbering and Positions:

  • Vertex 0: (i, j, k) → cell->vertices[0]
  • Vertex 1: (i+1, j, k) → cell->vertices[1]
  • Vertex 2: (i+1, j+1, k) → cell->vertices[2]
  • Vertex 3: (i, j+1, k) → cell->vertices[3]
  • Vertex 4: (i, j+1, k+1) → cell->vertices[4]
  • Vertex 5: (i+1, j+1, k+1) → cell->vertices[5]
  • Vertex 6: (i+1, j, k+1) → cell->vertices[6]
  • Vertex 7: (i, j, k+1) → cell->vertices[7]
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 to indicate successful execution. Non-zero on failure.
Note
  • It is assumed that the grid indices (idx, idy, idz) are within valid bounds.
  • The coor array should be properly initialized with accurate coordinates for all grid points.
  • The function assumes unit spacing between grid points. Modify the coordinate assignments if your grid spacing differs.
  • The boundary checks have been removed as they are performed before calling this function.

Definition at line 521 of file walkingsearch.c.

523{
524
525 // Validate input pointers
526 if (coor == NULL) {
527 LOG_ALLOW(LOCAL,LOG_ERROR, "GetCellVerticesFromGrid - 'coor' is NULL.\n");
528 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "GetCellVerticesFromGrid - Input array 'coor' is NULL.");
529 }
530 if (cell == NULL) {
531 LOG_ALLOW(LOCAL,LOG_ERROR, "GetCellVerticesFromGrid - 'cell' is NULL.\n");
532 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "GetCellVerticesFromGrid - Output parameter 'cell' is NULL.");
533 }
534
535 // Assign vertices based on grid indices matching the figure
536 // Vertex numbering follows the convention depicted in the figure
537 cell->vertices[0] = coor[idz][idy][idx]; // Vertex 0: (i, j, k)
538 cell->vertices[1] = coor[idz][idy][idx+1]; // Vertex 1: (i+1, j, k)
539 cell->vertices[2] = coor[idz][idy+1][idx+1]; // Vertex 2: (i+1, j+1, k)
540 cell->vertices[3] = coor[idz][idy+1][idx]; // Vertex 3: (i, j+1, k)
541 cell->vertices[4] = coor[idz+1][idy+1][idx]; // Vertex 4: (i, j+1, k+1)
542 cell->vertices[5] = coor[idz+1][idy+1][idx+1]; // Vertex 5: (i+1, j+1, k+1)
543 cell->vertices[6] = coor[idz+1][idy][idx+1]; // Vertex 6: (i+1, j, k+1)
544 cell->vertices[7] = coor[idz+1][idy][idx]; // Vertex 7: (i, j, k+1)
545
546 LOG_ALLOW(LOCAL,LOG_DEBUG, "GetCellVerticesFromGrid - Retrieved vertices for cell (%d, %d, %d).\n", idx, idy, idz);
547
548 return 0; // Indicate successful execution
549}
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 for the grid search.

  • If the particle has valid previous cell indices (not -1,-1,-1), the search starts from that previous cell.
  • Otherwise (e.g., first time locating the particle), the search starts from the beginning corner (xs, ys, zs) of the local grid domain owned by the current process. It also 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 and previous cell (if any).
[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.

Definition at line 571 of file walkingsearch.c.

572{
573 PetscErrorCode ierr;
574 DMDALocalInfo info;
575
576 // Validate input pointers
577 if (user == NULL || particle == NULL || idx == NULL || idy == NULL || idz == NULL || traversal_steps == NULL) {
578 LOG_ALLOW(LOCAL,LOG_ERROR, "InitializeTraversalParameters - One or more input pointers are NULL.\n");
579 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "InitializeTraversalParameters - One or more input pointers are NULL.");
580 }
581
582 // Get grid information (needed for fallback start and potentially validation)
583 ierr = DMDAGetLocalInfo(user->da, &info); CHKERRQ(ierr);
584
585 // --- Check if the particle has a valid previous cell ID ---
586 // Assuming particle->cell stores the *global* indices
587 if (particle->cell[0] >= 0 && particle->cell[1] >= 0 && particle->cell[2] >= 0) {
588
589 // It sees a valid cell ID exists.
590 // Before using it, it explicitly checks if this cell is accessible.
591 PetscBool is_handoff_cell_valid;
592 ierr = CheckCellWithinLocalGrid(user, particle->cell[0], particle->cell[1], particle->cell[2], &is_handoff_cell_valid); CHKERRQ(ierr);
593
594 if (is_handoff_cell_valid) {
595 // FAST PATH: The check passed. The cell is safe. Use it.
596 *idx = particle->cell[0];
597 *idy = particle->cell[1];
598 *idz = particle->cell[2];
599
600 LOG_ALLOW(LOCAL,LOG_DEBUG, "InitializeTraversalParameters - Particle %lld has previous cell (%d, %d, %d). Starting search there.\n",
601 (long long)particle->PID, *idx, *idy, *idz); // Cast id to long long for printing PetscInt64
602
603 } else {
604 // SAFE FALLBACK: The check failed! The handoff cell is NOT safe.
605 // Discard the unsafe handoff cell and revert to starting at the
606 // guaranteed-safe local corner.
607 *idx = info.xs;
608 *idy = info.ys;
609 *idz = info.zs;
610 }
611 } else {
612 // No valid previous cell ID (e.g., -1,-1,-1 or first time).
613 // Start from the first cell in the local owned grid domain.
614 *idx = info.xs;
615 *idy = info.ys;
616 *idz = info.zs;
617 LOG_ALLOW(LOCAL,LOG_DEBUG, "InitializeTraversalParameters - Particle %lld has no valid previous cell. Starting search at local corner (%d, %d, %d).\n",
618 (long long)particle->PID, *idx, *idy, *idz);
619 }
620
621 // Initialize traversal step counter
622 *traversal_steps = 0;
623
624 // Log the chosen starting point
625 LOG_ALLOW(LOCAL,LOG_INFO, "InitializeTraversalParameters - Traversal for particle %lld initialized to start at cell (%d, %d, %d).\n",
626 (long long)particle->PID, *idx, *idy, *idz);
627
628 return 0;
629}
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:32
PetscInt cell[3]
Definition variables.h:166
PetscInt64 PID
Definition variables.h:165
PetscErrorCode CheckCellWithinLocalGrid(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, PetscBool *is_within)
Checks if the current GLOBAL CELL indices are within the LOCAL GHOSTED grid boundaries accessible by ...
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 GLOBAL CELL indices are within the LOCAL GHOSTED grid boundaries accessible by this MPI process.

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

This function determines if the provided global cell indices (idx, idy, idz) fall within the range of cells covered by the current process's owned and ghost NODES. A cell C(i,j,k) (origin N(i,j,k)) is considered within this ghosted region if its origin node N(i,j,k) is within the rank's ghosted nodal region, AND node N(i+1,j+1,k+1) is also within it (to ensure the entire cell extent is covered by available node data). More simply, we check if the cell's origin node is within the range of nodes that can form the start of a ghosted cell.

Parameters
[in]userPointer to the user-defined context (needs user->fda for node info).
[in]idxThe global i-index of the cell's origin node.
[in]idyThe global j-index of the cell's origin node.
[in]idzThe global k-index of the cell's origin node.
[out]is_withinPointer to a PetscBool that will be set to PETSC_TRUE if within ghosted bounds, else PETSC_FALSE.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 650 of file walkingsearch.c.

651{
652 PetscErrorCode ierr;
653 DMDALocalInfo info_nodes; // Node information from the DMDA that defines ghost regions (user->fda)
654
655 PetscFunctionBeginUser; // Assuming this is part of your PETSc style
656
657 // Validate inputs
658 if (user == NULL || is_within == NULL) {
659 LOG_ALLOW(LOCAL, LOG_ERROR, "Input pointer is NULL in CheckCellWithinLocalGrid.\n");
660 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input pointer is NULL in CheckCellWithinLocalGrid.");
661 }
662 if (user->fda == NULL) {
663 LOG_ALLOW(LOCAL, LOG_ERROR, "user->fda is NULL in CheckCellWithinLocalGrid. Cannot get ghost info.\n");
664 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "user->fda is NULL. Cannot get ghost info.");
665 }
666
667 // Get node info from user->fda (this DMDA has the ghost layer information for nodes)
668 ierr = DMDAGetLocalInfo(user->fda, &info_nodes); CHKERRQ(ierr);
669
670 // Determine the range of GLOBAL CELL INDICES that are covered by this rank's ghosted NODAL region.
671 // A cell C(i,j,k) has origin node N(i,j,k).
672 // The ghosted nodal region starts at global node index info_nodes.gxs and has info_nodes.gxm nodes.
673
674 // Global starting index of the first cell whose origin node is within the ghosted nodal region.
675 PetscInt gxs_cell_global_start = info_nodes.gxs;
676 PetscInt gys_cell_global_start = info_nodes.gys;
677 PetscInt gzs_cell_global_start = info_nodes.gzs;
678
679 // Number of cells that can be formed starting from nodes within the ghosted nodal region.
680 // If there are N ghosted nodes (info_nodes.gxm), they can be origins for N-1 cells.
681 PetscInt gxm_cell_local_count = (info_nodes.gxm > 0) ? info_nodes.gxm - 1 : 0;
682 PetscInt gym_cell_local_count = (info_nodes.gym > 0) ? info_nodes.gym - 1 : 0;
683 PetscInt gzm_cell_local_count = (info_nodes.gzm > 0) ? info_nodes.gzm - 1 : 0;
684
685 // Global exclusive end index for cells whose origins are in the ghosted nodal region.
686 PetscInt gxe_cell_global_end_exclusive = gxs_cell_global_start + gxm_cell_local_count;
687 PetscInt gye_cell_global_end_exclusive = gys_cell_global_start + gym_cell_local_count;
688 PetscInt gze_cell_global_end_exclusive = gzs_cell_global_start + gzm_cell_local_count;
689
690 // Check if the given global cell index (idx, idy, idz) falls within this range.
691 // This means the origin node of cell (idx,idy,idz) is within the rank's accessible ghosted node region,
692 // and that node can indeed serve as a cell origin (i.e., it's not the very last node in the ghosted region).
693 if (idx >= gxs_cell_global_start && idx < gxe_cell_global_end_exclusive &&
694 idy >= gys_cell_global_start && idy < gye_cell_global_end_exclusive &&
695 idz >= gzs_cell_global_start && idz < gze_cell_global_end_exclusive) {
696 *is_within = PETSC_TRUE;
697 } else {
698 *is_within = PETSC_FALSE;
699 }
700
701 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",
702 idx, idy, idz, (*is_within) ? "within" : "outside",
703 gxs_cell_global_start, gxe_cell_global_end_exclusive,
704 gys_cell_global_start, gye_cell_global_end_exclusive,
705 gzs_cell_global_start, gze_cell_global_end_exclusive);
706
707 PetscFunctionReturn(0);
708}
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.

Definition at line 722 of file walkingsearch.c.

723{
724 PetscErrorCode ierr;
725 Vec Coor;
726 Cmpnts ***coor_array;
727 PetscMPIInt rank;
728 DMDALocalInfo info_nodes;
729
730 // Validate input pointers
731 if (user == NULL || cell == NULL) {
732 LOG_ALLOW(LOCAL,LOG_ERROR, "RetrieveCurrentCell - One or more input pointers are NULL.\n");
733 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "RetrieveCurrentCell - One or more input pointers are NULL.");
734 }
735
736 // Get local coordinates
737 ierr = DMGetCoordinatesLocal(user->da, &Coor); CHKERRQ(ierr);
738 ierr = DMDAVecGetArrayRead(user->fda, Coor, &coor_array); CHKERRQ(ierr);
739
740 // Get the local grid information FOR THE GHOSTED ARRAY from user->fda
741 // This info contains the mapping between global and local indices.
742 ierr = DMDAGetLocalInfo(user->fda, &info_nodes); CHKERRQ(ierr);
743
744 PetscInt idx_local = idx; // - info_nodes.gxs;
745 PetscInt idy_local = idy; // - info_nodes.gys;
746 PetscInt idz_local = idz; // - info_nodes.gzs;
747
748 LOG_ALLOW(LOCAL,LOG_DEBUG," [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);
749
750 // Get the current cell's vertices
751 ierr = GetCellVerticesFromGrid(coor_array, idx_local, idy_local, idz_local, cell); CHKERRQ(ierr);
752
753 // Restore array
754 ierr = DMDAVecRestoreArrayRead(user->fda, Coor, &coor_array); CHKERRQ(ierr);
755
756 // Get MPI rank for debugging
757 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
758
759 // Debug: Print cell vertices
760 LOG_ALLOW(LOCAL,LOG_DEBUG, "RetrieveCurrentCell - Cell (%d, %d, %d) vertices \n", idx, idy, idz);
761 ierr = LOG_CELL_VERTICES(cell, rank); CHKERRQ(ierr);
762
763 return 0;
764}
PetscErrorCode LOG_CELL_VERTICES(const Cell *cell, PetscMPIInt rank)
Prints the coordinates of a cell's vertices.
Definition logging.c:189
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.
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.

Definition at line 811 of file walkingsearch.c.

812{
813 PetscErrorCode ierr;
814 PetscReal cellSize;
815 PetscReal cellThreshold;
816
817 // Validate input pointers to ensure they are not NULL, preventing potential segmentation faults.
818 if (cell == NULL || position == NULL) {
819 LOG_ALLOW(LOCAL,LOG_ERROR, "EvaluateParticlePosition - One or more input pointers are NULL.\n");
820 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "EvaluateParticlePosition - One or more input pointers are NULL.");
821 }
822
823 // Compute a local cell size
824 ierr = GetCellCharacteristicSize(cell, &cellSize); CHKERRQ(ierr);
825
826 // scale base threshold by cell size (ex: if threshold = 1e-6 and cell size = 0.01, cellThreshold = 1e-8)
827 cellThreshold = threshold*cellSize;
828
829 // Invoke the function to calculate signed distances from the particle to each face of the cell.
830 // The distances are stored in the array pointed to by 'd'.
831 ierr = CalculateDistancesToCellFaces(p, cell, d, cellThreshold); CHKERRQ(ierr);
832 CHKERRQ(ierr); // Check for errors in distance calculation.
833
834
835 // Catch degenerate-plane error manually:
836 if (ierr == PETSC_ERR_USER) {
838 "EvaluateParticlePosition - Skipping cell due to degenerate face.\n");
839 // We can set *position = -1 here
840 *position = -1; // treat as outside
841 return 0; // not a fatal error, just skip
842 } else {
843 CHKERRQ(ierr);
844 }
845
846
847 // Debugging output: Print the computed distances to each face for verification purposes.
848 LOG_ALLOW(LOCAL,LOG_DEBUG, "EvaluateParticlePosition - Face Distances:\n");
850 CHKERRQ(ierr); // Check for errors in printing distances.
851
852 // Determine the particle's position relative to the cell based on the computed distances.
853 // The function sets the value pointed to by 'position' accordingly:
854 // 0 for inside, 1 (2 or 3) for on the boundary, and -1 for outside.
855 ierr = DeterminePointPosition(d,position);
856 CHKERRQ(ierr); // Check for errors in position determination.
857
858 return 0; // Indicate successful execution of the function.
859}
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:159
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:49
PetscErrorCode LOG_FACE_DISTANCES(PetscReal *d)
Prints the signed distances to each face of the cell.
Definition logging.c:229
PetscErrorCode GetCellCharacteristicSize(const Cell *cell, PetscReal *cellSize)
Estimates a characteristic length of the cell for threshold scaling.
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateCellIndicesBasedOnDistancesTEST()

PetscErrorCode UpdateCellIndicesBasedOnDistancesTEST ( 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.
[in]infoDMDALocalInfo structure that holds local & global domain bounds.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 882 of file walkingsearch.c.

883{
884
885 /*
886 PetscInt cxm,cxs; // maximum & minimum cell ID in x
887 PetscInt cym,cys; // maximum & minimum cell ID in y
888 PetscInt czm,czs; // maximum & minimum cell ID in z
889
890 cxs = info->xs; cxm = cxs + info->xm - 2;
891 cys = info->ys; cym = cys + info->ym - 2;
892 czs = info->zs; czm = czs + info->zm - 2;
893 */
894
895 // LOG_ALLOW(LOCAL, LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Received d: "
896 // "d[LEFT=%d]=%.3e, d[RIGHT=%d]=%.3e, d[BOTTOM=%d]=%.3e, "
897 // "d[TOP=%d]=%.3e, d[FRONT=%d]=%.3e, d[BACK=%d]=%.3e\n",
898 // LEFT, d[LEFT], RIGHT, d[RIGHT], BOTTOM, d[BOTTOM],
899 // TOP, d[TOP], FRONT, d[FRONT], BACK, d[BACK]);
900 // LOG_ALLOW(LOCAL, LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Raw d: "
901 // "[%.3e, %.3e, %.3e, %.3e, %.3e, %.3e]\n",
902 // d[0], d[1], d[2], d[3], d[4], d[5]);
903
904 // Validate input pointers
905 if (d == NULL) {
906 LOG_ALLOW(LOCAL,LOG_ERROR, "UpdateCellIndicesBasedOnDistances - 'd' is NULL.\n");
907 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UpdateCellIndicesBasedOnDistances - Input array 'd' is NULL.");
908 }
909 if (idx == NULL || idy == NULL || idz == NULL) {
910 LOG_ALLOW(LOCAL,LOG_ERROR, "UpdateCellIndicesBasedOnDistances - One or more index pointers are NULL.\n");
911 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UpdateCellIndicesBasedOnDistances - One or more index pointers are NULL.");
912 }
913
914 // Debug: Print current face distances
915 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Current Face Distances:\n");
917
918 // Update k-direction based on FRONT and BACK distances
919 if (d[FRONT] < 0.0) {
920 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[FRONT] < 0.0, incrementing idz.\n");
921 (*idz) += 1;
922 }
923 else if(d[BACK] < 0.0){
924 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[BACK] < 0.0, decrementing idz.\n");
925 (*idz) -= 1;
926 }
927
928 // Update i-direction based on LEFT and RIGHT distances
929 if (d[LEFT] < 0.0) {
930 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[LEFT] < 0.0, decrementing idx.\n");
931 (*idx) -= 1;
932 }
933 else if (d[RIGHT] < 0.0) {
934 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[RIGHT] < 0.0, incrementing idx.\n");
935 (*idx) += 1;
936 }
937
938 // Update j-direction based on BOTTOM and TOP distances
939 if (d[BOTTOM] < 0.0) {
940 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[BOTTOM] < 0.0, decrementing idy.\n");
941 (*idy) -= 1;
942 }
943 else if (d[TOP] < 0.0) {
944 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Condition met: d[TOP] < 0.0, incrementing idy.\n");
945 (*idy) += 1;
946 }
947
948 /*
949 // The 'cell' corners you can reference go from [xs .. xs+xm-1], but
950 // to form a valid cell in x, you need (idx+1) in range, so max is (xs+xm-2).
951 *idx = PetscMax(cxs, PetscMin(*idx, cxm));
952 *idy = PetscMax(cys, PetscMin(*idy, cym));
953 *idz = PetscMax(czs, PetscMin(*idz, czm));
954 */
955
956 LOG_ALLOW(LOCAL,LOG_DEBUG, "UpdateCellIndicesBasedOnDistances - Updated Indices - idx, idy, idz: %d, %d, %d\n", *idx, *idy, *idz);
957
958 return 0; // Indicate successful execution
959}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ 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.

Definition at line 977 of file walkingsearch.c.

978{
979 // Validate input pointers
980 if (user == NULL || particle == NULL) {
981 LOG_ALLOW(LOCAL,LOG_ERROR, "FinalizeTraversal - One or more input pointers are NULL.\n");
982 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "FinalizeTraversal - One or more input pointers are NULL.");
983 }
984
985 if (cell_found) {
986 LOG_ALLOW(LOCAL,LOG_INFO, "FinalizeTraversal - Particle located in cell (%d, %d, %d) after %d traversal steps.\n",
987 idx, idy, idz, traversal_steps);
988 }
989 else {
990 LOG_ALLOW(LOCAL,LOG_WARNING, "FinalizeTraversal - Particle could not be located within the grid after %d traversal steps.\n", (PetscInt)traversal_steps);
991 particle->cell[0] = -1;
992 particle->cell[1] = -1;
993 particle->cell[2] = -1;
994 }
995
996 LOG_ALLOW(LOCAL, LOG_INFO, "FinalizeTraversal - Completed final traversal sync across all ranks.\n");
997
998
999 return 0;
1000}

◆ 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.

Definition at line 1026 of file walkingsearch.c.

1027{
1028 PetscErrorCode ierr;
1029 PetscMPIInt size;
1030
1031 PetscFunctionBeginUser;
1032
1033 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
1034
1035 // --- 1. Input Validation ---
1036 if (!user || !user->RankCellInfoMap) {
1037 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "UserCtx or RankCellInfoMap is not initialized in FindOwnerOfCell.");
1038 }
1039 if (!owner_rank) {
1040 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer owner_rank is NULL in FindOwnerOfCell.");
1041 }
1042
1043 // --- 2. Linear Search through the Decomposition Map ---
1044 // Initialize to a "not found" state.
1045 *owner_rank = -1;
1046
1047 // Loop through the map, which contains the ownership info for every rank 'r'.
1048 for (PetscMPIInt r = 0; r < size; ++r) {
1049 const RankCellInfo *info = &user->RankCellInfoMap[r];
1050
1051 // A rank owns a cell if the cell's index is within its start (inclusive)
1052 // and end (exclusive) range for all three dimensions.
1053 if ((i >= info->xs_cell && i < info->xs_cell + info->xm_cell) &&
1054 (j >= info->ys_cell && j < info->ys_cell + info->ym_cell) &&
1055 (k >= info->zs_cell && k < info->zs_cell + info->zm_cell))
1056 {
1057 *owner_rank = r; // We found the owner.
1058 break; // The search is over, exit the loop.
1059 }
1060 }
1061
1062 // --- 3. Logging for Diagnostics ---
1063 // This is extremely useful for debugging particle migration issues.
1064 if (*owner_rank == -1) {
1065 LOG_ALLOW(LOCAL, LOG_DEBUG, "FindOwnerOfCell: No owner found for global cell (%d, %d, %d). It is likely outside the domain.\n", i, j, k);
1066 } else {
1067 LOG_ALLOW(LOCAL, LOG_DEBUG, "FindOwnerOfCell: Owner of cell (%d, %d, %d) is Rank %d.\n", i, j, k, *owner_rank);
1068 }
1069
1070 PetscFunctionReturn(0);
1071}
PetscInt ys_cell
Definition variables.h:183
PetscInt xs_cell
Definition variables.h:183
PetscInt zm_cell
Definition variables.h:184
PetscInt zs_cell
Definition variables.h:183
PetscInt xm_cell
Definition variables.h:184
RankCellInfo * RankCellInfoMap
Definition variables.h:696
PetscInt ym_cell
Definition variables.h:184
A lean struct to hold the global cell ownership range for a single MPI rank.
Definition variables.h:182
Here is the caller graph for this function:

◆ LocateParticleOrFindMigrationTarget_TEST()

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.

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.

Definition at line 1094 of file walkingsearch.c.

1097{
1098 PetscErrorCode ierr;
1099 PetscMPIInt rank;
1100
1101 // --- Search State Variables ---
1102 PetscInt idx, idy, idz; // Current search cell global indices
1103 PetscInt traversal_steps; // Counter to prevent infinite loops
1104 PetscBool search_concluded = PETSC_FALSE; // Flag to terminate the main while loop
1105
1106 // --- Oscillation/Stuck Loop Detection Variables ---
1107 PetscInt repeatedIndexCount = 0;
1108 PetscInt prevIdx = PETSC_MIN_INT, prevIdy = PETSC_MIN_INT, prevIdz = PETSC_MIN_INT;
1109 PetscInt last_position_result = -999;
1110
1111 PetscFunctionBeginUser;
1112 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1114
1115 // --- 1. Initialize the Search ---
1116 ierr = InitializeTraversalParameters(user, particle, &idx, &idy, &idz, &traversal_steps); CHKERRQ(ierr);
1117
1118 LOG_ALLOW(LOCAL,LOG_INFO, " The Threshold for considering a particle to be at a face is %.16f.\n",DISTANCE_THRESHOLD);
1119
1120 LOG_ALLOW(LOCAL,LOG_DEBUG," [PID %lld]Traversal Initiated at : i = %d, j = %d, k = %d.\n",(long long)particle->PID,idx,idy,idz);
1121
1122 // --- 2. Main Walking Search Loop ---
1123 while (!search_concluded && traversal_steps < MAX_TRAVERSAL) {
1124 traversal_steps++;
1125
1126 // --- 2a. GLOBAL Domain Boundary Check ---
1127 if (idx < 0 || idx >= (user->IM - 1) || idy < 0 || idy >= (user->JM - 1) || idz < 0 || idz >= (user->KM - 1)) {
1128 LOG_ALLOW(LOCAL, LOG_WARNING, "[PID %lld]: Walked outside GLOBAL domain boundaries to invalid cell (%d,%d,%d). Search fails.\n",
1129 (long long)particle->PID, idx, idy, idz);
1130 idx = -1; // Invalidate the result to signal failure
1131 break; // Exit the loop immediately
1132 }
1133
1134 // --- 2b. LOCAL GHOST REGION CHECK (PREVENTS SEGV) ---
1135 // Before trying to access cell data, check if we have it.
1136 PetscBool is_cell_local;
1137 ierr = CheckCellWithinLocalGrid(user, idx, idy, idz, &is_cell_local); CHKERRQ(ierr);
1138 if (!is_cell_local) {
1139 // We have walked outside the local rank's ghost region.
1140 // This definitively means the particle belongs to another rank.
1141 // Conclude the search here; the current (idx,idy,idz) is the handoff cell.
1142 LOG_ALLOW(LOCAL, LOG_INFO, "[PID %lld]: Walked outside local ghost region to cell (%d,%d,%d). Concluding search for handoff.\n",
1143 (long long)particle->PID, idx, idy, idz);
1144 search_concluded = PETSC_TRUE;
1145 continue; // Skip the rest of the loop; proceed to finalization.
1146 }
1147
1148 // --- 2c. Stuck Loop Detection & Enhanced Tie-Breaker ---
1149 if (idx == prevIdx && idy == prevIdy && idz == prevIdz) {
1150 repeatedIndexCount++;
1151 if (repeatedIndexCount > REPEAT_COUNT_THRESHOLD) {
1152 // Only apply tie-breaker if we are stuck for the right reason (on a boundary)
1153 if (last_position_result >= 1) {
1154 LOG_ALLOW(LOCAL, LOG_WARNING, "LocateOrMigrate [PID %lld]: Stuck on boundary of cell (%d,%d,%d) for %d steps. Applying enhanced tie-breaker.\n",
1155 (long long)particle->PID, idx, idy, idz, repeatedIndexCount);
1156
1157 // Re-evaluate at the stuck cell to get definitive weights
1158 Cell final_cell;
1159 PetscReal final_d[NUM_FACES];
1160 PetscInt final_position; // Dummy variable
1161
1162 ierr = RetrieveCurrentCell(user, idx, idy, idz, &final_cell); CHKERRQ(ierr);
1163 ierr = EvaluateParticlePosition(&final_cell, final_d, particle->loc, &final_position, DISTANCE_THRESHOLD);
1164
1165 if (ierr == 0) { // If evaluation succeeded
1166 ierr = UpdateParticleWeights(final_d, particle); CHKERRQ(ierr);
1167 search_concluded = PETSC_TRUE; // Conclude search, accepting this cell.
1168 } else { // Evaluation failed (e.g., degenerate cell)
1169 LOG_ALLOW(LOCAL, LOG_ERROR, "[PID %lld]: Tie-breaker failed during final evaluation at cell (%d,%d,%d). Search fails.\n",
1170 (long long)particle->PID, idx, idy, idz);
1171 idx = -1; // Invalidate result
1172 search_concluded = PETSC_TRUE;
1173 }
1174 } else { // Stuck for the wrong reason (not on a boundary)
1175 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",
1176 (long long)particle->PID, idx, idy, idz);
1177 idx = -1; // Invalidate result
1178 search_concluded = PETSC_TRUE;
1179 }
1180 if(search_concluded) continue;
1181 }
1182 } else {
1183 repeatedIndexCount = 0;
1184 }
1185 prevIdx = idx; prevIdy = idy; prevIdz = idz;
1186
1187 // --- 2d. Geometric Evaluation ---
1188 Cell current_cell;
1189 PetscReal distances[NUM_FACES];
1190 PetscInt position_in_cell;
1191
1192 ierr = RetrieveCurrentCell(user, idx, idy, idz, &current_cell); CHKERRQ(ierr);
1193 ierr = EvaluateParticlePosition(&current_cell, distances, particle->loc, &position_in_cell, DISTANCE_THRESHOLD); CHKERRQ(ierr);
1194 last_position_result = position_in_cell;
1195
1196 // --- 2e. Decision Making ---
1197 if (position_in_cell >= 0) { // Particle is INSIDE or ON THE BOUNDARY
1198 search_concluded = PETSC_TRUE;
1199 ierr = UpdateParticleWeights(distances, particle); CHKERRQ(ierr);
1200 } else { // Particle is OUTSIDE
1201 ierr = UpdateCellIndicesBasedOnDistancesTEST(distances, &idx, &idy, &idz); CHKERRQ(ierr);
1202 }
1203 }
1204
1205 // --- 3. Finalize and Determine Actionable Status ---
1206 if (idx == -1 || (!search_concluded && traversal_steps >= MAX_TRAVERSAL)) {
1207 if (idx != -1) {
1208 LOG_ALLOW(LOCAL, LOG_ERROR, "[PID %lld]: Search FAILED, exceeded MAX_TRAVERSAL limit of %d.\n",
1209 (long long)particle->PID, MAX_TRAVERSAL);
1210 }
1211 *status_out = LOST;
1212 particle->cell[0] = -1; particle->cell[1] = -1; particle->cell[2] = -1;
1213 } else {
1214 // Search succeeded in finding a candidate cell, now determine its owner.
1215 PetscMPIInt owner_rank;
1216 ierr = FindOwnerOfCell(user, idx, idy, idz, &owner_rank); CHKERRQ(ierr);
1217
1218 LOG_ALLOW(LOCAL,LOG_DEBUG," [PID %ld] Owner rank : %d.\n",particle->PID,owner_rank);
1219
1220 // Always update the particle's cell index. It's a good guess for the receiving rank.
1221 particle->cell[0] = idx; particle->cell[1] = idy; particle->cell[2] = idz;
1222
1223 if (owner_rank == rank) {
1224 *status_out = ACTIVE_AND_LOCATED;
1225 } else if (owner_rank != -1) {
1226 // Particle belongs to another rank. Return the direct, actionable status.
1227 *status_out = MIGRATING_OUT;
1228 particle->destination_rank = owner_rank;
1229 } else { // Found a valid index, but no owner in the map.
1230 *status_out = LOST;
1231 particle->cell[0] = -1; particle->cell[1] = -1; particle->cell[2] = -1;
1232 }
1233 }
1234
1235 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d][PID %ld] Search complete.\n",rank,particle->PID);
1236
1237 // --- 4. Report the Final Outcome ---
1238 ierr = ReportSearchOutcome(particle, *status_out, traversal_steps); CHKERRQ(ierr);
1239
1241 PetscFunctionReturn(0);
1242}
PetscErrorCode UpdateParticleWeights(PetscReal *d, Particle *particle)
Updates a particle's interpolation weights based on distances to cell faces.
#define LOG_FUNC_TIMER_END_EVENT(eventID, scope)
Ends timing a function by:
Definition logging.h:462
PetscLogEvent EVENT_IndividualLocation
Definition logging.c:36
#define LOG_FUNC_TIMER_BEGIN_EVENT(eventID, scope)
Begins timing a function by:
Definition logging.h:436
@ LOST
Definition variables.h:138
@ ACTIVE_AND_LOCATED
Definition variables.h:136
@ MIGRATING_OUT
Definition variables.h:137
PetscInt KM
Definition variables.h:639
Cmpnts loc
Definition variables.h:167
PetscMPIInt destination_rank
Definition variables.h:171
PetscInt JM
Definition variables.h:639
PetscInt IM
Definition variables.h:639
Defines the vertices of a single hexahedral grid cell.
Definition variables.h:159
#define DISTANCE_THRESHOLD
#define MAX_TRAVERSAL
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 ReportSearchOutcome(const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
Logs the final outcome of the particle location search.
#define REPEAT_COUNT_THRESHOLD
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 RetrieveCurrentCell(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Retrieves the coordinates of the eight vertices of the current cell.
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.
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.

Definition at line 1247 of file walkingsearch.c.

1250{
1251 PetscFunctionBeginUser;
1252 switch (status) {
1253 case ACTIVE_AND_LOCATED:
1254 LOG_ALLOW(LOCAL, LOG_INFO, "Search SUCCESS [PID %lld]: Located in global cell (%d, %d, %d) after %d steps.\n",
1255 (long long)particle->PID, particle->cell[0], particle->cell[1], particle->cell[2], traversal_steps);
1256 break;
1257 case MIGRATING_OUT:
1258 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",
1259 (long long)particle->PID, particle->destination_rank, particle->cell[0], particle->cell[1], particle->cell[2], traversal_steps);
1260 break;
1261 case LOST:
1262 LOG_ALLOW(LOCAL, LOG_WARNING, "Search FAILED [PID %lld]: Particle is LOST after %d steps.\n",
1263 (long long)particle->PID, traversal_steps);
1264 break;
1265 default:
1266 LOG_ALLOW(LOCAL, LOG_WARNING, "Search ended with unexpected status %d for PID %lld.\n", status, (long long)particle->PID);
1267 break;
1268 }
1269 PetscFunctionReturn(0);
1270}
Here is the caller graph for this function: