Skip to content

Add tutorial for driven solver (adaptive and uniform)#702

Merged
hughcars merged 21 commits into
mainfrom
phdum/driven_solver_docs
Jun 22, 2026
Merged

Add tutorial for driven solver (adaptive and uniform)#702
hughcars merged 21 commits into
mainfrom
phdum/driven_solver_docs

Conversation

@phdum-a

@phdum-a phdum-a commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

PR #676 had two tutorials: one on the driven solver generally, and one on the circuit extraction specifically.

This PR decouples these two tutorials for simplicity. It extracts the first tutorial since this is ready for review and does not depend on other text (like the port documentation in #696).

@phdum-a phdum-a requested a review from Sbozzolo April 9, 2026 16:59
@phdum-a phdum-a added the no-long-tests This PR does not require the long tests to be merged label Apr 9, 2026
@phdum-a phdum-a requested a review from parrangoiz April 9, 2026 17:03
@phdum-a

phdum-a commented Apr 15, 2026

Copy link
Copy Markdown
Contributor Author

Pushed 3 tiny commits to fix typo ($\Ohm$ -> $\Omega$), notation $V -> Q$ for orthogonalised basis, and python script formatting.

@Sbozzolo Sbozzolo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Largely discussed offline.]

The content looks great. I suggest breaking it up to make it more digestable (part of it could be in Features, other could be in References).

Two concerns on maintanability:

  • There are hardcoded numbers throughout the text that would need to change if other things change
  • The Python scripts have a lot of overlapping material

Comment on lines +63 to +66
- `"Linear"/"Tol"`: set the linear solver tolerance to be substantially smaller than
`"AdaptiveTol"`. The adaptive solver is based on an interpolation and can be unusually sensitive
to errors in the linear solver. Increase this tolerance in your validation runs and ensure the
output is no different. Should *Palace* log warnings like `Minimal rational interpolation encountered rank-deficient matrix` try tightening this tolerance substantially.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something we should explicitly say in the log message in Palace?

near the limit of what *Palace*'s solvers can reach using double precision. The error of the uniform
linear solve ``\bm{A}(\omega) \bm{x} = \bm{b}(\omega)`` also depends on the condition number of the
system matrix ``\bm{A}(\omega)`` at each frequency ``\omega = 2 \pi f``. Importantly, if the system
has resonances (poles) near the real axis, the linear solve may become very poorly conditioned. This

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
has resonances (poles) near the real axis, the linear solve may become very poorly conditioned. This
has resonances (poles) near the real axis, the linear solve may become poorly conditioned. This

resonator and in the feedline.

We will now perform uniform and adaptive driven simulations on this model, by exciting the
``50~\Ohm`` resistive ports. We will use the same mesh `examples/transmon/mesh/transmon.msh2` as the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
``50~\Ohm`` resistive ports. We will use the same mesh `examples/transmon/mesh/transmon.msh2` as the
``50~\Omega`` resistive ports. We will use the same mesh `examples/transmon/mesh/transmon.msh2` as the

### Uniform Solver

First, we set up a uniform driven simulation using the configuration file
[`cpw_lumped_uniform_convergence.json`](https://github.com/awslabs/palace/blob/main/examples/cpw/cpw_lumped_uniform_convergence.json).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was not included in the commit

Comment on lines +37 to +55
mpl.rcParams.update(
{
"figure.dpi": 150,
"font.family": "serif",
"font.serif": ["Times"],
"mathtext.fontset": "cm",
"axes.formatter.use_mathtext": True,
"savefig.bbox": None,
}
)

mpl.rcParams.update({
"figure.dpi": 150,
"font.family": "serif",
"font.serif": ["Times"],
"mathtext.fontset": "cm",
"axes.formatter.use_mathtext": True,
"savefig.bbox": None,
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated?

- [`"AdaptiveTol"`](../config/solver.md#solver%5B%22Driven%22%5D): start with `1e-3` on a coarse
grid for S-parameter sweeps. Tighten this tolerance as needed during the validation against the
uniform solver or in production runs.
- `"Linear"/"Tol"`: set the linear solver tolerance to be substantially smaller than

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually use the notation ["Linear"]["Tol"] for nested configs. To be more precise, the other doc pages often refer to configs arguments as config["Solver"]["Linear"]["Tol"].

sample frequency point ``f``. We will also refer to these solves as "full" or "High-Dimensional
Solves" (HDM) since they solve the full linear problem on the finite element space. Here we are
sampling a linear grid between ``2~\mathrm{GHz}`` and ``32~\mathrm{GHz}`` in steps of ``\Delta f = 0.1~\mathrm{GHz}``, but [users can provide more complicated sample
specification](../config/solver.md#solver%5B%22Driven%22%5D%5B%22Samples%22%5D).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
specification](../config/solver.md#solver%5B%22Driven%22%5D%5B%22Samples%22%5D).
specifications](../config/solver.md#solver%5B%22Driven%22%5D%5B%22Samples%22%5D).

discussed in the [eigenmode tutorial](transmon.md). We assume familiarity with that tutorial. As
discussed there, the model consists of a transmon qubit and a quarter-wave coplanar waveguide
readout resonator coupled to a feedline. There are three lumped ports in this model: ports 1 and 2
are the ``50~\Omega`` resistive feedline terminations and port 3 is a passive LC element (``L = 14.86\,\textrm{nH}``, ``C = 5.5\,\textrm{fF}``) representing the linearised Josephson junction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
are the ``50~\Omega`` resistive feedline terminations and port 3 is a passive LC element (``L = 14.86\,\textrm{nH}``, ``C = 5.5\,\textrm{fF}``) representing the linearised Josephson junction.
are the ``50~\Omega`` resistive feedline terminations and port 3 is a passive LC element (``L = 14.86\,\mathrm{nH}``, ``C = 5.5\,\mathrm{fF}``) representing the linearised Josephson junction.

for consistency with everything else

Comment on lines +500 to +501
- A “transmon” mode near ``4.10~\textrm{GHz}`` with ``Q = 1.8 \cdot 10^4``,
- A “resonator” mode near ``5.60~\textrm{GHz}`` with ``Q = 7.9 \cdot 10^3``.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- A “transmon” mode near ``4.10~\textrm{GHz}`` with ``Q = 1.8 \cdot 10^4``,
- A “resonator” mode near ``5.60~\textrm{GHz}`` with ``Q = 7.9 \cdot 10^3``.
- A “transmon” mode near ``4.10~\marhrm{GHz}`` with ``Q = 1.8 \cdot 10^4``,
- A “resonator” mode near ``5.60~\mathrm{GHz}`` with ``Q = 7.9 \cdot 10^3``.


In both plots above, the error is more structured than it was in the CPW example. It is worse near
the eigenmode locations and better far away. The adaptive solver also adds HDM solves in a more
structured manner to “shadow” the eigenmodes. This behaviour is simple to interpret — the response

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
structured manner to “shadow” the eigenmodes. This behaviour is simple to interpret — the response
structured manner to “shadow” the eigenmodes. This behavior is simple to interpret — the response

:P

@hughcars hughcars left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few small/nit things, but this is a huge step forward for the quality of documentation. You should mention it in the CHANGELOG, as though it isn't affecting user facing behaviour, it is a big improvement in how users will understand what is a non-standard technique for those not steeped in the numerical methods.

Only one a little bigger is it would be nice to generate the plots a) automatically from runs (possibly a long test) so that the docs are always kept in lock step with the code state, and b) generate with julia. b is mainly just a taste thing to avoid the language split, if the plots are much easier in python then I can be convinced.

Comment on lines +35 to +36
interpolates the response at all other output frequencies. This is fast, but requires more careful
set-up and validation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
interpolates the response at all other output frequencies. This is fast, but requires more careful
set-up and validation.
interpolates the response at all other output frequencies. This is fast, but introduces a source of error compared to the full model evaluation, which has to be controlled.

grid for S-parameter sweeps. Tighten this tolerance as needed during the validation against the
uniform solver or in production runs.
- `"Linear"/"Tol"`: set the linear solver tolerance to be substantially smaller than
`"AdaptiveTol"`. The adaptive solver is based on an interpolation and can be unusually sensitive

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`"AdaptiveTol"`. The adaptive solver is based on an interpolation and can be unusually sensitive
`"AdaptiveTol"`. The adaptive solver is based on an interpolation and can be very sensitive

Comment on lines +76 to +77
The rest of this tutorial will illustrate the driven solvers on two different examples (CPWs and
transmon), explain the adaptive algorithm in detail, and give more detailed user guidance.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The rest of this tutorial will illustrate the driven solvers on two different examples (CPWs and
transmon), explain the adaptive algorithm in detail, and give more detailed user guidance.
The rest of this tutorial will illustrate the driven solvers on two different examples (CPWs and
and the single transmon), explain the adaptive algorithm in detail, and give more detailed user guidance.

will define this quantity more precisely later. Simulation output, like `domain-E.csv`, has the same
structure as the uniform solver — they are evaluated on the same frequency grid specified by
`"Samples"` in the configuration file. However, the adaptive solver constructs a different
"internal" frequency grid on which it does HDM solves. This internal grid is automatically chosen by

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"internal" frequency grid on which it does HDM solves. This internal grid is automatically chosen by
*internal* frequency grid on which it does HDM solves. This internal grid is automatically chosen by

generally the same thing for most of the "" of terms here, they're not qualified so much as emphasized.

calculate many output samples as the “online” phase.

There is a large literature on constructing dimensional reductions of linear systems and we refer to
the literature for an introduction [1,2]. *Palace* finds a set of ``n`` real orthogonal vectors

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link the anchors.

Comment on lines +453 to +454
a practical sense of the error for different quantities, to help identify an appropriate adaptive
tolerance and to diagnose convergence errors.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
a practical sense of the error for different quantities, to help identify an appropriate adaptive
tolerance and to diagnose convergence errors.
a practical sense of the error for different quantities, to help identify an appropriate adaptive
tolerance, linear solver tolerance, and to diagnose convergence errors.

The interplay here with how accurate the HDM is itself is worth lightly mentioning. Not worth twiddling the adaptive if your HDM samples are all bad to begin with.

Comment on lines +555 to +558
excitation and frequency sample separately. However, for the adaptive solver, the projective basis
``\bm{Q}`` is shared between all excitations and the convergence criterion ``\varepsilon < \varepsilon_\mathrm{tol}`` is on that combined basis. This means that the output of each excitation
can be different when we simulate them together with one ROM or separately with two ROMs. However,
these differences are within the adaptive tolerance. See the discussion above.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's worth mentioning how this can work well with AMR, as the adaptation is driven by the error in both simulations, and the mesh kept consistent between the two. In the limit of deep AMR convergence it wouldn't matter, but for the ~1e-2 errors we often work at, it can make a big difference to ensure that the same mesh is used for all the excitations. Can possibly put in one of those info boxes that @Sbozzolo uses in his examples.

Comment on lines +651 to +664
[1] P. Benner, D. C. Sorensen, and V. Mehrmann, Eds., Dimension Reduction of Large-Scale Systems:
Proceedings of a Workshop held in Oberwolfach, Germany, October 19–25, 2003. in Lecture Notes in
Computational Science and Engineering, no. 45. Berlin, Heidelberg: Springer Berlin Heidelberg, 2005.
doi: 10.1007/3-540-27909-1.

[2] A. C. Antoulas, Approximation of Large-Scale Dynamical Systems. Society for Industrial and
Applied Mathematics, 2005. doi: 10.1137/1.9780898718713.

[3] D. Pradovera, “Toward a certified greedy Loewner framework with minimal sampling,” Adv Comput
Math, vol. 49, no. 6, p. 92, Dec. 2023, doi: 10.1007/s10444-023-10091-7.

[4] D. Pradovera, “Interpolatory rational model order reduction of parametric problems lacking
uniform inf-sup stability,” SIAM J. Numer. Anal., vol. 58, no. 4, pp. 2265–2293, Jan. 2020, doi:
10.1137/19M1269695.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if you can hyperlink to the doi.

Comment on lines +73 to +80
# # Run uniform sweep
# println("Running uniform sweep...")
# run(
# Cmd(
# `$palace_exec -np $num_processors cpw_tutorial_lumped_uniform.json`;
# dir=cpw_dir
# )
# )

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debris. If running uniform is to be an option make it a kwarg. I'd bias to just deleting this, or having it be an adaptive_tol=0.0 option below.


This Julia script runs Palace driven solver simulations on the transmon example, for
the "Driven Solver: Uniform vs Adaptive" tutorial. Use the accompanying
`transmon_tutorial_driven_plots.py` python script to generate plots once the data is

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason for splitting python/julia for these files? Is generating plots from julia more complicated?

@hughcars hughcars force-pushed the phdum/driven_solver_docs branch 2 times, most recently from 9d43666 to bd11b74 Compare June 16, 2026 17:23
phdum-a and others added 20 commits June 17, 2026 12:09
- First draft of CPW driven solver plots
- Add CPW json files for tutorial
- Rename files
- Add scripts to generate data and plots
- Update plots
- Add scripts to generate data and plots
* docs/src/examples/tutorial_driven_uniform_v_adaptive.md
  - Quick-start: rephrase the adaptive-solver introduction to flag it as
    a source of approximation error rather than just a setup cost.
  - Quick-start: switch the tolerance bullet to the standard
    `["Solver"]["Linear"]["Tol"]` nested-config notation, both in the
    bullet list and again in the 'Numerical problems' challenge.
  - Quick-start: re-target the broken
    `cpw_lumped_uniform_convergence.json` link to the file that is
    actually used by the tutorial, `cpw_tutorial_lumped_uniform.json`.
  - Quick-start: 'examples (CPWs and the single transmon)' for clarity.
  - Uniform solver: drop the redundant 'very' before 'poorly conditioned',
    and link to the `Samples` anchor with the right pluralisation.
  - Adaptive solver: change "internal" frequency grid to *internal* so
    it reads as emphasis (consistent with the rest of the page).
  - Projective construction: render `Re(x*)`, `Im(x*)` with explicit
    parentheses, and italicise *internal* in the same paragraph.
  - Choosing internal samples: 'does not explain how' (was 'tell us'),
    and soften 'is familiar' to 'may be familiar'.
  - Adaptive solver problems: re-flow 'Early termination' and
    'Numerical problems' as a numbered list so the bold labels render and
    the structure is obvious. (Previously the bolds collapsed into prose
    on the rendered preview, see PR704 preview build.)
  - User guidance: 'efficiently choose samples based on the observed
    approximation error', drop the now-unused 'computer' before 'memory',
    and call out 'linear solver tolerance' alongside adaptive tolerance
    in the validation paragraph.
  - Transmon set-up: switch all `\\textrm` units to `\\mathrm` for
    consistency with the rest of the docs (`nH`, `fF`, two `GHz`).
  - Transmon set-up: typo `\\Ohm` -> `\\Omega`.
  - Transmon Part II: 'behavior' (was 'behaviour'), to keep with US
    spelling already used elsewhere.
  - References: hyperlink the four DOIs.
  - Add a maintainer note (HTML comment, invisible to readers) at the top
    of the file documenting that the SVGs are committed snapshots, not
    auto-generated, and giving the regeneration recipe. Auto-generation is
    not feasible: each Palace run takes hours, so neither CI long-tests
    nor docs build-time hooks can absorb the cost. We accept that the
    plots may drift relative to the current solver; refresh by hand if a
    change meaningfully alters the qualitative shape of these curves.

* examples/cpw/cpw_tutorial_lumped_driven.jl
  - Replace the commented-out uniform-sweep block with a kwarg-style
    extension: `adaptive_tols` now starts with `0.0`, which Palace
    treats as the uniform driven solver, and is written to
    `postpro/tutorial_driven_rom/driven_uniform_reference`. This is
    the directory the plotting scripts already expect, so the script
    now generates the full set of tutorial data in a single invocation.

* CHANGELOG.md
  - Add an 'In progress' entry under 'New Features' announcing the new
    'Driven Solver: Uniform vs Adaptive' tutorial.

The Python plot scripts are not touched in this commit; they will be
replaced by the Julia/Makie ports in a follow-up PR.

Signed-off-by: Hugh Carson <hughcars@amazon.com>
Replaces the two Python plotting scripts with Julia/CairoMakie ports so
the data generation (`*_tutorial_driven.jl`) and the result plots are
both in the same language, dropping the language split flagged in the
PR review.

* examples/cpw/cpw_tutorial_lumped_driven_plots.jl (new)
* examples/transmon/transmon_tutorial_driven_plots.jl (new)
  - Reproduce the matplotlib plots: matplotlib `plasma` palette sampled
    over [0.1, 0.9], serif (Times) typography, two-line titles, dashed
    tolerance bands, dotted 1e-12 reference floor, diamond markers for
    the adaptive sample frequencies, and the gray-star initialization
    points on the convergence curve.
  - Use CairoMakie + ColorSchemes + CSV + DataFrames; no native deps
    beyond what `Plots` already pulled in.
  - Equation labels in titles and the per-axis `S_{ij}` annotations are
    rendered as `LaTeXString`s via MathTeXEngine. The descriptive
    line of two-line titles uses a plain string in a separate Label
    (LaTeX line breaks `\\\\` are not supported by MathTeXEngine).
  - Both scripts accept `--out <dir>` to override the default
    `docs/src/assets/examples` output, useful for previewing.

* examples/cpw/cpw_tutorial_lumped_driven_plots.py (deleted)
* examples/transmon/transmon_tutorial_driven_plots.py (deleted)

* examples/Project.toml
  - Add ColorSchemes (used directly by the new plotting scripts; was
    already an indirect dependency through CairoMakie).

* docs/src/assets/examples/driven_ua_*.svg
  - Regenerate all 11 SVGs from the same simulation outputs using the
    new Julia plotters. The files in this commit are visually equivalent
    to the matplotlib originals (same data, same palette, same axis
    limits and tick spacings).

* docs/src/examples/tutorial_driven_uniform_v_adaptive.md
  - Update the maintainer note and the in-page `!!! note` block to
    reference the `.jl` plot scripts instead of the now-deleted
    `.py` scripts.

Signed-off-by: Hugh Carson <hughcars@amazon.com>
@hughcars hughcars force-pushed the phdum/driven_solver_docs branch from bd11b74 to f0ec3db Compare June 17, 2026 16:09
@hughcars hughcars enabled auto-merge June 17, 2026 16:10
@hughcars hughcars merged commit 21cb5d3 into main Jun 22, 2026
108 of 110 checks passed
@hughcars hughcars deleted the phdum/driven_solver_docs branch June 22, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-long-tests This PR does not require the long tests to be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants