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

// code for simulation loop More...

#include "simulation.h"
Include dependency graph for simulation.c:

Go to the source code of this file.

Macros

#define __FUNCT__   "PerformInitialSetup"
 
#define __FUNCT__   "PerformLoadedParticleSetup"
 
#define __FUNCT__   "FinalizeRestartState"
 
#define __FUNCT__   "AdvanceSimulation"
 

Functions

PetscErrorCode UpdateSolverHistoryVectors (UserCtx *user)
 Copies the current time step's solution fields into history vectors (e.g., U(t_n) -> U_o, U_o -> U_rm1) for the next time step's calculations.
 
PetscErrorCode PerformInitializedParticleSetup (SimCtx *simCtx)
 Finalizes the simulation setup at t=0, ensuring a consistent state before time marching.
 
PetscErrorCode PerformLoadedParticleSetup (SimCtx *simCtx)
 Finalizes the simulation state after particle and fluid data have been loaded from a restart.
 
PetscErrorCode FinalizeRestartState (SimCtx *simCtx)
 Performs post-load/post-init consistency checks for a restarted simulation.
 
PetscErrorCode AdvanceSimulation (SimCtx *simCtx)
 Executes the main time-marching loop for the coupled Euler-Lagrange simulation.
 

Detailed Description

// code for simulation loop

Test program for DMSwarm interpolation using the fdf-curvIB method. Provides the setup to start any simulation with DMSwarm and DMDAs.

Definition in file simulation.c.

Macro Definition Documentation

◆ __FUNCT__ [1/4]

#define __FUNCT__   "PerformInitialSetup"

Definition at line 79 of file simulation.c.

◆ __FUNCT__ [2/4]

#define __FUNCT__   "PerformLoadedParticleSetup"

Definition at line 79 of file simulation.c.

◆ __FUNCT__ [3/4]

#define __FUNCT__   "FinalizeRestartState"

Definition at line 79 of file simulation.c.

◆ __FUNCT__ [4/4]

#define __FUNCT__   "AdvanceSimulation"

Definition at line 79 of file simulation.c.

Function Documentation

◆ UpdateSolverHistoryVectors()

PetscErrorCode UpdateSolverHistoryVectors ( UserCtx user)

Copies the current time step's solution fields into history vectors (e.g., U(t_n) -> U_o, U_o -> U_rm1) for the next time step's calculations.

This function is critical for multi-step time integration schemes (like BDF2) used by the legacy solver. It must be called at the end of every time step, after the new solution has been fully computed.

The order of operations is important to avoid overwriting data prematurely.

Parameters
userThe UserCtx for a single block. The function modifies the history vectors (Ucont_o, Ucont_rm1, etc.) within this context.
Returns
PetscErrorCode 0 on success.

Definition at line 23 of file simulation.c.

24{
25 PetscErrorCode ierr;
26 SimCtx *simCtx = user->simCtx; // Access global settings if needed
27
28 PetscFunctionBeginUser;
29 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d, Block %d: Updating solver history vectors.\n",
30 simCtx->rank, user->_this);
31
32 // --- Primary Contravariant Velocity History ---
33 // The order is critical here.
34 // 1. First, move the n-1 state (Ucont_o) to the n-2 slot (Ucont_rm1).
35 ierr = VecCopy(user->Ucont_o, user->Ucont_rm1); CHKERRQ(ierr);
36 // 2. Then, move the new n state (Ucont) to the n-1 slot (Ucont_o).
37 ierr = VecCopy(user->Ucont, user->Ucont_o); CHKERRQ(ierr);
38
39 LOG_ALLOW(LOCAL,LOG_DEBUG, "Rank %d, Block %d, Ucont history updated.\n",simCtx->rank,user->_this);
40
41 // --- Update History for Other Fields ---
42 // These are typically only needed at the n-1 state.
43 ierr = VecCopy(user->Ucat, user->Ucat_o); CHKERRQ(ierr);
44 ierr = VecCopy(user->P, user->P_o); CHKERRQ(ierr);
45 LOG_ALLOW(LOCAL,LOG_DEBUG, "Rank %d, Block %d, Ucat & P history updated.\n",simCtx->rank,user->_this);
46
47 if (simCtx->immersed) {
48 ierr = VecCopy(user->Nvert, user->Nvert_o); CHKERRQ(ierr);
49 }
50
51 // --- Update History for Turbulence Models (if active) ---
52 if (simCtx->rans) {
53 ierr = VecCopy(user->K_Omega, user->K_Omega_o); CHKERRQ(ierr);
54 }
55
56 // --- Synchronize Local Ghost Regions for the new history vectors ---
57 // This is essential so that stencils in the next time step's calculations
58 // have correct values from neighboring processes.
59 ierr = DMGlobalToLocalBegin(user->fda, user->Ucont_o, INSERT_VALUES, user->lUcont_o); CHKERRQ(ierr);
60 ierr = DMGlobalToLocalEnd(user->fda, user->Ucont_o, INSERT_VALUES, user->lUcont_o); CHKERRQ(ierr);
61
62 ierr = DMGlobalToLocalBegin(user->fda, user->Ucont_rm1, INSERT_VALUES, user->lUcont_rm1); CHKERRQ(ierr);
63 ierr = DMGlobalToLocalEnd(user->fda, user->Ucont_rm1, INSERT_VALUES, user->lUcont_rm1); CHKERRQ(ierr);
64
65 if (simCtx->immersed) {
66 ierr = DMGlobalToLocalBegin(user->da, user->Nvert_o, INSERT_VALUES, user->lNvert_o); CHKERRQ(ierr);
67 ierr = DMGlobalToLocalEnd(user->da, user->Nvert_o, INSERT_VALUES, user->lNvert_o); CHKERRQ(ierr);
68 }
69
70 if (simCtx->rans) {
71 ierr = DMGlobalToLocalBegin(user->fda2, user->K_Omega_o, INSERT_VALUES, user->lK_Omega_o); CHKERRQ(ierr);
72 ierr = DMGlobalToLocalEnd(user->fda2, user->K_Omega_o, INSERT_VALUES, user->lK_Omega_o); CHKERRQ(ierr);
73 }
74
75 PetscFunctionReturn(0);
76}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
PetscMPIInt rank
Definition variables.h:588
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:731
PetscInt rans
Definition variables.h:669
Vec K_Omega_o
Definition variables.h:783
Vec K_Omega
Definition variables.h:783
Vec lUcont_rm1
Definition variables.h:763
PetscInt _this
Definition variables.h:741
Vec Ucont
Definition variables.h:755
Vec lUcont_o
Definition variables.h:762
Vec Ucat_o
Definition variables.h:762
Vec lK_Omega_o
Definition variables.h:783
Vec Ucat
Definition variables.h:755
Vec Ucont_o
Definition variables.h:762
Vec Nvert_o
Definition variables.h:762
Vec Ucont_rm1
Definition variables.h:763
Vec Nvert
Definition variables.h:755
Vec lNvert_o
Definition variables.h:762
PetscInt immersed
Definition variables.h:614
Vec P_o
Definition variables.h:762
The master context for the entire simulation.
Definition variables.h:585
Here is the caller graph for this function:

◆ PerformInitializedParticleSetup()

PetscErrorCode PerformInitializedParticleSetup ( SimCtx simCtx)

Finalizes the simulation setup at t=0, ensuring a consistent state before time marching.

This function is called from main() after the initial Eulerian and Lagrangian states have been created but before the main time loop begins. Its responsibilities are:

  1. Settling the particle swarm: Migrates particles to their correct owner ranks and finds their initial host cells. This includes handling special surface initializations.
  2. Coupling the fields: Interpolates the initial Eulerian fields to the settled particle locations.
  3. Preparing for the first step: Scatters particle data back to the grid.
  4. Writing the initial output for step 0.
Parameters
simCtxPointer to the main simulation context structure.
Returns
PetscErrorCode 0 on success, non-zero on failure.

Definition at line 95 of file simulation.c.

96{
97 PetscErrorCode ierr;
98 // --- Get pointers from SimCtx instead of passing them as arguments ---
99 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
100 BoundingBox *bboxlist = simCtx->bboxlist;
101
102 PetscFunctionBeginUser;
103
104 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Performing initial particle setup procedures.\n", simCtx->ti, simCtx->step);
105
106 // --- 0. Loop over all blocks to compute Eulerian diffusivity.
107 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
108 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
109 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
110 }
111
112 // --- 1. Initial Particle Settlement (Location and Migration) ---
113 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Initial Settlement: Locating and migrating all particles...\n", simCtx->ti, simCtx->step);
114 ierr = LocateAllParticlesInGrid(user, bboxlist); CHKERRQ(ierr);
115
117 LOG_ALLOW(GLOBAL, LOG_DEBUG, "[T=%.4f, Step=%d] Particle field states after Initial settlement...\n", simCtx->ti, simCtx->step);
118 ierr = LOG_PARTICLE_FIELDS(user,simCtx->LoggingFrequency); CHKERRQ(ierr);
119 }
120
121 // --- 2. Re-initialize Particles on Inlet Surface (if applicable) ---
124 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Re-initializing particles on inlet surface...\n", simCtx->ti, simCtx->step);
125 ierr = ReinitializeParticlesOnInletSurface(user, simCtx->ti, simCtx->step); CHKERRQ(ierr);
126
127 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Resetting statuses for post-reinitialization settlement.\n", simCtx->ti, simCtx->step);
128 ierr = ResetAllParticleStatuses(user); CHKERRQ(ierr);
129
130 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Post-Reinitialization Settlement...\n", simCtx->ti, simCtx->step);
131 ierr = LocateAllParticlesInGrid(user, bboxlist); CHKERRQ(ierr);
132
133 }
134
135 // --- 3. Finalize State for t=0 ---
136 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Interpolating initial fields to settled particles.\n", simCtx->ti, simCtx->step);
137 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
138 //ierr = ScatterAllParticleFieldsToEulerFields(user); CHKERRQ(ierr);
139
140 // --- 4. Initial History and Output ---
141 // Update solver history vectors with the t=0 state before the first real step
142 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
143 ierr = UpdateSolverHistoryVectors(&user[bi]); CHKERRQ(ierr);
144 }
145
146 if (simCtx->OutputFreq > 0 || (simCtx->StepsToRun == 0 && simCtx->StartStep == 0)) {
147 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Writing initial simulation data.\n", simCtx->ti, simCtx->step);
148
149 // --- Particle Output (assumes functions operate on the master user context) ---
150 if(get_log_level() == LOG_DEBUG){
151 LOG(GLOBAL, LOG_DEBUG, "[T=%.4f, Step=%d] Initial Particle field.\n", simCtx->ti, simCtx->step);
152 ierr = LOG_PARTICLE_FIELDS(user,simCtx->LoggingFrequency); CHKERRQ(ierr);
153 }
154 ierr = WriteAllSwarmFields(user); CHKERRQ(ierr);
155
156 // --- Eulerian Field Output (MUST loop over all blocks) --- // <<< CHANGED/FIXED
157 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
158 ierr = WriteSimulationFields(&user[bi]); CHKERRQ(ierr);
159 }
160 }
161
162 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initial setup complete. Ready for time marching. ---\n");
163 PetscFunctionReturn(0);
164}
PetscErrorCode LocateAllParticlesInGrid(UserCtx *user, BoundingBox *bboxlist)
Orchestrates the complete particle location and migration process for one timestep.
PetscErrorCode ResetAllParticleStatuses(UserCtx *user)
This function is designed to be called at the end of a full timestep, after all particle-based calcul...
PetscErrorCode ReinitializeParticlesOnInletSurface(UserCtx *user, PetscReal currentTime, PetscInt step)
Re-initializes the positions of particles currently on this rank if this rank owns part of the design...
PetscErrorCode InterpolateAllFieldsToSwarm(UserCtx *user)
Interpolates all relevant fields from the DMDA to the DMSwarm.
PetscErrorCode WriteAllSwarmFields(UserCtx *user)
Writes a predefined set of PETSc Swarm fields to files.
Definition io.c:2061
PetscErrorCode WriteSimulationFields(UserCtx *user)
Writes simulation fields to files.
Definition io.c:1761
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:157
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:84
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:39
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Prints particle fields in a table that automatically adjusts its column widths.
Definition logging.c:400
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
PetscErrorCode ComputeEulerianDiffusivityGradient(UserCtx *user)
Computes the gradient of the scalar Diffusivity field (Drift Vector).
Definition rhs.c:2115
PetscErrorCode ComputeEulerianDiffusivity(UserCtx *user)
Computes the effective diffusivity scalar field ($\Gamma_{eff}$) on the Eulerian grid.
Definition rhs.c:1985
PetscErrorCode UpdateSolverHistoryVectors(UserCtx *user)
Copies the current time step's solution fields into history vectors (e.g., U(t_n) -> U_o,...
Definition simulation.c:23
#define __FUNCT__
Definition simulation.c:79
UserCtx * user
Definition variables.h:474
PetscBool inletFaceDefined
Definition variables.h:747
PetscInt block_number
Definition variables.h:649
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:466
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:469
UserMG usermg
Definition variables.h:698
PetscInt StepsToRun
Definition variables.h:596
PetscInt StartStep
Definition variables.h:595
BoundingBox * bboxlist
Definition variables.h:679
ParticleInitializationType ParticleInitialization
Definition variables.h:680
PetscInt OutputFreq
Definition variables.h:602
PetscInt mglevels
Definition variables.h:481
PetscInt step
Definition variables.h:593
MGCtx * mgctx
Definition variables.h:484
PetscReal ti
Definition variables.h:594
PetscInt LoggingFrequency
Definition variables.h:703
Defines a 3D axis-aligned bounding box.
Definition variables.h:154
User-defined context containing data specific to a single computational grid level.
Definition variables.h:728
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PerformLoadedParticleSetup()

PetscErrorCode PerformLoadedParticleSetup ( SimCtx simCtx)

Finalizes the simulation state after particle and fluid data have been loaded from a restart.

This helper function performs the critical sequence of operations required to ensure the loaded Lagrangian and Eulerian states are fully consistent and the solver is ready to proceed. This includes:

  1. Verifying particle locations in the grid and building runtime links.
  2. Synchronizing particle velocity with the authoritative grid velocity via interpolation.
  3. Scattering particle source terms (e.g., volume fraction) back to the grid.
  4. Updating the solver's history vectors with the final, fully-coupled state.
  5. Writing the complete, consistent state to output files for the restart step.
Parameters
simCtxThe main simulation context.
Returns
PetscErrorCode 0 on success.

Definition at line 183 of file simulation.c.

184{
185 PetscErrorCode ierr;
186 PetscFunctionBeginUser;
187 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
188
189 // --- 0. Re-compute Eulerian Diffusivity from loaded fields.
190 LOG_ALLOW(GLOBAL, LOG_INFO, "Re-computing Eulerian Diffusivity from loaded fields...\n");
191 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
192 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
193 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
194 }
195
196 // 0.1 This moves particles to their correct ranks immediately using the loaded Cell ID.
197 LOG_ALLOW(GLOBAL, LOG_INFO, "Performing fast restart migration using preloaded Cell IDs...\n");
198 ierr = MigrateRestartParticlesUsingCellID(user); CHKERRQ(ierr);
199
200 // 1. To catch any edge cases (particles with invalid CellIDs or newcomers).
201 // Because we kept the statuses, this function will now SKIP all the particles
202 // that are already on the correct rank,
203 ierr = LocateAllParticlesInGrid(user, simCtx->bboxlist); CHKERRQ(ierr);
204
205 if(get_log_level() == LOG_DEBUG){
206 LOG(GLOBAL, LOG_DEBUG, "[T=%.4f, Step=%d] Particle field states after locating loaded particles...\n", simCtx->ti, simCtx->step);
207 ierr = LOG_PARTICLE_FIELDS(user,simCtx->LoggingFrequency); CHKERRQ(ierr);
208 }
209
210 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Interpolating initial fields to settled particles.\n", simCtx->ti, simCtx->step);
211
212 // 2. Ensure particles have velocity from the authoritative loaded grid for consistency.
213 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
214
215 // 3. Update Eulerian source terms from the loaded particle data.
216 ierr = ScatterAllParticleFieldsToEulerFields(user); CHKERRQ(ierr);
217
218 // --- 4. Initial History and Output ---
219 // Update solver history vectors with the t=0 state before the first real step
220 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
221 ierr = UpdateSolverHistoryVectors(&user[bi]); CHKERRQ(ierr);
222 }
223
224 if (simCtx->OutputFreq > 0 || (simCtx->StepsToRun == 0 && simCtx->StartStep == 0)) {
225 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Writing initial simulation data.\n", simCtx->ti, simCtx->step);
226
227 // --- Particle Output (assumes functions operate on the master user context) ---
228 if(get_log_level() >=LOG_INFO) ierr = LOG_PARTICLE_FIELDS(user, simCtx->LoggingFrequency); CHKERRQ(ierr);
229 ierr = WriteAllSwarmFields(user); CHKERRQ(ierr);
230
231 // --- Eulerian Field Output (MUST loop over all blocks) --- // <<< CHANGED/FIXED
232 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
233 ierr = WriteSimulationFields(&user[bi]); CHKERRQ(ierr);
234 }
235 }
236
237 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initial setup complete. Ready for time marching. ---\n");
238 PetscFunctionReturn(0);
239}
PetscErrorCode MigrateRestartParticlesUsingCellID(UserCtx *user)
Fast-path migration for restart particles using preloaded Cell IDs.
PetscErrorCode ScatterAllParticleFieldsToEulerFields(UserCtx *user)
Scatters a predefined set of particle fields to their corresponding Eulerian fields.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FinalizeRestartState()

PetscErrorCode FinalizeRestartState ( SimCtx simCtx)

Performs post-load/post-init consistency checks for a restarted simulation.

This function is called from main() ONLY when a restart is being performed (i.e., StartStep > 0). It inspects the particle restart mode to determine the correct finalization procedure for the Lagrangian swarm.

  • If particles were loaded from a file (mode == "load"), it verifies their locations within the grid to establish necessary runtime links.
  • If new particles were initialized into the restarted flow (mode == "init"), it runs the full PerformInitialSetup sequence to migrate, locate, and couple the new particles with the existing fluid state.
Parameters
simCtxThe main simulation context.
Returns
PetscErrorCode 0 on success.

Definition at line 259 of file simulation.c.

260{
261 PetscErrorCode ierr;
262 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
263
264 PetscFunctionBeginUser;
265
266 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Finalizing RESTART from state (step=%d, t=%.4f) ---\n", simCtx->StartStep, simCtx->ti);
267
268 // This function only needs to handle the particle finalization logic.
269 // The Eulerian state is assumed to be fully loaded and consistent at this point.
270 if (simCtx->np > 0) {
271
272 // Use the particle restart mode to decide the workflow.
273 if (strcmp(simCtx->particleRestartMode, "load") == 0) {
274 // PARTICLES WERE LOADED: The state is complete, but we must verify
275 // the loaded CellIDs and build the in-memory grid-to-particle links.
276 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle Mode 'load': Verifying particle locations and building grid links...\n");
277 ierr = PerformLoadedParticleSetup(simCtx); CHKERRQ(ierr);
278
279 } else { // Mode must be "init"
280 // PARTICLES WERE RE-INITIALIZED: They need to be fully settled and coupled
281 // to the surrounding (restarted) fluid state.
282 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle Mode 'init': Running full initial setup for new particles in restarted flow.\n");
283 ierr = PerformInitializedParticleSetup(simCtx); CHKERRQ(ierr);
284 }
285 } else {
286 LOG_ALLOW(GLOBAL, LOG_INFO, "No particles in simulation, restart finalization is complete.\n");
287
288 // Write the initial eulerian fields (this is done in PerformInitialSetup if particles exist.)
289 for(PetscInt bi = 0; bi < simCtx->block_number; bi ++){
290 ierr = WriteSimulationFields(&user[bi]); CHKERRQ(ierr);
291 }
292 }
293
294 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Restart state successfully finalized. --\n");
295
296 PetscFunctionReturn(0);
297}
PetscErrorCode PerformInitializedParticleSetup(SimCtx *simCtx)
Finalizes the simulation setup at t=0, ensuring a consistent state before time marching.
Definition simulation.c:95
PetscErrorCode PerformLoadedParticleSetup(SimCtx *simCtx)
Finalizes the simulation state after particle and fluid data have been loaded from a restart.
Definition simulation.c:183
PetscInt np
Definition variables.h:676
char particleRestartMode[16]
Definition variables.h:681
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AdvanceSimulation()

PetscErrorCode AdvanceSimulation ( SimCtx simCtx)

Executes the main time-marching loop for the coupled Euler-Lagrange simulation.

Executes the main time-marching loop for the particle simulation.

This function orchestrates the advancement of the simulation from the configured StartStep to the final step. It does NOT perform the initial t=0 setup, as that is handled by InitializeEulerianState and PerformInitialSetup in main().

For each timestep, it performs the following sequence:

  1. Pre-Solver Actions: Updates time-dependent boundary conditions (e.g., fluxin) and resets particle states for the new step.
  2. Eulerian Solve: Calls the refactored legacy FlowSolver to advance the entire fluid field by one time step.
  3. Lagrangian Update: Executes the full particle workflow: advection based on the previous step's velocity, followed by settling (location/migration) in the new grid, and finally interpolation of the new fluid velocity.
  4. Two-Way Coupling: Scatters particle data back to the grid to act as source terms for the subsequent time step.
  5. History & I/O: Updates the solver's history vectors and writes output files at the specified frequency.
Parameters
userArray of UserCtx structures for the finest grid level.
Returns
PetscErrorCode 0 on success, non-zero on failure.

Definition at line 324 of file simulation.c.

325{
326 PetscErrorCode ierr;
327 // Get the master context from the first block. All blocks share it.
328 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
329
330 // Retrieve control parameters from SimCtx for clarity
331 const PetscInt StartStep = simCtx->StartStep;
332 const PetscInt StepsToRun = simCtx->StepsToRun;
333 const PetscInt OutputFreq = simCtx->OutputFreq;
334 const PetscReal dt = simCtx->dt;
335
336 // Variables for particle removal statistics
337 //PetscInt removed_local_ob, removed_global_ob;
338 PetscInt removed_local_lost, removed_global_lost;
339
340 PetscFunctionBeginUser;
342 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting main time-marching loop: %d steps from step %d (t=%.4f), dt=%.4f\n",
343 StepsToRun, StartStep, simCtx->StartTime, dt);
344
345 // --- Main Time-Marching Loop ---
346 for (PetscInt step = StartStep; step < StartStep + StepsToRun; step++) {
347
348 // =================================================================
349 // 1. PRE-STEP SETUP
350 // =================================================================
351
352 // Update simulation time and step counters in the master context
353 simCtx->step = step + 1;
354 simCtx->ti += simCtx->dt; //simCtx->StartTime + step * simCtx->dt;
355
356 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Advancing Step %d (To t=%.4f) ---\n", simCtx->step, simCtx->ti);
357
358
359 // For particles, reset their status to prepare for the new advection/location cycle
360 if (simCtx->np > 0) {
361 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Resetting all particle statuses to NEEDS_LOCATION.\n");
362 ierr = ResetAllParticleStatuses(user); CHKERRQ(ierr);
363 }
364
365 // =================================================================
366 // 2. EULERIAN SOLVER STEP
367 // =================================================================
369 ierr = LOG_FIELD_ANATOMY(&user[0],"Coordinates","PreFlowSolver"); CHKERRQ(ierr);
370 ierr = LOG_FIELD_ANATOMY(&user[0],"Csi","PreFlowSolver"); CHKERRQ(ierr);
371 ierr = LOG_FIELD_ANATOMY(&user[0],"Eta","PreFlowSolver"); CHKERRQ(ierr);
372 ierr = LOG_FIELD_ANATOMY(&user[0],"Zet","PreFlowSolver"); CHKERRQ(ierr);
373 ierr = LOG_FIELD_ANATOMY(&user[0],"Center-Coordinates","PreFlowSolver"); CHKERRQ(ierr);
374 ierr = LOG_FIELD_ANATOMY(&user[0],"X-Face-Centers","PreFlowSolver"); CHKERRQ(ierr);
375 ierr = LOG_FIELD_ANATOMY(&user[0],"Y-Face-Centers","PreFlowSolver"); CHKERRQ(ierr);
376 ierr = LOG_FIELD_ANATOMY(&user[0],"Z-Face-Centers","PreFlowSolver"); CHKERRQ(ierr);
377 ierr = LOG_FIELD_ANATOMY(&user[0],"Ucat","PreFlowSolver"); CHKERRQ(ierr);
378 }
379 LOG_ALLOW(GLOBAL, LOG_INFO, "Updating Eulerian Field ...\n");
380 if(strcmp(simCtx->eulerianSource,"load")==0){
381 //LOAD mode: Read pre-computed fields for the current step.
382 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'load': Reading fields (t=%.4f,step=%d)...\n",simCtx->ti,simCtx->step);
383 for(PetscInt bi = 0; bi < simCtx->block_number;bi++){
384 ierr = ReadSimulationFields(&user[bi],simCtx->step); CHKERRQ(ierr);
385 }
386 }else if(strcmp(simCtx->eulerianSource,"analytical")==0){
387 // ANALYTICAL mode:Call the Analytical Solution Prescription Engine to enable a variety of analytical functions
388 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'analytical'. Updating Eulerian field via the Analytical Solution Engine ...\n");
389 ierr = AnalyticalSolutionEngine(simCtx); CHKERRQ(ierr);
390 }else if(strcmp(simCtx->eulerianSource,"solve")==0){
391 // SOLVE mode:Call the refactored, high-level legacy solver. This single function
392 // advances the entire multi-block fluid field from t_n to t_{n+1}.
393 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'solve'. Updating Eulerian field via Solver...\n");
394 ierr = FlowSolver(simCtx); CHKERRQ(ierr);
395 }
396 LOG_ALLOW(GLOBAL, LOG_INFO, "Eulerian Field Updated ...\n");
398 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Post FlowSolver field states:\n");
399 ierr = LOG_FIELD_ANATOMY(&user[0],"Ucat","PostFlowSolver"); CHKERRQ(ierr);
400 ierr = LOG_FIELD_ANATOMY(&user[0],"P","PostFlowSolver"); CHKERRQ(ierr);
401 ierr = LOG_FIELD_ANATOMY(&user[0],"Ucont","PostFlowSolver"); CHKERRQ(ierr);
402 }
403
404
405 // =================================================================
406 // 3. LAGRANGIAN PARTICLE STEP
407 // =================================================================
408
409 if (simCtx->np > 0) {
410 LOG_ALLOW(GLOBAL, LOG_INFO, "Updating Lagrangian particle system...\n");
411
412 // a. Update Eulerian Transport Properties:
413 // Optimization: Only recalculate if turbulence is active (Nu_t changes).
414 // For Laminar flow, the value calculated at Setup is constant.
415 if (simCtx->les || simCtx->rans) {
416 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
417 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
418 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
419 }
420 }
421
422 // a.1 (Optional) Log Eulerian Diffusivity min/max and anatomy for debugging.
424 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Updated Diffusivity Min/Max:\n");
425 ierr = LOG_FIELD_MIN_MAX(&user[0],"Diffusivity"); CHKERRQ(ierr);
426 ierr = LOG_FIELD_MIN_MAX(&user[0],"DiffusivityGradient"); CHKERRQ(ierr);
427 //LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Updated Diffusivity Anatomy:\n");
428 ierr = LOG_FIELD_ANATOMY(&user[0],"Diffusivity","PostDiffusivityUpdate"); CHKERRQ(ierr);
429 }
430 // b. Advect particles using the velocity interpolated from the *previous* step.
431 // P(t_{n+1}) = P(t_n) + V_p(t_n) * dt
432 ierr = UpdateAllParticlePositions(user); CHKERRQ(ierr);
433
434 // c. Settle all particles: find their new host cells and migrate them across ranks.
435 ierr = LocateAllParticlesInGrid(user, simCtx->bboxlist); CHKERRQ(ierr);
436
437 // d. Remove any particles that are now lost or out of the global domain.
438 ierr = CheckAndRemoveLostParticles(user, &removed_local_lost, &removed_global_lost); CHKERRQ(ierr);
439 //ierr = CheckAndRemoveOutOfBoundsParticles(user, &removed_local_ob, &removed_global_ob, simCtx->bboxlist); CHKERRQ(ierr);
440 if (removed_global_lost> 0) { // if(removed_global_lost + removed_global_ob > 0){
441 LOG_ALLOW(GLOBAL, LOG_INFO, "Removed %d particles globally this step.\n", removed_global_lost); // removed_global_lost + removed_global_ob;
442 simCtx->particlesLostLastStep = removed_global_lost;
443 }
444
445 // e. Interpolate the NEW fluid velocity (just computed by FlowSolver) onto the
446 // particles' new positions. This gives them V_p(t_{n+1}) for the *next* advection step.
447 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
448
449 // f. Update the Particle Fields (e.g., temperature, concentration) if applicable.
450 // This can be extended to include reactions, growth, etc.
451 ierr = UpdateAllParticleFields(user); CHKERRQ(ierr);
452
453 // g. (For Two-Way Coupling) Scatter particle data back to the grid to act as a source term.
454 ierr = CalculateParticleCountPerCell(user); CHKERRQ(ierr);
455 ierr = ScatterAllParticleFieldsToEulerFields(user); CHKERRQ(ierr);
456
457 // h. (Optional) Calculate advanced particle metrics for logging/debugging.
458 ierr = CalculateAdvancedParticleMetrics(user); CHKERRQ(ierr);
459
460 ierr = LOG_PARTICLE_METRICS(user, "Timestep Metrics"); CHKERRQ(ierr);
461
462
464 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Post Lagrangian update field states:\n");
465 ierr = LOG_FIELD_MIN_MAX(&user[0],"Psi"); CHKERRQ(ierr);
466 }
467 }
468
469 // =================================================================
470 // 4. UPDATE HISTORY & I/O
471 // =================================================================
472
473 // Copy the newly computed fields (Ucont, P, etc.) to the history vectors
474 // (_o, _rm1) to prepare for the next time step.
475 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
476 ierr = UpdateSolverHistoryVectors(&user[bi]); CHKERRQ(ierr);
477 }
478
479 //ierr = LOG_UCAT_ANATOMY(&user[0],"Final"); CHKERRQ(ierr);
480
481 // Handle periodic file output
482 if (OutputFreq > 0 && (step + 1) % OutputFreq == 0) {
483 LOG_ALLOW(GLOBAL, LOG_INFO, "Writing output for step %d.\n",simCtx->step);
484 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
485 ierr = WriteSimulationFields(&user[bi]); CHKERRQ(ierr);
486 }
487 if (simCtx->np > 0) {
488 ierr = WriteAllSwarmFields(user); CHKERRQ(ierr);
489 if(get_log_level() >= LOG_INFO){
490 LOG(GLOBAL, LOG_INFO, "Particle states at step %d:\n", simCtx->step);
492 if(strcmp(simCtx->eulerianSource,"analytical") == 0){
494 }
495 }
496 }
497 }
498
500
501 // Update Progress Bar
502 if(simCtx->rank == 0) {
503 PrintProgressBar(step,StartStep,StepsToRun,simCtx->ti);
504 if(get_log_level()>=LOG_WARNING) PetscPrintf(PETSC_COMM_SELF,"\n");
505 }
506 } // --- End of Time-Marching Loop ---
507
508 // After the loop, print the 100% complete bar on rank 0 and add a newline
509 // to ensure subsequent terminal output starts on a fresh line.
510 if (simCtx->rank == 0 && StepsToRun > 0) {
511 PrintProgressBar(StartStep + StepsToRun - 1, StartStep, StepsToRun, simCtx->ti);
512 PetscPrintf(PETSC_COMM_SELF, "\n");
513 fflush(stdout);
514 }
515
516 LOG_ALLOW(GLOBAL, LOG_INFO, "Time marching completed. Final time t=%.4f.\n", simCtx->ti);
518 PetscFunctionReturn(0);
519}
PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
Dispatches to the appropriate analytical solution function based on simulation settings.
PetscErrorCode UpdateAllParticlePositions(UserCtx *user)
Loops over all local particles in the DMSwarm, updating their positions based on velocity and the glo...
PetscErrorCode CheckAndRemoveLostParticles(UserCtx *user, PetscInt *removedCountLocal, PetscInt *removedCountGlobal)
Removes particles that have been definitively flagged as LOST by the location algorithm.
PetscErrorCode UpdateAllParticleFields(UserCtx *user)
Orchestrates the update of all physical properties for particles.
PetscErrorCode CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
PetscErrorCode ReadSimulationFields(UserCtx *user, PetscInt ti)
Reads binary field data for velocity, pressure, and other required vectors.
Definition io.c:1231
PetscErrorCode LOG_PARTICLE_METRICS(UserCtx *user, const char *stageName)
Logs particle swarm metrics, adapting its behavior based on a boolean flag in SimCtx.
Definition logging.c:1851
PetscErrorCode LOG_INTERPOLATION_ERROR(UserCtx *user)
Logs the interpolation error between the analytical and computed solutions.
Definition logging.c:1727
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:746
PetscErrorCode LOG_FIELD_MIN_MAX(UserCtx *user, const char *fieldName)
Computes and logs the local and global min/max values of a 3-component vector field.
Definition logging.c:1293
void PrintProgressBar(PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
Prints a progress bar to the console.
Definition logging.c:1227
PetscErrorCode LOG_FIELD_ANATOMY(UserCtx *user, const char *field_name, const char *stage_name)
Logs the anatomy of a specified field at key boundary locations, respecting the solver's specific gri...
Definition logging.c:1460
PetscErrorCode CalculateAdvancedParticleMetrics(UserCtx *user)
Computes advanced particle statistics and stores them in SimCtx.
Definition logging.c:1790
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:737
PetscErrorCode ProfilingLogTimestepSummary(PetscInt step)
Logs the performance summary for the current timestep and resets timers.
Definition logging.c:1064
PetscErrorCode FlowSolver(SimCtx *simCtx)
Orchestrates a single time step of the Eulerian fluid solver.
Definition solvers.c:26
PetscReal StartTime
Definition variables.h:598
PetscInt particlesLostLastStep
Definition variables.h:682
PetscReal dt
Definition variables.h:599
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:604
PetscInt les
Definition variables.h:669
Here is the call graph for this function:
Here is the caller graph for this function: