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

Test program for DMSwarm interpolation using the fdf-curvIB method. More...

#include "runloop.h"
Include dependency graph for runloop.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

Test program for DMSwarm interpolation using the fdf-curvIB method.

Provides the setup to start any simulation with DMSwarm and DMDAs.

Definition in file runloop.c.

Macro Definition Documentation

◆ __FUNCT__ [1/4]

#define __FUNCT__   "PerformInitialSetup"

Definition at line 79 of file runloop.c.

◆ __FUNCT__ [2/4]

#define __FUNCT__   "PerformLoadedParticleSetup"

Definition at line 79 of file runloop.c.

◆ __FUNCT__ [3/4]

#define __FUNCT__   "FinalizeRestartState"

Definition at line 79 of file runloop.c.

◆ __FUNCT__ [4/4]

#define __FUNCT__   "AdvanceSimulation"

Definition at line 79 of file runloop.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 runloop.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:44
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:199
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
PetscMPIInt rank
Definition variables.h:594
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:741
PetscInt rans
Definition variables.h:676
Vec K_Omega_o
Definition variables.h:792
Vec K_Omega
Definition variables.h:792
Vec lUcont_rm1
Definition variables.h:772
PetscInt _this
Definition variables.h:751
Vec Ucont
Definition variables.h:764
Vec lUcont_o
Definition variables.h:771
Vec Ucat_o
Definition variables.h:771
Vec lK_Omega_o
Definition variables.h:792
Vec Ucat
Definition variables.h:764
Vec Ucont_o
Definition variables.h:771
Vec Nvert_o
Definition variables.h:771
Vec Ucont_rm1
Definition variables.h:772
Vec Nvert
Definition variables.h:764
Vec lNvert_o
Definition variables.h:771
PetscInt immersed
Definition variables.h:620
Vec P_o
Definition variables.h:771
The master context for the entire simulation.
Definition variables.h:591
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 runloop.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->tiout > 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 ierr = WriteAllSwarmFields(user); CHKERRQ(ierr);
149
150 // --- Eulerian Field Output (MUST loop over all blocks) --- // <<< CHANGED/FIXED
151 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
152 ierr = WriteSimulationFields(&user[bi]); CHKERRQ(ierr);
153 }
154 }
155
157 ierr = EmitParticleConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
158 }
159
160 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initial setup complete. Ready for time marching. ---\n");
161 PetscFunctionReturn(0);
162}
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:2129
PetscErrorCode WriteSimulationFields(UserCtx *user)
Writes simulation fields to files.
Definition io.c:1829
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:153
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
PetscBool IsParticleConsoleSnapshotEnabled(const SimCtx *simCtx)
Returns whether periodic particle console snapshots are enabled.
Definition logging.c:517
PetscErrorCode EmitParticleConsoleSnapshot(UserCtx *user, SimCtx *simCtx, PetscInt step)
Emits one particle console snapshot into the main solver log.
Definition logging.c:534
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:40
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Prints particle fields in a table that automatically adjusts its column widths.
Definition logging.c:396
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
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 runloop.c:23
#define __FUNCT__
Definition runloop.c:79
UserCtx * user
Definition variables.h:476
PetscBool inletFaceDefined
Definition variables.h:757
PetscInt block_number
Definition variables.h:656
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:468
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:471
PetscInt tiout
Definition variables.h:603
UserMG usermg
Definition variables.h:705
PetscInt StepsToRun
Definition variables.h:602
PetscInt StartStep
Definition variables.h:601
BoundingBox * bboxlist
Definition variables.h:686
ParticleInitializationType ParticleInitialization
Definition variables.h:687
PetscInt mglevels
Definition variables.h:483
PetscInt step
Definition variables.h:599
MGCtx * mgctx
Definition variables.h:486
PetscReal ti
Definition variables.h:600
PetscInt LoggingFrequency
Definition variables.h:710
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:738
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 181 of file runloop.c.

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

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

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