Skip to content

Add the DeltaSDC project: mixed precision in delta form, emulated and on GPUs - #784

Open
pancetta wants to merge 30 commits into
masterfrom
feature/delta_sdc
Open

pancetta wants to merge 30 commits into
masterfrom
feature/delta_sdc

Conversation

@pancetta

@pancetta pancetta commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Adds pySDC/projects/DeltaSDC, the mixed-precision study. It is built on the delta-form sweepers and transfers already in master (#685, #687, #688, #690), on the finite-difference problems' own solve precision and FFT solve (#785), and on the correction-solve contract the delta-form sweeper now keeps (#786). It changes nothing in the library. Outside the project folder and its tests, the PR touches three files, six lines:

  • ci_pipeline.yml: DeltaSDC in the project test matrix;
  • docs/source/projects/DeltaSDC.rst: the page that includes the README;
  • pySDC/projects/gallery.yml: the project's card on the website.

The library fixes this needed on GPUs landed separately in #732, #733 and #734. What the project used to implement itself -- genuine reduced-precision solves, the FFT solve, ParaDiag's reduced-precision node-local solve, and the scaling a half-precision solver needs on the linear route -- now comes from #785 and #786. What stays here is the study: the emulation where no genuine route exists (PETSc, DOLFIN, half precision on a sparse solver), the precision cascade, the controls, the drivers, the figures and the README.

What the study shows

SDC in delta form solves for a correction rather than the state. So a node-local solve, or a whole coarse level, can run at reduced precision without capping the attainable accuracy: its error is relative to a quantity that goes to zero. The README has the details. The main results:

  • What a solve has to deliver. Measured by spoiling exact solves: SDC's fine solve needs about four digits, MLSDC's fine solve about six, MLSDC's coarse solve about two. A real half-precision FFT solve on a T4 reproduces those predictions (+2 / +1 / +4 iterations at 1024²).
  • Emulated across backends: NumPy, PETSc, FEniCS, node-parallel MPI and ParaDiag. Each comes with a control that has to fail, so that "no change" is a measurement rather than a harness that stopped measuring.
  • Genuine reduced precision where the backend allows it: FD problems with a dtype per level, fp32 CG solves, ParaDiag at complex64, and an fp16 FFT solve through cuFFT's complex32 transforms.
  • Timed on GPUs (run_gpu.py). At 1024² on a T4, fp32 solves plus an fp32 coarse level are 2.8× faster than fp64 SDC at the same answer, and fp32 alone gives 1.7×, the sparse bandwidth ratio. On an H100 the gain is about 1.1×, because a CG iteration there is launch overhead rather than memory traffic.

The project's problem classes take useGPU like the rest of pySDC, and run_demo.py --gpu reproduces the README's tables on a GPU.

Tests

  • Project tests (base, project CI job): 47, including test_plots.py. It runs the two plot scripts (about 7 s), asserts what each figure shows, and writes them into data/ for the README and the gallery card.
  • Optional backends (pySDC/tests/test_projects/test_DeltaSDC, fenics / petsc / mpi4py): 4, plus one base check that the GPU tests cover every row of the README tables.
  • GPU (cupy, picked up by the Modal job): 29 tests. They check every row of both README tables, one test per row so xdist spreads them over the four GPUs, plus fingerprints showing the reduced precision is genuine rather than silently upcast. 48 s on 4×T4 through etc/modal_gpu_tests.py.

Checked locally on the branch after merging current master: black and ruff over pySDC, 50 CPU tests including FEniCS and PETSc, and the 2 MPI tests. The website build has not been run locally. The CI docs job builds it, and fails if an embedded figure is missing.

For review

  • About 5,500 lines, most of it the study's scripts (3,400 lines of Python, tests included) and a 730-line README.
  • level_precision and the other emulation knobs stay in the project on purpose: PETSc and DOLFIN fix their scalar type at build time, so for those backends emulation is the only way to measure anything.

🤖 Generated with Claude Code

pancetta and others added 12 commits September 13, 2026 08:42
What the delta form and its hierarchy (#687, #688) buy, measured -- with the controls that make the
measurements mean anything, which is most of what is here.

Three independent places can run below backend precision, and they compose to within one iteration
of the float64 baseline:

  the node-local solve    specified by the accuracy it delivers, not by a format: SDC's fine solve
                          needs about four digits, MLSDC's about six, MLSDC's coarse solve about
                          two -- four orders of magnitude apart in the same run
  a whole coarse level    float16, once the two O(1) cancellations are gone
  the fine level's state  float16 early, climbing as the corrections shrink, float64 by the end

Every claim has a control that must break: the stock hierarchy at the same reduced precision (which
stalls), the finest level reduced (2.2e-05), the increment formed by subtraction (3.4e-06), an
unscaled float16 correction (5.9e-05, which is float16's smallest normal).

  mlsdc.py        reduced precision on a level, emulated -- for PETSc and DOLFIN, which fix their
                  scalar type at build time, and the controls
  cascade.py      storage precision raised as the iteration converges, on an indicator the delta
                  form supplies itself: step up while |delta| < safety * eps * |u|
  paradiag.py     ParaDiag needs no reformulation at all -- it is already iterative refinement over
                  the whole block -- so this is two precision knobs and the tests that price them
  problems*.py    the analytic increments and correction solves, on numpy, PETSc and FEniCS
  run_*.py        one driver per backend, each printing and asserting its own matrix

Registered in the project CI matrix and the docs index. The optional-backend tests live under
pySDC/tests/test_projects/test_DeltaSDC, following test_step_7: that CI job selects by marker while
the project job installs only this project's environment.

41 project tests and 4 optional-backend tests pass, on numpy 1.26.4 and 2.4.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eration asks for

Three talk figures, and the two changes to allencahn_delta they needed.

allencahn_delta could not run its node-local solve at float16: SciPy holds no half-precision
sparse matrix, and the correction underflows float16's smallest normal (6.1e-5) after a handful
of sweeps. Both are now addressed the way heat_delta already did it:

* ``normalize`` scales the unknown to O(1) around the whole Newton loop. Unlike the linear case
  this is not a wrapper around the solve -- the increment expansion carries the scale on its
  quadratic and cubic terms, so it stays exact.
* ``solve_precision`` now separates storage from arithmetic. The correction is stored at the
  requested format, operators and Krylov run at ``promote_types(solve_precision, float32)`` --
  the convention the genuinely reduced-precision levels already use, and what half-precision
  hardware does anyway.

Measured on Allen-Cahn, 16 iterations: fp64 floors at 9.6e-13, normalised fp16 at 7.5e-13 two
iterations later, unnormalised fp16 stalls at 1.8e-06. The demo table is unchanged row for row.

plot_mixed_precision.py draws that comparison for heat and Allen-Cahn. plot_delivered_accuracy.py
sweeps the relative accuracy eta of the returned correction with the project's existing
heat_inexact: 14 iterations from 1e-16 all the way to 3e-5, then 15/16/18 at 1e-4/1e-3/1e-2, with
the residual floor never moving. A real float16 solve lands one iteration below the sweep at its
own unit roundoff, the random perturbation being the more pessimistic model of the two.

The generated figures are not committed; the scripts reproduce them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on GPUs

Three things that could not run on a GPU and that no GPU test exercised:

- `get_finite_difference_matrix` edits the boundary rows of a Dirichlet or Neumann operator in
  `lil` format, which CuPy does not have, so every non-periodic FD problem raised
  NotImplementedError with `useGPU=True`. The 1D stencil is now built on the host and only the
  finished matrix moves to the device, as `mesh_to_mesh` already does.
- The four Allen-Cahn Newton solvers formed their residual on the datatype, whose `__abs__` is a
  norm. NumPy's `linalg.norm` strips the wrapper first, CuPy's does not, so every solve died on
  `cupy_mesh`. They now work on plain arrays. The GPU test compared only `eval_f`; it now compares
  the solvers too.
- `run_mpi_tests.sh` dropped `PYTEST_SERIAL_EXTRA` for a tree that declares no MPI ranks, so such a
  tree ran its GPU tests on one device of the four the job rents. Measured on a narrowed run: 106 s
  on one worker, 56 s on four.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#691 moved the Allen-Cahn problems to wells at 0 and 1: the reaction is now
(1 / 2 eps^2) v (1 - v^2) in v = 2u - 1. The master merge applied cleanly, but
allencahn_delta's analytic increment and Jacobian still expanded the old
(1 / eps^2) u (1 - u^2), so the correction solve no longer solved the problem's
own equation: six project tests failed, one answer off by 3.7e14, and the suite
took 17 minutes instead of 13 seconds.

Same expansion, written in v with d = 2 delta, so every term still carries a
factor of the correction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The project's problem classes now take `useGPU` like the rest of pySDC:
allencahn_delta, heat_delta and heat_paradiag compute through xp/xsp/linalg, and
round_value rounds any array with `astype`. `run_demo.py --gpu` reproduces both
README tables on a T4, iteration for iteration (NumPy 2 counts).

`test_gpu.py` (cupy marker, so the Modal GPU job picks it up) checks every row
of both tables as its own test -- iteration count, distance to the fp64 peer, and
that every control still fails -- so xdist spreads them over the four devices;
plus the genuine-precision fingerprints and the ParaDiag complex64 path.

New, and timed on hardware rather than emulated:
- problems.heat_solve_dtype: a CG correction solve that genuinely runs in fp32.
- run_gpu.py: time to solution of the ladder, 2D heat, CPU or GPU. At 1024^2 on a
  T4, fp32 CG plus an fp32 coarse level is 2.8x faster than fp64 SDC at the same
  answer; fp32 alone is 1.7x (the sparse bandwidth ratio). An H100 gains ~1.1x:
  there a CG iteration is launch overhead, not memory traffic.
- ParaDiag on the GPU: with periodic boundaries the node-local solve is an FFT
  diagonalisation (exact), and the reduced transform is one matmul on either
  device. The README's ParaDiag table reproduces on a T4. At scale complex64
  costs one iteration at small alpha; AdaptiveAlpha must be told the precision
  (inner_tol) or it drives alpha where complex64 diverges for an iteration.

The README records all of it, and replaces "none of this is a statement about
speed" with the measurement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…acy spec with it

Neither SciPy's nor CuPy's sparse matrices hold float16, so no node-local solve
in the project could compute in half precision. heat_solve_dtype gains
solver_type='FFT' for periodic grids: the operator is circulant, so the solve
is a forward FFT, a division and an inverse FFT at solve_dtype. At float16 on a
GPU those are cuFFT's complex32 transforms (cupy.cuda.cufft.XtPlanNd), with
every value stored and every product rounded in half precision. On a CPU the
same flag is an emulation, rounding through float16 around a complex64
transform. The rhs is normalised and the transforms unitary, which keeps an
unnormalised 1024^2 transform (1e6) inside float16's 65504.

The README's delivered-accuracy table, measured by spoiling exact solves,
predicts what half precision (eta ~ 4e-3 at 1024^2) costs. Measured on a T4 with
real arithmetic (run_gpu.py --fft): SDC +2, MLSDC coarse +1, MLSDC fine +4,
against predicted +2..4, +1 and +4..9. Every row reaches its fp64 peer. The
CPU emulation is optimistic: it finds the coarse solve free at 256^2, where the
genuine arithmetic already costs an iteration.

Tests: the FFT solve against a direct solve at all three precisions, with a
lower bound so a solve that stayed in double fails (CPU); on the GPU, the
half-precision fingerprint and the spec's ordering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master now lists projects through pySDC/projects/gallery.yml rather than a
toctree in docs/source/index.rst, so the conflict there resolves to master's
file, and DeltaSDC gets a gallery card instead. Its excerpt is the
configuration table of run_gpu.py: what a precision ladder looks like in a
description.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… constant

The serial and node-parallel rounding transfers had the same restrict and
prolong overrides; they now come from one RoundedTransferMixin. ParaDiag's
problem and heat_solve_dtype both diagonalised their periodic operator with the
same few lines; that is now circulant_eigenvalues in problems.py. The PETSc
problems import TOLERANCE_SAFETY instead of defining a second copy, and mlsdc.py
no longer re-exports total_increment, which nothing imported from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and gallery

plot_mixed_precision.py and plot_delivered_accuracy.py were talk figures that
nothing ran. They now write into data/, and tests/test_plots.py runs both (about
7 s) and asserts what each figure shows: the normalised half-precision solve
keeps the fp64 floor while the naive one stalls, and the iteration count is flat
down to about five digits of solver accuracy. The CI uploads data/ with the
project's artifacts, so the README embeds the figures where their claims are
made, and the gallery card shows the heat equation one. matplotlib joins the
project environment for it.

The star in the delivered-accuracy figure was labelled a "real float16 solve";
it is heat_delta's emulation, and now says so. The README's file table gains
run_gpu.py and the plot scripts, and a section underline that was one character
short is fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…acy table does

test_heat_ladder demanded that a coarse solve rounded through float16 cost no
iteration at all. It costs 7 on Apple's BLAS and 8 on Linux OpenBLAS, with the
same NumPy (1.26 and 2.5) and SciPy on both, so the project job failed in CI and
passed locally. That is the README's own delivered-accuracy table: an
unrefined float16 solve delivers an eta between its 1e-4 and 1e-3 columns, 7 and
8 iterations, and the real half-precision FFT solve on a GPU already costs that
one iteration at 256^2 and up. The test now allows it, and the README says "at
most one extra iteration" instead of "for free".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  pySDC/projects/DeltaSDC
  eta_spec.py
  genuine.py 33-34, 100-127, 141-153, 155-185
  inexact.py 73-74
  precision_theory.py 91-92, 115-117, 134, 270
  problems.py 332-338
  work_precision.py 48-49, 53-54, 68-74, 88-100
Project Total  

This report was generated by python-coverage-comment-action

pancetta and others added 2 commits October 8, 2026 15:30
…ables on the CPU

The coverage report had run_mpi.py and sweepers_MPI.py at 0%: the test spawned
`mpirun python run_mpi.py` in a subprocess, which coverage does not follow. It
now uses pySDC's convention for MPI tests, @pytest.mark.parallel(3), which
etc/run_mpi_tests.sh runs under mpiexec in-process. run_mpi.main takes the
precision as an argument instead of reading sys.argv, and a mismatch is an
assertion every rank reaches, broadcast from rank 0, instead of comm.Abort.

run_gpu.py was at 55%: nothing called its command line. A base test now runs
its three tables (CG, FFT, ParaDiag with adaptive alpha) on a 16x16 grid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
heat_paradiag replaced the problem's init and cast its operator to complex by
hand, which predates `dtype` on the finite-difference problems: with
dtype='complex128', now its default, the stock problem does both. What remains
is what `dtype` cannot do -- solve at a different precision from the state,
since dtype='complex64' would store the solution in single precision too, which
is the control that stalls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pancetta
pancetta marked this pull request as draft October 8, 2026 14:09
pancetta and others added 2 commits October 8, 2026 16:16
…rameters

The node-local solve precision was `solve_precision` on five problem classes
and `solve_dtype` on heat_solve_dtype. The library's own delta-form parameter
is `correction_precision`, so the project now says `solve_precision`
throughout, and heat_solve_dtype is folded into heat_delta: one heat problem,
with `solver_type` choosing the route -- 'direct' the dense emulation it had,
'CG' and 'FFT' the genuine solves heat_solve_dtype had.

The problems' own parameters (solve_precision, normalize, and the test helper's
eta and seed) are registered with _makeAttributeAndRegister, as every pySDC
problem parameter is, instead of being set as plain attributes that never
reached prob.params. heat_paradiag uses the registered value rather than a
private copy, and counts its solves as `jacobian_solves`, the library's name,
instead of `paradiag_solve`.

The README's demo tables come out identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sion

The README used ε for both the collocation residual (ε_m, ε_G = R ε_F, the
update ε ← ε − δ + Δt QΔf) and a format's precision (ε|u|, ε/α), sometimes in
the same paragraph. The residual is now r_m, as SDC is usually written, and ε
means precision throughout, which the method section now says once. Where |r|
meant the right-hand side of the correction solve, it now says so. The
AdaptiveAlpha floor wrote its inner tolerance as τ, which is the FAS correction
everywhere else in the README; it now names the parameter, inner_tol.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pancetta and others added 2 commits October 9, 2026 00:05
Brings in #785 (solve_precision and the FFT solve on the finite-difference
problems) and #786 (the correction-solve contract), which the project moves
onto next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lve contract

#785 gave the finite-difference problems a solve precision of their own and an
FFT solve, and #786 made the delta-form sweeper scale the linear route's
right-hand side for any solver. The project's own versions of both go:

- heat_delta keeps only what no library solver has, half precision on a sparse
  solver, which it emulates; every other precision is the library's genuine
  solve. Its CG and FFT routes and its `normalize` knob are gone.
- heat_paradiag goes entirely: ParaDiag runs on the stock heat problem with
  dtype='complex128' and the library's solve_precision. paradiag.py keeps the
  transform at reduced precision, and circulant_eigenvalues goes with it.
- run_gpu.py uses heatNd_unforced and heatNd_forced directly.
- The project's FFT tests, which the library's test_FD_solve_precision now
  covers, and the GPU fingerprint of the FFT solve go.

The heat ladder's "unnormalised fp16 solve" control no longer fails, because
the sweeper now scales for that solver -- the contract working. It is removed
from the table, and lives on in the library's test with the scaling switched
off. The heat figure's control becomes stock SDC with the same half-precision
solve (it stalls at 0.25); Allen-Cahn keeps its unscaled solver, since on the
nonlinear route the solver scales itself. The README says so.

Every iteration count in the heat table is unchanged; the fp32 rows' floors move
within round-off (7.2e-14 to 8.8e-14), their solves now genuine rather than
emulated. ParaDiag's table is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pancetta
pancetta marked this pull request as ready for review October 9, 2026 05:34
pancetta and others added 7 commits October 9, 2026 10:47
…nd methods

The delivered-accuracy specification -- what relative accuracy eta a node-local
solve must deliver before it costs iterations -- was measured on 1D heat only.
eta_spec.py measures it on 19 configurations: heat across four decades of
stiffness, two to five nodes and three preconditioners, MLSDC with the fine or
the coarse solve spoiled, advection from CFL 0.5 to 8, Allen-Cahn at three step
sizes and Van der Pol from mu=1 to 100. Per configuration: the exact run's
contraction rate rho, and eta*, the largest eta at which the run, and every run
with a more accurate solve, costs at most one iteration more.

inexact() generalises heat_inexact to any problem and both solve routes, so the
sweep needs no problem twins; heat_inexact is now inexact(heat_delta).
vanderpol_delta gives Van der Pol a correction solve -- an analytically expanded
increment and a Newton iteration on the parent's solve_jacobian -- without which
the delta sweeper would substitute the state.

First result: eta* spans seven decades, 3e-8 to 1e-1, and does not follow the
contraction rate measured on the solution. Where the solution's mode contracts
much faster than the worst mode of the iteration (heat at small dt, advection),
(rho_solution / rho_worst)^K predicts eta* to a factor of two: the solver's error
excites every mode, and the slow ones outlast the converging solution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sweep showed the contraction rate measured on the solution does not predict
eta*. Linear error propagation does: a sweep maps the collocation error by
K = I - L^-1 R; a solve error made in sweep j enters as L^-1 D eps, is contracted
by every later sweep and shows in the residual through R. Per mode of the
operator that is an M x M computation, and with white noise of relative size eta
on every solve -- what the spoiling does, and what rounding does -- the expected
maximum residual it leaves at iteration K + 1 gives eta*. The only input from
the exact run is the size of each node's correction per sweep; nonlinear
problems use the Jacobian at the initial value, and MIN-SR-FLEX's changing
preconditioner is followed sweep by sweep.

Predicted against measured, for the 15 heat, advection and Allen-Cahn
configurations: within a factor of 4 across seven decades, 3e-9 to 3e-3. Van der
Pol is the exception, where the theory is optimistic by up to 300x: two
unknowns are no white-noise statistics, and the linearisation is crude.

IE is dropped, as agreed; MIN-SR-S is added for advection and Allen-Cahn, and
MIN-SR-NS for non-stiff Van der Pol. MIN-SR-NS does not converge on stiff heat,
and MIN-SR-FLEX, built for a fixed number of sweeps, takes 51 iterations to the
tolerance there, so neither is in the heat set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The modal prediction needed the operator's spectrum, so a nonlinear problem had to
be linearised at one state, and an opaque solver could not be treated at all.
Perturbation theory needs neither. Two mechanisms, and eta* is the smaller:

- noise: spoiling a single sweep j measures the residual its solve error leaves
  at iteration K + 1, a transfer coefficient T_j; independent errors superpose,
  so eta*_noise = tol / sqrt(sum T_j^2). K + 1 probing runs, nothing linearised.
- rate: the error is relative to the correction and feeds back, so each sweep
  contracts by about rho + eta; an iteration is lost once (rho + eta)^(K+1) no
  longer beats rho^K: eta*_rate = rho (rho^(-1/(K+1)) - 1), from the exact run.

Against the measured eta* of all 19 SDC configurations: within a factor of 5,
from 3e-9 to 1e-1, Van der Pol included, which the noise mechanism alone
mispredicted by up to 1000x -- it is the one case where the rate binds.
eta*_rate is 1e-2 to 3e-2 everywhere, so for every format finer than bfloat16
only the noise mechanism matters.

inexact() takes `calls`, the solve calls to spoil, which is how a single sweep is
perturbed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
precision_theory.py predicts eta* without any inexact run: the exact run's
per-sweep corrections, the test-equation matrices E(z), F(z) integrated over
the operator's analytic spectral measure, Hoeffding + union bound, and the
rate condition for the feedback. All 19 SDC configurations within the
measurement's half-decade resolution or a factor 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Iteration matrix K = I - P^-1 C acting on the error, the residual through C,
restol instead of tol, eigenvalues instead of a spectral measure. Same numbers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…len-Cahn bound

precision_theory: per-iteration contributions to Psi, bound(extra=m), and
schedule(), a format per iteration from Theorem 2. Allen-Cahn uses the maximum
over the interval of its frozen symmetric Jacobian's spectrum instead of the
bulk-median heuristic; every prediction is now on the safe side. inexact():
a per-iteration schedule of noise levels or formats, rounding relative to the
maximum (fp64, fp32, fp16, bf16).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…data

genuine.py: node solves in true fp32/fp16/bf16 arithmetic (dense LU, every
operation rounded to the format), the comparison table and time stepping with
formats chosen from the previous step's run. precision_theory: a 'residual'
error model for backward-stable solves (residual u ||D_j|| |delta_j|,
transfer C K^n P^-1) next to the 'result' model, the rate condition on the
forward error kappa u, analysis from any recorded run (record_run, analyse).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pancetta and others added 5 commits October 9, 2026 19:45
work_precision.py minimises the work for a target error over M, dt, restol
and the formats (fp64 versus formats chosen from the previous step, genuine
low-precision solves) and draws the fronts. precision_theory.kappa: the
a-priori stiffness of the node systems, for the first step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The project keeps what computes; what presents results (the two plot scripts
and their test, the figure and table printing of eta_spec, work_precision and
genuine) goes, to come back as the reproduction scripts of a publication.
work_precision.sweep returns the rows instead of writing pickles. The README
now covers usage, contents and tests; the measurements, tables and lessons
learned are no longer in it. References to the README in code and tests are
reworded, and the cascade's rule that u[0] keeps its precision moved into its
docstring. The gallery card has no plot until then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nts after #808

run_demo's Allen-Cahn MLSDC transferred 64 -> 32 on a periodic grid without
periodic=True. Before #808 that took the nested shortcut on the wrong grid
(an O(h) interpolation error), since #808 the general non-periodic one. With
the periodic transfer, 64 -> 32 is nested, and every MLSDC row of the table
needs 16 sweeps instead of 20; the controls still stall at 60.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The project now covers one question: whether the implicit solves of SDC can
be done in reduced precision without losing the accuracy of the collocation
problem. The broader study (emulated low precision on MLSDC's coarse levels,
the storage precision ladder, the node-parallel variant, ParaDiag, PETSc,
FEniCS and the GPU runs, with their tests) is removed; the code and the README
with its results are kept in the tag deltasdc-precision-study-2026-11.
eta_spec loses its MLSDC cases, and bf16 is dropped from the formats. The
README is rewritten for what remains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant