PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
ParticleSwarm.c File Reference
#include "ParticleSwarm.h"
Include dependency graph for ParticleSwarm.c:

Go to the source code of this file.

Macros

#define INTERPOLATION_DISTANCE_TOLERANCE   1.0e-14
 
#define __FUNCT__   "InitializeSwarm"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "RegisterSwarmField"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "RegisterParticleFields"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "DetermineVolumetricInitializationParameters"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "InitializeParticleBasicProperties"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "InitializeSwarmFieldValue"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "AssignInitialFieldToSwarm"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "AssignInitialPropertiesToSwarm"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "DistributeParticles"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "FinalizeSwarmSetup"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "CreateParticleSwarm"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "UnpackSwarmFields"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "UpdateSwarmFields"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "IsParticleInsideBoundingBox"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "UpdateParticleWeights"
 Initializes or loads the particle swarm based on the simulation context.
 
#define __FUNCT__   "InitializeParticleSwarm"
 Initializes or loads the particle swarm based on the simulation context.
 

Functions

PetscErrorCode InitializeSwarm (UserCtx *user)
 Initializes the DMSwarm object within the UserCtx structure.
 
PetscErrorCode RegisterSwarmField (DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
 Registers a swarm field without finalizing registration.
 
PetscErrorCode RegisterParticleFields (DM swarm)
 Registers necessary particle fields within the DMSwarm.
 
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).
 
static PetscErrorCode InitializeParticleBasicProperties (UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
 Initializes basic properties for particles on the local process.
 
static PetscErrorCode InitializeSwarmFieldValue (const char *fieldName, PetscInt p, PetscInt fieldDim, PetscReal *fieldData)
 Helper function to Initialize a given particle’s field value.
 
static PetscErrorCode AssignInitialFieldToSwarm (UserCtx *user, const char *fieldName, PetscInt fieldDim)
 Initializes a generic swarm field with point-level updates.
 
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.
 
PetscErrorCode DistributeParticles (PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
 Distributes particles evenly across MPI processes, handling any remainders.
 
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 CreateParticleSwarm (UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
 Creates and initializes a Particle Swarm.
 
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 UpdateSwarmFields (PetscInt i, const Particle *particle, PetscReal *weights, PetscInt *cellIndices, PetscInt *status_field)
 Updates DMSwarm fields with data from a Particle struct.
 
PetscBool IsParticleInsideBoundingBox (const BoundingBox *bbox, const Particle *particle)
 Checks if a particle's location is within a specified bounding box.
 
PetscErrorCode UpdateParticleWeights (PetscReal *d, Particle *particle)
 Updates a particle's interpolation weights based on distances to cell faces.
 
PetscErrorCode InitializeParticleSwarm (SimCtx *simCtx)
 Perform particle swarm initialization, particle-grid interaction, and related operations.
 

Macro Definition Documentation

◆ INTERPOLATION_DISTANCE_TOLERANCE

#define INTERPOLATION_DISTANCE_TOLERANCE   1.0e-14

Definition at line 5 of file ParticleSwarm.c.

◆ __FUNCT__ [1/16]

#define __FUNCT__   "InitializeSwarm"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [2/16]

#define __FUNCT__   "RegisterSwarmField"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [3/16]

#define __FUNCT__   "RegisterParticleFields"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [4/16]

#define __FUNCT__   "DetermineVolumetricInitializationParameters"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [5/16]

#define __FUNCT__   "InitializeParticleBasicProperties"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [6/16]

#define __FUNCT__   "InitializeSwarmFieldValue"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [7/16]

#define __FUNCT__   "AssignInitialFieldToSwarm"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [8/16]

#define __FUNCT__   "AssignInitialPropertiesToSwarm"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [9/16]

#define __FUNCT__   "DistributeParticles"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [10/16]

#define __FUNCT__   "FinalizeSwarmSetup"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [11/16]

#define __FUNCT__   "CreateParticleSwarm"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [12/16]

#define __FUNCT__   "UnpackSwarmFields"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [13/16]

#define __FUNCT__   "UpdateSwarmFields"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [14/16]

#define __FUNCT__   "IsParticleInsideBoundingBox"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [15/16]

#define __FUNCT__   "UpdateParticleWeights"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

◆ __FUNCT__ [16/16]

#define __FUNCT__   "InitializeParticleSwarm"

Initializes or loads the particle swarm based on the simulation context.

This function is the central point for setting up the DMSwarm. Its behavior depends on the simulation context (simCtx):

  1. Fresh Start (simCtx->StartStep == 0): A new particle population is generated according to the specified initial conditions.
  2. Restart (simCtx->StartStep > 0):
    • If simCtx->particleRestartMode is "init", a new particle population is generated, just like a fresh start. This allows injecting fresh particles into a pre-computed flow field.
    • If simCtx->particleRestartMode is "load", the particle state is loaded from restart files corresponding to the StartStep.
Parameters
[in,out]simCtxPointer to the main SimulationContext, which contains all configuration and provides access to the UserCtx.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 8 of file ParticleSwarm.c.

Function Documentation

◆ InitializeSwarm()

PetscErrorCode InitializeSwarm ( UserCtx user)

Initializes the DMSwarm object within the UserCtx structure.

This function creates the DMSwarm, sets its type and dimension, and configures basic swarm properties.

Parameters
[in,out]userPointer to the UserCtx structure containing simulation context.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 18 of file ParticleSwarm.c.

18 {
19 PetscErrorCode ierr; // Error code for PETSc functions
20
21 PetscFunctionBeginUser;
23 // Create the DMSwarm object for particle management
24 ierr = DMCreate(PETSC_COMM_WORLD, &user->swarm); CHKERRQ(ierr);
25 ierr = DMSetType(user->swarm, DMSWARM); CHKERRQ(ierr);
26 ierr = DMSetDimension(user->swarm, 3); CHKERRQ(ierr);
27 ierr = DMSwarmSetType(user->swarm, DMSWARM_BASIC); CHKERRQ(ierr);
28 LOG_ALLOW(LOCAL,LOG_INFO, "DMSwarm created and configured.\n");
29
31 PetscFunctionReturn(0);
32}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:201
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:740
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:32
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:731
Here is the caller graph for this function:

◆ RegisterSwarmField()

PetscErrorCode RegisterSwarmField ( DM  swarm,
const char *  fieldName,
PetscInt  fieldDim,
PetscDataType  dtype 
)

Registers a swarm field without finalizing registration.

This function calls DMSwarmRegisterPetscDatatypeField for the given field, but does not finalize the registration. The finalization is deferred until all fields have been registered.

Parameters
swarm[in] The DMSwarm object.
fieldName[in] Name of the field to register.
fieldDim[in] Dimension of the field (1 for scalar, 3 for vector, etc.).
dtype[in] The datatype of the swarm field being registered.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 50 of file ParticleSwarm.c.

51{
52 PetscErrorCode ierr;
53 PetscFunctionBeginUser;
54
55 ierr = DMSwarmRegisterPetscDatatypeField(swarm, fieldName, fieldDim, dtype); CHKERRQ(ierr);
56 // PetscDataTypes is an extern char* [] defined in petscsystypes.h that gives string names for PetscDataType enums
57 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field '%s' with dimension=%d, type=%s.\n",
58 fieldName, fieldDim, PetscDataTypes[dtype]);
59
60 PetscFunctionReturn(0);
61}
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:33
Here is the caller graph for this function:

◆ RegisterParticleFields()

PetscErrorCode RegisterParticleFields ( DM  swarm)

Registers necessary particle fields within the DMSwarm.

This function registers fields such as position, velocity, CellID, and weight for each particle.

Parameters
[in,out]swarmThe DMSwarm object managing the particle swarm.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 76 of file ParticleSwarm.c.

77{
78 PetscErrorCode ierr;
79 PetscFunctionBeginUser;
80
81 // Register each field using the helper function
82 ierr = RegisterSwarmField(swarm, "position", 3 ,PETSC_REAL); CHKERRQ(ierr);
83 LOG_ALLOW(LOCAL,LOG_DEBUG, "Registered field 'position'.\n");
84
85 ierr = RegisterSwarmField(swarm, "velocity", 3, PETSC_REAL); CHKERRQ(ierr);
86 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'velocity'.\n");
87
88 ierr = RegisterSwarmField(swarm, "DMSwarm_CellID", 3, PETSC_INT); CHKERRQ(ierr);
89 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'DMSwarm_CellID'.\n");
90
91 ierr = RegisterSwarmField(swarm, "weight", 3,PETSC_REAL); CHKERRQ(ierr);
92 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'weight'.\n");
93
94 ierr = RegisterSwarmField(swarm,"Psi", 1,PETSC_REAL); CHKERRQ(ierr);
95 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'Psi' - Scalar.\n");
96
97 ierr = RegisterSwarmField(swarm,"DMSwarm_location_status",1,PETSC_INT);CHKERRQ(ierr);
98 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'DMSwarm_location_status' - Status of Location of Particle(located,lost etc).\n");
99
100 // Finalize the field registration after all fields have been added
101 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
102 LOG_ALLOW(LOCAL,LOG_INFO,"RegisterParticleFields - Finalized field registration.\n");
103
104 PetscFunctionReturn(0);
105}
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Registers a swarm field without finalizing registration.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DetermineVolumetricInitializationParameters()

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 
)
static

Determines cell selection and intra-cell logical coordinates for volumetric initialization (Mode 1).

This function is called when simCtx->ParticleInitialization == 1. It randomly selects an owned cell on the current MPI rank and then generates random intra-cell logical coordinates [0,1)^3 within that chosen cell.

The process involves:

  1. Checking if the current MPI rank owns any 3D cells.
  2. If it does, it randomly selects an owned cell index in each logical direction (i, j, k) by scaling a [0,1) random number with the number of owned cells in that direction.
  3. These local owned cell indices are then converted to the local node indices (ci/cj/ck_metric_lnode_out) corresponding to the origin of the selected cell, for use with MetricLogicalToPhysical. This conversion uses xs/ys/zs_gnode.
  4. All three intra-cell logical coordinates (xi/eta/zta_metric_logic_out) for MetricLogicalToPhysical are chosen randomly within the [0,1) range.
  5. A flag (can_place_in_volume_out) indicates if a valid placement could be determined.

Important Note on DMDALocalInfo info members (same as for surface init):

  • info->xs, info->ys, info->ks: Global starting indices of owned cells.
  • info->mx, info->my, info->mz: Number of grid points (nodes) in each local dimension on this process. Therefore, the number of owned cells in a dimension is info->mX - 1 (if info->mX > 0).
Parameters
[in]userPointer to UserCtx. (Currently not used in this specific helper, but kept for API consistency).
[in]infoPointer to DMDALocalInfo for the current rank's grid portion.
[in]xs_gnode,ys_gnode,zs_gnodeLocal indices (in the ghosted array) of the first owned node.
[in]rand_logic_i_ptrPointer to the RNG for i-dimension tasks [0,1).
[in]rand_logic_j_ptrPointer to the RNG for j-dimension tasks [0,1).
[in]rand_logic_k_ptrPointer to the RNG for k-dimension tasks [0,1).
[out]ci_metric_lnode_outPointer to store the local i-node index of the selected cell's origin.
[out]cj_metric_lnode_outPointer to store the local j-node index of the selected cell's origin.
[out]ck_metric_lnode_outPointer to store the local k-node index of the selected cell's origin.
[out]xi_metric_logic_outPointer to store the intra-cell logical xi-coordinate [0,1).
[out]eta_metric_logic_outPointer to store the intra-cell logical eta-coordinate [0,1).
[out]zta_metric_logic_outPointer to store the intra-cell logical zeta-coordinate [0,1).
[out]can_place_in_volume_outPETSC_TRUE if placement parameters were successfully determined, PETSC_FALSE otherwise.
Returns
PetscErrorCode 0 on success, or a PETSc error code.

Definition at line 147 of file ParticleSwarm.c.

154{
155 PetscErrorCode ierr = 0;
156 PetscReal r_val; // Temporary for random numbers from [0,1) RNGs
157 PetscInt local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k;
158 PetscMPIInt rank_for_logging; // For logging if needed
159
160 PetscFunctionBeginUser;
161
163
164 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank_for_logging); CHKERRQ(ierr);
165
166 *can_place_in_volume_out = PETSC_FALSE; // Default to: cannot place
167
168 // Default intra-cell logicals and cell node indices (e.g. if placement fails)
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;
171
172 // Calculate number of owned cells in each direction from node counts in info
173 // Assumes info->mx, info->my, info->mz are node counts on this process for each dimension.
174 // Number of cells = Number of nodes - 1 (if > 0 nodes).
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;
178
179 if (num_owned_cells_i > 0 && num_owned_cells_j > 0 && num_owned_cells_k > 0) { // If rank owns any 3D cells
180 *can_place_in_volume_out = PETSC_TRUE;
181
182 // --- 1. Select a Random Owned Cell ---
183 // The selected index will be a 0-based index relative to the start of this rank's owned cells.
184
185 // Select random local owned cell index in I-direction
186 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
187 local_owned_cell_idx_i = (PetscInt)(r_val * num_owned_cells_i);
188 // Clamp to be safe: local_owned_cell_idx_i should be in [0, num_owned_cells_i - 1]
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; // Convert to local node index for cell origin
191
192 // Select random local owned cell index in J-direction
193 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
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;
197
198 // Select random local owned cell index in K-direction
199 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
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;
203
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);
209
210
211 // --- 2. Generate Random Intra-Cell Logical Coordinates [0,1) for MetricLogicalToPhysical ---
212 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, xi_metric_logic_out); CHKERRQ(ierr); // Re-use RNGs
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);
215
216 // Ensure logical coordinates are strictly within [0,1) for robustness with MetricLogicalToPhysical
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);
220 // Ensure they are not negative either (though [0,1) RNGs shouldn't produce this)
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);
224
225 } else {
226 // This rank does not own any 3D cells (e.g., in a 1D or 2D decomposition,
227 // or if the global domain itself is not 3D in terms of cells).
228 // *can_place_in_volume_out remains PETSC_FALSE.
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);
231 }
232
234 PetscFunctionReturn(0);
235}
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
Here is the caller graph for this function:

◆ InitializeParticleBasicProperties()

static PetscErrorCode InitializeParticleBasicProperties ( UserCtx user,
PetscInt  particlesPerProcess,
PetscRandom *  rand_logic_i,
PetscRandom *  rand_logic_j,
PetscRandom *  rand_logic_k,
BoundingBox bboxlist 
)
static

Initializes basic properties for particles on the local process.

This function assigns initial physical positions, Particle IDs (PIDs), and placeholder cell IDs to particles. The method of position initialization depends on simCtx->ParticleInitialization:

  • Mode 0 (Surface): Particles are placed on a designated inlet surface if the current rank services that surface. Otherwise, they are placed at (0,0,0) to be migrated to the correct rank later.
  • Mode 1 (Volumetric): Particles are placed randomly within a cell owned by the current rank.

The logical coordinates for placement are generated using provided random number generators. These logical coordinates are then transformed to physical coordinates using MetricLogicalToPhysical.

Parameters
userPointer to the UserCtx structure, containing simulation settings and grid information.
particlesPerProcessThe number of particles to initialize on this MPI rank.
rand_logic_iPointer to a PetscRandom generator for the xi logical coordinate.
rand_logic_jPointer to a PetscRandom generator for the eta logical coordinate.
rand_logic_kPointer to a PetscRandom generator for the zeta logical coordinate.
bboxlist(Unused in this function for placement) Pointer to the bounding box list; provided for API consistency but not used for determining initial positions here. Particle positions are determined by logical-to-physical mapping based on rank's owned cells.
Returns
PetscErrorCode 0 on success, non-zero on failure.

Definition at line 266 of file ParticleSwarm.c.

272{
273 PetscErrorCode ierr;
274 DM swarm = user->swarm;
275 PetscReal *positions_field = NULL; // Pointer to swarm field for physical positions (x,y,z)
276 PetscInt64 *particleIDs = NULL; // Pointer to swarm field for Particle IDs
277 PetscInt *cellIDs_petsc = NULL; // Pointer to swarm field for DMSwarm_CellID (i,j,k of containing cell)
278 PetscInt *status_field = NULL; // Pointer to swarm field for DMSwarm_location_status(NEEDS_LOCATION etc)
279 PetscMPIInt rank,size; // MPI rank of the current process, and total number of ranks.
280 const Cmpnts ***coor_nodes_local_array; // Read-only access to local node coordinates (from user->da)
281 Vec Coor_local; // Local vector for node coordinates
282 DMDALocalInfo info; // Local grid information (node-based) from user->da
283 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank; // Local starting node indices (incl. ghosts) of rank's DA patch
284 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global; // Global node counts in each direction
285
286 // Variables for surface initialization (Mode 0)
287 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
288
289 PetscFunctionBeginUser;
290
292
293 SimCtx *simCtx = user->simCtx;
294
295 // --- 1. Input Validation and Basic Setup ---
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.");
298 }
299 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
300 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
301
302 // Get DMDA information for the node-centered coordinate grid (user->da)
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);
309
310 // Modification to IM_nodes_global etc. to account for 1-cell halo in each direction.
311 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
312
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;
316
317 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Initializing %d particles. Mode: %s.\n",
318 rank, particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
319
320 // --- 2. Pre-computation for Surface Initialization (Mode 0) ---
321 if (simCtx->ParticleInitialization == 0 || simCtx->ParticleInitialization == 3) { // Surface initialization
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) {
324 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Will attempt to place particles on inlet face %s.\n", rank, BCFaceToString((BCFace)user->identifiedInletBCFace));
325 } else {
326 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Cannot service inlet face %s. Particles will be at Inlet Center (%.6f,%.6f,%.6f) and rely on migration.\n", rank, BCFaceToString((BCFace)user->identifiedInletBCFace),user->simCtx->CMx_c,user->simCtx->CMy_c,user->simCtx->CMz_c);
327 }
328 }
329
330 // --- 3. Get Access to Swarm Fields ---
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);
335
336 // --- 4. Determine Starting Global PID for this Rank ---
337 PetscInt particles_per_rank_ideal = simCtx->np / size; // Assumes user->size is PETSC_COMM_WORLD size
338 PetscInt remainder_particles = simCtx->np % size;
339 PetscInt base_pid_for_rank = rank * particles_per_rank_ideal + PetscMin(rank, remainder_particles);
340 // This calculation must match how particlesPerProcess was determined (e.g., in DistributeParticles).
341
342 // --- 5. Loop Over Particles to Initialize ---
343 for (PetscInt p = 0; p < particlesPerProcess; p++) {
344 PetscInt idx = 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;
349
350 if (simCtx->ParticleInitialization == 0) { // --- 5.a. Surface Random Initialization ---
351 if (can_this_rank_service_inlet) {
352 ierr = GetRandomCellAndLogicalCoordsOnInletFace(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
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);
357 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
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;
362 }else{
363 // Rank cannot service inlet - place at inlet center to be migrated later
364 phys_coords.x = user->simCtx->CMx_c;
365 phys_coords.y = user->simCtx->CMy_c;
366 phys_coords.z = user->simCtx->CMz_c;
367 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
368 }
369 }else if(simCtx->ParticleInitialization == 3) { // --- 5.a1. Custom Initialization DEBUG (Mode 3) ---
370 if(can_this_rank_service_inlet) {
371 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
372 ierr = GetDeterministicFaceGridLocation(user,&info,xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
373 IM_cells_global, JM_cells_global, KM_cells_global,
374 particle_global_id,
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);
378
379 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
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);
383
384 }else{
385 // Rank cannot service inlet - place at inlet center to be migrated later
386 phys_coords.x = user->simCtx->CMx_c;
387 phys_coords.y = user->simCtx->CMy_c;
388 phys_coords.z = user->simCtx->CMz_c;
389 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
390 }
391 }else if(simCtx->ParticleInitialization == 1){ // --- 5.b. Volumetric Initialization (simCtx->ParticleInitialization == 1) ---
392 PetscBool can_place_volumetrically;
393 ierr = DetermineVolumetricInitializationParameters(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
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){
399 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
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;
404 } else {
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);
408 }
409 }else {
410 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown ParticleInitialization mode %d.", simCtx->ParticleInitialization);
411 }
412
413 // --- 5.c. Store Particle Properties ---
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;
417
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;
420 status_field[p] = UNINITIALIZED;
421
422 // --- 5.d. Logging for this particle ---
423 if (particle_placed_by_this_rank) {
424 LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, idx, user->simCtx->LoggingFrequency,//(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
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",
426 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
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);
430
431 } else {
432 LOG_LOOP_ALLOW(LOCAL, LOG_WARNING, idx, user->simCtx->LoggingFrequency, //(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
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",
434 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
435 phys_coords.x, phys_coords.y, phys_coords.z);
436 }
437 }
438
439 // --- 6. Restore Pointers and Cleanup ---
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);
445
446 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Completed processing for %d particles.\n",
447 rank, particlesPerProcess);
448
450
451 PetscFunctionReturn(0);
452}
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...
Definition Boundaries.c:459
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,...
Definition Boundaries.c:25
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.
Definition Boundaries.c:267
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).
Definition Metric.c:77
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).
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt,...)
Logs a message inside a loop, but only every interval iterations.
Definition logging.h:313
const char * BCFaceToString(BCFace face)
Helper function to convert BCFace enum to a string representation.
Definition logging.c:643
const char * ParticleInitializationToString(PetscInt ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
Definition logging.c:675
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:35
BCFace identifiedInletBCFace
Definition variables.h:681
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:664
@ UNINITIALIZED
Definition variables.h:140
PetscReal CMy_c
Definition variables.h:589
PetscInt np
Definition variables.h:616
PetscScalar x
Definition variables.h:101
PetscReal CMz_c
Definition variables.h:589
PetscScalar z
Definition variables.h:101
PetscScalar y
Definition variables.h:101
PetscInt ParticleInitialization
Definition variables.h:620
PetscInt LoggingFrequency
Definition variables.h:636
PetscReal CMx_c
Definition variables.h:589
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:200
A 3D point or vector with PetscScalar components.
Definition variables.h:100
The master context for the entire simulation.
Definition variables.h:538
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitializeSwarmFieldValue()

static PetscErrorCode InitializeSwarmFieldValue ( const char *  fieldName,
PetscInt  p,
PetscInt  fieldDim,
PetscReal *  fieldData 
)
static

Helper function to Initialize a given particle’s field value.

This function performs conditional, point-level Initialization for a swarm field based on its name. For example, you might want to initialize the "velocity" field to 0.0, but the "temperature" field to a nonzero default (e.g., 300.0). This function can be extended for other fields.

Parameters
[in]fieldNameName of the swarm field.
[in]pParticle index.
[in]fieldDimDimension of the field.
[out]fieldDataPointer to the field’s data array.
Returns
PetscErrorCode Returns 0 on success.

Definition at line 470 of file ParticleSwarm.c.

471{
472 PetscFunctionBeginUser;
473
475
476 if (strcmp(fieldName, "velocity") == 0) {
477 // For velocity, initialize all components to zero
478 for (PetscInt d = 0; d < fieldDim; d++) {
479 fieldData[fieldDim * p + d] = 0.0;
480 }
481 } else if (strcmp(fieldName, "temperature") == 0) {
482 // For temperature, for example, initialize to a default value (e.g., 300.0)
483 for (PetscInt d = 0; d < fieldDim; d++) {
484 fieldData[fieldDim * p + d] = 300.0;
485 }
486 } else if (strcmp(fieldName, "Psi") == 0) {
487 for (PetscInt d = 0; d < fieldDim; d++) {
488 fieldData[fieldDim * p + d] = 0.0;
489 }
490 } else {
491 // Default: initialize all components to zero
492 for (PetscInt d = 0; d < fieldDim; d++) {
493 fieldData[fieldDim * p + d] = 0.0;
494 }
495 }
496
498 PetscFunctionReturn(0);
499}
Here is the caller graph for this function:

◆ AssignInitialFieldToSwarm()

static PetscErrorCode AssignInitialFieldToSwarm ( UserCtx user,
const char *  fieldName,
PetscInt  fieldDim 
)
static

Initializes a generic swarm field with point-level updates.

This field-agnostic function retrieves the specified swarm field (which may be scalar or multi-component) and initializes each particle's entry using a helper that performs conditional updates based on the field name.

Parameters
[in,out]userPointer to the UserCtx structure containing the swarm.
[in]fieldNameName of the swarm field to initialize.
[in]fieldDimDimension of the field (e.g., 1 for scalar, 3 for vector).
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 517 of file ParticleSwarm.c.

518{
519 PetscErrorCode ierr;
520 DM swarm = user->swarm;
521 PetscReal *fieldData = NULL;
522 PetscInt nLocal;
523
524 PetscFunctionBeginUser;
525
527
528 // Get the number of local particles
529 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
530 LOG_ALLOW(LOCAL,LOG_INFO, "%d local particles found.\n", nLocal);
531
532 // Retrieve the swarm field pointer for the specified fieldName
533 ierr = DMSwarmGetField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
534 LOG_ALLOW(LOCAL,LOG_DEBUG, "Retrieved field '%s'.\n", fieldName);
535
536 // Loop over all particles and update the field using the helper function
537 for (PetscInt p = 0; p < nLocal; p++) {
538 ierr = InitializeSwarmFieldValue(fieldName, p, fieldDim, fieldData); CHKERRQ(ierr);
539 PetscReal disp_data[fieldDim];
540
541 for (PetscInt d = 0; d < fieldDim; d++) {
542 disp_data[d] = fieldData[fieldDim* p + d];
543 }
544 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]);
545 }
546
547 // Restore the swarm field pointer
548 ierr = DMSwarmRestoreField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
549 LOG_ALLOW(LOCAL,LOG_INFO, "Initialization of field '%s' complete.\n", fieldName);
550
551
553
554 PetscFunctionReturn(0);
555}
static PetscErrorCode InitializeSwarmFieldValue(const char *fieldName, PetscInt p, PetscInt fieldDim, PetscReal *fieldData)
Helper function to Initialize a given particle’s field value.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AssignInitialPropertiesToSwarm()

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.

This function orchestrates the initialization of particle properties. It first determines the inlet face if surface initialization (Mode 0) is selected by parsing "bcs.dat". Then, it initializes basic particle properties (physical position, Particle ID, and placeholder Cell IDs) by calling InitializeParticleBasicProperties. This call uses the provided rand_logic_i/j/k RNGs, which must be pre-initialized for [0,1). The rand_phys_x/y/z RNGs (physically bounded) are passed but may not be used by InitializeParticleBasicProperties for position setting if all initialization paths use logical-to-physical mapping. Finally, it calls helper functions to initialize other registered swarm fields like "velocity", "weight", and "Psi" (scalar) to default values.

Parameters
[in,out]userPointer to the UserCtx structure.
[in]particlesPerProcessNumber of particles assigned to this MPI process.
[in]rand_phys_xRNG for physical x-coordinates (from InitializeRandomGenerators).
[in]rand_phys_yRNG for physical y-coordinates (from InitializeRandomGenerators).
[in]rand_phys_zRNG for physical z-coordinates (from InitializeRandomGenerators).
[in]rand_logic_iRNG for i-logical dimension tasks [0,1) (from InitializeLogicalSpaceRNGs).
[in]rand_logic_jRNG for j-logical dimension tasks [0,1) (from InitializeLogicalSpaceRNGs).
[in]rand_logic_kRNG for k-logical dimension tasks [0,1) (from InitializeLogicalSpaceRNGs).
[in]bboxlistArray of BoundingBox structures (potentially unused by IPBP).
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 587 of file ParticleSwarm.c.

596{
597 PetscErrorCode ierr;
598 PetscFunctionBeginUser;
599
601
602 SimCtx *simCtx = user->simCtx;
603
604 // --- 0. Input Validation ---
605 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
606 // Check all RNGs now as they are passed in
607 LOG_ALLOW(GLOBAL, LOG_ERROR, "Null user, bboxlist, or RNG pointer.\n");
608 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input detected.");
609 }
610
611 LOG_ALLOW(GLOBAL, LOG_INFO, "Initializing swarm with %d particles per process. Mode: %s.\n",
612 particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
613
614 // --- 1. Parse BCS File for Inlet Information (if Mode 0) ---
615 if (simCtx->ParticleInitialization == 0 || simCtx->ParticleInitialization == 3) { // Surface initialization
616 if(user->inletFaceDefined == PETSC_FALSE){
617 LOG_ALLOW(GLOBAL, LOG_ERROR, "Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
618 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
619 }else{
620 LOG_ALLOW(GLOBAL, LOG_INFO, "After Parsing BCS file for Inlet, Inlet face = %s\n", BCFaceToString((BCFace)user->identifiedInletBCFace));
621 }
622 }
623
624 // --- 2. Initialize Basic Particle Properties (Position, PID, Cell IDs placeholder) ---
625 // The rand_logic_i/j/k are now passed directly.
626 // The rand_phys_x/y/z are passed but InitializeParticleBasicProperties (refactored version)
627 // will not use them for setting positions if all its paths use logical-to-physical mapping.
628 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Calling InitializeParticleBasicProperties.\n");
629 ierr = InitializeParticleBasicProperties(user, particlesPerProcess,
630 rand_logic_i, rand_logic_j, rand_logic_k,
631 bboxlist); // bboxlist passed along
632 CHKERRQ(ierr);
633 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully initialized basic particle properties.\n");
634
635 // Note: The logical RNGs (rand_logic_i/j/k) are NOT destroyed here.
636 // They were created externally (e.g., by InitializeLogicalSpaceRNGs) and
637 // should be destroyed externally (e.g., in FinalizeSwarmSetup).
638 // Same for rand_phys_x/y/z.
639
640 // --- 3. Initialize Other Swarm Fields (Velocity, Weight, Pressure, etc.) ---
641 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'velocity' field.\n");
642 ierr = AssignInitialFieldToSwarm(user, "velocity", 3); CHKERRQ(ierr);
643 LOG_ALLOW(LOCAL, LOG_INFO, "'velocity' field initialization complete.\n");
644
645 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'weight' field.\n");
646 ierr = AssignInitialFieldToSwarm(user, "weight", 3); CHKERRQ(ierr); // Assuming weight is vec3
647 LOG_ALLOW(LOCAL, LOG_INFO, "'weight' field initialization complete.\n");
648
649 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'P' (Pressure) field.\n");
650 ierr = AssignInitialFieldToSwarm(user, "Psi", 1); CHKERRQ(ierr);
651 LOG_ALLOW(GLOBAL, LOG_INFO, "'P' field initialization complete.\n");
652
653 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully completed all swarm property initialization.\n");
654
655
657
658 PetscFunctionReturn(0);
659}
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, const char *fieldName, PetscInt fieldDim)
Initializes a generic swarm field with point-level updates.
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initializes basic properties for particles on the local process.
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:47
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:29
PetscBool inletFaceDefined
Definition variables.h:680
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DistributeParticles()

PetscErrorCode DistributeParticles ( PetscInt  numParticles,
PetscMPIInt  rank,
PetscMPIInt  size,
PetscInt *  particlesPerProcess,
PetscInt *  remainder 
)

Distributes particles evenly across MPI processes, handling any remainders.

This function calculates the number of particles each MPI process should handle, distributing the remainder particles to the first few ranks if necessary.

Parameters
[in]numParticlesTotal number of particles to create across all MPI processes.
[in]rankMPI rank of the current process.
[in]sizeTotal number of MPI processes.
[out]particlesPerProcessNumber of particles assigned to the current MPI process.
[out]remainderRemainder particles when dividing numParticles by size.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 678 of file ParticleSwarm.c.

678 {
679
680 PetscFunctionBeginUser;
681
683 // Calculate the base number of particles per process
684 *particlesPerProcess = numParticles / size;
685 *remainder = numParticles % size;
686
687 // Distribute the remainder particles to the first 'remainder' ranks
688 if (rank < *remainder) {
689 *particlesPerProcess += 1;
690 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO,"Rank %d receives an extra particle. Total: %d\n", rank, *particlesPerProcess);
691 } else {
692 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO, "Rank %d receives %d particles.\n", rank, *particlesPerProcess);
693 }
694
696 PetscFunctionReturn(0);
697}
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level,...
Definition logging.h:268
Here is the caller graph for this function:

◆ FinalizeSwarmSetup()

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.

This function cleans up resources by destroying random number generators and LOG_ALLOWs the completion of swarm setup.

Parameters
[in]randxRandom number generator for the x-coordinate.
[in]randyRandom number generator for the y-coordinate.
[in]randzRandom number generator for the z-coordinate.
[in]rand_logic_iRandom number generator for the xi-coordinate.
[in]rand_logic_jRandom number generator for the eta-coordinate.
[in]rand_logic_kRandom number generator for the zeta-coordinate.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 716 of file ParticleSwarm.c.

716 {
717 PetscErrorCode ierr; // Error code for PETSc functions
718 PetscFunctionBeginUser;
720 // Destroy random number generators to free resources
721 // Physical space
722 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
723 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
724 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
725 // Logical space
726 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
727 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
728 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
729
730 LOG_ALLOW(LOCAL,LOG_DEBUG,"Destroyed all random number generators.\n");
731
733 PetscFunctionReturn(0);
734}
Here is the caller graph for this function:

◆ CreateParticleSwarm()

PetscErrorCode CreateParticleSwarm ( UserCtx user,
PetscInt  numParticles,
PetscInt *  particlesPerProcess,
BoundingBox bboxlist 
)

Creates and initializes a Particle Swarm.

This function sets up a DMSwarm within the provided UserCtx structure, initializes particle fields, and distributes particles across MPI processes. It ensures that the number of particles is evenly divided among the available MPI ranks. If the total number of particles isn't divisible by the number of processes, the remainder is distributed to the first few ranks.

Parameters
[in,out]userPointer to the UserCtx structure containing the simulation context.
[in]numParticlesTotal number of particles to create across all MPI processes.
[in]bboxlistPointer to an array of BoundingBox structures, one per rank.
[in]particlesPerProcess
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.
Note
  • Ensure that numParticles is a positive integer.
  • The control.dat file should contain necessary PETSc options.
  • The bboxlist array should be properly populated before calling this function.

Definition at line 760 of file ParticleSwarm.c.

760 {
761 PetscErrorCode ierr; // PETSc error handling variable
762 PetscMPIInt rank, size; // Variables to store MPI rank and size
763 PetscInt remainder = 0; // Remainder of particles after division
764
765 PetscFunctionBeginUser;
767 // Validate input parameters
768 if (numParticles <= 0) {
769 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Number of particles must be positive. Given: %d\n", numParticles);
770 return PETSC_ERR_ARG_OUTOFRANGE;
771 }
772
773 // Retrieve MPI rank and size
774 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
775 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
776 LOG_ALLOW(GLOBAL,LOG_INFO," Domain dimensions: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
777 user->Min_X,user->Max_X,user->Min_Y,user->Max_Y, user->Min_Z,user->Max_Z);
778 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG, "[Rank %d] Local Bounding Box: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
779 rank,user->bbox.min_coords.x,user->bbox.max_coords.x,
780 user->bbox.min_coords.y,user->bbox.max_coords.y,
781 user->bbox.min_coords.z,user->bbox.max_coords.z);
782 // Distribute particles among MPI processes
783 ierr = DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
784
785 // Initialize the DMSwarm - creates the swarm, sets the type and dimension
786 ierr = InitializeSwarm(user); CHKERRQ(ierr);
787
788 if (user->da) {
789 ierr = DMSwarmSetCellDM(user->swarm, user->da); CHKERRQ(ierr);
790 LOG_ALLOW(LOCAL,LOG_INFO,"Associated DMSwarm with Cell DM (user->da).\n");
791 } else {
792 // If user->da is essential for your simulation logic with particles, this should be a fatal error.
793 LOG_ALLOW(GLOBAL, LOG_WARNING, "user->da (Cell DM for Swarm) is NULL. Cell-based swarm operations might fail.\n");
794 // SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "user->da (Cell DM) is NULL but required.");
795 }
796
797 // Register particle fields (position, velocity, CellID, weight, etc.)
798 ierr = RegisterParticleFields(user->swarm); CHKERRQ(ierr);
799
800 // Set the local number of particles for this rank and additional buffer for particle migration
801 ierr = DMSwarmSetLocalSizes(user->swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
802 LOG_ALLOW(GLOBAL,LOG_INFO, "Set local swarm size: %d particles.\n", *particlesPerProcess);
803
804 // Optionally, LOG_ALLOW detailed DM info in debug mode
805 if (get_log_level() == LOG_DEBUG && is_function_allowed(__func__)) {
806 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Viewing DMSwarm:\n");
807 ierr = DMView(user->swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
808 }
809
810 LOG_ALLOW(GLOBAL,LOG_INFO, "Particle swarm creation and initialization complete.\n");
811
813 PetscFunctionReturn(0);
814}
PetscErrorCode DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
Distributes particles evenly across MPI processes, handling any remainders.
PetscErrorCode InitializeSwarm(UserCtx *user)
Initializes the DMSwarm object within the UserCtx structure.
PetscErrorCode RegisterParticleFields(DM swarm)
Registers necessary particle fields within the DMSwarm.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:157
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:39
PetscReal Min_X
Definition variables.h:671
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:156
PetscReal Max_Y
Definition variables.h:671
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:155
PetscReal Min_Z
Definition variables.h:671
PetscReal Max_X
Definition variables.h:671
PetscReal Min_Y
Definition variables.h:671
BoundingBox bbox
Definition variables.h:672
PetscReal Max_Z
Definition variables.h:671
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UnpackSwarmFields()

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.

This helper function populates a Particle structure using data retrieved from DMSwarm fields.

Parameters
[in]iIndex of the particle in the DMSwarm.
[in]PIDsPointer to the array of particle IDs.
[in]weightsPointer to the array of particle weights.
[in]positionsPointer to the array of particle positions.
[in]cellIndicesPointer to the array of particle cell indices.
[in]velocitiesPointer to the array of particle velocities.
[in]LocStatusPointer to the array of cell location status indicators.
[out]particlePointer to the Particle struct to initialize.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 836 of file ParticleSwarm.c.

838 {
839 PetscFunctionBeginUser;
840
842
843 PetscMPIInt rank;
844 PetscErrorCode ierr;
845
846 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
847
848 if (particle == NULL) {
849 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output Particle pointer is NULL. \n");
850 }
851
852 // logging the start of particle initialization
853 LOG_ALLOW(LOCAL,LOG_DEBUG, "[Rank %d]Unpacking Particle [%d] with PID: %ld.\n",rank, i, PIDs[i]);
854
855 // Initialize PID
856 particle->PID = PIDs[i];
857 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] PID set to: %ld.\n", rank,i, particle->PID);
858
859 // Initialize weights
860 particle->weights.x = weights[3 * i];
861 particle->weights.y = weights[3 * i + 1];
862 particle->weights.z = weights[3 * i + 2];
863 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] weights set to: (%.6f, %.6f, %.6f).\n",
864 rank,i, particle->weights.x, particle->weights.y, particle->weights.z);
865
866 // Initialize locations
867 particle->loc.x = positions[3 * i];
868 particle->loc.y = positions[3 * i + 1];
869 particle->loc.z = positions[3 * i + 2];
870 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] location set to: (%.6f, %.6f, %.6f).\n",
871 rank,i, particle->loc.x, particle->loc.y, particle->loc.z);
872
873 // Initialize velocities (assuming default zero; modify if necessary)
874 particle->vel.x = velocities[3 * i];
875 particle->vel.y = velocities[3 * i + 1];
876 particle->vel.z = velocities[3 * i + 2];
877 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] velocities unpacked to: [%.6f,%.6f,%.6f].\n",rank, i,particle->vel.x,particle->vel.y,particle->vel.z);
878
879 // Initialize cell indices
880 particle->cell[0] = cellIndices[3 * i];
881 particle->cell[1] = cellIndices[3 * i + 1];
882 particle->cell[2] = cellIndices[3 * i + 2];
883 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] cell indices set to: [%d, %d, %d].\n",rank,i, particle->cell[0], particle->cell[1], particle->cell[2]);
884
885 particle->location_status = (ParticleLocationStatus)LocStatus[i];
886 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] Status set to: %d.\n",rank, i, particle->location_status);
887
888 // The destination_rank is only set by the location search, not read from the swarm,
889 // so we initialize it to a known invalid state.
890 particle->destination_rank = MPI_PROC_NULL;
891
892 // logging the completion of particle initialization
893 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d]Completed initialization of Particle [%d]. \n", rank,i);
894
895
897
898 PetscFunctionReturn(0);
899}
Cmpnts vel
Definition variables.h:169
PetscInt cell[3]
Definition variables.h:167
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Definition variables.h:135
Cmpnts loc
Definition variables.h:168
PetscMPIInt destination_rank
Definition variables.h:172
ParticleLocationStatus location_status
Definition variables.h:171
Cmpnts weights
Definition variables.h:170
PetscInt64 PID
Definition variables.h:166
Here is the caller graph for this function:

◆ UpdateSwarmFields()

PetscErrorCode UpdateSwarmFields ( PetscInt  i,
const Particle particle,
PetscReal *  weights,
PetscInt *  cellIndices,
PetscInt *  status_field 
)

Updates DMSwarm fields with data from a Particle struct.

This helper function writes back the modified Particle data to the corresponding DMSwarm fields.

Parameters
[in]iIndex of the particle in the DMSwarm.
[in]particlePointer to the Particle struct containing updated data.
[in,out]weightsPointer to the array of particle weights.
[in,out]cellIndicesPointer to the array of particle cell indices.
[in,out]LocStatusPointer to the array of cell location status indicators.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Definition at line 918 of file ParticleSwarm.c.

919 {
920 PetscFunctionBeginUser;
922
923 if (particle == NULL) {
924 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input Particle pointer is NULL.\n");
925 }
926
927 // logging the start of swarm fields update
928 LOG_ALLOW(LOCAL,LOG_DEBUG,"Updating DMSwarm fields for Particle [%d].\n", i);
929
930 // Update weights
931 weights[3 * i] = particle->weights.x;
932 weights[3 * i + 1] = particle->weights.y;
933 weights[3 * i + 2] = particle->weights.z;
934 LOG_ALLOW(LOCAL,LOG_VERBOSE,"Updated weights for Particle [%d]: (%.6f, %.6f, %.6f).\n",
935 i, weights[3 * i], weights[3 * i + 1], weights[3 * i + 2]);
936
937 // Update cell indices
938 cellIndices[3 * i] = particle->cell[0];
939 cellIndices[3 * i + 1] = particle->cell[1];
940 cellIndices[3 * i + 2] = particle->cell[2];
941 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Updated cell indices for Particle [%d]: [%d, %d, %d].\n",
942 i, cellIndices[3 * i], cellIndices[3 * i + 1], cellIndices[3 * i + 2]);
943
944 status_field[i] = particle->location_status;
945 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Updated location status for Particle [%d]: [%d].\n",
946 i, status_field[i]);
947
948 // logging the completion of swarm fields update
949 LOG_ALLOW(LOCAL,LOG_DEBUG,"Completed updating DMSwarm fields for Particle [%d].\n", i);
950
951
953 PetscFunctionReturn(0);
954}
Here is the caller graph for this function:

◆ IsParticleInsideBoundingBox()

PetscBool IsParticleInsideBoundingBox ( const BoundingBox bbox,
const Particle particle 
)

Checks if a particle's location is within a specified bounding box.

This function determines whether the given particle's location lies inside the provided bounding box. It performs an axis-aligned bounding box (AABB) check by comparing the particle's coordinates to the minimum and maximum coordinates of the bounding box in each dimension (x, y, z).

logging statements are included to provide detailed information about the function's execution.

Parameters
[in]bboxPointer to the BoundingBox structure containing minimum and maximum coordinates.
[in]particlePointer to the Particle structure containing the particle's location and identifier.
Returns
PetscBool Returns PETSC_TRUE if the particle is inside the bounding box, PETSC_FALSE otherwise.
Note
  • The function assumes that the bbox and particle pointers are valid and non-NULL.
  • The function includes logging statements that start with the function name.
  • The LOG_ALLOW_SCOPE variable is used to distinguish between GLOBAL and LOCAL LOG_ALLOW outputs.
  • Be cautious when logging in performance-critical code sections, especially if the function is called frequently.

Definition at line 979 of file ParticleSwarm.c.

980{
981 PetscFunctionBeginUser;
983
984 // Validate input pointers
985 if (!bbox) {
986 // LOG_ALLOW error message and return PETSC_FALSE
987 LOG_ALLOW(LOCAL,LOG_ERROR, "Error - 'bbox' pointer is NULL.");
989 return PETSC_FALSE;
990 }
991 if (!particle) {
992 LOG_ALLOW(LOCAL,LOG_ERROR,"Error - 'particle' pointer is NULL.");
994 return PETSC_FALSE;
995 }
996
997 // Extract particle location and bounding box coordinates
998 const Cmpnts loc = particle->loc;
999 const Cmpnts min_coords = bbox->min_coords;
1000 const Cmpnts max_coords = bbox->max_coords;
1001
1002 // LOG_ALLOW the particle location and bounding box coordinates for debugging
1003 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "Particle PID %ld location: (%.6f, %.6f, %.6f).\n",particle->PID, loc.x, loc.y, loc.z);
1004 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "BoundingBox min_coords: (%.6f, %.6f, %.6f), max_coords: (%.6f, %.6f, %.6f).\n",
1005 min_coords.x, min_coords.y, min_coords.z, max_coords.x, max_coords.y, max_coords.z);
1006
1007 // Check if the particle's location is within the bounding box
1008 if ((loc.x >= min_coords.x && loc.x <= max_coords.x) &&
1009 (loc.y >= min_coords.y && loc.y <= max_coords.y) &&
1010 (loc.z >= min_coords.z && loc.z <= max_coords.z)) {
1011 // Particle is inside the bounding box
1012 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "Particle PID %ld is inside the bounding box.\n",particle->PID);
1014 return PETSC_TRUE;
1015 }
1016
1017 // Particle is outside the bounding box
1018 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE,"Particle PID %ld is outside the bounding box.\n",particle->PID);
1020 return PETSC_FALSE;
1021}

◆ UpdateParticleWeights()

PetscErrorCode UpdateParticleWeights ( PetscReal *  d,
Particle particle 
)

Updates a particle's interpolation weights based on distances to cell faces.

This function computes interpolation weights using distances to the six cell faces (d) and updates the weight field of the provided particle.

Parameters
[in]dPointer to an array of distances to the six cell faces.
[out]particlePointer to the Particle structure whose weights are to be updated.
Returns
PetscErrorCode Returns 0 on success, or a non-zero error code on failure.

Definition at line 1037 of file ParticleSwarm.c.

1037 {
1038
1039 PetscFunctionBeginUser;
1041
1042 // Validate input pointers
1043 if (!d || !particle) {
1044 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
1045 "Null pointer argument (d or particle).");
1046 }
1047
1048
1049 // Validate distances
1050 for (PetscInt i = LEFT; i < NUM_FACES; i++) {
1053 "face distance d[%d] = %f <= %f; "
1054 "clamping to 1e-14 to avoid zero/negative.\n",
1055 i, (double)d[i], INTERPOLATION_DISTANCE_TOLERANCE);
1057 }
1058 }
1059
1060 // LOG_ALLOW the input distances
1062 "Calculating weights with distances: "
1063 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
1064 d[LEFT], d[RIGHT], d[BOTTOM], d[TOP], d[FRONT], d[BACK]);
1065
1066 // Compute and update the particle's weights
1067 particle->weights.x = d[LEFT] / (d[LEFT] + d[RIGHT]);
1068 particle->weights.y = d[BOTTOM] / (d[BOTTOM] + d[TOP]);
1069 particle->weights.z = d[BACK] / (d[FRONT] + d[BACK]);
1070
1071 // LOG_ALLOW the updated weights
1073 "Updated particle weights: x=%f, y=%f, z=%f.\n",
1074 particle->weights.x, particle->weights.y, particle->weights.z);
1075
1076
1078 PetscFunctionReturn(0);
1079}
#define INTERPOLATION_DISTANCE_TOLERANCE
@ TOP
Definition variables.h:145
@ FRONT
Definition variables.h:145
@ BOTTOM
Definition variables.h:145
@ BACK
Definition variables.h:145
@ LEFT
Definition variables.h:145
@ NUM_FACES
Definition variables.h:145
@ RIGHT
Definition variables.h:145
Here is the caller graph for this function:

◆ InitializeParticleSwarm()

PetscErrorCode InitializeParticleSwarm ( SimCtx simCtx)

Perform particle swarm initialization, particle-grid interaction, and related operations.

This function handles the following tasks:

  1. Initializes the particle swarm using the provided bounding box list (bboxlist) to determine initial placement if ParticleInitialization is 0.
  2. Locates particles within the computational grid.
  3. Updates particle positions based on grid interactions (if such logic exists elsewhere in the code).
  4. Interpolates particle velocities from grid points using trilinear interpolation.
Parameters
[in,out]userPointer to the UserCtx structure containing grid and particle swarm information.
[in]npNumber of particles to initialize in the swarm.
[in]bboxlistPointer to an array of BoundingBox structures, one per MPI rank.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.
Note
  • Ensure that np (number of particles) is positive.
  • The bboxlist array must be correctly computed and passed in before calling this function.
  • If ParticleInitialization == 0, particles will be placed at the midpoint of the local bounding box.

Definition at line 1103 of file ParticleSwarm.c.

1104{
1105 PetscErrorCode ierr;
1106 PetscInt particlesPerProcess = 0;
1107 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1108
1109 PetscFunctionBeginUser;
1111
1112 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting particle swarm setup for %d particles.\n", simCtx->np);
1113
1114 // --- Phase 1: Create the DMSwarm Object (Always required) ---
1115 // This creates the container and registers the fields. It does not add particles yet.
1116 ierr = CreateParticleSwarm(user, simCtx->np, &particlesPerProcess, simCtx->bboxlist); CHKERRQ(ierr);
1117 LOG_ALLOW(GLOBAL, LOG_INFO, "DMSwarm object and fields created successfully.\n");
1118
1119
1120 // --- Phase 2: Decide whether to Initialize new particles or Load existing ones ---
1121 PetscBool should_initialize_new_particles = PETSC_FALSE;
1122 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1123 should_initialize_new_particles = PETSC_TRUE;
1124 }else{
1125 if (simCtx->StartStep == 0) {
1126 should_initialize_new_particles = PETSC_TRUE; // Standard fresh start
1127 } else {
1128 // It's a restart, so check the user's requested particle mode.
1129 if (strcmp(simCtx->particleRestartMode, "init") == 0) {
1130 should_initialize_new_particles = PETSC_TRUE; // User wants to re-initialize particles in a restarted flow.
1131 }
1132 }
1133 }
1134
1135 // --- Phase 3: Execute the chosen particle setup path ---
1136 if (should_initialize_new_particles) {
1137 // --- PATH A: Generate a fresh population of particles ---
1138 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: INITIALIZE. Generating new particle population.\n");
1139 PetscRandom randx, randy, randz;
1140 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1141
1142 ierr = InitializeRandomGenerators(user, &randx, &randy, &randz); CHKERRQ(ierr);
1143 ierr = InitializeLogicalSpaceRNGs(&rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1144 ierr = AssignInitialPropertiesToSwarm(user, particlesPerProcess, &randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k, simCtx->bboxlist); CHKERRQ(ierr);
1145 ierr = FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1146
1147 } else {
1148 // --- PATH B: Load particle population from restart files ---
1149 // This path is only taken if simCtx->StartStep > 0 AND simCtx->particleRestartMode == "load"
1150 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: LOAD. Loading particle population from files for step %d.\n", simCtx->StartStep);
1151
1152 ierr = PreCheckAndResizeSwarm(user, simCtx->StartStep, "dat"); CHKERRQ(ierr);
1153
1154 ierr = ReadAllSwarmFields(user, simCtx->StartStep); CHKERRQ(ierr);
1155 // Note: We check for file-open errors inside ReadAllSwarmFields now.
1156
1157 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle data loaded. CellID and status are preserved from file.\n");
1158 }
1159
1160 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Particle swarm setup complete.\n");
1161
1163 PetscFunctionReturn(0);
1164}
PetscErrorCode PreCheckAndResizeSwarm(UserCtx *user, PetscInt ti, const char *ext)
Checks particle count in the reference file and resizes the swarm if needed.
PetscErrorCode CreateParticleSwarm(UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
Creates and initializes a Particle Swarm.
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 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.
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Reads multiple fields (positions, velocity, CellID, and weight) into a DMSwarm.
Definition io.c:1327
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
Definition setup.c:2549
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).
Definition setup.c:2600
UserCtx * user
Definition variables.h:427
UserMG usermg
Definition variables.h:631
PetscInt StartStep
Definition variables.h:548
char particleRestartMode[16]
Definition variables.h:621
BoundingBox * bboxlist
Definition variables.h:619
PetscInt mglevels
Definition variables.h:434
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:512
MGCtx * mgctx
Definition variables.h:437
ExecutionMode exec_mode
Definition variables.h:556
User-defined context containing data specific to a single computational grid level.
Definition variables.h:661
Here is the call graph for this function:
Here is the caller graph for this function: