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__   "DistributeParticlesByOwnedCells"
 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)
 Derive particle counts and spacing for volumetric swarm initialization.
 
static PetscErrorCode InitializeParticleBasicProperties (UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
 Initialize position-independent particle fields after a particle is created.
 
static PetscErrorCode InitializeSwarmFieldValue (const ParticleFieldDescriptor *descriptor, PetscInt p, PetscReal *fieldData)
 Assign one configured initial value to a swarm field entry.
 
static PetscErrorCode AssignInitialFieldToSwarm (UserCtx *user, ParticleFieldId field_id)
 Apply a configured initial field specification across the local swarm.
 
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().
 
static PetscErrorCode DistributeParticlesByOwnedCells (UserCtx *user, PetscInt numParticles, PetscInt *localCount)
 Split particles across ranks in proportion to the cells each rank owns.
 
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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#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/17]

#define __FUNCT__   "DistributeParticlesByOwnedCells"

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/17]

#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__ [13/17]

#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__ [14/17]

#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__ [15/17]

#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__ [16/17]

#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__ [17/17]

#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:45
#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:200
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:894
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:885
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:32
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 for (PetscInt raw_id = 0; raw_id < PARTICLE_FIELD_ID_COUNT; ++raw_id) {
67 const ParticleFieldDescriptor *descriptor = NULL;
68
69 ierr = ParticleFieldGetDescriptor((ParticleFieldId)raw_id, &descriptor); CHKERRQ(ierr);
70 if (descriptor->registration == PARTICLE_FIELD_REGISTRATION_PETSC) continue;
71
72 ierr = RegisterSwarmField(swarm, descriptor->canonical_name,
73 descriptor->components, descriptor->data_type); CHKERRQ(ierr);
74 }
75
76 // Finalize the field registration after all fields have been added
77 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
78 LOG_ALLOW(LOCAL,LOG_INFO,"RegisterParticleFields - Finalized field registration.\n");
79
80 PetscFunctionReturn(0);
81}
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Internal helper implementation: RegisterSwarmField().
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_COUNT
ParticleFieldRegistration registration
@ PARTICLE_FIELD_REGISTRATION_PETSC
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
Immutable metadata for one persistent particle field.
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

Derive particle counts and spacing for volumetric swarm initialization.

Definition at line 88 of file ParticleSwarm.c.

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

Initialize position-independent particle fields after a particle is created.

Definition at line 188 of file ParticleSwarm.c.

194{
195 PetscErrorCode ierr;
196 (void)bboxlist;
197 DM swarm = user->swarm;
198 PetscReal *positions_field = NULL; // Pointer to swarm field for physical positions (x,y,z)
199 PetscInt64 *particleIDs = NULL; // Pointer to swarm field for Particle IDs
200 PetscInt *cellIDs_petsc = NULL; // Pointer to swarm field for DMSwarm_CellID (i,j,k of containing cell)
201 PetscInt *status_field = NULL; // Pointer to swarm field for DMSwarm_location_status(NEEDS_LOCATION etc)
202 PetscMPIInt rank,size; // MPI rank of the current process, and total number of ranks.
203 const Cmpnts ***coor_nodes_local_array; // Read-only access to local node coordinates (from user->da)
204 Vec Coor_local; // Local vector for node coordinates
205 DMDALocalInfo info; // Local grid information (node-based) from user->da
206 PetscInt xs_gnode_rank, ys_gnode_rank, zs_gnode_rank; // Local starting node indices (incl. ghosts) of rank's DA patch
207 PetscInt IM_nodes_global, JM_nodes_global, KM_nodes_global; // Global node counts in each direction
208
209 // Variables for surface initialization (Mode 0)
210 PetscBool can_this_rank_service_inlet = PETSC_FALSE;
211
212 PetscFunctionBeginUser;
213
215
216 SimCtx *simCtx = user->simCtx;
217
218 // --- 1. Input Validation and Basic Setup ---
219 if (!user || !rand_logic_i || !rand_logic_j || !rand_logic_k) {
220 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null user or RNG pointer.");
221 }
222 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
223 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size); CHKERRQ(ierr);
224
225 // Get DMDA information for the node-centered coordinate grid (user->da)
226 ierr = DMGetCoordinatesLocal(user->da, &Coor_local); CHKERRQ(ierr);
227 if (!Coor_local) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMGetCoordinatesLocal for user->da returned NULL Coor_local.");
228 ierr = DMDAVecGetArrayRead(user->fda, Coor_local, (void*)&coor_nodes_local_array); CHKERRQ(ierr);
229 ierr = DMDAGetLocalInfo(user->da, &info); CHKERRQ(ierr);
230 ierr = DMDAGetCorners(user->da, &xs_gnode_rank, &ys_gnode_rank, &zs_gnode_rank, NULL, NULL, NULL); CHKERRQ(ierr);
231 ierr = DMDAGetInfo(user->da, NULL, &IM_nodes_global, &JM_nodes_global, &KM_nodes_global, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); CHKERRQ(ierr);
232
233 // Modification to IM_nodes_global etc. to account for 1-cell halo in each direction.
234 IM_nodes_global -= 1; JM_nodes_global -= 1; KM_nodes_global -= 1;
235
236 const PetscInt IM_cells_global = IM_nodes_global > 0 ? IM_nodes_global - 1 : 0;
237 const PetscInt JM_cells_global = JM_nodes_global > 0 ? JM_nodes_global - 1 : 0;
238 const PetscInt KM_cells_global = KM_nodes_global > 0 ? KM_nodes_global - 1 : 0;
239
240 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Initializing %d particles. Mode: %s.\n",
241 rank, particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
242
243 // --- 2. Pre-computation for Surface Initialization (PARTICLE_INIT_SURFACE_RANDOM and PARTICLE_INIT_SURFACE_EDGES) ---
245 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
246 ierr = CanRankServiceInletFace(user, &info, IM_nodes_global, JM_nodes_global, KM_nodes_global, &can_this_rank_service_inlet); CHKERRQ(ierr);
247 if (can_this_rank_service_inlet) {
248 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Will attempt to place particles on inlet face %s.\n", rank, BCFaceToString((BCFace)user->identifiedInletBCFace));
249 } else {
250 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);
251 }
252 }
253
254 // --- 3. Get Access to Swarm Fields ---
255 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void**)&positions_field); CHKERRQ(ierr);
256 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
257 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void**)&cellIDs_petsc); CHKERRQ(ierr);
258 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_LOCATION_STATUS),NULL,NULL,(void**)&status_field); CHKERRQ(ierr);
259
260 // --- 4. Determine Starting Global PID for this Rank ---
261 // PIDs are consecutive across ranks in rank order, so each rank starts where the ranks
262 // before it end. Taking that from the actual local counts keeps it right however the
263 // particles were split (evenly, or by owned cells for volumetric seeding).
264 PetscInt base_pid_for_rank = 0;
265 {
266 PetscInt local_count = particlesPerProcess;
267 ierr = MPI_Exscan(&local_count, &base_pid_for_rank, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
268 if (rank == 0) base_pid_for_rank = 0; /* MPI_Exscan leaves rank 0's result undefined */
269 }
270
271 // --- 5. Loop Over Particles to Initialize ---
272 for (PetscInt p = 0; p < particlesPerProcess; p++) {
273 PetscInt idx = p;
274 PetscInt ci_metric_lnode, cj_metric_lnode, ck_metric_lnode;
275 PetscReal xi_metric_logic, eta_metric_logic, zta_metric_logic;
276 Cmpnts phys_coords = {0.0, 0.0, 0.0};
277 PetscBool particle_placed_by_this_rank = PETSC_FALSE;
278
279 if (simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_RANDOM) { // --- 5.a. Surface Random Initialization ---
280 if (can_this_rank_service_inlet) {
281 ierr = GetRandomCellAndLogicalCoordsOnInletFace(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
282 IM_nodes_global, JM_nodes_global, KM_nodes_global,
283 rand_logic_i, rand_logic_j, rand_logic_k,
284 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
285 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic); CHKERRQ(ierr);
286 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
287 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
288 xi_metric_logic, eta_metric_logic, zta_metric_logic,
289 &phys_coords); CHKERRQ(ierr);
290 particle_placed_by_this_rank = PETSC_TRUE;
291 }else{
292 // Rank cannot service inlet - place at inlet center to be migrated later
293 phys_coords.x = user->simCtx->CMx_c;
294 phys_coords.y = user->simCtx->CMy_c;
295 phys_coords.z = user->simCtx->CMz_c;
296 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
297 }
298 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // --- 5.a1. Surface Edges Initialization (deterministic) ---
299 if(can_this_rank_service_inlet) {
300 PetscInt64 particle_global_id = (PetscInt64)(base_pid_for_rank + p);
301 ierr = GetDeterministicFaceGridLocation(user,&info,xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
302 IM_cells_global, JM_cells_global, KM_cells_global,
303 particle_global_id,
304 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
305 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
306 &particle_placed_by_this_rank); CHKERRQ(ierr);
307 if(particle_placed_by_this_rank){
308 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
309 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
310 xi_metric_logic, eta_metric_logic, zta_metric_logic,
311 &phys_coords); CHKERRQ(ierr);
312 }else{
313 // Even if rank can service face, it may not own the portion of the face that a particle is placed in.
314 phys_coords.x = user->simCtx->CMx_c;
315 phys_coords.y = user->simCtx->CMy_c;
316 phys_coords.z = user->simCtx->CMz_c;
317 }
318 }else{
319 // Rank cannot service inlet - place at inlet center to be migrated later
320 phys_coords.x = user->simCtx->CMx_c;
321 phys_coords.y = user->simCtx->CMy_c;
322 phys_coords.z = user->simCtx->CMz_c;
323 particle_placed_by_this_rank = PETSC_FALSE; // Relies on migration
324 }
325 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_VOLUME){ // --- 5.b. Volumetric Initialization ---
326 PetscBool can_place_volumetrically = PETSC_FALSE;
327 ierr = DetermineVolumetricInitializationParameters(user, &info, xs_gnode_rank, ys_gnode_rank, zs_gnode_rank,
328 rand_logic_i, rand_logic_j, rand_logic_k,
329 &ci_metric_lnode, &cj_metric_lnode, &ck_metric_lnode,
330 &xi_metric_logic, &eta_metric_logic, &zta_metric_logic,
331 &can_place_volumetrically); CHKERRQ(ierr);
332 if(can_place_volumetrically){
333 ierr = MetricLogicalToPhysical(user, coor_nodes_local_array,
334 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
335 xi_metric_logic, eta_metric_logic, zta_metric_logic,
336 &phys_coords); CHKERRQ(ierr);
337 particle_placed_by_this_rank = PETSC_TRUE;
338 } else {
340 "Rank %d: PID %lld (idx %ld) (Volumetric Mode) - DetermineVolumetric... returned false. Default Phys: (%.2f,%.2f,%.2f).\n",
341 rank, (long long)(base_pid_for_rank + p), (long)p, phys_coords.x, phys_coords.y, phys_coords.z);
342 }
343 }else if(simCtx->ParticleInitialization == PARTICLE_INIT_POINT_SOURCE){ // --- 5.c. Point Source Initialization ---
344 // All particles placed at the user-specified fixed point (psrc_x, psrc_y, psrc_z).
345 // No random number generation or logical-to-physical conversion needed.
346 phys_coords.x = simCtx->psrc_x;
347 phys_coords.y = simCtx->psrc_y;
348 phys_coords.z = simCtx->psrc_z;
349 particle_placed_by_this_rank = PETSC_TRUE;
350 }else {
351 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown ParticleInitialization mode %d.", simCtx->ParticleInitialization);
352 }
353
354 // --- 5.c. Store Particle Properties ---
355 positions_field[3*p+0] = phys_coords.x;
356 positions_field[3*p+1] = phys_coords.y;
357 positions_field[3*p+2] = phys_coords.z;
358
359 particleIDs[p] = (PetscInt64)base_pid_for_rank + p;
360 cellIDs_petsc[3*p+0] = -1; cellIDs_petsc[3*p+1] = -1; cellIDs_petsc[3*p+2] = -1;
361 status_field[p] = UNINITIALIZED;
362
363 // --- 5.d. Logging for this particle ---
364 if (particle_placed_by_this_rank) {
365 LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, idx, user->simCtx->LoggingFrequency,//(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
366 "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",
367 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
368 ci_metric_lnode, cj_metric_lnode, ck_metric_lnode,
369 xi_metric_logic, eta_metric_logic, zta_metric_logic,
370 phys_coords.x, phys_coords.y, phys_coords.z);
371
372 } else {
373 LOG_LOOP_ALLOW(LOCAL, LOG_WARNING, idx, user->simCtx->LoggingFrequency, //(particlesPerProcess > 20 ? particlesPerProcess/10 : 1),
374 "Rank %d: PID %lld (idx %ld) Mode %s NOT placed by this rank's logic. Default Coor: (%.2f,%.2f,%.2f). Relies on migration.\n",
375 rank, (long long)particleIDs[p], (long)p, ParticleInitializationToString(simCtx->ParticleInitialization),
376 phys_coords.x, phys_coords.y, phys_coords.z);
377 }
378 }
379
380 // --- 6. Restore Pointers and Cleanup ---
381 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void**)&positions_field); CHKERRQ(ierr);
382 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
383 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void**)&cellIDs_petsc); CHKERRQ(ierr);
384 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_LOCATION_STATUS), NULL, NULL, (void**)&status_field); CHKERRQ(ierr);
385 ierr = DMDAVecRestoreArrayRead(user->fda, Coor_local, (void*)&coor_nodes_local_array); CHKERRQ(ierr);
386
387 LOG_ALLOW(LOCAL, LOG_INFO, "Rank %d: Completed processing for %d particles.\n",
388 rank, particlesPerProcess);
389
391
392 PetscFunctionReturn(0);
393}
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:400
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:213
PetscErrorCode MetricLogicalToPhysical(UserCtx *user, const Cmpnts ***X, PetscInt i, PetscInt j, PetscInt k, PetscReal xi, PetscReal eta, PetscReal zta, Cmpnts *Xp)
Maps a logical point inside one hexahedral cell to physical space.
Definition Metric.c:76
static PetscErrorCode DetermineVolumetricInitializationParameters(UserCtx *user, DMDALocalInfo *info, PetscInt xs_gnode, PetscInt ys_gnode, PetscInt zs_gnode, PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr, PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out, PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out, PetscBool *can_place_in_volume_out)
Derive particle counts and spacing for volumetric swarm initialization.
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt,...)
Logs a message inside a loop, but only every interval iterations.
Definition logging.h:298
const char * BCFaceToString(BCFace face)
Returns the canonical log token for a boundary-face enum value.
Definition logging.c:671
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Returns the canonical log token for a particle-initialization mode.
Definition logging.c:724
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_LOCATION_STATUS
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_PID
@ PARTICLE_FIELD_ID_CELL_ID
BCFace identifiedInletBCFace
Definition variables.h:1101
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:710
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:713
@ PARTICLE_INIT_POINT_SOURCE
All particles at a fixed (psrc_x,psrc_y,psrc_z) — for validation.
Definition variables.h:712
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
Definition variables.h:711
@ UNINITIALIZED
Definition variables.h:168
PetscReal CMy_c
Definition variables.h:944
PetscReal psrc_x
Definition variables.h:945
PetscScalar x
Definition variables.h:122
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
Definition variables.h:945
PetscReal CMz_c
Definition variables.h:944
ParticleInitializationType ParticleInitialization
Definition variables.h:994
PetscScalar z
Definition variables.h:122
PetscReal psrc_y
Definition variables.h:945
PetscScalar y
Definition variables.h:122
PetscInt LoggingFrequency
Definition variables.h:1020
PetscReal CMx_c
Definition variables.h:944
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:287
A 3D point or vector with PetscScalar components.
Definition variables.h:121
The master context for the entire simulation.
Definition variables.h:859
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitializeSwarmFieldValue()

static PetscErrorCode InitializeSwarmFieldValue ( const ParticleFieldDescriptor *  descriptor,
PetscInt  p,
PetscReal *  fieldData 
)
static

Assign one configured initial value to a swarm field entry.

Definition at line 400 of file ParticleSwarm.c.

402{
403 PetscFunctionBeginUser;
404
406
407 PetscCheck(descriptor != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
408 "Particle field descriptor cannot be NULL during initialization.");
409 PetscCheck(fieldData != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
410 "Particle field data cannot be NULL during initialization.");
411 PetscCheck(descriptor->data_type == PETSC_REAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
412 "Default initialization currently supports only PETSC_REAL particle fields; '%s' uses %s.",
413 descriptor->canonical_name, PetscDataTypes[descriptor->data_type]);
414 PetscCheck((descriptor->capabilities & PARTICLE_FIELD_CAPABILITY_DEFAULT_INITIALIZE) != 0,
415 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
416 "Particle field '%s' does not use catalog-default initialization.",
417 descriptor->canonical_name);
418
419 for (PetscInt d = 0; d < descriptor->components; ++d) {
420 fieldData[descriptor->components * p + d] = descriptor->default_real_value;
421 }
422
424 PetscFunctionReturn(0);
425}
@ PARTICLE_FIELD_CAPABILITY_DEFAULT_INITIALIZE
Here is the caller graph for this function:

◆ AssignInitialFieldToSwarm()

static PetscErrorCode AssignInitialFieldToSwarm ( UserCtx *  user,
ParticleFieldId  field_id 
)
static

Apply a configured initial field specification across the local swarm.

Definition at line 433 of file ParticleSwarm.c.

434{
435 PetscErrorCode ierr;
436 DM swarm = user->swarm;
437 PetscReal *fieldData = NULL;
438 PetscInt nLocal;
439 const ParticleFieldDescriptor *descriptor = NULL;
440 const char *fieldName = NULL;
441
442 PetscFunctionBeginUser;
443
445
446 ierr = ParticleFieldGetDescriptor(field_id, &descriptor); CHKERRQ(ierr);
447 fieldName = descriptor->canonical_name;
448
449 // Get the number of local particles
450 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
451 LOG_ALLOW(LOCAL,LOG_INFO, "%d local particles found.\n", nLocal);
452
453 // Retrieve the swarm field pointer for the specified fieldName
454 ierr = DMSwarmGetField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
455 LOG_ALLOW(LOCAL,LOG_DEBUG, "Retrieved field '%s'.\n", fieldName);
456
457 // Loop over all particles and update the field using the helper function
458 for (PetscInt p = 0; p < nLocal; p++) {
459 ierr = InitializeSwarmFieldValue(descriptor, p, fieldData); CHKERRQ(ierr);
460 PetscReal disp_data[descriptor->components];
461
462 for (PetscInt d = 0; d < descriptor->components; d++) {
463 disp_data[d] = fieldData[descriptor->components * p + d];
464 }
465 LOG_LOOP_ALLOW(LOCAL,LOG_VERBOSE,p, 100," Particle %d: %s[%d] = [%.6f, ...,%.6f].\n", p,fieldName,descriptor->components,disp_data[0],disp_data[descriptor->components-1]);
466 }
467
468 // Restore the swarm field pointer
469 ierr = DMSwarmRestoreField(swarm, fieldName, NULL, NULL, (void**)&fieldData); CHKERRQ(ierr);
470 LOG_ALLOW(LOCAL,LOG_INFO, "Initialization of field '%s' complete.\n", fieldName);
471
472
474
475 PetscFunctionReturn(0);
476}
static PetscErrorCode InitializeSwarmFieldValue(const ParticleFieldDescriptor *descriptor, PetscInt p, PetscReal *fieldData)
Assign one configured initial value to a swarm field entry.
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 485 of file ParticleSwarm.c.

494{
495 PetscErrorCode ierr;
496 PetscFunctionBeginUser;
497
499
500 SimCtx *simCtx = user->simCtx;
501
502 // --- 0. Input Validation ---
503 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
504 // Check all RNGs now as they are passed in
505 LOG_ALLOW(GLOBAL, LOG_ERROR, "Null user, bboxlist, or RNG pointer.\n");
506 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input detected.");
507 }
508
509 LOG_ALLOW(GLOBAL, LOG_INFO, "Initializing swarm with %d particles per process. Mode: %s.\n",
510 particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
511
512 // --- 1. Parse BCS File for Inlet Information (if surface initialization) ---
514 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
515 if(user->inletFaceDefined == PETSC_FALSE){
516 LOG_ALLOW(GLOBAL, LOG_ERROR, "Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
517 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
518 }else{
519 LOG_ALLOW(GLOBAL, LOG_INFO, "After Parsing BCS file for Inlet, Inlet face = %s\n", BCFaceToString((BCFace)user->identifiedInletBCFace));
520 }
521 }
522
523 // --- 2. Initialize Basic Particle Properties (Position, PID, Cell IDs placeholder) ---
524 // The rand_logic_i/j/k are now passed directly.
525 // The rand_phys_x/y/z are passed but InitializeParticleBasicProperties (refactored version)
526 // will not use them for setting positions if all its paths use logical-to-physical mapping.
527 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Calling InitializeParticleBasicProperties.\n");
528 ierr = InitializeParticleBasicProperties(user, particlesPerProcess,
529 rand_logic_i, rand_logic_j, rand_logic_k,
530 bboxlist); // bboxlist passed along
531 CHKERRQ(ierr);
532 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully initialized basic particle properties.\n");
533
534 // Note: The logical RNGs (rand_logic_i/j/k) are NOT destroyed here.
535 // They were created externally (e.g., by InitializeLogicalSpaceRNGs) and
536 // should be destroyed externally (e.g., in FinalizeSwarmSetup).
537 // Same for rand_phys_x/y/z.
538
539 // --- 3. Initialize Other Swarm Fields (Velocity, Weight, Pressure, etc.) ---
540 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'velocity' field.\n");
541 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_VELOCITY); CHKERRQ(ierr);
542 LOG_ALLOW(LOCAL, LOG_INFO, "'velocity' field initialization complete.\n");
543
544 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'weight' field.\n");
545 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_WEIGHT); CHKERRQ(ierr); // Weight is a three-component field.
546 LOG_ALLOW(LOCAL, LOG_INFO, "'weight' field initialization complete.\n");
547
548 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Diffusivity' field.\n");
549 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_DIFFUSIVITY); CHKERRQ(ierr);
550 LOG_ALLOW(GLOBAL, LOG_INFO, "'Diffusivity' field initialization complete.\n");
551
552 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'DiffusivityGradient' field.\n");
554 LOG_ALLOW(GLOBAL, LOG_INFO, "'DiffusivityGradient' field initialization complete.\n");
555
556 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Psi' (Scalar) field.\n");
557 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_PSI); CHKERRQ(ierr);
558 LOG_ALLOW(GLOBAL, LOG_INFO, "'P' field initialization complete.\n");
559
560 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully completed all swarm property initialization.\n");
561
562
564
565 PetscFunctionReturn(0);
566}
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, ParticleFieldId field_id)
Apply a configured initial field specification across the local swarm.
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initialize position-independent particle fields after a particle is created.
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:29
@ PARTICLE_FIELD_ID_WEIGHT
@ PARTICLE_FIELD_ID_PSI
@ PARTICLE_FIELD_ID_DIFFUSIVITY_GRADIENT
@ PARTICLE_FIELD_ID_DIFFUSIVITY
@ PARTICLE_FIELD_ID_VELOCITY
PetscBool inletFaceDefined
Definition variables.h:1100
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 577 of file ParticleSwarm.c.

577 {
578
579 PetscFunctionBeginUser;
580
582 // Calculate the base number of particles per process
583 *particlesPerProcess = numParticles / size;
584 *remainder = numParticles % size;
585
586 // Distribute the remainder particles to the first 'remainder' ranks
587 if (rank < *remainder) {
588 *particlesPerProcess += 1;
589 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO,"Rank %d receives an extra particle. Total: %d\n", rank, *particlesPerProcess);
590 } else {
591 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO, "Rank %d receives %d particles.\n", rank, *particlesPerProcess);
592 }
593
595 PetscFunctionReturn(0);
596}
#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:253
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 607 of file ParticleSwarm.c.

607 {
608 PetscErrorCode ierr; // Error code for PETSc functions
609 PetscFunctionBeginUser;
611 // Destroy random number generators to free resources
612 // Physical space
613 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
614 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
615 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
616 // Logical space
617 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
618 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
619 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
620
621 LOG_ALLOW(LOCAL,LOG_DEBUG,"Destroyed all random number generators.\n");
622
624 PetscFunctionReturn(0);
625}
Here is the caller graph for this function:

◆ DistributeParticlesByOwnedCells()

static PetscErrorCode DistributeParticlesByOwnedCells ( UserCtx *  user,
PetscInt  numParticles,
PetscInt *  localCount 
)
static

Split particles across ranks in proportion to the cells each rank owns.

Volumetric seeding places each rank's particles uniformly in its own cells, so an even split gives a density that jumps wherever the decomposition gives ranks unequal cell counts. Largest-remainder rounding keeps the total exact, and every rank computes the same answer from the gathered counts.

Parameters
[in]userFinest-level context whose DMDA ownership defines the split.
[in]numParticlesGlobal particle count.
[out]localCountParticles this rank seeds.
Returns
PetscErrorCode 0 on success.

Definition at line 640 of file ParticleSwarm.c.

641{
642 PetscMPIInt rank, size;
643 PetscInt start, ni, nj, nk, owned, total = 0, assigned = 0;
644 PetscInt *cells = NULL, *count = NULL;
645 PetscReal *frac = NULL;
646
647 PetscFunctionBeginUser;
648 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
649 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
650 PetscCall(GetOwnedCellRange(&user->info, 0, &start, &ni));
651 PetscCall(GetOwnedCellRange(&user->info, 1, &start, &nj));
652 PetscCall(GetOwnedCellRange(&user->info, 2, &start, &nk));
653 owned = ni * nj * nk;
654 PetscCall(PetscMalloc3(size, &cells, size, &count, size, &frac));
655 PetscCallMPI(MPI_Allgather(&owned, 1, MPIU_INT, cells, 1, MPIU_INT, PETSC_COMM_WORLD));
656 for (PetscMPIInt r = 0; r < size; ++r) total += cells[r];
657 PetscCheck(total > 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
658 "Volumetric particle seeding found no owned cells on any rank.");
659 for (PetscMPIInt r = 0; r < size; ++r) {
660 const PetscReal share = (PetscReal)numParticles * (PetscReal)cells[r] / (PetscReal)total;
661 count[r] = (PetscInt)PetscFloorReal(share);
662 frac[r] = share - (PetscReal)count[r];
663 assigned += count[r];
664 }
665 for (PetscInt extra = numParticles - assigned; extra > 0; --extra) {
666 PetscMPIInt best = 0;
667 for (PetscMPIInt r = 1; r < size; ++r) if (frac[r] > frac[best]) best = r;
668 count[best] += 1;
669 frac[best] = -1.0;
670 }
671 *localCount = count[rank];
672 PetscCall(PetscFree3(cells, count, frac));
673 PetscFunctionReturn(0);
674}
DMDALocalInfo info
Definition variables.h:1086
Here is the call graph for this function:
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 682 of file ParticleSwarm.c.

682 {
683 PetscErrorCode ierr; // PETSc error handling variable
684 (void)bboxlist;
685 PetscMPIInt rank, size; // Variables to store MPI rank and size
686 PetscInt remainder = 0; // Remainder of particles after division
687
688 PetscFunctionBeginUser;
690 // Validate input parameters
691 if (numParticles <= 0) {
692 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Number of particles must be positive. Given: %d\n", numParticles);
694 return PETSC_ERR_ARG_OUTOFRANGE;
695 }
696
697 // Retrieve MPI rank and size
698 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
699 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
700 LOG_ALLOW(GLOBAL,LOG_INFO," Domain dimensions: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
701 user->Min_X,user->Max_X,user->Min_Y,user->Max_Y, user->Min_Z,user->Max_Z);
702 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG, "[Rank %d] Local Bounding Box: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
703 rank,user->bbox.min_coords.x,user->bbox.max_coords.x,
704 user->bbox.min_coords.y,user->bbox.max_coords.y,
705 user->bbox.min_coords.z,user->bbox.max_coords.z);
706 // Distribute particles among MPI processes
708 ierr = DistributeParticlesByOwnedCells(user, numParticles, particlesPerProcess); CHKERRQ(ierr);
709 } else {
710 ierr = DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
711 }
712
713 // Initialize the DMSwarm - creates the swarm, sets the type and dimension
714 ierr = InitializeSwarm(user); CHKERRQ(ierr);
715
716 if (user->da) {
717 ierr = DMSwarmSetCellDM(user->swarm, user->da); CHKERRQ(ierr);
718 LOG_ALLOW(LOCAL,LOG_INFO,"Associated DMSwarm with Cell DM (user->da).\n");
719 } else {
720 // If user->da is essential for your simulation logic with particles, this should be a fatal error.
721 LOG_ALLOW(GLOBAL, LOG_WARNING, "user->da (Cell DM for Swarm) is NULL. Cell-based swarm operations might fail.\n");
722 // SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "user->da (Cell DM) is NULL but required.");
723 }
724
725 // Register particle fields (position, velocity, CellID, weight, etc.)
726 ierr = RegisterParticleFields(user->swarm); CHKERRQ(ierr);
727
728 // Set the local number of particles for this rank and additional buffer for particle migration
729 ierr = DMSwarmSetLocalSizes(user->swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
730 LOG_ALLOW(GLOBAL,LOG_INFO, "Set local swarm size: %d particles.\n", *particlesPerProcess);
731
732 // Optionally, LOG_ALLOW detailed DM info in debug mode
733 if (get_log_level() == LOG_DEBUG && is_function_allowed(__func__)) {
734 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Viewing DMSwarm:\n");
735 ierr = DMView(user->swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
736 }
737
738 LOG_ALLOW(GLOBAL,LOG_INFO, "Particle swarm creation and initialization complete.\n");
739
741 PetscFunctionReturn(0);
742}
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().
static PetscErrorCode DistributeParticlesByOwnedCells(UserCtx *user, PetscInt numParticles, PetscInt *localCount)
Split particles across ranks in proportion to the cells each rank owns.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:186
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:87
PetscReal Min_X
Definition variables.h:1089
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:199
PetscReal Max_Y
Definition variables.h:1089
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:198
PetscReal Min_Z
Definition variables.h:1089
PetscReal Max_X
Definition variables.h:1089
PetscReal Min_Y
Definition variables.h:1089
BoundingBox bbox
Definition variables.h:1090
PetscReal Max_Z
Definition variables.h:1089
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 758 of file ParticleSwarm.c.

760 {
761 PetscFunctionBeginUser;
762
764
765 PetscMPIInt rank;
766 PetscErrorCode ierr;
767
768 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
769
770 if (particle == NULL) {
771 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output Particle pointer is NULL. \n");
772 }
773
774 // logging the start of particle initialization
775 LOG_ALLOW(LOCAL,LOG_DEBUG, "[Rank %d]Unpacking Particle [%d] with PID: %ld.\n",rank, i, PIDs[i]);
776
777 // Initialize PID
778 if(PIDs == NULL){
779 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input PIDs pointer is NULL.\n");
780 }
781 particle->PID = PIDs[i];
782 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] PID set to: %ld.\n", rank,i, particle->PID);
783
784 // Initialize weights
785 if(weights == NULL){
786 particle->weights.x = 1.0;
787 particle->weights.y = 1.0;
788 particle->weights.z = 1.0;
789 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);
790 }else{
791 particle->weights.x = weights[3 * i];
792 particle->weights.y = weights[3 * i + 1];
793 particle->weights.z = weights[3 * i + 2];
794 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] weights set to: (%.6f, %.6f, %.6f).\n",
795 rank,i, particle->weights.x, particle->weights.y, particle->weights.z);
796 }
797 // Initialize locations
798 if(positions == NULL){
799 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input positions pointer is NULL.\n");
800 }
801 particle->loc.x = positions[3 * i];
802 particle->loc.y = positions[3 * i + 1];
803 particle->loc.z = positions[3 * i + 2];
804 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] location set to: (%.6f, %.6f, %.6f).\n",
805 rank,i, particle->loc.x, particle->loc.y, particle->loc.z);
806
807 // Initialize velocities (assuming default zero; modify if necessary)
808 if(velocities == NULL){
809 particle->vel.x = 0.0;
810 particle->vel.y = 0.0;
811 particle->vel.z = 0.0;
812 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);
813 }else{
814 particle->vel.x = velocities[3 * i];
815 particle->vel.y = velocities[3 * i + 1];
816 particle->vel.z = velocities[3 * i + 2];
817 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);
818 }
819
820 // Initialize diffusivity
821 if(diffusivity == NULL){
822 particle->diffusivity = 1.0; // Default diffusivity
823 }else{
824 particle->diffusivity = diffusivity[i];
825 }
826 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] diffusivity set to: %.6f.\n",rank,i, particle->diffusivity);
827
828 // Initialize diffusivity gradient
829 if(diffusivitygradient == NULL){
830 particle->diffusivitygradient.x = 0.0;
831 particle->diffusivitygradient.y = 0.0;
832 particle->diffusivitygradient.z = 0.0;
833 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);
834 }else{
835 particle->diffusivitygradient.x = diffusivitygradient[i].x;
836 particle->diffusivitygradient.y = diffusivitygradient[i].y;
837 particle->diffusivitygradient.z = diffusivitygradient[i].z;
838 }
839 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);
840
841 // Initialize psi
842 if(psi == NULL){
843 particle->psi = 0.0; // Default psi
844 }else{
845 particle->psi = psi[i];
846 }
847 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] psi set to: %.6f.\n",rank,i, particle->psi);
848
849 // Initialize cell indices
850 if(cellIndices == NULL){
851 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input cellIndices pointer is NULL.\n");
852 }
853 particle->cell[0] = cellIndices[3 * i];
854 particle->cell[1] = cellIndices[3 * i + 1];
855 particle->cell[2] = cellIndices[3 * i + 2];
856 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]);
857
858 if(LocStatus == NULL){
859 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input LocStatus pointer is NULL.\n");
860 }
861 // Initialize location status
862 particle->location_status = (ParticleLocationStatus)LocStatus[i];
863 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] Status set to: %d.\n",rank, i, particle->location_status);
864
865 // The destination_rank is only set by the location search, not read from the swarm,
866 // so we initialize it to a known invalid state.
867 particle->destination_rank = MPI_PROC_NULL;
868
869 // logging the completion of particle initialization
870 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d]Completed initialization of Particle [%d]. \n", rank,i);
871
872
874
875 PetscFunctionReturn(0);
876}
Cmpnts vel
Definition variables.h:212
PetscInt cell[3]
Definition variables.h:210
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Definition variables.h:163
Cmpnts diffusivitygradient
Definition variables.h:217
Cmpnts loc
Definition variables.h:211
PetscMPIInt destination_rank
Definition variables.h:215
ParticleLocationStatus location_status
Definition variables.h:214
PetscReal diffusivity
Definition variables.h:216
PetscReal psi
Definition variables.h:218
Cmpnts weights
Definition variables.h:213
PetscInt64 PID
Definition variables.h:209
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 884 of file ParticleSwarm.c.

893{
894 PetscFunctionBeginUser;
896
897 if (!particle) {
898 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input Particle pointer is NULL.\n");
899 }
900
901 // --- 1. Position (x, y, z) ---
902 if (positions) {
903 positions[3 * i + 0] = particle->loc.x;
904 positions[3 * i + 1] = particle->loc.y;
905 positions[3 * i + 2] = particle->loc.z;
906 }
907
908 // --- 2. Velocity (u, v, w) ---
909 if (velocities) {
910 velocities[3 * i + 0] = particle->vel.x;
911 velocities[3 * i + 1] = particle->vel.y;
912 velocities[3 * i + 2] = particle->vel.z;
913 }
914
915 // --- 3. Weights (i, j, k) ---
916 if (weights) {
917 weights[3 * i + 0] = particle->weights.x;
918 weights[3 * i + 1] = particle->weights.y;
919 weights[3 * i + 2] = particle->weights.z;
920 }
921
922 // --- 4. Cell Indices (i, j, k) ---
923 if (cellIndices) {
924 cellIndices[3 * i + 0] = particle->cell[0];
925 cellIndices[3 * i + 1] = particle->cell[1];
926 cellIndices[3 * i + 2] = particle->cell[2];
927 }
928
929 // --- 5. Status ---
930 if (status) {
931 status[i] = (PetscInt)particle->location_status;
932 }
933
934 // --- 6. Diffusivity ---
935 if (diffusivity) {
936 diffusivity[i] = particle->diffusivity;
937 }
938
939 if(diffusivitygradient){
940 diffusivitygradient[i].x = particle->diffusivitygradient.x;
941 diffusivitygradient[i].y = particle->diffusivitygradient.y;
942 diffusivitygradient[i].z = particle->diffusivitygradient.z;
943 }
944 // --- 7. Psi ---
945 if (psi) {
946 psi[i] = particle->psi;
947 }
948
949 // LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, i, 1000, "Updated fields for Particle [%d].\n", i);
950
952 PetscFunctionReturn(0);
953}
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 961 of file ParticleSwarm.c.

962{
963 PetscFunctionBeginUser;
965
966 // Validate input pointers
967 if (!bbox) {
968 // LOG_ALLOW error message and return PETSC_FALSE
969 LOG_ALLOW(LOCAL,LOG_ERROR, "Error - 'bbox' pointer is NULL.");
971 return PETSC_FALSE;
972 }
973 if (!particle) {
974 LOG_ALLOW(LOCAL,LOG_ERROR,"Error - 'particle' pointer is NULL.");
976 return PETSC_FALSE;
977 }
978
979 // Extract particle location and bounding box coordinates
980 const Cmpnts loc = particle->loc;
981 const Cmpnts min_coords = bbox->min_coords;
982 const Cmpnts max_coords = bbox->max_coords;
983
984 // LOG_ALLOW the particle location and bounding box coordinates for debugging
985 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "Particle PID %ld location: (%.6f, %.6f, %.6f).\n",particle->PID, loc.x, loc.y, loc.z);
986 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "BoundingBox min_coords: (%.6f, %.6f, %.6f), max_coords: (%.6f, %.6f, %.6f).\n",
987 min_coords.x, min_coords.y, min_coords.z, max_coords.x, max_coords.y, max_coords.z);
988
989 // Check if the particle's location is within the bounding box
990 if ((loc.x >= min_coords.x && loc.x <= max_coords.x) &&
991 (loc.y >= min_coords.y && loc.y <= max_coords.y) &&
992 (loc.z >= min_coords.z && loc.z <= max_coords.z)) {
993 // Particle is inside the bounding box
994 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "Particle PID %ld is inside the bounding box.\n",particle->PID);
996 return PETSC_TRUE;
997 }
998
999 // Particle is outside the bounding box
1000 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE,"Particle PID %ld is outside the bounding box.\n",particle->PID);
1002 return PETSC_FALSE;
1003}
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 1012 of file ParticleSwarm.c.

1012 {
1013
1014 PetscFunctionBeginUser;
1016
1017 // Validate input pointers
1018 if (!d || !particle) {
1019 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
1020 "Null pointer argument (d or particle).");
1021 }
1022
1023
1024 // Validate distances
1025 for (PetscInt i = LEFT; i < NUM_FACES; i++) {
1028 "face distance d[%d] = %f <= %f; "
1029 "clamping to 1e-14 to avoid zero/negative.\n",
1030 i, (double)d[i], INTERPOLATION_DISTANCE_TOLERANCE);
1032 }
1033 }
1034
1035 // LOG_ALLOW the input distances
1037 "Calculating weights with distances: "
1038 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
1039 d[LEFT], d[RIGHT], d[BOTTOM], d[TOP], d[FRONT], d[BACK]);
1040
1041 // Compute and update the particle's weights
1042 particle->weights.x = d[LEFT] / (d[LEFT] + d[RIGHT]);
1043 particle->weights.y = d[BOTTOM] / (d[BOTTOM] + d[TOP]);
1044 particle->weights.z = d[BACK] / (d[FRONT] + d[BACK]);
1045
1046 // LOG_ALLOW the updated weights
1048 "Updated particle weights: x=%f, y=%f, z=%f.\n",
1049 particle->weights.x, particle->weights.y, particle->weights.z);
1050
1051
1053 PetscFunctionReturn(0);
1054}
#define INTERPOLATION_DISTANCE_TOLERANCE
@ TOP
Definition variables.h:173
@ FRONT
Definition variables.h:173
@ BOTTOM
Definition variables.h:173
@ BACK
Definition variables.h:173
@ LEFT
Definition variables.h:173
@ NUM_FACES
Definition variables.h:173
@ RIGHT
Definition variables.h:173
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 1085 of file ParticleSwarm.c.

1086{
1087 PetscErrorCode ierr;
1088 PetscInt particlesPerProcess = 0;
1089 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1090
1091 PetscFunctionBeginUser;
1093
1094 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting particle swarm setup for %d particles.\n", simCtx->np);
1095
1096 // --- Phase 1: Create the DMSwarm Object (Always required) ---
1097 // This creates the container and registers the fields. It does not add particles yet.
1098 ierr = CreateParticleSwarm(user, simCtx->np, &particlesPerProcess, simCtx->bboxlist); CHKERRQ(ierr);
1099 LOG_ALLOW(GLOBAL, LOG_INFO, "DMSwarm object and fields created successfully.\n");
1100
1101
1102 // --- Phase 2: Decide whether to Initialize new particles or Load existing ones ---
1103 PetscBool should_initialize_new_particles = PETSC_FALSE;
1104 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1105 should_initialize_new_particles = PETSC_TRUE;
1106 }else{
1107 if (simCtx->StartStep == 0) {
1108 should_initialize_new_particles = PETSC_TRUE; // Standard fresh start
1109 } else {
1110 // It's a restart, so check the user's requested particle mode.
1111 if (strcmp(simCtx->particleRestartMode, "init") == 0) {
1112 should_initialize_new_particles = PETSC_TRUE; // User wants to re-initialize particles in a restarted flow.
1113 }
1114 }
1115 }
1116
1117 // --- Phase 3: Execute the chosen particle setup path ---
1118 if (should_initialize_new_particles) {
1119 // --- PATH A: Generate a fresh population of particles ---
1120 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: INITIALIZE. Generating new particle population.\n");
1121 PetscRandom randx, randy, randz;
1122 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1123
1124 ierr = InitializeRandomGenerators(user, &randx, &randy, &randz); CHKERRQ(ierr);
1125 ierr = InitializeLogicalSpaceRNGs(user->simCtx->particleRandomSeed, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1126 ierr = AssignInitialPropertiesToSwarm(user, particlesPerProcess, &randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k, simCtx->bboxlist); CHKERRQ(ierr);
1127 ierr = FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1128
1129 } else {
1130 // --- PATH B: Load particle population from restart files ---
1131 // This path is only taken if simCtx->StartStep > 0 AND simCtx->particleRestartMode == "load"
1132 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: LOAD. Loading particle population from files for step %d.\n", simCtx->StartStep);
1133
1134 ierr = PreCheckAndResizeSwarm(user, simCtx->StartStep, "dat"); CHKERRQ(ierr);
1135
1136 ierr = ReadAllSwarmFields(user, simCtx->StartStep); CHKERRQ(ierr);
1137 // Note: We check for file-open errors inside ReadAllSwarmFields now.
1138
1139 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle data loaded. CellID and status are preserved from file.\n");
1140 }
1141
1142 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Particle swarm setup complete.\n");
1143
1145 PetscFunctionReturn(0);
1146}
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:1883
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
Definition setup.c:3851
PetscErrorCode InitializeLogicalSpaceRNGs(PetscInt base_seed, 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:3895
UserCtx * user
Definition variables.h:729
UserMG usermg
Definition variables.h:1015
PetscInt np
Definition variables.h:990
PetscInt StartStep
Definition variables.h:869
char particleRestartMode[16]
Definition variables.h:996
BoundingBox * bboxlist
Definition variables.h:993
PetscInt mglevels
Definition variables.h:736
PetscInt particleRandomSeed
Base seed for every particle RNG stream (-particle_random_seed).
Definition variables.h:991
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:833
MGCtx * mgctx
Definition variables.h:739
ExecutionMode exec_mode
Definition variables.h:878
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
Here is the call graph for this function:
Here is the caller graph for this function: