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 <signal.h>
8
9#include "runloop.h"
10#include "statistics_window.h"
13
14static volatile sig_atomic_t g_runtime_shutdown_signal = 0;
15static PetscBool g_runtime_shutdown_auto_requested = PETSC_FALSE;
16
17/**
18 * @brief Record receipt of a termination signal for safe handling by the run loop.
19 */
20static void RuntimeShutdownSignalHandler(int signum)
21{
24 }
25}
26
27/**
28 * @brief Request a controlled shutdown because the estimated walltime margin is exhausted.
29 */
31{
34 }
35}
36
37/**
38 * @brief Report whether a signal or walltime guard has requested run-loop shutdown.
39 */
40static PetscBool RuntimeShutdownRequested(void)
41{
43}
44
45/**
46 * @brief Makes the Eulerian particle averages consistent with the particles before step 1.
47 * @details The first step's particle update relaxes each particle toward the scattered
48 * Eulerian mean, and its own scatter comes only after that update. So whatever
49 * the particles hold at setup - an initial condition, a loaded state, or the
50 * verification profile - must be scattered here, or step 1 relaxes toward a mean
51 * that never saw it. The verification profile, when active, is applied first.
52 * Local to this translation unit.
53 */
54static PetscErrorCode RefreshScatteredParticleState(UserCtx *user)
55{
56 PetscFunctionBeginUser;
57 if (!user) PetscFunctionReturn(0);
60 }
62 PetscFunctionReturn(0);
63}
64
65/**
66 * @brief Translate a recorded termination signal into a user-facing signal name.
67 */
68static const char *RuntimeShutdownSignalName(PetscInt signum)
69{
70 switch (signum) {
71#ifdef SIGTERM
72 case SIGTERM: return "SIGTERM";
73#endif
74#ifdef SIGUSR1
75 case SIGUSR1: return "SIGUSR1";
76#endif
77#ifdef SIGINT
78 case SIGINT: return "SIGINT";
79#endif
80 default: return "UNKNOWN";
81 }
82}
83
84/**
85 * @brief Translate the current shutdown reason into a user-facing diagnostic label.
86 */
87static const char *RuntimeShutdownReasonName(void)
88{
91 }
93 return "AUTO_WALLTIME_GUARD";
94 }
95 return "NONE";
96}
97
98/**
99 * @brief Install the process signal handler used to request graceful simulation shutdown.
100 */
101static PetscErrorCode RegisterRuntimeSignalHandler(int signum)
102{
103 struct sigaction action;
104
105 PetscFunctionBeginUser;
106 memset(&action, 0, sizeof(action));
107 action.sa_handler = RuntimeShutdownSignalHandler;
108
109 if (sigemptyset(&action.sa_mask) != 0) {
110 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "sigemptyset failed for signal %d.", signum);
111 }
112
113 if (sigaction(signum, &action, NULL) != 0) {
114 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "sigaction failed for signal %d.", signum);
115 }
116
117 PetscFunctionReturn(0);
118}
119
120/**
121 * @brief Implementation of \ref InitializeRuntimeSignalHandlers().
122 * @details Full API contract (arguments, ownership, side effects) is documented with
123 * the matching public header declaration.
124 * @see InitializeRuntimeSignalHandlers()
125 */
127{
128 PetscErrorCode ierr;
129
130 PetscFunctionBeginUser;
133
134#ifdef SIGTERM
135 ierr = RegisterRuntimeSignalHandler(SIGTERM); CHKERRQ(ierr);
136#endif
137#ifdef SIGUSR1
138 ierr = RegisterRuntimeSignalHandler(SIGUSR1); CHKERRQ(ierr);
139#endif
140#ifdef SIGINT
141 ierr = RegisterRuntimeSignalHandler(SIGINT); CHKERRQ(ierr);
142#endif
143
144 PetscFunctionReturn(0);
145}
146
147/**
148 * @brief Implementation of \ref RuntimeWalltimeGuardUpdateEWMA().
149 * @details Full API contract (arguments, ownership, side effects) is documented with
150 * the matching public header declaration.
151 * @see RuntimeWalltimeGuardUpdateEWMA()
152 */
153PetscReal RuntimeWalltimeGuardUpdateEWMA(PetscBool has_previous, PetscReal previous_ewma_seconds, PetscReal latest_step_seconds, PetscReal alpha)
154{
155 if (!has_previous) return latest_step_seconds;
156 return alpha * latest_step_seconds + (1.0 - alpha) * previous_ewma_seconds;
157}
158
159/**
160 * @brief Implementation of \ref RuntimeWalltimeGuardConservativeEstimate().
161 * @details Full API contract (arguments, ownership, side effects) is documented with
162 * the matching public header declaration.
163 * @see RuntimeWalltimeGuardConservativeEstimate()
164 */
165PetscReal RuntimeWalltimeGuardConservativeEstimate(PetscReal warmup_average_seconds, PetscReal ewma_seconds, PetscReal latest_step_seconds)
166{
167 return PetscMax(warmup_average_seconds, PetscMax(ewma_seconds, latest_step_seconds));
168}
169
170/**
171 * @brief Implementation of \ref RuntimeWalltimeGuardRequiredHeadroom().
172 * @details Full API contract (arguments, ownership, side effects) is documented with
173 * the matching public header declaration.
174 * @see RuntimeWalltimeGuardRequiredHeadroom()
175 */
176PetscReal RuntimeWalltimeGuardRequiredHeadroom(PetscReal min_seconds, PetscReal multiplier, PetscReal conservative_estimate_seconds)
177{
178 return PetscMax(min_seconds, multiplier * conservative_estimate_seconds);
179}
180
181/**
182 * @brief Implementation of \ref RuntimeWalltimeGuardShouldTrigger().
183 * @details Full API contract (arguments, ownership, side effects) is documented with
184 * the matching public header declaration.
185 * @see RuntimeWalltimeGuardShouldTrigger()
186 */
187PetscBool RuntimeWalltimeGuardShouldTrigger(PetscInt completed_steps, PetscInt warmup_steps, PetscReal remaining_seconds, PetscReal min_seconds, PetscReal multiplier, PetscReal warmup_average_seconds, PetscReal ewma_seconds, PetscReal latest_step_seconds, PetscReal *required_headroom_seconds_out)
188{
189 PetscReal conservative_estimate = 0.0;
190 PetscReal required_headroom = 0.0;
191
192 if (required_headroom_seconds_out) *required_headroom_seconds_out = 0.0;
193 if (completed_steps < warmup_steps) return PETSC_FALSE;
194
195 conservative_estimate = RuntimeWalltimeGuardConservativeEstimate(warmup_average_seconds, ewma_seconds, latest_step_seconds);
196 required_headroom = RuntimeWalltimeGuardRequiredHeadroom(min_seconds, multiplier, conservative_estimate);
197 if (required_headroom_seconds_out) *required_headroom_seconds_out = required_headroom;
198 return (PetscBool)(remaining_seconds <= required_headroom);
199}
200
201/**
202 * @brief Estimate the remaining scheduler walltime after reserving the configured shutdown margin.
203 */
204static PetscReal RuntimeWalltimeGuardRemainingSeconds(const SimCtx *simCtx)
205{
206 time_t now = time(NULL);
207
208 if (now == (time_t)-1) return -1.0;
209 return simCtx->walltimeGuardLimitSeconds - ((PetscReal)now - simCtx->walltimeGuardJobStartEpochSeconds);
210}
211
212/**
213 * @brief Update the timestep-duration estimate used by the automatic walltime guard.
214 */
215static void UpdateRuntimeWalltimeGuardEstimator(SimCtx *simCtx, PetscReal completed_step_seconds)
216{
218 simCtx->walltimeGuardLatestStepSeconds = completed_step_seconds;
219
221 simCtx->walltimeGuardWarmupTotalSeconds += completed_step_seconds;
225 simCtx->walltimeGuardHasEWMA = PETSC_TRUE;
226 }
227 return;
228 }
229
231 simCtx->walltimeGuardHasEWMA,
233 completed_step_seconds,
235 );
236 simCtx->walltimeGuardHasEWMA = PETSC_TRUE;
237}
238
239/**
240 * @brief Request graceful shutdown when another timestep would exceed the walltime budget.
241 */
242static PetscErrorCode MaybeRequestRuntimeWalltimeGuardShutdown(SimCtx *simCtx, const char *checkpoint_name)
243{
244 PetscReal remaining_seconds = 0.0;
245 PetscReal required_headroom = 0.0;
246
247 PetscFunctionBeginUser;
248 if (!simCtx->walltimeGuardActive || RuntimeShutdownRequested()) PetscFunctionReturn(0);
249
250 remaining_seconds = RuntimeWalltimeGuardRemainingSeconds(simCtx);
254 remaining_seconds,
260 &required_headroom)) {
261 PetscFunctionReturn(0);
262 }
263
265 LOG_ALLOW(
266 GLOBAL,
268 "[T=%.4f, Step=%d] AUTO_WALLTIME_GUARD requested at %s: remaining walltime %.1f s <= required headroom %.1f s "
269 "(warmup avg %.1f s, ewma %.1f s, latest %.1f s).\n",
270 simCtx->ti,
271 simCtx->step,
272 checkpoint_name,
273 (double)remaining_seconds,
274 (double)required_headroom,
275 (double)simCtx->walltimeGuardWarmupAverageSeconds,
276 (double)simCtx->walltimeGuardEWMASeconds,
277 (double)simCtx->walltimeGuardLatestStepSeconds
278 );
279
280 PetscFunctionReturn(0);
281}
282
283/**
284 * @brief Write restart-safe output when a controlled shutdown interrupts the run loop.
285 */
286static PetscErrorCode WriteForcedTerminationOutput(SimCtx *simCtx, UserCtx *user, const char *phase)
287{
288 PetscErrorCode ierr;
289
290 PetscFunctionBeginUser;
291
292 ierr = RuntimeMemoryLogSample(simCtx, simCtx->step, "Shutdown", RuntimeShutdownReasonName()); CHKERRQ(ierr);
293
295 "[T=%.4f, Step=%d] Shutdown requested by %s during %s. Writing final output outside the normal cadence before exiting.\n",
296 simCtx->ti, simCtx->step, RuntimeShutdownReasonName(), phase);
297
298 ierr = WriteCheckpointBundle(simCtx, "signal"); CHKERRQ(ierr);
299
301 ierr = EmitParticleConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
302 }
303
304 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRMPI(ierr);
305 fflush(stdout);
306
307 PetscFunctionReturn(0);
308}
309
310/**
311 * @brief Internal helper implementation: `UpdateSolverHistoryVectors()`.
312 * @details Local to this translation unit.
313 */
314PetscErrorCode UpdateSolverHistoryVectors(UserCtx *user, PetscBool preserve_previous_state)
315{
316 PetscErrorCode ierr;
317 SimCtx *simCtx = user->simCtx; // Access global settings if needed
318
319 PetscFunctionBeginUser;
320 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d, Block %d: Updating solver history vectors.\n",
321 simCtx->rank, user->_this);
322
323 // --- Primary Contravariant Velocity History ---
324 // The order is critical here.
325 // 1. Move n-1 into n-2 during normal advancement. A restored checkpoint
326 // already supplied the authoritative n-1 state in Ucont_rm1.
327 if (!preserve_previous_state) {
328 ierr = VecCopy(user->Ucont_o, user->Ucont_rm1); CHKERRQ(ierr);
329 }
330 // 2. Then, move the new n state (Ucont) to the n-1 slot (Ucont_o).
331 ierr = VecCopy(user->Ucont, user->Ucont_o); CHKERRQ(ierr);
332
333 LOG_ALLOW(LOCAL,LOG_DEBUG, "Rank %d, Block %d, Ucont history updated.\n",simCtx->rank,user->_this);
334
335 // --- Update History for Other Fields ---
336 // These are typically only needed at the n-1 state.
337 ierr = VecCopy(user->Ucat, user->Ucat_o); CHKERRQ(ierr);
338 ierr = VecCopy(user->P, user->P_o); CHKERRQ(ierr);
339 LOG_ALLOW(LOCAL,LOG_DEBUG, "Rank %d, Block %d, Ucat & P history updated.\n",simCtx->rank,user->_this);
340
341 if (simCtx->immersed) {
342 ierr = VecCopy(user->Nvert, user->Nvert_o); CHKERRQ(ierr);
343 }
344
345 // --- Synchronize Local Ghost Regions for the new history vectors ---
346 // This is essential so that stencils in the next time step's calculations
347 // have correct values from neighboring processes.
348 ierr = UpdateLocalGhosts(user, FIELD_ID_UCONT_O); CHKERRQ(ierr);
349 ierr = UpdateLocalGhosts(user, FIELD_ID_UCONT_RM1); CHKERRQ(ierr);
350
351 if (simCtx->immersed) {
352 ierr = UpdateLocalGhosts(user, FIELD_ID_NVERT_O); CHKERRQ(ierr);
353 }
354
355 PetscFunctionReturn(0);
356}
357
358#undef __FUNCT__
359#define __FUNCT__ "PerformInitialSetup"
360/**
361 * @brief Internal helper implementation: `PerformInitializedParticleSetup()`.
362 * @details Local to this translation unit.
363 */
365{
366 PetscErrorCode ierr;
367 // --- Get pointers from SimCtx instead of passing them as arguments ---
368 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
369 BoundingBox *bboxlist = simCtx->bboxlist;
370
371 PetscFunctionBeginUser;
372
373 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Performing initial particle setup procedures.\n", simCtx->ti, simCtx->step);
374
375 // --- 0. Loop over all blocks to compute Eulerian diffusivity.
376 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
377 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
378 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
379 }
380
381 // --- 1. Initial Particle Settlement (Location and Migration) ---
382 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Initial Settlement: Locating and migrating all particles...\n", simCtx->ti, simCtx->step);
383 ierr = LocateAllParticlesInGrid(user, bboxlist); CHKERRQ(ierr);
384
386 LOG_ALLOW(GLOBAL, LOG_DEBUG, "[T=%.4f, Step=%d] Particle field states after Initial settlement...\n", simCtx->ti, simCtx->step);
387 ierr = LOG_PARTICLE_FIELDS(user,simCtx->LoggingFrequency); CHKERRQ(ierr);
388 }
389
390 // --- 2. Re-initialize Particles on Inlet Surface (if applicable) ---
393 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Re-initializing particles on inlet surface...\n", simCtx->ti, simCtx->step);
394 ierr = ReinitializeParticlesOnInletSurface(user, simCtx->ti, simCtx->step); CHKERRQ(ierr);
395
396 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Resetting statuses for post-reinitialization settlement.\n", simCtx->ti, simCtx->step);
397 ierr = ResetAllParticleStatuses(user); CHKERRQ(ierr);
398
399 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Post-Reinitialization Settlement...\n", simCtx->ti, simCtx->step);
400 ierr = LocateAllParticlesInGrid(user, bboxlist); CHKERRQ(ierr);
401
402 }
403
404 // --- 2b. Configured initial particle-field values, once positions are final ---
405 // Surface seeding places particles in step 2, so this comes after it; the scatter
406 // below then carries the values to the Eulerian mean before the first update.
407 if (simCtx->particleFieldPlan) {
408 PetscInt nlocal = 0;
409 ParticleFieldEvent event = {0.0, 0};
410
411 ierr = PicurvPhysicalTime(simCtx, simCtx->ti, &event.physical_time); CHKERRQ(ierr);
412 ierr = DMSwarmGetLocalSize(user->swarm, &nlocal); CHKERRQ(ierr);
413 ierr = ParticleFieldPlanApply(user, simCtx->particleFieldPlan, &event, 0, nlocal); CHKERRQ(ierr);
414 ierr = ParticleFieldPlanSummarize(user, simCtx->particleFieldPlan); CHKERRQ(ierr);
415 }
416
417 // --- 3. Finalize State for t=0 ---
418 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Interpolating initial fields to settled particles.\n", simCtx->ti, simCtx->step);
419 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
420 ierr = RefreshScatteredParticleState(user); CHKERRQ(ierr);
421
422 // --- 4. Initial History and Output ---
423 // Update solver history vectors with the t=0 state before the first real step
424 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
425 ierr = UpdateSolverHistoryVectors(&user[bi],
426 (PetscBool)(simCtx->StartStep > 0 && simCtx->restartHistoryAvailable)); CHKERRQ(ierr);
427 }
428
429 {
430 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Writing initialized checkpoint.\n", simCtx->ti, simCtx->step);
431 ierr = WriteCheckpointBundle(simCtx, simCtx->StartStep == 0 ? "initial" : "branch_start"); CHKERRQ(ierr);
432 ierr = LOG_SCATTER_METRICS(user); CHKERRQ(ierr);
433 }
434
436 ierr = EmitParticleConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
437 }
438
439 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initial setup complete. Ready for time marching. ---\n");
440 PetscFunctionReturn(0);
441}
442
443#undef __FUNCT__
444#define __FUNCT__ "PerformLoadedParticleSetup"
445/**
446 * @brief Internal helper implementation: `PerformLoadedParticleSetup()`.
447 * @details Local to this translation unit.
448 */
449PetscErrorCode PerformLoadedParticleSetup(SimCtx *simCtx)
450{
451 PetscErrorCode ierr;
452 PetscFunctionBeginUser;
453 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
454
455 // --- 0. Re-compute Eulerian Diffusivity from loaded fields.
456 LOG_ALLOW(GLOBAL, LOG_INFO, "Re-computing Eulerian Diffusivity from loaded fields...\n");
457 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
458 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
459 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
460 }
461
462 // 0.1 This moves particles to their correct ranks immediately using the loaded Cell ID.
463 LOG_ALLOW(GLOBAL, LOG_INFO, "Performing fast restart migration using preloaded Cell IDs...\n");
464 ierr = MigrateRestartParticlesUsingCellID(user); CHKERRQ(ierr);
465
466 // 1. To catch any edge cases (particles with invalid CellIDs or newcomers).
467 // Because we kept the statuses, this function will now SKIP all the particles
468 // that are already on the correct rank,
469 ierr = LocateAllParticlesInGrid(user, simCtx->bboxlist); CHKERRQ(ierr);
470
471 if(get_log_level() == LOG_DEBUG){
472 LOG(GLOBAL, LOG_DEBUG, "[T=%.4f, Step=%d] Particle field states after locating loaded particles...\n", simCtx->ti, simCtx->step);
473 ierr = LOG_PARTICLE_FIELDS(user,simCtx->LoggingFrequency); CHKERRQ(ierr);
474 }
475
476 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Interpolating initial fields to settled particles.\n", simCtx->ti, simCtx->step);
477
478 // 2. Ensure particles have velocity from the authoritative loaded grid for consistency.
479 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
480
481 // 3. Update Eulerian source terms from the loaded particle data.
482 ierr = RefreshScatteredParticleState(user); CHKERRQ(ierr);
483
484 // --- 4. Initial History and Output ---
485 // Update solver history vectors with the t=0 state before the first real step
486 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
487 ierr = UpdateSolverHistoryVectors(&user[bi],
488 (PetscBool)(simCtx->StartStep > 0 && simCtx->restartHistoryAvailable)); CHKERRQ(ierr);
489 }
490
491 {
492 LOG_ALLOW(GLOBAL, LOG_INFO, "[T=%.4f, Step=%d] Writing restored checkpoint.\n", simCtx->ti, simCtx->step);
493 ierr = WriteCheckpointBundle(simCtx, "branch_start"); CHKERRQ(ierr);
494 ierr = LOG_SCATTER_METRICS(user); CHKERRQ(ierr);
495 }
496
498 ierr = EmitParticleConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
499 }
500
501 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initial setup complete. Ready for time marching. ---\n");
502 PetscFunctionReturn(0);
503}
504
505#undef __FUNCT__
506#define __FUNCT__ "FinalizeRestartState"
507/**
508 * @brief Internal helper implementation: `FinalizeRestartState()`.
509 * @details Local to this translation unit.
510 */
511PetscErrorCode FinalizeRestartState(SimCtx *simCtx)
512{
513 PetscErrorCode ierr;
514 PetscFunctionBeginUser;
515
516 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Finalizing RESTART from state (step=%d, t=%.4f) ---\n", simCtx->StartStep, simCtx->ti);
517
518 // This function only needs to handle the particle finalization logic.
519 // The Eulerian state is assumed to be fully loaded and consistent at this point.
520 if (simCtx->np > 0) {
521
522 // Use the particle restart mode to decide the workflow.
523 if (strcmp(simCtx->particleRestartMode, "load") == 0) {
524 // PARTICLES WERE LOADED: The state is complete, but we must verify
525 // the loaded CellIDs and build the in-memory grid-to-particle links.
526 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle Mode 'load': Verifying particle locations and building grid links...\n");
527 ierr = PerformLoadedParticleSetup(simCtx); CHKERRQ(ierr);
528
529 } else { // Mode must be "init"
530 // PARTICLES WERE RE-INITIALIZED: They need to be fully settled and coupled
531 // to the surrounding (restarted) fluid state.
532 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle Mode 'init': Running full initial setup for new particles in restarted flow.\n");
533 ierr = PerformInitializedParticleSetup(simCtx); CHKERRQ(ierr);
534 }
535 } else {
536 LOG_ALLOW(GLOBAL, LOG_INFO, "No particles in simulation, restart finalization is complete.\n");
537
538 ierr = WriteCheckpointBundle(simCtx, "branch_start"); CHKERRQ(ierr);
539 }
540
541 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Restart state successfully finalized. --\n");
542
543 PetscFunctionReturn(0);
544}
545
546#undef __FUNCT__
547#define __FUNCT__ "AdvanceSimulation"
548/**
549 * @brief Internal helper implementation: `AdvanceSimulation()`.
550 * @details Local to this translation unit.
551 */
552PetscErrorCode AdvanceSimulation(SimCtx *simCtx)
553{
554 PetscErrorCode ierr;
555 PetscReal step_start_seconds = 0.0;
556 PetscReal step_elapsed_local = 0.0;
557 PetscReal step_elapsed_max = 0.0;
558 // Get the master context from the first block. All blocks share it.
559 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
560
561 // Retrieve control parameters from SimCtx for clarity
562 const PetscInt StartStep = simCtx->StartStep;
563 const PetscInt StepsToRun = simCtx->StepsToRun;
564 const PetscReal dt = simCtx->dt;
565
566 // Variables for particle removal statistics
567 //PetscInt removed_local_ob, removed_global_ob;
568 PetscInt removed_local_lost, removed_global_lost;
569 PetscReal removed_scalar_lost = 0.0;
570 PetscBool terminated_early = PETSC_FALSE;
571 PetscInt last_completed_loop_index = StartStep - 1;
572
573 PetscFunctionBeginUser;
575 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting main time-marching loop: %d steps from step %d (t=%.4f), dt=%.4f\n",
576 StepsToRun, StartStep, simCtx->StartTime, dt);
577
578 // --- Main Time-Marching Loop ---
579 for (PetscInt step = StartStep; step < StartStep + StepsToRun; step++) {
580 ierr = MaybeRequestRuntimeWalltimeGuardShutdown(simCtx, "pre-step checkpoint"); CHKERRQ(ierr);
582 ierr = WriteForcedTerminationOutput(simCtx, user, "pre-step checkpoint"); CHKERRQ(ierr);
583 terminated_early = PETSC_TRUE;
584 break;
585 }
586
587 step_start_seconds = MPI_Wtime();
588
589 // =================================================================
590 // 1. PRE-STEP SETUP
591 // =================================================================
592
593 // Update simulation time and step counters in the master context
594 simCtx->step = step + 1;
595 simCtx->ti += simCtx->dt; //simCtx->StartTime + step * simCtx->dt;
596
597 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Advancing Step %d (To t=%.4f) ---\n", simCtx->step, simCtx->ti);
598
599
600 // For particles, reset their status to prepare for the new advection/location cycle
601 if (simCtx->np > 0) {
602 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Resetting all particle statuses to NEEDS_LOCATION.\n");
603 ierr = ResetAllParticleStatuses(user); CHKERRQ(ierr);
604 }
605
606 // =================================================================
607 // 2. EULERIAN SOLVER STEP
608 // =================================================================
610 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_COORDINATES, "PreFlowSolver"); CHKERRQ(ierr);
611 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CSI, "PreFlowSolver"); CHKERRQ(ierr);
612 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_ETA, "PreFlowSolver"); CHKERRQ(ierr);
613 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_ZET, "PreFlowSolver"); CHKERRQ(ierr);
614 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CENT, "PreFlowSolver"); CHKERRQ(ierr);
615 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CENTX, "PreFlowSolver"); CHKERRQ(ierr);
616 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CENTY, "PreFlowSolver"); CHKERRQ(ierr);
617 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CENTZ, "PreFlowSolver"); CHKERRQ(ierr);
618 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_UCAT, "PreFlowSolver"); CHKERRQ(ierr);
619 }
620 LOG_ALLOW(GLOBAL, LOG_INFO, "Updating Eulerian Field ...\n");
621 if(strcmp(simCtx->eulerianSource,"load")==0){
622 //LOAD mode: Read pre-computed fields for the current step.
623 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'load': Reading fields (t=%.4f,step=%d)...\n",simCtx->ti,simCtx->step);
624 for(PetscInt bi = 0; bi < simCtx->block_number;bi++){
625 ierr = ReadSimulationFields(&user[bi],simCtx->step); CHKERRQ(ierr);
626 }
627 }else if(strcmp(simCtx->eulerianSource,"analytical")==0){
628 // ANALYTICAL mode:Call the Analytical Solution Prescription Engine to enable a variety of analytical functions
629 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'analytical'. Updating Eulerian field via the Analytical Solution Engine ...\n");
630 ierr = AnalyticalSolutionEngine(simCtx); CHKERRQ(ierr);
631 }else if(strcmp(simCtx->eulerianSource,"solve")==0){
632 // SOLVE mode:Call the refactored, high-level legacy solver. This single function
633 // advances the entire multi-block fluid field from t_n to t_{n+1}.
634 LOG_ALLOW(GLOBAL,LOG_INFO,"Eulerian Source 'solve'. Updating Eulerian field via Solver...\n");
635 ierr = FlowSolver(simCtx); CHKERRQ(ierr);
636 }
637 LOG_ALLOW(GLOBAL, LOG_INFO, "Eulerian Field Updated ...\n");
639 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Post FlowSolver field states:\n");
640 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_UCAT, "PostFlowSolver"); CHKERRQ(ierr);
641 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_P, "PostFlowSolver"); CHKERRQ(ierr);
642 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_UCONT, "PostFlowSolver"); CHKERRQ(ierr);
643 /* Model fields exist only when their model is active. */
644 if (simCtx->les) {
645 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_NU_T, "PostFlowSolver"); CHKERRQ(ierr);
646 }
647 if (simCtx->les == DYNAMIC_SMAGORINSKY) {
648 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_CS, "PostFlowSolver"); CHKERRQ(ierr);
649 }
650 if (simCtx->wallfunction) {
651 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_U_TAU, "PostFlowSolver"); CHKERRQ(ierr);
652 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_NU_WALL, "PostFlowSolver"); CHKERRQ(ierr);
653 }
654 }
655
656
657 // =================================================================
658 // 3. LAGRANGIAN PARTICLE STEP
659 // =================================================================
660
661 if (simCtx->np > 0) {
662 LOG_ALLOW(GLOBAL, LOG_INFO, "Updating Lagrangian particle system...\n");
663 simCtx->particlesLostLastStep = 0;
664 simCtx->particlesLostScalarLastStep = 0.0;
665
666 // a. Update Eulerian Transport Properties:
667 // Optimization: Only recalculate if turbulence is active (Nu_t changes).
668 // For Laminar flow, the value calculated at Setup is constant.
669 if (simCtx->les) {
670 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
671 ierr = ComputeEulerianDiffusivity(&user[bi]); CHKERRQ(ierr);
672 ierr = ComputeEulerianDiffusivityGradient(&user[bi]); CHKERRQ(ierr);
673 }
674 }
675
676 // a.1 (Optional) Log Eulerian Diffusivity min/max and anatomy for debugging.
678 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Updated Diffusivity Min/Max:\n");
679 ierr = LOG_FIELD_MIN_MAX(&user[0], FIELD_ID_DIFFUSIVITY); CHKERRQ(ierr);
680 ierr = LOG_FIELD_MIN_MAX(&user[0], FIELD_ID_DIFFUSIVITY_GRADIENT); CHKERRQ(ierr);
681 //LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Updated Diffusivity Anatomy:\n");
682 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_DIFFUSIVITY, "PostDiffusivityUpdate"); CHKERRQ(ierr);
683 }
684 // b. Advect particles using the velocity interpolated from the *previous* step.
685 // P(t_{n+1}) = P(t_n) + V_p(t_n) * dt
686 ierr = UpdateAllParticlePositions(user); CHKERRQ(ierr);
687
688 // c. Settle all particles: find their new host cells and migrate them across ranks.
689 ierr = LocateAllParticlesInGrid(user, simCtx->bboxlist); CHKERRQ(ierr);
690
691 // d. Remove any particles that are now lost or out of the global domain.
692 ierr = CheckAndRemoveLostParticles(user, &removed_local_lost, &removed_global_lost,
693 &removed_scalar_lost); CHKERRQ(ierr);
694 //ierr = CheckAndRemoveOutOfBoundsParticles(user, &removed_local_ob, &removed_global_ob, simCtx->bboxlist); CHKERRQ(ierr);
695 simCtx->particlesLostLastStep = removed_global_lost;
696 simCtx->particlesLostScalarLastStep = removed_scalar_lost;
697 simCtx->particlesLostCumulative += removed_global_lost;
698 if (removed_global_lost> 0) { // if(removed_global_lost + removed_global_ob > 0){
699 LOG_ALLOW(GLOBAL, LOG_INFO, "Removed %d particles globally this step.\n", removed_global_lost); // removed_global_lost + removed_global_ob;
700 }
701
702 // e. Interpolate the NEW fluid velocity (just computed by FlowSolver) onto the
703 // particles' new positions. This gives them V_p(t_{n+1}) for the *next* advection step.
704 ierr = InterpolateAllFieldsToSwarm(user); CHKERRQ(ierr);
705
706 // f. Update the Particle Fields (e.g., temperature, concentration) if applicable.
707 // This can be extended to include reactions, growth, etc.
708 ierr = UpdateAllParticleFields(user); CHKERRQ(ierr);
709
710 // g. (For Two-Way Coupling) Scatter particle data back to the grid to act as a source term.
711 ierr = CalculateParticleCountPerCell(user); CHKERRQ(ierr);
712 ierr = ScatterAllParticleFieldsToEulerFields(user); CHKERRQ(ierr);
713
714 // h. (Optional) Calculate advanced particle metrics for logging/debugging.
715 ierr = CalculateAdvancedParticleMetrics(user); CHKERRQ(ierr);
716 ierr = LOG_SEARCH_METRICS(user); CHKERRQ(ierr);
717
718 ierr = LOG_PARTICLE_METRICS(user, "Timestep Metrics"); CHKERRQ(ierr);
719
720
722 LOG_ALLOW(GLOBAL, LOG_VERBOSE, "Post Lagrangian update field states:\n");
723 ierr = LOG_FIELD_MIN_MAX(&user[0], FIELD_ID_PSI); CHKERRQ(ierr);
724 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_PSI, "PostScatter"); CHKERRQ(ierr);
725 ierr = LOG_FIELD_ANATOMY(&user[0], FIELD_ID_PARTICLE_COUNT, "PostScatter"); CHKERRQ(ierr);
726 }
727 }
728
729 // =================================================================
730 // 4. UPDATE HISTORY & I/O
731 // =================================================================
732
733 // The completed-state event feeds statistics windows before physical-solution
734 // monitoring, and before history rotation replaces the state just computed.
735 ierr = FieldStatisticsUpdateWindows(simCtx, simCtx->step, simCtx->ti); CHKERRQ(ierr);
737 ierr = EmitStatisticsConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
738 }
739
740 PetscCall(LOG_SOLUTION_CONVERGENCE(simCtx));
741
742 // Copy the newly computed fields (Ucont, P, etc.) to the history vectors
743 // (_o, _rm1) to prepare for the next time step.
744 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
745 ierr = UpdateSolverHistoryVectors(&user[bi], PETSC_FALSE); CHKERRQ(ierr);
746 }
747
748 //ierr = LOG_UCAT_ANATOMY(&user[0],"Final"); CHKERRQ(ierr);
749
750 // Handle periodic file output
751 if (ShouldWriteDataOutput(simCtx, simCtx->step)) {
752 LOG_ALLOW(GLOBAL, LOG_INFO, "Writing output for step %d.\n",simCtx->step);
753 ierr = WriteCheckpointBundle(simCtx, "cadence"); CHKERRQ(ierr);
754 if (simCtx->np > 0) {
755 if (strcmp(simCtx->eulerianSource, "analytical") == 0 &&
758 }
759 ierr = LOG_SCATTER_METRICS(user); CHKERRQ(ierr);
760 }
761 }
762
763 if (ShouldEmitPeriodicParticleConsoleSnapshot(simCtx, simCtx->step)) {
764 ierr = EmitParticleConsoleSnapshot(user, simCtx, simCtx->step); CHKERRQ(ierr);
765 }
766
767 ProfilingLogTimestepSummary(simCtx, simCtx->step);
768 ierr = RuntimeMemoryLogSample(simCtx, simCtx->step, "Step", "-"); CHKERRQ(ierr);
769
770 // Update Progress Bar
771 if(simCtx->rank == 0) {
772 PrintProgressBar(step,StartStep,StepsToRun,simCtx->ti);
773 if(get_log_level()>=LOG_WARNING) PetscPrintf(PETSC_COMM_SELF,"\n");
774 }
775
776 last_completed_loop_index = step;
777
778 step_elapsed_local = MPI_Wtime() - step_start_seconds;
779 step_elapsed_max = step_elapsed_local;
780 ierr = MPI_Allreduce(&step_elapsed_local, &step_elapsed_max, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
781 if (simCtx->walltimeGuardActive) {
782 UpdateRuntimeWalltimeGuardEstimator(simCtx, step_elapsed_max);
783 ierr = MaybeRequestRuntimeWalltimeGuardShutdown(simCtx, "post-step checkpoint"); CHKERRQ(ierr);
784 }
785
787 ierr = WriteForcedTerminationOutput(simCtx, user, "post-step checkpoint"); CHKERRQ(ierr);
788 terminated_early = PETSC_TRUE;
789 break;
790 }
791 } // --- End of Time-Marching Loop ---
792
793 // After the loop, print the final progress state on rank 0 and add a newline
794 // to ensure subsequent terminal output starts on a fresh line.
795 if (simCtx->rank == 0 && StepsToRun > 0) {
796 if (!terminated_early && last_completed_loop_index >= StartStep) {
797 PrintProgressBar(StartStep + StepsToRun - 1, StartStep, StepsToRun, simCtx->ti);
798 } else if (terminated_early && last_completed_loop_index >= StartStep) {
799 PrintProgressBar(last_completed_loop_index, StartStep, StepsToRun, simCtx->ti);
800 }
801 PetscPrintf(PETSC_COMM_SELF, "\n");
802 fflush(stdout);
803 }
804
805 if (terminated_early) {
807 "Time marching stopped early after %s. Final retained state is step %d at t=%.4f.\n",
808 RuntimeShutdownReasonName(), simCtx->step, simCtx->ti);
809 } else {
810 if (StepsToRun > 0) {
811 ierr = WriteCheckpointBundle(simCtx, "final"); CHKERRQ(ierr);
812 }
813 LOG_ALLOW(GLOBAL, LOG_INFO, "Time marching completed. Final time t=%.4f.\n", simCtx->ti);
814 }
816 PetscFunctionReturn(0);
817}
PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
Dispatches to the appropriate analytical solution function based on simulation settings.
PetscBool AnalyticalTypeSupportsInterpolationError(const char *analytical_type)
Reports whether an analytical type has a non-trivial velocity field for which interpolation error mea...
Configured initial values of particle-carried fields, and the expression language that defines them.
PetscErrorCode ParticleFieldPlanSummarize(UserCtx *user, const ParticleFieldPlan *plan)
Log and record the realized initial values of every planned field.
PetscErrorCode ParticleFieldPlanApply(UserCtx *user, const ParticleFieldPlan *plan, const ParticleFieldEvent *event, PetscInt first, PetscInt end)
Write the plan's values into swarm entries [first, end) of this rank.
When and why a plan is applied.
PetscErrorCode CheckAndRemoveLostParticles(UserCtx *user, PetscInt *removedCountLocal, PetscInt *removedCountGlobal, PetscReal *removedScalarSumGlobal)
Removes particles that have been definitively flagged as LOST by the location algorithm.
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 CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
PetscErrorCode LocateAllParticlesInGrid(UserCtx *user, BoundingBox *bboxlist)
Orchestrates the complete particle location and migration process for one timestep.
PetscErrorCode ResetAllParticleStatuses(UserCtx *user)
Marks all local particles as NEEDS_LOCATION for the next settlement pass.
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 UpdateAllParticleFields(UserCtx *user)
Orchestrates the update of all physical properties for particles.
@ FIELD_ID_PSI
@ FIELD_ID_CENTZ
@ FIELD_ID_CSI
@ FIELD_ID_UCAT
@ FIELD_ID_NVERT_O
@ FIELD_ID_COORDINATES
@ FIELD_ID_UCONT_O
@ FIELD_ID_NU_T
@ FIELD_ID_CENTY
@ FIELD_ID_DIFFUSIVITY_GRADIENT
@ FIELD_ID_UCONT
@ FIELD_ID_U_TAU
@ FIELD_ID_ETA
@ FIELD_ID_NU_WALL
@ FIELD_ID_CS
@ FIELD_ID_CENT
@ FIELD_ID_P
@ FIELD_ID_UCONT_RM1
@ FIELD_ID_ZET
@ FIELD_ID_CENTX
@ FIELD_ID_PARTICLE_COUNT
@ FIELD_ID_DIFFUSIVITY
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 ReadSimulationFields(UserCtx *user, PetscInt ti)
Reads binary field data for velocity, pressure, and other required vectors.
Definition io.c:1471
PetscBool ShouldWriteDataOutput(const SimCtx *simCtx, PetscInt completed_step)
Returns whether full field/restart output should be written for the.
Definition io.c:426
PetscErrorCode WriteCheckpointBundle(SimCtx *simCtx, const char *reason)
Write and atomically publish one complete checkpoint bundle.
Definition io.c:2554
PetscErrorCode PicurvPhysicalTime(const SimCtx *simCtx, PetscReal solver_time, PetscReal *physical)
Convert a solver time to physical seconds, t * L_ref / U_ref.
Definition io.c:3177
PetscErrorCode LOG_FIELD_MIN_MAX(UserCtx *user, FieldId field_id)
Computes and logs the local and global min/max values of a 3-component vector field.
Definition logging.c:2458
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:3458
PetscBool ShouldEmitPeriodicStatisticsConsoleSnapshot(const struct SimCtx *simCtx, PetscInt completed_step)
Reports whether a completed step falls on the console snapshot cadence.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:186
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
PetscErrorCode LOG_INTERPOLATION_ERROR(UserCtx *user)
Logs the interpolation error between the analytical and computed solutions.
Definition logging.c:2974
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
PetscBool ShouldEmitPeriodicParticleConsoleSnapshot(const SimCtx *simCtx, PetscInt completed_step)
Returns whether a particle console snapshot should be emitted for the.
Definition logging.c:545
#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
PetscBool IsParticleConsoleSnapshotEnabled(const SimCtx *simCtx)
Returns whether periodic particle console snapshots are enabled.
Definition logging.c:528
PetscErrorCode EmitParticleConsoleSnapshot(UserCtx *user, SimCtx *simCtx, PetscInt step)
Emits one particle console snapshot into the main solver log.
Definition logging.c:559
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:894
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:84
PetscErrorCode EmitStatisticsConsoleSnapshot(UserCtx *user, const struct SimCtx *simCtx, PetscInt step)
Emits one console snapshot of window progress.
void PrintProgressBar(PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
Prints a progress bar to the console.
Definition logging.c:2411
PetscErrorCode RuntimeMemoryLogSample(SimCtx *simCtx, PetscInt step, const char *event, const char *reason)
Append a reduced runtime memory sample to the configured memory log.
Definition logging.c:2195
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:87
PetscErrorCode ProfilingLogTimestepSummary(SimCtx *simCtx, PetscInt step)
Logs the performance summary for the current timestep and resets timers.
Definition logging.c:2100
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Prints particle fields in a table that automatically adjusts its column widths.
Definition logging.c:400
PetscErrorCode CalculateAdvancedParticleMetrics(UserCtx *user)
Computes advanced particle statistics and stores them in SimCtx.
Definition logging.c:3404
PetscErrorCode LOG_SCATTER_METRICS(UserCtx *user)
Logs particle-to-grid scatter verification metrics for the prescribed scalar truth path.
Definition logging.c:3056
PetscErrorCode LOG_SOLUTION_CONVERGENCE(SimCtx *simCtx)
Logs physical solution-convergence metrics once per completed timestep.
Definition logging.c:1695
PetscErrorCode LOG_FIELD_ANATOMY(UserCtx *user, FieldId field_id, const char *stage_name)
Logs the anatomy of a specified field at key boundary locations, respecting the solver's specific gri...
Definition logging.c:2861
PetscErrorCode LOG_SEARCH_METRICS(UserCtx *user)
Writes compact runtime search metrics to CSV and optionally to console.
Definition logging.c:3245
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
@ 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:885
PetscErrorCode ComputeEulerianDiffusivity(UserCtx *user)
Computes the effective diffusivity scalar field (Gamma_eff) on the Eulerian grid.
Definition rhs.c:1867
PetscErrorCode ComputeEulerianDiffusivityGradient(UserCtx *user)
Computes the Eulerian gradient of the effective diffusivity field.
Definition rhs.c:1999
PetscErrorCode InitializeRuntimeSignalHandlers(void)
Implementation of InitializeRuntimeSignalHandlers().
Definition runloop.c:126
static PetscReal RuntimeWalltimeGuardRemainingSeconds(const SimCtx *simCtx)
Estimate the remaining scheduler walltime after reserving the configured shutdown margin.
Definition runloop.c:204
static PetscErrorCode MaybeRequestRuntimeWalltimeGuardShutdown(SimCtx *simCtx, const char *checkpoint_name)
Request graceful shutdown when another timestep would exceed the walltime budget.
Definition runloop.c:242
PetscErrorCode AdvanceSimulation(SimCtx *simCtx)
Internal helper implementation: AdvanceSimulation().
Definition runloop.c:552
static PetscErrorCode RefreshScatteredParticleState(UserCtx *user)
Makes the Eulerian particle averages consistent with the particles before step 1.
Definition runloop.c:54
PetscReal RuntimeWalltimeGuardUpdateEWMA(PetscBool has_previous, PetscReal previous_ewma_seconds, PetscReal latest_step_seconds, PetscReal alpha)
Implementation of RuntimeWalltimeGuardUpdateEWMA().
Definition runloop.c:153
static PetscBool g_runtime_shutdown_auto_requested
Definition runloop.c:15
static void RuntimeShutdownSignalHandler(int signum)
Record receipt of a termination signal for safe handling by the run loop.
Definition runloop.c:20
static void RuntimeRequestAutoWalltimeGuard(void)
Request a controlled shutdown because the estimated walltime margin is exhausted.
Definition runloop.c:30
PetscReal RuntimeWalltimeGuardConservativeEstimate(PetscReal warmup_average_seconds, PetscReal ewma_seconds, PetscReal latest_step_seconds)
Implementation of RuntimeWalltimeGuardConservativeEstimate().
Definition runloop.c:165
PetscReal RuntimeWalltimeGuardRequiredHeadroom(PetscReal min_seconds, PetscReal multiplier, PetscReal conservative_estimate_seconds)
Implementation of RuntimeWalltimeGuardRequiredHeadroom().
Definition runloop.c:176
PetscErrorCode FinalizeRestartState(SimCtx *simCtx)
Internal helper implementation: FinalizeRestartState().
Definition runloop.c:511
static PetscErrorCode WriteForcedTerminationOutput(SimCtx *simCtx, UserCtx *user, const char *phase)
Write restart-safe output when a controlled shutdown interrupts the run loop.
Definition runloop.c:286
PetscBool RuntimeWalltimeGuardShouldTrigger(PetscInt completed_steps, PetscInt warmup_steps, PetscReal remaining_seconds, PetscReal min_seconds, PetscReal multiplier, PetscReal warmup_average_seconds, PetscReal ewma_seconds, PetscReal latest_step_seconds, PetscReal *required_headroom_seconds_out)
Implementation of RuntimeWalltimeGuardShouldTrigger().
Definition runloop.c:187
static const char * RuntimeShutdownSignalName(PetscInt signum)
Translate a recorded termination signal into a user-facing signal name.
Definition runloop.c:68
PetscErrorCode PerformInitializedParticleSetup(SimCtx *simCtx)
Internal helper implementation: PerformInitializedParticleSetup().
Definition runloop.c:364
PetscErrorCode UpdateSolverHistoryVectors(UserCtx *user, PetscBool preserve_previous_state)
Internal helper implementation: UpdateSolverHistoryVectors().
Definition runloop.c:314
static const char * RuntimeShutdownReasonName(void)
Translate the current shutdown reason into a user-facing diagnostic label.
Definition runloop.c:87
static PetscErrorCode RegisterRuntimeSignalHandler(int signum)
Install the process signal handler used to request graceful simulation shutdown.
Definition runloop.c:101
static PetscBool RuntimeShutdownRequested(void)
Report whether a signal or walltime guard has requested run-loop shutdown.
Definition runloop.c:40
static volatile sig_atomic_t g_runtime_shutdown_signal
Definition runloop.c:14
PetscErrorCode PerformLoadedParticleSetup(SimCtx *simCtx)
Internal helper implementation: PerformLoadedParticleSetup().
Definition runloop.c:449
#define __FUNCT__
Definition runloop.c:359
static void UpdateRuntimeWalltimeGuardEstimator(SimCtx *simCtx, PetscReal completed_step_seconds)
Update the timestep-duration estimate used by the automatic walltime guard.
Definition runloop.c:215
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Definition setup.c:2489
PetscErrorCode FlowSolver(SimCtx *simCtx)
Orchestrates a single time step of the Eulerian fluid solver.
Definition solvers.c:11
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
PetscErrorCode FieldStatisticsUpdateWindows(struct SimCtx *simCtx, PetscInt step, PetscReal time)
Offers one completed state to every configured window.
@ DYNAMIC_SMAGORINSKY
Definition variables.h:551
UserCtx * user
Definition variables.h:729
PetscBool inletFaceDefined
Definition variables.h:1100
PetscMPIInt rank
Definition variables.h:862
PetscInt block_number
Definition variables.h:952
PetscBool walltimeGuardActive
Definition variables.h:1038
PetscReal walltimeGuardWarmupTotalSeconds
Definition variables.h:1046
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:710
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:713
PetscReal StartTime
Definition variables.h:873
PetscBool walltimeGuardHasEWMA
Definition variables.h:1048
PetscInt particlesLostLastStep
Definition variables.h:997
UserMG usermg
Definition variables.h:1015
PetscReal walltimeGuardMinSeconds
Definition variables.h:1041
PetscInt _this
Definition variables.h:1092
PetscReal walltimeGuardLatestStepSeconds
Definition variables.h:1050
PetscReal dt
Definition variables.h:874
PetscInt StepsToRun
Definition variables.h:870
PetscInt np
Definition variables.h:990
Vec Ucont
Definition variables.h:1113
PetscInt StartStep
Definition variables.h:869
Vec Ucat_o
Definition variables.h:1120
char particleRestartMode[16]
Definition variables.h:996
BoundingBox * bboxlist
Definition variables.h:993
PetscInt walltimeGuardCompletedSteps
Definition variables.h:1045
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:879
PetscInt walltimeGuardWarmupSteps
Definition variables.h:1039
ParticleInitializationType ParticleInitialization
Definition variables.h:994
Vec Ucont_o
Definition variables.h:1120
PetscInt wallfunction
Enable wall functions on WALL faces.
Definition variables.h:985
PetscInt mglevels
Definition variables.h:736
Vec Nvert_o
Definition variables.h:1120
PetscInt particlesLostCumulative
Definition variables.h:998
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:893
PetscReal walltimeGuardWarmupAverageSeconds
Definition variables.h:1047
Vec Ucont_rm1
Definition variables.h:1121
PetscInt step
Definition variables.h:867
PetscReal walltimeGuardEWMASeconds
Definition variables.h:1049
PetscReal walltimeGuardLimitSeconds
Definition variables.h:1044
PetscReal walltimeGuardEstimatorAlpha
Definition variables.h:1042
PetscInt les
Active LES closure; an LESModelType value.
Definition variables.h:984
Vec Nvert
Definition variables.h:1113
MGCtx * mgctx
Definition variables.h:739
PetscReal particlesLostScalarLastStep
Sum of Psi over the particles removed this step.
Definition variables.h:999
PetscBool restartHistoryAvailable
Definition variables.h:888
PetscReal ti
Definition variables.h:868
PetscReal walltimeGuardMultiplier
Definition variables.h:1040
PetscInt immersed
Definition variables.h:891
PetscReal walltimeGuardJobStartEpochSeconds
Definition variables.h:1043
PetscInt LoggingFrequency
Definition variables.h:1020
struct ParticleFieldPlan * particleFieldPlan
Configured initial particle-field values, or NULL.
Definition variables.h:1000
Defines a 3D axis-aligned bounding box.
Definition variables.h:197
The master context for the entire simulation.
Definition variables.h:859
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
PetscErrorCode ApplyVerificationScalarOverrideToParticles(UserCtx *user)
Populates the particle Psi field from a verification-only source override.
PetscBool VerificationScalarOverrideActive(const SimCtx *simCtx)
Reports whether a verification-only scalar override is active.