148 UserCtx *user, DMDALocalInfo *info,
149 PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode,
150 PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr,
151 PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out,
152 PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out,
153 PetscBool *can_place_in_volume_out)
155 PetscErrorCode ierr = 0;
157 PetscInt local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k;
158 PetscMPIInt rank_for_logging;
160 PetscFunctionBeginUser;
164 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank_for_logging); CHKERRQ(ierr);
166 *can_place_in_volume_out = PETSC_FALSE;
169 *xi_metric_logic_out = 0.5; *eta_metric_logic_out = 0.5; *zta_metric_logic_out = 0.5;
170 *ci_metric_lnode_out = xs_gnode; *cj_metric_lnode_out = ys_gnode; *ck_metric_lnode_out = zs_gnode;
175 PetscInt num_owned_cells_i = (info->mx > 1) ? info->mx - 1 : 0;
176 PetscInt num_owned_cells_j = (info->my > 1) ? info->my - 1 : 0;
177 PetscInt num_owned_cells_k = (info->mz > 1) ? info->mz - 1 : 0;
179 if (num_owned_cells_i > 0 && num_owned_cells_j > 0 && num_owned_cells_k > 0) {
180 *can_place_in_volume_out = PETSC_TRUE;
186 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, &r_val); CHKERRQ(ierr);
187 local_owned_cell_idx_i = (PetscInt)(r_val * num_owned_cells_i);
189 local_owned_cell_idx_i = PetscMin(PetscMax(0, local_owned_cell_idx_i), num_owned_cells_i - 1);
190 *ci_metric_lnode_out = xs_gnode + local_owned_cell_idx_i;
193 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, &r_val); CHKERRQ(ierr);
194 local_owned_cell_idx_j = (PetscInt)(r_val * num_owned_cells_j);
195 local_owned_cell_idx_j = PetscMin(PetscMax(0, local_owned_cell_idx_j), num_owned_cells_j - 1);
196 *cj_metric_lnode_out = ys_gnode + local_owned_cell_idx_j;
199 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, &r_val); CHKERRQ(ierr);
200 local_owned_cell_idx_k = (PetscInt)(r_val * num_owned_cells_k);
201 local_owned_cell_idx_k = PetscMin(PetscMax(0, local_owned_cell_idx_k), num_owned_cells_k - 1);
202 *ck_metric_lnode_out = zs_gnode + local_owned_cell_idx_k;
204 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"DVP - Rank %d: Selected Cell (Owned Idx: %d,%d,%d -> LNodeStart: %d,%d,%d). OwnedCells(i,j,k): (%d,%d,%d). GhostNodeStarts(xs,ys,zs): (%d,%d,%d) \n",
205 rank_for_logging, local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k,
206 *ci_metric_lnode_out, *cj_metric_lnode_out, *ck_metric_lnode_out,
207 num_owned_cells_i, num_owned_cells_j, num_owned_cells_k,
208 xs_gnode, ys_gnode, zs_gnode);
212 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, xi_metric_logic_out); CHKERRQ(ierr);
213 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, eta_metric_logic_out); CHKERRQ(ierr);
214 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, zta_metric_logic_out); CHKERRQ(ierr);
217 *xi_metric_logic_out = PetscMin(*xi_metric_logic_out, 1.0 - 1.0e-7);
218 *eta_metric_logic_out = PetscMin(*eta_metric_logic_out, 1.0 - 1.0e-7);
219 *zta_metric_logic_out = PetscMin(*zta_metric_logic_out, 1.0 - 1.0e-7);
221 *xi_metric_logic_out = PetscMax(*xi_metric_logic_out, 0.0);
222 *eta_metric_logic_out = PetscMax(*eta_metric_logic_out, 0.0);
223 *zta_metric_logic_out = PetscMax(*zta_metric_logic_out, 0.0);
229 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"DVP - Rank %d: Cannot place particle volumetrically. Rank has zero owned cells in at least one dimension (owned cells i,j,k: %d,%d,%d).\n",
230 rank_for_logging, num_owned_cells_i, num_owned_cells_j, num_owned_cells_k);
234 PetscFunctionReturn(0);
267 PetscInt particlesPerProcess,
268 PetscRandom *rand_logic_i,
269 PetscRandom *rand_logic_j,
270 PetscRandom *rand_logic_k,
274 DM swarm = user->
swarm;
275 PetscReal *positions_field = NULL;
276 PetscInt64 *particleIDs = NULL;
277 PetscInt *cellIDs_petsc = NULL;
278 PetscInt *status_field = NULL;
279 PetscMPIInt rank,size;
280 const Cmpnts ***coor_nodes_local_array;
283 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank;
284 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global;
287 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
289 PetscFunctionBeginUser;
296 if (!user || !rand_logic_i || !rand_logic_j || !rand_logic_k) {
297 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null user or RNG pointer.");
299 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
300 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
303 ierr = DMGetCoordinatesLocal(user->
da, &Coor_local); CHKERRQ(ierr);
304 if (!Coor_local) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB,
"DMGetCoordinatesLocal for user->da returned NULL Coor_local.");
305 ierr = DMDAVecGetArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
306 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
307 ierr = DMDAGetGhostCorners(user->
da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
308 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);
311 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
313 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
314 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
315 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
322 ierr =
CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
323 if (can_this_rank_service_inlet) {
331 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
332 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
333 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs_petsc); CHKERRQ(ierr);
334 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status",NULL,NULL,(
void**)&status_field); CHKERRQ(ierr);
337 PetscInt particles_per_rank_ideal = simCtx->
np / size;
338 PetscInt remainder_particles = simCtx->
np % size;
339 PetscInt base_pid_for_rank = rank * particles_per_rank_ideal + PetscMin(rank, remainder_particles);
343 for (PetscInt p = 0; p < particlesPerProcess; p++) {
345 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
346 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
347 Cmpnts phys_coords = {0.0, 0.0, 0.0};
348 PetscBool particle_placed_by_this_rank = PETSC_FALSE;
351 if (can_this_rank_service_inlet) {
353 IM_nodes_global, JM_nodes_global, KM_nodes_global,
354 rand_logic_i, rand_logic_j, rand_logic_k,
355 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
356 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
358 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
359 xi_metric_logic, eta_metric_logic, zta_metric_logic,
360 &phys_coords); CHKERRQ(ierr);
361 particle_placed_by_this_rank = PETSC_TRUE;
367 particle_placed_by_this_rank = PETSC_FALSE;
370 if(can_this_rank_service_inlet) {
371 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
373 IM_cells_global, JM_cells_global, KM_cells_global,
375 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
376 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
377 &particle_placed_by_this_rank); CHKERRQ(ierr);
380 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
381 xi_metric_logic, eta_metric_logic, zta_metric_logic,
382 &phys_coords); CHKERRQ(ierr);
389 particle_placed_by_this_rank = PETSC_FALSE;
392 PetscBool can_place_volumetrically;
394 rand_logic_i, rand_logic_j, rand_logic_k,
395 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
396 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
397 &can_place_volumetrically); CHKERRQ(ierr);
398 if(can_place_volumetrically){
400 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
401 xi_metric_logic, eta_metric_logic, zta_metric_logic,
402 &phys_coords); CHKERRQ(ierr);
403 particle_placed_by_this_rank = PETSC_TRUE;
406 "Rank %d: PID %lld (idx %ld) (Volumetric Mode %d) - DetermineVolumetric... returned false. Default Phys: (%.2f,%.2f,%.2f).\n",
407 rank, (
long long)(base_pid_for_rank + p), (
long)p, simCtx->
ParticleInitialization, phys_coords.
x, phys_coords.
y, phys_coords.
z);
410 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Unknown ParticleInitialization mode %d.", simCtx->
ParticleInitialization);
414 positions_field[3*p+0] = phys_coords.
x;
415 positions_field[3*p+1] = phys_coords.
y;
416 positions_field[3*p+2] = phys_coords.
z;
418 particleIDs[p] = (PetscInt64)base_pid_for_rank + p;
419 cellIDs_petsc[3*p+0] = -1; cellIDs_petsc[3*p+1] = -1; cellIDs_petsc[3*p+2] = -1;
423 if (particle_placed_by_this_rank) {
425 "Rank %d: PID %lld (idx %ld) PLACED. Mode %s. Embedded Cell:(%d,%d,%d). Logical Coords: (%.2e,%.2f,%.2f).\n Final Coords: (%.6f,%.6f,%.6f).\n",
427 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
428 xi_metric_logic, eta_metric_logic, zta_metric_logic,
429 phys_coords.
x, phys_coords.
y, phys_coords.
z);
433 "Rank %d: PID %lld (idx %ld) Mode %s NOT placed by this rank's logic. Default Coor: (%.2f,%.2f,%.2f). Relies on migration.\n",
435 phys_coords.
x, phys_coords.
y, phys_coords.
z);
440 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
441 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
442 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs_petsc); CHKERRQ(ierr);
443 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_field); CHKERRQ(ierr);
444 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
447 rank, particlesPerProcess);
451 PetscFunctionReturn(0);
PetscErrorCode FinalizeSwarmSetup(PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Finalizes the swarm setup by destroying random generators and logging completion.
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.
static PetscErrorCode DetermineVolumetricInitializationParameters(UserCtx *user, DMDALocalInfo *info, PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode, 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, PetscBool *can_place_in_volume_out)
Determines cell selection and intra-cell logical coordinates for volumetric initialization (Mode 1).
PetscErrorCode AssignInitialPropertiesToSwarm(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_phys_x, PetscRandom *rand_phys_y, PetscRandom *rand_phys_z, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initializes all particle properties in the swarm.