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);
649 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCent, ¢); CHKERRQ(ierr);
652 PetscInt candidates[7][3];
653 const char* candidate_names[7] = {
"X-min face",
"X-max face",
"Y-min face",
654 "Y-max face",
"Z-min face",
"Z-max face",
"Volume center"};
657 PetscInt mid_i = info.xs + (info.xm - 1) / 2;
658 PetscInt mid_j = info.ys + (info.ym - 1) / 2;
659 PetscInt mid_k = info.zs + (info.zm - 1) / 2;
660 PetscInt max_i = info.xs + info.xm - 2;
661 PetscInt max_j = info.ys + info.ym - 2;
662 PetscInt max_k = info.zs + info.zm - 2;
665 if (max_i < info.xs) max_i = info.xs;
666 if (max_j < info.ys) max_j = info.ys;
667 if (max_k < info.zs) max_k = info.zs;
670 candidates[0][0] = info.xs; candidates[0][1] = mid_j; candidates[0][2] = mid_k;
672 candidates[1][0] = max_i; candidates[1][1] = mid_j; candidates[1][2] = mid_k;
674 candidates[2][0] = mid_i; candidates[2][1] = info.ys; candidates[2][2] = mid_k;
676 candidates[3][0] = mid_i; candidates[3][1] = max_j; candidates[3][2] = mid_k;
678 candidates[4][0] = mid_i; candidates[4][1] = mid_j; candidates[4][2] = info.zs;
680 candidates[5][0] = mid_i; candidates[5][1] = mid_j; candidates[5][2] = max_k;
682 candidates[6][0] = mid_i; candidates[6][1] = mid_j; candidates[6][2] = mid_k;
685 PetscReal min_distance = PETSC_MAX_REAL;
686 PetscInt best_candidate = 6;
688 for (PetscInt i = 0; i < 7; i++) {
689 PetscInt ci = candidates[i][0];
690 PetscInt cj = candidates[i][1];
691 PetscInt ck = candidates[i][2];
694 Cmpnts cell_center = cent[ck+1][cj+1][ci+1];
697 PetscReal dx = particle->
loc.
x - cell_center.
x;
698 PetscReal dy = particle->
loc.
y - cell_center.
y;
699 PetscReal dz = particle->
loc.
z - cell_center.
z;
700 PetscReal distance = sqrt(dx*dx + dy*dy + dz*dz);
703 i, candidate_names[i], ci, cj, ck, cell_center.
x, cell_center.
y, cell_center.
z, distance);
705 if (distance < min_distance) {
706 min_distance = distance;
715 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCent, ¢); CHKERRQ(ierr);
717 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",
718 (
long long)particle->
PID, candidate_names[best_candidate], *idx, *idy, *idz, min_distance);
722 *traversal_steps = 0;
726 (
long long)particle->
PID, *idx, *idy, *idz);
728 PetscFunctionReturn(0);
733#define __FUNCT__ "CheckCellWithinLocalGrid"
756 DMDALocalInfo info_nodes;
758 PetscFunctionBeginUser;
762 if (user == NULL || is_within == NULL) {
764 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input pointer is NULL in CheckCellWithinLocalGrid.");
766 if (user->
fda == NULL) {
768 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->fda is NULL. Cannot get ghost info.");
772 ierr = DMDAGetLocalInfo(user->
fda, &info_nodes); CHKERRQ(ierr);
779 PetscInt gxs_cell_global_start = info_nodes.gxs;
780 PetscInt gys_cell_global_start = info_nodes.gys;
781 PetscInt gzs_cell_global_start = info_nodes.gzs;
785 PetscInt gxm_cell_local_count = (info_nodes.gxm > 0) ? info_nodes.gxm - 1 : 0;
786 PetscInt gym_cell_local_count = (info_nodes.gym > 0) ? info_nodes.gym - 1 : 0;
787 PetscInt gzm_cell_local_count = (info_nodes.gzm > 0) ? info_nodes.gzm - 1 : 0;
790 PetscInt gxe_cell_global_end_exclusive = gxs_cell_global_start + gxm_cell_local_count;
791 PetscInt gye_cell_global_end_exclusive = gys_cell_global_start + gym_cell_local_count;
792 PetscInt gze_cell_global_end_exclusive = gzs_cell_global_start + gzm_cell_local_count;
797 if (idx >= gxs_cell_global_start && idx < gxe_cell_global_end_exclusive &&
798 idy >= gys_cell_global_start && idy < gye_cell_global_end_exclusive &&
799 idz >= gzs_cell_global_start && idz < gze_cell_global_end_exclusive) {
800 *is_within = PETSC_TRUE;
802 *is_within = PETSC_FALSE;
805 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",
806 idx, idy, idz, (*is_within) ?
"within" :
"outside",
807 gxs_cell_global_start, gxe_cell_global_end_exclusive,
808 gys_cell_global_start, gye_cell_global_end_exclusive,
809 gzs_cell_global_start, gze_cell_global_end_exclusive);
812 PetscFunctionReturn(0);
816#define __FUNCT__ "RetrieveCurrentCell"
834 DMDALocalInfo info_nodes;
836 PetscFunctionBeginUser;
840 if (user == NULL || cell == NULL) {
842 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
846 ierr = DMGetCoordinatesLocal(user->
da, &Coor); CHKERRQ(ierr);
847 ierr = DMDAVecGetArrayRead(user->
fda, Coor, &coor_array); CHKERRQ(ierr);
851 ierr = DMDAGetLocalInfo(user->
fda, &info_nodes); CHKERRQ(ierr);
853 PetscInt idx_local = idx;
854 PetscInt idy_local = idy;
855 PetscInt idz_local = idz;
857 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);
863 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor, &coor_array); CHKERRQ(ierr);
866 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
873 PetscFunctionReturn(0);
877#define __FUNCT__ "EvaluateParticlePosition"
927 PetscReal cellThreshold;
928 PetscFunctionBeginUser;
932 if (cell == NULL || position == NULL) {
934 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
941 cellThreshold = threshold*cellSize;
950 if (ierr == PETSC_ERR_USER) {
952 "Skipping cell due to degenerate face.\n");
973 PetscFunctionReturn(0);
977#define __FUNCT__ "UpdateCellIndicesBasedOnDistances"
1002 PetscFunctionBeginUser;
1026 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input array 'd' is NULL.");
1028 if (idx == NULL || idy == NULL || idz == NULL) {
1030 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more index pointers are NULL.");
1038 if (d[
FRONT] < 0.0) {
1042 else if(d[
BACK] < 0.0){
1048 if (d[
LEFT] < 0.0) {
1052 else if (d[
RIGHT] < 0.0) {
1062 else if (d[
TOP] < 0.0) {
1078 PetscFunctionReturn(0);
1083#define __FUNCT__ "FinalizeTraversal"
1102 PetscFunctionBeginUser;
1104 if (user == NULL || particle == NULL) {
1106 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"One or more input pointers are NULL.");
1111 idx, idy, idz, traversal_steps);
1114 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"Particle could not be located within the grid after %d traversal steps.\n", (PetscInt)traversal_steps);
1115 particle->
cell[0] = -1;
1116 particle->
cell[1] = -1;
1117 particle->
cell[2] = -1;
1124 PetscFunctionReturn(0);
1128#define __FUNCT__ "FindOwnerOfCell"
1154 PetscErrorCode ierr;
1157 PetscFunctionBeginUser;
1161 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
1165 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"UserCtx or RankCellInfoMap is not initialized in FindOwnerOfCell.");
1168 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output pointer owner_rank is NULL in FindOwnerOfCell.");
1176 for (PetscMPIInt r = 0; r < size; ++r) {
1192 if (*owner_rank == -1) {
1193 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"No owner found for global cell (%d, %d, %d). It is likely outside the domain.\n", i, j, k);
1199 PetscFunctionReturn(0);
1203#define __FUNCT__ "LocateParticleOrFindMigrationTarget"
1230 PetscErrorCode ierr;
1234 PetscInt idx, idy, idz;
1235 PetscInt traversal_steps;
1236 PetscBool search_concluded = PETSC_FALSE;
1239 PetscInt repeatedIndexCount = 0;
1240 PetscInt prevIdx = PETSC_MIN_INT, prevIdy = PETSC_MIN_INT, prevIdz = PETSC_MIN_INT;
1241 PetscInt last_position_result = -999;
1243 PetscFunctionBeginUser;
1245 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1252 LOG_ALLOW(
LOCAL,
LOG_TRACE,
" [PID %lld]Traversal Initiated at : i = %d, j = %d, k = %d.\n",(
long long)particle->
PID,idx,idy,idz);
1255 while (!search_concluded && traversal_steps <
MAX_TRAVERSAL) {
1262 PetscBool hit_boundary = PETSC_FALSE;
1265 hit_boundary = PETSC_TRUE;
1268 if (idx >= (user->
IM - 1)) {
1270 hit_boundary = PETSC_TRUE;
1275 hit_boundary = PETSC_TRUE;
1278 if (idy >= (user->
JM - 1)) {
1280 hit_boundary = PETSC_TRUE;
1285 hit_boundary = PETSC_TRUE;
1288 if (idz >= (user->
KM - 1)) {
1290 hit_boundary = PETSC_TRUE;
1295 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[PID %lld]: Hit GLOBAL domain boundary. Clamped to boundary cell (%d,%d,%d) and continuing search.\n",
1296 (
long long)particle->
PID, idx, idy, idz);
1301 PetscBool is_cell_local;
1303 if (!is_cell_local) {
1307 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[PID %lld]: Walked outside local ghost region to cell (%d,%d,%d). Concluding search for handoff.\n",
1308 (
long long)particle->
PID, idx, idy, idz);
1309 search_concluded = PETSC_TRUE;
1314 if (idx == prevIdx && idy == prevIdy && idz == prevIdz) {
1315 repeatedIndexCount++;
1318 if (last_position_result >= 1) {
1319 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[PID %lld]: Stuck on boundary of cell (%d,%d,%d) for %d steps. Applying enhanced tie-breaker.\n",
1320 (
long long)particle->
PID, idx, idy, idz, repeatedIndexCount);
1325 PetscInt final_position;
1332 search_concluded = PETSC_TRUE;
1334 LOG_ALLOW(
LOCAL,
LOG_ERROR,
"[PID %lld]: Tie-breaker failed during final evaluation at cell (%d,%d,%d). Search fails.\n",
1335 (
long long)particle->
PID, idx, idy, idz);
1337 search_concluded = PETSC_TRUE;
1340 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",
1341 (
long long)particle->
PID, idx, idy, idz);
1343 search_concluded = PETSC_TRUE;
1345 if(search_concluded)
continue;
1348 repeatedIndexCount = 0;
1350 prevIdx = idx; prevIdy = idy; prevIdz = idz;
1355 PetscInt position_in_cell;
1359 last_position_result = position_in_cell;
1362 if (position_in_cell >= 0) {
1363 search_concluded = PETSC_TRUE;
1371 if (idx == -1 || (!search_concluded && traversal_steps >=
MAX_TRAVERSAL)) {
1377 particle->
cell[0] = -1; particle->
cell[1] = -1; particle->
cell[2] = -1;
1380 PetscMPIInt owner_rank;
1381 ierr =
FindOwnerOfCell(user, idx, idy, idz, &owner_rank); CHKERRQ(ierr);
1386 particle->
cell[0] = idx; particle->
cell[1] = idy; particle->
cell[2] = idz;
1388 if (owner_rank == rank) {
1390 }
else if (owner_rank != -1) {
1396 particle->
cell[0] = -1; particle->
cell[1] = -1; particle->
cell[2] = -1;
1406 PetscFunctionReturn(0);
1411#define __FUNCT__ "ReportSearchOutcome"
1417 PetscInt traversal_steps)
1419 PetscFunctionBeginUser;
1423 LOG_ALLOW(
LOCAL,
LOG_INFO,
"Search SUCCESS [PID %lld]: Located in global cell (%d, %d, %d) after %d steps.\n",
1424 (
long long)particle->
PID, particle->
cell[0], particle->
cell[1], particle->
cell[2], traversal_steps);
1427 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",
1432 (
long long)particle->
PID, traversal_steps);
1439 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.