PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Functions
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)
 High-level particle initialization orchestrator for a simulation run.
 

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.
[out]particlesPerProcessNumber of particles assigned to the local rank.
[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.

Creates and initializes a Particle Swarm.

Local to this translation unit.

Definition at line 651 of file ParticleSwarm.c.

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

◆ 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.

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}
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.

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}
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.

Registers necessary particle fields within the DMSwarm.

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

See also
RegisterParticleFields()

Definition at line 61 of file ParticleSwarm.c.

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

◆ 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.

Initializes all particle properties in the swarm.

Local to this translation unit.

Definition at line 503 of file ParticleSwarm.c.

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

◆ 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.

Distributes particles evenly across MPI processes, handling any remainders.

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

See also
DistributeParticles()

Definition at line 595 of file ParticleSwarm.c.

595 {
596
597 PetscFunctionBeginUser;
598
600 // Calculate the base number of particles per process
601 *particlesPerProcess = numParticles / size;
602 *remainder = numParticles % size;
603
604 // Distribute the remainder particles to the first 'remainder' ranks
605 if (rank < *remainder) {
606 *particlesPerProcess += 1;
607 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO,"Rank %d receives an extra particle. Total: %d\n", rank, *particlesPerProcess);
608 } else {
609 LOG_ALLOW_SYNC(GLOBAL,LOG_INFO, "Rank %d receives %d particles.\n", rank, *particlesPerProcess);
610 }
611
613 PetscFunctionReturn(0);
614}
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.

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

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

See also
FinalizeSwarmSetup()

Definition at line 625 of file ParticleSwarm.c.

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

◆ 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.

Initializes a Particle struct with data from DMSwarm fields.

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

See also
UnpackSwarmFields()

Definition at line 722 of file ParticleSwarm.c.

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

Updates DMSwarm data arrays from a Particle struct.

Local to this translation unit.

Definition at line 848 of file ParticleSwarm.c.

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

◆ IsParticleInsideBoundingBox()

PetscBool IsParticleInsideBoundingBox ( const BoundingBox bbox,
const Particle particle 
)

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.

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

Local to this translation unit.

Definition at line 925 of file ParticleSwarm.c.

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

◆ 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.

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

Local to this translation unit.

Definition at line 976 of file ParticleSwarm.c.

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

◆ InitializeParticleSwarm()

PetscErrorCode InitializeParticleSwarm ( SimCtx simCtx)

High-level particle initialization orchestrator for a simulation run.

This routine drives end-to-end swarm setup from the top-level simulation context: creation/registration of particle fields, initial placement according to configured mode, initial localization on the Eulerian grid, and startup interpolation needed before entering the main run loop.

Parameters
[in,out]simCtxMaster simulation context containing all blocks and run settings.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

High-level particle initialization orchestrator for a simulation run.

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

See also
InitializeParticleSwarm()

Definition at line 1049 of file ParticleSwarm.c.

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