10#define MAX_TRAVERSAL 1000
11#define DISTANCE_THRESHOLD 1e-11
12#define REPEAT_COUNT_THRESHOLD 5
15#define __FUNCT__ "GetCellCharacteristicSize"
28 PetscErrorCode ierr = 0;
29 PetscFunctionBeginUser;
31 if (!cell || !cellSize) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
32 "GetCellCharacteristicSize: Null pointer(s).");
39 PetscInt edges[12][2] = {
40 {0,1},{1,2},{2,3},{3,0},
41 {4,5},{5,6},{6,7},{7,4},
42 {0,7},{1,6},{2,5},{3,4}
45 PetscReal totalEdgeLen = 0.0;
46 for (PetscInt i=0; i<12; i++) {
47 PetscInt vA = edges[i][0];
48 PetscInt vB = edges[i][1];
51 PetscReal dx = B.
x - A.
x;
52 PetscReal dy = B.
y - A.
y;
53 PetscReal dz = B.
z - A.
z;
54 PetscReal edgeLen = sqrt(dx*dx + dy*dy + dz*dz);
55 totalEdgeLen += edgeLen;
59 *cellSize = totalEdgeLen / 12.0;
62 PetscFunctionReturn(ierr);
67#define __FUNCT__ "ComputeSignedDistanceToPlane"
111 PetscReal *d_signed,
const PetscReal threshold)
113 PetscErrorCode ierr = 0;
116 PetscFunctionBeginUser;
119 if (d_signed == NULL) {
120 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
122 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output pointer 'd_signed' must not be NULL.");
134 PetscReal edge1_x = v2.
x - v1.
x;
135 PetscReal edge1_y = v2.
y - v1.
y;
136 PetscReal edge1_z = v2.
z - v1.
z;
138 PetscReal edge2_x = v4.
x - v1.
x;
139 PetscReal edge2_y = v4.
y - v1.
y;
140 PetscReal edge2_z = v4.
z - v1.
z;
145 PetscReal normal_x_initial = edge1_y * edge2_z - edge1_z * edge2_y;
146 PetscReal normal_y_initial = edge1_z * edge2_x - edge1_x * edge2_z;
147 PetscReal normal_z_initial = edge1_x * edge2_y - edge1_y * edge2_x;
148 LOG_ALLOW(
LOCAL,
LOG_VERBOSE,
" Initial Raw Normal (edge1 x edge2): (%.6e, %.6e, %.6e)\n", normal_x_initial, normal_y_initial, normal_z_initial);
150 PetscReal normal_magnitude = sqrt(normal_x_initial * normal_x_initial +
151 normal_y_initial * normal_y_initial +
152 normal_z_initial * normal_z_initial);
155 if (normal_magnitude < 1.0e-12) {
156 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
158 "Degenerate plane detected on rank %d. Normal magnitude (%.3e) is too small.\n",
159 rank, normal_magnitude);
160 LOG_ALLOW(
LOCAL,
LOG_ERROR,
" Offending vertices for normal: v1(%.3e,%.3e,%.3e), v2(%.3e,%.3e,%.3e), v4(%.3e,%.3e,%.3e)\n",
161 v1.
x,v1.
y,v1.
z, v2.
x,v2.
y,v2.
z, v4.
x,v4.
y,v4.
z);
162 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER,
"Degenerate plane detected (normal vector is near zero).");
166 PetscReal face_centroid_x = 0.25 * (v1.
x + v2.
x + v3.
x + v4.
x);
167 PetscReal face_centroid_y = 0.25 * (v1.
y + v2.
y + v3.
y + v4.
y);
168 PetscReal face_centroid_z = 0.25 * (v1.
z + v2.
z + v3.
z + v4.
z);
169 LOG_ALLOW(
LOCAL,
LOG_VERBOSE,
" Face Centroid: (%.6e, %.6e, %.6e)\n", face_centroid_x, face_centroid_y, face_centroid_z);
173 PetscReal vec_fc_to_cc_x = cell_centroid.
x - face_centroid_x;
174 PetscReal vec_fc_to_cc_y = cell_centroid.
y - face_centroid_y;
175 PetscReal vec_fc_to_cc_z = cell_centroid.
z - face_centroid_z;
176 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);
179 PetscReal dot_prod_orientation = normal_x_initial * vec_fc_to_cc_x +
180 normal_y_initial * vec_fc_to_cc_y +
181 normal_z_initial * vec_fc_to_cc_z;
184 PetscReal normal_x = normal_x_initial;
185 PetscReal normal_y = normal_y_initial;
186 PetscReal normal_z = normal_z_initial;
189 if (dot_prod_orientation > 1.0e-9) {
190 normal_x = -normal_x_initial;
191 normal_y = -normal_y_initial;
192 normal_z = -normal_z_initial;
194 }
else if (dot_prod_orientation == 0.0 && normal_magnitude > 1e-12) {
199 ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank); CHKERRQ(ierr);
200 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);
208 normal_x /= normal_magnitude;
209 normal_y /= normal_magnitude;
210 normal_z /= normal_magnitude;
215 PetscReal vec_p_to_fc_x = face_centroid_x - p_target.
x;
216 PetscReal vec_p_to_fc_y = face_centroid_y - p_target.
y;
217 PetscReal vec_p_to_fc_z = face_centroid_z - p_target.
z;
220 *d_signed = vec_p_to_fc_x * normal_x +
221 vec_p_to_fc_y * normal_y +
222 vec_p_to_fc_z * normal_z;
227 if (fabs(*d_signed) < threshold) {
235 PetscFunctionReturn(0);
240#define __FUNCT__ "CalculateDistancesToCellFaces"
285 PetscFunctionBeginUser;
291 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"'cell' is NULL.");
297 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"'d' is NULL.");
301 Cmpnts cell_centroid = {0.0, 0.0, 0.0};
302 for (
int i = 0; i < 8; ++i) {
307 cell_centroid.
x /= 8.0;
308 cell_centroid.
y /= 8.0;
309 cell_centroid.
z /= 8.0;
312 cell_centroid.
x, cell_centroid.
y, cell_centroid.
z);
394 "d[LEFT=%d]=%.3e, d[RIGHT=%d]=%.3e, d[BOTTOM=%d]=%.3e, "
395 "d[TOP=%d]=%.3e, d[FRONT=%d]=%.3e, d[BACK=%d]=%.3e\n",
399 "[%.3e, %.3e, %.3e, %.3e, %.3e, %.3e]\n",
400 d[0], d[1], d[2], d[3], d[4], d[5]);
403 PetscFunctionReturn(0);
407#define __FUNCT__ "DeterminePointPosition"
427 PetscFunctionBeginUser;
432 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input parameter 'd' is NULL.");
434 if (result == NULL) {
436 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output parameter 'result' is NULL.");
440 PetscBool isInside = PETSC_TRUE;
441 PetscBool isOnBoundary = PETSC_FALSE;
442 PetscInt IntersectionCount = 0;
447 isInside = PETSC_FALSE;
450 isOnBoundary = PETSC_TRUE;
460 else if(isOnBoundary) {
461 if(IntersectionCount == 1){
465 else if(IntersectionCount == 2){
469 else if(IntersectionCount >= 3){
480 PetscFunctionReturn(0);
484#define __FUNCT__ "GetCellVerticesFromGrid"
546 PetscFunctionBeginUser;
551 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input array 'coor' is NULL.");
555 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output parameter 'cell' is NULL.");
560 cell->
vertices[0] = coor[idz][idy][idx];
561 cell->
vertices[1] = coor[idz][idy][idx+1];
562 cell->
vertices[2] = coor[idz][idy+1][idx+1];
563 cell->
vertices[3] = coor[idz][idy+1][idx];
564 cell->
vertices[4] = coor[idz+1][idy+1][idx];
565 cell->
vertices[5] = coor[idz+1][idy+1][idx+1];
566 cell->
vertices[6] = coor[idz+1][idy][idx+1];
567 cell->
vertices[7] = coor[idz+1][idy][idx];
572 PetscFunctionReturn(0);
576#define __FUNCT__ "InitializeTraversalParameters"
602 PetscFunctionBeginUser;
606 if (user == NULL || particle == NULL || idx == NULL || idy == NULL || idz == NULL || traversal_steps == NULL) {
608 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
612 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
616 if (particle->
cell[0] >= 0 && particle->
cell[1] >= 0 && particle->
cell[2] >= 0) {
620 PetscBool is_handoff_cell_valid;
623 if (is_handoff_cell_valid) {
625 *idx = particle->
cell[0];
626 *idy = particle->
cell[1];
627 *idz = particle->
cell[2];
630 (
long long)particle->
PID, *idx, *idy, *idz);
646 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Particle %lld has no valid previous cell. Starting search at local corner (%d, %d, %d).\n",
647 (
long long)particle->
PID, *idx, *idy, *idz);
651 *traversal_steps = 0;
655 (
long long)particle->
PID, *idx, *idy, *idz);
657 PetscFunctionReturn(0);
662#define __FUNCT__ "CheckCellWithinLocalGrid"
685 DMDALocalInfo info_nodes;
687 PetscFunctionBeginUser;
691 if (user == NULL || is_within == NULL) {
693 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input pointer is NULL in CheckCellWithinLocalGrid.");
695 if (user->
fda == NULL) {
697 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->fda is NULL. Cannot get ghost info.");
701 ierr = DMDAGetLocalInfo(user->
fda, &info_nodes); CHKERRQ(ierr);
708 PetscInt gxs_cell_global_start = info_nodes.gxs;
709 PetscInt gys_cell_global_start = info_nodes.gys;
710 PetscInt gzs_cell_global_start = info_nodes.gzs;
714 PetscInt gxm_cell_local_count = (info_nodes.gxm > 0) ? info_nodes.gxm - 1 : 0;
715 PetscInt gym_cell_local_count = (info_nodes.gym > 0) ? info_nodes.gym - 1 : 0;
716 PetscInt gzm_cell_local_count = (info_nodes.gzm > 0) ? info_nodes.gzm - 1 : 0;
719 PetscInt gxe_cell_global_end_exclusive = gxs_cell_global_start + gxm_cell_local_count;
720 PetscInt gye_cell_global_end_exclusive = gys_cell_global_start + gym_cell_local_count;
721 PetscInt gze_cell_global_end_exclusive = gzs_cell_global_start + gzm_cell_local_count;
726 if (idx >= gxs_cell_global_start && idx < gxe_cell_global_end_exclusive &&
727 idy >= gys_cell_global_start && idy < gye_cell_global_end_exclusive &&
728 idz >= gzs_cell_global_start && idz < gze_cell_global_end_exclusive) {
729 *is_within = PETSC_TRUE;
731 *is_within = PETSC_FALSE;
734 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",
735 idx, idy, idz, (*is_within) ?
"within" :
"outside",
736 gxs_cell_global_start, gxe_cell_global_end_exclusive,
737 gys_cell_global_start, gye_cell_global_end_exclusive,
738 gzs_cell_global_start, gze_cell_global_end_exclusive);
741 PetscFunctionReturn(0);
745#define __FUNCT__ "RetrieveCurrentCell"
763 DMDALocalInfo info_nodes;
765 PetscFunctionBeginUser;
769 if (user == NULL || cell == NULL) {
771 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
775 ierr = DMGetCoordinatesLocal(user->
da, &Coor); CHKERRQ(ierr);
776 ierr = DMDAVecGetArrayRead(user->
fda, Coor, &coor_array); CHKERRQ(ierr);
780 ierr = DMDAGetLocalInfo(user->
fda, &info_nodes); CHKERRQ(ierr);
782 PetscInt idx_local = idx;
783 PetscInt idy_local = idy;
784 PetscInt idz_local = idz;
786 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);
792 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor, &coor_array); CHKERRQ(ierr);
795 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
802 PetscFunctionReturn(0);
806#define __FUNCT__ "EvaluateParticlePosition"
856 PetscReal cellThreshold;
857 PetscFunctionBeginUser;
861 if (cell == NULL || position == NULL) {
863 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
870 cellThreshold = threshold*cellSize;
879 if (ierr == PETSC_ERR_USER) {
881 "Skipping cell due to degenerate face.\n");
902 PetscFunctionReturn(0);
906#define __FUNCT__ "UpdateCellIndicesBasedOnDistances"
931 PetscFunctionBeginUser;
955 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input array 'd' is NULL.");
957 if (idx == NULL || idy == NULL || idz == NULL) {
959 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more index pointers are NULL.");
967 if (d[
FRONT] < 0.0) {
971 else if(d[
BACK] < 0.0){
981 else if (d[
RIGHT] < 0.0) {
991 else if (d[
TOP] < 0.0) {
1007 PetscFunctionReturn(0);
1012#define __FUNCT__ "FinalizeTraversal"
1031 PetscFunctionBeginUser;
1033 if (user == NULL || particle == NULL) {
1035 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
1040 idx, idy, idz, traversal_steps);
1043 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"Particle could not be located within the grid after %d traversal steps.\n", (PetscInt)traversal_steps);
1044 particle->
cell[0] = -1;
1045 particle->
cell[1] = -1;
1046 particle->
cell[2] = -1;
1053 PetscFunctionReturn(0);
1057#define __FUNCT__ "FindOwnerOfCell"
1083 PetscErrorCode ierr;
1086 PetscFunctionBeginUser;
1090 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
1094 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"UserCtx or RankCellInfoMap is not initialized in FindOwnerOfCell.");
1097 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output pointer owner_rank is NULL in FindOwnerOfCell.");
1105 for (PetscMPIInt r = 0; r < size; ++r) {
1121 if (*owner_rank == -1) {
1122 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"No owner found for global cell (%d, %d, %d). It is likely outside the domain.\n", i, j, k);
1128 PetscFunctionReturn(0);
1132#define __FUNCT__ "LocateParticleOrFindMigrationTarget"
1159 PetscErrorCode ierr;
1163 PetscInt idx, idy, idz;
1164 PetscInt traversal_steps;
1165 PetscBool search_concluded = PETSC_FALSE;
1168 PetscInt repeatedIndexCount = 0;
1169 PetscInt prevIdx = PETSC_MIN_INT, prevIdy = PETSC_MIN_INT, prevIdz = PETSC_MIN_INT;
1170 PetscInt last_position_result = -999;
1172 PetscFunctionBeginUser;
1174 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1181 LOG_ALLOW(
LOCAL,
LOG_TRACE,
" [PID %lld]Traversal Initiated at : i = %d, j = %d, k = %d.\n",(
long long)particle->
PID,idx,idy,idz);
1184 while (!search_concluded && traversal_steps <
MAX_TRAVERSAL) {
1188 if (idx < 0 || idx >= (user->
IM - 1) || idy < 0 || idy >= (user->
JM - 1) || idz < 0 || idz >= (user->
KM - 1)) {
1189 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[PID %lld]: Walked outside GLOBAL domain boundaries to invalid cell (%d,%d,%d). Search fails.\n",
1190 (
long long)particle->
PID, idx, idy, idz);
1197 PetscBool is_cell_local;
1199 if (!is_cell_local) {
1203 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[PID %lld]: Walked outside local ghost region to cell (%d,%d,%d). Concluding search for handoff.\n",
1204 (
long long)particle->
PID, idx, idy, idz);
1205 search_concluded = PETSC_TRUE;
1210 if (idx == prevIdx && idy == prevIdy && idz == prevIdz) {
1211 repeatedIndexCount++;
1214 if (last_position_result >= 1) {
1215 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[PID %lld]: Stuck on boundary of cell (%d,%d,%d) for %d steps. Applying enhanced tie-breaker.\n",
1216 (
long long)particle->
PID, idx, idy, idz, repeatedIndexCount);
1221 PetscInt final_position;
1228 search_concluded = PETSC_TRUE;
1230 LOG_ALLOW(
LOCAL,
LOG_ERROR,
"[PID %lld]: Tie-breaker failed during final evaluation at cell (%d,%d,%d). Search fails.\n",
1231 (
long long)particle->
PID, idx, idy, idz);
1233 search_concluded = PETSC_TRUE;
1236 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",
1237 (
long long)particle->
PID, idx, idy, idz);
1239 search_concluded = PETSC_TRUE;
1241 if(search_concluded)
continue;
1244 repeatedIndexCount = 0;
1246 prevIdx = idx; prevIdy = idy; prevIdz = idz;
1251 PetscInt position_in_cell;
1255 last_position_result = position_in_cell;
1258 if (position_in_cell >= 0) {
1259 search_concluded = PETSC_TRUE;
1267 if (idx == -1 || (!search_concluded && traversal_steps >=
MAX_TRAVERSAL)) {
1273 particle->
cell[0] = -1; particle->
cell[1] = -1; particle->
cell[2] = -1;
1276 PetscMPIInt owner_rank;
1277 ierr =
FindOwnerOfCell(user, idx, idy, idz, &owner_rank); CHKERRQ(ierr);
1282 particle->
cell[0] = idx; particle->
cell[1] = idy; particle->
cell[2] = idz;
1284 if (owner_rank == rank) {
1286 }
else if (owner_rank != -1) {
1292 particle->
cell[0] = -1; particle->
cell[1] = -1; particle->
cell[2] = -1;
1302 PetscFunctionReturn(0);
1307#define __FUNCT__ "ReportSearchOutcome"
1313 PetscInt traversal_steps)
1315 PetscFunctionBeginUser;
1319 LOG_ALLOW(
LOCAL,
LOG_INFO,
"Search SUCCESS [PID %lld]: Located in global cell (%d, %d, %d) after %d steps.\n",
1320 (
long long)particle->
PID, particle->
cell[0], particle->
cell[1], particle->
cell[2], traversal_steps);
1323 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",
1328 (
long long)particle->
PID, traversal_steps);
1335 PetscFunctionReturn(0);
PetscErrorCode UpdateParticleWeights(PetscReal *d, Particle *particle)
Updates a particle's interpolation weights based on distances to cell faces.
Logging utilities and macros for PETSc-based applications.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
#define LOCAL
Logging scope definitions for controlling message output.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
PetscErrorCode LOG_FACE_DISTANCES(PetscReal *d)
Prints the signed distances to each face of the cell.
@ LOG_ERROR
Critical errors that may halt the program.
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
PetscErrorCode LOG_CELL_VERTICES(const Cell *cell, PetscMPIInt rank)
Prints the coordinates of a cell's vertices.
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
PetscMPIInt destination_rank
RankCellInfo * RankCellInfoMap
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Defines the vertices of a single hexahedral grid cell.
A 3D point or vector with PetscScalar components.
Defines a particle's core properties for Lagrangian tracking.
A lean struct to hold the global cell ownership range for a single MPI rank.
User-defined context containing data specific to a single computational grid level.
#define DISTANCE_THRESHOLD
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 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 GetCellCharacteristicSize(const Cell *cell, PetscReal *cellSize)
Estimates a characteristic length of the cell for threshold scaling.
PetscErrorCode EvaluateParticlePosition(const Cell *cell, PetscReal *d, const Cmpnts p, PetscInt *position, const PetscReal threshold)
Determines the spatial relationship of a particle relative to a cubic cell.
PetscErrorCode ComputeSignedDistanceToPlane(const Cmpnts v1, const Cmpnts v2, const Cmpnts v3, const Cmpnts v4, const Cmpnts cell_centroid, const Cmpnts p_target, PetscReal *d_signed, const PetscReal threshold)
Computes the signed distance from a point to the plane approximating a quadrilateral face.
PetscErrorCode ReportSearchOutcome(const Particle *particle, ParticleLocationStatus status, PetscInt traversal_steps)
Logs the final outcome of the particle location search.
#define REPEAT_COUNT_THRESHOLD
PetscErrorCode CalculateDistancesToCellFaces(const Cmpnts p, const Cell *cell, PetscReal *d, const PetscReal threshold)
Computes the signed distances from a point to each face of a cubic cell.
PetscErrorCode DeterminePointPosition(PetscReal *d, PetscInt *result)
Classifies a point based on precomputed face distances.
PetscErrorCode UpdateCellIndicesBasedOnDistances(PetscReal d[NUM_FACES], PetscInt *idx, PetscInt *idy, PetscInt *idz)
Updates the cell indices based on the signed distances to each face.
PetscErrorCode FindOwnerOfCell(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscMPIInt *owner_rank)
Finds the MPI rank that owns a given global cell index.
PetscErrorCode RetrieveCurrentCell(UserCtx *user, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Retrieves the coordinates of the eight vertices of the current cell.
PetscErrorCode GetCellVerticesFromGrid(Cmpnts ***coor, PetscInt idx, PetscInt idy, PetscInt idz, Cell *cell)
Retrieves the coordinates of the eight vertices of a cell based on grid indices.
PetscErrorCode 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 ...
Header file for particle location functions using the walking search algorithm.