Stationary Solvers

This section describes how to solve stationary (time-independent) PDEs using the high-level API provided by this package. Both monolithic (single system) and block-iterative (subproblem) approaches are supported. For time-dependent problems, there is an extra section.

Meshes and FESpaces

To solve a ProblemDescription, you must provide discretization information:

  • Mesh: The computational domain, represented as an ExtendableGrid. See ExtendableGrids.jl for details and grid constructors. For simplex grids, see SimplexGridFactory.jl. Gmsh mesh import is also supported.

  • Finite Element Spaces: For each unknown, specify a finite element space (FESpace) that defines the ansatz functions. Construct with:

    julia FESpace{FEType}(grid::ExtendableGrid) where FEType is the finite element type. See the list of available FETypes in the ExtendableFEMBase.jl documentation.

Monolithic Solve

To solve a problem, call solve with a ProblemDescription and an array of FESpaces (one per unknown). The solver automatically detects whether the problem is linear or nonlinear and chooses the appropriate algorithm (direct solve or fixed-point iteration/Newton's method). The nonlinear residual is reduced to the prescribed tolerance.

CommonSolve.solveFunction
solve(
    PD::ProblemDescription,
    FES::Dict{<:Unknown};
    ...
) -> Any
solve(
    PD::ProblemDescription,
    FES::Dict{<:Unknown},
    SC;
    unknowns,
    kwargs...
) -> Any

Solve a PDE problem described by a ProblemDescription using the provided finite element spaces and solver configuration.

Arguments

  • PD::ProblemDescription: The problem description, including operators, unknowns, and boundary conditions.
  • FES::Union{<:FESpace, Vector{<:FESpace}, Dict{<:Unknown}}: The finite element space(s) for discretizing the unknowns. Can be a single space, a vector of spaces (one per unknown), or a dictionary mapping unknowns to spaces.
  • SC: (optional) Solver configuration. If not provided, a new configuration is created.
  • unknowns: (optional) Vector of unknowns to solve for (default: PD.unknowns).
  • kwargs...: Additional keyword arguments for solver configuration and algorithmic options (see below).

Keyword Arguments

  • abstol: abstol for linear solver (if iterative). Default: 1.0e-11

  • check_matrix: check matrix for symmetry and positive definiteness and largest/smallest eigenvalues. Default: false

  • constant_matrix: matrix is constant (skips reassembly and refactorization in solver). Default: false

  • constant_rhs: right-hand side is constant (skips reassembly). Default: false

  • damping: amount of damping, value should be between in (0,1). Default: 0

  • inactive: inactive unknowns (are made available in assembly, but not updated in solve). Default: ExtendableFEM.Unknown[]

  • init: initial solution (also used to save the new solution). Default: nothing

  • initialized: linear system in solver configuration is already assembled (turns true after first solve). Default: false

  • is_linear: linear problem (avoid reassembly of nonlinear operators to check residual). Default: ''auto''

  • maxiterations: maximal number of nonlinear iterations/linear solves. Default: 10

  • method_linear: any solver or custom LinearSolveFunction compatible with LinearSolve.jl (default = UMFPACKFactorization()). Default: LinearSolve.UMFPACKFactorization(true, true)

  • plot: plot all solved unknowns with a (very rough but fast) unicode plot. Default: false

  • precon_linear: function that computes preconditioner for method_linear in case an iterative solver is chosen. Default: nothing

  • reltol: reltol for linear solver (if iterative). Default: 1.0e-11

  • restrict_dofs: array of dofs for each unknown that should be solved (default: all dofs). Default: Any[]

  • return_config: solver returns solver configuration (including A and b of last iteration). Default: false

  • show_config: show configuration at the beginning of solve. Default: false

  • show_matrix: show system matrix after assembly. Default: false

  • spy: show unicode spy plot of system matrix during solve. Default: false

  • symmetrize: make system matrix symmetric (replace by (A+A')/2). Default: false

  • symmetrize_structure: make the system sparse matrix structurally symmetric (e.g. if [j,k] is also [k,j] must be set, all diagonal entries must be set). Default: false

  • target_residual: stop if the absolute (nonlinear) residual is smaller than this number. Default: 1.0e-10

  • time: current time to be used in all time-dependent operators. Default: 0.0

  • timeroutputs: configures show of timeroutputs (choose between :hide, :full, :compact). Default: full

  • verbosity: verbosity level. Default: 0

Returns

  • The solution as an FEVector (or a tuple (sol, SC) if return_config=true).

Notes

  • The function automatically detects and handles linear and nonlinear problems depending on the operator definitions and runs a fixed-point iteration if necessary.
  • See the iterate_until_stationarity function for non-monolithic problems.
  • This method extends the CommonSolve.solve interface, where ProblemDescription acts as the problem type and FES as the solver type.
source
Note

The type of fixed-point algorithm depends on how nonlinearities are assembled. If all are assembled as NonlinearOperator, a Newton scheme is used (customizable via keyword arguments like damping). If nonlinearities are linearized by LinearOperator and BilinearOperator, other fixed-point iterations are used.

Block-Iterative Solve (Subproblem Iteration)

For problems that can be solved by iterating over subproblems, configure each subproblem separately with a ProblemDescription/SolverConfiguration. This allows different tolerances and keyword arguments for each subproblem.

Construct a SolverConfiguration with:

ExtendableFEM.SolverConfigurationType
SolverConfiguration(
    Problem::ProblemDescription;
    init,
    unknowns,
    kwargs...
)

Construct a SolverConfiguration for a given problem and set of finite element spaces.

A SolverConfiguration bundles all data and options needed to assemble and solve a finite element system for a given ProblemDescription. It stores the system matrix, right-hand side, solution vector, solver parameters, and bookkeeping for unknowns and degrees of freedom.

Arguments

  • Problem::ProblemDescription: The problem to be solved, including operators, unknowns, and boundary conditions.
  • FES::Union{<:FESpace, Vector{<:FESpace}}: The finite element space(s) for the unknowns. Can be a single space or a vector of spaces (one per unknown).
  • unknowns::Vector{Unknown}: (optional) The unknowns to be solved for (default: Problem.unknowns).
  • init: (optional) Initial FEVector for the solution. If provided, the finite element spaces are inferred from it.
  • kwargs...: Additional keyword arguments to set solver parameters (see below).

Keyword Arguments

  • abstol: abstol for linear solver (if iterative). Default: 1.0e-11

  • check_matrix: check matrix for symmetry and positive definiteness and largest/smallest eigenvalues. Default: false

  • constant_matrix: matrix is constant (skips reassembly and refactorization in solver). Default: false

  • constant_rhs: right-hand side is constant (skips reassembly). Default: false

  • damping: amount of damping, value should be between in (0,1). Default: 0

  • inactive: inactive unknowns (are made available in assembly, but not updated in solve). Default: ExtendableFEM.Unknown[]

  • init: initial solution (also used to save the new solution). Default: nothing

  • initialized: linear system in solver configuration is already assembled (turns true after first solve). Default: false

  • is_linear: linear problem (avoid reassembly of nonlinear operators to check residual). Default: ''auto''

  • maxiterations: maximal number of nonlinear iterations/linear solves. Default: 10

  • method_linear: any solver or custom LinearSolveFunction compatible with LinearSolve.jl (default = UMFPACKFactorization()). Default: LinearSolve.UMFPACKFactorization(true, true)

  • plot: plot all solved unknowns with a (very rough but fast) unicode plot. Default: false

  • precon_linear: function that computes preconditioner for method_linear in case an iterative solver is chosen. Default: nothing

  • reltol: reltol for linear solver (if iterative). Default: 1.0e-11

  • restrict_dofs: array of dofs for each unknown that should be solved (default: all dofs). Default: Any[]

  • return_config: solver returns solver configuration (including A and b of last iteration). Default: false

  • show_config: show configuration at the beginning of solve. Default: false

  • show_matrix: show system matrix after assembly. Default: false

  • spy: show unicode spy plot of system matrix during solve. Default: false

  • symmetrize: make system matrix symmetric (replace by (A+A')/2). Default: false

  • symmetrize_structure: make the system sparse matrix structurally symmetric (e.g. if [j,k] is also [k,j] must be set, all diagonal entries must be set). Default: false

  • target_residual: stop if the absolute (nonlinear) residual is smaller than this number. Default: 1.0e-10

  • time: current time to be used in all time-dependent operators. Default: 0.0

  • timeroutputs: configures show of timeroutputs (choose between :hide, :full, :compact). Default: full

  • verbosity: verbosity level. Default: 0

Returns

  • A SolverConfiguration instance, ready to be passed to the solve function.

Notes

  • If init is provided, the finite element spaces are inferred from it and the solution vector is initialized accordingly.
  • The constructor checks that the number of unknowns matches the number of finite element spaces and that all unknowns are present in the problem description.
  • The configuration includes storage for the system matrix, right-hand side, solution, temporary solution, residual, and solver statistics.
source

Trigger the fixed-point iteration over subproblems with:

ExtendableFEM.iterate_until_stationarityFunction
iterate_until_stationarity(
    SCs::Vector{<:SolverConfiguration};
    ...
)
iterate_until_stationarity(
    SCs::Vector{<:SolverConfiguration},
    FES;
    maxsteps,
    energy_integrator,
    init,
    unknowns,
    kwargs...
) -> Tuple{FEVector{Float64, _A, _B, Vector{Float64}} where {_A, _B}, Int64}

Iteratively solve coupled problems (i.e. an array of SolverConfigurations/ProblemDescriptions with intersecting unknowns) by iterating between them. Iteration continues until the residuals of all subproblems fall below their specified tolerances, or until maxsteps is reached.

Arguments

  • SCs::Vector{<:SolverConfiguration}: Array of solver configurations, one for each subproblem. Each must contain its own ProblemDescription.
  • FES: (optional) Nested vector of finite element spaces for all subproblems and unknowns. If not provided, must be inferred from init.
  • maxsteps::Int: Maximum number of outer iterations (default: 1000).
  • energy_integrator: (optional) Function or object to evaluate an energy or error after each iteration (for diagnostics).
  • init: (optional) Initial FEVector containing all unknowns for all subproblems. Required if FES is not provided.
  • unknowns: (optional) List of unknowns for each subproblem (default: [SC.PD.unknowns for SC in SCs]).
  • kwargs...: Additional keyword arguments passed to each subproblem's solver.

Returns

  • sol: The final solution vector containing all unknowns.
  • it: The number of outer iterations performed.

Notes

  • Each subproblem is solved in sequence within each outer iteration, using its own configuration and options.´
  • If energy_integrator is provided, its value is printed after each iteration for monitoring convergence.
  • This function is intended for non-monolithic (partitioned) solution strategies; for monolithic problems with a single ProblemDescription, see solve.
source