5#define INTERPOLATION_DISTANCE_TOLERANCE 1.0e-14
8#define __FUNCT__ "InitializeSwarm"
18 PetscFunctionBeginUser;
21 ierr = DMCreate(PETSC_COMM_WORLD, &user->
swarm); CHKERRQ(ierr);
22 ierr = DMSetType(user->
swarm, DMSWARM); CHKERRQ(ierr);
23 ierr = DMSetDimension(user->
swarm, 3); CHKERRQ(ierr);
24 ierr = DMSwarmSetType(user->
swarm, DMSWARM_BASIC); CHKERRQ(ierr);
28 PetscFunctionReturn(0);
32#define __FUNCT__ "RegisterSwarmField"
38PetscErrorCode
RegisterSwarmField(DM swarm,
const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
41 PetscFunctionBeginUser;
43 ierr = DMSwarmRegisterPetscDatatypeField(swarm, fieldName, fieldDim, dtype); CHKERRQ(ierr);
46 fieldName, fieldDim, PetscDataTypes[dtype]);
48 PetscFunctionReturn(0);
52#define __FUNCT__ "RegisterParticleFields"
64 PetscFunctionBeginUser;
89 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Registered field 'DMSwarm_location_status' - Status of Location of Particle(located,lost etc).\n");
92 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
95 PetscFunctionReturn(0);
99#define __FUNCT__ "DetermineVolumetricInitializationParameters"
105 UserCtx *user, DMDALocalInfo *info,
106 PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode,
107 PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr,
108 PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out,
109 PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out,
110 PetscBool *can_place_in_volume_out)
112 PetscErrorCode ierr = 0;
115 PetscInt local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k;
116 PetscMPIInt rank_for_logging;
118 PetscFunctionBeginUser;
122 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank_for_logging); CHKERRQ(ierr);
124 *can_place_in_volume_out = PETSC_FALSE;
127 *xi_metric_logic_out = 0.5; *eta_metric_logic_out = 0.5; *zta_metric_logic_out = 0.5;
128 *ci_metric_lnode_out = xs_gnode; *cj_metric_lnode_out = ys_gnode; *ck_metric_lnode_out = zs_gnode;
132 PetscInt owned_start_cell_i, num_owned_cells_on_rank_i;
133 PetscInt owned_start_cell_j, num_owned_cells_on_rank_j;
134 PetscInt owned_start_cell_k, num_owned_cells_on_rank_k;
136 ierr =
GetOwnedCellRange(info, 0, &owned_start_cell_i, &num_owned_cells_on_rank_i); CHKERRQ(ierr);
137 ierr =
GetOwnedCellRange(info, 1, &owned_start_cell_j, &num_owned_cells_on_rank_j); CHKERRQ(ierr);
138 ierr =
GetOwnedCellRange(info, 2, &owned_start_cell_k, &num_owned_cells_on_rank_k); CHKERRQ(ierr);
140 if (num_owned_cells_on_rank_i > 0 && num_owned_cells_on_rank_j > 0 && num_owned_cells_on_rank_k > 0) {
141 *can_place_in_volume_out = PETSC_TRUE;
147 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, &r_val); CHKERRQ(ierr);
148 local_owned_cell_idx_i = (PetscInt)(r_val * num_owned_cells_on_rank_i);
150 local_owned_cell_idx_i = PetscMin(PetscMax(0, local_owned_cell_idx_i), num_owned_cells_on_rank_i - 1);
151 *ci_metric_lnode_out = xs_gnode + local_owned_cell_idx_i;
154 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, &r_val); CHKERRQ(ierr);
155 local_owned_cell_idx_j = (PetscInt)(r_val * num_owned_cells_on_rank_j);
156 local_owned_cell_idx_j = PetscMin(PetscMax(0, local_owned_cell_idx_j), num_owned_cells_on_rank_j - 1);
157 *cj_metric_lnode_out = ys_gnode + local_owned_cell_idx_j;
160 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, &r_val); CHKERRQ(ierr);
161 local_owned_cell_idx_k = (PetscInt)(r_val * num_owned_cells_on_rank_k);
162 local_owned_cell_idx_k = PetscMin(PetscMax(0, local_owned_cell_idx_k), num_owned_cells_on_rank_k - 1);
163 *ck_metric_lnode_out = zs_gnode + local_owned_cell_idx_k;
165 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"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",
166 rank_for_logging, local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k,
167 *ci_metric_lnode_out, *cj_metric_lnode_out, *ck_metric_lnode_out,
168 num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k,
169 xs_gnode, ys_gnode, zs_gnode);
173 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, xi_metric_logic_out); CHKERRQ(ierr);
174 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, eta_metric_logic_out); CHKERRQ(ierr);
175 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, zta_metric_logic_out); CHKERRQ(ierr);
178 *xi_metric_logic_out = PetscMin(*xi_metric_logic_out, 1.0 - 1.0e-7);
179 *eta_metric_logic_out = PetscMin(*eta_metric_logic_out, 1.0 - 1.0e-7);
180 *zta_metric_logic_out = PetscMin(*zta_metric_logic_out, 1.0 - 1.0e-7);
182 *xi_metric_logic_out = PetscMax(*xi_metric_logic_out, 0.0);
183 *eta_metric_logic_out = PetscMax(*eta_metric_logic_out, 0.0);
184 *zta_metric_logic_out = PetscMax(*zta_metric_logic_out, 0.0);
190 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"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",
191 rank_for_logging, num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k);
195 PetscFunctionReturn(0);
199#define __FUNCT__ "InitializeParticleBasicProperties"
206 PetscInt particlesPerProcess,
207 PetscRandom *rand_logic_i,
208 PetscRandom *rand_logic_j,
209 PetscRandom *rand_logic_k,
214 DM swarm = user->
swarm;
215 PetscReal *positions_field = NULL;
216 PetscInt64 *particleIDs = NULL;
217 PetscInt *cellIDs_petsc = NULL;
218 PetscInt *status_field = NULL;
219 PetscMPIInt rank,size;
220 const Cmpnts ***coor_nodes_local_array;
223 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank;
224 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global;
227 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
229 PetscFunctionBeginUser;
236 if (!user || !rand_logic_i || !rand_logic_j || !rand_logic_k) {
237 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null user or RNG pointer.");
239 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
240 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
243 ierr = DMGetCoordinatesLocal(user->
da, &Coor_local); CHKERRQ(ierr);
244 if (!Coor_local) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB,
"DMGetCoordinatesLocal for user->da returned NULL Coor_local.");
245 ierr = DMDAVecGetArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
246 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
247 ierr = DMDAGetCorners(user->
da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
248 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);
251 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
253 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
254 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
255 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
263 ierr =
CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
264 if (can_this_rank_service_inlet) {
272 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
273 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
274 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs_petsc); CHKERRQ(ierr);
275 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status",NULL,NULL,(
void**)&status_field); CHKERRQ(ierr);
278 PetscInt particles_per_rank_ideal = simCtx->
np / size;
279 PetscInt remainder_particles = simCtx->
np % size;
280 PetscInt base_pid_for_rank = rank * particles_per_rank_ideal + PetscMin(rank, remainder_particles);
284 for (PetscInt p = 0; p < particlesPerProcess; p++) {
286 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
287 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
288 Cmpnts phys_coords = {0.0, 0.0, 0.0};
289 PetscBool particle_placed_by_this_rank = PETSC_FALSE;
292 if (can_this_rank_service_inlet) {
294 IM_nodes_global, JM_nodes_global, KM_nodes_global,
295 rand_logic_i, rand_logic_j, rand_logic_k,
296 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
297 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
299 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
300 xi_metric_logic, eta_metric_logic, zta_metric_logic,
301 &phys_coords); CHKERRQ(ierr);
302 particle_placed_by_this_rank = PETSC_TRUE;
308 particle_placed_by_this_rank = PETSC_FALSE;
311 if(can_this_rank_service_inlet) {
312 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
314 IM_cells_global, JM_cells_global, KM_cells_global,
316 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
317 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
318 &particle_placed_by_this_rank); CHKERRQ(ierr);
319 if(particle_placed_by_this_rank){
321 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
322 xi_metric_logic, eta_metric_logic, zta_metric_logic,
323 &phys_coords); CHKERRQ(ierr);
335 particle_placed_by_this_rank = PETSC_FALSE;
338 PetscBool can_place_volumetrically = PETSC_FALSE;
340 rand_logic_i, rand_logic_j, rand_logic_k,
341 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
342 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
343 &can_place_volumetrically); CHKERRQ(ierr);
344 if(can_place_volumetrically){
346 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
347 xi_metric_logic, eta_metric_logic, zta_metric_logic,
348 &phys_coords); CHKERRQ(ierr);
349 particle_placed_by_this_rank = PETSC_TRUE;
352 "Rank %d: PID %lld (idx %ld) (Volumetric Mode) - DetermineVolumetric... returned false. Default Phys: (%.2f,%.2f,%.2f).\n",
353 rank, (
long long)(base_pid_for_rank + p), (
long)p, phys_coords.
x, phys_coords.
y, phys_coords.
z);
358 phys_coords.
x = simCtx->
psrc_x;
359 phys_coords.
y = simCtx->
psrc_y;
360 phys_coords.
z = simCtx->
psrc_z;
361 particle_placed_by_this_rank = PETSC_TRUE;
363 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Unknown ParticleInitialization mode %d.", simCtx->
ParticleInitialization);
367 positions_field[3*p+0] = phys_coords.
x;
368 positions_field[3*p+1] = phys_coords.
y;
369 positions_field[3*p+2] = phys_coords.
z;
371 particleIDs[p] = (PetscInt64)base_pid_for_rank + p;
372 cellIDs_petsc[3*p+0] = -1; cellIDs_petsc[3*p+1] = -1; cellIDs_petsc[3*p+2] = -1;
376 if (particle_placed_by_this_rank) {
378 "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",
380 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
381 xi_metric_logic, eta_metric_logic, zta_metric_logic,
382 phys_coords.
x, phys_coords.
y, phys_coords.
z);
386 "Rank %d: PID %lld (idx %ld) Mode %s NOT placed by this rank's logic. Default Coor: (%.2f,%.2f,%.2f). Relies on migration.\n",
388 phys_coords.
x, phys_coords.
y, phys_coords.
z);
393 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&positions_field); CHKERRQ(ierr);
394 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&particleIDs); CHKERRQ(ierr);
395 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs_petsc); CHKERRQ(ierr);
396 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status_field); CHKERRQ(ierr);
397 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
400 rank, particlesPerProcess);
404 PetscFunctionReturn(0);
408#define __FUNCT__ "InitializeSwarmFieldValue"
415 PetscFunctionBeginUser;
419 if (strcmp(fieldName,
"velocity") == 0) {
421 for (PetscInt d = 0; d < fieldDim; d++) {
422 fieldData[fieldDim * p + d] = 0.0;
424 }
else if (strcmp(fieldName,
"Diffusivity") == 0) {
426 for (PetscInt d = 0; d < fieldDim; d++) {
427 fieldData[fieldDim * p + d] = 1.0;
429 }
else if (strcmp(fieldName,
"DiffusivityGradient") == 0) {
431 for (PetscInt d = 0; d < fieldDim; d++) {
432 fieldData[fieldDim * p + d] = 1.0;
434 }
else if (strcmp(fieldName,
"Psi") == 0) {
435 for (PetscInt d = 0; d < fieldDim; d++) {
436 fieldData[fieldDim * p + d] = 0.0;
440 for (PetscInt d = 0; d < fieldDim; d++) {
441 fieldData[fieldDim * p + d] = 0.0;
446 PetscFunctionReturn(0);
451#define __FUNCT__ "AssignInitialFieldToSwarm"
459 DM swarm = user->
swarm;
460 PetscReal *fieldData = NULL;
463 PetscFunctionBeginUser;
468 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
472 ierr = DMSwarmGetField(swarm, fieldName, NULL, NULL, (
void**)&fieldData); CHKERRQ(ierr);
476 for (PetscInt p = 0; p < nLocal; p++) {
478 PetscReal disp_data[fieldDim];
480 for (PetscInt d = 0; d < fieldDim; d++) {
481 disp_data[d] = fieldData[fieldDim* p + d];
483 LOG_LOOP_ALLOW(
LOCAL,
LOG_VERBOSE,p, 100,
" Particle %d: %s[%d] = [%.6f, ...,%.6f].\n", p,fieldName,fieldDim,disp_data[0],disp_data[fieldDim-1]);
487 ierr = DMSwarmRestoreField(swarm, fieldName, NULL, NULL, (
void**)&fieldData); CHKERRQ(ierr);
493 PetscFunctionReturn(0);
497#define __FUNCT__ "AssignInitialPropertiesToSwarm"
504 PetscInt particlesPerProcess,
505 PetscRandom *rand_phys_x,
506 PetscRandom *rand_phys_y,
507 PetscRandom *rand_phys_z,
508 PetscRandom *rand_logic_i,
509 PetscRandom *rand_logic_j,
510 PetscRandom *rand_logic_k,
514 PetscFunctionBeginUser;
521 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
524 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null input detected.");
534 LOG_ALLOW(
GLOBAL,
LOG_ERROR,
"Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
535 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
547 rand_logic_i, rand_logic_j, rand_logic_k,
583 PetscFunctionReturn(0);
588#define __FUNCT__ "DistributeParticles"
595PetscErrorCode
DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt* particlesPerProcess, PetscInt* remainder) {
597 PetscFunctionBeginUser;
601 *particlesPerProcess = numParticles / size;
602 *remainder = numParticles % size;
605 if (rank < *remainder) {
606 *particlesPerProcess += 1;
613 PetscFunctionReturn(0);
618#define __FUNCT__ "FinalizeSwarmSetup"
625PetscErrorCode
FinalizeSwarmSetup(PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k) {
627 PetscFunctionBeginUser;
631 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
632 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
633 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
635 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
636 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
637 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
642 PetscFunctionReturn(0);
646#define __FUNCT__ "CreateParticleSwarm"
654 PetscMPIInt rank, size;
655 PetscInt remainder = 0;
657 PetscFunctionBeginUser;
660 if (numParticles <= 0) {
662 return PETSC_ERR_ARG_OUTOFRANGE;
666 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
667 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
675 ierr =
DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
681 ierr = DMSwarmSetCellDM(user->
swarm, user->
da); CHKERRQ(ierr);
693 ierr = DMSwarmSetLocalSizes(user->
swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
699 ierr = DMView(user->
swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
705 PetscFunctionReturn(0);
714#define __FUNCT__ "UnpackSwarmFields"
723 const PetscReal *positions,
const PetscInt *cellIndices,
724 PetscReal *velocities,PetscInt *LocStatus,PetscReal *diffusivity,
Cmpnts *diffusivitygradient, PetscReal *psi,
Particle *particle) {
725 PetscFunctionBeginUser;
732 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
734 if (particle == NULL) {
735 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output Particle pointer is NULL. \n");
743 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input PIDs pointer is NULL.\n");
745 particle->
PID = PIDs[i];
753 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[Rank %d]Particle [%d] weights pointer is NULL. Defaulting weights to (1.0, 1.0, 1.0).\n", rank,i);
755 particle->
weights.
x = weights[3 * i];
756 particle->
weights.
y = weights[3 * i + 1];
757 particle->
weights.
z = weights[3 * i + 2];
762 if(positions == NULL){
763 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input positions pointer is NULL.\n");
765 particle->
loc.
x = positions[3 * i];
766 particle->
loc.
y = positions[3 * i + 1];
767 particle->
loc.
z = positions[3 * i + 2];
769 rank,i, particle->
loc.
x, particle->
loc.
y, particle->
loc.
z);
772 if(velocities == NULL){
773 particle->
vel.
x = 0.0;
774 particle->
vel.
y = 0.0;
775 particle->
vel.
z = 0.0;
776 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[Rank %d]Particle [%d] velocities pointer is NULL. Defaulting velocities to (0.0, 0.0, 0.0).\n", rank,i);
778 particle->
vel.
x = velocities[3 * i];
779 particle->
vel.
y = velocities[3 * i + 1];
780 particle->
vel.
z = velocities[3 * i + 2];
785 if(diffusivity == NULL){
793 if(diffusivitygradient == NULL){
797 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[Rank %d]Particle [%d] diffusivity gradient pointer is NULL. Defaulting to (0.0, 0.0, 0.0).\n", rank,i);
809 particle->
psi = psi[i];
814 if(cellIndices == NULL){
815 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input cellIndices pointer is NULL.\n");
817 particle->
cell[0] = cellIndices[3 * i];
818 particle->
cell[1] = cellIndices[3 * i + 1];
819 particle->
cell[2] = cellIndices[3 * i + 2];
822 if(LocStatus == NULL){
823 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input LocStatus pointer is NULL.\n");
839 PetscFunctionReturn(0);
843#define __FUNCT__ "UpdateSwarmFields"
849 PetscReal *positions,
850 PetscReal *velocities,
852 PetscInt *cellIndices,
854 PetscReal *diffusivity,
855 Cmpnts *diffusivitygradient,
858 PetscFunctionBeginUser;
862 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input Particle pointer is NULL.\n");
867 positions[3 * i + 0] = particle->
loc.
x;
868 positions[3 * i + 1] = particle->
loc.
y;
869 positions[3 * i + 2] = particle->
loc.
z;
874 velocities[3 * i + 0] = particle->
vel.
x;
875 velocities[3 * i + 1] = particle->
vel.
y;
876 velocities[3 * i + 2] = particle->
vel.
z;
881 weights[3 * i + 0] = particle->
weights.
x;
882 weights[3 * i + 1] = particle->
weights.
y;
883 weights[3 * i + 2] = particle->
weights.
z;
888 cellIndices[3 * i + 0] = particle->
cell[0];
889 cellIndices[3 * i + 1] = particle->
cell[1];
890 cellIndices[3 * i + 2] = particle->
cell[2];
903 if(diffusivitygradient){
910 psi[i] = particle->
psi;
916 PetscFunctionReturn(0);
920#define __FUNCT__ "IsParticleInsideBoundingBox"
927 PetscFunctionBeginUser;
951 min_coords.
x, min_coords.
y, min_coords.
z, max_coords.
x, max_coords.
y, max_coords.
z);
954 if ((loc.
x >= min_coords.
x && loc.
x <= max_coords.
x) &&
955 (loc.
y >= min_coords.
y && loc.
y <= max_coords.
y) &&
956 (loc.
z >= min_coords.
z && loc.
z <= max_coords.
z)) {
971#define __FUNCT__ "UpdateParticleWeights"
978 PetscFunctionBeginUser;
982 if (!d || !particle) {
983 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
984 "Null pointer argument (d or particle).");
992 "face distance d[%d] = %f <= %f; "
993 "clamping to 1e-14 to avoid zero/negative.\n",
1001 "Calculating weights with distances: "
1002 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
1012 "Updated particle weights: x=%f, y=%f, z=%f.\n",
1017 PetscFunctionReturn(0);
1041#define __FUNCT__ "InitializeParticleSwarm"
1051 PetscErrorCode ierr;
1052 PetscInt particlesPerProcess = 0;
1055 PetscFunctionBeginUser;
1067 PetscBool should_initialize_new_particles = PETSC_FALSE;
1069 should_initialize_new_particles = PETSC_TRUE;
1072 should_initialize_new_particles = PETSC_TRUE;
1076 should_initialize_new_particles = PETSC_TRUE;
1082 if (should_initialize_new_particles) {
1085 PetscRandom randx, randy, randz;
1086 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1091 ierr =
FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1109 PetscFunctionReturn(0);
PetscErrorCode GetRandomCellAndLogicalCoordsOnInletFace(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 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 GetDeterministicFaceGridLocation(UserCtx *user, const DMDALocalInfo *info, PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank, PetscInt IM_cells_global, PetscInt JM_cells_global, PetscInt KM_cells_global, PetscInt64 particle_global_id, 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 *placement_successful_out)
Places particles in a deterministic grid/raster pattern on a specified domain face.
PetscErrorCode MetricLogicalToPhysical(UserCtx *user, const Cmpnts ***X, PetscInt i, PetscInt j, PetscInt k, PetscReal xi, PetscReal eta, PetscReal zta, Cmpnts *Xp)
Public interface for MetricLogicalToPhysical().
PetscErrorCode PreCheckAndResizeSwarm(UserCtx *user, PetscInt ti, const char *ext)
Checks particle count in the reference file and resizes the swarm if needed.
PetscErrorCode UpdateParticleWeights(PetscReal *d, Particle *particle)
Internal helper implementation: UpdateParticleWeights().
PetscErrorCode CreateParticleSwarm(UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
Internal helper implementation: CreateParticleSwarm().
PetscErrorCode FinalizeSwarmSetup(PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Implementation of FinalizeSwarmSetup().
PetscErrorCode DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
Implementation of DistributeParticles().
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, const char *fieldName, PetscInt fieldDim)
Internal helper implementation: AssignInitialFieldToSwarm().
#define INTERPOLATION_DISTANCE_TOLERANCE
static PetscErrorCode InitializeSwarmFieldValue(const char *fieldName, PetscInt p, PetscInt fieldDim, PetscReal *fieldData)
Internal helper implementation: InitializeSwarmFieldValue().
PetscBool IsParticleInsideBoundingBox(const BoundingBox *bbox, const Particle *particle)
Internal helper implementation: IsParticleInsideBoundingBox().
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Internal helper implementation: InitializeParticleBasicProperties().
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)
Implementation of UnpackSwarmFields().
PetscErrorCode InitializeSwarm(UserCtx *user)
Implementation of InitializeSwarm().
PetscErrorCode UpdateSwarmFields(PetscInt i, const Particle *particle, PetscReal *positions, PetscReal *velocities, PetscReal *weights, PetscInt *cellIndices, PetscInt *status, PetscReal *diffusivity, Cmpnts *diffusivitygradient, PetscReal *psi)
Internal helper implementation: UpdateSwarmFields().
PetscErrorCode InitializeParticleSwarm(SimCtx *simCtx)
Implementation of InitializeParticleSwarm().
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Internal helper implementation: RegisterSwarmField().
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)
Internal helper implementation: DetermineVolumetricInitializationParameters().
PetscErrorCode RegisterParticleFields(DM swarm)
Implementation of RegisterParticleFields().
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)
Internal helper implementation: AssignInitialPropertiesToSwarm().
Header file for Particle Swarm management functions.
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Reads multiple fields (positions, velocity, CellID, and weight) into a DMSwarm.
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt,...)
Logs a message inside a loop, but only every interval iterations.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
const char * BCFaceToString(BCFace face)
Helper function to convert BCFace enum to a string representation.
#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.
@ 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.
@ 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).
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
PetscErrorCode GetOwnedCellRange(const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
Determines the global starting index and number of CELLS owned by the current processor in a specifie...
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
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).
PetscBool inletFaceDefined
BCFace identifiedInletBCFace
SimCtx * simCtx
Back-pointer to the master simulation context.
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
@ PARTICLE_INIT_POINT_SOURCE
All particles at a fixed (psrc_x,psrc_y,psrc_z) — for validation.
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
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 diffusivitygradient
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
PetscMPIInt destination_rank
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
ParticleLocationStatus location_status
char particleRestartMode[16]
ParticleInitializationType ParticleInitialization
@ EXEC_MODE_POSTPROCESSOR
PetscInt LoggingFrequency
BCFace
Identifies the six logical faces of a structured computational block.
Defines a 3D axis-aligned bounding box.
A 3D point or vector with PetscScalar components.
Defines a particle's core properties for Lagrangian tracking.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.