137 DM swarm = user->
swarm;
139 PetscReal *pos = NULL;
140 PetscReal *vel = NULL;
141 PetscReal *diffusivity = NULL;
142 Cmpnts *diffusivitygradient = NULL;
143 PetscReal *psi = NULL;
144 PetscReal *weights = NULL;
145 PetscInt *cell = NULL;
146 PetscInt *status = NULL;
147 PetscInt64 *pid = NULL;
150 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
152 PetscFunctionBeginUser;
157 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
161 PetscFunctionReturn(0);
177 for (p = 0; p < nLocal; p++) {
182 ierr =
UnpackSwarmFields(p, pid, weights, pos, cell, vel, status, diffusivity, diffusivitygradient, psi, &particle); CHKERRQ(ierr);
188 ierr =
UpdateSwarmFields(p, &particle, pos, vel, weights, cell, status, diffusivity, diffusivitygradient, psi); CHKERRQ(ierr);
207 PetscFunctionReturn(0);
229 PetscInt *removedCountLocal,
230 PetscInt *removedCountGlobal,
234 DM swarm = user->
swarm;
235 PetscInt nLocalInitial;
236 PetscReal *pos_p = NULL;
237 PetscInt64 *pid_p = NULL;
238 PetscInt local_removed_count = 0;
239 PetscMPIInt global_removed_count_mpi = 0;
240 PetscMPIInt rank, size;
242 PetscFunctionBeginUser;
243 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
244 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
248 *removedCountLocal = 0;
249 if (removedCountGlobal) *removedCountGlobal = 0;
251 ierr = DMSwarmGetLocalSize(swarm, &nLocalInitial); CHKERRQ(ierr);
255 if (nLocalInitial > 0) {
261 for (PetscInt p = nLocalInitial - 1; p >= 0; p--) {
262 PetscBool isInsideAnyBox = PETSC_FALSE;
263 Cmpnts current_pos = {pos_p[3*p + 0], pos_p[3*p + 1], pos_p[3*p + 2]};
266 for (PetscMPIInt proc = 0; proc < size; proc++) {
268 isInsideAnyBox = PETSC_TRUE;
273 if (!isInsideAnyBox) {
274 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Removing out-of-bounds particle [PID %lld] at local index %d. Pos: (%g, %g, %g)\n",
275 rank, (
long long)pid_p[p], p, current_pos.
x, current_pos.
y, current_pos.
z);
286 ierr = DMSwarmRemovePointAtIndex(swarm, p); CHKERRQ(ierr);
287 local_removed_count++;
290 PetscInt nLocalCurrent;
291 ierr = DMSwarmGetLocalSize(swarm, &nLocalCurrent); CHKERRQ(ierr);
293 if (nLocalCurrent > 0 && p > 0) {
314 PetscInt nLocalFinal;
315 ierr = DMSwarmGetLocalSize(swarm, &nLocalFinal); CHKERRQ(ierr);
316 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[Rank %d] Finished removing %d out-of-bounds particles. Final local size: %d.\n", rank, local_removed_count, nLocalFinal);
319 *removedCountLocal = local_removed_count;
320 if (removedCountGlobal) {
321 ierr = MPI_Allreduce(&local_removed_count, &global_removed_count_mpi, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)swarm)); CHKERRQ(ierr);
322 *removedCountGlobal = global_removed_count_mpi;
327 PetscFunctionReturn(0);
337 PetscInt *removedCountLocal,
338 PetscInt *removedCountGlobal,
339 PetscReal *removedScalarSumGlobal)
342 DM swarm = user->
swarm;
343 PetscInt nLocalInitial;
344 PetscInt *status_p = NULL;
345 PetscInt64 *pid_p = NULL;
346 PetscReal *pos_p = NULL;
347 PetscReal *psi_p = NULL;
348 PetscReal local_removed_psi = 0.0;
349 PetscInt local_removed_count = 0;
350 PetscMPIInt global_removed_count_mpi = 0;
353 PetscFunctionBeginUser;
355 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
359 *removedCountLocal = 0;
360 if (removedCountGlobal) *removedCountGlobal = 0;
361 if (removedScalarSumGlobal) *removedScalarSumGlobal = 0.0;
363 ierr = DMSwarmGetLocalSize(swarm, &nLocalInitial); CHKERRQ(ierr);
367 if (nLocalInitial > 0) {
375 for (PetscInt p = nLocalInitial - 1; p >= 0; p--) {
376 if (status_p[p] ==
LOST) {
377 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Removing LOST particle [PID %lld] at local index %d. Position: (%.4f, %.4f, %.4f).\n",
378 rank, (
long long)pid_p[p], p, pos_p[3*p], pos_p[3*p+1], pos_p[3*p+2]);
385 local_removed_psi += psi_p[p];
394 ierr = DMSwarmRemovePointAtIndex(swarm, p); CHKERRQ(ierr);
395 local_removed_count++;
398 PetscInt nLocalCurrent;
399 ierr = DMSwarmGetLocalSize(swarm, &nLocalCurrent); CHKERRQ(ierr);
401 if (nLocalCurrent > 0 && p > 0) {
428 PetscInt nLocalFinal;
429 ierr = DMSwarmGetLocalSize(swarm, &nLocalFinal); CHKERRQ(ierr);
430 LOG_ALLOW(
LOCAL,
LOG_INFO,
"Rank %d: Finished removing %d LOST particles. Final local size: %d.\n", rank, local_removed_count, nLocalFinal);
433 *removedCountLocal = local_removed_count;
434 if (removedCountGlobal) {
435 ierr = MPI_Allreduce(&local_removed_count, &global_removed_count_mpi, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)swarm)); CHKERRQ(ierr);
436 *removedCountGlobal = global_removed_count_mpi;
440 if (removedScalarSumGlobal) {
441 ierr = MPI_Allreduce(&local_removed_psi, removedScalarSumGlobal, 1, MPIU_REAL, MPI_SUM,
442 PetscObjectComm((PetscObject)swarm)); CHKERRMPI(ierr);
446 PetscFunctionReturn(0);
524 DM swarm = user->
swarm;
528 PetscInt *global_cell_id_arr;
529 PetscScalar ***count_arr_3d;
533 PetscInt particles_counted_locally = 0;
535 PetscFunctionBeginUser;
537 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
540 if (!da) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->da is NULL.");
541 if (!swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->swarm is NULL.");
542 if (!countVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->ParticleCount is NULL.");
545 ierr = DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &count_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
546 if (count_dof != 1) {
547 PetscSNPrintf(msg,
sizeof(msg),
"countDM must have DOF=1, got %" PetscInt_FMT
".", count_dof);
548 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"%s", msg);
552 ierr = VecSet(localcountVec, 0.0); CHKERRQ(ierr);
556 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
562 ierr = DMDAVecGetArray(da, localcountVec, &count_arr_3d); CHKERRQ(ierr);
565 PetscInt gxs, gys, gzs, gxm, gym, gzm;
566 ierr = DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm); CHKERRQ(ierr);
569 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"CalculateParticleCountPerCell (Rank %d): Processing %" PetscInt_FMT
" local particles using GLOBAL CellIDs.\n",rank,nlocal);
570 for (p = 0; p < nlocal; p++) {
572 PetscInt i_geom = global_cell_id_arr[p * 3 + 0];
573 PetscInt j_geom = global_cell_id_arr[p * 3 + 1];
574 PetscInt k_geom = global_cell_id_arr[p * 3 + 2];
577 PetscInt i = (PetscInt)i_geom + 1;
578 PetscInt j = (PetscInt)j_geom + 1;
579 PetscInt k = (PetscInt)k_geom + 1;
587 "[Rank %d] Read CellID for p=%" PetscInt_FMT
", PID = %" PetscInt64_FMT
": (%" PetscInt_FMT
", %" PetscInt_FMT
", %" PetscInt_FMT
")\n",
588 rank, p, PID_arr[p], i, j, k);
591 if (i >= gxs && i < gxs + gxm &&
592 j >= gys && j < gys + gym &&
593 k >= gzs && k < gzs + gzm )
598 count_arr_3d[k][j][i] += 1.0;
599 particles_counted_locally++;
604 "(Rank %d): Skipping particle %" PetscInt64_FMT
" with global CellID (%" PetscInt_FMT
", %" PetscInt_FMT
", %" PetscInt_FMT
") - likely outside local+ghost range.\n",
605 rank, PID_arr[p], i, j, k);
608 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"(Rank %d): Local counting finished. Processed %" PetscInt_FMT
" particles locally.\n", rank, particles_counted_locally);
611 ierr = DMDAVecRestoreArray(da, localcountVec, &count_arr_3d); CHKERRQ(ierr);
617 ierr = VecZeroEntries(countVec); CHKERRQ(ierr);
618 ierr = DMLocalToGlobalBegin(da, localcountVec, ADD_VALUES, countVec); CHKERRQ(ierr);
619 ierr = DMLocalToGlobalEnd(da, localcountVec, ADD_VALUES, countVec); CHKERRQ(ierr);
630 PetscReal total_counted_particles = 0.0, max_count_in_cell = 0.0;
631 ierr = VecSum(countVec, &total_counted_particles); CHKERRQ(ierr);
632 PetscInt max_idx_global = -1;
633 ierr = VecMax(countVec, &max_idx_global, &max_count_in_cell); CHKERRQ(ierr);
635 total_counted_particles, max_count_in_cell);
638 if (max_idx_global >= 0) {
642 ierr = DMDAGetInfo(da, NULL, &M, &N, &P, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
645 PetscInt Kmax = max_idx_global / (M * N);
646 PetscInt Jmax = (max_idx_global % (M * N)) / M;
647 PetscInt Imax = max_idx_global % M;
649 (
int)Imax, (
int)Jmax, (
int)Kmax, (
int)max_idx_global);
652 PetscScalar count_at_origin = 0.0;
653 PetscScalar ***count_arr_for_check;
654 ierr = DMDAVecGetArrayRead(da, countVec, &count_arr_for_check); CHKERRQ(ierr);
656 PetscInt xs, ys, zs, xm, ym, zm;
657 ierr = DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
658 if (0 >= xs && 0 < xs+xm && 0 >= ys && 0 < ys+ym && 0 >= zs && 0 < zs+zm) {
659 count_at_origin = count_arr_for_check[0][0][0];
662 count_at_origin = -999.0;
664 ierr = DMDAVecRestoreArrayRead(da, countVec, &count_arr_for_check); CHKERRQ(ierr);
676 PetscFunctionReturn(0);
780 DM swarm = user->
swarm;
781 PetscReal *positions_field = NULL;
782 PetscInt64 *particleIDs = NULL;
783 PetscInt *cell_ID_field = NULL;
784 const Cmpnts ***coor_nodes_local_array;
787 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank;
788 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global;
790 PetscRandom rand_logic_reinit_i, rand_logic_reinit_j, rand_logic_reinit_k;
791 PetscInt nlocal_current;
792 PetscInt particles_actually_reinitialized_count = 0;
793 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
795 PetscFunctionBeginUser;
802 PetscFunctionReturn(0);
805 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
806 ierr = DMSwarmGetLocalSize(swarm, &nlocal_current); CHKERRQ(ierr);
809 if (nlocal_current == 0) {
810 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[T=%.4f, Step=%d] Rank %d has no local particles to re-initialize on inlet.\n", currentTime, step, rank);
812 PetscFunctionReturn(0);
816 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
817 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);
818 ierr = DMDAGetCorners(user->
da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
821 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
823 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
824 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
825 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
830 ierr =
CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
833 ierr = DMGetCoordinatesLocal(user->
da, &Coor_local); CHKERRQ(ierr);
834 ierr = DMDAVecGetArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
839 if (!can_this_rank_service_inlet) {
843 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[T=%.4f, Step=%d] Rank %d is resetting %d local particles to inlet center (%.6f, %.6f, %.6f) for migration.\n", currentTime, step, rank, nlocal_current, user->
simCtx->
CMx_c, user->
simCtx->
CMy_c, user->
simCtx->
CMz_c);
845 for(PetscInt p = 0; p < nlocal_current; p++){
850 cell_ID_field[3*p+0] = -1;
851 cell_ID_field[3*p+1] = -1;
852 cell_ID_field[3*p+2] = -1;
856 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
861 PetscFunctionReturn(0);
870 for (PetscInt p = 0; p < nlocal_current; p++) {
871 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
872 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
873 Cmpnts phys_coords = {0.0,0.0,0.0};
874 PetscBool particle_was_placed = PETSC_FALSE;
879 IM_nodes_global, JM_nodes_global, KM_nodes_global,
880 &rand_logic_reinit_i, &rand_logic_reinit_j, &rand_logic_reinit_k,
881 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
882 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
887 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
888 xi_metric_logic, eta_metric_logic, zta_metric_logic,
889 &phys_coords); CHKERRQ(ierr);
892 positions_field[3*p+0] = phys_coords.
x;
893 positions_field[3*p+1] = phys_coords.
y;
894 positions_field[3*p+2] = phys_coords.
z;
895 particle_was_placed = PETSC_TRUE;
898 PetscBool placement_flag = PETSC_FALSE;
900 IM_cells_global, JM_cells_global, KM_cells_global,
902 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
903 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,&placement_flag); CHKERRQ(ierr);
909 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
910 xi_metric_logic, eta_metric_logic, zta_metric_logic,
911 &phys_coords); CHKERRQ(ierr);
914 positions_field[3*p+0] = phys_coords.
x;
915 positions_field[3*p+1] = phys_coords.
y;
916 positions_field[3*p+2] = phys_coords.
z;
917 particle_was_placed = PETSC_TRUE;
921 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
"Rank %d: Particle PID %ld deterministic placement failed (belongs to different rank). Falling back to random placement.\n", rank, particleIDs[p]);
924 IM_nodes_global, JM_nodes_global, KM_nodes_global,
925 &rand_logic_reinit_i, &rand_logic_reinit_j, &rand_logic_reinit_k,
926 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
927 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
931 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
932 xi_metric_logic, eta_metric_logic, zta_metric_logic,
933 &phys_coords); CHKERRQ(ierr);
936 positions_field[3*p+0] = phys_coords.
x;
937 positions_field[3*p+1] = phys_coords.
y;
938 positions_field[3*p+2] = phys_coords.
z;
939 particle_was_placed = PETSC_TRUE;
943 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"ReinitializeParticlesOnInletSurface only supports ParticleInitialization modes 0 and 3.");
946 if(particle_was_placed){
947 particles_actually_reinitialized_count++;
949 cell_ID_field[3*p+0] = -1;
950 cell_ID_field[3*p+1] = -1;
951 cell_ID_field[3*p+2] = -1;
954 "Rank %d: PID %ld (idx %ld) RE-PLACED. CellOriginNode(locDAIdx):(%d,%d,%d). LogicCoords: (%.2e,%.2f,%.2f). PhysCoords: (%.6f,%.6f,%.6f).\n",
955 rank, particleIDs[p], (
long)p,
956 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
957 xi_metric_logic, eta_metric_logic, zta_metric_logic,
958 phys_coords.
x, phys_coords.
y, phys_coords.
z);
963 if (particles_actually_reinitialized_count > 0) {
964 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);
965 }
else if (nlocal_current > 0) {
966 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);
970 ierr = PetscRandomDestroy(&rand_logic_reinit_i); CHKERRQ(ierr);
971 ierr = PetscRandomDestroy(&rand_logic_reinit_j); CHKERRQ(ierr);
972 ierr = PetscRandomDestroy(&rand_logic_reinit_k); CHKERRQ(ierr);
977 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
981 PetscFunctionReturn(0);
1104 PetscInt n_local_before,
1105 const PetscInt64 pids_before[])
1107 PetscErrorCode ierr;
1109 PetscInt n_local_after;
1110 PetscInt newcomer_count = 0;
1113 PetscInt64 *pid_field_after = NULL;
1114 PetscInt *status_field_after = NULL;
1115 PetscInt *cell_field_after = NULL;
1117 PetscFunctionBeginUser;
1123 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Input DMSwarm is NULL in FlagNewcomersForLocation.");
1126 if (n_local_before > 0 && !pids_before) {
1127 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input pids_before array is NULL for n_local_before > 0.");
1130 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1133 ierr = DMSwarmGetLocalSize(swarm, &n_local_after); CHKERRQ(ierr);
1136 rank, n_local_before, n_local_after);
1139 if (n_local_after == 0) {
1141 PetscFunctionReturn(0);
1149 if (!pid_field_after || !status_field_after) {
1150 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Failed to get required swarm fields in FlagNewcomersForLocation.");
1155 for (PetscInt p_idx = 0; p_idx < n_local_after; ++p_idx) {
1156 PetscInt64 current_pid = pid_field_after[p_idx];
1157 PetscBool is_found_in_before_list;
1160 ierr =
BinarySearchInt64(n_local_before, pids_before, current_pid, &is_found_in_before_list); CHKERRQ(ierr);
1163 if (!is_found_in_before_list) {
1172 rank, current_pid, p_idx);
1182 if (newcomer_count > 0) {
1188 PetscFunctionReturn(0);
1199 PetscErrorCode ierr;
1200 DM swarm = user->
swarm;
1202 PetscInt *cell_p = NULL;
1203 PetscInt64 *pid_p = NULL;
1207 PetscInt local_migration_count = 0;
1208 PetscInt migrationListCapacity = 0;
1209 PetscInt global_migration_count = 0;
1211 PetscFunctionBeginUser;
1213 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1215 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1225 for (PetscInt p_idx = 0; p_idx < nlocal; ++p_idx) {
1226 PetscInt ci = cell_p[3*p_idx + 0];
1227 PetscInt cj = cell_p[3*p_idx + 1];
1228 PetscInt ck = cell_p[3*p_idx + 2];
1231 if (ci < 0 || cj < 0 || ck < 0) {
1235 PetscMPIInt owner_rank;
1238 if (owner_rank != -1 && owner_rank != rank) {
1240 ierr =
AddToMigrationList(&migrationList, &migrationListCapacity, &local_migration_count,
1241 p_idx, owner_rank); CHKERRQ(ierr);
1244 (
long)pid_p[p_idx], ci, cj, ck, owner_rank, rank);
1253 ierr = MPI_Allreduce(&local_migration_count, &global_migration_count, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRQ(ierr);
1255 if (global_migration_count > 0) {
1256 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Fast restart migration: Directly migrating %d particles using CellIDs.\n", global_migration_count);
1257 ierr =
SetMigrationRanks(user, migrationList, local_migration_count); CHKERRQ(ierr);
1265 ierr = PetscFree(migrationList); CHKERRQ(ierr);
1268 PetscFunctionReturn(0);
1401 PetscErrorCode ierr;
1402 PetscInt passes = 0;
1403 const PetscInt MAX_MIGRATION_PASSES = 50;
1404 PetscInt global_migrations_this_pass;
1406 PetscInt total_migrated_this_timestep = 0;
1408 PetscFunctionBeginUser;
1410 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1412 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"LocateAllParticlesInGrid (Orchestrator) - Beginning particle settlement process.\n");
1423 PetscInt local_migration_count = 0;
1424 PetscInt migrationListCapacity = 0;
1425 PetscInt nlocal_before;
1426 PetscInt64 *pids_before_snapshot = NULL;
1427 PetscInt local_lost_count = 0;
1429 ierr = DMSwarmGetLocalSize(user->
swarm, &nlocal_before); CHKERRQ(ierr);
1433 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[Rank %d] Pass %d begins with %d local particles.\n", rank, passes, nlocal_before);
1437 if (nlocal_before > 0) {
1439 PetscReal *pos_p, *weights_p, *vel_p;
1440 PetscInt *cell_p, *status_p;
1453 for (PetscInt p_idx = 0; p_idx < nlocal_before; p_idx++) {
1458 "Local Particle idx=%d, PID=%ld, status=%s, cell=(%d, %d, %d)\n",
1467 LOG_ALLOW(
LOCAL,
LOG_VERBOSE,
" [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]);
1476 ierr =
UnpackSwarmFields(p_idx, pid_p, weights_p, pos_p, cell_p, vel_p, status_p,NULL,NULL,NULL,¤t_particle); CHKERRQ(ierr);
1485 if (current_particle.
cell[0] >= 0) {
1528 PetscMPIInt guessed_owner_rank = MPI_PROC_NULL;
1532 if (guessed_owner_rank != MPI_PROC_NULL && guessed_owner_rank != rank) {
1534 LOG_ALLOW(
LOCAL,
LOG_VERBOSE,
"[PID %ld] Guess SUCCESS: Found migration target Rank %d. Finalizing.\n", current_particle.
PID, guessed_owner_rank);
1543 if (guessed_owner_rank == rank) {
1544 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"[PID %ld] Guess determined particle is local. Proceeding to robust walk to find cell.\n", current_particle.
PID);
1546 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[PID %ld] Guess FAILED to find an owner. Proceeding to robust walk for definitive search.\n", current_particle.
PID);
1555 ierr =
UpdateSwarmFields(p_idx, ¤t_particle, pos_p, vel_p, weights_p, cell_p, status_p,NULL,NULL,NULL); CHKERRQ(ierr);
1559 }
else if (final_status ==
LOST) {
1578 LOG_ALLOW(
LOCAL,
LOG_INFO,
"[Rank %d] Pass %d: Identified %d particles to migrate out.\n", rank, passes, local_migration_count);
1583 ierr = MPI_Allreduce(&local_migration_count, &global_migrations_this_pass, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRQ(ierr);
1585 total_migrated_this_timestep += global_migrations_this_pass;
1587 if(global_migrations_this_pass > 0 ){
1589 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Pass %d: Migrating %d particles globally.\n", passes, global_migrations_this_pass);
1591 ierr =
SetMigrationRanks(user, migrationList, local_migration_count); CHKERRQ(ierr);
1601 ierr = PetscFree(pids_before_snapshot);
1602 ierr = PetscFree(migrationList);
1604 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"End of pass %d. Total particles migrated globally: %d.\n", passes, global_migrations_this_pass);
1606 }
while (global_migrations_this_pass > 0 && passes < MAX_MIGRATION_PASSES);
1609 if (passes >= MAX_MIGRATION_PASSES) {
1610 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);
1621 PetscFunctionReturn(0);
PetscErrorCode UnpackSwarmFields(PetscInt i, const PetscInt64 *PIDs, const PetscReal *weights, const PetscReal *positions, const PetscInt *cellIndices, PetscReal *velocities, PetscInt *LocStatus, PetscReal *diffusivity, Cmpnts *diffusivitygradient, PetscReal *psi, Particle *particle)
Initializes a Particle struct with data from DMSwarm fields.
PetscErrorCode UpdateSwarmFields(PetscInt i, const Particle *particle, PetscReal *positions, PetscReal *velocities, PetscReal *weights, PetscInt *cellIndices, PetscInt *status, PetscReal *diffusivity, Cmpnts *diffusivitygradient, PetscReal *psi)
Updates DMSwarm data arrays from a Particle struct.