Repository navigation
Jacobian reuse across reinit! and for matrix-free preconditioners - #1353
Open
ParadaCarleton wants to merge 3 commits into
Open
ParadaCarleton wants to merge 3 commits into
ParadaCarleton wants to merge 3 commits into
Conversation
A matrix-free Jacobian operator is rebound to the current iterate on every step, so JacobianReuse switched itself off for it. What is expensive there is the preconditioner: an iterative linear solver rebuilt its `precs` whenever `A` was rebound, even when the caller asked to reuse. An explicit JacobianReuse policy now stays active for a matrix-free operator. Steps remain exact Newton steps (the operator is bound to the current iterate); the preconditioner built for the last refreshed Jacobian is kept until the policy refreshes. The size-based default still leaves matrix-free solves untouched. `reuse_A_if_factorization = true` now keeps the preconditioner of an iterative linear solver (via LinearSolve's `reinit!(...; reuse_precs = true)`) in addition to a factorization.
…oss solves reinit! reset the Jacobian reuse policy, so a sequence of related solves through one cache (continuation correctors) refactorized and rebuilt the preconditioner at the start of every solve; only the manual step!(cache; recompute_jacobian = false) interface kept a Jacobian. With reuse_jacobian = true, the first-order cache keeps its Jacobian, the linear solver's factorization and preconditioner, and the policy's age. The residual reference is set to the new initial residual, so the first step's contraction decides a refresh as usual, and the stale-Jacobian retry still applies. Default reinit! behavior is unchanged.
…= true) in quasi-Newton solvers
Author
|
Could a maintainer approve the CI workflows (they are waiting on first-contributor approval) and review this? BifurcationKit.jl#345 builds its continuation corrector on |
This branch has not been deployed
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
Three extensions of the adaptive Jacobian reuse from #1072, each opt-in, defaults unchanged.
JacobianReuseon a matrix-free Jacobian is kept when the linear solver builds a preconditioner;NonlinearSolveBaseLinearSolveExtupdates the operator withreinit!(lincache; A, reuse_precs = true). The size-based default and matrix-free solves withoutprecsstay off (the concern in JacobianReuse default should key off Jacobian cost, not length(u0) #1216).reinit!(cache, u0; reuse_jacobian = true)(2e443be) carries the Jacobian across a sequence of related solves (continuation correctors, parameter sweeps). The existing stale-Jacobian retry still refreshes when the carried one fails.QuasiNewtonCache.reinit_self!zeroed the step counter and discarded the Broyden-updated Jacobian, inverse orLimitedMemoryBroydenhistory; with the keyword it is kept and the method's own reset rules decide refreshes.Evidence
N = 1500 nonlinear BVP, GMRES with a dense-LU preconditioner, one solve, same Newton steps:
JacobianReuse()JacobianReuse(max_residual_ratio = 1)Same problem, 21 continuation steps, one
reinit!per step, same 66 Newton steps:reinit!defaultreuse_jacobian = truemax_age = 50, max_residual_ratio = 1,reuse_jacobian = trueQuasi-Newton, 21-step continuation, N = 800,
Broyden(init_jacobian = Val(:true_jacobian)):reuse_jacobian = falsereuse_jacobian = trueTests:
lib/NonlinearSolveFirstOrder/test/misc_tests__item9.jl(matrix-free keeps precs; no-precs and auto stay off; carried Jacobian acrossreinit!; retry when the line search rejects it; a 21-step sequence) andlib/NonlinearSolveQuasiNewton/test/core_tests__item14.jl(Broyden good/bad, true Jacobian, Klement,LimitedMemoryBroyden, in-place and out-of-place; a forced refresh re-evaluates; no carry before any step). NonlinearSolveBase Core and NonlinearSolveQuasiNewton Core pass. FirstOrder Core has 21 EnzymeThunkCallErrors in the TrustRegion OOP-SVector rootfind tests, identical on the base commit 06b1229.Not covered:
Broyden(update_rule = Val(:diagonal)), which does not converge on the test problem with or without the keyword.Merge Danger
Door: two-way
Blast Radius: opt-in
Every change is behind an explicit
JacobianReusepolicy orreuse_jacobian = true; the defaults take the old paths.