PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Macros | Functions
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)
 Implementation of InitializeSwarm().
 
PetscErrorCode RegisterSwarmField (DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
 Internal helper implementation: RegisterSwarmField().
 
PetscErrorCode RegisterParticleFields (DM swarm)
 Implementation of RegisterParticleFields().
 
static PetscErrorCode DetermineVolumetricInitializationParameters (UserCtx *user, DMDALocalInfo *info, PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode, PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr, PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out, PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out, PetscBool *can_place_in_volume_out)
 Internal helper implementation: DetermineVolumetricInitializationParameters().
 
static PetscErrorCode InitializeParticleBasicProperties (UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
 Internal helper implementation: InitializeParticleBasicProperties().
 
static PetscErrorCode InitializeSwarmFieldValue (const char *fieldName, PetscInt p, PetscInt fieldDim, PetscReal *fieldData)
 Internal helper implementation: InitializeSwarmFieldValue().
 
static PetscErrorCode AssignInitialFieldToSwarm (UserCtx *user, const char *fieldName, PetscInt fieldDim)
 Internal helper implementation: AssignInitialFieldToSwarm().
 
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().
 
PetscErrorCode DistributeParticles (PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
 Implementation of DistributeParticles().
 
PetscErrorCode FinalizeSwarmSetup (PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
 Implementation of FinalizeSwarmSetup().
 
PetscErrorCode CreateParticleSwarm (UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
 Internal helper implementation: CreateParticleSwarm().
 
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 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().
 
PetscBool IsParticleInsideBoundingBox (const BoundingBox *bbox, const Particle *particle)
 Internal helper implementation: IsParticleInsideBoundingBox().
 
PetscErrorCode UpdateParticleWeights (PetscReal *d, Particle *particle)
 Internal helper implementation: UpdateParticleWeights().
 
PetscErrorCode InitializeParticleSwarm (SimCtx *simCtx)
 Implementation of InitializeParticleSwarm().
 

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)

Implementation of InitializeSwarm().

Initializes the DMSwarm object within the UserCtx structure.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
InitializeSwarm()

Definition at line 15 of file ParticleSwarm.c.

15 {
16 PetscErrorCode ierr; // Error code for PETSc functions
17
18 PetscFunctionBeginUser;
20 // Create the DMSwarm object for particle management
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);
25 LOG_ALLOW(LOCAL,LOG_INFO, "DMSwarm created and configured.\n");
26
28 PetscFunctionReturn(0);
29}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:44
#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:199
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:779
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:770
Here is the caller graph for this function:

◆ RegisterSwarmField()

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

Internal helper implementation: RegisterSwarmField().

Registers a swarm field without finalizing registration.

Local to this translation unit.

Definition at line 38 of file ParticleSwarm.c.

39{
40 PetscErrorCode ierr;
41 PetscFunctionBeginUser;
42
43 ierr = DMSwarmRegisterPetscDatatypeField(swarm, fieldName, fieldDim, dtype); CHKERRQ(ierr);
44 // PetscDataTypes is an extern char* [] defined in petscsystypes.h that gives string names for PetscDataType enums
45 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field '%s' with dimension=%d, type=%s.\n",
46 fieldName, fieldDim, PetscDataTypes[dtype]);
47
48 PetscFunctionReturn(0);
49}
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
Here is the caller graph for this function:

◆ RegisterParticleFields()

PetscErrorCode RegisterParticleFields ( DM  swarm)

Implementation of RegisterParticleFields().

Registers necessary particle fields within the DMSwarm.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
RegisterParticleFields()

Definition at line 61 of file ParticleSwarm.c.

62{
63 PetscErrorCode ierr;
64 PetscFunctionBeginUser;
65
66 // Register each field using the helper function
67 ierr = RegisterSwarmField(swarm, "position", 3 ,PETSC_REAL); CHKERRQ(ierr);
68 LOG_ALLOW(LOCAL,LOG_DEBUG, "Registered field 'position'.\n");
69
70 ierr = RegisterSwarmField(swarm, "velocity", 3, PETSC_REAL); CHKERRQ(ierr);
71 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'velocity'.\n");
72
73 ierr = RegisterSwarmField(swarm, "DMSwarm_CellID", 3, PETSC_INT); CHKERRQ(ierr);
74 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'DMSwarm_CellID'.\n");
75
76 ierr = RegisterSwarmField(swarm, "weight", 3,PETSC_REAL); CHKERRQ(ierr);
77 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'weight'.\n");
78
79 ierr = RegisterSwarmField(swarm,"Diffusivity", 1,PETSC_REAL); CHKERRQ(ierr);
80 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'Diffusivity' - Scalar.\n");
81
82 ierr = RegisterSwarmField(swarm,"DiffusivityGradient", 3,PETSC_REAL); CHKERRQ(ierr);
83 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'DiffusivityGradient' - Vector.\n");
84
85 ierr = RegisterSwarmField(swarm,"Psi", 1,PETSC_REAL); CHKERRQ(ierr);
86 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'Psi' - Scalar.\n");
87
88 ierr = RegisterSwarmField(swarm,"DMSwarm_location_status",1,PETSC_INT);CHKERRQ(ierr);
89 LOG_ALLOW(LOCAL,LOG_DEBUG,"Registered field 'DMSwarm_location_status' - Status of Location of Particle(located,lost etc).\n");
90
91 // Finalize the field registration after all fields have been added
92 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
93 LOG_ALLOW(LOCAL,LOG_INFO,"RegisterParticleFields - Finalized field registration.\n");
94
95 PetscFunctionReturn(0);
96}
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Internal helper implementation: RegisterSwarmField().
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

Internal helper implementation: DetermineVolumetricInitializationParameters().

Local to this translation unit.

Definition at line 104 of file ParticleSwarm.c.

111{
112 PetscErrorCode ierr = 0;
113 (void)user;
114 PetscReal r_val; // Temporary for random numbers from [0,1) RNGs
115 PetscInt local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k;
116 PetscMPIInt rank_for_logging; // For logging if needed
117
118 PetscFunctionBeginUser;
119
121
122 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank_for_logging); CHKERRQ(ierr);
123
124 *can_place_in_volume_out = PETSC_FALSE; // Default to: cannot place
125
126 // Default intra-cell logicals and cell node indices (e.g. if placement fails)
127 *xi_metric_logic_out = 0.5; *eta_metric_logic_out = 0.5; *zta_metric_logic_out = 0.5;
128 *ci_metric_lnode_out = xs_gnode; *cj_metric_lnode_out = ys_gnode; *ck_metric_lnode_out = zs_gnode;
129
130 // Calculate number of owned cells in each direction from node counts in info
131 // Get number of cells this rank owns in each dimension (tangential to the face mainly)
132 PetscInt owned_start_cell_i, num_owned_cells_on_rank_i;
133 PetscInt owned_start_cell_j, num_owned_cells_on_rank_j;
134 PetscInt owned_start_cell_k, num_owned_cells_on_rank_k;
135
136 ierr = GetOwnedCellRange(info, 0, &owned_start_cell_i, &num_owned_cells_on_rank_i); CHKERRQ(ierr);
137 ierr = GetOwnedCellRange(info, 1, &owned_start_cell_j, &num_owned_cells_on_rank_j); CHKERRQ(ierr);
138 ierr = GetOwnedCellRange(info, 2, &owned_start_cell_k, &num_owned_cells_on_rank_k); CHKERRQ(ierr);
139
140 if (num_owned_cells_on_rank_i > 0 && num_owned_cells_on_rank_j > 0 && num_owned_cells_on_rank_k > 0) { // If rank owns any 3D cells
141 *can_place_in_volume_out = PETSC_TRUE;
142
143 // --- 1. Select a Random Owned Cell ---
144 // The selected index will be a 0-based index relative to the start of this rank's owned cells.
145
146 // Select random local owned cell index in I-direction
147 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
148 local_owned_cell_idx_i = (PetscInt)(r_val * num_owned_cells_on_rank_i);
149 // Clamp to be safe: local_owned_cell_idx_i should be in [0, num_owned_cells_on_rank_i - 1]
150 local_owned_cell_idx_i = PetscMin(PetscMax(0, local_owned_cell_idx_i), num_owned_cells_on_rank_i - 1);
151 *ci_metric_lnode_out = xs_gnode + local_owned_cell_idx_i; // Convert to local node index for cell origin
152
153 // Select random local owned cell index in J-direction
154 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
155 local_owned_cell_idx_j = (PetscInt)(r_val * num_owned_cells_on_rank_j);
156 local_owned_cell_idx_j = PetscMin(PetscMax(0, local_owned_cell_idx_j), num_owned_cells_on_rank_j - 1);
157 *cj_metric_lnode_out = ys_gnode + local_owned_cell_idx_j;
158
159 // Select random local owned cell index in K-direction
160 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, &r_val); CHKERRQ(ierr); // Dereference RNG pointer
161 local_owned_cell_idx_k = (PetscInt)(r_val * num_owned_cells_on_rank_k);
162 local_owned_cell_idx_k = PetscMin(PetscMax(0, local_owned_cell_idx_k), num_owned_cells_on_rank_k - 1);
163 *ck_metric_lnode_out = zs_gnode + local_owned_cell_idx_k;
164
165 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Selected Cell (Owned Idx: %d,%d,%d -> LNodeStart: %d,%d,%d). OwnedCells(i,j,k): (%d,%d,%d). GhostNodeStarts(xs,ys,zs): (%d,%d,%d) \n",
166 rank_for_logging, local_owned_cell_idx_i, local_owned_cell_idx_j, local_owned_cell_idx_k,
167 *ci_metric_lnode_out, *cj_metric_lnode_out, *ck_metric_lnode_out,
168 num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k,
169 xs_gnode, ys_gnode, zs_gnode);
170
171
172 // --- 2. Generate Random Intra-Cell Logical Coordinates [0,1) for MetricLogicalToPhysical ---
173 ierr = PetscRandomGetValueReal(*rand_logic_i_ptr, xi_metric_logic_out); CHKERRQ(ierr); // Re-use RNGs
174 ierr = PetscRandomGetValueReal(*rand_logic_j_ptr, eta_metric_logic_out); CHKERRQ(ierr);
175 ierr = PetscRandomGetValueReal(*rand_logic_k_ptr, zta_metric_logic_out); CHKERRQ(ierr);
176
177 // Ensure logical coordinates are strictly within [0,1) for robustness with MetricLogicalToPhysical
178 *xi_metric_logic_out = PetscMin(*xi_metric_logic_out, 1.0 - 1.0e-7);
179 *eta_metric_logic_out = PetscMin(*eta_metric_logic_out, 1.0 - 1.0e-7);
180 *zta_metric_logic_out = PetscMin(*zta_metric_logic_out, 1.0 - 1.0e-7);
181 // Ensure they are not negative either (though [0,1) RNGs shouldn't produce this)
182 *xi_metric_logic_out = PetscMax(*xi_metric_logic_out, 0.0);
183 *eta_metric_logic_out = PetscMax(*eta_metric_logic_out, 0.0);
184 *zta_metric_logic_out = PetscMax(*zta_metric_logic_out, 0.0);
185
186 } else {
187 // This rank does not own any 3D cells (e.g., in a 1D or 2D decomposition,
188 // or if the global domain itself is not 3D in terms of cells).
189 // *can_place_in_volume_out remains PETSC_FALSE.
190 LOG_ALLOW(LOCAL, LOG_WARNING, "Rank %d: Cannot place particle volumetrically. Rank has zero owned cells in at least one dimension (owned cells i,j,k: %d,%d,%d).\n",
191 rank_for_logging, num_owned_cells_on_rank_i, num_owned_cells_on_rank_j, num_owned_cells_on_rank_k);
192 }
193
195 PetscFunctionReturn(0);
196}
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
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...
Definition setup.c:1883
Here is the call graph for this function:
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

Internal helper implementation: InitializeParticleBasicProperties().

Local to this translation unit.

Definition at line 205 of file ParticleSwarm.c.

211{
212 PetscErrorCode ierr;
213 (void)bboxlist;
214 DM swarm = user->swarm;
215 PetscReal *positions_field = NULL; // Pointer to swarm field for physical positions (x,y,z)
216 PetscInt64 *particleIDs = NULL; // Pointer to swarm field for Particle IDs
217 PetscInt *cellIDs_petsc = NULL; // Pointer to swarm field for DMSwarm_CellID (i,j,k of containing cell)
218 PetscInt *status_field = NULL; // Pointer to swarm field for DMSwarm_location_status(NEEDS_LOCATION etc)
219 PetscMPIInt rank,size; // MPI rank of the current process, and total number of ranks.
220 const Cmpnts ***coor_nodes_local_array; // Read-only access to local node coordinates (from user->da)
221 Vec Coor_local; // Local vector for node coordinates
222 DMDALocalInfo info; // Local grid information (node-based) from user->da
223 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank; // Local starting node indices (incl. ghosts) of rank's DA patch
224 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global; // Global node counts in each direction
225
226 // Variables for surface initialization (Mode 0)
227 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
228
229 PetscFunctionBeginUser;
230
232
233 SimCtx *simCtx = user->simCtx;
234
235 // --- 1. Input Validation and Basic Setup ---
236 if (!user || !rand_logic_i || !rand_logic_j || !rand_logic_k) {
237 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null user or RNG pointer.");
238 }
239 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
240 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
241
242 // Get DMDA information for the node-centered coordinate grid (user->da)
243 ierr = DMGetCoordinatesLocal(user->da, &Coor_local); CHKERRQ(ierr);
244 if (!Coor_local) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMGetCoordinatesLocal for user->da returned NULL Coor_local.");
245 ierr = DMDAVecGetArrayRead(user->fda, Coor_local, (void*)&coor_nodes_local_array); CHKERRQ(ierr);
246 ierr = DMDAGetLocalInfo(user->da, &info); CHKERRQ(ierr);
247 ierr = DMDAGetCorners(user->da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
248 ierr = DMDAGetInfo(user->da, NULL, &IM_nodes_global, &JM_nodes_global, &KM_nodes_global, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); CHKERRQ(ierr);
249
250 // Modification to IM_nodes_global etc. to account for 1-cell halo in each direction.
251 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
252
253 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
254 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
255 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
256
257 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Initializing %d particles. Mode: %s.\n",
258 rank, particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
259
260 // --- 2. Pre-computation for Surface Initialization (PARTICLE_INIT_SURFACE_RANDOM and PARTICLE_INIT_SURFACE_EDGES) ---
262 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
263 ierr = CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
264 if (can_this_rank_service_inlet) {
265 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Will attempt to place particles on inlet face %s.\n", rank, BCFaceToString((BCFace)user->identifiedInletBCFace));
266 } else {
267 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);
268 }
269 }
270
271 // --- 3. Get Access to Swarm Fields ---
272 ierr = DMSwarmGetField(swarm, "position", NULL, NULL, (void**)&positions_field); CHKERRQ(ierr);
273 ierr = DMSwarmGetField(swarm, "DMSwarm_pid", NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
274 ierr = DMSwarmGetField(swarm, "DMSwarm_CellID", NULL, NULL, (void**)&cellIDs_petsc); CHKERRQ(ierr);
275 ierr = DMSwarmGetField(swarm, "DMSwarm_location_status",NULL,NULL,(void**)&status_field); CHKERRQ(ierr);
276
277 // --- 4. Determine Starting Global PID for this Rank ---
278 PetscInt particles_per_rank_ideal = simCtx->np / size; // Assumes user->size is PETSC_COMM_WORLD size
279 PetscInt remainder_particles = simCtx->np % size;
280 PetscInt base_pid_for_rank = rank * particles_per_rank_ideal + PetscMin(rank, remainder_particles);
281 // This calculation must match how particlesPerProcess was determined (e.g., in DistributeParticles).
282
283 // --- 5. Loop Over Particles to Initialize ---
284 for (PetscInt p = 0; p < particlesPerProcess; p++) {
285 PetscInt idx = p;
286 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
287 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
288 Cmpnts phys_coords = {0.0, 0.0, 0.0};
289 PetscBool particle_placed_by_this_rank = PETSC_FALSE;
290
291 if (simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_RANDOM) { // --- 5.a. Surface Random Initialization ---
292 if (can_this_rank_service_inlet) {
293 ierr = GetRandomCellAndLogicalCoordsOnInletFace(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
294 IM_nodes_global, JM_nodes_global, KM_nodes_global,
295 rand_logic_i, rand_logic_j, rand_logic_k,
296 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
297 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
298 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
299 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
300 xi_metric_logic, eta_metric_logic, zta_metric_logic,
301 &phys_coords); CHKERRQ(ierr);
302 particle_placed_by_this_rank = PETSC_TRUE;
303 }else{
304 // Rank cannot service inlet - place at inlet center to be migrated later
305 phys_coords.x = user->simCtx->CMx_c;
306 phys_coords.y = user->simCtx->CMy_c;
307 phys_coords.z = user->simCtx->CMz_c;
308 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
309 }
310 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // --- 5.a1. Surface Edges Initialization (deterministic) ---
311 if(can_this_rank_service_inlet) {
312 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
313 ierr = GetDeterministicFaceGridLocation(user,&info,xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
314 IM_cells_global, JM_cells_global, KM_cells_global,
315 particle_global_id,
316 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
317 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
318 &particle_placed_by_this_rank); CHKERRQ(ierr);
319 if(particle_placed_by_this_rank){
320 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
321 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
322 xi_metric_logic, eta_metric_logic, zta_metric_logic,
323 &phys_coords); CHKERRQ(ierr);
324 }else{
325 // Even if rank can service face, it may not own the portion of the face that a particle is placed in.
326 phys_coords.x = user->simCtx->CMx_c;
327 phys_coords.y = user->simCtx->CMy_c;
328 phys_coords.z = user->simCtx->CMz_c;
329 }
330 }else{
331 // Rank cannot service inlet - place at inlet center to be migrated later
332 phys_coords.x = user->simCtx->CMx_c;
333 phys_coords.y = user->simCtx->CMy_c;
334 phys_coords.z = user->simCtx->CMz_c;
335 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
336 }
337 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_VOLUME){ // --- 5.b. Volumetric Initialization ---
338 PetscBool can_place_volumetrically = PETSC_FALSE;
339 ierr = DetermineVolumetricInitializationParameters(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
340 rand_logic_i, rand_logic_j, rand_logic_k,
341 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
342 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
343 &can_place_volumetrically); CHKERRQ(ierr);
344 if(can_place_volumetrically){
345 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
346 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
347 xi_metric_logic, eta_metric_logic, zta_metric_logic,
348 &phys_coords); CHKERRQ(ierr);
349 particle_placed_by_this_rank = PETSC_TRUE;
350 } else {
352 "Rank %d: PID %lld (idx %ld) (Volumetric Mode) - DetermineVolumetric... returned false. Default Phys: (%.2f,%.2f,%.2f).\n",
353 rank, (long long)(base_pid_for_rank + p), (long)p, phys_coords.x, phys_coords.y, phys_coords.z);
354 }
355 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_POINT_SOURCE){ // --- 5.c. Point Source Initialization ---
356 // All particles placed at the user-specified fixed point (psrc_x, psrc_y, psrc_z).
357 // No random number generation or logical-to-physical conversion needed.
358 phys_coords.x = simCtx->psrc_x;
359 phys_coords.y = simCtx->psrc_y;
360 phys_coords.z = simCtx->psrc_z;
361 particle_placed_by_this_rank = PETSC_TRUE;
362 }else {
363 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown ParticleInitialization mode %d.", simCtx->ParticleInitialization);
364 }
365
366 // --- 5.c. Store Particle Properties ---
367 positions_field[3*p+0] = phys_coords.x;
368 positions_field[3*p+1] = phys_coords.y;
369 positions_field[3*p+2] = phys_coords.z;
370
371 particleIDs[p] = (PetscInt64)base_pid_for_rank + p;
372 cellIDs_petsc[3*p+0] = -1; cellIDs_petsc[3*p+1] = -1; cellIDs_petsc[3*p+2] = -1;
373 status_field[p] = UNINITIALIZED;
374
375 // --- 5.d. Logging for this particle ---
376 if (particle_placed_by_this_rank) {
377 LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, idx, user->simCtx->LoggingFrequency,//(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
378 "Rank %d: PID %lld (idx %ld) PLACED. Mode %s. Embedded Cell:(%d,%d,%d). Logical Coords: (%.2e,%.2f,%.2f).\n Final Coords: (%.6f,%.6f,%.6f).\n",
379 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
380 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
381 xi_metric_logic, eta_metric_logic, zta_metric_logic,
382 phys_coords.x, phys_coords.y, phys_coords.z);
383
384 } else {
385 LOG_LOOP_ALLOW(LOCAL, LOG_WARNING, idx, user->simCtx->LoggingFrequency, //(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
386 "Rank %d: PID %lld (idx %ld) Mode %s NOT placed by this rank's logic. Default Coor: (%.2f,%.2f,%.2f). Relies on migration.\n",
387 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
388 phys_coords.x, phys_coords.y, phys_coords.z);
389 }
390 }
391
392 // --- 6. Restore Pointers and Cleanup ---
393 ierr = DMSwarmRestoreField(swarm, "position", NULL, NULL, (void**)&positions_field); CHKERRQ(ierr);
394 ierr = DMSwarmRestoreField(swarm, "DMSwarm_pid", NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
395 ierr = DMSwarmRestoreField(swarm, "DMSwarm_CellID", NULL, NULL, (void**)&cellIDs_petsc); CHKERRQ(ierr);
396 ierr = DMSwarmRestoreField(swarm, "DMSwarm_location_status", NULL, NULL, (void**)&status_field); CHKERRQ(ierr);
397 ierr = DMDAVecRestoreArrayRead(user->fda, Coor_local, (void*)&coor_nodes_local_array); CHKERRQ(ierr);
398
399 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Completed processing for %d particles.\n",
400 rank, particlesPerProcess);
401
403
404 PetscFunctionReturn(0);
405}
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:399
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:11
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:212
PetscErrorCode MetricLogicalToPhysical(UserCtx *user, const Cmpnts ***X, PetscInt i, PetscInt j, PetscInt k, PetscReal xi, PetscReal eta, PetscReal zta, Cmpnts *Xp)
Public interface for MetricLogicalToPhysical().
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)
Internal helper implementation: DetermineVolumetricInitializationParameters().
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt,...)
Logs a message inside a loop, but only every interval iterations.
Definition logging.h:297
const char * BCFaceToString(BCFace face)
Helper function to convert BCFace enum to a string representation.
Definition logging.c:669
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:33
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
Definition logging.c:703
BCFace identifiedInletBCFace
Definition variables.h:831
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:814
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:509
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:512
@ PARTICLE_INIT_POINT_SOURCE
All particles at a fixed (psrc_x,psrc_y,psrc_z) — for validation.
Definition variables.h:511
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
Definition variables.h:510
@ UNINITIALIZED
Definition variables.h:140
PetscReal CMy_c
Definition variables.h:705
PetscReal psrc_x
Definition variables.h:706
PetscInt np
Definition variables.h:739
PetscScalar x
Definition variables.h:101
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
Definition variables.h:706
PetscReal CMz_c
Definition variables.h:705
ParticleInitializationType ParticleInitialization
Definition variables.h:743
PetscScalar z
Definition variables.h:101
PetscReal psrc_y
Definition variables.h:706
PetscScalar y
Definition variables.h:101
PetscInt LoggingFrequency
Definition variables.h:769
PetscReal CMx_c
Definition variables.h:705
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:244
A 3D point or vector with PetscScalar components.
Definition variables.h:100
The master context for the entire simulation.
Definition variables.h:643
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

Internal helper implementation: InitializeSwarmFieldValue().

Local to this translation unit.

Definition at line 413 of file ParticleSwarm.c.

414{
415 PetscFunctionBeginUser;
416
418
419 if (strcmp(fieldName, "velocity") == 0) {
420 // For velocity, initialize all components to zero
421 for (PetscInt d = 0; d < fieldDim; d++) {
422 fieldData[fieldDim * p + d] = 0.0;
423 }
424 } else if (strcmp(fieldName, "Diffusivity") == 0) {
425 // For Diffusivity,initialize to a default value (e.g., 1.0)
426 for (PetscInt d = 0; d < fieldDim; d++) {
427 fieldData[fieldDim * p + d] = 1.0;
428 }
429 } else if (strcmp(fieldName, "DiffusivityGradient") == 0) {
430 // For DiffusivityGradient,initialize to a default value (e.g., 1.0)
431 for (PetscInt d = 0; d < fieldDim; d++) {
432 fieldData[fieldDim * p + d] = 1.0;
433 }
434 } else if (strcmp(fieldName, "Psi") == 0) {
435 for (PetscInt d = 0; d < fieldDim; d++) {
436 fieldData[fieldDim * p + d] = 0.0;
437 }
438 } else {
439 // Default: initialize all components to zero
440 for (PetscInt d = 0; d < fieldDim; d++) {
441 fieldData[fieldDim * p + d] = 0.0;
442 }
443 }
444
446 PetscFunctionReturn(0);
447}
Here is the caller graph for this function:

◆ AssignInitialFieldToSwarm()

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

Internal helper implementation: AssignInitialFieldToSwarm().

Local to this translation unit.

Definition at line 456 of file ParticleSwarm.c.

457{
458 PetscErrorCode ierr;
459 DM swarm = user->swarm;
460 PetscReal *fieldData = NULL;
461 PetscInt nLocal;
462
463 PetscFunctionBeginUser;
464
466
467 // Get the number of local particles
468 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
469 LOG_ALLOW(LOCAL,LOG_INFO, "%d local particles found.\n", nLocal);
470
471 // Retrieve the swarm field pointer for the specified fieldName
472 ierr = DMSwarmGetField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
473 LOG_ALLOW(LOCAL,LOG_DEBUG, "Retrieved field '%s'.\n", fieldName);
474
475 // Loop over all particles and update the field using the helper function
476 for (PetscInt p = 0; p < nLocal; p++) {
477 ierr = InitializeSwarmFieldValue(fieldName, p, fieldDim, fieldData); CHKERRQ(ierr);
478 PetscReal disp_data[fieldDim];
479
480 for (PetscInt d = 0; d < fieldDim; d++) {
481 disp_data[d] = fieldData[fieldDim* p + d];
482 }
483 LOG_LOOP_ALLOW(LOCAL,LOG_VERBOSE,p, 100," Particle %d: %s[%d] = [%.6f, ...,%.6f].\n", p,fieldName,fieldDim,disp_data[0],disp_data[fieldDim-1]);
484 }
485
486 // Restore the swarm field pointer
487 ierr = DMSwarmRestoreField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
488 LOG_ALLOW(LOCAL,LOG_INFO, "Initialization of field '%s' complete.\n", fieldName);
489
490
492
493 PetscFunctionReturn(0);
494}
static PetscErrorCode InitializeSwarmFieldValue(const char *fieldName, PetscInt p, PetscInt fieldDim, PetscReal *fieldData)
Internal helper implementation: InitializeSwarmFieldValue().
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 
)

Internal helper implementation: AssignInitialPropertiesToSwarm().

Initializes all particle properties in the swarm.

Local to this translation unit.

Definition at line 503 of file ParticleSwarm.c.

512{
513 PetscErrorCode ierr;
514 PetscFunctionBeginUser;
515
517
518 SimCtx *simCtx = user->simCtx;
519
520 // --- 0. Input Validation ---
521 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
522 // Check all RNGs now as they are passed in
523 LOG_ALLOW(GLOBAL, LOG_ERROR, "Null user, bboxlist, or RNG pointer.\n");
524 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input detected.");
525 }
526
527 LOG_ALLOW(GLOBAL, LOG_INFO, "Initializing swarm with %d particles per process. Mode: %s.\n",
528 particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
529
530 // --- 1. Parse BCS File for Inlet Information (if surface initialization) ---
532 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
533 if(user->inletFaceDefined == PETSC_FALSE){
534 LOG_ALLOW(GLOBAL, LOG_ERROR, "Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
535 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
536 }else{
537 LOG_ALLOW(GLOBAL, LOG_INFO, "After Parsing BCS file for Inlet, Inlet face = %s\n", BCFaceToString((BCFace)user->identifiedInletBCFace));
538 }
539 }
540
541 // --- 2. Initialize Basic Particle Properties (Position, PID, Cell IDs placeholder) ---
542 // The rand_logic_i/j/k are now passed directly.
543 // The rand_phys_x/y/z are passed but InitializeParticleBasicProperties (refactored version)
544 // will not use them for setting positions if all its paths use logical-to-physical mapping.
545 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Calling InitializeParticleBasicProperties.\n");
546 ierr = InitializeParticleBasicProperties(user, particlesPerProcess,
547 rand_logic_i, rand_logic_j, rand_logic_k,
548 bboxlist); // bboxlist passed along
549 CHKERRQ(ierr);
550 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully initialized basic particle properties.\n");
551
552 // Note: The logical RNGs (rand_logic_i/j/k) are NOT destroyed here.
553 // They were created externally (e.g., by InitializeLogicalSpaceRNGs) and
554 // should be destroyed externally (e.g., in FinalizeSwarmSetup).
555 // Same for rand_phys_x/y/z.
556
557 // --- 3. Initialize Other Swarm Fields (Velocity, Weight, Pressure, etc.) ---
558 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'velocity' field.\n");
559 ierr = AssignInitialFieldToSwarm(user, "velocity", 3); CHKERRQ(ierr);
560 LOG_ALLOW(LOCAL, LOG_INFO, "'velocity' field initialization complete.\n");
561
562 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'weight' field.\n");
563 ierr = AssignInitialFieldToSwarm(user, "weight", 3); CHKERRQ(ierr); // Assuming weight is vec3
564 LOG_ALLOW(LOCAL, LOG_INFO, "'weight' field initialization complete.\n");
565
566 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Diffusivity' field.\n");
567 ierr = AssignInitialFieldToSwarm(user, "Diffusivity", 1); CHKERRQ(ierr);
568 LOG_ALLOW(GLOBAL, LOG_INFO, "'Diffusivity' field initialization complete.\n");
569
570 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'DiffusivityGradient' field.\n");
571 ierr = AssignInitialFieldToSwarm(user, "DiffusivityGradient", 3); CHKERRQ(ierr);
572 LOG_ALLOW(GLOBAL, LOG_INFO, "'DiffusivityGradient' field initialization complete.\n");
573
574 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Psi' (Scalar) field.\n");
575 ierr = AssignInitialFieldToSwarm(user, "Psi", 1); CHKERRQ(ierr);
576 LOG_ALLOW(GLOBAL, LOG_INFO, "'P' field initialization complete.\n");
577
578 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully completed all swarm property initialization.\n");
579
580
582
583 PetscFunctionReturn(0);
584}
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, const char *fieldName, PetscInt fieldDim)
Internal helper implementation: AssignInitialFieldToSwarm().
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Internal helper implementation: InitializeParticleBasicProperties().
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:28
PetscBool inletFaceDefined
Definition variables.h:830
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 
)

Implementation of DistributeParticles().

Distributes particles evenly across MPI processes, handling any remainders.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
DistributeParticles()

Definition at line 595 of file ParticleSwarm.c.

595 {
596
597 PetscFunctionBeginUser;
598
600 // Calculate the base number of particles per process
601 *particlesPerProcess = numParticles / size;
602 *remainder = numParticles % size;
603
604 // Distribute the remainder particles to the first 'remainder' ranks
605 if (rank < *remainder) {
606 *particlesPerProcess += 1;
607 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO,"Rank %d receives an extra particle. Total: %d\n", rank, *particlesPerProcess);
608 } else {
609 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO, "Rank %d receives %d particles.\n", rank, *particlesPerProcess);
610 }
611
613 PetscFunctionReturn(0);
614}
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
Definition logging.h:252
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 
)

Implementation of FinalizeSwarmSetup().

Finalizes the swarm setup by destroying random generators and logging completion.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
FinalizeSwarmSetup()

Definition at line 625 of file ParticleSwarm.c.

625 {
626 PetscErrorCode ierr; // Error code for PETSc functions
627 PetscFunctionBeginUser;
629 // Destroy random number generators to free resources
630 // Physical space
631 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
632 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
633 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
634 // Logical space
635 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
636 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
637 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
638
639 LOG_ALLOW(LOCAL,LOG_DEBUG,"Destroyed all random number generators.\n");
640
642 PetscFunctionReturn(0);
643}
Here is the caller graph for this function:

◆ CreateParticleSwarm()

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

Internal helper implementation: CreateParticleSwarm().

Creates and initializes a Particle Swarm.

Local to this translation unit.

Definition at line 651 of file ParticleSwarm.c.

651 {
652 PetscErrorCode ierr; // PETSc error handling variable
653 (void)bboxlist;
654 PetscMPIInt rank, size; // Variables to store MPI rank and size
655 PetscInt remainder = 0; // Remainder of particles after division
656
657 PetscFunctionBeginUser;
659 // Validate input parameters
660 if (numParticles <= 0) {
661 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Number of particles must be positive. Given: %d\n", numParticles);
662 return PETSC_ERR_ARG_OUTOFRANGE;
663 }
664
665 // Retrieve MPI rank and size
666 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
667 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
668 LOG_ALLOW(GLOBAL,LOG_INFO," Domain dimensions: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
669 user->Min_X,user->Max_X,user->Min_Y,user->Max_Y, user->Min_Z,user->Max_Z);
670 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG, "[Rank %d] Local Bounding Box: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
671 rank,user->bbox.min_coords.x,user->bbox.max_coords.x,
672 user->bbox.min_coords.y,user->bbox.max_coords.y,
673 user->bbox.min_coords.z,user->bbox.max_coords.z);
674 // Distribute particles among MPI processes
675 ierr = DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
676
677 // Initialize the DMSwarm - creates the swarm, sets the type and dimension
678 ierr = InitializeSwarm(user); CHKERRQ(ierr);
679
680 if (user->da) {
681 ierr = DMSwarmSetCellDM(user->swarm, user->da); CHKERRQ(ierr);
682 LOG_ALLOW(LOCAL,LOG_INFO,"Associated DMSwarm with Cell DM (user->da).\n");
683 } else {
684 // If user->da is essential for your simulation logic with particles, this should be a fatal error.
685 LOG_ALLOW(GLOBAL, LOG_WARNING, "user->da (Cell DM for Swarm) is NULL. Cell-based swarm operations might fail.\n");
686 // SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "user->da (Cell DM) is NULL but required.");
687 }
688
689 // Register particle fields (position, velocity, CellID, weight, etc.)
690 ierr = RegisterParticleFields(user->swarm); CHKERRQ(ierr);
691
692 // Set the local number of particles for this rank and additional buffer for particle migration
693 ierr = DMSwarmSetLocalSizes(user->swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
694 LOG_ALLOW(GLOBAL,LOG_INFO, "Set local swarm size: %d particles.\n", *particlesPerProcess);
695
696 // Optionally, LOG_ALLOW detailed DM info in debug mode
697 if (get_log_level() == LOG_DEBUG && is_function_allowed(__func__)) {
698 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Viewing DMSwarm:\n");
699 ierr = DMView(user->swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
700 }
701
702 LOG_ALLOW(GLOBAL,LOG_INFO, "Particle swarm creation and initialization complete.\n");
703
705 PetscFunctionReturn(0);
706}
PetscErrorCode DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
Implementation of DistributeParticles().
PetscErrorCode InitializeSwarm(UserCtx *user)
Implementation of InitializeSwarm().
PetscErrorCode RegisterParticleFields(DM swarm)
Implementation of RegisterParticleFields().
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:183
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:84
PetscReal Min_X
Definition variables.h:821
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:156
PetscReal Max_Y
Definition variables.h:821
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:155
PetscReal Min_Z
Definition variables.h:821
PetscReal Max_X
Definition variables.h:821
PetscReal Min_Y
Definition variables.h:821
BoundingBox bbox
Definition variables.h:822
PetscReal Max_Z
Definition variables.h:821
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,
PetscReal *  diffusivity,
Cmpnts diffusivitygradient,
PetscReal *  psi,
Particle particle 
)

Implementation of UnpackSwarmFields().

Initializes a Particle struct with data from DMSwarm fields.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
UnpackSwarmFields()

Definition at line 722 of file ParticleSwarm.c.

724 {
725 PetscFunctionBeginUser;
726
728
729 PetscMPIInt rank;
730 PetscErrorCode ierr;
731
732 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
733
734 if (particle == NULL) {
735 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output Particle pointer is NULL. \n");
736 }
737
738 // logging the start of particle initialization
739 LOG_ALLOW(LOCAL,LOG_DEBUG, "[Rank %d]Unpacking Particle [%d] with PID: %ld.\n",rank, i, PIDs[i]);
740
741 // Initialize PID
742 if(PIDs == NULL){
743 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input PIDs pointer is NULL.\n");
744 }
745 particle->PID = PIDs[i];
746 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] PID set to: %ld.\n", rank,i, particle->PID);
747
748 // Initialize weights
749 if(weights == NULL){
750 particle->weights.x = 1.0;
751 particle->weights.y = 1.0;
752 particle->weights.z = 1.0;
753 LOG_ALLOW(LOCAL,LOG_WARNING, "[Rank %d]Particle [%d] weights pointer is NULL. Defaulting weights to (1.0, 1.0, 1.0).\n", rank,i);
754 }else{
755 particle->weights.x = weights[3 * i];
756 particle->weights.y = weights[3 * i + 1];
757 particle->weights.z = weights[3 * i + 2];
758 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] weights set to: (%.6f, %.6f, %.6f).\n",
759 rank,i, particle->weights.x, particle->weights.y, particle->weights.z);
760 }
761 // Initialize locations
762 if(positions == NULL){
763 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input positions pointer is NULL.\n");
764 }
765 particle->loc.x = positions[3 * i];
766 particle->loc.y = positions[3 * i + 1];
767 particle->loc.z = positions[3 * i + 2];
768 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] location set to: (%.6f, %.6f, %.6f).\n",
769 rank,i, particle->loc.x, particle->loc.y, particle->loc.z);
770
771 // Initialize velocities (assuming default zero; modify if necessary)
772 if(velocities == NULL){
773 particle->vel.x = 0.0;
774 particle->vel.y = 0.0;
775 particle->vel.z = 0.0;
776 LOG_ALLOW(LOCAL,LOG_WARNING, "[Rank %d]Particle [%d] velocities pointer is NULL. Defaulting velocities to (0.0, 0.0, 0.0).\n", rank,i);
777 }else{
778 particle->vel.x = velocities[3 * i];
779 particle->vel.y = velocities[3 * i + 1];
780 particle->vel.z = velocities[3 * i + 2];
781 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);
782 }
783
784 // Initialize diffusivity
785 if(diffusivity == NULL){
786 particle->diffusivity = 1.0; // Default diffusivity
787 }else{
788 particle->diffusivity = diffusivity[i];
789 }
790 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] diffusivity set to: %.6f.\n",rank,i, particle->diffusivity);
791
792 // Initialize diffusivity gradient
793 if(diffusivitygradient == NULL){
794 particle->diffusivitygradient.x = 0.0;
795 particle->diffusivitygradient.y = 0.0;
796 particle->diffusivitygradient.z = 0.0;
797 LOG_ALLOW(LOCAL,LOG_WARNING, "[Rank %d]Particle [%d] diffusivity gradient pointer is NULL. Defaulting to (0.0, 0.0, 0.0).\n", rank,i);
798 }else{
799 particle->diffusivitygradient.x = diffusivitygradient[i].x;
800 particle->diffusivitygradient.y = diffusivitygradient[i].y;
801 particle->diffusivitygradient.z = diffusivitygradient[i].z;
802 }
803 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] diffusivity gradient set to: (%.6f, %.6f, %.6f).\n", rank,i,particle->diffusivitygradient.x,particle->diffusivitygradient.y,particle->diffusivitygradient.z);
804
805 // Initialize psi
806 if(psi == NULL){
807 particle->psi = 0.0; // Default psi
808 }else{
809 particle->psi = psi[i];
810 }
811 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] psi set to: %.6f.\n",rank,i, particle->psi);
812
813 // Initialize cell indices
814 if(cellIndices == NULL){
815 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input cellIndices pointer is NULL.\n");
816 }
817 particle->cell[0] = cellIndices[3 * i];
818 particle->cell[1] = cellIndices[3 * i + 1];
819 particle->cell[2] = cellIndices[3 * i + 2];
820 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]);
821
822 if(LocStatus == NULL){
823 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input LocStatus pointer is NULL.\n");
824 }
825 // Initialize location status
826 particle->location_status = (ParticleLocationStatus)LocStatus[i];
827 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] Status set to: %d.\n",rank, i, particle->location_status);
828
829 // The destination_rank is only set by the location search, not read from the swarm,
830 // so we initialize it to a known invalid state.
831 particle->destination_rank = MPI_PROC_NULL;
832
833 // logging the completion of particle initialization
834 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d]Completed initialization of Particle [%d]. \n", rank,i);
835
836
838
839 PetscFunctionReturn(0);
840}
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 diffusivitygradient
Definition variables.h:174
Cmpnts loc
Definition variables.h:168
PetscMPIInt destination_rank
Definition variables.h:172
ParticleLocationStatus location_status
Definition variables.h:171
PetscReal diffusivity
Definition variables.h:173
PetscReal psi
Definition variables.h:175
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 *  positions,
PetscReal *  velocities,
PetscReal *  weights,
PetscInt *  cellIndices,
PetscInt *  status,
PetscReal *  diffusivity,
Cmpnts diffusivitygradient,
PetscReal *  psi 
)

Internal helper implementation: UpdateSwarmFields().

Updates DMSwarm data arrays from a Particle struct.

Local to this translation unit.

Definition at line 848 of file ParticleSwarm.c.

857{
858 PetscFunctionBeginUser;
860
861 if (!particle) {
862 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input Particle pointer is NULL.\n");
863 }
864
865 // --- 1. Position (x, y, z) ---
866 if (positions) {
867 positions[3 * i + 0] = particle->loc.x;
868 positions[3 * i + 1] = particle->loc.y;
869 positions[3 * i + 2] = particle->loc.z;
870 }
871
872 // --- 2. Velocity (u, v, w) ---
873 if (velocities) {
874 velocities[3 * i + 0] = particle->vel.x;
875 velocities[3 * i + 1] = particle->vel.y;
876 velocities[3 * i + 2] = particle->vel.z;
877 }
878
879 // --- 3. Weights (i, j, k) ---
880 if (weights) {
881 weights[3 * i + 0] = particle->weights.x;
882 weights[3 * i + 1] = particle->weights.y;
883 weights[3 * i + 2] = particle->weights.z;
884 }
885
886 // --- 4. Cell Indices (i, j, k) ---
887 if (cellIndices) {
888 cellIndices[3 * i + 0] = particle->cell[0];
889 cellIndices[3 * i + 1] = particle->cell[1];
890 cellIndices[3 * i + 2] = particle->cell[2];
891 }
892
893 // --- 5. Status ---
894 if (status) {
895 status[i] = (PetscInt)particle->location_status;
896 }
897
898 // --- 6. Diffusivity ---
899 if (diffusivity) {
900 diffusivity[i] = particle->diffusivity;
901 }
902
903 if(diffusivitygradient){
904 diffusivitygradient[i].x = particle->diffusivitygradient.x;
905 diffusivitygradient[i].y = particle->diffusivitygradient.y;
906 diffusivitygradient[i].z = particle->diffusivitygradient.z;
907 }
908 // --- 7. Psi ---
909 if (psi) {
910 psi[i] = particle->psi;
911 }
912
913 // LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, i, 1000, "Updated fields for Particle [%d].\n", i);
914
916 PetscFunctionReturn(0);
917}
Here is the caller graph for this function:

◆ IsParticleInsideBoundingBox()

PetscBool IsParticleInsideBoundingBox ( const BoundingBox bbox,
const Particle particle 
)

Internal helper implementation: IsParticleInsideBoundingBox().

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

Local to this translation unit.

Definition at line 925 of file ParticleSwarm.c.

926{
927 PetscFunctionBeginUser;
929
930 // Validate input pointers
931 if (!bbox) {
932 // LOG_ALLOW error message and return PETSC_FALSE
933 LOG_ALLOW(LOCAL,LOG_ERROR, "Error - 'bbox' pointer is NULL.");
935 return PETSC_FALSE;
936 }
937 if (!particle) {
938 LOG_ALLOW(LOCAL,LOG_ERROR,"Error - 'particle' pointer is NULL.");
940 return PETSC_FALSE;
941 }
942
943 // Extract particle location and bounding box coordinates
944 const Cmpnts loc = particle->loc;
945 const Cmpnts min_coords = bbox->min_coords;
946 const Cmpnts max_coords = bbox->max_coords;
947
948 // LOG_ALLOW the particle location and bounding box coordinates for debugging
949 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "Particle PID %ld location: (%.6f, %.6f, %.6f).\n",particle->PID, loc.x, loc.y, loc.z);
950 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "BoundingBox min_coords: (%.6f, %.6f, %.6f), max_coords: (%.6f, %.6f, %.6f).\n",
951 min_coords.x, min_coords.y, min_coords.z, max_coords.x, max_coords.y, max_coords.z);
952
953 // Check if the particle's location is within the bounding box
954 if ((loc.x >= min_coords.x && loc.x <= max_coords.x) &&
955 (loc.y >= min_coords.y && loc.y <= max_coords.y) &&
956 (loc.z >= min_coords.z && loc.z <= max_coords.z)) {
957 // Particle is inside the bounding box
958 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "Particle PID %ld is inside the bounding box.\n",particle->PID);
960 return PETSC_TRUE;
961 }
962
963 // Particle is outside the bounding box
964 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE,"Particle PID %ld is outside the bounding box.\n",particle->PID);
966 return PETSC_FALSE;
967}
Here is the caller graph for this function:

◆ UpdateParticleWeights()

PetscErrorCode UpdateParticleWeights ( PetscReal *  d,
Particle particle 
)

Internal helper implementation: UpdateParticleWeights().

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

Local to this translation unit.

Definition at line 976 of file ParticleSwarm.c.

976 {
977
978 PetscFunctionBeginUser;
980
981 // Validate input pointers
982 if (!d || !particle) {
983 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
984 "Null pointer argument (d or particle).");
985 }
986
987
988 // Validate distances
989 for (PetscInt i = LEFT; i < NUM_FACES; i++) {
992 "face distance d[%d] = %f <= %f; "
993 "clamping to 1e-14 to avoid zero/negative.\n",
994 i, (double)d[i], INTERPOLATION_DISTANCE_TOLERANCE);
996 }
997 }
998
999 // LOG_ALLOW the input distances
1001 "Calculating weights with distances: "
1002 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
1003 d[LEFT], d[RIGHT], d[BOTTOM], d[TOP], d[FRONT], d[BACK]);
1004
1005 // Compute and update the particle's weights
1006 particle->weights.x = d[LEFT] / (d[LEFT] + d[RIGHT]);
1007 particle->weights.y = d[BOTTOM] / (d[BOTTOM] + d[TOP]);
1008 particle->weights.z = d[BACK] / (d[FRONT] + d[BACK]);
1009
1010 // LOG_ALLOW the updated weights
1012 "Updated particle weights: x=%f, y=%f, z=%f.\n",
1013 particle->weights.x, particle->weights.y, particle->weights.z);
1014
1015
1017 PetscFunctionReturn(0);
1018}
#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)

Implementation of InitializeParticleSwarm().

High-level particle initialization orchestrator for a simulation run.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/ParticleSwarm.h.

See also
InitializeParticleSwarm()

Definition at line 1049 of file ParticleSwarm.c.

1050{
1051 PetscErrorCode ierr;
1052 PetscInt particlesPerProcess = 0;
1053 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1054
1055 PetscFunctionBeginUser;
1057
1058 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting particle swarm setup for %d particles.\n", simCtx->np);
1059
1060 // --- Phase 1: Create the DMSwarm Object (Always required) ---
1061 // This creates the container and registers the fields. It does not add particles yet.
1062 ierr = CreateParticleSwarm(user, simCtx->np, &particlesPerProcess, simCtx->bboxlist); CHKERRQ(ierr);
1063 LOG_ALLOW(GLOBAL, LOG_INFO, "DMSwarm object and fields created successfully.\n");
1064
1065
1066 // --- Phase 2: Decide whether to Initialize new particles or Load existing ones ---
1067 PetscBool should_initialize_new_particles = PETSC_FALSE;
1068 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1069 should_initialize_new_particles = PETSC_TRUE;
1070 }else{
1071 if (simCtx->StartStep == 0) {
1072 should_initialize_new_particles = PETSC_TRUE; // Standard fresh start
1073 } else {
1074 // It's a restart, so check the user's requested particle mode.
1075 if (strcmp(simCtx->particleRestartMode, "init") == 0) {
1076 should_initialize_new_particles = PETSC_TRUE; // User wants to re-initialize particles in a restarted flow.
1077 }
1078 }
1079 }
1080
1081 // --- Phase 3: Execute the chosen particle setup path ---
1082 if (should_initialize_new_particles) {
1083 // --- PATH A: Generate a fresh population of particles ---
1084 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: INITIALIZE. Generating new particle population.\n");
1085 PetscRandom randx, randy, randz;
1086 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1087
1088 ierr = InitializeRandomGenerators(user, &randx, &randy, &randz); CHKERRQ(ierr);
1089 ierr = InitializeLogicalSpaceRNGs(&rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1090 ierr = AssignInitialPropertiesToSwarm(user, particlesPerProcess, &randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k, simCtx->bboxlist); CHKERRQ(ierr);
1091 ierr = FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1092
1093 } else {
1094 // --- PATH B: Load particle population from restart files ---
1095 // This path is only taken if simCtx->StartStep > 0 AND simCtx->particleRestartMode == "load"
1096 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: LOAD. Loading particle population from files for step %d.\n", simCtx->StartStep);
1097
1098 ierr = PreCheckAndResizeSwarm(user, simCtx->StartStep, "dat"); CHKERRQ(ierr);
1099
1100 ierr = ReadAllSwarmFields(user, simCtx->StartStep); CHKERRQ(ierr);
1101 // Note: We check for file-open errors inside ReadAllSwarmFields now.
1102
1103 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle data loaded. CellID and status are preserved from file.\n");
1104 }
1105
1106 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Particle swarm setup complete.\n");
1107
1109 PetscFunctionReturn(0);
1110}
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)
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 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().
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Reads multiple fields (positions, velocity, CellID, and weight) into a DMSwarm.
Definition io.c:1383
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
Definition setup.c:2684
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:2725
UserCtx * user
Definition variables.h:528
UserMG usermg
Definition variables.h:764
PetscInt StartStep
Definition variables.h:653
char particleRestartMode[16]
Definition variables.h:745
BoundingBox * bboxlist
Definition variables.h:742
PetscInt mglevels
Definition variables.h:535
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:617
MGCtx * mgctx
Definition variables.h:538
ExecutionMode exec_mode
Definition variables.h:662
User-defined context containing data specific to a single computational grid level.
Definition variables.h:811
Here is the call graph for this function:
Here is the caller graph for this function: