6#ifndef ERROR_MSG_BUFFER_SIZE
7#define ERROR_MSG_BUFFER_SIZE 256
21 PetscFunctionBeginUser;
26 position->
x += velocity->
x * dt;
27 position->
y += velocity->
y * dt;
28 position->
z += velocity->
z * dt;
30 PetscFunctionReturn(0);
34#define __FUNCT__ "UpdateAllParticlePositions"
45 DM swarm = user->
swarm;
47 PetscReal *pos = NULL;
48 PetscReal *vel = NULL;
52 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
54 PetscFunctionBeginUser;
59 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
62 PetscFunctionReturn(0);
65 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
66 ierr = DMSwarmGetField(swarm,
"velocity", NULL, NULL, (
void**)&vel); CHKERRQ(ierr);
71 for (p = 0; p < nLocal; p++) {
73 temp_pos.
x = pos[3*p];
74 temp_pos.
y = pos[3*p + 1];
75 temp_pos.
z = pos[3*p + 2];
78 temp_vel.
x = vel[3*p];
79 temp_vel.
y = vel[3*p + 1];
80 temp_vel.
z = vel[3*p + 2];
85 pos[3*p] = temp_pos.
x;
86 pos[3*p + 1] = temp_pos.
y;
87 pos[3*p + 2] = temp_pos.
z;
89 vel[3*p] = temp_vel.
x;
90 vel[3*p + 1] = temp_vel.
y;
91 vel[3*p + 2] = temp_vel.
z;
95 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
96 ierr = DMSwarmRestoreField(swarm,
"velocity", NULL, NULL, (
void**)&vel); CHKERRQ(ierr);
102 PetscFunctionReturn(0);
292 PetscInt *removedCountLocal,
293 PetscInt *removedCountGlobal,
297 DM swarm = user->
swarm;
298 PetscInt nLocalInitial;
299 PetscReal *pos_p = NULL;
300 PetscInt64 *pid_p = NULL;
301 PetscInt local_removed_count = 0;
302 PetscMPIInt global_removed_count_mpi = 0;
303 PetscMPIInt rank, size;
305 PetscFunctionBeginUser;
306 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
307 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
311 *removedCountLocal = 0;
312 if (removedCountGlobal) *removedCountGlobal = 0;
314 ierr = DMSwarmGetLocalSize(swarm, &nLocalInitial); CHKERRQ(ierr);
318 if (nLocalInitial > 0) {
320 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
321 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
324 for (PetscInt p = nLocalInitial - 1; p >= 0; p--) {
325 PetscBool isInsideAnyBox = PETSC_FALSE;
326 Cmpnts current_pos = {pos_p[3*p + 0], pos_p[3*p + 1], pos_p[3*p + 2]};
329 for (PetscMPIInt proc = 0; proc < size; proc++) {
331 isInsideAnyBox = PETSC_TRUE;
336 if (!isInsideAnyBox) {
337 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Removing out-of-bounds particle [PID %lld] at local index %d. Pos: (%g, %g, %g)\n",
338 rank, (
long long)pid_p[p], p, current_pos.
x, current_pos.
y, current_pos.
z);
345 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
346 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
349 ierr = DMSwarmRemovePointAtIndex(swarm, p); CHKERRQ(ierr);
350 local_removed_count++;
353 PetscInt nLocalCurrent;
354 ierr = DMSwarmGetLocalSize(swarm, &nLocalCurrent); CHKERRQ(ierr);
356 if (nLocalCurrent > 0 && p > 0) {
357 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
358 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
373 if (pos_p) { ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr); }
374 if (pid_p) { ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr); }
377 PetscInt nLocalFinal;
378 ierr = DMSwarmGetLocalSize(swarm, &nLocalFinal); CHKERRQ(ierr);
379 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[Rank %d] Finished removing %d out-of-bounds particles. Final local size: %d.\n", rank, local_removed_count, nLocalFinal);
382 *removedCountLocal = local_removed_count;
383 if (removedCountGlobal) {
384 ierr = MPI_Allreduce(&local_removed_count, &global_removed_count_mpi, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)swarm)); CHKERRQ(ierr);
385 *removedCountGlobal = global_removed_count_mpi;
390 PetscFunctionReturn(0);
511#define __FUNCT__ "CheckAndRemoveLostParticles"
543 PetscInt *removedCountLocal,
544 PetscInt *removedCountGlobal)
547 DM swarm = user->
swarm;
548 PetscInt nLocalInitial;
549 PetscInt *status_p = NULL;
550 PetscInt64 *pid_p = NULL;
551 PetscReal *pos_p = NULL;
552 PetscInt local_removed_count = 0;
553 PetscMPIInt global_removed_count_mpi = 0;
556 PetscFunctionBeginUser;
558 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
562 *removedCountLocal = 0;
563 if (removedCountGlobal) *removedCountGlobal = 0;
565 ierr = DMSwarmGetLocalSize(swarm, &nLocalInitial); CHKERRQ(ierr);
569 if (nLocalInitial > 0) {
571 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status_p); CHKERRQ(ierr);
572 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
573 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
576 for (PetscInt p = nLocalInitial - 1; p >= 0; p--) {
577 if (status_p[p] ==
LOST) {
578 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Removing LOST particle [PID %lld] at local index %d. Position: (%.4f, %.4f, %.4f).\n",
579 rank, (
long long)pid_p[p], p, pos_p[3*p], pos_p[3*p+1], pos_p[3*p+2]);
586 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status_p); CHKERRQ(ierr);
587 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
588 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
591 ierr = DMSwarmRemovePointAtIndex(swarm, p); CHKERRQ(ierr);
592 local_removed_count++;
595 PetscInt nLocalCurrent;
596 ierr = DMSwarmGetLocalSize(swarm, &nLocalCurrent); CHKERRQ(ierr);
598 if (nLocalCurrent > 0 && p > 0) {
599 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status_p); CHKERRQ(ierr);
600 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr);
601 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr);
617 if (status_p) { ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status_p); CHKERRQ(ierr); }
618 if (pid_p) { ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void **)&pid_p); CHKERRQ(ierr); }
619 if (pos_p) { ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void **)&pos_p); CHKERRQ(ierr); }
622 PetscInt nLocalFinal;
623 ierr = DMSwarmGetLocalSize(swarm, &nLocalFinal); CHKERRQ(ierr);
624 LOG_ALLOW(
LOCAL,
LOG_INFO,
"Rank %d: Finished removing %d LOST particles. Final local size: %d.\n", rank, local_removed_count, nLocalFinal);
627 *removedCountLocal = local_removed_count;
628 if (removedCountGlobal) {
629 ierr = MPI_Allreduce(&local_removed_count, &global_removed_count_mpi, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)swarm)); CHKERRQ(ierr);
630 *removedCountGlobal = global_removed_count_mpi;
636 PetscFunctionReturn(0);
651 DM swarm = user->
swarm;
653 PetscInt *rankField = NULL;
655 PetscFunctionBeginUser;
658 ierr = DMSwarmGetField(swarm,
"DMSwarm_rank", NULL, NULL, (
void **)&rankField); CHKERRQ(ierr);
661 for(p_idx = 0; p_idx < migrationCount; ++p_idx) {
662 rankField[migrationList[p_idx].
local_index] = migrationList[p_idx].target_rank;
665 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_rank", NULL, NULL, (
void **)&rankField); CHKERRQ(ierr);
666 PetscFunctionReturn(0);
682 DM swarm = user->
swarm;
685 PetscFunctionBeginUser;
686 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
691 ierr = DMSwarmMigrate(swarm, PETSC_TRUE); CHKERRQ(ierr);
694 PetscFunctionReturn(0);
717 DM swarm = user->
swarm;
720 PetscInt *global_cell_id_arr;
721 PetscScalar ***count_arr_3d;
725 PetscInt particles_counted_locally = 0;
727 PetscFunctionBeginUser;
728 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
731 if (!da) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->da is NULL.");
732 if (!swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->swarm is NULL.");
733 if (!countVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->ParticleCount is NULL.");
736 ierr = DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &count_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
737 if (count_dof != 1) { PetscSNPrintf(msg,
sizeof(msg),
"countDM must have DOF=1, got %d.", count_dof); SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, msg); }
740 ierr = VecSet(countVec, 0.0); CHKERRQ(ierr);
744 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
745 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&global_cell_id_arr); CHKERRQ(ierr);
746 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid",NULL,NULL,(
void **)&PID_arr);CHKERRQ(ierr);
749 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"CalculateParticleCountPerCell: Accessing ParticleCount vector array (using DMDAVecGetArray).\n");
750 ierr = DMDAVecGetArray(da, countVec, &count_arr_3d); CHKERRQ(ierr);
753 PetscInt xs, ys, zs, xm, ym, zm;
754 ierr = DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
757 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"CalculateParticleCountPerCell (Rank %d): Processing %d local particles using GLOBAL CellIDs.\n",rank,nlocal);
758 for (p = 0; p < nlocal; p++) {
760 PetscInt64 i = global_cell_id_arr[p * 3 + 0];
761 PetscInt64 j = global_cell_id_arr[p * 3 + 1];
762 PetscInt64 k = global_cell_id_arr[p * 3 + 2];
769 LOG_LOOP_ALLOW(
LOCAL,
LOG_DEBUG,p,100,
"[Rank %d CalcCount] Read CellID for p=%d, PID = %ld: (%ld, %ld, %ld)\n", rank, p,PID_arr[p],i, j, k);
779 if (i >= xs && i < xs + xm &&
780 j >= ys && j < ys + ym &&
781 k >= zs && k < zs + zm )
785 count_arr_3d[k][j][i] += 1.0;
786 particles_counted_locally++;
789 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"CalculateParticleCountPerCell (Rank %d): Skipping particle %ld with global CellID (%ld, %ld, %ld) - likely outside local+ghost range.\n",rank, PID_arr[p] , i, j, k);
792 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"CalculateParticleCountPerCell (Rank %d): Local counting finished. Processed %d particles locally.\n", rank, particles_counted_locally);
795 ierr = DMDAVecRestoreArray(da, countVec, &count_arr_3d); CHKERRQ(ierr);
796 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&global_cell_id_arr); CHKERRQ(ierr);
797 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid",NULL,NULL,(
void **)&PID_arr);CHKERRQ(ierr);
801 ierr = VecAssemblyBegin(countVec); CHKERRQ(ierr);
802 ierr = VecAssemblyEnd(countVec); CHKERRQ(ierr);
805 PetscReal total_counted_particles = 0.0, max_count_in_cell = 0.0;
806 ierr = VecSum(countVec, &total_counted_particles); CHKERRQ(ierr);
807 PetscInt max_idx_global = -1;
808 ierr = VecMax(countVec, &max_idx_global, &max_count_in_cell); CHKERRQ(ierr);
809 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"CalculateParticleCountPerCell: Total counted globally = %.0f, Max count in cell = %.0f\n",
810 total_counted_particles, max_count_in_cell);
813 if (max_idx_global >= 0) {
817 ierr = DMDAGetInfo(da, NULL, &M, &N, &P, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
820 PetscInt Kmax = max_idx_global / (M * N);
821 PetscInt Jmax = (max_idx_global % (M * N)) / M;
822 PetscInt Imax = max_idx_global % M;
824 (
int)Imax, (
int)Jmax, (
int)Kmax, (
int)max_idx_global);
827 PetscScalar count_at_origin = 0.0;
828 PetscScalar ***count_arr_for_check;
829 ierr = DMDAVecGetArrayRead(da, countVec, &count_arr_for_check); CHKERRQ(ierr);
831 PetscInt xs, ys, zs, xm, ym, zm;
832 ierr = DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
833 if (0 >= xs && 0 < xs+xm && 0 >= ys && 0 < ys+ym && 0 >= zs && 0 < zs+zm) {
834 count_at_origin = count_arr_for_check[0][0][0];
837 count_at_origin = -999.0;
839 ierr = DMDAVecRestoreArrayRead(da, countVec, &count_arr_for_check); CHKERRQ(ierr);
849 PetscFunctionReturn(0);
860 PetscInt N_current, nlocal_current;
864 PetscFunctionBeginUser;
865 ierr = PetscObjectGetComm((PetscObject)swarm, &comm); CHKERRQ(ierr);
866 ierr = MPI_Comm_rank(comm, &rank); CHKERRQ(ierr);
867 ierr = DMSwarmGetSize(swarm, &N_current); CHKERRQ(ierr);
868 ierr = DMSwarmGetLocalSize(swarm, &nlocal_current); CHKERRQ(ierr);
870 PetscInt delta = N_target - N_current;
873 PetscFunctionReturn(0);
877 PetscInt num_to_remove_global = -delta;
878 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"ResizeSwarmGlobally: Current size %d > target size %d. Removing %d particles globally.\n", N_current, N_target, num_to_remove_global);
888 ierr = MPI_Exscan(&nlocal_current, &rstart, 1, MPIU_INT, MPI_SUM, comm); CHKERRMPI(ierr);
890 rend = rstart + nlocal_current;
894 PetscInt nlocal_remove_count = 0;
895 if (rend > N_target) {
896 PetscInt start_remove_local_idx = (N_target > rstart) ? (N_target - rstart) : 0;
897 nlocal_remove_count = nlocal_current - start_remove_local_idx;
900 if (nlocal_remove_count < 0) nlocal_remove_count = 0;
901 if (nlocal_remove_count > nlocal_current) nlocal_remove_count = nlocal_current;
903 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Global range [%d, %d). Target size %d. Need to remove %d local particles (from end).\n", rank, rstart, rend, N_target, nlocal_remove_count);
906 PetscInt removal_ops_done = 0;
907 for (PetscInt p = nlocal_current - 1; p >= 0 && removal_ops_done < nlocal_remove_count; --p) {
908 ierr = DMSwarmRemovePointAtIndex(swarm, p); CHKERRQ(ierr);
912 if (removal_ops_done != nlocal_remove_count) {
913 SETERRQ(comm, PETSC_ERR_PLIB,
"Rank %d: Failed to remove the expected number of local particles (%d != %d)", rank, removal_ops_done, nlocal_remove_count);
918 ierr = MPI_Barrier(comm); CHKERRMPI(ierr);
921 PetscInt num_to_add_global = delta;
922 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"ResizeSwarmGlobally: Current size %d < target size %d. Adding %d particles globally.\n", N_current, N_target, num_to_add_global);
923 ierr = DMSwarmAddNPoints(swarm, num_to_add_global); CHKERRQ(ierr);
929 ierr = DMSwarmGetSize(swarm, &N_final); CHKERRQ(ierr);
930 if (N_final != N_target) {
931 SETERRQ(comm, PETSC_ERR_PLIB,
"Failed to resize swarm: expected %d particles, got %d", N_target, N_final);
934 PetscFunctionReturn(0);
956 char filename[PETSC_MAX_PATH_LEN];
958 PetscInt N_current = 0;
961 const char *refFieldName =
"position";
962 const PetscInt bs = 3;
968 const int placeholder_int = 0;
970 PetscFunctionBeginUser;
971 ierr = PetscObjectGetComm((PetscObject)user->
swarm, &comm); CHKERRQ(ierr);
972 ierr = MPI_Comm_rank(comm, &rank); CHKERRQ(ierr);
976 ierr = PetscSNPrintf(filename,
sizeof(filename),
"results/%s%05" PetscInt_FMT
"_%d.%s",
977 refFieldName, ti, placeholder_int, ext); CHKERRQ(ierr);
980 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"PreCheckAndResizeSwarm: Checking particle count for timestep %d using ref file '%s'.\n", ti, filename);
984 PetscBool fileExists = PETSC_FALSE;
985 ierr = PetscTestFile(filename,
'r', &fileExists); CHKERRQ(ierr);
996 ierr = VecCreate(PETSC_COMM_SELF, &tmpVec); CHKERRQ(ierr);
997 ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF, filename, FILE_MODE_READ, &viewer); CHKERRQ(ierr);
998 ierr = VecLoad(tmpVec, viewer); CHKERRQ(ierr);
999 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
1001 ierr = VecGetSize(tmpVec, &vecSize); CHKERRQ(ierr);
1002 ierr = VecDestroy(&tmpVec); CHKERRQ(ierr);
1004 if (vecSize % bs != 0) {
1006 LOG_ALLOW(
GLOBAL,
LOG_ERROR,
"Rank 0: Vector size %d from file '%s' is not divisible by block size %d.\n", vecSize, filename, bs);
1008 N_file = vecSize / bs;
1015 ierr = MPI_Bcast(&N_file, 1, MPIU_INT, 0, comm); CHKERRMPI(ierr);
1019 SETERRQ(comm, PETSC_ERR_FILE_OPEN,
"Mandatory reference file '%s' not found for timestep %d (as determined by Rank 0).", filename, ti);
1022 SETERRQ(comm, PETSC_ERR_FILE_READ,
"Reference file '%s' has incorrect format (as determined by Rank 0).", filename);
1025 SETERRQ(comm, PETSC_ERR_PLIB,
"Received invalid particle count %d from Rank 0.", N_file);
1030 ierr = DMSwarmGetSize(user->
swarm, &N_current); CHKERRQ(ierr);
1032 if (N_file != N_current) {
1033 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Swarm size %d differs from file size %d. Resizing swarm globally.\n", N_current, N_file);
1042 PetscFunctionReturn(0);
1061 PetscErrorCode ierr;
1063 DM swarm = user->
swarm;
1064 PetscReal *positions_field = NULL;
1065 PetscReal *pos_phy_field = NULL;
1066 PetscInt64 *particleIDs = NULL;
1067 PetscInt *cell_ID_field = NULL;
1068 const Cmpnts ***coor_nodes_local_array;
1071 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank;
1072 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global;
1074 PetscRandom rand_logic_reinit_i, rand_logic_reinit_j, rand_logic_reinit_k;
1075 PetscInt nlocal_current;
1076 PetscInt particles_actually_reinitialized_count = 0;
1077 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
1079 PetscFunctionBeginUser;
1083 PetscFunctionReturn(0);
1086 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1087 ierr = DMSwarmGetLocalSize(swarm, &nlocal_current); CHKERRQ(ierr);
1090 if (nlocal_current == 0) {
1091 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[T=%.4f, Step=%d] Rank %d has no local particles to re-initialize on inlet.\n", currentTime, step, rank);
1092 PetscFunctionReturn(0);
1096 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
1097 ierr = DMDAGetInfo(user->
da, NULL, &IM_nodes_global, &JM_nodes_global, &KM_nodes_global, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); CHKERRQ(ierr);
1098 ierr = DMDAGetGhostCorners(user->
da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
1101 ierr =
CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
1103 if (!can_this_rank_service_inlet) {
1105 PetscFunctionReturn(0);
1111 ierr = DMGetCoordinatesLocal(user->
da, &Coor_local); CHKERRQ(ierr);
1112 ierr = DMDAVecGetArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
1113 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
1114 ierr = DMSwarmGetField(swarm,
"pos_phy", NULL, NULL, (
void**)&pos_phy_field); CHKERRQ(ierr);
1115 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
1116 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_ID_field); CHKERRQ(ierr);
1124 for (PetscInt p = 0; p < nlocal_current; p++) {
1125 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
1126 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
1131 IM_nodes_global, JM_nodes_global, KM_nodes_global,
1132 &rand_logic_reinit_i, &rand_logic_reinit_j, &rand_logic_reinit_k,
1133 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
1134 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
1138 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
1139 xi_metric_logic, eta_metric_logic, zta_metric_logic,
1140 &phys_coords); CHKERRQ(ierr);
1143 positions_field[3*p+0] = phys_coords.
x;
1144 positions_field[3*p+1] = phys_coords.
y;
1145 positions_field[3*p+2] = phys_coords.
z;
1146 pos_phy_field[3*p+0] = phys_coords.
x;
1147 pos_phy_field[3*p+1] = phys_coords.
y;
1148 pos_phy_field[3*p+2] = phys_coords.
z;
1149 particles_actually_reinitialized_count++;
1151 cell_ID_field[3*p+0] = -1;
1152 cell_ID_field[3*p+1] = -1;
1153 cell_ID_field[3*p+2] = -1;
1156 "ReInit - Rank %d: PID %ld (idx %ld) RE-PLACED. CellOriginNode(locDAIdx):(%d,%d,%d). LogicCoords: (%.2e,%.2f,%.2f). PhysCoords: (%.6f,%.6f,%.6f).\n",
1157 rank, particleIDs[p], (
long)p,
1158 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
1159 xi_metric_logic, eta_metric_logic, zta_metric_logic,
1160 phys_coords.
x, phys_coords.
y, phys_coords.
z);
1164 if (particles_actually_reinitialized_count > 0) {
1165 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"[T=%.4f, Step=%d] Rank %d (on inlet face %d) successfully re-initialized %d of %d local particles.\n", currentTime, step, rank, user->
identifiedInletBCFace, particles_actually_reinitialized_count, nlocal_current);
1166 }
else if (nlocal_current > 0) {
1167 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
"[T=%.4f, Step=%d] Rank %d claimed to service inlet face %d, but re-initialized 0 of %d local particles. This may indicate an issue if particles were expected to be re-placed.\n", currentTime, step, rank, user->
identifiedInletBCFace, nlocal_current);
1171 ierr = PetscRandomDestroy(&rand_logic_reinit_i); CHKERRQ(ierr);
1172 ierr = PetscRandomDestroy(&rand_logic_reinit_j); CHKERRQ(ierr);
1173 ierr = PetscRandomDestroy(&rand_logic_reinit_k); CHKERRQ(ierr);
1175 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
1176 ierr = DMSwarmRestoreField(swarm,
"pos_phy", NULL, NULL, (
void**)&pos_phy_field); CHKERRQ(ierr);
1177 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
1178 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_ID_field); CHKERRQ(ierr);
1179 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
1182 PetscFunctionReturn(0);
1187 PetscInt64 val_a = *(
const PetscInt64*)a;
1188 PetscInt64 val_b = *(
const PetscInt64*)b;
1189 if (val_a < val_b)
return -1;
1190 if (val_a > val_b)
return 1;
1217 PetscInt64 **pids_snapshot_out)
1219 PetscErrorCode ierr;
1222 PetscFunctionBeginUser;
1225 if (!pids_snapshot_out) {
1226 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output pointer pids_snapshot_out is NULL.");
1229 if (n_local > 0 && !pid_field) {
1230 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input pid_field pointer is NULL for n_local > 0.");
1233 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1238 *pids_snapshot_out = NULL;
1239 PetscFunctionReturn(0);
1243 ierr = PetscMalloc1(n_local, pids_snapshot_out); CHKERRQ(ierr);
1247 ierr = PetscMemcpy(*pids_snapshot_out, pid_field, n_local *
sizeof(PetscInt64)); CHKERRQ(ierr);
1252 ierr = PetscSortInt64(n_local, *pids_snapshot_out); CHKERRQ(ierr);
1255 PetscFunctionReturn(0);
1281 PetscInt *capacity_p,
1283 PetscInt particle_local_idx,
1284 PetscMPIInt destination_rank)
1286 PetscErrorCode ierr;
1289 PetscFunctionBeginUser;
1292 if (!migration_list_p || !capacity_p || !count_p) {
1293 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null pointer provided to AddToMigrationList for list management.");
1297 if (*count_p >= *capacity_p) {
1298 PetscInt old_capacity = *capacity_p;
1300 PetscInt new_capacity = (old_capacity == 0) ? 16 : old_capacity * 2;
1305 ierr = PetscRealloc(new_capacity *
sizeof(
MigrationInfo), migration_list_p); CHKERRQ(ierr);
1307 *capacity_p = new_capacity;
1309 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1310 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"AddToMigrationList [Rank %d]: Reallocated migrationList capacity from %d to %d.\n",
1311 rank, old_capacity, new_capacity);
1318 list[*count_p].local_index = particle_local_idx;
1319 list[*count_p].target_rank = destination_rank;
1324 PetscFunctionReturn(0);
1356 PetscInt n_local_before,
1357 const PetscInt64 pids_before[])
1359 PetscErrorCode ierr;
1361 PetscInt n_local_after;
1362 PetscInt newcomer_count = 0;
1365 PetscInt64 *pid_field_after = NULL;
1366 PetscInt *status_field_after = NULL;
1367 PetscInt *cell_field_after = NULL;
1369 PetscFunctionBeginUser;
1373 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Input DMSwarm is NULL in FlagNewcomersForLocation.");
1376 if (n_local_before > 0 && !pids_before) {
1377 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input pids_before array is NULL for n_local_before > 0.");
1380 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1383 ierr = DMSwarmGetLocalSize(swarm, &n_local_after); CHKERRQ(ierr);
1385 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"FlagNewcomersForLocation [Rank %d]: Checking for newcomers. Size before: %d, Size after: %d\n",
1386 rank, n_local_before, n_local_after);
1389 if (n_local_after == 0) {
1390 PetscFunctionReturn(0);
1395 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pid_field_after); CHKERRQ(ierr);
1396 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_field_after); CHKERRQ(ierr);
1397 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_field_after); CHKERRQ(ierr);
1398 if (!pid_field_after || !status_field_after) {
1399 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Failed to get required swarm fields in FlagNewcomersForLocation.");
1404 for (PetscInt p_idx = 0; p_idx < n_local_after; ++p_idx) {
1405 PetscInt64 current_pid = pid_field_after[p_idx];
1406 PetscBool is_found_in_before_list;
1409 ierr =
BinarySearchInt64(n_local_before, pids_before, current_pid, &is_found_in_before_list); CHKERRQ(ierr);
1412 if (!is_found_in_before_list) {
1421 rank, current_pid, p_idx);
1427 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pid_field_after); CHKERRQ(ierr);
1428 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_field_after); CHKERRQ(ierr);
1429 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_field_after); CHKERRQ(ierr);
1431 if (newcomer_count > 0) {
1435 PetscFunctionReturn(0);
1465 PetscMPIInt *guess_rank_out)
1467 PetscErrorCode ierr;
1468 PetscMPIInt rank, size;
1472 PetscFunctionBeginUser;
1475 if (!user || !particle || !guess_rank_out || !bboxlist) {
1476 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null pointer provided to GuessParticleOwnerWithBBox.");
1478 if (!localBBox|| !neighbors) {
1479 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Required user->bboxl or user->neighbors is not initialized.");
1482 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1483 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
1485 *guess_rank_out = MPI_PROC_NULL;
1494 *guess_rank_out = rank;
1495 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[PID %ld]: Fast path guess SUCCESS. Particle is within the local (Rank %d) bounding box.\n",
1496 particle->
PID, rank);
1497 PetscFunctionReturn(0);
1510 *guess_rank_out = neighbors->
rank_xm;
1512 *guess_rank_out = neighbors->
rank_xp;
1514 *guess_rank_out = neighbors->
rank_ym;
1516 *guess_rank_out = neighbors->
rank_yp;
1518 *guess_rank_out = neighbors->
rank_zm;
1520 *guess_rank_out = neighbors->
rank_zp;
1524 if (*guess_rank_out != MPI_PROC_NULL) {
1526 particle->
PID, *guess_rank_out);
1527 PetscFunctionReturn(0);
1535 for (PetscMPIInt r = 0; r < size; ++r) {
1536 if (r == rank)
continue;
1539 PetscBool is_in = PETSC_TRUE;
1541 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[Guess BBox | Rank %d] Checking PID %lld at (%.4f, %.4f, %.4f) against Rank %d's box: [(%.4f, %.4f, %.4f) to (%.4f, %.4f, %.4f)]. Result: %s\n",
1542 (
int)rank, (
long long)particle->
PID,
1547 is_in ?
"INSIDE" :
"OUTSIDE");
1549 *guess_rank_out = r;
1551 particle->
PID, *guess_rank_out);
1552 PetscFunctionReturn(0);
1561 PetscFunctionReturn(0);
1565#define __FUNCT__ "LocateAllParticlesInGrid_TEST"
1600 PetscErrorCode ierr;
1601 PetscInt passes = 0;
1602 const PetscInt MAX_MIGRATION_PASSES = 10;
1603 PetscInt global_migrations_this_pass;
1606 PetscFunctionBeginUser;
1608 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1610 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"LocateAllParticlesInGrid (Orchestrator) - Beginning particle settlement process.\n");
1620 PetscInt local_migration_count = 0;
1621 PetscInt migrationListCapacity = 0;
1622 PetscInt nlocal_before;
1623 PetscInt64 *pids_before_snapshot = NULL;
1624 PetscInt local_lost_count = 0;
1626 ierr = DMSwarmGetLocalSize(user->
swarm, &nlocal_before); CHKERRQ(ierr);
1627 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[Rank %d] Pass %d begins with %d local particles.\n", rank, passes, nlocal_before);
1631 if (nlocal_before > 0) {
1633 PetscReal *pos_p, *weights_p, *vel_p;
1634 PetscInt *cell_p, *status_p;
1636 ierr = DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void**)&pos_p); CHKERRQ(ierr);
1637 ierr = DMSwarmGetField(user->
swarm,
"velocity", NULL, NULL, (
void**)&vel_p); CHKERRQ(ierr);
1638 ierr = DMSwarmGetField(user->
swarm,
"weight", NULL, NULL, (
void**)&weights_p); CHKERRQ(ierr);
1639 ierr = DMSwarmGetField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_p); CHKERRQ(ierr);
1640 ierr = DMSwarmGetField(user->
swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pid_p); CHKERRQ(ierr);
1641 ierr = DMSwarmGetField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_p); CHKERRQ(ierr);
1647 for (PetscInt p_idx = 0; p_idx < nlocal_before; p_idx++) {
1652 "p_idx=%d, PID=%ld, status=%d, cell=(%d, %d, %d)\n",
1661 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
" [rank %d][PID %ld] skipped in pass %d as it is already located at (%d,%d,%d).\n",rank,pid_p[p_idx],passes,cell_p[3*p_idx],cell_p[3*p_idx + 1],cell_p[3*p_idx + 2]);
1670 ierr =
UnpackSwarmFields(p_idx, pid_p, weights_p, pos_p, cell_p, vel_p, status_p, ¤t_particle); CHKERRQ(ierr);
1679 if (current_particle.
cell[0] >= 0) {
1680 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[PID %ld] has valid prior cell. Strategy: Robust Walk from previous cell.\n", current_particle.
PID);
1722 PetscMPIInt guessed_owner_rank = MPI_PROC_NULL;
1726 if (guessed_owner_rank != MPI_PROC_NULL && guessed_owner_rank != rank) {
1727 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[PID %ld] Guess SUCCESS: Found migration target Rank %d. Finalizing.\n", current_particle.
PID, guessed_owner_rank);
1735 if (guessed_owner_rank == rank) {
1736 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[PID %ld] Guess determined particle is local. Proceeding to robust walk to find cell.\n", current_particle.
PID);
1738 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[PID %ld] Guess FAILED to find an owner. Proceeding to robust walk for definitive search.\n", current_particle.
PID);
1747 ierr =
UpdateSwarmFields(p_idx, ¤t_particle, weights_p, cell_p, status_p); CHKERRQ(ierr);
1751 }
else if (final_status ==
LOST) {
1758 ierr = DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void**)&pos_p); CHKERRQ(ierr);
1759 ierr = DMSwarmRestoreField(user->
swarm,
"velocity", NULL, NULL, (
void**)&vel_p); CHKERRQ(ierr);
1760 ierr = DMSwarmRestoreField(user->
swarm,
"weight", NULL, NULL, (
void**)&weights_p); CHKERRQ(ierr);
1761 ierr = DMSwarmRestoreField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cell_p); CHKERRQ(ierr);
1762 ierr = DMSwarmRestoreField(user->
swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pid_p); CHKERRQ(ierr);
1763 ierr = DMSwarmRestoreField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_p); CHKERRQ(ierr);
1767 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[Rank %d] Pass %d: Identified %d particles to migrate out.\n", rank, passes, local_migration_count);
1772 ierr = MPI_Allreduce(&local_migration_count, &global_migrations_this_pass, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRQ(ierr);
1774 if(global_migrations_this_pass > 0 ){
1776 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Pass %d: Migrating %d particles globally.\n", passes, global_migrations_this_pass);
1778 ierr =
SetMigrationRanks(user, migrationList, local_migration_count); CHKERRQ(ierr);
1788 ierr = PetscFree(pids_before_snapshot);
1789 ierr = PetscFree(migrationList);
1791 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"End of LocateAllParticlesInGrid pass %d. Total particles migrated globally: %d.\n", passes, global_migrations_this_pass);
1793 }
while (global_migrations_this_pass > 0 && passes < MAX_MIGRATION_PASSES);
1796 if (passes >= MAX_MIGRATION_PASSES) {
1797 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_CONV_FAILED,
"Particle migration failed to converge after %d passes. Check for particles oscillating between ranks.", MAX_MIGRATION_PASSES);
1803 PetscFunctionReturn(0);
1820 PetscErrorCode ierr;
1824 PetscFunctionBeginUser;
1826 ierr = DMSwarmGetLocalSize(user->
swarm, &n_local); CHKERRQ(ierr);
1830 ierr = DMSwarmGetField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_p); CHKERRQ(ierr);
1832 for (PetscInt p = 0; p < n_local; ++p) {
1841 ierr = DMSwarmRestoreField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_p); CHKERRQ(ierr);
1844 PetscFunctionReturn(0);
PetscErrorCode CanRankServiceInletFace(UserCtx *user, const DMDALocalInfo *info, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, PetscBool *can_service_inlet_out)
Determines if the current MPI rank owns any part of the globally defined inlet face,...
PetscErrorCode GetRandomCellAndLogicOnInletFace(UserCtx *user, const DMDALocalInfo *info, PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr, PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out, PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out)
Assuming the current rank services the inlet face, this function selects a random cell (owned by this...
PetscErrorCode MetricLogicalToPhysical(UserCtx *user, const Cmpnts ***X, PetscInt i, PetscInt j, PetscInt k, PetscReal xi, PetscReal eta, PetscReal zta, Cmpnts *Xp)
Public wrapper: map (cell index, ξ,η,ζ) to (x,y,z).
PetscErrorCode UpdateParticlePosition(UserCtx *user, Cmpnts *position, const Cmpnts *velocity)
Updates a particle's position based on its velocity and the timestep dt (stored in user->dt).
static int compare_PetscInt64(const void *a, const void *b)
PetscErrorCode GuessParticleOwnerWithBBox(UserCtx *user, const Particle *particle, const BoundingBox *bboxlist, PetscMPIInt *guess_rank_out)
Provides a fast, heuristic-based guess for a particle's owner rank using bounding boxes.
PetscErrorCode ResizeSwarmGlobally(DM swarm, PetscInt N_target)
PetscErrorCode AddToMigrationList(MigrationInfo **migration_list_p, PetscInt *capacity_p, PetscInt *count_p, PetscInt particle_local_idx, PetscMPIInt destination_rank)
Safely adds a new migration task to a dynamically sized list.
PetscErrorCode SetMigrationRanks(UserCtx *user, const MigrationInfo *migrationList, PetscInt migrationCount)
Sets the target rank field (DMSwarmPICField_rank) for particles scheduled for migration.
PetscErrorCode CheckAndRemoveOutOfBoundsParticles(UserCtx *user, PetscInt *removedCountLocal, PetscInt *removedCountGlobal, const BoundingBox *bboxlist)
Checks for particles outside the global physical domain and removes them.
PetscErrorCode GetLocalPIDSnapshot(const PetscInt64 pid_field[], PetscInt n_local, PetscInt64 **pids_snapshot_out)
Creates a sorted snapshot of all Particle IDs (PIDs) from a raw data array.
PetscErrorCode LocateAllParticlesInGrid_TEST(UserCtx *user, BoundingBox *bboxlist)
Orchestrates the complete particle location and migration process for one timestep.
PetscErrorCode UpdateAllParticlePositions(UserCtx *user)
Loops over all local particles in the DMSwarm, updating their positions based on velocity and the glo...
#define ERROR_MSG_BUFFER_SIZE
PetscErrorCode ResetAllParticleStatuses(UserCtx *user)
This function is designed to be called at the end of a full timestep, after all particle-based calcul...
PetscErrorCode ReinitializeParticlesOnInletSurface(UserCtx *user, PetscReal currentTime, PetscInt step)
Re-initializes the positions of particles currently on this rank if this rank owns part of the design...
PetscErrorCode CheckAndRemoveLostParticles(UserCtx *user, PetscInt *removedCountLocal, PetscInt *removedCountGlobal)
Removes particles that have been definitively flagged as LOST by the location algorithm.
PetscErrorCode FlagNewcomersForLocation(DM swarm, PetscInt n_local_before, const PetscInt64 pids_before[])
Identifies newly arrived particles after migration and flags them for a location search.
static PetscBool IsParticleInBox(const BoundingBox *bbox, const Cmpnts *pos)
Checks if a particle position is within the bounds of a given bounding box.
PetscErrorCode PreCheckAndResizeSwarm(UserCtx *user, PetscInt ti, const char *ext)
Checks particle count from a saved file and resizes the swarm globally.
PetscErrorCode PerformMigration(UserCtx *user)
Performs particle migration based on the pre-populated DMSwarmPICField_rank field.
PetscErrorCode UnpackSwarmFields(PetscInt i, const PetscInt64 *PIDs, const PetscReal *weights, const PetscReal *positions, const PetscInt *cellIndices, PetscReal *velocities, PetscInt *LocStatus, Particle *particle)
Initializes a Particle struct with data from DMSwarm fields.
PetscErrorCode InitializeLogicalSpaceRNGs(PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Initializes random number generators for logical space operations [0.0, 1.0).
PetscErrorCode UpdateSwarmFields(PetscInt i, const Particle *particle, PetscReal *weights, PetscInt *cellIndices, PetscInt *status_field)
Updates DMSwarm fields with data from a Particle struct.
PetscErrorCode CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt,...)
Logs a message inside a loop, but only every interval iterations.
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level,...
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
#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 LOG_FUNC_TIMER_END_EVENT(eventID, scope)
Ends timing a function by:
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
#define LOG_FUNC_TIMER_BEGIN_EVENT(eventID, scope)
Begins timing a function by:
@ LOG_ERROR
Critical errors that may halt the program.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
PetscLogEvent EVENT_GlobalParticleLocation
PetscErrorCode BinarySearchInt64(PetscInt n, const PetscInt64 arr[], PetscInt64 key, PetscBool *found)
Performs a binary search for a key in a sorted array of PetscInt64.
PetscBool inletFaceDefined
BCFace identifiedInletBCFace
SimCtx * simCtx
Back-pointer to the master simulation context.
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
PetscMPIInt destination_rank
ParticleLocationStatus location_status
PetscInt ParticleInitialization
Defines a 3D axis-aligned bounding box.
A 3D point or vector with PetscScalar components.
Information needed to migrate a single particle between MPI ranks.
Defines a particle's core properties for Lagrangian tracking.
Stores the MPI ranks of neighboring subdomains.
User-defined context containing data specific to a single computational grid level.
Head of a generic C-style linked list.
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.