PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
ParticleSwarm.h File Reference

Header file for Particle Swarm management functions. More...

#include <petsc.h>
#include <petscdmswarm.h>
#include <stdbool.h>
#include <math.h>
#include "variables.h"
#include "logging.h"
#include "walkingsearch.h"
#include "Metric.h"
#include "io.h"
Include dependency graph for ParticleSwarm.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

PetscErrorCode CreateParticleSwarm (UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
 Creates and initializes a Particle Swarm.
 
PetscErrorCode InitializeSwarm (UserCtx *user)
 Initializes the DMSwarm object within the UserCtx structure.
 
PetscErrorCode RegisterSwarmField (DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
 Registers a swarm field without finalizing registration.
 
PetscErrorCode RegisterParticleFields (DM swarm)
 Registers necessary particle fields within the DMSwarm.
 
PetscErrorCode AssignInitialPropertiesToSwarm (UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_phys_x, PetscRandom *rand_phys_y, PetscRandom *rand_phys_z, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
 Initializes all particle properties in the swarm.
 
PetscErrorCode DistributeParticles (PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
 Distributes particles evenly across MPI processes, handling any remainders.
 
PetscErrorCode FinalizeSwarmSetup (PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
 Finalizes the swarm setup by destroying random generators and logging completion.
 
PetscErrorCode 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)
 Initializes a Particle struct with data from DMSwarm fields.
 
PetscErrorCode UpdateSwarmFields (PetscInt i, const Particle *particle, PetscReal *positions, PetscReal *velocities, PetscReal *weights, PetscInt *cellIndices, PetscInt *status, PetscReal *diffusivity, Cmpnts *diffusivitygradient, PetscReal *psi)
 Updates DMSwarm data arrays from a Particle struct.
 
PetscBool IsParticleInsideBoundingBox (const BoundingBox *bbox, const Particle *particle)
 Checks if a particle's location is within a specified bounding box.
 
PetscErrorCode UpdateParticleWeights (PetscReal *d, Particle *particle)
 Updates a particle's interpolation weights based on distances to cell faces.
 
PetscErrorCode InitializeParticleSwarm (SimCtx *simCtx)
 Perform particle swarm initialization, particle-grid interaction, and related operations.
 

Detailed Description

Header file for Particle Swarm management functions.

This file contains declarations of functions responsible for creating, managing, initializing, migrating, and printing particle swarms within a simulation using PETSc's DMSwarm.

Definition in file ParticleSwarm.h.

Function Documentation

◆ CreateParticleSwarm()

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

Creates and initializes a Particle Swarm.

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

Additionally, it now takes a 'bboxlist' array as an input parameter and passes it on to AssignInitialProperties(), enabling particle initialization at the midpoint of each rank's bounding box if ParticleInitialization is set to 0.

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

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

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

Definition at line 796 of file ParticleSwarm.c.

796 {
797 PetscErrorCode ierr; // PETSc error handling variable
798 PetscMPIInt rank, size; // Variables to store MPI rank and size
799 PetscInt remainder = 0; // Remainder of particles after division
800
801 PetscFunctionBeginUser;
803 // Validate input parameters
804 if (numParticles <= 0) {
805 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Number of particles must be positive. Given: %d\n", numParticles);
806 return PETSC_ERR_ARG_OUTOFRANGE;
807 }
808
809 // Retrieve MPI rank and size
810 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
811 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
812 LOG_ALLOW(GLOBAL,LOG_INFO," Domain dimensions: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
813 user->Min_X,user->Max_X,user->Min_Y,user->Max_Y, user->Min_Z,user->Max_Z);
814 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG, "[Rank %d] Local Bounding Box: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
815 rank,user->bbox.min_coords.x,user->bbox.max_coords.x,
816 user->bbox.min_coords.y,user->bbox.max_coords.y,
817 user->bbox.min_coords.z,user->bbox.max_coords.z);
818 // Distribute particles among MPI processes
819 ierr = DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
820
821 // Initialize the DMSwarm - creates the swarm, sets the type and dimension
822 ierr = InitializeSwarm(user); CHKERRQ(ierr);
823
824 if (user->da) {
825 ierr = DMSwarmSetCellDM(user->swarm, user->da); CHKERRQ(ierr);
826 LOG_ALLOW(LOCAL,LOG_INFO,"Associated DMSwarm with Cell DM (user->da).\n");
827 } else {
828 // If user->da is essential for your simulation logic with particles, this should be a fatal error.
829 LOG_ALLOW(GLOBAL, LOG_WARNING, "user->da (Cell DM for Swarm) is NULL. Cell-based swarm operations might fail.\n");
830 // SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "user->da (Cell DM) is NULL but required.");
831 }
832
833 // Register particle fields (position, velocity, CellID, weight, etc.)
834 ierr = RegisterParticleFields(user->swarm); CHKERRQ(ierr);
835
836 // Set the local number of particles for this rank and additional buffer for particle migration
837 ierr = DMSwarmSetLocalSizes(user->swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
838 LOG_ALLOW(GLOBAL,LOG_INFO, "Set local swarm size: %d particles.\n", *particlesPerProcess);
839
840 // Optionally, LOG_ALLOW detailed DM info in debug mode
841 if (get_log_level() == LOG_DEBUG && is_function_allowed(__func__)) {
842 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Viewing DMSwarm:\n");
843 ierr = DMView(user->swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
844 }
845
846 LOG_ALLOW(GLOBAL,LOG_INFO, "Particle swarm creation and initialization complete.\n");
847
849 PetscFunctionReturn(0);
850}
PetscErrorCode DistributeParticles(PetscInt numParticles, PetscMPIInt rank, PetscMPIInt size, PetscInt *particlesPerProcess, PetscInt *remainder)
Distributes particles evenly across MPI processes, handling any remainders.
PetscErrorCode InitializeSwarm(UserCtx *user)
Initializes the DMSwarm object within the UserCtx structure.
PetscErrorCode RegisterParticleFields(DM swarm)
Registers necessary particle fields within the DMSwarm.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:157
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level,...
Definition logging.h:267
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:746
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:39
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:737
PetscReal Min_X
Definition variables.h:738
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:156
PetscReal Max_Y
Definition variables.h:738
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:155
PetscScalar x
Definition variables.h:101
PetscScalar z
Definition variables.h:101
PetscReal Min_Z
Definition variables.h:738
PetscReal Max_X
Definition variables.h:738
PetscReal Min_Y
Definition variables.h:738
PetscScalar y
Definition variables.h:101
BoundingBox bbox
Definition variables.h:739
PetscReal Max_Z
Definition variables.h:738
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitializeSwarm()

PetscErrorCode InitializeSwarm ( UserCtx user)

Initializes the DMSwarm object within the UserCtx structure.

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

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

Definition at line 18 of file ParticleSwarm.c.

18 {
19 PetscErrorCode ierr; // Error code for PETSc functions
20
21 PetscFunctionBeginUser;
23 // Create the DMSwarm object for particle management
24 ierr = DMCreate(PETSC_COMM_WORLD, &user->swarm); CHKERRQ(ierr);
25 ierr = DMSetType(user->swarm, DMSWARM); CHKERRQ(ierr);
26 ierr = DMSetDimension(user->swarm, 3); CHKERRQ(ierr);
27 ierr = DMSwarmSetType(user->swarm, DMSWARM_BASIC); CHKERRQ(ierr);
28 LOG_ALLOW(LOCAL,LOG_INFO, "DMSwarm created and configured.\n");
29
31 PetscFunctionReturn(0);
32}
Here is the caller graph for this function:

◆ RegisterSwarmField()

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

Registers a swarm field without finalizing registration.

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

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

Definition at line 50 of file ParticleSwarm.c.

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

◆ RegisterParticleFields()

PetscErrorCode RegisterParticleFields ( DM  swarm)

Registers necessary particle fields within the DMSwarm.

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

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

Definition at line 76 of file ParticleSwarm.c.

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

◆ AssignInitialPropertiesToSwarm()

PetscErrorCode AssignInitialPropertiesToSwarm ( UserCtx user,
PetscInt  particlesPerProcess,
PetscRandom *  rand_phys_x,
PetscRandom *  rand_phys_y,
PetscRandom *  rand_phys_z,
PetscRandom *  rand_logic_i,
PetscRandom *  rand_logic_j,
PetscRandom *  rand_logic_k,
BoundingBox bboxlist 
)

Initializes all particle properties in the swarm.

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

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

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

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

Definition at line 614 of file ParticleSwarm.c.

623{
624 PetscErrorCode ierr;
625 PetscFunctionBeginUser;
626
628
629 SimCtx *simCtx = user->simCtx;
630
631 // --- 0. Input Validation ---
632 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
633 // Check all RNGs now as they are passed in
634 LOG_ALLOW(GLOBAL, LOG_ERROR, "Null user, bboxlist, or RNG pointer.\n");
635 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input detected.");
636 }
637
638 LOG_ALLOW(GLOBAL, LOG_INFO, "Initializing swarm with %d particles per process. Mode: %s.\n",
639 particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
640
641 // --- 1. Parse BCS File for Inlet Information (if surface initialization) ---
643 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
644 if(user->inletFaceDefined == PETSC_FALSE){
645 LOG_ALLOW(GLOBAL, LOG_ERROR, "Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
646 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
647 }else{
648 LOG_ALLOW(GLOBAL, LOG_INFO, "After Parsing BCS file for Inlet, Inlet face = %s\n", BCFaceToString((BCFace)user->identifiedInletBCFace));
649 }
650 }
651
652 // --- 2. Initialize Basic Particle Properties (Position, PID, Cell IDs placeholder) ---
653 // The rand_logic_i/j/k are now passed directly.
654 // The rand_phys_x/y/z are passed but InitializeParticleBasicProperties (refactored version)
655 // will not use them for setting positions if all its paths use logical-to-physical mapping.
656 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Calling InitializeParticleBasicProperties.\n");
657 ierr = InitializeParticleBasicProperties(user, particlesPerProcess,
658 rand_logic_i, rand_logic_j, rand_logic_k,
659 bboxlist); // bboxlist passed along
660 CHKERRQ(ierr);
661 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully initialized basic particle properties.\n");
662
663 // Note: The logical RNGs (rand_logic_i/j/k) are NOT destroyed here.
664 // They were created externally (e.g., by InitializeLogicalSpaceRNGs) and
665 // should be destroyed externally (e.g., in FinalizeSwarmSetup).
666 // Same for rand_phys_x/y/z.
667
668 // --- 3. Initialize Other Swarm Fields (Velocity, Weight, Pressure, etc.) ---
669 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'velocity' field.\n");
670 ierr = AssignInitialFieldToSwarm(user, "velocity", 3); CHKERRQ(ierr);
671 LOG_ALLOW(LOCAL, LOG_INFO, "'velocity' field initialization complete.\n");
672
673 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'weight' field.\n");
674 ierr = AssignInitialFieldToSwarm(user, "weight", 3); CHKERRQ(ierr); // Assuming weight is vec3
675 LOG_ALLOW(LOCAL, LOG_INFO, "'weight' field initialization complete.\n");
676
677 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Diffusivity' field.\n");
678 ierr = AssignInitialFieldToSwarm(user, "Diffusivity", 1); CHKERRQ(ierr);
679 LOG_ALLOW(GLOBAL, LOG_INFO, "'Diffusivity' field initialization complete.\n");
680
681 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'DiffusivityGradient' field.\n");
682 ierr = AssignInitialFieldToSwarm(user, "DiffusivityGradient", 3); CHKERRQ(ierr);
683 LOG_ALLOW(GLOBAL, LOG_INFO, "'DiffusivityGradient' field initialization complete.\n");
684
685 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Psi' (Scalar) field.\n");
686 ierr = AssignInitialFieldToSwarm(user, "Psi", 1); CHKERRQ(ierr);
687 LOG_ALLOW(GLOBAL, LOG_INFO, "'P' field initialization complete.\n");
688
689 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully completed all swarm property initialization.\n");
690
691
693
694 PetscFunctionReturn(0);
695}
static PetscErrorCode AssignInitialFieldToSwarm(UserCtx *user, const char *fieldName, PetscInt fieldDim)
Initializes a generic swarm field with point-level updates.
static PetscErrorCode InitializeParticleBasicProperties(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initializes basic properties for particles on the local process.
const char * BCFaceToString(BCFace face)
Helper function to convert BCFace enum to a string representation.
Definition logging.c:643
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:28
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
Definition logging.c:675
PetscBool inletFaceDefined
Definition variables.h:747
BCFace identifiedInletBCFace
Definition variables.h:748
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:731
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:466
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:469
ParticleInitializationType ParticleInitialization
Definition variables.h:680
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:203
The master context for the entire simulation.
Definition variables.h:585
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DistributeParticles()

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

Distributes particles evenly across MPI processes, handling any remainders.

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

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

Definition at line 714 of file ParticleSwarm.c.

714 {
715
716 PetscFunctionBeginUser;
717
719 // Calculate the base number of particles per process
720 *particlesPerProcess = numParticles / size;
721 *remainder = numParticles % size;
722
723 // Distribute the remainder particles to the first 'remainder' ranks
724 if (rank < *remainder) {
725 *particlesPerProcess += 1;
726 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO,"Rank %d receives an extra particle. Total: %d\n", rank, *particlesPerProcess);
727 } else {
728 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO, "Rank %d receives %d particles.\n", rank, *particlesPerProcess);
729 }
730
732 PetscFunctionReturn(0);
733}
Here is the caller graph for this function:

◆ FinalizeSwarmSetup()

PetscErrorCode FinalizeSwarmSetup ( PetscRandom *  randx,
PetscRandom *  randy,
PetscRandom *  randz,
PetscRandom *  rand_logic_i,
PetscRandom *  rand_logic_j,
PetscRandom *  rand_logic_k 
)

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

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

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

Definition at line 752 of file ParticleSwarm.c.

752 {
753 PetscErrorCode ierr; // Error code for PETSc functions
754 PetscFunctionBeginUser;
756 // Destroy random number generators to free resources
757 // Physical space
758 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
759 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
760 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
761 // Logical space
762 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
763 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
764 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
765
766 LOG_ALLOW(LOCAL,LOG_DEBUG,"Destroyed all random number generators.\n");
767
769 PetscFunctionReturn(0);
770}
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 
)

Initializes a Particle struct with data from DMSwarm fields.

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

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

Definition at line 879 of file ParticleSwarm.c.

881 {
882 PetscFunctionBeginUser;
883
885
886 PetscMPIInt rank;
887 PetscErrorCode ierr;
888
889 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
890
891 if (particle == NULL) {
892 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output Particle pointer is NULL. \n");
893 }
894
895 // logging the start of particle initialization
896 LOG_ALLOW(LOCAL,LOG_DEBUG, "[Rank %d]Unpacking Particle [%d] with PID: %ld.\n",rank, i, PIDs[i]);
897
898 // Initialize PID
899 if(PIDs == NULL){
900 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input PIDs pointer is NULL.\n");
901 }
902 particle->PID = PIDs[i];
903 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] PID set to: %ld.\n", rank,i, particle->PID);
904
905 // Initialize weights
906 if(weights == NULL){
907 particle->weights.x = 1.0;
908 particle->weights.y = 1.0;
909 particle->weights.z = 1.0;
910 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);
911 }else{
912 particle->weights.x = weights[3 * i];
913 particle->weights.y = weights[3 * i + 1];
914 particle->weights.z = weights[3 * i + 2];
915 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] weights set to: (%.6f, %.6f, %.6f).\n",
916 rank,i, particle->weights.x, particle->weights.y, particle->weights.z);
917 }
918 // Initialize locations
919 if(positions == NULL){
920 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input positions pointer is NULL.\n");
921 }
922 particle->loc.x = positions[3 * i];
923 particle->loc.y = positions[3 * i + 1];
924 particle->loc.z = positions[3 * i + 2];
925 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] location set to: (%.6f, %.6f, %.6f).\n",
926 rank,i, particle->loc.x, particle->loc.y, particle->loc.z);
927
928 // Initialize velocities (assuming default zero; modify if necessary)
929 if(velocities == NULL){
930 particle->vel.x = 0.0;
931 particle->vel.y = 0.0;
932 particle->vel.z = 0.0;
933 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);
934 }else{
935 particle->vel.x = velocities[3 * i];
936 particle->vel.y = velocities[3 * i + 1];
937 particle->vel.z = velocities[3 * i + 2];
938 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);
939 }
940
941 // Initialize diffusivity
942 if(diffusivity == NULL){
943 particle->diffusivity = 1.0; // Default diffusivity
944 }else{
945 particle->diffusivity = diffusivity[i];
946 }
947 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] diffusivity set to: %.6f.\n",rank,i, particle->diffusivity);
948
949 // Initialize diffusivity gradient
950 if(diffusivitygradient == NULL){
951 particle->diffusivitygradient.x = 0.0;
952 particle->diffusivitygradient.y = 0.0;
953 particle->diffusivitygradient.z = 0.0;
954 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);
955 }else{
956 particle->diffusivitygradient.x = diffusivitygradient[i].x;
957 particle->diffusivitygradient.y = diffusivitygradient[i].y;
958 particle->diffusivitygradient.z = diffusivitygradient[i].z;
959 }
960 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);
961
962 // Initialize psi
963 if(psi == NULL){
964 particle->psi = 0.0; // Default psi
965 }else{
966 particle->psi = psi[i];
967 }
968 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] psi set to: %.6f.\n",rank,i, particle->psi);
969
970 // Initialize cell indices
971 if(cellIndices == NULL){
972 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input cellIndices pointer is NULL.\n");
973 }
974 particle->cell[0] = cellIndices[3 * i];
975 particle->cell[1] = cellIndices[3 * i + 1];
976 particle->cell[2] = cellIndices[3 * i + 2];
977 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]);
978
979 if(LocStatus == NULL){
980 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input LocStatus pointer is NULL.\n");
981 }
982 // Initialize location status
983 particle->location_status = (ParticleLocationStatus)LocStatus[i];
984 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] Status set to: %d.\n",rank, i, particle->location_status);
985
986 // The destination_rank is only set by the location search, not read from the swarm,
987 // so we initialize it to a known invalid state.
988 particle->destination_rank = MPI_PROC_NULL;
989
990 // logging the completion of particle initialization
991 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d]Completed initialization of Particle [%d]. \n", rank,i);
992
993
995
996 PetscFunctionReturn(0);
997}
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34
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 
)

Updates DMSwarm data arrays from a Particle struct.

This function writes data from the Particle struct back into the raw DMSwarm arrays. It is robust: if any array pointer is NULL, that specific field is skipped. This allows selective updating (e.g., update position but not velocity).

Parameters
[in]iIndex of the particle in the local swarm arrays.
[in]particlePointer to the Particle struct containing updated data.
[in,out]positions(Optional) Array of particle positions (size 3*n).
[in,out]velocities(Optional) Array of particle velocities (size 3*n).
[in,out]weights(Optional) Array of particle weights (size 3*n).
[in,out]cellIndices(Optional) Array of particle cell indices (size 3*n).
[in,out]status(Optional) Array of location status (size 1*n).
[in,out]diffusivity(Optional) Array of diffusivity values (size 1*n).
[in,out]diffusivitygradient(Optional) Array of diffusivity gradient values (size 3*n).
[in,out]psi(Optional) Array of scalar Psi values (size 1*n).
Returns
PetscErrorCode Returns 0 on success.

Definition at line 1021 of file ParticleSwarm.c.

1030{
1031 PetscFunctionBeginUser;
1033
1034 if (!particle) {
1035 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input Particle pointer is NULL.\n");
1036 }
1037
1038 // --- 1. Position (x, y, z) ---
1039 if (positions) {
1040 positions[3 * i + 0] = particle->loc.x;
1041 positions[3 * i + 1] = particle->loc.y;
1042 positions[3 * i + 2] = particle->loc.z;
1043 }
1044
1045 // --- 2. Velocity (u, v, w) ---
1046 if (velocities) {
1047 velocities[3 * i + 0] = particle->vel.x;
1048 velocities[3 * i + 1] = particle->vel.y;
1049 velocities[3 * i + 2] = particle->vel.z;
1050 }
1051
1052 // --- 3. Weights (i, j, k) ---
1053 if (weights) {
1054 weights[3 * i + 0] = particle->weights.x;
1055 weights[3 * i + 1] = particle->weights.y;
1056 weights[3 * i + 2] = particle->weights.z;
1057 }
1058
1059 // --- 4. Cell Indices (i, j, k) ---
1060 if (cellIndices) {
1061 cellIndices[3 * i + 0] = particle->cell[0];
1062 cellIndices[3 * i + 1] = particle->cell[1];
1063 cellIndices[3 * i + 2] = particle->cell[2];
1064 }
1065
1066 // --- 5. Status ---
1067 if (status) {
1068 status[i] = (PetscInt)particle->location_status;
1069 }
1070
1071 // --- 6. Diffusivity ---
1072 if (diffusivity) {
1073 diffusivity[i] = particle->diffusivity;
1074 }
1075
1076 if(diffusivitygradient){
1077 diffusivitygradient[i].x = particle->diffusivitygradient.x;
1078 diffusivitygradient[i].y = particle->diffusivitygradient.y;
1079 diffusivitygradient[i].z = particle->diffusivitygradient.z;
1080 }
1081 // --- 7. Psi ---
1082 if (psi) {
1083 psi[i] = particle->psi;
1084 }
1085
1086 // LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, i, 1000, "Updated fields for Particle [%d].\n", i);
1087
1089 PetscFunctionReturn(0);
1090}
Here is the caller graph for this function:

◆ IsParticleInsideBoundingBox()

PetscBool IsParticleInsideBoundingBox ( const BoundingBox bbox,
const Particle particle 
)

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

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

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

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

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

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

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

Definition at line 1114 of file ParticleSwarm.c.

1115{
1116 PetscFunctionBeginUser;
1118
1119 // Validate input pointers
1120 if (!bbox) {
1121 // LOG_ALLOW error message and return PETSC_FALSE
1122 LOG_ALLOW(LOCAL,LOG_ERROR, "Error - 'bbox' pointer is NULL.");
1124 return PETSC_FALSE;
1125 }
1126 if (!particle) {
1127 LOG_ALLOW(LOCAL,LOG_ERROR,"Error - 'particle' pointer is NULL.");
1129 return PETSC_FALSE;
1130 }
1131
1132 // Extract particle location and bounding box coordinates
1133 const Cmpnts loc = particle->loc;
1134 const Cmpnts min_coords = bbox->min_coords;
1135 const Cmpnts max_coords = bbox->max_coords;
1136
1137 // LOG_ALLOW the particle location and bounding box coordinates for debugging
1138 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "Particle PID %ld location: (%.6f, %.6f, %.6f).\n",particle->PID, loc.x, loc.y, loc.z);
1139 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "BoundingBox min_coords: (%.6f, %.6f, %.6f), max_coords: (%.6f, %.6f, %.6f).\n",
1140 min_coords.x, min_coords.y, min_coords.z, max_coords.x, max_coords.y, max_coords.z);
1141
1142 // Check if the particle's location is within the bounding box
1143 if ((loc.x >= min_coords.x && loc.x <= max_coords.x) &&
1144 (loc.y >= min_coords.y && loc.y <= max_coords.y) &&
1145 (loc.z >= min_coords.z && loc.z <= max_coords.z)) {
1146 // Particle is inside the bounding box
1147 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "Particle PID %ld is inside the bounding box.\n",particle->PID);
1149 return PETSC_TRUE;
1150 }
1151
1152 // Particle is outside the bounding box
1153 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE,"Particle PID %ld is outside the bounding box.\n",particle->PID);
1155 return PETSC_FALSE;
1156}
A 3D point or vector with PetscScalar components.
Definition variables.h:100

◆ UpdateParticleWeights()

PetscErrorCode UpdateParticleWeights ( PetscReal *  d,
Particle particle 
)

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

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

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

Definition at line 1172 of file ParticleSwarm.c.

1172 {
1173
1174 PetscFunctionBeginUser;
1176
1177 // Validate input pointers
1178 if (!d || !particle) {
1179 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
1180 "Null pointer argument (d or particle).");
1181 }
1182
1183
1184 // Validate distances
1185 for (PetscInt i = LEFT; i < NUM_FACES; i++) {
1188 "face distance d[%d] = %f <= %f; "
1189 "clamping to 1e-14 to avoid zero/negative.\n",
1190 i, (double)d[i], INTERPOLATION_DISTANCE_TOLERANCE);
1192 }
1193 }
1194
1195 // LOG_ALLOW the input distances
1197 "Calculating weights with distances: "
1198 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
1199 d[LEFT], d[RIGHT], d[BOTTOM], d[TOP], d[FRONT], d[BACK]);
1200
1201 // Compute and update the particle's weights
1202 particle->weights.x = d[LEFT] / (d[LEFT] + d[RIGHT]);
1203 particle->weights.y = d[BOTTOM] / (d[BOTTOM] + d[TOP]);
1204 particle->weights.z = d[BACK] / (d[FRONT] + d[BACK]);
1205
1206 // LOG_ALLOW the updated weights
1208 "Updated particle weights: x=%f, y=%f, z=%f.\n",
1209 particle->weights.x, particle->weights.y, particle->weights.z);
1210
1211
1213 PetscFunctionReturn(0);
1214}
#define INTERPOLATION_DISTANCE_TOLERANCE
@ TOP
Definition variables.h:145
@ FRONT
Definition variables.h:145
@ BOTTOM
Definition variables.h:145
@ BACK
Definition variables.h:145
@ LEFT
Definition variables.h:145
@ NUM_FACES
Definition variables.h:145
@ RIGHT
Definition variables.h:145
Here is the caller graph for this function:

◆ InitializeParticleSwarm()

PetscErrorCode InitializeParticleSwarm ( SimCtx simCtx)

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

This function handles the following tasks:

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

Definition at line 1238 of file ParticleSwarm.c.

1239{
1240 PetscErrorCode ierr;
1241 PetscInt particlesPerProcess = 0;
1242 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1243
1244 PetscFunctionBeginUser;
1246
1247 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting particle swarm setup for %d particles.\n", simCtx->np);
1248
1249 // --- Phase 1: Create the DMSwarm Object (Always required) ---
1250 // This creates the container and registers the fields. It does not add particles yet.
1251 ierr = CreateParticleSwarm(user, simCtx->np, &particlesPerProcess, simCtx->bboxlist); CHKERRQ(ierr);
1252 LOG_ALLOW(GLOBAL, LOG_INFO, "DMSwarm object and fields created successfully.\n");
1253
1254
1255 // --- Phase 2: Decide whether to Initialize new particles or Load existing ones ---
1256 PetscBool should_initialize_new_particles = PETSC_FALSE;
1257 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1258 should_initialize_new_particles = PETSC_TRUE;
1259 }else{
1260 if (simCtx->StartStep == 0) {
1261 should_initialize_new_particles = PETSC_TRUE; // Standard fresh start
1262 } else {
1263 // It's a restart, so check the user's requested particle mode.
1264 if (strcmp(simCtx->particleRestartMode, "init") == 0) {
1265 should_initialize_new_particles = PETSC_TRUE; // User wants to re-initialize particles in a restarted flow.
1266 }
1267 }
1268 }
1269
1270 // --- Phase 3: Execute the chosen particle setup path ---
1271 if (should_initialize_new_particles) {
1272 // --- PATH A: Generate a fresh population of particles ---
1273 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: INITIALIZE. Generating new particle population.\n");
1274 PetscRandom randx, randy, randz;
1275 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1276
1277 ierr = InitializeRandomGenerators(user, &randx, &randy, &randz); CHKERRQ(ierr);
1278 ierr = InitializeLogicalSpaceRNGs(&rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1279 ierr = AssignInitialPropertiesToSwarm(user, particlesPerProcess, &randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k, simCtx->bboxlist); CHKERRQ(ierr);
1280 ierr = FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1281
1282 } else {
1283 // --- PATH B: Load particle population from restart files ---
1284 // This path is only taken if simCtx->StartStep > 0 AND simCtx->particleRestartMode == "load"
1285 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: LOAD. Loading particle population from files for step %d.\n", simCtx->StartStep);
1286
1287 ierr = PreCheckAndResizeSwarm(user, simCtx->StartStep, "dat"); CHKERRQ(ierr);
1288
1289 ierr = ReadAllSwarmFields(user, simCtx->StartStep); CHKERRQ(ierr);
1290 // Note: We check for file-open errors inside ReadAllSwarmFields now.
1291
1292 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle data loaded. CellID and status are preserved from file.\n");
1293 }
1294
1295 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Particle swarm setup complete.\n");
1296
1298 PetscFunctionReturn(0);
1299}
PetscErrorCode PreCheckAndResizeSwarm(UserCtx *user, PetscInt ti, const char *ext)
Checks particle count in the reference file and resizes the swarm if needed.
PetscErrorCode CreateParticleSwarm(UserCtx *user, PetscInt numParticles, PetscInt *particlesPerProcess, BoundingBox *bboxlist)
Creates and initializes a Particle Swarm.
PetscErrorCode FinalizeSwarmSetup(PetscRandom *randx, PetscRandom *randy, PetscRandom *randz, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Finalizes the swarm setup by destroying random generators and logging completion.
PetscErrorCode AssignInitialPropertiesToSwarm(UserCtx *user, PetscInt particlesPerProcess, PetscRandom *rand_phys_x, PetscRandom *rand_phys_y, PetscRandom *rand_phys_z, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k, BoundingBox *bboxlist)
Initializes all particle properties in the swarm.
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Reads multiple fields (positions, velocity, CellID, and weight) into a DMSwarm.
Definition io.c:1534
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
Definition setup.c:2642
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:2693
UserCtx * user
Definition variables.h:474
UserMG usermg
Definition variables.h:698
PetscInt np
Definition variables.h:676
PetscInt StartStep
Definition variables.h:595
char particleRestartMode[16]
Definition variables.h:681
BoundingBox * bboxlist
Definition variables.h:679
PetscInt mglevels
Definition variables.h:481
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:559
MGCtx * mgctx
Definition variables.h:484
ExecutionMode exec_mode
Definition variables.h:603
User-defined context containing data specific to a single computational grid level.
Definition variables.h:728
Here is the call graph for this function:
Here is the caller graph for this function: