From 180933671b9ea706997c56489caf3b52b6b58abc Mon Sep 17 00:00:00 2001 From: sotashimozono Date: Wed, 9 Sep 2026 09:53:36 +0000 Subject: [PATCH] fix: the swept dt values must be distinct on disk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `production.toml` swept `dt = [1e-2, 5e-3, 2.5e-3, 1.25e-3]`, which is the natural halving sequence and the wrong answer. A swept float reaches its directory name through `%.2f`, so those four render `0.01, 0.01, 0.00, 0.00`: twenty distinct points claim ten directories and half the sweep silently overwrites the other half while the ledger reports every point as done. `debug.toml` had the same shape at four points into two. `ParamIO.diagnose` said so all along; nothing ran it. smoke.toml ok=true 1 point debug.toml ok=false 4 points -> 2 directories production.toml ok=false 20 points -> 10 directories Only smoke.toml was clean, and smoke.toml is the one CI runs — which is why this template shipped a sweep that cannot be run at size. The replacement values are not free either. `MyModule.decay_error` takes `n = round(Int, t_end/dt)`, so a dt that does not divide `t_end` integrates to a different final time and contributes an error that has nothing to do with the step size. `[0.08, 0.04, 0.02, 0.01]` is distinct on disk and fails this: at dt=0.08 the integration stops at t=0.96 and the truncation error cancels against the end-time error, giving 5.79e-04 — SMALLER than the error at dt=0.01, so the coarsest point would sit below the finest on the convergence plot. `[0.1, 0.05, 0.02, 0.01]` satisfies both: distinct under `%.2f`, exact divisors of 1.0, and the rendered name equals the value rather than a rounding of it. Verified: all three configs `ok=true`; the debug sweep runs to four distinct directories with four distinct rows, and err/dt stays flat across them; test/runtests.jl and report.jl both still pass. The upstream half of this is DataVault #39/#41 — `Vault` now honours `[datavault] float_format = "auto"`, which lets a sweep use any values it likes, and warns at construction when a grid collides. This template pins the registered DataVault 0.7, so it cannot adopt that until a release; the values are the fix that works today. Co-Authored-By: Claude Opus 5 (1M context) --- projects/ExampleSweep/configs/debug.toml | 2 +- projects/ExampleSweep/configs/production.toml | 4 +++- projects/ExampleSweep/configs/smoke.toml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/projects/ExampleSweep/configs/debug.toml b/projects/ExampleSweep/configs/debug.toml index 458de54..8b857e2 100644 --- a/projects/ExampleSweep/configs/debug.toml +++ b/projects/ExampleSweep/configs/debug.toml @@ -22,4 +22,4 @@ path_keys = ["system.a", "numerics.dt"] a = [0.5, 1.0] [paramsets.numerics] -dt = [1.0e-2, 5.0e-3] +dt = [0.05, 0.01] diff --git a/projects/ExampleSweep/configs/production.toml b/projects/ExampleSweep/configs/production.toml index 95d4e80..563a16f 100644 --- a/projects/ExampleSweep/configs/production.toml +++ b/projects/ExampleSweep/configs/production.toml @@ -22,4 +22,6 @@ path_keys = ["system.a", "numerics.dt"] a = [0.25, 0.5, 1.0, 2.0, 4.0] [paramsets.numerics] -dt = [1.0e-2, 5.0e-3, 2.5e-3, 1.25e-3] +# Distinct under `%.2f`, which is what names the directory, and exact divisors of 1.0, which +# `decay_error`'s `n = round(Int, t_end/dt)` needs. A halving sequence satisfies neither. +dt = [0.1, 0.05, 0.02, 0.01] diff --git a/projects/ExampleSweep/configs/smoke.toml b/projects/ExampleSweep/configs/smoke.toml index 2bf5f4c..ed3fbaa 100644 --- a/projects/ExampleSweep/configs/smoke.toml +++ b/projects/ExampleSweep/configs/smoke.toml @@ -22,4 +22,4 @@ path_keys = ["system.a", "numerics.dt"] a = [1.0] [paramsets.numerics] -dt = [1.0e-2] +dt = [0.01]