dragonfly_sim.utils.Nonlinear_utils
Classes
Nonlinear problem class for solving the non-linear problem |
|
Full-space Newton on PETSc SNES, driving a NonlinearProblem_mod. |
Module Contents
- class dragonfly_sim.utils.Nonlinear_utils.NonlinearProblem_mod(F: ufl.form.Form, J: ufl.form.Form, u: dolfinx.fem.function.Function, bcs: List[dolfinx.fem.bcs.DirichletBC] = [], form_compiler_options={}, jit_options={}, mat_type: str = None)
Nonlinear problem class for solving the non-linear problem \(F(u, v) = 0 \ \forall v \in V\) using PETSc as the linear algebra backend.
Copied from DOLFINx’s built-in NonlinearProblem and extended with a caller-selectable Jacobian matrix type (mat_type, e.g. “baij” for point-block ILU).
- F(x: petsc4py.PETSc.Vec, b: petsc4py.PETSc.Vec)
Assemble the residual F into the vector b.
- Args:
x: The vector containing the latest solution b: Vector to assemble the residual into
- J(x: petsc4py.PETSc.Vec, A: petsc4py.PETSc.Mat)
Assemble the Jacobian matrix.
- Args:
x: The vector containing the latest solution A: The matrix that will hold the Jacobian matrix
- form(x: petsc4py.PETSc.Vec)
This function is called before the residual or Jacobian is computed. This is usually used to update ghost values.
- Args:
x: The vector containing the latest solution
- property L: dolfinx.fem.forms.Form
Compiled linear form (the residual form)
- _A
- _L
- _a
- _b
- property a: dolfinx.fem.forms.Form
Compiled bilinear form (the Jacobian form)
- bcs = []
- mat_type = None
- u
- class dragonfly_sim.utils.Nonlinear_utils.SNESNewtonSolver(comm: mpi4py.MPI.Intracomm, problem: NonlinearProblem_mod, options_prefix: str = 'nls_solve_')
Full-space Newton on PETSc SNES, driving a NonlinearProblem_mod.
Replaces NewtonSolver_mod, which subclassed dolfinx’s C++ NewtonSolver – deprecated since dolfinx 0.10 and slated for removal. The attribute surface is the old one (rtol, atol, max_it, convergence_criterion, relaxation_parameter, error_on_nonconvergence, krylov_solver, A, b, solve(u) -> (n, converged)), and the defaults below reproduce the old solver step for step rather than adopting SNES’s own behaviour:
newtonls with the BASIC line search, so every step is taken in full, as NewtonSolver did. SNES’s default (bt) would evaluate the residual at extra trial points, and could shorten a step the old solver took in full.
dolfinx’s convergence test, not SNES’s: “incremental” judges ||dx_k|| against ||dx_1|| and never stops on the first step; “residual” judges ||F|| against ||F_0||. ||dx|| is the RAW Newton step, recorded before the step limiter rescales it.
a KSP that fails to converge does not stop the solve. NewtonSolver took the step regardless; SNES by default aborts with DIVERGED_LINEAR_SOLVE before taking any step (checked on this build).
the step limiter (set_step_limiter) replaces set_update. It runs as the line search’s pre-check and rescales dx IN PLACE; the basic line search then lands on x - dx, the same step the old x.axpy(-theta, dx) took.
Checked against NewtonSolver_mod on a nonlinear Poisson problem with Dirichlet BCs (1 and 3 ranks; both criteria, relaxation, a step limiter, max_it=1, a KSP capped short of convergence): iteration counts and converged flags identical, iterates equal to round-off (<= 4.4e-16). Not bit-identical: the Krylov solve itself differs in the last bit, from identical residual, settings and iteration count.
The Jacobian is assembled straight into problem._A, which is also the KSP’s operator. NewtonSolver_mod kept a second full-size matrix and copied problem._A into it every iteration.
The SNES iterate is its own vector, not u’s: the forms read u, and SNES evaluates the residual at a line-search work vector, so F and J copy their argument into u (owned entries, then a forward ghost update) before assembling. Handing SNES u’s vector instead would let that copy overwrite the iterate mid-line-search under any line search other than basic.
SNES options use the prefix nls_solve_, which the KSP inherits – the prefix the C++ NewtonSolver gave its KSP, so every -nls_solve_* option set by apply_krylov_solver_settings (or on the command line) still lands.
- _converged(snes, it, norms)
- _jacobian(snes, x, A, P)
- _precheck(x, dx)
- _residual(snes, x, b)
- _sync(x)
- destroy()
Free the SNES and this solver’s two vectors. The Jacobian belongs to the problem and is left alone.
- set_step_limiter(limiter)
Install limiter(solver, x, dx), called once per Newton step with the current iterate x and the Newton step dx (the solve of J dx = F). It must rescale dx IN PLACE to the step it wants taken: the new iterate is x - dx. It must not modify x. Replaces relaxation_parameter when set.
- solve(u: dolfinx.fem.function.Function)
Solve the non-linear problem into function u. Returns the number of Newton iterations and whether the solver converged.
- property A: petsc4py.PETSc.Mat
Jacobian matrix (the problem’s own, not a copy).
- _dx_norm = None
- _f
- _problem
- _residual0 = None
- _snes
- _step_limiter = None
- _x
- atol = 1e-10
- property b: petsc4py.PETSc.Vec
Residual vector.
- comm
- convergence_criterion = 'residual'
- error_on_nonconvergence = True
- property krylov_solver: petsc4py.PETSc.KSP
The Newton step’s linear solver.
- max_it = 50
- relaxation_parameter = 1.0
- rtol = 1e-09
- property snes: petsc4py.PETSc.SNES