PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
runloop.c
Go to the documentation of this file.
1/**
2 * @file runloop.c
3 * @brief Test program for DMSwarm interpolation using the fdf-curvIB method.
4 * Provides the setup to start any simulation with DMSwarm and DMDAs.
5 **/
6
7#include "runloop.h"
8
9/**
10 * @brief Copies the current time step's solution fields into history vectors
11 * (e.g., U(t_n) -> U_o, U_o -> U_rm1) for the next time step's calculations.
12 *
13 * This function is critical for multi-step time integration schemes (like BDF2)
14 * used by the legacy solver. It must be called at the end of every time step,
15 * after the new solution has been fully computed.
16 *
17 * The order of operations is important to avoid overwriting data prematurely.
18 *
19 * @param user The UserCtx for a single block. The function modifies the history
20 * vectors (Ucont_o, Ucont_rm1, etc.) within this context.
21 * @return PetscErrorCode 0 on success.
22 */
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}
77
78#undef __FUNCT__
79#define __FUNCT__ "PerformInitialSetup"
80/**
81 * @brief Finalizes the simulation setup at t=0, ensuring a consistent state before time marching.
82 *
83 * This function is called from main() after the initial Eulerian and Lagrangian states have been
84 * created but before the main time loop begins. Its responsibilities are:
85 *
86 * 1. Settling the particle swarm: Migrates particles to their correct owner ranks and finds their
87 * initial host cells. This includes handling special surface initializations.
88 * 2. Coupling the fields: Interpolates the initial Eulerian fields to the settled particle locations.
89 * 3. Preparing for the first step: Scatters particle data back to the grid.
90 * 4. Writing the initial output for step 0.
91 *
92 * @param simCtx Pointer to the main simulation context structure.
93 * @return PetscErrorCode 0 on success, non-zero on failure.
94 */
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}
163
164#undef __FUNCT__
165#define __FUNCT__ "PerformLoadedParticleSetup"
166/**
167 * @brief Finalizes the simulation state after particle and fluid data have been loaded from a restart.
168 *
169 * This helper function performs the critical sequence of operations required to ensure
170 * the loaded Lagrangian and Eulerian states are fully consistent and the solver is
171 * ready to proceed. This includes:
172 * 1. Verifying particle locations in the grid and building runtime links.
173 * 2. Synchronizing particle velocity with the authoritative grid velocity via interpolation.
174 * 3. Scattering particle source terms (e.g., volume fraction) back to the grid.
175 * 4. Updating the solver's history vectors with the final, fully-coupled state.
176 * 5. Writing the complete, consistent state to output files for the restart step.
177 *
178 * @param simCtx The main simulation context.
179 * @return PetscErrorCode 0 on success.
180 */
181PetscErrorCode PerformLoadedParticleSetup(SimCtx *simCtx)
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}
239
240#undef __FUNCT__
241#define __FUNCT__ "FinalizeRestartState"
242/**
243 * @brief Performs post-load/post-init consistency checks for a restarted simulation.
244 *
245 * This function is called from main() ONLY when a restart is being performed
246 * (i.e., StartStep > 0). It inspects the particle restart mode to determine the
247 * correct finalization procedure for the Lagrangian swarm.
248 *
249 * - If particles were loaded from a file (`mode == "load"`), it verifies their
250 * locations within the grid to establish necessary runtime links.
251 * - If new particles were initialized into the restarted flow (`mode == "init"`),
252 * it runs the full `PerformInitialSetup` sequence to migrate, locate, and
253 * couple the new particles with the existing fluid state.
254 *
255 * @param simCtx The main simulation context.
256 * @return PetscErrorCode 0 on success.
257 */
258PetscErrorCode FinalizeRestartState(SimCtx *simCtx)
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}
297
298#undef __FUNCT__
299#define __FUNCT__ "AdvanceSimulation"
300/**
301 * @brief Executes the main time-marching loop for the coupled Euler-Lagrange simulation.
302 *
303 * This function orchestrates the advancement of the simulation from the configured
304 * StartStep to the final step. It does NOT perform the initial t=0 setup, as that
305 * is handled by InitializeEulerianState and PerformInitialSetup in main().
306 *
307 * For each timestep, it performs the following sequence:
308 * 1. **Pre-Solver Actions:** Updates time-dependent boundary conditions (e.g., fluxin)
309 * and resets particle states for the new step.
310 * 2. **Eulerian Solve:** Calls the refactored legacy FlowSolver to advance the
311 * entire fluid field by one time step.
312 * 3. **Lagrangian Update:** Executes the full particle workflow: advection based
313 * on the previous step's velocity, followed by settling (location/migration)
314 * in the new grid, and finally interpolation of the new fluid velocity.
315 * 4. **Two-Way Coupling:** Scatters particle data back to the grid to act as source
316 * terms for the subsequent time step.
317 * 5. **History & I/O:** Updates the solver's history vectors and writes output files
318 * at the specified frequency.
319 *
320 * @param user Array of UserCtx structures for the finest grid level.
321 * @return PetscErrorCode 0 on success, non-zero on failure.
322 */
323PetscErrorCode AdvanceSimulation(SimCtx *simCtx)
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 MigrateRestartParticlesUsingCellID(UserCtx *user)
Fast-path migration for restart particles using preloaded Cell IDs.
PetscErrorCode UpdateAllParticlePositions(UserCtx *user)
Loops over all local particles in the DMSwarm, updating their positions based on velocity and the glo...
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 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 ScatterAllParticleFieldsToEulerFields(UserCtx *user)
Scatters a predefined set of particle fields to their corresponding Eulerian fields.
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 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 WriteSimulationFields(UserCtx *user)
Writes simulation fields to files.
Definition io.c:1829
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
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:153
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:44
PetscErrorCode LOG_INTERPOLATION_ERROR(UserCtx *user)
Logs the interpolation error between the analytical and computed solutions.
Definition logging.c:1777
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
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 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
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
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:761
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:83
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
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:40
PetscErrorCode ProfilingLogTimestepSummary(SimCtx *simCtx, PetscInt step)
Logs the performance summary for the current timestep and resets timers.
Definition logging.c:1085
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Prints particle fields in a table that automatically adjusts its column widths.
Definition logging.c:396
PetscErrorCode CalculateAdvancedParticleMetrics(UserCtx *user)
Computes advanced particle statistics and stores them in SimCtx.
Definition logging.c:1840
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
@ 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 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 AdvanceSimulation(SimCtx *simCtx)
Executes the main time-marching loop for the coupled Euler-Lagrange simulation.
Definition runloop.c:323
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
PetscErrorCode FinalizeRestartState(SimCtx *simCtx)
Performs post-load/post-init consistency checks for a restarted simulation.
Definition runloop.c:258
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
#define __FUNCT__
Definition runloop.c:79
PetscErrorCode FlowSolver(SimCtx *simCtx)
Orchestrates a single time step of the Eulerian fluid solver.
Definition solvers.c:26
UserCtx * user
Definition variables.h:476
PetscBool inletFaceDefined
Definition variables.h:757
PetscMPIInt rank
Definition variables.h:594
PetscInt block_number
Definition variables.h:656
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:741
PetscInt rans
Definition variables.h:676
@ 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
PetscReal StartTime
Definition variables.h:605
Vec K_Omega_o
Definition variables.h:792
PetscInt particlesLostLastStep
Definition variables.h:689
PetscInt tiout
Definition variables.h:603
UserMG usermg
Definition variables.h:705
Vec K_Omega
Definition variables.h:792
Vec lUcont_rm1
Definition variables.h:772
PetscInt _this
Definition variables.h:751
PetscReal dt
Definition variables.h:606
PetscInt StepsToRun
Definition variables.h:602
PetscInt np
Definition variables.h:683
Vec Ucont
Definition variables.h:764
PetscInt StartStep
Definition variables.h:601
Vec lUcont_o
Definition variables.h:771
Vec Ucat_o
Definition variables.h:771
char particleRestartMode[16]
Definition variables.h:688
BoundingBox * bboxlist
Definition variables.h:686
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:610
ParticleInitializationType ParticleInitialization
Definition variables.h:687
Vec lK_Omega_o
Definition variables.h:792
Vec Ucat
Definition variables.h:764
Vec Ucont_o
Definition variables.h:771
PetscInt mglevels
Definition variables.h:483
Vec Nvert_o
Definition variables.h:771
Vec Ucont_rm1
Definition variables.h:772
PetscInt step
Definition variables.h:599
PetscInt les
Definition variables.h:676
Vec Nvert
Definition variables.h:764
MGCtx * mgctx
Definition variables.h:486
Vec lNvert_o
Definition variables.h:771
PetscReal ti
Definition variables.h:600
PetscInt immersed
Definition variables.h:620
PetscInt LoggingFrequency
Definition variables.h:710
Vec P_o
Definition variables.h:771
Defines a 3D axis-aligned bounding box.
Definition variables.h:154
The master context for the entire simulation.
Definition variables.h:591
User-defined context containing data specific to a single computational grid level.
Definition variables.h:738