Skip to content

InitData never records m_last_chk (and restart sets m_last_plt=0): Evolve's final-output block rewrites the step's checkpoint/plotfile, renaming the restart checkpoint to *.old.* #246

Closed

Description

@WeiqunZhang

Severity: low · Category: io-restart
Locations: src/incflo.cpp:79, src/incflo.cpp:96-111, src/incflo.cpp:190-197, src/incflo_compute_dt.cpp:235-242
Based on commit 46de3367 (line numbers refer to that tree).

The defect

Evolve()'s "Output at the final time" block (incflo.cpp:190-197) writes a checkpoint when
m_nstep != m_last_chk and a plotfile when m_nstep != m_last_plt. The two counters are meant to record the
step of the most recent write, but InitData maintains them inconsistently:

  • Fresh start (incflo.cpp:79): WriteCheckPointFile() writes chk00000 but m_last_chk stays at its initial
    -1. (The plotfile branch right below it does set m_last_plt = 0.)
  • Restart (incflo.cpp:96-111): the checkpoint just read is the output for m_nstep, but m_last_chk stays
    -1; and when plotfile_on_restart/smallplotfile_on_restart write a file at step m_nstep, the code records
    m_last_plt = 0 / m_last_smallplt = 0 instead of m_nstep.

Whenever the loop then takes no steps -- max_step = 0, or a restart from the final checkpoint of a completed
run (the case PR #212 deliberately made a no-op by changing the entry test to >= stop_time - 1e-12*dt) -- the
final block re-writes chk<nstep> and plt<nstep>. AMReX's UtilCreateCleanDirectory (called by
PreBuildDirectorHierarchy and WriteMultiLevelPlotfile) renames an existing directory to
<name>.old.<unique> before writing, so the very checkpoint the run was restarted from is renamed and replaced
by an identical copy, and the existing plotfile likewise.

m_last_plt is also consulted by ComputeDt (compute_dt.cpp:235-242): the relaxed growth limit after a
plot_per_exact-shortened step keys on m_last_plt == m_nstep, which the restart branch's m_last_plt = 0 can
never satisfy on the first step after a restart.

Why it matters

Silent, confusing filesystem churn: after a no-op restart the user finds chk00020.old.<timestamp> and a fresh
chk00020 (same for plt00020), and a fresh run with max_step = 0 writes chk00000 twice. No wrong numbers,
but misleading output and needless I/O on large runs. The ComputeDt interaction is a (harmless) deviation
from the intended dt-growth rule for the first step after a restart with plotfile_on_restart.

How to reach it

Any build. Run test_3d/benchmark.double_shear_restart (max_step=20, check_int=10, plot_int=20) to completion,
then rerun with amr.restart = chk00020: do_not_evolve is true on entry (m_nstep >= m_max_step),
m_last_chk == -1 != 20, so chk00020 is renamed to chk00020.old.* and rewritten; plt00020 likewise.
Or run any input with max_step = 0 and amr.check_int = 1: chk00000 is written in InitData and again
at the end of Evolve().

Suggested fix

Record the step of each write in InitData, and treat the restart checkpoint as this step's checkpoint.

--- a/src/incflo.cpp
+++ b/src/incflo.cpp
@@ -76,7 +76,7 @@
 
         // xxxxx TODO averagedown ???
 
-        if (m_check_int > 0) { WriteCheckPointFile(); }
+        if (m_check_int > 0) { WriteCheckPointFile(); m_last_chk = 0; }
 
         // Plot initial distribution
         if (m_plot_int > 0 || m_plot_per_exact > 0 || m_plot_per_approx > 0)
@@ -95,6 +95,11 @@
         // Read starting configuration from chk file.
         ReadCheckpointFile();
 
+        // The checkpoint just read is the checkpoint for this step; without this
+        // the final-output block in Evolve() rewrites it (renaming the original to
+        // *.old.*) when the restart does not take any steps.
+        m_last_chk = m_nstep;
+
 #ifdef INCFLO_USE_PARTICLES
         particleData.Redistribute();
 #endif
@@ -102,12 +107,12 @@
         if (m_plotfile_on_restart)
         {
             WritePlotFile();
-            m_last_plt = 0;
+            m_last_plt = m_nstep;
         }
         if (m_smallplotfile_on_restart)
         {
             WriteSmallPlotFile();
-            m_last_smallplt = 0;
+            m_last_smallplt = m_nstep;
         }
     }
 

(audit/notes/T1-scratch/002.diff, checked with git apply --check.) A restart without
plotfile_on_restart deliberately keeps m_last_plt = -1, so a no-op restart still produces a final plotfile
if none is guaranteed to exist.

Activity

  1. added a commit that references this issue on Sep 27, 2026
    fd1ff9d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions