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 "particle_field_catalog.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 682 of file ParticleSwarm.c.

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

◆ 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 for (PetscInt raw_id = 0; raw_id < PARTICLE_FIELD_ID_COUNT; ++raw_id) {
67 const ParticleFieldDescriptor *descriptor = NULL;
68
69 ierr = ParticleFieldGetDescriptor((ParticleFieldId)raw_id, &descriptor); CHKERRQ(ierr);
70 if (descriptor->registration == PARTICLE_FIELD_REGISTRATION_PETSC) continue;
71
72 ierr = RegisterSwarmField(swarm, descriptor->canonical_name,
73 descriptor->components, descriptor->data_type); CHKERRQ(ierr);
74 }
75
76 // Finalize the field registration after all fields have been added
77 ierr = DMSwarmFinalizeFieldRegister(swarm); CHKERRQ(ierr);
78 LOG_ALLOW(LOCAL,LOG_INFO,"RegisterParticleFields - Finalized field registration.\n");
79
80 PetscFunctionReturn(0);
81}
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Internal helper implementation: RegisterSwarmField().
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_COUNT
ParticleFieldRegistration registration
@ PARTICLE_FIELD_REGISTRATION_PETSC
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
Immutable metadata for one persistent particle field.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ 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 485 of file ParticleSwarm.c.

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

◆ 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 577 of file ParticleSwarm.c.

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

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

◆ 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 758 of file ParticleSwarm.c.

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

◆ UpdateSwarmFields()

PetscErrorCode UpdateSwarmFields ( PetscInt  i,
const Particle *  particle,
PetscReal *  positions,
PetscReal *  velocities,
PetscReal *  weights,
PetscInt *  cellIndices,
PetscInt *  status,
PetscReal *  diffusivity,
Cmpnts *  diffusivitygradient,
PetscReal *  psi 
)

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 884 of file ParticleSwarm.c.

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

◆ IsParticleInsideBoundingBox()

PetscBool IsParticleInsideBoundingBox ( const BoundingBox *  bbox,
const Particle *  particle 
)

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 961 of file ParticleSwarm.c.

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

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

◆ InitializeParticleSwarm()

PetscErrorCode InitializeParticleSwarm ( SimCtx *  simCtx)

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 1085 of file ParticleSwarm.c.

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