Repository navigation
Poisson profiling cases with mass-matrix and stiffness preconditioners; Kronecker preconditioners in ImplicitDiffusion - #739
Merged
Conversation
…s; wire Kronecker preconditioners into ImplicitDiffusion
- ImplicitDiffusion/PoissonSolve/PoissonAdiabaticGyrokinetic: precond="MassMatrixPreconditioner"
(and the Diagonal variant) now builds the preconditioner from M0 (it was silently ignored),
new precond="StiffnessPreconditioner" (sigma = sigma_1, rebuilt when sigma_1/dt changes),
new option precond_params (kwargs for the preconditioner), default precond=None
- PoissonSolve: default stab_mat="M0" (was "Id")
- ImplicitDiffusion: pass pc only to "pcg" (solver="cg" raised a TypeError)
- StiffnessPreconditioner: take the 1d difference matrices from the 3d derivative blocks
(tokronstencil); the hand-built ones were wrong for a single periodic element
- new profiling cases cube_strong_scaling_{massmatrix,stiffness} with submit scripts
- tests: Kronecker preconditioners in PoissonSolve (pcg/cg, M0/Id), stiffness preconditioner
with changing dt, single-element regression; existing tests use precond=None
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
profiling/submit_*.py -> profiling/examples/<Model>/submit_*.py, so each submit script sits next to the folder with its params file. The scripts put profiling/ on sys.path for the driver modules, params_dir is relative to the new location. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n path in profiling workflow The profiling workflow called the nonexistent profiling/submit_diocotron_job.py with --language and --compiler, which the submit scripts did not accept. All submit scripts now take both (defaults fortran/GNU, as hardcoded before) and pass them to ProfilingCase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ussian exact solution - 8 new cases (hollow cylinder and full hollow torus, a1=1e-2, a2=1, Lz=R0=4) with no, multigrid, mass-matrix and stiffness preconditioner, with submit scripts next to their folders - all 12 Poisson cases (incl. the cube ones) use a Gaussian 0-form on the logical domain centered at eta=(0.5,0.5,0.5) as exact solution, with the analytic -Laplace(phi) per mapping as source; errors are computed at the pushed-forward evaluation points, thresholds calibrated at 64^3 - maxiter=3000 for all cases (multigrid on the hollow torus needs ~190 iterations at 32^3) - slice plots in physical coordinates (cross-section / poloidal plane) or logical coordinates Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mit script names - profiling/examples/Poisson/generate_cases.py writes params_poisson.py and the submit script of all 12 cases (3 mappings x 4 preconditioners) from one template and formats them with ruff; it also holds the error limits calibrated at 64^3 - submit_poisson_strong_scaling*.py -> submit_poisson_cube_strong_scaling*.py (labels unchanged), docstring/name/description in the same wording as the other cases Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dim_reduce=None explicitly - MassMatrixDiagonalPreconditioner was MassMatrixPreconditioner(dim_reduce=None, diagonal_scaling=True); with diagonal_scaling=True as default it is now MassMatrixPreconditioner(M, dim_reduce=None) - "MassMatrixDiagonalPreconditioner" removed from OptsMassPrecond and OptsDiffusionPrecond (clean break) - variational propagators and variational_utilities: MassMatrixPreconditioner(..., dim_reduce=None) (cheap update_mass_operator for weights that change every step), behavior unchanged; default precond option "MassMatrixPreconditioner" - ShearAlfvenCurrentCoupling5D: default precond "MassMatrixPreconditioner" (dim_reduce=0, fixed mass matrix) - default dim_reduce=0 kept: exact for weights/mappings varying only in eta1 (2 PCG iterations vs 7-10 on HollowCylinder), comparable otherwise; docstring explains when to use None; the reference of the diagonal scaling moved to MassMatrixPreconditioner Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spossann
commented
Oct 9, 2026
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Adiabatic gyrokinetic multigrid is built before the stabilization projection, leaving it configured for a different operator.
1 open finding
What changed in this PR
Adds Kronecker preconditioners to Poisson diffusion solves and expands strong-scaling profiling across cube, hollow-cylinder, and hollow-torus geometries.
Changes:
- Implements mass-matrix and stiffness preconditioners in
ImplicitDiffusion. - Consolidates mass preconditioners and fixes single-element periodic stiffness factors.
- Generates 12 Poisson profiling cases and relocates profiling submit scripts.
| File | Description |
|---|---|
src/struphy/propagators/variational_viscosity.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_resistivity.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_qb_evolve.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_pb_evolve.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_momentum_advection.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_mag_field_evolve.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_entropy_evolve.py |
Migrates mass preconditioners. |
src/struphy/propagators/variational_density_evolve.py |
Migrates and updates dynamic preconditioners. |
src/struphy/propagators/tests/test_poisson.py |
Tests Kronecker preconditioners and dynamic timestep handling. |
src/struphy/propagators/tests/test_gyrokinetic_poisson.py |
Preserves unpreconditioned test behavior. |
src/struphy/propagators/shear_alfven_current_coupling_5d.py |
Updates the default preconditioner. |
src/struphy/propagators/poisson_solve.py |
Exposes new preconditioner options and defaults. |
src/struphy/propagators/poisson_adiabatic_gyrokinetic.py |
Exposes diffusion preconditioners. |
src/struphy/propagators/implicit_diffusion.py |
Builds and updates selected preconditioners. |
src/struphy/io/options.py |
Revises preconditioner literals. |
src/struphy/feec/variational_utilities.py |
Migrates utility preconditioning. |
src/struphy/feec/tests/test_stiffness_preconditioner.py |
Covers single-element periodic directions. |
src/struphy/feec/tests/test_preconditioner_transpose.py |
Updates consolidated preconditioner tests. |
src/struphy/feec/preconditioner.py |
Consolidates mass preconditioners and fixes derivative factors. |
profiling/examples/ToyGyrokinetic/submit_diocotron_strong_scaling.py |
Relocates submission and adds compiler options. |
profiling/examples/Poisson/submit_poisson_hollow_torus_strong_scaling.py |
Submits unpreconditioned torus profiling. |
profiling/examples/Poisson/submit_poisson_hollow_torus_strong_scaling_stiffness.py |
Submits stiffness torus profiling. |
profiling/examples/Poisson/submit_poisson_hollow_torus_strong_scaling_multigrid.py |
Submits multigrid torus profiling. |
profiling/examples/Poisson/submit_poisson_hollow_torus_strong_scaling_massmatrix.py |
Submits mass-matrix torus profiling. |
profiling/examples/Poisson/submit_poisson_hollow_cylinder_strong_scaling.py |
Submits unpreconditioned cylinder profiling. |
profiling/examples/Poisson/submit_poisson_hollow_cylinder_strong_scaling_stiffness.py |
Submits stiffness cylinder profiling. |
profiling/examples/Poisson/submit_poisson_hollow_cylinder_strong_scaling_multigrid.py |
Submits multigrid cylinder profiling. |
profiling/examples/Poisson/submit_poisson_hollow_cylinder_strong_scaling_massmatrix.py |
Submits mass-matrix cylinder profiling. |
profiling/examples/Poisson/submit_poisson_cube_strong_scaling.py |
Updates unpreconditioned cube submission. |
profiling/examples/Poisson/submit_poisson_cube_strong_scaling_stiffness.py |
Submits stiffness cube profiling. |
profiling/examples/Poisson/submit_poisson_cube_strong_scaling_multigrid.py |
Updates multigrid cube submission. |
profiling/examples/Poisson/submit_poisson_cube_strong_scaling_massmatrix.py |
Submits mass-matrix cube profiling. |
profiling/examples/Poisson/hollow_torus_strong_scaling/params_poisson.py |
Defines unpreconditioned torus case. |
profiling/examples/Poisson/hollow_torus_strong_scaling_stiffness/params_poisson.py |
Defines stiffness torus case. |
profiling/examples/Poisson/hollow_torus_strong_scaling_multigrid/params_poisson.py |
Defines multigrid torus case. |
profiling/examples/Poisson/hollow_torus_strong_scaling_massmatrix/params_poisson.py |
Defines mass-matrix torus case. |
profiling/examples/Poisson/hollow_cylinder_strong_scaling/params_poisson.py |
Defines unpreconditioned cylinder case. |
profiling/examples/Poisson/hollow_cylinder_strong_scaling_stiffness/params_poisson.py |
Defines stiffness cylinder case. |
profiling/examples/Poisson/hollow_cylinder_strong_scaling_multigrid/params_poisson.py |
Defines multigrid cylinder case. |
profiling/examples/Poisson/hollow_cylinder_strong_scaling_massmatrix/params_poisson.py |
Defines mass-matrix cylinder case. |
profiling/examples/Poisson/generate_cases.py |
Generates all Poisson profiling cases. |
profiling/examples/Poisson/cube_strong_scaling/params_poisson.py |
Updates unpreconditioned cube case. |
profiling/examples/Poisson/cube_strong_scaling_stiffness/params_poisson.py |
Defines stiffness cube case. |
profiling/examples/Poisson/cube_strong_scaling_multigrid/params_poisson.py |
Updates multigrid cube case. |
profiling/examples/Poisson/cube_strong_scaling_massmatrix/params_poisson.py |
Defines mass-matrix cube case. |
.github/workflows/reusable-profiling-clusters.yml |
Calls the relocated Diocotron script. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
max-models
previously approved these changes
Oct 9, 2026
Multigrid would be built in ImplicitDiffusion.allocate() for the stabilization without the average, which this propagator applies afterwards, and is never updated (sigma is constant), so it would precondition the wrong operator. The multigrid field is removed again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
max-models
previously approved these changes
Oct 9, 2026
The 12 params files and submit scripts stay as they are; they are edited directly from now on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
max-models
approved these changes
Oct 9, 2026
spossann
added a commit
that referenced
this pull request
Oct 9, 2026
…stab, weighted average in the stabilization (#740) ## Summary Makes `StiffnessPreconditioner` work for `PoissonAdiabaticGyrokinetic` (and other `ImplicitDiffusion` operators with a general diffusion matrix and stabilization), and makes the toroidal adiabatic gyrokinetic Poisson operator symmetric. Follow-up of #739 (merged), rebased onto `devel`. Addresses the review comment #739 (comment) properly; #739 itself only rejected multigrid for `PoissonAdiabaticGyrokinetic`. Points the `feectools` submodule to the branch of struphy-hub/feectools#102 (`KroneckerSumSolver` with stiffness coefficients and additional Kronecker terms, feectools 0.8.0). The `feectools` pin in `pyproject.toml` is raised once 0.8.0 is on PyPI. ### `StiffnessPreconditioner`: `mid`, `stab`, `stab_average` Preconditioner for $\mathbb d^T \mathbb M_{\textrm{mid}} \mathbb d + \sigma \, \mathbb S (\mathbb I - \mathbb A)$, all new inputs as strings with the previous behavior as default: - `mid`: name of a mass operator in `mass_ops` (e.g. `"M1gyro"`, `"M1perp"`) or the operator itself (`WeightedMassOperator`, or sums/multiples such as `M1gyro = M1_MHDeq - M1para_MHDeq`), with the domain/codomain of $\mathbb M_{k+1}$; default $\mathbb M_{k+1}$. Blocks with zero mean (e.g. the parallel direction of a perpendicular operator) have no stiffness term; their 1d stiffness still defines the eigenbasis (`stiffness_coeffs` in feectools#102). - `stab`: name or operator with the domain/codomain of $\mathbb M_k$ (e.g. `"M0ad_withT"`), or `"Id"`; default $\mathbb M_k$. - `stab_average` (gradient only): directions averaged in the stabilization, e.g. `"eta3"`, `"eta2 eta3"`. The term is approximated by $\bar s\,(M_1 \otimes M_2 \otimes M_3 - F_1 \otimes F_2 \otimes F_3)$ with $F_d = c_d c_d^T/(\mathbb 1^T c_d)$, $c_d = M_d \mathbb 1$, which is exact in the eigenbasis of periodic directions (`mass_terms` in feectools#102). The average couples whole lines and is left out of the diagonal scaling (probing cannot resolve it; its diagonal is O(1/n)), which keeps the preconditioner exact on the logical cube. ### `WeightedAverageProjection` (new, `feec/mass.py`) The $\mathbb S$-orthogonal projection onto functions constant in the averaged directions, $\Pi = \mathbb E (\mathbb E^T \mathbb S \mathbb E)^{-1} \mathbb E^T \mathbb S$; then $\mathbb S(\mathbb I - \Pi)$ is symmetric. For $\mathbb M^0$ this is the flux-surface average with $\sqrt g$; it equals the plain `AverageOperator` when the weight of $\mathbb S$ does not depend on the averaged directions (cube, cylinder: identical to round-off). The reduced matrix is assembled once by colored probing and factorized (sparse LU); one application costs one application of $\mathbb S$. **Why:** with the plain (unweighted) `AverageOperator`, the toroidal stabilization $\mathbb M^0 (\mathbb I - \mathbb A)$ is not symmetric ($\sqrt g = rR$ depends on $\eta_2$; $|x^T S y - y^T S x| / |x^T S y| \approx 0.3$), but `PoissonAdiabaticGyrokinetic` solves it with pcg. **Toroidal results change** (the average is now weighted with $\sqrt g$, and with $n/T$ of `M0ad_withT`, a flux function for the usual equilibria); cylindrical results are unchanged. ### `ImplicitDiffusion`, `PoissonSolve`, `PoissonAdiabaticGyrokinetic` - New option `stab_average`; `ImplicitDiffusion` builds `stab_mat @ (I - WeightedAverageProjection)` before the preconditioners and passes `diffusion_mat`, `stab_mat` and `stab_average` to the stiffness preconditioner. `precond="MultiGrid"` is rejected with `stab_average`. - `PoissonAdiabaticGyrokinetic`: `stab_average` follows from `which_geometry` (cylindrical: `"eta3"`, toroidal: `"eta2 eta3"`) instead of patching `_stab_mat` after `allocate()`; multigrid rejected. ### Results PCG iterations, `PoissonAdiabaticGyrokinetic` (`M1gyro`, `M0ad_withT`, epsilon = 0.1, 12x12x8 elements): | geometry | no preconditioner | stiffness preconditioner | |---|---|---| | cylindrical (HollowCylinder) | 34 | 10 | | toroidal (HollowTorus) | 109 (429 before, non-symmetric) | 20 | On the unit cube the preconditioner is exact (2 iterations) for constant anisotropic or perpendicular `mid`, a scaled `stab` or `stab="Id"` (whose average is Euclidean, $F_d = \mathbb 1 \mathbb 1^T/n$), and `stab_average` `"eta3"`/`"eta2 eta3"`. `stab_average="eta1 eta2 eta3"` (global weighted mean) is supported as well. ### Tests - `test_stiffness_preconditioner_mid_stab_average` (exactness on the cube), `test_stiffness_preconditioner_mid_stab_options` - `test_weighted_average_projection.py` (new file in `feec/tests`, already in the CI shards): symmetry, projection, equality with `AverageOperator` (Cuboid, HollowCylinder, HollowTorus x M0, M0ad_withT) - `test_poisson_adiabatic_gyrokinetic_stiffness_preconditioner` (cylindrical, toroidal): same solution as without preconditioner, fewer than half the iterations; multigrid rejected Locally: stiffness, weighted average, gyrokinetic Poisson and Poisson tests pass serially and on 2 ranks; default-params test of `DriftKineticElectrostaticAdiabatic` passes; feectools kron tests pass serially and on 2 ranks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
max-models
added a commit
that referenced
this pull request
Oct 9, 2026
MassMatrixDiagonalPreconditioner was removed on devel (#739); the CuPy test now checks MassMatrixPreconditioner with and without diagonal scaling and with dim_reduce=None instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Adds two Poisson strong-scaling profiling cases that differ from the existing ones only in the preconditioner, and makes the preconditioner choice actually reach the solver in
ImplicitDiffusion(and thusPoissonSolveandPoissonAdiabaticGyrokinetic).New profiling cases
profiling/examples/Poisson/cube_strong_scaling_massmatrix/+profiling/examples/Poisson/submit_poisson_cube_strong_scaling_massmatrix.py(precond="MassMatrixPreconditioner",maxiter=3000)profiling/examples/Poisson/cube_strong_scaling_stiffness/+profiling/examples/Poisson/submit_poisson_cube_strong_scaling_stiffness.py(precond="StiffnessPreconditioner",maxiter=100)Poisson cases on HollowCylinder and HollowTorus
profiling/examples/Poisson/hollow_{cylinder,torus}_strong_scaling{,_multigrid,_massmatrix,_stiffness}/with submit scriptssubmit_poisson_hollow_{cylinder,torus}_strong_scaling*.py. HollowCylindera1=1e-2, a2=1, Lz=4; full HollowTorus (tor_period=1)a1=1e-2, a2=1, R0=4.given_in_basis="0"). The errors are computed at the pushed-forward evaluation points x = F(eta). The Laplacians agree with a metric-based finite-difference Laplacian to 3e-6; the error converges at second order (16^3 -> 64^3); thresholds are calibrated at 64^3.maxiter=3000for all cases (multigrid on the hollow torus needs ~190 iterations at 32^3, the stiffness preconditioner ~60 on the hollow mappings at 64^3).submit_poisson_cube_strong_scaling*.py(labels unchanged), like the other casessubmit_poisson_<mapping>_strong_scaling<_precond>.py.Profiling results (local, 64^3, 1 and 2 MPI ranks)
All 12 cases run locally with the submit scripts (rank counts limited to 1 and 2 on a laptop with an i5-1135G7, 4 cores), commits 71e3a91 / 49f252a (no change to the Poisson code in between). Times of the slowest rank in seconds, from the
profiling_data.h5files (solve: PoissonSolve,setup: total); the iteration counts are the same for 1 and 2 ranks. All runs pass their error checks (max relative error of phi: cube 9.03e-3, hollow cylinder 9.72e-3, hollow torus 9.85e-3).MassMatrixPreconditioner:diagonal_scaling=Trueby defaultAffects all propagators that build a mass preconditioner by name and the multigrid mass smoother. FEEC/multigrid/Poisson/curl-curl/saddle-point tests pass on 2 ranks (251 passed).
PoissonAdiabaticGyrokinetic: multigrid rejectedMultigrid would be built for the stabilization without the flux-surface average (applied after
ImplicitDiffusion.allocate()) and never updated, see the review comment. Full support of the stiffness preconditioner for this propagator (M1gyro, M0ad_withT, weighted average) follows in the stacked PR #740 (paired with struphy-hub/feectools#102).MassMatrixDiagonalPreconditionerremoved (API change)MassMatrixPreconditioner(dim_reduce=None, diagonal_scaling=True); with the new default it is nowMassMatrixPreconditioner(M, dim_reduce=None)."MassMatrixDiagonalPreconditioner"removed fromOptsMassPrecondandOptsDiffusionPrecond(clean break, params files naming it failcheck_option).variational_utilities:MassMatrixPreconditioner(..., dim_reduce=None)explicitly (cheapupdate_mass_operatorfor weights that change every step), behavior unchanged; defaultprecondoption is now"MassMatrixPreconditioner".ShearAlfvenCurrentCoupling5D: defaultprecond="MassMatrixPreconditioner", i.e. nowdim_reduce=0(its mass matrix is fixed).dim_reduce=0kept: exact for weights/mappings varying only in eta1 (PCG on a HollowCylinder: 2 iterations vs 7–10 withNone), comparable otherwise (HollowTorus 7–9 vs 8–11, Colella 10–85 vs 10–77).Tests: preconditioner, variational utilities/propagators, current coupling 5D, variational dissipation and the default-params fluid/hybrid/visco-resistive model tests pass serially (36); FEEC/variational tests on 2 ranks (20 passed).
Submit scripts next to their cases
profiling/submit_*.pymoved toprofiling/examples/<Model>/, next to the folder with their params file (Poisson and ToyGyrokinetic). They putprofiling/onsys.pathfor the driver modules;params_diris relative to the new location.--language(fortran/c) and--compiler(defaultsfortran/GNU, as hardcoded before), passed toProfilingCase.reusable-profiling-clusters.ymlcalled the nonexistentprofiling/submit_diocotron_job.pywith--language/--compiler, which no script accepted; it now callsprofiling/examples/ToyGyrokinetic/submit_diocotron_strong_scaling.py.Smoke run at 32³ on 2 ranks: no preconditioner 103 iterations, mass matrix 214, stiffness 2 (identical errors).
Preconditioner options in
ImplicitDiffusionprecond="MassMatrixPreconditioner"/"MassMatrixDiagonalPreconditioner"now builds the preconditioner fromM0. Before, every value except"MultiGrid"was silently ignored (pc=None).precond="StiffnessPreconditioner":StiffnessPreconditioner(mass_ops, "grad", sigma=sigma_1), rebuilt in__call__whensigma_1changes (e.g. withdivide_by_dt), like multigrid.sigma = sigma_1for anystab_mat(withsigma = 0the pseudo-inverse drops the constants, and PCG does not converge for periodic BCs withstab_mat="Id").precond_params: dict, passed to the preconditioner constructor (e.g.{"weights": "unit"}).precond=None(was"MassMatrixPreconditioner", which had no effect), so existing models keep their behavior. Any preconditioner requiressolver="pcg"."StiffnessPreconditioner"added toLiteralOptions.OptsDiffusionPrecond.Note: the mass-matrix preconditioner does not approximate the Laplacian and makes CG 3–6x slower (e.g. 555 vs 143 iterations in the new test); it is there for the profiling comparison.
Other changes
PoissonSolve: defaultstab_mat="M0"(was"Id"); consistent withImplicitDiffusionand with the weak form ε(ψ, φ) (most examples already set it explicitly).solver="cg":pcwas always passed toinverse, andConjugateGradienthas nopcargument (TypeError). Now passed only for"pcg".StiffnessPreconditioner: the hand-built 1d difference matrix was wrong for a single periodic element (+1overwrote-1, giving[[1]]instead of[[0]]), adding a spurious stiffness term in that direction (e.g. 2.5D grids[Nx, Ny, 1]). The 1d matrices are now taken from the 3d derivative blocks viaDirectionalDerivativeOperator.tokronstencil()(global on every rank), so they match the operator by construction. On a 2.5D cube the preconditioner is exact again (≤ 3 PCG iterations instead of 5–9).Tests
test_poisson_2d_kronecker_preconds(periodic/Dirichlet/Neumann ×stab_matM0/Id): mass-matrix and stiffness preconditioners, andsolver="cg", give the unpreconditioned solution; stiffness needs fewer iterations.test_implicit_diffusion_stiffness_dt: the stiffness preconditioner follows changes ofdt, exact on the cube.test_stiffness_approximation_unit_cube: new case with one element in z (fails without the fix).precond="MassMatrixPreconditioner"(effectively unpreconditioned so far) now useprecond=None.Locally on 2 ranks:
feec/tests/test_stiffness_preconditioner.py,propagators/tests/test_poisson.py,propagators/tests/test_gyrokinetic_poisson.pyall pass;test_verif_Poisson.pypasses. Other model tests left to CI.🤖 Generated with Claude Code