From cda28889a65f91bc21b47f953ffe9e667de5144f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sat, 20 Apr 2024 23:45:37 +0000 Subject: [PATCH] build based on c5c84f2 --- dev/.documenter-siteinfo.json | 2 +- dev/examples/plasticity.ipynb | 760 +++++++++--------- .../plasticity/{1305ef47.svg => 77172aa1.svg} | 380 ++++----- dev/examples/plasticity/index.html | 4 +- dev/examples/transient_heat/index.html | 2 +- dev/index.html | 2 +- dev/linearsolvers/index.html | 2 +- dev/nlsolvers/index.html | 6 +- dev/solvers/index.html | 2 +- dev/timesteppers/index.html | 6 +- dev/userfunctions/index.html | 2 +- 11 files changed, 584 insertions(+), 584 deletions(-) rename dev/examples/plasticity/{1305ef47.svg => 77172aa1.svg} (79%) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index abaa7e7..2b7ac10 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-20T23:37:42","documenter_version":"1.4.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-20T23:45:30","documenter_version":"1.4.0"}} \ No newline at end of file diff --git a/dev/examples/plasticity.ipynb b/dev/examples/plasticity.ipynb index 452bbc8..bd3c760 100644 --- a/dev/examples/plasticity.ipynb +++ b/dev/examples/plasticity.ipynb @@ -426,413 +426,413 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" ], "image/svg+xml": [ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" ] }, "metadata": {}, diff --git a/dev/examples/plasticity/1305ef47.svg b/dev/examples/plasticity/77172aa1.svg similarity index 79% rename from dev/examples/plasticity/1305ef47.svg rename to dev/examples/plasticity/77172aa1.svg index 7e10eb5..cf2ec23 100644 --- a/dev/examples/plasticity/1305ef47.svg +++ b/dev/examples/plasticity/77172aa1.svg @@ -1,204 +1,204 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/examples/plasticity/index.html b/dev/examples/plasticity/index.html index a558ab2..efd34e7 100644 --- a/dev/examples/plasticity/index.html +++ b/dev/examples/plasticity/index.html @@ -148,7 +148,7 @@ plot!(;legend=:bottomright) end; -example_solution()Example block output

Plain program

Here follows a version of the program without any comments. The file is also available here: plasticity.jl.

using FESolvers, Ferrite, Tensors, SparseArrays, LinearAlgebra, Plots
+example_solution()
Example block output

Plain program

Here follows a version of the program without any comments. The file is also available here: plasticity.jl.

using FESolvers, Ferrite, Tensors, SparseArrays, LinearAlgebra, Plots
 
 include("plasticity_definitions.jl");
 
@@ -329,4 +329,4 @@
 
 example_solution()
 
-# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl

This page was generated using Literate.jl.

+# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl

This page was generated using Literate.jl.

diff --git a/dev/examples/transient_heat/index.html b/dev/examples/transient_heat/index.html index 1f356ef..176d48b 100644 --- a/dev/examples/transient_heat/index.html +++ b/dev/examples/transient_heat/index.html @@ -305,4 +305,4 @@ solve_problem!(problem, solver); -# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl

This page was generated using Literate.jl.

+# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl

This page was generated using Literate.jl.

diff --git a/dev/index.html b/dev/index.html index 81cf529..6229947 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · FESolvers.jl
+Home · FESolvers.jl
diff --git a/dev/linearsolvers/index.html b/dev/linearsolvers/index.html index 897c20a..5500d6b 100644 --- a/dev/linearsolvers/index.html +++ b/dev/linearsolvers/index.html @@ -1,2 +1,2 @@ -Linear solvers · FESolvers.jl

Linear solvers

FESolvers.LinearSolveSolverType
LinearSolveSolver([alg], K, r=zeros(eltype(K), size(K,1)))

Create a linear solver with an algorithm alg from LinearSolve.jl. Please see LinearSolve.jl's documentation for different solver algorithms. If not given, LinearSolve's default algorithm will be used.

Extension

Using this solver requires using or importing LinearSolve.jl

source

Custom linear solver

A linear solver should support the solve_linear! function specified below.

FESolvers.solve_linear!Function
solve_linear!(Δx, K, r, linearsolver)

Using the method specified by linearsolver, solve K Δx = -r for Δx

source
+Linear solvers · FESolvers.jl

Linear solvers

FESolvers.LinearSolveSolverType
LinearSolveSolver([alg], K, r=zeros(eltype(K), size(K,1)))

Create a linear solver with an algorithm alg from LinearSolve.jl. Please see LinearSolve.jl's documentation for different solver algorithms. If not given, LinearSolve's default algorithm will be used.

Extension

Using this solver requires using or importing LinearSolve.jl

source

Custom linear solver

A linear solver should support the solve_linear! function specified below.

FESolvers.solve_linear!Function
solve_linear!(Δx, K, r, linearsolver)

Using the method specified by linearsolver, solve K Δx = -r for Δx

source
diff --git a/dev/nlsolvers/index.html b/dev/nlsolvers/index.html index 4666bdd..a746609 100644 --- a/dev/nlsolvers/index.html +++ b/dev/nlsolvers/index.html @@ -2,9 +2,9 @@ Nonlinear solvers · FESolvers.jl

Nonlinear solvers

FESolvers.NewtonSolverType
NewtonSolver(;
     linsolver=BackslashSolver(), linesearch=NoLineSearch(), 
     maxiter=10, tolerance=1.e-6,
-    update_jac_first=true, update_jac_each=true)

Use the standard Newton-Raphson solver to solve the nonlinear problem r(x) = 0 with tolerance within the maximum number of iterations maxiter.

Quasi-Newton methods

Linesearch: The linsolver argument determines the used linear solver whereas the linesearch can be set currently between NoLineSearch or ArmijoGoldstein. The latter globalizes the Newton strategy.

**Jacobian updates: ** The keyword update_jac_first decides if the jacobian from the previously converged time step should be updated after calling update_to_next_step!, or to use the old. Setting update_jac_each implies that the jacobian will not be updated during the iterations. If both update_jac_each and update_jac_first are false, the initial jacobian will be used throughout. Note that these keywords require that the problem respects the update_jacobian keyword given to update_problem!. For time-independent problems or time-depdent problems with constant time steps, update_jac_first=false is often a good choice. However, for time-dependent problems with changing time step length, the standard solver (default), may work better.

source
FESolvers.AdaptiveNewtonSolverType
AdaptiveNewtonSolver(;
+    update_jac_first=true, update_jac_each=true)

Use the standard Newton-Raphson solver to solve the nonlinear problem r(x) = 0 with tolerance within the maximum number of iterations maxiter.

Quasi-Newton methods

Linesearch: The linsolver argument determines the used linear solver whereas the linesearch can be set currently between NoLineSearch or ArmijoGoldstein. The latter globalizes the Newton strategy.

**Jacobian updates: ** The keyword update_jac_first decides if the jacobian from the previously converged time step should be updated after calling update_to_next_step!, or to use the old. Setting update_jac_each implies that the jacobian will not be updated during the iterations. If both update_jac_each and update_jac_first are false, the initial jacobian will be used throughout. Note that these keywords require that the problem respects the update_jacobian keyword given to update_problem!. For time-independent problems or time-depdent problems with constant time steps, update_jac_first=false is often a good choice. However, for time-dependent problems with changing time step length, the standard solver (default), may work better.

source
FESolvers.AdaptiveNewtonSolverType
AdaptiveNewtonSolver(;
     update_types, switch_criterion,
     linsolver=BackslashSolver(), linesearch=NoLineSearch(),
-    maxiter=10, tolerance=1e-6, update_jac_first=true)

Define an adaptive newton solver, where the update type (given to UpdateSpec) changes during the iterations. The different options are given to update_types, and the criterion to switch between them is given to switch_criterion. Remaining options are similar to the standard newton solver.

source
FESolvers.SteepestDescentType
SteepestDescent(;maxiter=10, tolerance=1.e-6)

Use a steepest descent solver to solve the nonlinear problem r(x) = 0, which minimizes a potential $\Pi$ with tolerance and the maximum number of iterations maxiter.

This method is second derivative free and is not as locally limited as a Newton-Raphson scheme. Thus, it is especially suited for strongly nonlinear behavior with potentially vanishing tangent stiffnesses. For this method, it is required to implement getdescentpreconditioner or alternatively getsystemmatrix with SteepestDescent.

source
FESolvers.LinearProblemSolverType
LinearProblemSolver(;linsolver=BackslashSolver())

This is a special type of "Nonlinear solver", which actually only solves linear problems, but allows all other features (i.e. time stepping and postprocessing) of the FESolvers package to be used. In particular, it allows you to maintain all other parts of your problem exactly the same as for a nonlinear problem, but it is possible to get better performance as it is, in principle, not necessary to assemble twice in each time step.

This solver is specialized for linear problems of the form

\[\boldsymbol{r}(\boldsymbol{x}(t),t)=\boldsymbol{K}(t) \boldsymbol{x}(t) - \boldsymbol{f}(t)\]

where $\boldsymbol{K}=\partial \boldsymbol{r}/\partial \boldsymbol{x}$. It expects that $\boldsymbol{x}(t)$ and $\boldsymbol{r}(t)$ have been updated to $\boldsymbol{x}_\mathrm{bc}$ and $\boldsymbol{r}_\mathrm{bc}=\boldsymbol{K}(t)\boldsymbol{x}_\mathrm{bc}-\boldsymbol{f}(t)$, such that

\[\boldsymbol{x}(t) = \boldsymbol{x}_\mathrm{bc} - \boldsymbol{K}^{-1}(t)\boldsymbol{r}_\mathrm{bc} + maxiter=10, tolerance=1e-6, update_jac_first=true)

Define an adaptive newton solver, where the update type (given to UpdateSpec) changes during the iterations. The different options are given to update_types, and the criterion to switch between them is given to switch_criterion. Remaining options are similar to the standard newton solver.

source
FESolvers.SteepestDescentType
SteepestDescent(;maxiter=10, tolerance=1.e-6)

Use a steepest descent solver to solve the nonlinear problem r(x) = 0, which minimizes a potential $\Pi$ with tolerance and the maximum number of iterations maxiter.

This method is second derivative free and is not as locally limited as a Newton-Raphson scheme. Thus, it is especially suited for strongly nonlinear behavior with potentially vanishing tangent stiffnesses. For this method, it is required to implement getdescentpreconditioner or alternatively getsystemmatrix with SteepestDescent.

source
FESolvers.LinearProblemSolverType
LinearProblemSolver(;linsolver=BackslashSolver())

This is a special type of "Nonlinear solver", which actually only solves linear problems, but allows all other features (i.e. time stepping and postprocessing) of the FESolvers package to be used. In particular, it allows you to maintain all other parts of your problem exactly the same as for a nonlinear problem, but it is possible to get better performance as it is, in principle, not necessary to assemble twice in each time step.

This solver is specialized for linear problems of the form

\[\boldsymbol{r}(\boldsymbol{x}(t),t)=\boldsymbol{K}(t) \boldsymbol{x}(t) - \boldsymbol{f}(t)\]

where $\boldsymbol{K}=\partial \boldsymbol{r}/\partial \boldsymbol{x}$. It expects that $\boldsymbol{x}(t)$ and $\boldsymbol{r}(t)$ have been updated to $\boldsymbol{x}_\mathrm{bc}$ and $\boldsymbol{r}_\mathrm{bc}=\boldsymbol{K}(t)\boldsymbol{x}_\mathrm{bc}-\boldsymbol{f}(t)$, such that

\[\boldsymbol{x}(t) = \boldsymbol{x}_\mathrm{bc} - \boldsymbol{K}^{-1}(t)\boldsymbol{r}_\mathrm{bc} = \boldsymbol{x}_\mathrm{bc} - \boldsymbol{K}^{-1}(t)\left[\boldsymbol{K}(t)\boldsymbol{x}_\mathrm{bc}-\boldsymbol{f}(t)\right] -= \boldsymbol{K}^{-1}(t)\boldsymbol{f}(t)\]

is the solution to the current time step. This normally implies when using Ferrite the same procedure as for nonlinear problems, i.e. that the boundary conditions are applied in update_to_next_step! and update_problem!, as well as the calculation of the residual according to above and that apply_zero!(K,r,ch) is called (on both the residual and the stiffness matrix).

If you have strange results when running the LinearProblemSolver, please ensure that the problem converges in one iteration for the NewtonSolver

source
FESolvers.DynamicSolverType
DynamicSolver(nlsolver, updater)

DynamicSolver contains a base nlsolver that must support set_update_type! such that the value of type in UpdateSpec can be changed dynamically. This is typically used to change regularization factors for the jacobian calculation. updater should be a function with the signature type, reset, finished = updater(nlsolver, num_attempts), where type is given to UpdateSpec in nlsolver, reset says if the problem should be reset, and finished tells if this is the last update that can be done (and if not converged then, it will fail). The inputs are the current nlsolver as well as the number of attempts.

source

Further details on selected solvers

AdaptiveNewtonSolver

For the adaptive newton solver, a few basic switchers have been implemented.

FESolvers.ToleranceSwitchType
ToleranceSwitch(;switch_at)

Use update_types[1] when the convergence measure is larger than switch_at. When the convergence measure is below switch_at, use update_types[2]. If the convergence measure increases above switch_at again, reset the problem and change to update_types[1] iterations with update_types[1].

source
FESolvers.IncreaseSwitchType
IncreaseSwitch(;num_slow)

Use the (typically) fast but less stable update_types[1] as long as the convergence measure is decreasing. If it starts increasing, switch to the (typically) slower but more stable update_types[2]. Use this for num_slow iterations after the convergence measure starts to decrease again.

source

To implement a custom switcher for AdaptiveNewtonSolver, define a new struct and the function switch_information for that struct:

FESolvers.switch_informationFunction
switch_information(switch_criterion, nlsolver)

Create a custom switch_criterion by overloading this function, which given the defined switch_criterion and the nlsolver, should return reset_problem::Bool and new_nr::Int, which determines if the problem should be reset to the state before its last update and which update_type should be used next, respectively.

source

Problem update specification

An UpdateSpec, which can be querried for information, is passed to update_problem! to give instructions on how to update the problem.

FESolvers.UpdateSpecType
UpdateSpec(;jacobian, residual, type=nothing)

An UpdateSpec is sent to update_problem! to pass the problem information about how it should be updated. The following methods should be used by the problem to request information

  • should_update_jacobian(::UpdateSpec)::Bool: Self explanatory
  • should_update_residual(::UpdateSpec)::Bool: Self explanatory
  • get_update_type(::UpdateSpec): How should the problem be updated? This is used by special solvers where, for example, different approximations of the stiffness is available, see e.g. AdaptiveNewtonSolver
source

Custom solvers

A custom nonlinear solver can be written by tapping into the existing functions at different levels. For example, LinearProblemSolver defines a custom solve_nonlinear! that uses the default calculate_update!.

All nonlinear solvers are expected to implement the following methods,

FESolvers.get_solver_stateFunction
get_solver_state(nlsolver)

All nonlinear solvers that contain a SolverState should normally overload this function to make many other functions work automatically.

source
FESolvers.reset_solver_state!Function
reset_solver_state!(nlsolver)

Called at the beginning of each new time step, and resets the solver's status and potentially convergence history etc.

source

get_solver_state

If get_solver_state is not implemented, the following methods must be implemented instead

FESolvers.get_convergence_measureFunction
get_convergence_measure(nlsolver)

Get the last convergence measure for nlsolver.

get_convergence_measure(nlsolver, k::Integer)

Get the kth convergence measure in the current iteration

get_convergence_measure(nlsolver, inds)

Get a view to the vector of the convergence measures for iterations inds, i.e. view(residuals, inds)

get_convergence_measure(nlsolver, ::Colon)

Get a view to the vector of all convergence measures, i.e. get_convergence_measure(nlsolver, 1:get_num_iter(nlsolver))

source

Methods required by solve_nonlinear!

After implementing the methods above, one can either implement solve_nonlinear!, or a set of method described below to use the default implementation.

FESolvers.solve_nonlinear!Function
solve_nonlinear!(problem, nlsolver, last_converged)

Solve the current time step in the nonlinear problem, (r(x) = 0), by using the nonlinear solver nlsolver. last_converged::Bool is just for information if the last time step converged or not. In many cases it suffices to overload calculate_update! for a custom nonlinear solver.

source

To use the default implementation of solve_nonlinear!, calculate_update! and the other methods in the list below must be implemented for the specific nonlinear solver. The default implementation of calculate_update! may be used as well, see the description below.

FESolvers.calculate_update!Function
function calculate_update!(Δx, problem, nlsolver)

According to the nonlinear solver, nlsolver, at iteration iter, calculate the update, Δx to the unknowns x.

source
FESolvers.get_update_specFunction
get_update_spec(nlsolver)::UpdateSpec

Get the update specification during regular iterations. It is the nlsolver's job to keep track of any state required for deciding changes to the update specification during iterations.

source
FESolvers.should_reset_problemFunction
should_reset_problem(nlsolver)

Note: Custom nonlinear solvers may rely on the default false return value.

If this function returns true, the problem will be reset as update_problem!(problem, -Δa) to reset the problem to the state at the last iteration (e.g. when switching the jacobian calculation)

source

Methods required by calculate_update!

To support the default calculate_update! implementation, the following methods must be implemented for the given solver.

Additional methods that usually don't require specialization

FESolvers.should_do_initial_updateFunction
should_do_initial_update(nlsolver)

Should the problem be updated initially, before starting time stepping? Normally, not required to overload as the update specification from get_initial_update_spec is used to decide how if an update is required.

source
FESolvers.reset_problem!Function
reset_problem!(problem, nlsolver; x, Δx_old)

Reset the problem, either by giving the new vector of unknown values, x, or the last increment to be reset, Δx_old. x will not be modified if given, but Δx_old will be modified to -Δx_old if given.

source

Linesearch

Some nonlinear solvers can use linesearch as a complement, and the following linesearches are included.

FESolvers.ArmijoGoldsteinType
Armijo-Goldstein{T}(;β=0.9,μ=0.01,τ0=1.0,τmin=1e-4)

Backtracking line search based on the Armijo-Goldstein condition

\[\Pi(\boldsymbol{u} + \tau \Delta\boldsymbol{u}) \leq \Pi(\boldsymbol{u}) - \mu\tau\delta\Pi(\boldsymbol{u})[\Delta \boldsymbol{u}]\]

where $\Pi$ is the potential, $\tau$ the stepsize, and $\delta\Pi$ the residuum.

#Fields

  • β::T = 0.9 constant factor that changes the steplength τ in each iteration
  • μ::T = 0.01 second constant factor that determines how much the potential needs to decrease additionally
  • τ0::T = 1.0 start stepsize
  • τmin::T = 1e-4 minimal stepsize
source

Custom linesearch

A custom linesearch should implement the following function

FESolvers.linesearch!Function
linesearch!(Δx, problem, ls::AbstractLineSearch)

Search along Δx to find the minimum of the potential. Return the modified Δx.

source
+= \boldsymbol{K}^{-1}(t)\boldsymbol{f}(t)\]

is the solution to the current time step. This normally implies when using Ferrite the same procedure as for nonlinear problems, i.e. that the boundary conditions are applied in update_to_next_step! and update_problem!, as well as the calculation of the residual according to above and that apply_zero!(K,r,ch) is called (on both the residual and the stiffness matrix).

If you have strange results when running the LinearProblemSolver, please ensure that the problem converges in one iteration for the NewtonSolver

source
FESolvers.DynamicSolverType
DynamicSolver(nlsolver, updater)

DynamicSolver contains a base nlsolver that must support set_update_type! such that the value of type in UpdateSpec can be changed dynamically. This is typically used to change regularization factors for the jacobian calculation. updater should be a function with the signature type, reset, finished = updater(nlsolver, num_attempts), where type is given to UpdateSpec in nlsolver, reset says if the problem should be reset, and finished tells if this is the last update that can be done (and if not converged then, it will fail). The inputs are the current nlsolver as well as the number of attempts.

source

Further details on selected solvers

AdaptiveNewtonSolver

For the adaptive newton solver, a few basic switchers have been implemented.

FESolvers.ToleranceSwitchType
ToleranceSwitch(;switch_at)

Use update_types[1] when the convergence measure is larger than switch_at. When the convergence measure is below switch_at, use update_types[2]. If the convergence measure increases above switch_at again, reset the problem and change to update_types[1] iterations with update_types[1].

source
FESolvers.IncreaseSwitchType
IncreaseSwitch(;num_slow)

Use the (typically) fast but less stable update_types[1] as long as the convergence measure is decreasing. If it starts increasing, switch to the (typically) slower but more stable update_types[2]. Use this for num_slow iterations after the convergence measure starts to decrease again.

source

To implement a custom switcher for AdaptiveNewtonSolver, define a new struct and the function switch_information for that struct:

FESolvers.switch_informationFunction
switch_information(switch_criterion, nlsolver)

Create a custom switch_criterion by overloading this function, which given the defined switch_criterion and the nlsolver, should return reset_problem::Bool and new_nr::Int, which determines if the problem should be reset to the state before its last update and which update_type should be used next, respectively.

source

Problem update specification

An UpdateSpec, which can be querried for information, is passed to update_problem! to give instructions on how to update the problem.

FESolvers.UpdateSpecType
UpdateSpec(;jacobian, residual, type=nothing)

An UpdateSpec is sent to update_problem! to pass the problem information about how it should be updated. The following methods should be used by the problem to request information

  • should_update_jacobian(::UpdateSpec)::Bool: Self explanatory
  • should_update_residual(::UpdateSpec)::Bool: Self explanatory
  • get_update_type(::UpdateSpec): How should the problem be updated? This is used by special solvers where, for example, different approximations of the stiffness is available, see e.g. AdaptiveNewtonSolver
source

Custom solvers

A custom nonlinear solver can be written by tapping into the existing functions at different levels. For example, LinearProblemSolver defines a custom solve_nonlinear! that uses the default calculate_update!.

All nonlinear solvers are expected to implement the following methods,

FESolvers.get_solver_stateFunction
get_solver_state(nlsolver)

All nonlinear solvers that contain a SolverState should normally overload this function to make many other functions work automatically.

source
FESolvers.reset_solver_state!Function
reset_solver_state!(nlsolver)

Called at the beginning of each new time step, and resets the solver's status and potentially convergence history etc.

source

get_solver_state

If get_solver_state is not implemented, the following methods must be implemented instead

FESolvers.get_convergence_measureFunction
get_convergence_measure(nlsolver)

Get the last convergence measure for nlsolver.

get_convergence_measure(nlsolver, k::Integer)

Get the kth convergence measure in the current iteration

get_convergence_measure(nlsolver, inds)

Get a view to the vector of the convergence measures for iterations inds, i.e. view(residuals, inds)

get_convergence_measure(nlsolver, ::Colon)

Get a view to the vector of all convergence measures, i.e. get_convergence_measure(nlsolver, 1:get_num_iter(nlsolver))

source

Methods required by solve_nonlinear!

After implementing the methods above, one can either implement solve_nonlinear!, or a set of method described below to use the default implementation.

FESolvers.solve_nonlinear!Function
solve_nonlinear!(problem, nlsolver, last_converged)

Solve the current time step in the nonlinear problem, (r(x) = 0), by using the nonlinear solver nlsolver. last_converged::Bool is just for information if the last time step converged or not. In many cases it suffices to overload calculate_update! for a custom nonlinear solver.

source

To use the default implementation of solve_nonlinear!, calculate_update! and the other methods in the list below must be implemented for the specific nonlinear solver. The default implementation of calculate_update! may be used as well, see the description below.

FESolvers.calculate_update!Function
function calculate_update!(Δx, problem, nlsolver)

According to the nonlinear solver, nlsolver, at iteration iter, calculate the update, Δx to the unknowns x.

source
FESolvers.get_update_specFunction
get_update_spec(nlsolver)::UpdateSpec

Get the update specification during regular iterations. It is the nlsolver's job to keep track of any state required for deciding changes to the update specification during iterations.

source
FESolvers.should_reset_problemFunction
should_reset_problem(nlsolver)

Note: Custom nonlinear solvers may rely on the default false return value.

If this function returns true, the problem will be reset as update_problem!(problem, -Δa) to reset the problem to the state at the last iteration (e.g. when switching the jacobian calculation)

source

Methods required by calculate_update!

To support the default calculate_update! implementation, the following methods must be implemented for the given solver.

Additional methods that usually don't require specialization

FESolvers.should_do_initial_updateFunction
should_do_initial_update(nlsolver)

Should the problem be updated initially, before starting time stepping? Normally, not required to overload as the update specification from get_initial_update_spec is used to decide how if an update is required.

source
FESolvers.reset_problem!Function
reset_problem!(problem, nlsolver; x, Δx_old)

Reset the problem, either by giving the new vector of unknown values, x, or the last increment to be reset, Δx_old. x will not be modified if given, but Δx_old will be modified to -Δx_old if given.

source

Linesearch

Some nonlinear solvers can use linesearch as a complement, and the following linesearches are included.

FESolvers.ArmijoGoldsteinType
Armijo-Goldstein{T}(;β=0.9,μ=0.01,τ0=1.0,τmin=1e-4)

Backtracking line search based on the Armijo-Goldstein condition

\[\Pi(\boldsymbol{u} + \tau \Delta\boldsymbol{u}) \leq \Pi(\boldsymbol{u}) - \mu\tau\delta\Pi(\boldsymbol{u})[\Delta \boldsymbol{u}]\]

where $\Pi$ is the potential, $\tau$ the stepsize, and $\delta\Pi$ the residuum.

#Fields

  • β::T = 0.9 constant factor that changes the steplength τ in each iteration
  • μ::T = 0.01 second constant factor that determines how much the potential needs to decrease additionally
  • τ0::T = 1.0 start stepsize
  • τmin::T = 1e-4 minimal stepsize
source

Custom linesearch

A custom linesearch should implement the following function

FESolvers.linesearch!Function
linesearch!(Δx, problem, ls::AbstractLineSearch)

Search along Δx to find the minimum of the potential. Return the modified Δx.

source
diff --git a/dev/solvers/index.html b/dev/solvers/index.html index 8f92c0c..a93bd30 100644 --- a/dev/solvers/index.html +++ b/dev/solvers/index.html @@ -1,2 +1,2 @@ -Solvers · FESolvers.jl
+Solvers · FESolvers.jl
diff --git a/dev/timesteppers/index.html b/dev/timesteppers/index.html index aa07a12..a41efb6 100644 --- a/dev/timesteppers/index.html +++ b/dev/timesteppers/index.html @@ -1,7 +1,7 @@ Time steppers · FESolvers.jl

Time steppers

The following time steppers are implemented in FESolvers.

FESolvers.FixedTimeStepperType
FixedTimeStepper(;num_steps::Int, Δt=1, t_start=0)
-FixedTimeStepper(t::Vector)

A time stepper which gives fixed time steps. If the convenience interface is used, constant increments are used. Note that length(t)=num_steps+1 since the first value is just the initial value and is not an actual step.

source
FESolvers.AdaptiveTimeStepperType
AdaptiveTimeStepper(
+FixedTimeStepper(t::Vector)

A time stepper which gives fixed time steps. If the convenience interface is used, constant increments are used. Note that length(t)=num_steps+1 since the first value is just the initial value and is not an actual step.

source
FESolvers.AdaptiveTimeStepperType
AdaptiveTimeStepper(
     Δt_init::T, t_end::T; 
     t_start=zero(T), Δt_min=Δt_init, Δt_max=typemax(T), 
-    change_factor=T(0.5), optiter_ratio=T(0.5), k=one(T)) where T

An adaptive time stepper with an initial step Δt_init and total time t_end. Two ways of adaption:

  1. If the previous attempt did not converge, the time

step is reduced as Δt*=change_factor and the step is retried.

  1. If convergence, the next time step depends on how many iterations was

required to converge; numiter. The time step is changed as Δt*=change_factor^(k*m), where m=(numiter-optiter)/(maxiter-optiter). In this expression, maxiter and optiter are the maximum and optimum number of iterations for the nonlinear solver. optiter=floor(maxiter*optiter_ratio) and maxiter is obtained from the nonlinear solver (via get_max_iter(s))

If numiter=maxiter, then m=1 and the time step update is the same as for a non-converged solution if k=1. Note that k>0, change_factor∈[0,1], and optiter_ratio∈[0,1] are expected, otherwise warnings are thrown.

source

Custom time stepper

A time stepper should support the following functions

FESolvers.is_last_stepFunction
is_last_step(timestepper)->Bool

Return true if the current step/time is the last step, return false otherwise

source
FESolvers.step_time!Function
step_time!(solver)
-step_time!(timestepper, nlsolver)

Increment the timestepper depending on the convergence status of nlsolver. If not converged and a smaller time step is not possible, throw ConvergenceError.

Note that a call to the first definition is forwarded to the second function definition by decomposing the solver, unless another specialization is defined.

source
+ change_factor=T(0.5), optiter_ratio=T(0.5), k=one(T)) where T

An adaptive time stepper with an initial step Δt_init and total time t_end. Two ways of adaption:

  1. If the previous attempt did not converge, the time

step is reduced as Δt*=change_factor and the step is retried.

  1. If convergence, the next time step depends on how many iterations was

required to converge; numiter. The time step is changed as Δt*=change_factor^(k*m), where m=(numiter-optiter)/(maxiter-optiter). In this expression, maxiter and optiter are the maximum and optimum number of iterations for the nonlinear solver. optiter=floor(maxiter*optiter_ratio) and maxiter is obtained from the nonlinear solver (via get_max_iter(s))

If numiter=maxiter, then m=1 and the time step update is the same as for a non-converged solution if k=1. Note that k>0, change_factor∈[0,1], and optiter_ratio∈[0,1] are expected, otherwise warnings are thrown.

source

Custom time stepper

A time stepper should support the following functions

FESolvers.is_last_stepFunction
is_last_step(timestepper)->Bool

Return true if the current step/time is the last step, return false otherwise

source
FESolvers.step_time!Function
step_time!(solver)
+step_time!(timestepper, nlsolver)

Increment the timestepper depending on the convergence status of nlsolver. If not converged and a smaller time step is not possible, throw ConvergenceError.

Note that a call to the first definition is forwarded to the second function definition by decomposing the solver, unless another specialization is defined.

source
diff --git a/dev/userfunctions/index.html b/dev/userfunctions/index.html index 60ce869..9956034 100644 --- a/dev/userfunctions/index.html +++ b/dev/userfunctions/index.html @@ -1,2 +1,2 @@ -User problem · FESolvers.jl

User problem

The key to using the FESolvers.jl package is to define your problem. This problem should support a set of functions in order for the solver to solve your problem. While some functions are always required, some are only required by certain solvers. Furthermore, a two-level API exist: Simple and advanced. The simple API does not expose which solver is used, while the advanced API requires you to dispatch on the type of solver.

Applicable to all solvers

FESolvers.update_to_next_step!Function
update_to_next_step!(problem, time)

Update prescribed values, external loads etc. for the given time.

This function is called in the beginning of each new time step. Note that for adaptive time stepping, it may be called with a lower time than the previous time if the solution did not converge.

source
FESolvers.update_problem!Function
update_problem!(problem, Δx, update_spec::UpdateSpec)

Update the unknowns of the problem by Δx according to update_spec. Note that

  • Some linear solvers may be inaccurate, and if a modified stiffness is used to enforce constraints on x, it is good the force Δx=0 on these components inside this function.
  • Δx=nothing in the first call after update_to_next_step! in which case, typically, no change of x should be made. Dirichlet boundary conditions are typically updated in update_to_next_step!.

The update_spec gives the information about what and how to update. See the documentation for UpdateSpec for further details. This feature is used by some nonlinear solvers to customize the iteration strategy to speed up or aid convergence. For basic cases when getting started, this can be ignored and a simple function definition would be

FESolvers.update_problem!(problem, Δx, _)
update_problem!(problem, Δx; update_residual::Bool, update_jacobian::Bool)

The old but now deprecated interface is still available without update_spec. The instructions are here:

  • Assemble the residual if update_residual=true
  • Assemble the jacobian if update_jacobian=true
source
FESolvers.handle_converged!Function
handle_converged!(problem)

Do necessary update operations once it is known that the problem has converged. E.g., update old values to the current. Only called after the problem has converged, after postprocess!

source
FESolvers.handle_notconverged!Function
handle_notconverged!(problem, solver)

Optional function to make changes to the problem in case it did not converge. If not implemented, this defaults to a no-op.

source
FESolvers.postprocess!Function
postprocess!(problem, solver)

Perform any postprocessing at the current time. Called at the beginning of the simulation, and directly after time step converged (right before handle_converged!).

source
FESolvers.close_problemFunction
close_problem(problem)

This function is called after solving the problem, even if the solution fails due to an error thrown, for example if the problem doesn't converge. Use to close any file streams etc. that are open and should be closed

source

Simple API

FESolvers.calculate_convergence_measureFunction
calculate_convergence_measure(problem, Δa, iter) -> AbstractFloat

Calculate a value to be compared with the tolerance of the nonlinear solver. A standard case when using Ferrite.jl is norm(getresidual(problem)[Ferrite.free_dofs(ch)]) where ch::Ferrite.ConstraintHandler. Δa is the update of the unknowns from the previous iteration. Note that iter=1 implies Δa=0

source
FESolvers.getjacobianFunction

getjacobian(problem)

Return the jacobian drdx, or approximations thereof.

Must be defined for NewtonSolver, but can also be defined by the advanced API alternative getsystemmatrix: getsystemmatrix(problem, ::NewtonSolver)

source
FESolvers.getdescentpreconditionerFunction

getdescentpreconditioner(problem)

Return a preconditioner K for calculating the descent direction p, considering solving r(x)=0 as a minimization problem of f(x) where r=∇f. The descent direction is then p = K⁻¹ ∇f

Used by the SteepestDescent solver, and defaults to I if not defined. The advanced API alternative is getsystemmatrix: getsystemmatrix(problem, ::SteepestDescent)

source
FESolvers.calculate_energyFunction
calculate_energy(problem,𝐮)

Return the energy of the system (a scalar) which is the integrated energy density over the domain Ω.

source

Advanced API

FESolvers.getsystemmatrixFunction
getsystemmatrix(problem,nlsolver)

Return the system matrix of the problem. For a Newton solver this method should return the Jacobian, while for a steepest descent method this can be a preconditioner as e.g., the L2 product of the gradients. By default the system matrix for the SteepestDescent method is the unity matrix and thus, renders a vanilla gradient descent solver.

source

Additional functions

These functions are usually not necessary to overload

FESolvers.setunknowns!Function
setunknowns!(problem, x)

Copy the given values x into the unknown values of problem. Defaults to copy!(getunknowns(problem), x), which works as long as getunknowns returns the Vector{<:Number} stored in the problem struct. If, e.g. the unknowns is a custom type or a nested vector, this function should be overloaded.

source
+User problem · FESolvers.jl

User problem

The key to using the FESolvers.jl package is to define your problem. This problem should support a set of functions in order for the solver to solve your problem. While some functions are always required, some are only required by certain solvers. Furthermore, a two-level API exist: Simple and advanced. The simple API does not expose which solver is used, while the advanced API requires you to dispatch on the type of solver.

Applicable to all solvers

FESolvers.update_to_next_step!Function
update_to_next_step!(problem, time)

Update prescribed values, external loads etc. for the given time.

This function is called in the beginning of each new time step. Note that for adaptive time stepping, it may be called with a lower time than the previous time if the solution did not converge.

source
FESolvers.update_problem!Function
update_problem!(problem, Δx, update_spec::UpdateSpec)

Update the unknowns of the problem by Δx according to update_spec. Note that

  • Some linear solvers may be inaccurate, and if a modified stiffness is used to enforce constraints on x, it is good the force Δx=0 on these components inside this function.
  • Δx=nothing in the first call after update_to_next_step! in which case, typically, no change of x should be made. Dirichlet boundary conditions are typically updated in update_to_next_step!.

The update_spec gives the information about what and how to update. See the documentation for UpdateSpec for further details. This feature is used by some nonlinear solvers to customize the iteration strategy to speed up or aid convergence. For basic cases when getting started, this can be ignored and a simple function definition would be

FESolvers.update_problem!(problem, Δx, _)
update_problem!(problem, Δx; update_residual::Bool, update_jacobian::Bool)

The old but now deprecated interface is still available without update_spec. The instructions are here:

  • Assemble the residual if update_residual=true
  • Assemble the jacobian if update_jacobian=true
source
FESolvers.handle_converged!Function
handle_converged!(problem)

Do necessary update operations once it is known that the problem has converged. E.g., update old values to the current. Only called after the problem has converged, after postprocess!

source
FESolvers.handle_notconverged!Function
handle_notconverged!(problem, solver)

Optional function to make changes to the problem in case it did not converge. If not implemented, this defaults to a no-op.

source
FESolvers.postprocess!Function
postprocess!(problem, solver)

Perform any postprocessing at the current time. Called at the beginning of the simulation, and directly after time step converged (right before handle_converged!).

source
FESolvers.close_problemFunction
close_problem(problem)

This function is called after solving the problem, even if the solution fails due to an error thrown, for example if the problem doesn't converge. Use to close any file streams etc. that are open and should be closed

source

Simple API

FESolvers.calculate_convergence_measureFunction
calculate_convergence_measure(problem, Δa, iter) -> AbstractFloat

Calculate a value to be compared with the tolerance of the nonlinear solver. A standard case when using Ferrite.jl is norm(getresidual(problem)[Ferrite.free_dofs(ch)]) where ch::Ferrite.ConstraintHandler. Δa is the update of the unknowns from the previous iteration. Note that iter=1 implies Δa=0

source
FESolvers.getjacobianFunction

getjacobian(problem)

Return the jacobian drdx, or approximations thereof.

Must be defined for NewtonSolver, but can also be defined by the advanced API alternative getsystemmatrix: getsystemmatrix(problem, ::NewtonSolver)

source
FESolvers.getdescentpreconditionerFunction

getdescentpreconditioner(problem)

Return a preconditioner K for calculating the descent direction p, considering solving r(x)=0 as a minimization problem of f(x) where r=∇f. The descent direction is then p = K⁻¹ ∇f

Used by the SteepestDescent solver, and defaults to I if not defined. The advanced API alternative is getsystemmatrix: getsystemmatrix(problem, ::SteepestDescent)

source
FESolvers.calculate_energyFunction
calculate_energy(problem,𝐮)

Return the energy of the system (a scalar) which is the integrated energy density over the domain Ω.

source

Advanced API

FESolvers.getsystemmatrixFunction
getsystemmatrix(problem,nlsolver)

Return the system matrix of the problem. For a Newton solver this method should return the Jacobian, while for a steepest descent method this can be a preconditioner as e.g., the L2 product of the gradients. By default the system matrix for the SteepestDescent method is the unity matrix and thus, renders a vanilla gradient descent solver.

source

Additional functions

These functions are usually not necessary to overload

FESolvers.setunknowns!Function
setunknowns!(problem, x)

Copy the given values x into the unknown values of problem. Defaults to copy!(getunknowns(problem), x), which works as long as getunknowns returns the Vector{<:Number} stored in the problem struct. If, e.g. the unknowns is a custom type or a nested vector, this function should be overloaded.

source