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

628 {
629 PetscErrorCode ierr; // PETSc error handling variable
630 (void)bboxlist;
631 PetscMPIInt rank, size; // Variables to store MPI rank and size
632 PetscInt remainder = 0; // Remainder of particles after division
633
634 PetscFunctionBeginUser;
636 // Validate input parameters
637 if (numParticles <= 0) {
638 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Number of particles must be positive. Given: %d\n", numParticles);
640 return PETSC_ERR_ARG_OUTOFRANGE;
641 }
642
643 // Retrieve MPI rank and size
644 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
645 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
646 LOG_ALLOW(GLOBAL,LOG_INFO," Domain dimensions: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
647 user->Min_X,user->Max_X,user->Min_Y,user->Max_Y, user->Min_Z,user->Max_Z);
648 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG, "[Rank %d] Local Bounding Box: [%.2f,%.2f],[%.2f,%.2f],[%.2f,%.2f] \n",
649 rank,user->bbox.min_coords.x,user->bbox.max_coords.x,
650 user->bbox.min_coords.y,user->bbox.max_coords.y,
651 user->bbox.min_coords.z,user->bbox.max_coords.z);
652 // Distribute particles among MPI processes
653 ierr = DistributeParticles(numParticles, rank, size, particlesPerProcess, &remainder); CHKERRQ(ierr);
654
655 // Initialize the DMSwarm - creates the swarm, sets the type and dimension
656 ierr = InitializeSwarm(user); CHKERRQ(ierr);
657
658 if (user->da) {
659 ierr = DMSwarmSetCellDM(user->swarm, user->da); CHKERRQ(ierr);
660 LOG_ALLOW(LOCAL,LOG_INFO,"Associated DMSwarm with Cell DM (user->da).\n");
661 } else {
662 // If user->da is essential for your simulation logic with particles, this should be a fatal error.
663 LOG_ALLOW(GLOBAL, LOG_WARNING, "user->da (Cell DM for Swarm) is NULL. Cell-based swarm operations might fail.\n");
664 // SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "user->da (Cell DM) is NULL but required.");
665 }
666
667 // Register particle fields (position, velocity, CellID, weight, etc.)
668 ierr = RegisterParticleFields(user->swarm); CHKERRQ(ierr);
669
670 // Set the local number of particles for this rank and additional buffer for particle migration
671 ierr = DMSwarmSetLocalSizes(user->swarm, *particlesPerProcess, numParticles); CHKERRQ(ierr);
672 LOG_ALLOW(GLOBAL,LOG_INFO, "Set local swarm size: %d particles.\n", *particlesPerProcess);
673
674 // Optionally, LOG_ALLOW detailed DM info in debug mode
675 if (get_log_level() == LOG_DEBUG && is_function_allowed(__func__)) {
676 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Viewing DMSwarm:\n");
677 ierr = DMView(user->swarm, PETSC_VIEWER_STDOUT_WORLD); CHKERRQ(ierr);
678 }
679
680 LOG_ALLOW(GLOBAL,LOG_INFO, "Particle swarm creation and initialization complete.\n");
681
683 PetscFunctionReturn(0);
684}
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: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:859
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:850
PetscReal Min_X
Definition variables.h:921
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:173
PetscReal Max_Y
Definition variables.h:921
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:172
PetscScalar x
Definition variables.h:103
PetscScalar z
Definition variables.h:103
PetscReal Min_Z
Definition variables.h:921
PetscReal Max_X
Definition variables.h:921
PetscReal Min_Y
Definition variables.h:921
PetscScalar y
Definition variables.h:103
BoundingBox bbox
Definition variables.h:922
PetscReal Max_Z
Definition variables.h:921
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 480 of file ParticleSwarm.c.

489{
490 PetscErrorCode ierr;
491 PetscFunctionBeginUser;
492
494
495 SimCtx *simCtx = user->simCtx;
496
497 // --- 0. Input Validation ---
498 if (!user || !bboxlist || !rand_logic_i || !rand_logic_j || !rand_logic_k || !rand_phys_x || !rand_phys_y || !rand_phys_z) {
499 // Check all RNGs now as they are passed in
500 LOG_ALLOW(GLOBAL, LOG_ERROR, "Null user, bboxlist, or RNG pointer.\n");
501 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input detected.");
502 }
503
504 LOG_ALLOW(GLOBAL, LOG_INFO, "Initializing swarm with %d particles per process. Mode: %s.\n",
505 particlesPerProcess, ParticleInitializationToString(simCtx->ParticleInitialization));
506
507 // --- 1. Parse BCS File for Inlet Information (if surface initialization) ---
509 simCtx->ParticleInitialization == PARTICLE_INIT_SURFACE_EDGES) { // Surface initialization
510 if(user->inletFaceDefined == PETSC_FALSE){
511 LOG_ALLOW(GLOBAL, LOG_ERROR, "Particle Initialization on inlet surface selected, but no INLET face was identified from bcs.dat. Cannot proceed.\n");
512 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "ParticleInitialization Mode 0 requires an INLET face to be defined in bcs.dat.");
513 }else{
514 LOG_ALLOW(GLOBAL, LOG_INFO, "After Parsing BCS file for Inlet, Inlet face = %s\n", BCFaceToString((BCFace)user->identifiedInletBCFace));
515 }
516 }
517
518 // --- 2. Initialize Basic Particle Properties (Position, PID, Cell IDs placeholder) ---
519 // The rand_logic_i/j/k are now passed directly.
520 // The rand_phys_x/y/z are passed but InitializeParticleBasicProperties (refactored version)
521 // will not use them for setting positions if all its paths use logical-to-physical mapping.
522 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Calling InitializeParticleBasicProperties.\n");
523 ierr = InitializeParticleBasicProperties(user, particlesPerProcess,
524 rand_logic_i, rand_logic_j, rand_logic_k,
525 bboxlist); // bboxlist passed along
526 CHKERRQ(ierr);
527 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully initialized basic particle properties.\n");
528
529 // Note: The logical RNGs (rand_logic_i/j/k) are NOT destroyed here.
530 // They were created externally (e.g., by InitializeLogicalSpaceRNGs) and
531 // should be destroyed externally (e.g., in FinalizeSwarmSetup).
532 // Same for rand_phys_x/y/z.
533
534 // --- 3. Initialize Other Swarm Fields (Velocity, Weight, Pressure, etc.) ---
535 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'velocity' field.\n");
536 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_VELOCITY); CHKERRQ(ierr);
537 LOG_ALLOW(LOCAL, LOG_INFO, "'velocity' field initialization complete.\n");
538
539 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'weight' field.\n");
540 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_WEIGHT); CHKERRQ(ierr); // Weight is a three-component field.
541 LOG_ALLOW(LOCAL, LOG_INFO, "'weight' field initialization complete.\n");
542
543 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Diffusivity' field.\n");
544 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_DIFFUSIVITY); CHKERRQ(ierr);
545 LOG_ALLOW(GLOBAL, LOG_INFO, "'Diffusivity' field initialization complete.\n");
546
547 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'DiffusivityGradient' field.\n");
549 LOG_ALLOW(GLOBAL, LOG_INFO, "'DiffusivityGradient' field initialization complete.\n");
550
551 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Initializing 'Psi' (Scalar) field.\n");
552 ierr = AssignInitialFieldToSwarm(user, PARTICLE_FIELD_ID_PSI); CHKERRQ(ierr);
553 LOG_ALLOW(GLOBAL, LOG_INFO, "'P' field initialization complete.\n");
554
555 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully completed all swarm property initialization.\n");
556
557
559
560 PetscFunctionReturn(0);
561}
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:932
BCFace identifiedInletBCFace
Definition variables.h:933
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:909
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:552
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:555
ParticleInitializationType ParticleInitialization
Definition variables.h:831
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:261
The master context for the entire simulation.
Definition variables.h:695
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 572 of file ParticleSwarm.c.

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

602 {
603 PetscErrorCode ierr; // Error code for PETSc functions
604 PetscFunctionBeginUser;
606 // Destroy random number generators to free resources
607 // Physical space
608 ierr = PetscRandomDestroy(randx); CHKERRQ(ierr);
609 ierr = PetscRandomDestroy(randy); CHKERRQ(ierr);
610 ierr = PetscRandomDestroy(randz); CHKERRQ(ierr);
611 // Logical space
612 ierr = PetscRandomDestroy(rand_logic_i); CHKERRQ(ierr);
613 ierr = PetscRandomDestroy(rand_logic_j); CHKERRQ(ierr);
614 ierr = PetscRandomDestroy(rand_logic_k); CHKERRQ(ierr);
615
616 LOG_ALLOW(LOCAL,LOG_DEBUG,"Destroyed all random number generators.\n");
617
619 PetscFunctionReturn(0);
620}
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 700 of file ParticleSwarm.c.

702 {
703 PetscFunctionBeginUser;
704
706
707 PetscMPIInt rank;
708 PetscErrorCode ierr;
709
710 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
711
712 if (particle == NULL) {
713 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output Particle pointer is NULL. \n");
714 }
715
716 // logging the start of particle initialization
717 LOG_ALLOW(LOCAL,LOG_DEBUG, "[Rank %d]Unpacking Particle [%d] with PID: %ld.\n",rank, i, PIDs[i]);
718
719 // Initialize PID
720 if(PIDs == NULL){
721 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input PIDs pointer is NULL.\n");
722 }
723 particle->PID = PIDs[i];
724 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] PID set to: %ld.\n", rank,i, particle->PID);
725
726 // Initialize weights
727 if(weights == NULL){
728 particle->weights.x = 1.0;
729 particle->weights.y = 1.0;
730 particle->weights.z = 1.0;
731 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);
732 }else{
733 particle->weights.x = weights[3 * i];
734 particle->weights.y = weights[3 * i + 1];
735 particle->weights.z = weights[3 * i + 2];
736 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] weights set to: (%.6f, %.6f, %.6f).\n",
737 rank,i, particle->weights.x, particle->weights.y, particle->weights.z);
738 }
739 // Initialize locations
740 if(positions == NULL){
741 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input positions pointer is NULL.\n");
742 }
743 particle->loc.x = positions[3 * i];
744 particle->loc.y = positions[3 * i + 1];
745 particle->loc.z = positions[3 * i + 2];
746 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] location set to: (%.6f, %.6f, %.6f).\n",
747 rank,i, particle->loc.x, particle->loc.y, particle->loc.z);
748
749 // Initialize velocities (assuming default zero; modify if necessary)
750 if(velocities == NULL){
751 particle->vel.x = 0.0;
752 particle->vel.y = 0.0;
753 particle->vel.z = 0.0;
754 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);
755 }else{
756 particle->vel.x = velocities[3 * i];
757 particle->vel.y = velocities[3 * i + 1];
758 particle->vel.z = velocities[3 * i + 2];
759 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);
760 }
761
762 // Initialize diffusivity
763 if(diffusivity == NULL){
764 particle->diffusivity = 1.0; // Default diffusivity
765 }else{
766 particle->diffusivity = diffusivity[i];
767 }
768 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] diffusivity set to: %.6f.\n",rank,i, particle->diffusivity);
769
770 // Initialize diffusivity gradient
771 if(diffusivitygradient == NULL){
772 particle->diffusivitygradient.x = 0.0;
773 particle->diffusivitygradient.y = 0.0;
774 particle->diffusivitygradient.z = 0.0;
775 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);
776 }else{
777 particle->diffusivitygradient.x = diffusivitygradient[i].x;
778 particle->diffusivitygradient.y = diffusivitygradient[i].y;
779 particle->diffusivitygradient.z = diffusivitygradient[i].z;
780 }
781 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);
782
783 // Initialize psi
784 if(psi == NULL){
785 particle->psi = 0.0; // Default psi
786 }else{
787 particle->psi = psi[i];
788 }
789 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d]Particle [%d] psi set to: %.6f.\n",rank,i, particle->psi);
790
791 // Initialize cell indices
792 if(cellIndices == NULL){
793 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input cellIndices pointer is NULL.\n");
794 }
795 particle->cell[0] = cellIndices[3 * i];
796 particle->cell[1] = cellIndices[3 * i + 1];
797 particle->cell[2] = cellIndices[3 * i + 2];
798 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]);
799
800 if(LocStatus == NULL){
801 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input LocStatus pointer is NULL.\n");
802 }
803 // Initialize location status
804 particle->location_status = (ParticleLocationStatus)LocStatus[i];
805 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d]Particle [%d] Status set to: %d.\n",rank, i, particle->location_status);
806
807 // The destination_rank is only set by the location search, not read from the swarm,
808 // so we initialize it to a known invalid state.
809 particle->destination_rank = MPI_PROC_NULL;
810
811 // logging the completion of particle initialization
812 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d]Completed initialization of Particle [%d]. \n", rank,i);
813
814
816
817 PetscFunctionReturn(0);
818}
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34
Cmpnts vel
Definition variables.h:186
PetscInt cell[3]
Definition variables.h:184
ParticleLocationStatus
Defines the state of a particle with respect to its location and migration status during the iterativ...
Definition variables.h:137
Cmpnts diffusivitygradient
Definition variables.h:191
Cmpnts loc
Definition variables.h:185
PetscMPIInt destination_rank
Definition variables.h:189
ParticleLocationStatus location_status
Definition variables.h:188
PetscReal diffusivity
Definition variables.h:190
PetscReal psi
Definition variables.h:192
Cmpnts weights
Definition variables.h:187
PetscInt64 PID
Definition variables.h:183
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 826 of file ParticleSwarm.c.

835{
836 PetscFunctionBeginUser;
838
839 if (!particle) {
840 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input Particle pointer is NULL.\n");
841 }
842
843 // --- 1. Position (x, y, z) ---
844 if (positions) {
845 positions[3 * i + 0] = particle->loc.x;
846 positions[3 * i + 1] = particle->loc.y;
847 positions[3 * i + 2] = particle->loc.z;
848 }
849
850 // --- 2. Velocity (u, v, w) ---
851 if (velocities) {
852 velocities[3 * i + 0] = particle->vel.x;
853 velocities[3 * i + 1] = particle->vel.y;
854 velocities[3 * i + 2] = particle->vel.z;
855 }
856
857 // --- 3. Weights (i, j, k) ---
858 if (weights) {
859 weights[3 * i + 0] = particle->weights.x;
860 weights[3 * i + 1] = particle->weights.y;
861 weights[3 * i + 2] = particle->weights.z;
862 }
863
864 // --- 4. Cell Indices (i, j, k) ---
865 if (cellIndices) {
866 cellIndices[3 * i + 0] = particle->cell[0];
867 cellIndices[3 * i + 1] = particle->cell[1];
868 cellIndices[3 * i + 2] = particle->cell[2];
869 }
870
871 // --- 5. Status ---
872 if (status) {
873 status[i] = (PetscInt)particle->location_status;
874 }
875
876 // --- 6. Diffusivity ---
877 if (diffusivity) {
878 diffusivity[i] = particle->diffusivity;
879 }
880
881 if(diffusivitygradient){
882 diffusivitygradient[i].x = particle->diffusivitygradient.x;
883 diffusivitygradient[i].y = particle->diffusivitygradient.y;
884 diffusivitygradient[i].z = particle->diffusivitygradient.z;
885 }
886 // --- 7. Psi ---
887 if (psi) {
888 psi[i] = particle->psi;
889 }
890
891 // LOG_LOOP_ALLOW(LOCAL, LOG_VERBOSE, i, 1000, "Updated fields for Particle [%d].\n", i);
892
894 PetscFunctionReturn(0);
895}
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 903 of file ParticleSwarm.c.

904{
905 PetscFunctionBeginUser;
907
908 // Validate input pointers
909 if (!bbox) {
910 // LOG_ALLOW error message and return PETSC_FALSE
911 LOG_ALLOW(LOCAL,LOG_ERROR, "Error - 'bbox' pointer is NULL.");
913 return PETSC_FALSE;
914 }
915 if (!particle) {
916 LOG_ALLOW(LOCAL,LOG_ERROR,"Error - 'particle' pointer is NULL.");
918 return PETSC_FALSE;
919 }
920
921 // Extract particle location and bounding box coordinates
922 const Cmpnts loc = particle->loc;
923 const Cmpnts min_coords = bbox->min_coords;
924 const Cmpnts max_coords = bbox->max_coords;
925
926 // LOG_ALLOW the particle location and bounding box coordinates for debugging
927 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "Particle PID %ld location: (%.6f, %.6f, %.6f).\n",particle->PID, loc.x, loc.y, loc.z);
928 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE, "BoundingBox min_coords: (%.6f, %.6f, %.6f), max_coords: (%.6f, %.6f, %.6f).\n",
929 min_coords.x, min_coords.y, min_coords.z, max_coords.x, max_coords.y, max_coords.z);
930
931 // Check if the particle's location is within the bounding box
932 if ((loc.x >= min_coords.x && loc.x <= max_coords.x) &&
933 (loc.y >= min_coords.y && loc.y <= max_coords.y) &&
934 (loc.z >= min_coords.z && loc.z <= max_coords.z)) {
935 // Particle is inside the bounding box
936 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "Particle PID %ld is inside the bounding box.\n",particle->PID);
938 return PETSC_TRUE;
939 }
940
941 // Particle is outside the bounding box
942 LOG_ALLOW_SYNC(LOCAL, LOG_VERBOSE,"Particle PID %ld is outside the bounding box.\n",particle->PID);
944 return PETSC_FALSE;
945}
A 3D point or vector with PetscScalar components.
Definition variables.h:102
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 954 of file ParticleSwarm.c.

954 {
955
956 PetscFunctionBeginUser;
958
959 // Validate input pointers
960 if (!d || !particle) {
961 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
962 "Null pointer argument (d or particle).");
963 }
964
965
966 // Validate distances
967 for (PetscInt i = LEFT; i < NUM_FACES; i++) {
970 "face distance d[%d] = %f <= %f; "
971 "clamping to 1e-14 to avoid zero/negative.\n",
972 i, (double)d[i], INTERPOLATION_DISTANCE_TOLERANCE);
974 }
975 }
976
977 // LOG_ALLOW the input distances
979 "Calculating weights with distances: "
980 "[LEFT=%f, RIGHT=%f, BOTTOM=%f, TOP=%f, FRONT=%f, BACK=%f].\n",
981 d[LEFT], d[RIGHT], d[BOTTOM], d[TOP], d[FRONT], d[BACK]);
982
983 // Compute and update the particle's weights
984 particle->weights.x = d[LEFT] / (d[LEFT] + d[RIGHT]);
985 particle->weights.y = d[BOTTOM] / (d[BOTTOM] + d[TOP]);
986 particle->weights.z = d[BACK] / (d[FRONT] + d[BACK]);
987
988 // LOG_ALLOW the updated weights
990 "Updated particle weights: x=%f, y=%f, z=%f.\n",
991 particle->weights.x, particle->weights.y, particle->weights.z);
992
993
995 PetscFunctionReturn(0);
996}
#define INTERPOLATION_DISTANCE_TOLERANCE
@ TOP
Definition variables.h:147
@ FRONT
Definition variables.h:147
@ BOTTOM
Definition variables.h:147
@ BACK
Definition variables.h:147
@ LEFT
Definition variables.h:147
@ NUM_FACES
Definition variables.h:147
@ RIGHT
Definition variables.h:147
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 1027 of file ParticleSwarm.c.

1028{
1029 PetscErrorCode ierr;
1030 PetscInt particlesPerProcess = 0;
1031 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1032
1033 PetscFunctionBeginUser;
1035
1036 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting particle swarm setup for %d particles.\n", simCtx->np);
1037
1038 // --- Phase 1: Create the DMSwarm Object (Always required) ---
1039 // This creates the container and registers the fields. It does not add particles yet.
1040 ierr = CreateParticleSwarm(user, simCtx->np, &particlesPerProcess, simCtx->bboxlist); CHKERRQ(ierr);
1041 LOG_ALLOW(GLOBAL, LOG_INFO, "DMSwarm object and fields created successfully.\n");
1042
1043
1044 // --- Phase 2: Decide whether to Initialize new particles or Load existing ones ---
1045 PetscBool should_initialize_new_particles = PETSC_FALSE;
1046 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1047 should_initialize_new_particles = PETSC_TRUE;
1048 }else{
1049 if (simCtx->StartStep == 0) {
1050 should_initialize_new_particles = PETSC_TRUE; // Standard fresh start
1051 } else {
1052 // It's a restart, so check the user's requested particle mode.
1053 if (strcmp(simCtx->particleRestartMode, "init") == 0) {
1054 should_initialize_new_particles = PETSC_TRUE; // User wants to re-initialize particles in a restarted flow.
1055 }
1056 }
1057 }
1058
1059 // --- Phase 3: Execute the chosen particle setup path ---
1060 if (should_initialize_new_particles) {
1061 // --- PATH A: Generate a fresh population of particles ---
1062 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: INITIALIZE. Generating new particle population.\n");
1063 PetscRandom randx, randy, randz;
1064 PetscRandom rand_logic_i, rand_logic_j, rand_logic_k;
1065
1066 ierr = InitializeRandomGenerators(user, &randx, &randy, &randz); CHKERRQ(ierr);
1067 ierr = InitializeLogicalSpaceRNGs(&rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1068 ierr = AssignInitialPropertiesToSwarm(user, particlesPerProcess, &randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k, simCtx->bboxlist); CHKERRQ(ierr);
1069 ierr = FinalizeSwarmSetup(&randx, &randy, &randz, &rand_logic_i, &rand_logic_j, &rand_logic_k); CHKERRQ(ierr);
1070
1071 } else {
1072 // --- PATH B: Load particle population from restart files ---
1073 // This path is only taken if simCtx->StartStep > 0 AND simCtx->particleRestartMode == "load"
1074 LOG_ALLOW(GLOBAL, LOG_INFO, "Mode: LOAD. Loading particle population from files for step %d.\n", simCtx->StartStep);
1075
1076 ierr = PreCheckAndResizeSwarm(user, simCtx->StartStep, "dat"); CHKERRQ(ierr);
1077
1078 ierr = ReadAllSwarmFields(user, simCtx->StartStep); CHKERRQ(ierr);
1079 // Note: We check for file-open errors inside ReadAllSwarmFields now.
1080
1081 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle data loaded. CellID and status are preserved from file.\n");
1082 }
1083
1084 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Particle swarm setup complete.\n");
1085
1087 PetscFunctionReturn(0);
1088}
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:1864
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
Definition setup.c:3200
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:3241
UserCtx * user
Definition variables.h:571
UserMG usermg
Definition variables.h:852
PetscInt np
Definition variables.h:827
PetscInt StartStep
Definition variables.h:705
char particleRestartMode[16]
Definition variables.h:833
BoundingBox * bboxlist
Definition variables.h:830
PetscInt mglevels
Definition variables.h:578
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:669
MGCtx * mgctx
Definition variables.h:581
ExecutionMode exec_mode
Definition variables.h:714
User-defined context containing data specific to a single computational grid level.
Definition variables.h:906
Here is the call graph for this function:
Here is the caller graph for this function: