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;
77 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
80 PetscFunctionReturn(0);
84#define __FUNCT__ "DetermineVolumetricInitializationParameters"
89 UserCtx *user, DMDALocalInfo *info,
90 PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode,
91 PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr,
92 PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out,
93 PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out,
94 PetscBool *can_place_in_volume_out)
96 PetscErrorCode ierr = 0;
99 PetscInt local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k;
100 PetscMPIInt rank_for_logging;
102 PetscFunctionBeginUser;
106 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank_for_logging); CHKERRQ(ierr);
108 *can_place_in_volume_out = PETSC_FALSE;
111 *xi_metric_logic_out = 0.5; *eta_metric_logic_out = 0.5; *zta_metric_logic_out = 0.5;
112 *ci_metric_lnode_out = xs_gnode; *cj_metric_lnode_out = ys_gnode; *ck_metric_lnode_out = zs_gnode;
116 PetscInt owned_start_cell_i, num_owned_cells_on_rank_i;
117 PetscInt owned_start_cell_j, num_owned_cells_on_rank_j;
118 PetscInt owned_start_cell_k, num_owned_cells_on_rank_k;
120 ierr =
GetOwnedCellRange(info, 0, &owned_start_cell_i, &num_owned_cells_on_rank_i); CHKERRQ(ierr);
121 ierr =
GetOwnedCellRange(info, 1, &owned_start_cell_j, &num_owned_cells_on_rank_j); CHKERRQ(ierr);
122 ierr =
GetOwnedCellRange(info, 2, &owned_start_cell_k, &num_owned_cells_on_rank_k); CHKERRQ(ierr);
124 if (num_owned_cells_on_rank_i > 0 && num_owned_cells_on_rank_j > 0 && num_owned_cells_on_rank_k > 0) {
125 *can_place_in_volume_out = PETSC_TRUE;
131 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, &r_val); CHKERRQ(ierr);
132 local_owned_cell_idx_i = (PetscInt)(r_val * num_owned_cells_on_rank_i);
134 local_owned_cell_idx_i = PetscMin(PetscMax(0, local_owned_cell_idx_i), num_owned_cells_on_rank_i - 1);
135 *ci_metric_lnode_out = xs_gnode + local_owned_cell_idx_i;
138 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, &r_val); CHKERRQ(ierr);
139 local_owned_cell_idx_j = (PetscInt)(r_val * num_owned_cells_on_rank_j);
140 local_owned_cell_idx_j = PetscMin(PetscMax(0, local_owned_cell_idx_j), num_owned_cells_on_rank_j - 1);
141 *cj_metric_lnode_out = ys_gnode + local_owned_cell_idx_j;
144 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, &r_val); CHKERRQ(ierr);
145 local_owned_cell_idx_k = (PetscInt)(r_val * num_owned_cells_on_rank_k);
146 local_owned_cell_idx_k = PetscMin(PetscMax(0, local_owned_cell_idx_k), num_owned_cells_on_rank_k - 1);
147 *ck_metric_lnode_out = zs_gnode + local_owned_cell_idx_k;
149 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",
150 rank_for_logging, local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k,
151 *ci_metric_lnode_out, *cj_metric_lnode_out, *ck_metric_lnode_out,
152 num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k,
153 xs_gnode, ys_gnode, zs_gnode);
157 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, xi_metric_logic_out); CHKERRQ(ierr);
158 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, eta_metric_logic_out); CHKERRQ(ierr);
159 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, zta_metric_logic_out); CHKERRQ(ierr);
162 *xi_metric_logic_out = PetscMin(*xi_metric_logic_out, 1.0 - 1.0e-7);
163 *eta_metric_logic_out = PetscMin(*eta_metric_logic_out, 1.0 - 1.0e-7);
164 *zta_metric_logic_out = PetscMin(*zta_metric_logic_out, 1.0 - 1.0e-7);
166 *xi_metric_logic_out = PetscMax(*xi_metric_logic_out, 0.0);
167 *eta_metric_logic_out = PetscMax(*eta_metric_logic_out, 0.0);
168 *zta_metric_logic_out = PetscMax(*zta_metric_logic_out, 0.0);
174 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",
175 rank_for_logging, num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k);
179 PetscFunctionReturn(0);
183#define __FUNCT__ "InitializeParticleBasicProperties"
189 PetscInt particlesPerProcess,
190 PetscRandom *rand_logic_i,
191 PetscRandom *rand_logic_j,
192 PetscRandom *rand_logic_k,
197 DM swarm = user->
swarm;
198 PetscReal *positions_field = NULL;
199 PetscInt64 *particleIDs = NULL;
200 PetscInt *cellIDs_petsc = NULL;
201 PetscInt *status_field = NULL;
202 PetscMPIInt rank,size;
203 const Cmpnts ***coor_nodes_local_array;
206 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank;
207 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global;
210 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
212 PetscFunctionBeginUser;
219 if (!user || !rand_logic_i || !rand_logic_j || !rand_logic_k) {
220 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null user or RNG pointer.");
222 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
223 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
226 ierr = DMGetCoordinatesLocal(user->
da, &Coor_local); CHKERRQ(ierr);
227 if (!Coor_local) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB,
"DMGetCoordinatesLocal for user->da returned NULL Coor_local.");
228 ierr = DMDAVecGetArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
229 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
230 ierr = DMDAGetCorners(user->
da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
231 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);
234 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
236 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
237 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
238 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
246 ierr =
CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
247 if (can_this_rank_service_inlet) {
261 PetscInt particles_per_rank_ideal = simCtx->
np / size;
262 PetscInt remainder_particles = simCtx->
np % size;
263 PetscInt base_pid_for_rank = rank * particles_per_rank_ideal + PetscMin(rank, remainder_particles);
267 for (PetscInt p = 0; p < particlesPerProcess; p++) {
269 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
270 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
271 Cmpnts phys_coords = {0.0, 0.0, 0.0};
272 PetscBool particle_placed_by_this_rank = PETSC_FALSE;
275 if (can_this_rank_service_inlet) {
277 IM_nodes_global, JM_nodes_global, KM_nodes_global,
278 rand_logic_i, rand_logic_j, rand_logic_k,
279 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
280 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
282 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
283 xi_metric_logic, eta_metric_logic, zta_metric_logic,
284 &phys_coords); CHKERRQ(ierr);
285 particle_placed_by_this_rank = PETSC_TRUE;
291 particle_placed_by_this_rank = PETSC_FALSE;
294 if(can_this_rank_service_inlet) {
295 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
297 IM_cells_global, JM_cells_global, KM_cells_global,
299 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
300 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
301 &particle_placed_by_this_rank); CHKERRQ(ierr);
302 if(particle_placed_by_this_rank){
304 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
305 xi_metric_logic, eta_metric_logic, zta_metric_logic,
306 &phys_coords); CHKERRQ(ierr);
318 particle_placed_by_this_rank = PETSC_FALSE;
321 PetscBool can_place_volumetrically = PETSC_FALSE;
323 rand_logic_i, rand_logic_j, rand_logic_k,
324 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
325 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
326 &can_place_volumetrically); CHKERRQ(ierr);
327 if(can_place_volumetrically){
329 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
330 xi_metric_logic, eta_metric_logic, zta_metric_logic,
331 &phys_coords); CHKERRQ(ierr);
332 particle_placed_by_this_rank = PETSC_TRUE;
335 "Rank %d: PID %lld (idx %ld) (Volumetric Mode) - DetermineVolumetric... returned false. Default Phys: (%.2f,%.2f,%.2f).\n",
336 rank, (
long long)(base_pid_for_rank + p), (
long)p, phys_coords.
x, phys_coords.
y, phys_coords.
z);
341 phys_coords.
x = simCtx->
psrc_x;
342 phys_coords.
y = simCtx->
psrc_y;
343 phys_coords.
z = simCtx->
psrc_z;
344 particle_placed_by_this_rank = PETSC_TRUE;
346 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Unknown ParticleInitialization mode %d.", simCtx->
ParticleInitialization);
350 positions_field[3*p+0] = phys_coords.
x;
351 positions_field[3*p+1] = phys_coords.
y;
352 positions_field[3*p+2] = phys_coords.
z;
354 particleIDs[p] = (PetscInt64)base_pid_for_rank + p;
355 cellIDs_petsc[3*p+0] = -1; cellIDs_petsc[3*p+1] = -1; cellIDs_petsc[3*p+2] = -1;
359 if (particle_placed_by_this_rank) {
361 "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",
363 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
364 xi_metric_logic, eta_metric_logic, zta_metric_logic,
365 phys_coords.
x, phys_coords.
y, phys_coords.
z);
369 "Rank %d: PID %lld (idx %ld) Mode %s NOT placed by this rank's logic. Default Coor: (%.2f,%.2f,%.2f). Relies on migration.\n",
371 phys_coords.
x, phys_coords.
y, phys_coords.
z);
380 ierr = DMDAVecRestoreArrayRead(user->
fda, Coor_local, (
void*)&coor_nodes_local_array); CHKERRQ(ierr);
383 rank, particlesPerProcess);
387 PetscFunctionReturn(0);
391#define __FUNCT__ "InitializeSwarmFieldValue"
396 PetscInt p, PetscReal *fieldData)
398 PetscFunctionBeginUser;
402 PetscCheck(descriptor != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
403 "Particle field descriptor cannot be NULL during initialization.");
404 PetscCheck(fieldData != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
405 "Particle field data cannot be NULL during initialization.");
406 PetscCheck(descriptor->
data_type == PETSC_REAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
407 "Default initialization currently supports only PETSC_REAL particle fields; '%s' uses %s.",
410 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
411 "Particle field '%s' does not use catalog-default initialization.",
414 for (PetscInt d = 0; d < descriptor->
components; ++d) {
419 PetscFunctionReturn(0);
424#define __FUNCT__ "AssignInitialFieldToSwarm"
431 DM swarm = user->
swarm;
432 PetscReal *fieldData = NULL;
435 const char *fieldName = NULL;
437 PetscFunctionBeginUser;
445 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
449 ierr = DMSwarmGetField(swarm, fieldName, NULL, NULL, (
void**)&fieldData); CHKERRQ(ierr);
453 for (PetscInt p = 0; p < nLocal; p++) {
457 for (PetscInt d = 0; d < descriptor->
components; d++) {
458 disp_data[d] = fieldData[descriptor->
components * p + d];
460 LOG_LOOP_ALLOW(
LOCAL,
LOG_VERBOSE,p, 100,
" Particle %d: %s[%d] = [%.6f, ...,%.6f].\n", p,fieldName,descriptor->
components,disp_data[0],disp_data[descriptor->
components-1]);
464 ierr = DMSwarmRestoreField(swarm, fieldName, NULL, NULL, (
void**)&fieldData); CHKERRQ(ierr);
470 PetscFunctionReturn(0);
474#define __FUNCT__ "AssignInitialPropertiesToSwarm"
481 PetscInt particlesPerProcess,
482 PetscRandom *rand_phys_x,
483 PetscRandom *rand_phys_y,
484 PetscRandom *rand_phys_z,
485 PetscRandom *rand_logic_i,
486 PetscRandom *rand_logic_j,
487 PetscRandom *rand_logic_k,
491 PetscFunctionBeginUser;
498 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
501 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null input detected.");
511 LOG_ALLOW(
GLOBAL,
LOG_ERROR,
"Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
512 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
524 rand_logic_i, rand_logic_j, rand_logic_k,
560 PetscFunctionReturn(0);
565#define __FUNCT__ "DistributeParticles"
572PetscErrorCode
DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt* particlesPerProcess, PetscInt* remainder) {
574 PetscFunctionBeginUser;
578 *particlesPerProcess = numParticles / size;
579 *remainder = numParticles % size;
582 if (rank < *remainder) {
583 *particlesPerProcess += 1;
590 PetscFunctionReturn(0);
595#define __FUNCT__ "FinalizeSwarmSetup"
602PetscErrorCode
FinalizeSwarmSetup(PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k) {
604 PetscFunctionBeginUser;
608 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
609 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
610 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
612 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
613 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
614 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
619 PetscFunctionReturn(0);
623#define __FUNCT__ "CreateParticleSwarm"
631 PetscMPIInt rank, size;
632 PetscInt remainder = 0;
634 PetscFunctionBeginUser;
637 if (numParticles <= 0) {
640 return PETSC_ERR_ARG_OUTOFRANGE;
644 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
645 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
653 ierr =
DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
659 ierr = DMSwarmSetCellDM(user->
swarm, user->
da); CHKERRQ(ierr);
671 ierr = DMSwarmSetLocalSizes(user->
swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
677 ierr = DMView(user->
swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
683 PetscFunctionReturn(0);
692#define __FUNCT__ "UnpackSwarmFields"
701 const PetscReal *positions,
const PetscInt *cellIndices,
702 PetscReal *velocities,PetscInt *LocStatus,PetscReal *diffusivity,
Cmpnts *diffusivitygradient, PetscReal *psi,
Particle *particle) {
703 PetscFunctionBeginUser;
710 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
712 if (particle == NULL) {
713 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output Particle pointer is NULL. \n");
721 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input PIDs pointer is NULL.\n");
723 particle->
PID = PIDs[i];
731 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);
733 particle->
weights.
x = weights[3 * i];
734 particle->
weights.
y = weights[3 * i + 1];
735 particle->
weights.
z = weights[3 * i + 2];
740 if(positions == NULL){
741 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input positions pointer is NULL.\n");
743 particle->
loc.
x = positions[3 * i];
744 particle->
loc.
y = positions[3 * i + 1];
745 particle->
loc.
z = positions[3 * i + 2];
747 rank,i, particle->
loc.
x, particle->
loc.
y, particle->
loc.
z);
750 if(velocities == NULL){
751 particle->
vel.
x = 0.0;
752 particle->
vel.
y = 0.0;
753 particle->
vel.
z = 0.0;
754 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);
756 particle->
vel.
x = velocities[3 * i];
757 particle->
vel.
y = velocities[3 * i + 1];
758 particle->
vel.
z = velocities[3 * i + 2];
763 if(diffusivity == NULL){
771 if(diffusivitygradient == NULL){
775 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);
787 particle->
psi = psi[i];
792 if(cellIndices == NULL){
793 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input cellIndices pointer is NULL.\n");
795 particle->
cell[0] = cellIndices[3 * i];
796 particle->
cell[1] = cellIndices[3 * i + 1];
797 particle->
cell[2] = cellIndices[3 * i + 2];
800 if(LocStatus == NULL){
801 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input LocStatus pointer is NULL.\n");
817 PetscFunctionReturn(0);
821#define __FUNCT__ "UpdateSwarmFields"
827 PetscReal *positions,
828 PetscReal *velocities,
830 PetscInt *cellIndices,
832 PetscReal *diffusivity,
833 Cmpnts *diffusivitygradient,
836 PetscFunctionBeginUser;
840 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input Particle pointer is NULL.\n");
845 positions[3 * i + 0] = particle->
loc.
x;
846 positions[3 * i + 1] = particle->
loc.
y;
847 positions[3 * i + 2] = particle->
loc.
z;
852 velocities[3 * i + 0] = particle->
vel.
x;
853 velocities[3 * i + 1] = particle->
vel.
y;
854 velocities[3 * i + 2] = particle->
vel.
z;
859 weights[3 * i + 0] = particle->
weights.
x;
860 weights[3 * i + 1] = particle->
weights.
y;
861 weights[3 * i + 2] = particle->
weights.
z;
866 cellIndices[3 * i + 0] = particle->
cell[0];
867 cellIndices[3 * i + 1] = particle->
cell[1];
868 cellIndices[3 * i + 2] = particle->
cell[2];
881 if(diffusivitygradient){
888 psi[i] = particle->
psi;
894 PetscFunctionReturn(0);
898#define __FUNCT__ "IsParticleInsideBoundingBox"
905 PetscFunctionBeginUser;
929 min_coords.
x, min_coords.
y, min_coords.
z, max_coords.
x, max_coords.
y, max_coords.
z);
932 if ((loc.
x >= min_coords.
x && loc.
x <= max_coords.
x) &&
933 (loc.
y >= min_coords.
y && loc.
y <= max_coords.
y) &&
934 (loc.
z >= min_coords.
z && loc.
z <= max_coords.
z)) {
949#define __FUNCT__ "UpdateParticleWeights"
956 PetscFunctionBeginUser;
960 if (!d || !particle) {
961 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
962 "Null pointer argument (d or particle).");
970 "face distance d[%d] = %f <= %f; "
971 "clamping to 1e-14 to avoid zero/negative.\n",
979 "Calculating weights with distances: "
980 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
990 "Updated particle weights: x=%f, y=%f, z=%f.\n",
995 PetscFunctionReturn(0);
1019#define __FUNCT__ "InitializeParticleSwarm"
1029 PetscErrorCode ierr;
1030 PetscInt particlesPerProcess = 0;
1033 PetscFunctionBeginUser;
1045 PetscBool should_initialize_new_particles = PETSC_FALSE;
1047 should_initialize_new_particles = PETSC_TRUE;
1050 should_initialize_new_particles = PETSC_TRUE;
1054 should_initialize_new_particles = PETSC_TRUE;
1060 if (should_initialize_new_particles) {
1063 PetscRandom randx, randy, randz;
1064 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1069 ierr =
FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1087 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)
Maps a logical point inside one hexahedral cell to physical space.
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().
#define INTERPOLATION_DISTANCE_TOLERANCE
PetscBool IsParticleInsideBoundingBox(const BoundingBox *bbox, const Particle *particle)
Internal helper implementation: IsParticleInsideBoundingBox().
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, ParticleFieldId field_id)
Apply a configured initial field specification across the local swarm.
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initialize position-independent particle fields after a particle is created.
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)
Derive particle counts and spacing for volumetric swarm initialization.
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().
static PetscErrorCode InitializeSwarmFieldValue(const ParticleFieldDescriptor *descriptor, PetscInt p, PetscReal *fieldData)
Assign one configured initial value to a swarm field entry.
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)
Returns the canonical log token for a boundary-face enum value.
#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)
Returns the canonical log token for a particle-initialization mode.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_LOCATION_STATUS
@ PARTICLE_FIELD_ID_WEIGHT
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_CELL_ID
@ PARTICLE_FIELD_ID_DIFFUSIVITY_GRADIENT
@ PARTICLE_FIELD_ID_COUNT
@ PARTICLE_FIELD_ID_DIFFUSIVITY
@ PARTICLE_FIELD_ID_VELOCITY
PetscReal default_real_value
unsigned int capabilities
ParticleFieldRegistration registration
@ PARTICLE_FIELD_CAPABILITY_DEFAULT_INITIALIZE
@ PARTICLE_FIELD_REGISTRATION_PETSC
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
const char * canonical_name
Immutable metadata for one persistent particle field.
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.