diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index b73ab508c..34b2d0f02 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2023-12-18T21:02:20","documenter_version":"1.2.1"}} \ No newline at end of file +{"documenter":{"julia_version":"1.9.4","generation_timestamp":"2023-12-19T13:33:48","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/dev/assets/Manifest.toml b/dev/assets/Manifest.toml index f967ff9e2..5222b169b 100644 --- a/dev/assets/Manifest.toml +++ b/dev/assets/Manifest.toml @@ -249,9 +249,9 @@ version = "6.144.0" [[deps.DiffEqCallbacks]] deps = ["DataStructures", "DiffEqBase", "ForwardDiff", "Functors", "LinearAlgebra", "Markdown", "NLsolve", "Parameters", "RecipesBase", "RecursiveArrayTools", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "d0b94b3694d55e7eedeee918e7daee9e3b873399" +git-tree-sha1 = "e48b985459d1cbe8c809de192529f1e25c3382a6" uuid = "459566f4-90b8-5000-8ac3-15dfb0a30def" -version = "2.35.0" +version = "2.36.0" [deps.DiffEqCallbacks.weakdeps] OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" @@ -699,9 +699,9 @@ uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearSolve]] deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "Requires", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "03cd36673f050ec49f9bdfce31e0e7e22d877e64" +git-tree-sha1 = "b1148a6596c5cd9b2d848c26b500c79d102ffc5d" uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "2.21.0" +version = "2.21.1" [deps.LinearSolve.extensions] LinearSolveBandedMatricesExt = "BandedMatrices" diff --git a/dev/fundamentals/FAQ/index.html b/dev/fundamentals/FAQ/index.html index 065cddb2d..ecefd1004 100644 --- a/dev/fundamentals/FAQ/index.html +++ b/dev/fundamentals/FAQ/index.html @@ -1,2 +1,2 @@ -Frequently Asked Questions · SciMLBase.jl

Frequently Asked Questions

What are the code styling rules for SciML?

All SciML libraries are supposed to follow SciMLStyle. Any deviation from that style is something to be fixed.

Where do I find more information on the internals of some packages?

The SciML Developer Documentation describes the internals of some of the larger solver libraries at length.

What are the community practices that SciML developers should use?

See ColPrac: Contributor's Guide on Collaborative Practices for Community Packages

Are there developer programs to help fund parties interested in helping develop SciML?

Yes! See the SciML Developer Programs webpage.

+Frequently Asked Questions · SciMLBase.jl

Frequently Asked Questions

What are the code styling rules for SciML?

All SciML libraries are supposed to follow SciMLStyle. Any deviation from that style is something to be fixed.

Where do I find more information on the internals of some packages?

The SciML Developer Documentation describes the internals of some of the larger solver libraries at length.

What are the community practices that SciML developers should use?

See ColPrac: Contributor's Guide on Collaborative Practices for Community Packages

Are there developer programs to help fund parties interested in helping develop SciML?

Yes! See the SciML Developer Programs webpage.

diff --git a/dev/index.html b/dev/index.html index 812bc5775..26b1b3619 100644 --- a/dev/index.html +++ b/dev/index.html @@ -42,7 +42,7 @@ [864edb3b] DataStructures v0.18.15 [e2d170a0] DataValueInterfaces v1.0.0 [2b5f629d] DiffEqBase v6.144.0 - [459566f4] DiffEqCallbacks v2.35.0 + [459566f4] DiffEqCallbacks v2.36.0 [163ba53b] DiffResults v1.1.0 [b552c78f] DiffRules v1.15.1 [b4f34e82] Distances v0.10.11 @@ -66,7 +66,7 @@ [069b7b12] FunctionWrappers v1.1.3 [77dc65aa] FunctionWrappersWrappers v0.1.3 [d9f16b24] Functors v0.4.5 - [46192b85] GPUArraysCore v0.1.5 +⌃ [46192b85] GPUArraysCore v0.1.5 [c145ed77] GenericSchur v0.5.3 [d7ba0133] Git v1.3.0 [c27321d9] Glob v1.3.1 @@ -97,7 +97,7 @@ [50d2b5c4] Lazy v0.15.1 [5078a376] LazyArrays v1.8.3 [d3d80556] LineSearches v7.2.0 - [7ed4a6bd] LinearSolve v2.21.0 + [7ed4a6bd] LinearSolve v2.21.1 [2ab3a3ac] LogExpFunctions v0.3.26 [bdcacae8] LoopVectorization v0.12.166 [d8e11817] MLStyle v0.4.17 @@ -235,4 +235,4 @@ [8e850b90] libblastrampoline_jll v5.8.0+0 [8e850ede] nghttp2_jll v1.52.0+1 [3f19e933] p7zip_jll v17.4.0+0 -Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated -m`

You can also download the manifest file and the project file.

+Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated -m`

You can also download the manifest file and the project file.

diff --git a/dev/interfaces/Algorithms/index.html b/dev/interfaces/Algorithms/index.html index 7083eaee6..6c7e6048e 100644 --- a/dev/interfaces/Algorithms/index.html +++ b/dev/interfaces/Algorithms/index.html @@ -1,2 +1,2 @@ -SciMLAlgorithms · SciMLBase.jl

SciMLAlgorithms

Definition of the AbstractSciMLAlgorithm Interface

SciMLAlgorithms are defined as types which have dispatches to the function signature:

CommonSolve.solve(prob::AbstractSciMLProblem,alg::AbstractSciMLAlgorithm;kwargs...)

Algorithm-Specific Arguments

Note that because the keyword arguments of solve are designed to be common across the whole problem type, algorithms should have the algorithm-specific keyword arguments defined as part of the algorithm constructor. For example, Rodas5 has a choice of autodiff::Bool which is not common across all ODE solvers, and thus autodiff is a algorithm-specific keyword argument handled via Rodas5(autodiff=true).

Remake

Note that remake is applicable to AbstractSciMLAlgorithm types, but this is not used in the public API. It's used for solvers to swap out components like ForwardDiff chunk sizes.

Common Algorithm Keyword Arguments

Commonly used algorithm keyword arguments are:

Traits

SciMLBase.isautodifferentiableFunction

isautodifferentiable(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with direct automatic differentiation, i.e. can have algorithms like ForwardDiff or ReverseDiff attempt to differentiate directly through the solver.

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.allows_arbitrary_number_typesFunction

allowsarbitrarynumber_types(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with direct automatic differentiation, i.e. can have algorithms like ForwardDiff or ReverseDiff attempt to differentiate directly through the solver.

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.allowscomplexFunction

allowscomplex(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with having complex numbers as the state variables.

Defaults to false.

source
SciMLBase.isadaptiveFunction

isadaptive(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses adaptivity, i.e. has a non-quasi-static compute graph.

Defaults to true.

source
is_integrator_adaptive(i::DEIntegrator)

Checks if the integrator is adaptive

source
SciMLBase.isdiscreteFunction

isdiscrete(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm allows for discrete state values, such as integers.

Defaults to false.

source
SciMLBase.forwarddiffs_modelFunction

forwarddiffs_model(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses ForwardDiff.jl on the model function is called with ForwardDiff.jl

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.forwarddiffs_model_timeFunction

forwarddiffsmodeltime(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses ForwardDiff.jl on the model f(u,p,t) function is called with ForwardDiff.jl on the t argument.

Defaults to false as only a few pure-Julia algorithms (Rosenbrock methods) have this as true

source

Abstract SciML Algorithms

+SciMLAlgorithms · SciMLBase.jl

SciMLAlgorithms

Definition of the AbstractSciMLAlgorithm Interface

SciMLAlgorithms are defined as types which have dispatches to the function signature:

CommonSolve.solve(prob::AbstractSciMLProblem,alg::AbstractSciMLAlgorithm;kwargs...)

Algorithm-Specific Arguments

Note that because the keyword arguments of solve are designed to be common across the whole problem type, algorithms should have the algorithm-specific keyword arguments defined as part of the algorithm constructor. For example, Rodas5 has a choice of autodiff::Bool which is not common across all ODE solvers, and thus autodiff is a algorithm-specific keyword argument handled via Rodas5(autodiff=true).

Remake

Note that remake is applicable to AbstractSciMLAlgorithm types, but this is not used in the public API. It's used for solvers to swap out components like ForwardDiff chunk sizes.

Common Algorithm Keyword Arguments

Commonly used algorithm keyword arguments are:

Traits

SciMLBase.isautodifferentiableFunction

isautodifferentiable(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with direct automatic differentiation, i.e. can have algorithms like ForwardDiff or ReverseDiff attempt to differentiate directly through the solver.

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.allows_arbitrary_number_typesFunction

allowsarbitrarynumber_types(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with direct automatic differentiation, i.e. can have algorithms like ForwardDiff or ReverseDiff attempt to differentiate directly through the solver.

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.allowscomplexFunction

allowscomplex(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm is compatible with having complex numbers as the state variables.

Defaults to false.

source
SciMLBase.isadaptiveFunction

isadaptive(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses adaptivity, i.e. has a non-quasi-static compute graph.

Defaults to true.

source
is_integrator_adaptive(i::DEIntegrator)

Checks if the integrator is adaptive

source
SciMLBase.isdiscreteFunction

isdiscrete(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm allows for discrete state values, such as integers.

Defaults to false.

source
SciMLBase.forwarddiffs_modelFunction

forwarddiffs_model(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses ForwardDiff.jl on the model function is called with ForwardDiff.jl

Defaults to false as only pure-Julia algorithms can have this be true.

source
SciMLBase.forwarddiffs_model_timeFunction

forwarddiffsmodeltime(alg::AbstractDEAlgorithm)

Trait declaration for whether an algorithm uses ForwardDiff.jl on the model f(u,p,t) function is called with ForwardDiff.jl on the t argument.

Defaults to false as only a few pure-Julia algorithms (Rosenbrock methods) have this as true

source

Abstract SciML Algorithms

diff --git a/dev/interfaces/Array_and_Number/index.html b/dev/interfaces/Array_and_Number/index.html index 4082736f7..6d759d175 100644 --- a/dev/interfaces/Array_and_Number/index.html +++ b/dev/interfaces/Array_and_Number/index.html @@ -1,2 +1,2 @@ -SciML Container (Array) and Number Interfaces · SciMLBase.jl

SciML Container (Array) and Number Interfaces

We live in a society, and therefore there are rules. In this tutorial we outline the rules which are required on container and number types which are allowable in SciML tools.

Warn

In general as of 2023, strict adherence to this interface is an early work-in-progress. If anything does not conform to the documented interface, please open an issue.

Note

There are many types which can work with a specific solver that do satisfy this interface. Many times as part of prototyping you may want to side-step the high level interface checks in order to simply test whether a new type is working. To do this, set interface_checks = false as a keyword argument to init/solve to bypass any of the internal interface checks. This means you will no longer get a nice high-level error message and instead it will attempt to use the type without restrictions. Note that not every problem/solver has implemented this new keyword argument as of 2023.

Note About Wrapped Solvers

Due to limitations of wrapped solvers, any solver that is a wrapped solver from an existing C/Fortran code is inherently limited to Float64 and Vector{Float64} for its operations. This includes packages like Sundials.jl, LSODA.jl, DASKR.jl, MINPACK.jl, and many more. This is fundamental to these solvers and it is not expected that they will allow the full set of SciML types in the future. If more abstract number/container definitions are required, then these are not the appropriate solvers to use.

SciML Number Types

The number types are the types used to define the dependent variables (i.e. u0) and the independent variables (t or tspan). These two types can be different, and can have different restrictions depending on the type of solver which is employed. The following rules for a Number type are held in general:

  • Number types can be used in SciML directly or in containers. If a problem defines a value like u0 using a Number type, the out-of-place form must be used for the problem definition.
  • x::T + y::T = z::T
  • x::T * y::T = z::T
  • oneunit(x::T)::T
  • one(x::T) * oneunit(x::T) = z::T
  • t::T2 * x::T + y::T = z::T for T2 a time type and T the dependent variable type (this includes the muladd equivalent form).

Additionally, the following rules apply to subsets of uses:

Adaptive Number Types

  • x::T / y::T = z::T
  • Default choices of norms can assume sqrt(x::T)::T exists. If internalnorm is overridden then this may not be required (for example, changing the norm to inf-norm).
  • x::T ^ y::T = z::T

Time Types (Independent Variables)

  • If a solver is time adaptive, the time type must be a floating point number. Rational is only allowed for non-adaptive solves.

SciML Container (Array) Types

Container types are types which hold number types. They can be used to define objects like the state vector (u0) of a problem. The following operations are required in a container type to be used with SciML solvers:

Note

"eltype(x::T)::T2 is a compatible Number type" excludes Array{Array{T}} types of types. However, recursive vectors can conformed to the interface with zero overhead using tools from RecursiveArrayTools.jl such as VectorOfArray(x). Since this greatly simplifies the interfaces and the ability to check for correctness, doing this wrapping is highly recommended and there are no plans to relax this requirement.

Additionally, the following rules apply to subsets of uses:

SciML Mutable Array Types

  • similar(x::T)::T
  • zero(x::T)::T
  • z::T .= x::T .+ y::T is defined
  • z::T .= x::T .* y::T is defined
  • z::T .= t::T2 .* x::T where T2 is the time type (a Number) and T is the container type.
  • (Optional) Base.resize!(x,i) is required for resize!(integrator,i) to be supported.

SciML Matrix (Operator) Type

Note that the matrix type may not match the type of the initial container u0. An example is ComponentMatrix as the matrix structure corresponding to a ComponentArray. However, the following actions are assumed to hold on the resulting matrix type:

  • solve(LinearProblem(A::T,b::T2),linsolve) must be defined for a solver to work on a given SciML matrix type T2.
  • If the matrix is an operator, i.e. a lazy construct, it should conform to the SciMLOperators interface.
  • If not a SciMLOperator, diagind(W::T) should be defined and @view(A[idxs])=@view(A[idxs]) + λ::T
+SciML Container (Array) and Number Interfaces · SciMLBase.jl

SciML Container (Array) and Number Interfaces

We live in a society, and therefore there are rules. In this tutorial we outline the rules which are required on container and number types which are allowable in SciML tools.

Warn

In general as of 2023, strict adherence to this interface is an early work-in-progress. If anything does not conform to the documented interface, please open an issue.

Note

There are many types which can work with a specific solver that do satisfy this interface. Many times as part of prototyping you may want to side-step the high level interface checks in order to simply test whether a new type is working. To do this, set interface_checks = false as a keyword argument to init/solve to bypass any of the internal interface checks. This means you will no longer get a nice high-level error message and instead it will attempt to use the type without restrictions. Note that not every problem/solver has implemented this new keyword argument as of 2023.

Note About Wrapped Solvers

Due to limitations of wrapped solvers, any solver that is a wrapped solver from an existing C/Fortran code is inherently limited to Float64 and Vector{Float64} for its operations. This includes packages like Sundials.jl, LSODA.jl, DASKR.jl, MINPACK.jl, and many more. This is fundamental to these solvers and it is not expected that they will allow the full set of SciML types in the future. If more abstract number/container definitions are required, then these are not the appropriate solvers to use.

SciML Number Types

The number types are the types used to define the dependent variables (i.e. u0) and the independent variables (t or tspan). These two types can be different, and can have different restrictions depending on the type of solver which is employed. The following rules for a Number type are held in general:

  • Number types can be used in SciML directly or in containers. If a problem defines a value like u0 using a Number type, the out-of-place form must be used for the problem definition.
  • x::T + y::T = z::T
  • x::T * y::T = z::T
  • oneunit(x::T)::T
  • one(x::T) * oneunit(x::T) = z::T
  • t::T2 * x::T + y::T = z::T for T2 a time type and T the dependent variable type (this includes the muladd equivalent form).

Additionally, the following rules apply to subsets of uses:

Adaptive Number Types

  • x::T / y::T = z::T
  • Default choices of norms can assume sqrt(x::T)::T exists. If internalnorm is overridden then this may not be required (for example, changing the norm to inf-norm).
  • x::T ^ y::T = z::T

Time Types (Independent Variables)

  • If a solver is time adaptive, the time type must be a floating point number. Rational is only allowed for non-adaptive solves.

SciML Container (Array) Types

Container types are types which hold number types. They can be used to define objects like the state vector (u0) of a problem. The following operations are required in a container type to be used with SciML solvers:

Note

"eltype(x::T)::T2 is a compatible Number type" excludes Array{Array{T}} types of types. However, recursive vectors can conformed to the interface with zero overhead using tools from RecursiveArrayTools.jl such as VectorOfArray(x). Since this greatly simplifies the interfaces and the ability to check for correctness, doing this wrapping is highly recommended and there are no plans to relax this requirement.

Additionally, the following rules apply to subsets of uses:

SciML Mutable Array Types

  • similar(x::T)::T
  • zero(x::T)::T
  • z::T .= x::T .+ y::T is defined
  • z::T .= x::T .* y::T is defined
  • z::T .= t::T2 .* x::T where T2 is the time type (a Number) and T is the container type.
  • (Optional) Base.resize!(x,i) is required for resize!(integrator,i) to be supported.

SciML Matrix (Operator) Type

Note that the matrix type may not match the type of the initial container u0. An example is ComponentMatrix as the matrix structure corresponding to a ComponentArray. However, the following actions are assumed to hold on the resulting matrix type:

  • solve(LinearProblem(A::T,b::T2),linsolve) must be defined for a solver to work on a given SciML matrix type T2.
  • If the matrix is an operator, i.e. a lazy construct, it should conform to the SciMLOperators interface.
  • If not a SciMLOperator, diagind(W::T) should be defined and @view(A[idxs])=@view(A[idxs]) + λ::T
diff --git a/dev/interfaces/Common_Keywords/index.html b/dev/interfaces/Common_Keywords/index.html index 35284b0ad..f12c390f2 100644 --- a/dev/interfaces/Common_Keywords/index.html +++ b/dev/interfaces/Common_Keywords/index.html @@ -1,2 +1,2 @@ -Common Keyword Arguments · SciMLBase.jl

Common Keyword Arguments

The following defines the keyword arguments which are meant to be preserved throughout all of the AbstractSciMLProblem cases (where applicable).

Default Algorithm Hinting

To help choose the default algorithm, the keyword argument alg_hints is provided to solve. alg_hints is a Vector{Symbol} which describe the problem at a high level to the solver. The options are:

This functionality is derived via the benchmarks in SciMLBenchmarks.jl

Currently this is only implemented for the differential equation solvers.

Output Control

These arguments control the output behavior of the solvers. It defaults to maximum output to give the best interactive user experience, but can be reduced all the way to only saving the solution at the final timepoint.

The following options are all related to output control. See the "Examples" section at the end of this page for some example usage.

  • dense: Denotes whether to save the extra pieces required for dense (continuous) output. Default is save_everystep && !isempty(saveat) for algorithms which have the ability to produce dense output, i.e. by default it's true unless the user has turned off saving on steps or has chosen a saveat value. If dense=false, the solution still acts like a function, and sol(t) is a linear interpolation between the saved time points.
  • saveat: Denotes specific times to save the solution at, during the solving phase. The solver will save at each of the timepoints in this array in the most efficient manner available to the solver. If only saveat is given, then the arguments save_everystep and dense are false by default. If saveat is given a number, then it will automatically expand to tspan[1]:saveat:tspan[2]. For methods where interpolation is not possible, saveat may be equivalent to tstops. The default value is [].
  • save_idxs: Denotes the indices for the components of the equation to save. Defaults to saving all indices. For example, if you are solving a 3-dimensional ODE, and given save_idxs = [1, 3], only the first and third components of the solution will be outputted. Notice that of course in this case the outputted solution will be two-dimensional.
  • tstops: Denotes extra times that the timestepping algorithm must step to. This should be used to help the solver deal with discontinuities and singularities, since stepping exactly at the time of the discontinuity will improve accuracy. If a method cannot change timesteps (fixed timestep multistep methods), then tstops will use an interpolation, matching the behavior of saveat. If a method cannot change timesteps and also cannot interpolate, then tstops must be a multiple of dt or else an error will be thrown. Default is [].
  • d_discontinuities: Denotes locations of discontinuities in low order derivatives. This will force FSAL algorithms which assume derivative continuity to re-evaluate the derivatives at the point of discontinuity. The default is [].
  • save_everystep: Saves the result at every step. Default is true if isempty(saveat).
  • save_on: Denotes whether intermediate solutions are saved. This overrides the settings of dense, saveat and save_everystep and is used by some applications to manually turn off saving temporarily. Everyday use of the solvers should leave this unchanged. Defaults to true.
  • save_start: Denotes whether the initial condition should be included in the solution type as the first timepoint. Defaults to true.
  • save_end: Denotes whether the final timepoint is forced to be saved, regardless of the other saving settings. Defaults to true.
  • initialize_save: Denotes whether to save after the callback initialization phase (when u_modified=true). Defaults to true.

Note that dense requires save_everystep=true and saveat=false.

Stepsize Control

These arguments control the timestepping routines.

Basic Stepsize Control

  • adaptive: Turns on adaptive timestepping for appropriate methods. Default is true.
  • abstol: Absolute tolerance in adaptive timestepping. This is the tolerance on local error estimates, not necessarily the global error (though these quantities are related).
  • reltol: Relative tolerance in adaptive timestepping. This is the tolerance on local error estimates, not necessarily the global error (though these quantities are related).
  • dt: Sets the initial stepsize. This is also the stepsize for fixed timestep methods. Defaults to an automatic choice if the method is adaptive.
  • dtmax: Maximum dt for adaptive timestepping. Defaults are package-dependent.
  • dtmin: Minimum dt for adaptive timestepping. Defaults are package-dependent.

Fixed Stepsize Usage

Note that if a method does not have adaptivity, the following rules apply:

  • If dt is set, then the algorithm will step with size dt each iteration.
  • If tstops and dt are both set, then the algorithm will step with either a size dt, or use a smaller step to hit the tstops point.
  • If tstops is set without dt, then the algorithm will step directly to each value in tstops
  • If neither dt nor tstops are set, the solver will throw an error.

Memory Optimizations

  • alias_u0: allows the solver to alias the initial condition array that is contained in the problem struct. Defaults to false.
  • cache: pass a solver cache to decrease the construction time. This is not implemented for any of the problem interfaces at this moment.

Miscellaneous

  • maxiters: Maximum number of iterations before stopping.
  • callback: Specifies a callback function that is called between iterations.
  • verbose: Toggles whether warnings are thrown when the solver exits early. Defaults to true.

Progress Monitoring

These arguments control the usage of the progressbar in the logger.

  • progress: Turns on/off the Juno progressbar. Default is false.
  • progress_steps: Numbers of steps between updates of the progress bar. Default is 1000.
  • progress_name: Controls the name of the progressbar. Default is the name of the problem type.
  • progress_message: Controls the message with the progressbar. Defaults to showing dt, t, the maximum of u.

The progress bars all use the Julia Logging interface in order to be generic to the IDE or programming tool that is used. For more information on how this is all put together, see this discussion.

Error Calculations

If you are using the test problems (i.e. SciMLFunctions where f.analytic is defined), then options control the errors which are calculated. By default, any cheap error estimates are always calculated. Extra keyword arguments include:

  • timeseries_errors
  • dense_errors

for specifying more expensive errors.

Automatic Differentiation Control

See the Automatic Differentiation page for a full description of sensealg

+Common Keyword Arguments · SciMLBase.jl

Common Keyword Arguments

The following defines the keyword arguments which are meant to be preserved throughout all of the AbstractSciMLProblem cases (where applicable).

Default Algorithm Hinting

To help choose the default algorithm, the keyword argument alg_hints is provided to solve. alg_hints is a Vector{Symbol} which describe the problem at a high level to the solver. The options are:

This functionality is derived via the benchmarks in SciMLBenchmarks.jl

Currently this is only implemented for the differential equation solvers.

Output Control

These arguments control the output behavior of the solvers. It defaults to maximum output to give the best interactive user experience, but can be reduced all the way to only saving the solution at the final timepoint.

The following options are all related to output control. See the "Examples" section at the end of this page for some example usage.

  • dense: Denotes whether to save the extra pieces required for dense (continuous) output. Default is save_everystep && !isempty(saveat) for algorithms which have the ability to produce dense output, i.e. by default it's true unless the user has turned off saving on steps or has chosen a saveat value. If dense=false, the solution still acts like a function, and sol(t) is a linear interpolation between the saved time points.
  • saveat: Denotes specific times to save the solution at, during the solving phase. The solver will save at each of the timepoints in this array in the most efficient manner available to the solver. If only saveat is given, then the arguments save_everystep and dense are false by default. If saveat is given a number, then it will automatically expand to tspan[1]:saveat:tspan[2]. For methods where interpolation is not possible, saveat may be equivalent to tstops. The default value is [].
  • save_idxs: Denotes the indices for the components of the equation to save. Defaults to saving all indices. For example, if you are solving a 3-dimensional ODE, and given save_idxs = [1, 3], only the first and third components of the solution will be outputted. Notice that of course in this case the outputted solution will be two-dimensional.
  • tstops: Denotes extra times that the timestepping algorithm must step to. This should be used to help the solver deal with discontinuities and singularities, since stepping exactly at the time of the discontinuity will improve accuracy. If a method cannot change timesteps (fixed timestep multistep methods), then tstops will use an interpolation, matching the behavior of saveat. If a method cannot change timesteps and also cannot interpolate, then tstops must be a multiple of dt or else an error will be thrown. Default is [].
  • d_discontinuities: Denotes locations of discontinuities in low order derivatives. This will force FSAL algorithms which assume derivative continuity to re-evaluate the derivatives at the point of discontinuity. The default is [].
  • save_everystep: Saves the result at every step. Default is true if isempty(saveat).
  • save_on: Denotes whether intermediate solutions are saved. This overrides the settings of dense, saveat and save_everystep and is used by some applications to manually turn off saving temporarily. Everyday use of the solvers should leave this unchanged. Defaults to true.
  • save_start: Denotes whether the initial condition should be included in the solution type as the first timepoint. Defaults to true.
  • save_end: Denotes whether the final timepoint is forced to be saved, regardless of the other saving settings. Defaults to true.
  • initialize_save: Denotes whether to save after the callback initialization phase (when u_modified=true). Defaults to true.

Note that dense requires save_everystep=true and saveat=false.

Stepsize Control

These arguments control the timestepping routines.

Basic Stepsize Control

  • adaptive: Turns on adaptive timestepping for appropriate methods. Default is true.
  • abstol: Absolute tolerance in adaptive timestepping. This is the tolerance on local error estimates, not necessarily the global error (though these quantities are related).
  • reltol: Relative tolerance in adaptive timestepping. This is the tolerance on local error estimates, not necessarily the global error (though these quantities are related).
  • dt: Sets the initial stepsize. This is also the stepsize for fixed timestep methods. Defaults to an automatic choice if the method is adaptive.
  • dtmax: Maximum dt for adaptive timestepping. Defaults are package-dependent.
  • dtmin: Minimum dt for adaptive timestepping. Defaults are package-dependent.

Fixed Stepsize Usage

Note that if a method does not have adaptivity, the following rules apply:

  • If dt is set, then the algorithm will step with size dt each iteration.
  • If tstops and dt are both set, then the algorithm will step with either a size dt, or use a smaller step to hit the tstops point.
  • If tstops is set without dt, then the algorithm will step directly to each value in tstops
  • If neither dt nor tstops are set, the solver will throw an error.

Memory Optimizations

  • alias_u0: allows the solver to alias the initial condition array that is contained in the problem struct. Defaults to false.
  • cache: pass a solver cache to decrease the construction time. This is not implemented for any of the problem interfaces at this moment.

Miscellaneous

  • maxiters: Maximum number of iterations before stopping.
  • callback: Specifies a callback function that is called between iterations.
  • verbose: Toggles whether warnings are thrown when the solver exits early. Defaults to true.

Progress Monitoring

These arguments control the usage of the progressbar in the logger.

  • progress: Turns on/off the Juno progressbar. Default is false.
  • progress_steps: Numbers of steps between updates of the progress bar. Default is 1000.
  • progress_name: Controls the name of the progressbar. Default is the name of the problem type.
  • progress_message: Controls the message with the progressbar. Defaults to showing dt, t, the maximum of u.

The progress bars all use the Julia Logging interface in order to be generic to the IDE or programming tool that is used. For more information on how this is all put together, see this discussion.

Error Calculations

If you are using the test problems (i.e. SciMLFunctions where f.analytic is defined), then options control the errors which are calculated. By default, any cheap error estimates are always calculated. Extra keyword arguments include:

  • timeseries_errors
  • dense_errors

for specifying more expensive errors.

Automatic Differentiation Control

See the Automatic Differentiation page for a full description of sensealg

diff --git a/dev/interfaces/Differentiation/index.html b/dev/interfaces/Differentiation/index.html index 3d27dfbe8..b93bd3e03 100644 --- a/dev/interfaces/Differentiation/index.html +++ b/dev/interfaces/Differentiation/index.html @@ -25,4 +25,4 @@ function _concrete_solve_forward(args...; kwargs...) error("No sensitivity rules exist. Check that you added `using DiffEqSensitivity`") -end

The sensitivity mechanism is kept in a separate package because of the high dependency and load time cost introduced by the automatic differentiation libraries. Different choices of automatic differentiation are then selected by the sensealg keyword argument in solve, which is made into a positional argument in the _solve_adjoint and other functions in order to allow dispatch.

SensitivityADPassThrough

The special sensitivity algorithm SensitivityADPassThrough is used to ignore the internal sensitivity dispatches and instead do automatic differentiation directly through the solver. Generally this sensealg is only used internally.

Note about ForwardDiff

ForwardDiff does not use ChainRules.jl and thus it completely ignores the special handling.

+end

The sensitivity mechanism is kept in a separate package because of the high dependency and load time cost introduced by the automatic differentiation libraries. Different choices of automatic differentiation are then selected by the sensealg keyword argument in solve, which is made into a positional argument in the _solve_adjoint and other functions in order to allow dispatch.

SensitivityADPassThrough

The special sensitivity algorithm SensitivityADPassThrough is used to ignore the internal sensitivity dispatches and instead do automatic differentiation directly through the solver. Generally this sensealg is only used internally.

Note about ForwardDiff

ForwardDiff does not use ChainRules.jl and thus it completely ignores the special handling.

diff --git a/dev/interfaces/Init_Solve/index.html b/dev/interfaces/Init_Solve/index.html index 509a67131..97d48eadd 100644 --- a/dev/interfaces/Init_Solve/index.html +++ b/dev/interfaces/Init_Solve/index.html @@ -1,3 +1,3 @@ The SciML init and solve Functions · SciMLBase.jl

The SciML init and solve Functions

solve function has the default definition

solve(args...; kwargs...) = solve!(init(args...; kwargs...))

The interface for the three functions is as follows:

init(::ProblemType, args...; kwargs...) :: IteratorType
-solve!(::IteratorType) :: SolutionType

where ProblemType, IteratorType, and SolutionType are the types defined in your package.

To avoid method ambiguity, the first argument of solve, solve!, and init must be dispatched on the type defined in your package. For example, do not define a method such as

init(::AbstractVector, ::AlgorithmType)

init and the Iterator Interface

init's return gives an IteratorType which is designed to allow the user to have more direct handling over the internal solving process. Because of this internal nature, the IteratorType has a less unified interface across problem types than other portions like ProblemType and SolutionType. For example, for differential equations this is the Integrator Interface designed for mutating solutions in a manner for callback implementation, which is distinctly different from the LinearSolve init interface which is designed for caching efficiency with reusing factorizations.

__solve and High-Level Handling

While init and solve are the common entry point for users, solver packages will mostly define dispatches on SciMLBase.__init and SciMLBase.__solve. The reason is because this allows for SciMLBase.init and SciMLBase.solve to have common implementations across all solvers for doing things such as checking for common errors and throwing high level messages. Solvers can opt-out of the high level error handling by directly defining SciMLBase.init and SciMLBase.solve instead, though this is not recommended in order to allow for uniformity of the error messages.

+solve!(::IteratorType) :: SolutionType

where ProblemType, IteratorType, and SolutionType are the types defined in your package.

To avoid method ambiguity, the first argument of solve, solve!, and init must be dispatched on the type defined in your package. For example, do not define a method such as

init(::AbstractVector, ::AlgorithmType)

init and the Iterator Interface

init's return gives an IteratorType which is designed to allow the user to have more direct handling over the internal solving process. Because of this internal nature, the IteratorType has a less unified interface across problem types than other portions like ProblemType and SolutionType. For example, for differential equations this is the Integrator Interface designed for mutating solutions in a manner for callback implementation, which is distinctly different from the LinearSolve init interface which is designed for caching efficiency with reusing factorizations.

__solve and High-Level Handling

While init and solve are the common entry point for users, solver packages will mostly define dispatches on SciMLBase.__init and SciMLBase.__solve. The reason is because this allows for SciMLBase.init and SciMLBase.solve to have common implementations across all solvers for doing things such as checking for common errors and throwing high level messages. Solvers can opt-out of the high level error handling by directly defining SciMLBase.init and SciMLBase.solve instead, though this is not recommended in order to allow for uniformity of the error messages.

diff --git a/dev/interfaces/PDE/index.html b/dev/interfaces/PDE/index.html index d6e92c53e..d620bf880 100644 --- a/dev/interfaces/PDE/index.html +++ b/dev/interfaces/PDE/index.html @@ -23,4 +23,4 @@ @named pde_system = PDESystem(eq,bcs,domains,[t,x],[u])source

Domains (WIP)

Domains are specifying by saying indepvar in domain, where indepvar is a single or a collection of independent variables, and domain is the chosen domain type. A 2-tuple can be used to indicate an Interval. Thus forms for the indepvar can be like:

t ∈ (0.0,1.0)
 (t,x) ∈ UnitDisk()
-[v,w,x,y,z] ∈ VectorUnitBall(5)

Domain Types (WIP)

import from DomainSets.jl, but a 2-tuple can be used instead)

discretize and symbolic_discretize

The only functions which act on a PDESystem are the following:

Boundary Conditions (WIP)

Transformations

Analyses

Discretizer Ecosystem

NeuralPDE.jl: PhysicsInformedNN

NeuralPDE.jl defines the PhysicsInformedNN discretizer which uses a DiffEqFlux.jl neural network to solve the differential equation.

MethodOfLines.jl: MOLFiniteDifference (WIP)

MethodOfLines.jl defines the MOLFiniteDifference discretizer which performs a finite difference discretization using the DiffEqOperators.jl stencils. These stencils make use of NNLib.jl for fast operations on semi-linear domains.

+[v,w,x,y,z] ∈ VectorUnitBall(5)

Domain Types (WIP)

import from DomainSets.jl, but a 2-tuple can be used instead)

discretize and symbolic_discretize

The only functions which act on a PDESystem are the following:

Boundary Conditions (WIP)

Transformations

Analyses

Discretizer Ecosystem

NeuralPDE.jl: PhysicsInformedNN

NeuralPDE.jl defines the PhysicsInformedNN discretizer which uses a DiffEqFlux.jl neural network to solve the differential equation.

MethodOfLines.jl: MOLFiniteDifference (WIP)

MethodOfLines.jl defines the MOLFiniteDifference discretizer which performs a finite difference discretization using the DiffEqOperators.jl stencils. These stencils make use of NNLib.jl for fast operations on semi-linear domains.

diff --git a/dev/interfaces/Problems/index.html b/dev/interfaces/Problems/index.html index cb6ff3d9a..a29bc9868 100644 --- a/dev/interfaces/Problems/index.html +++ b/dev/interfaces/Problems/index.html @@ -1,19 +1,19 @@ SciMLProblems · SciMLBase.jl

SciMLProblems

The cornerstone of the SciML common interface is the problem type definition. These definitions are the encoding of mathematical problems into a numerically computable form.

Note About Symbolics and ModelingToolkit

The symbolic analog to the problem interface is the ModelingToolkit AbstractSystem. For example, ODESystem is the symbolic analog to ODEProblem. Each of these system types have a method for constructing the associated problem and function types.

Definition of the AbstractSciMLProblem Interface

The following standard principles should be adhered to across all AbstractSciMLProblem instantiations.

In-place Specification

Each AbstractSciMLProblem type can be called with an "is inplace" (iip) choice. For example:

ODEProblem(f,u0,tspan,p)
-ODEProblem{iip}(f,u0,tspan,p)

which is a boolean for whether the function is in the inplace form (mutating to change the first value). This is automatically determined using the methods table but note that for full type-inferability of the AbstractSciMLProblem this iip-ness should be specified.

Additionally, the functions are fully specialized to reduce the runtimes. If one would instead like to not specialize on the functions to reduce compile time, then one can set recompile to false.

Specialization Levels

Specialization levels in problem definitions are used to control the amount of compilation specialization is performed on the model functions in order to trade off between runtime performance, simplicity, and compile-time performance. The default choice of specialization is AutoSpecialize, which seeks to allow for using fully precompiled solvers in common scenarios but falls back to a runtime-optimal approach when further customization is used.

Specialization levels are given as the second type parameter in AbstractSciMLProblem constructors. For example, this is done via:

ODEProblem{iip,specialization}(f,u0,tspan,p)

Note that iip choice is required for specialization choices to be made.

Specialization Choices

SciMLBase.AbstractSpecializationType
abstract type AbstractSpecialization

Supertype for the specialization types. Controls the compilation and function specialization behavior of SciMLFunctions, ultimately controlling the runtime vs compile-time trade-off.

source
SciMLBase.AutoSpecializeType
struct AutoSpecialize <: SciMLBase.AbstractSpecialization

The default specialization level for problem functions. AutoSpecialize works by applying a function wrap just-in-time before the solve process to disable just-in-time re-specialization of the solver to the specific choice of model f and thus allow for using a cached solver compilation from a different f. This wrapping process can lead to a small decreased runtime performance with a benefit of a greatly decreased compile-time.

Note About Benchmarking and Runtime Optimality

It is recommended that AutoSpecialize is not used in any benchmarking due to the potential effect of function wrapping on runtimes. AutoSpecialize's use case is targeted at decreased latency for REPL performance and not for cases where where top runtime performance is required (such as in optimization loops). Generally, for non-stiff equations the cost will be minimal and potentially not even measurable. For stiff equations, function wrapping has the limitation that only chunk sized 1 Dual numbers are allowed, which can decrease Jacobian construction performance.

Limitations of AutoSpecialize

The following limitations are not fundamental to the implementation of AutoSpecialize, but are instead chosen as a compromise between default precompilation times and ease of maintenance. Please open an issue to discuss lifting any potential limitations.

  • AutoSpecialize is only setup to wrap the functions from in-place ODEs. Other cases are excluded for the time being due to time limitations.
  • AutoSpecialize will only lead to compilation reuse if the ODEFunction's other functions (such as jac and tgrad) are the default nothing. These could be JIT wrapped as well in a future version.
  • AutoSpecialize'd functions are only compatible with Jacobian calculations performed with chunk size 1, and only with tag DiffEqBase.OrdinaryDiffEqTag(). Thus ODE solvers written on the common interface must be careful to detect the AutoSpecialize case and perform differentiation under these constraints, use finite differencing, or manually unwrap before solving. This will lead to decreased runtime performance for sufficiently large Jacobians.
  • AutoSpecialize only wraps on Julia v1.8 and higher.
  • AutoSpecialize does not handle cases with units. If unitful values are detected, wrapping is automatically disabled.
  • AutoSpecialize only wraps cases for which promote_rule is defined between u0 and dual numbers, u0 and t, and for which ArrayInterface.promote_eltype is defined on u0 to dual numbers.
  • AutoSpecialize only wraps cases for which f.mass_matrix isa UniformScaling, the default.
  • AutoSpecialize does not wrap cases where f isa AbstractSciMLOperator
  • By default, only the u0 isa Vector{Float64}, eltype(tspan) isa Float64, and typeof(p) isa Union{Vector{Float64},SciMLBase.NullParameters} are specialized by the solver libraries. Other forms can be specialized with AutoSpecialize, but must be done in the precompilation of downstream libraries.
  • AutoSpecialized functions are manually unwrapped in adjoint methods in SciMLSensitivity.jl in order to allow compiler support for automatic differentiation. Improved versions of adjoints which decrease the recompilation surface will come in non-breaking updates.

Cases where automatic wrapping is disabled are equivalent to FullSpecialize.

Example

f(du,u,p,t) = (du .= u)
+ODEProblem{iip}(f,u0,tspan,p)

which is a boolean for whether the function is in the inplace form (mutating to change the first value). This is automatically determined using the methods table but note that for full type-inferability of the AbstractSciMLProblem this iip-ness should be specified.

Additionally, the functions are fully specialized to reduce the runtimes. If one would instead like to not specialize on the functions to reduce compile time, then one can set recompile to false.

Specialization Levels

Specialization levels in problem definitions are used to control the amount of compilation specialization is performed on the model functions in order to trade off between runtime performance, simplicity, and compile-time performance. The default choice of specialization is AutoSpecialize, which seeks to allow for using fully precompiled solvers in common scenarios but falls back to a runtime-optimal approach when further customization is used.

Specialization levels are given as the second type parameter in AbstractSciMLProblem constructors. For example, this is done via:

ODEProblem{iip,specialization}(f,u0,tspan,p)

Note that iip choice is required for specialization choices to be made.

Specialization Choices

SciMLBase.AbstractSpecializationType
abstract type AbstractSpecialization

Supertype for the specialization types. Controls the compilation and function specialization behavior of SciMLFunctions, ultimately controlling the runtime vs compile-time trade-off.

source
SciMLBase.AutoSpecializeType
struct AutoSpecialize <: SciMLBase.AbstractSpecialization

The default specialization level for problem functions. AutoSpecialize works by applying a function wrap just-in-time before the solve process to disable just-in-time re-specialization of the solver to the specific choice of model f and thus allow for using a cached solver compilation from a different f. This wrapping process can lead to a small decreased runtime performance with a benefit of a greatly decreased compile-time.

Note About Benchmarking and Runtime Optimality

It is recommended that AutoSpecialize is not used in any benchmarking due to the potential effect of function wrapping on runtimes. AutoSpecialize's use case is targeted at decreased latency for REPL performance and not for cases where where top runtime performance is required (such as in optimization loops). Generally, for non-stiff equations the cost will be minimal and potentially not even measurable. For stiff equations, function wrapping has the limitation that only chunk sized 1 Dual numbers are allowed, which can decrease Jacobian construction performance.

Limitations of AutoSpecialize

The following limitations are not fundamental to the implementation of AutoSpecialize, but are instead chosen as a compromise between default precompilation times and ease of maintenance. Please open an issue to discuss lifting any potential limitations.

  • AutoSpecialize is only setup to wrap the functions from in-place ODEs. Other cases are excluded for the time being due to time limitations.
  • AutoSpecialize will only lead to compilation reuse if the ODEFunction's other functions (such as jac and tgrad) are the default nothing. These could be JIT wrapped as well in a future version.
  • AutoSpecialize'd functions are only compatible with Jacobian calculations performed with chunk size 1, and only with tag DiffEqBase.OrdinaryDiffEqTag(). Thus ODE solvers written on the common interface must be careful to detect the AutoSpecialize case and perform differentiation under these constraints, use finite differencing, or manually unwrap before solving. This will lead to decreased runtime performance for sufficiently large Jacobians.
  • AutoSpecialize only wraps on Julia v1.8 and higher.
  • AutoSpecialize does not handle cases with units. If unitful values are detected, wrapping is automatically disabled.
  • AutoSpecialize only wraps cases for which promote_rule is defined between u0 and dual numbers, u0 and t, and for which ArrayInterface.promote_eltype is defined on u0 to dual numbers.
  • AutoSpecialize only wraps cases for which f.mass_matrix isa UniformScaling, the default.
  • AutoSpecialize does not wrap cases where f isa AbstractSciMLOperator
  • By default, only the u0 isa Vector{Float64}, eltype(tspan) isa Float64, and typeof(p) isa Union{Vector{Float64},SciMLBase.NullParameters} are specialized by the solver libraries. Other forms can be specialized with AutoSpecialize, but must be done in the precompilation of downstream libraries.
  • AutoSpecialized functions are manually unwrapped in adjoint methods in SciMLSensitivity.jl in order to allow compiler support for automatic differentiation. Improved versions of adjoints which decrease the recompilation surface will come in non-breaking updates.

Cases where automatic wrapping is disabled are equivalent to FullSpecialize.

Example

f(du,u,p,t) = (du .= u)
 
 # Note this is the same as ODEProblem(f, [1.0], (0.0,1.0))
 # If no preferences are set
-ODEProblem{true, SciMLBase.AutoSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.NoSpecializeType
struct NoSpecialize <: SciMLBase.AbstractSpecialization

NoSpecialize forces SciMLFunctions to not specialize on the types of functions wrapped within it. This ultimately contributes to a form such that every prob.f type is the same, meaning compilation caches are fully reused, with the downside of losing runtime performance. NoSpecialize is the form that most fully trades off runtime for compile time. Unlike AutoSpecialize, NoSpecialize can be used with any SciMLFunction.

Example

f(du,u,p,t) = (du .= u)
-ODEProblem{true, SciMLBase.NoSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.FunctionWrapperSpecializeType
struct FunctionWrapperSpecialize <: SciMLBase.AbstractSpecialization

FunctionWrapperSpecialize is an eager wrapping choice which performs a function wrapping during the ODEProblem construction. This performs the function wrapping at the earliest possible point, giving the best compile-time vs runtime performance, but with the difficulty that any usage of prob.f needs to account for the function wrapper's presence. While optimal in a performance sense, this method has many usability issues with nonstandard solvers and analyses as it requires unwrapping before re-wrapping for any type changes. Thus this method is not used by default. Given that the compile-time different is almost undetectable from AutoSpecialize, this method is mostly used as a benchmarking reference for speed of light for AutoSpecialize.

Limitations of FunctionWrapperSpecialize

FunctionWrapperSpecialize has all of the limitations of AutoSpecialize, but also includes the limitations:

  • prob.f is directly specialized to the types of (u,p,t), and any usage of prob.f on other types first requires using SciMLBase.unwrapped_f(prob.f) to remove the function wrapper.
  • FunctionWrapperSpecialize can only be used by the ODEProblem constructor. If an ODEFunction is being constructed, the user must manually use DiffEqBase.wrap_iip on f before calling ODEFunction{true,FunctionWrapperSpecialize}(f). This is a fundamental limitation of the approach as the types of (u,p,t) are required in the construction process and not accessible in the AbstractSciMLFunction constructors.

Example

f(du,u,p,t) = (du .= u)
-ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.FullSpecializeType
struct FullSpecialize <: SciMLBase.AbstractSpecialization

FullSpecialize is an eager specialization choice which directly types the AbstractSciMLFunction struct to match the type of the model f. This forces recompilation of the solver on each new function type f, leading to the most compile times with the benefit of having the best runtime performance.

FullSpecialize should be used in all cases where top runtime performance is required, such as in long-running simulations and benchmarking.

Example

f(du,u,p,t) = (du .= u)
-ODEProblem{true, SciMLBase.FullSpecialize}(f, [1.0], (0.0,1.0))
source
Note

The specialization level must be precompile snooped in the appropriate solver package in order to enable the full precompilation and system image generation for zero-latency usage. By default, this is only done with AutoSpecialize and on types u isa Vector{Float64}, eltype(tspan) isa Float64, and p isa Union{Vector{Float64}, SciMLBase.NullParameters}. Precompilation snooping in the solvers can be done using the Preferences.jl setup on the appropriate solver. See the solver library's documentation for more details.

Default Parameters

By default, AbstractSciMLProblem types use the SciMLBase.NullParameters() singleton to define the absence of parameters by default. The reason is because this throws an informative error if the parameter is used or accessed within the user's function, for example, p[1] will throw an informative error about forgetting to pass parameters.

Keyword Argument Splatting

All AbstractSciMLProblem types allow for passing keyword arguments that would get forwarded to the solver. The reason for this is that in many cases, like in EnsembleProblem usage, a AbstractSciMLProblem might be associated with some solver configuration, such as a callback or tolerance. Thus, for flexibility the extra keyword arguments to the AbstractSciMLProblem are carried to the solver.

problem_type

AbstractSciMLProblem types include a non-public API definition of problem_type which holds a trait type corresponding to the way the AbstractSciMLProblem was constructed. For example, if a SecondOrderODEProblem constructor is used, the returned problem is simply a ODEProblem for interoperability with any ODEProblem algorithm. However, in this case the problem_type will be populated with the SecondOrderODEProblem type, indicating the original definition and extra structure.

Remake

SciMLBase.remakeFunction
remake(thing; <keyword arguments>)

Re-construct thing with new field values specified by the keyword arguments.

source
remake(prob::ODEProblem; f = missing, u0 = missing, tspan = missing,
-       p = missing, kwargs = missing, _kwargs...)

Remake the given ODEProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::BVProblem; f = missing, u0 = missing, tspan = missing,
-       p = missing, kwargs = missing, problem_type = missing, _kwargs...)

Remake the given BVProblem.

source
remake(prob::SDEProblem; f = missing, u0 = missing, tspan = missing,
+ODEProblem{true, SciMLBase.AutoSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.NoSpecializeType
struct NoSpecialize <: SciMLBase.AbstractSpecialization

NoSpecialize forces SciMLFunctions to not specialize on the types of functions wrapped within it. This ultimately contributes to a form such that every prob.f type is the same, meaning compilation caches are fully reused, with the downside of losing runtime performance. NoSpecialize is the form that most fully trades off runtime for compile time. Unlike AutoSpecialize, NoSpecialize can be used with any SciMLFunction.

Example

f(du,u,p,t) = (du .= u)
+ODEProblem{true, SciMLBase.NoSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.FunctionWrapperSpecializeType
struct FunctionWrapperSpecialize <: SciMLBase.AbstractSpecialization

FunctionWrapperSpecialize is an eager wrapping choice which performs a function wrapping during the ODEProblem construction. This performs the function wrapping at the earliest possible point, giving the best compile-time vs runtime performance, but with the difficulty that any usage of prob.f needs to account for the function wrapper's presence. While optimal in a performance sense, this method has many usability issues with nonstandard solvers and analyses as it requires unwrapping before re-wrapping for any type changes. Thus this method is not used by default. Given that the compile-time different is almost undetectable from AutoSpecialize, this method is mostly used as a benchmarking reference for speed of light for AutoSpecialize.

Limitations of FunctionWrapperSpecialize

FunctionWrapperSpecialize has all of the limitations of AutoSpecialize, but also includes the limitations:

  • prob.f is directly specialized to the types of (u,p,t), and any usage of prob.f on other types first requires using SciMLBase.unwrapped_f(prob.f) to remove the function wrapper.
  • FunctionWrapperSpecialize can only be used by the ODEProblem constructor. If an ODEFunction is being constructed, the user must manually use DiffEqBase.wrap_iip on f before calling ODEFunction{true,FunctionWrapperSpecialize}(f). This is a fundamental limitation of the approach as the types of (u,p,t) are required in the construction process and not accessible in the AbstractSciMLFunction constructors.

Example

f(du,u,p,t) = (du .= u)
+ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(f, [1.0], (0.0,1.0))
source
SciMLBase.FullSpecializeType
struct FullSpecialize <: SciMLBase.AbstractSpecialization

FullSpecialize is an eager specialization choice which directly types the AbstractSciMLFunction struct to match the type of the model f. This forces recompilation of the solver on each new function type f, leading to the most compile times with the benefit of having the best runtime performance.

FullSpecialize should be used in all cases where top runtime performance is required, such as in long-running simulations and benchmarking.

Example

f(du,u,p,t) = (du .= u)
+ODEProblem{true, SciMLBase.FullSpecialize}(f, [1.0], (0.0,1.0))
source
Note

The specialization level must be precompile snooped in the appropriate solver package in order to enable the full precompilation and system image generation for zero-latency usage. By default, this is only done with AutoSpecialize and on types u isa Vector{Float64}, eltype(tspan) isa Float64, and p isa Union{Vector{Float64}, SciMLBase.NullParameters}. Precompilation snooping in the solvers can be done using the Preferences.jl setup on the appropriate solver. See the solver library's documentation for more details.

Default Parameters

By default, AbstractSciMLProblem types use the SciMLBase.NullParameters() singleton to define the absence of parameters by default. The reason is because this throws an informative error if the parameter is used or accessed within the user's function, for example, p[1] will throw an informative error about forgetting to pass parameters.

Keyword Argument Splatting

All AbstractSciMLProblem types allow for passing keyword arguments that would get forwarded to the solver. The reason for this is that in many cases, like in EnsembleProblem usage, a AbstractSciMLProblem might be associated with some solver configuration, such as a callback or tolerance. Thus, for flexibility the extra keyword arguments to the AbstractSciMLProblem are carried to the solver.

problem_type

AbstractSciMLProblem types include a non-public API definition of problem_type which holds a trait type corresponding to the way the AbstractSciMLProblem was constructed. For example, if a SecondOrderODEProblem constructor is used, the returned problem is simply a ODEProblem for interoperability with any ODEProblem algorithm. However, in this case the problem_type will be populated with the SecondOrderODEProblem type, indicating the original definition and extra structure.

Remake

SciMLBase.remakeFunction
remake(thing; <keyword arguments>)

Re-construct thing with new field values specified by the keyword arguments.

source
remake(prob::ODEProblem; f = missing, u0 = missing, tspan = missing,
+       p = missing, kwargs = missing, _kwargs...)

Remake the given ODEProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::BVProblem; f = missing, u0 = missing, tspan = missing,
+       p = missing, kwargs = missing, problem_type = missing, _kwargs...)

Remake the given BVProblem.

source
remake(prob::SDEProblem; f = missing, u0 = missing, tspan = missing,
        p = missing, noise = missing, noise_rate_prototype = missing,
-       seed = missing, kwargs = missing, _kwargs...)

Remake the given SDEProblem.

source
remake(prob::OptimizationProblem; f = missing, u0 = missing, p = missing,
+       seed = missing, kwargs = missing, _kwargs...)

Remake the given SDEProblem.

source
remake(prob::OptimizationProblem; f = missing, u0 = missing, p = missing,
     lb = missing, ub = missing, int = missing, lcons = missing, ucons = missing,
-    sense = missing, kwargs = missing, _kwargs...)

Remake the given OptimizationProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::NonlinearProblem; f = missing, u0 = missing, p = missing,
-    problem_type = missing, kwargs = missing, _kwargs...)

Remake the given NonlinearProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::NonlinearLeastSquaresProblem; f = missing, u0 = missing, p = missing,
-    kwargs = missing, _kwargs...)

Remake the given NonlinearLeastSquaresProblem.

source

Problem Traits

SciMLBase.isinplaceMethod
isinplace(prob::AbstractSciMLProblem)

Determine whether the function of the given problem operates in place or not.

source

AbstractSciMLProblem API

Defaults and Preferences

SpecializationLevel at SciMLBase can be used to set the default specialization level. The following shows how to set the specialization default to FullSpecialize:

using Preferences, UUIDs
-set_preferences!(UUID("0bca4576-84f4-4d90-8ffe-ffa030f20462"), "SpecializationLevel" => "FullSpecialize")

The default is AutoSpecialize.

Abstract SciMLProblems

SciMLBase.AbstractDEProblemType
abstract type AbstractDEProblem <: SciMLBase.AbstractSciMLProblem

Base type for all DifferentialEquations.jl problems. Concrete subtypes of AbstractDEProblem contain the necessary information to fully define a differential equation of the corresponding type.

source
SciMLBase.AbstractODEProblemType
abstract type AbstractODEProblem{uType, tType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define ODE problems.

source
SciMLBase.AbstractDiscreteProblemType
abstract type AbstractDiscreteProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}

Base for types which define discrete problems.

source
SciMLBase.AbstractRODEProblemType
abstract type AbstractRODEProblem{uType, tType, isinplace, ND} <: SciMLBase.AbstractDEProblem

Base for types which define RODE problems.

source
SciMLBase.AbstractSDEProblemType
abstract type AbstractSDEProblem{uType, tType, isinplace, ND} <: SciMLBase.AbstractRODEProblem{uType, tType, isinplace, ND}

Base for types which define SDE problems.

source
SciMLBase.AbstractDAEProblemType
abstract type AbstractDAEProblem{uType, duType, tType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define DAE problems.

source
SciMLBase.AbstractDDEProblemType
abstract type AbstractDDEProblem{uType, tType, lType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define DDE problems.

source
SciMLBase.AbstractBVProblemType
abstract type AbstractBVProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}

Base for types which define BVP problems.

source
SciMLBase.AbstractSDDEProblemType
abstract type AbstractSDDEProblem{uType, tType, lType, isinplace, ND} <: SciMLBase.AbstractDEProblem

Base for types which define SDDE problems.

source
+ sense = missing, kwargs = missing, _kwargs...)

Remake the given OptimizationProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::NonlinearProblem; f = missing, u0 = missing, p = missing,
+    problem_type = missing, kwargs = missing, _kwargs...)

Remake the given NonlinearProblem. If u0 or p are given as symbolic maps ModelingToolkit.jl has to be loaded.

source
remake(prob::NonlinearLeastSquaresProblem; f = missing, u0 = missing, p = missing,
+    kwargs = missing, _kwargs...)

Remake the given NonlinearLeastSquaresProblem.

source

Problem Traits

SciMLBase.isinplaceMethod
isinplace(prob::AbstractSciMLProblem)

Determine whether the function of the given problem operates in place or not.

source
SciMLBase.is_diagonal_noiseFunction
is_diagonal_noise(prob::AbstractSciMLProblem)
source

AbstractSciMLProblem API

Defaults and Preferences

SpecializationLevel at SciMLBase can be used to set the default specialization level. The following shows how to set the specialization default to FullSpecialize:

using Preferences, UUIDs
+set_preferences!(UUID("0bca4576-84f4-4d90-8ffe-ffa030f20462"), "SpecializationLevel" => "FullSpecialize")

The default is AutoSpecialize.

Abstract SciMLProblems

SciMLBase.AbstractSciMLProblemType
abstract type AbstractSciMLProblem
source
SciMLBase.AbstractDEProblemType
abstract type AbstractDEProblem <: SciMLBase.AbstractSciMLProblem

Base type for all DifferentialEquations.jl problems. Concrete subtypes of AbstractDEProblem contain the necessary information to fully define a differential equation of the corresponding type.

source
SciMLBase.AbstractLinearProblemType
abstract type AbstractLinearProblem{bType, isinplace} <: SciMLBase.AbstractSciMLProblem

Base for types which define linear systems.

source
SciMLBase.AbstractNonlinearProblemType
abstract type AbstractNonlinearProblem{uType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define nonlinear solve problems (f(u)=0).

source
SciMLBase.AbstractIntegralProblemType
abstract type AbstractIntegralProblem{isinplace} <: SciMLBase.AbstractSciMLProblem

Base for types which define integrals suitable for quadrature.

source
SciMLBase.AbstractOptimizationProblemType
abstract type AbstractOptimizationProblem{isinplace} <: SciMLBase.AbstractSciMLProblem

Base for types which define equations for optimization.

source
SciMLBase.AbstractNoiseProblemType
abstract type AbstractNoiseProblem <: SciMLBase.AbstractDEProblem
source
SciMLBase.AbstractODEProblemType
abstract type AbstractODEProblem{uType, tType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define ODE problems.

source
SciMLBase.AbstractDiscreteProblemType
abstract type AbstractDiscreteProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}

Base for types which define discrete problems.

source
SciMLBase.AbstractAnalyticalProblemType
abstract type AbstractAnalyticalProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}
source
SciMLBase.AbstractRODEProblemType
abstract type AbstractRODEProblem{uType, tType, isinplace, ND} <: SciMLBase.AbstractDEProblem

Base for types which define RODE problems.

source
SciMLBase.AbstractSDEProblemType
abstract type AbstractSDEProblem{uType, tType, isinplace, ND} <: SciMLBase.AbstractRODEProblem{uType, tType, isinplace, ND}

Base for types which define SDE problems.

source
SciMLBase.AbstractDAEProblemType
abstract type AbstractDAEProblem{uType, duType, tType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define DAE problems.

source
SciMLBase.AbstractDDEProblemType
abstract type AbstractDDEProblem{uType, tType, lType, isinplace} <: SciMLBase.AbstractDEProblem

Base for types which define DDE problems.

source
SciMLBase.AbstractConstantLagDDEProblemType
abstract type AbstractConstantLagDDEProblem{uType, tType, lType, isinplace} <: SciMLBase.AbstractDDEProblem{uType, tType, lType, isinplace}
source
SciMLBase.AbstractSecondOrderODEProblemType
abstract type AbstractSecondOrderODEProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}
source
SciMLBase.AbstractBVProblemType
abstract type AbstractBVProblem{uType, tType, isinplace} <: SciMLBase.AbstractODEProblem{uType, tType, isinplace}

Base for types which define BVP problems.

source
SciMLBase.AbstractJumpProblemType
abstract type AbstractJumpProblem{P, J} <: SciMLBase.AbstractDEProblem

Base for types which define jump problems.

source
SciMLBase.AbstractSDDEProblemType
abstract type AbstractSDDEProblem{uType, tType, lType, isinplace, ND} <: SciMLBase.AbstractDEProblem

Base for types which define SDDE problems.

source
SciMLBase.AbstractConstantLagSDDEProblemType
abstract type AbstractConstantLagSDDEProblem{uType, tType, lType, isinplace, ND} <: SciMLBase.AbstractSDDEProblem{uType, tType, lType, isinplace, ND}
source
SciMLBase.AbstractPDEProblemType
abstract type AbstractPDEProblem <: SciMLBase.AbstractDEProblem

Base for types which define PDE problems.

source
diff --git a/dev/interfaces/SciMLFunctions/index.html b/dev/interfaces/SciMLFunctions/index.html index 590a1558c..74c5df844 100644 --- a/dev/interfaces/SciMLFunctions/index.html +++ b/dev/interfaces/SciMLFunctions/index.html @@ -4,4 +4,4 @@ f = (du,u,p,t) -> du .= t .* u jac = (J,u,p,t) -> (J[1,1] = t; J[2,2] = t; J) jp = Diagonal(zeros(2)) -fun = ODEFunction(f; jac=jac, jac_prototype=jp)

Note that the integrators will always make a deep copy of fun.jac_prototype, so there's no worry of aliasing.

In general the jacobian prototype can be anything that has mul! defined, in particular sparse matrices or custom lazy types that support mul!. A special case is when the jac_prototype is a AbstractSciMLOperator, in which case you do not need to supply jac as it is automatically set to update_coefficients!. Refer to the SciMLOperators section for more information on setting up time/parameter dependent operators.

Sparsity Handling

The solver libraries internally use packages such as FiniteDiff.jl and SparseDiffTools.jl for high performance calculation of sparse Jacobians and Hessians, along with matrix-free calculations of Jacobian-Vector products (Jv), vector-Jacobian products (v'J), and Hessian-vector products (H*v). The SciML interface gives users the ability to control these connections in order to allow for top notch performance.

The key arguments in the SciMLFunction is the prototype, which is an object that will be used as the underlying Jacobian/Hessian. Thus if one wants to use a sparse Jacobian, one should specify jac_prototype to be a sparse matrix. The sparsity pattern used in the differentiation scheme is defined by sparsity. By default, sparsity=jac_prototype, meaning that the sparse automatic differentiation scheme should specialize on the sparsity pattern given by the actual sparsity pattern. This can be overridden to say perform partial matrix coloring approximations. Additionally, the color vector for the sparse differentiation directions can be specified directly via colorvec. For more information on how these arguments control the differentiation process, see the aforementioned differentiation library documentations.

Traits

Missing docstring.

Missing docstring for SciMLBase.isinplace(f::SciMLBase.AbstractSciMLFunction). Check Documenter's build log for details.

AbstractSciMLFunction API

Abstract SciML Functions

SciMLBase.AbstractDiffEqFunctionType
abstract type AbstractDiffEqFunction{iip} <: SciMLBase.AbstractSciMLFunction{iip}

Base for types defining differential equation functions.

source
SciMLBase.AbstractODEFunctionType
abstract type AbstractODEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractSDEFunctionType
abstract type AbstractSDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDDEFunctionType
abstract type AbstractDDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDAEFunctionType
abstract type AbstractDAEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractRODEFunctionType
abstract type AbstractRODEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDiscreteFunctionType
abstract type AbstractDiscreteFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractSDDEFunctionType
abstract type AbstractSDDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractNonlinearFunctionType
abstract type AbstractNonlinearFunction{iip} <: SciMLBase.AbstractSciMLFunction{iip}
source
+fun = ODEFunction(f; jac=jac, jac_prototype=jp)

Note that the integrators will always make a deep copy of fun.jac_prototype, so there's no worry of aliasing.

In general the jacobian prototype can be anything that has mul! defined, in particular sparse matrices or custom lazy types that support mul!. A special case is when the jac_prototype is a AbstractSciMLOperator, in which case you do not need to supply jac as it is automatically set to update_coefficients!. Refer to the SciMLOperators section for more information on setting up time/parameter dependent operators.

Sparsity Handling

The solver libraries internally use packages such as FiniteDiff.jl and SparseDiffTools.jl for high performance calculation of sparse Jacobians and Hessians, along with matrix-free calculations of Jacobian-Vector products (Jv), vector-Jacobian products (v'J), and Hessian-vector products (H*v). The SciML interface gives users the ability to control these connections in order to allow for top notch performance.

The key arguments in the SciMLFunction is the prototype, which is an object that will be used as the underlying Jacobian/Hessian. Thus if one wants to use a sparse Jacobian, one should specify jac_prototype to be a sparse matrix. The sparsity pattern used in the differentiation scheme is defined by sparsity. By default, sparsity=jac_prototype, meaning that the sparse automatic differentiation scheme should specialize on the sparsity pattern given by the actual sparsity pattern. This can be overridden to say perform partial matrix coloring approximations. Additionally, the color vector for the sparse differentiation directions can be specified directly via colorvec. For more information on how these arguments control the differentiation process, see the aforementioned differentiation library documentations.

Traits

Missing docstring.

Missing docstring for SciMLBase.isinplace(f::SciMLBase.AbstractSciMLFunction). Check Documenter's build log for details.

AbstractSciMLFunction API

Abstract SciML Functions

SciMLBase.AbstractDiffEqFunctionType
abstract type AbstractDiffEqFunction{iip} <: SciMLBase.AbstractSciMLFunction{iip}

Base for types defining differential equation functions.

source
SciMLBase.AbstractODEFunctionType
abstract type AbstractODEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractSDEFunctionType
abstract type AbstractSDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDDEFunctionType
abstract type AbstractDDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDAEFunctionType
abstract type AbstractDAEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractRODEFunctionType
abstract type AbstractRODEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractDiscreteFunctionType
abstract type AbstractDiscreteFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractSDDEFunctionType
abstract type AbstractSDDEFunction{iip} <: SciMLBase.AbstractDiffEqFunction{iip}
source
SciMLBase.AbstractNonlinearFunctionType
abstract type AbstractNonlinearFunction{iip} <: SciMLBase.AbstractSciMLFunction{iip}
source
diff --git a/dev/interfaces/Solutions/index.html b/dev/interfaces/Solutions/index.html index 0d6f0e899..636b0b29e 100644 --- a/dev/interfaces/Solutions/index.html +++ b/dev/interfaces/Solutions/index.html @@ -1,2 +1,2 @@ -SciMLSolutions · SciMLBase.jl

SciMLSolutions

Definition of the AbstractSciMLSolution Interface

All AbstractSciMLSolution types are a subset of some AbstractArray. Types with time series (like ODESolution) are subtypes of RecursiveArrayTools.AbstractVectorOfArray and RecursiveArrayTools.AbstractDiffEqArray where appropriate. Types without a time series (like OptimizationSolution) are directly subsets of AbstractArray.

Array Interface

Instead of working on the Vector{uType} directly, we can use the provided array interface.

sol[j]

to access the value at timestep j (if the timeseries was saved), and

sol.t[j]

to access the value of t at timestep j. For multi-dimensional systems, this will address first by component and lastly by time, and thus

sol[i,j]

will be the ith component at timestep j. Hence, sol[j][i] == sol[i, j]. This is done because Julia is column-major, so the leading dimension should be contiguous in memory. If the independent variables had shape (for example, was a matrix), then i is the linear index. We can also access solutions with shape:

sol[i,k,j]

gives the [i,k] component of the system at timestep j. The colon operator is supported, meaning that

sol[i,:]

gives the timeseries for the ith component.

Common Field Names

  • u: the solution values
  • t: the independent variable values, matching the length of the solution, if applicable
  • resid: the residual of the solution, if applicable
  • original: the solution object from the original solver, if it's a wrapper algorithm
  • retcode: see the documentation section on return codes
  • prob: the problem that was solved
  • alg: the algorithm used to solve the problem

Return Codes (RetCodes)

The solution types have a retcode field which returns a SciMLBase.ReturnCode.T (from EnumX.jl, see that package for the semantics of handling EnumX types) signifying the error or satisfaction state of the solution.

SciMLBase.ReturnCodeModule

SciML.ReturnCode

SciML.ReturnCode is the standard return code enum interface for the SciML interface. Return codes are notes given by the solvers to indicate the state of the solution, for example whether it successfully solved the equations, whether it failed to solve the equations, and importantly, why it exited.

Using SciML.ReturnCode

SciML.ReturnCode use the interface of EnumX.jl and thus inherits all of the behaviors of being an EnumX. This includes the Enum type itself being referred to as SciML.ReturnCode.T, and each of the constituent enum states being referred to via getproperty, i.e. SciML.ReturnCode.Success.

Note About Success Checking

Previous iterations of the interface suggested using sol.retcode == :Success, however, that is now not advised instead should be replaced with SciMLBase.successful_retcode(sol). The reason is that there are many different codes that can be interpreted as successful, such as ReturnCode.Terminated which means successfully used terminate!(integrator) to end an integration at a user-specified condition. As such, successful_retcode is the most general way to query for if the solver did not error.

Properties

  • successful_retcode(retcode::ReturnCode.T): Determines whether the output enum is considered a success state of the solver, i.e. the solver successfully solved the equations. ReturnCode.Success is the most basic form, simply declaring that it was successful, but many more informative success return codes exist as well.
source

Return Code Traits

SciMLBase.successful_retcodeFunction

successful_retcode(retcode::ReturnCode.T)::Bool successful_retcode(sol::AbstractSciMLSolution)::Bool

Returns a boolean for whether a return code should be interpreted as a form of success.

source

Specific Return Codes

SciMLBase.ReturnCode.DefaultConstant

ReturnCode.Default

The default state of the solver. If this return code is given, then the solving process is either still in process or the solver library has not been setup with the return code interface and thus the return code is undetermined.

Common Reasons for Seeing this Return Code

  • A common reason for Default return codes is that a solver is a non-SciML solver which does not fully conform to the interface. Please open an issue if this is seen and it will be improved.
  • Another common reason for a Default return code is if the solver is probed internally before the solving process is done, such as through the callback interface. Return codes are set to Default to start and are changed to Success and other return codes upon finishing the solving process or hitting a numerical difficulty.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.SuccessConstant

ReturnCode.Success

The success state of the solver. If this return code is given, then the solving process was successful, but no extra information about that success is given.

Common Reasons for Seeing this Return Code

  • This is the most common return code and most solvers will give this return code if the solving process went as expected without any errors or detected numerical issues.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.TerminatedConstant

ReturnCode.Terminated

The successful termination state of the solver. If this return code is given, then the solving process was successful at terminating the solve, usually through a callback affect! via terminate!(integrator).

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is if a user calls a callback which uses terminate!(integrator) to halt the integration at a user-chosen stopping point.
  • Another common reason for this return code is due to implicit terminate! statements in some library callbacks. For example, SteadyStateCallback uses terminate! internally, so solutions which reach steady state will have a ReturnCode.Terminated state instead of a ReturnCode.Success state. Similarly, problems solved via SteadyStateDiffEq.jl will have this ReturnCode.Terminated state if a timestepping method is used to solve to steady state.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.DtNaNConstant

ReturnCode.DtNaN

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the dt of the integration was determined to be NaN and thus the solver could not continue.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the automatic dt selection algorithm is used but the starting derivative has a NaN or Inf derivative term. Double check that the f(u0,p,t0) term is well-defined without NaN or Inf values.
  • Another common reason for this return code is because of a user set dt which is calculated to be a NaN. If solve(prob,alg,dt=x), double check that x is not NaN.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.MaxItersConstant

ReturnCode.MaxIters

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the solver's iterations hit the maxiters either set by default or by the user in the solve/init command.

Note about Nonlinear Optimization

In nonlinear optimization, many solvers (such as OptimizationOptimisers.Adam) do not have an exit criteria other than iters == maxiters. In this case, the solvers will iterate until maxiters and exit with a Success return code, as that is a successful run of the solver and not considered to be an error state. Solves with early termination criteria, such as Optim.BFGS exiting when the gradient is sufficiently close to zero, will give ReturnCode.MaxIters on exits which require the maximum iteration.

Common Reasons for Seeing this Return Code

  • This commonly occurs in ODE solving if a non-stiff method (e.g. Tsit5) is used in an algorithm choice for a stiff ODE. It is recommended that in such cases, one tries a stiff ODE solver.
  • This commonly occurs in optimization and nonlinear solvers if the tolerance on solve to too low and cannot be achieved due to floating point error or the condition number of the solver matrix. Double check that the chosen tolerance is numerically possible.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.DtLessThanMinConstant

ReturnCode.DtLessThanMin

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the dt of the integration was made to be less than dtmin, i.e. dt < dtmin.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the integration is going unstable. As f(u,p,t) -> infinity, the time steps required by the solver to accurately handle the dynamics decreases. When it gets sufficiently small, dtmin, an exit is thrown as the solution is likely unstable. dtmin is also chosen to be around the value where floating point issues cause t + dt == t, and thus a dt of that size is impossible at floating point precision.
  • Another common reason for this return code is if domain constraints are set, such as by using isoutofdomain, but the domain constraint is incorrect. For example, if one is solving the ODE f(u,p,t) = -u - 1, one may think "but I want a solution with u > 0 and thus I will set isoutofdomain(u,p,t) = u < 0. However, the true solution of this ODE is not positive, and thus what will occur is that the solver will try to decrease dt until it can give an accurate solution that is positive. As this is impossible, it will continue to shrink the dt until dt < dtmin and then exit with this return code.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.UnstableConstant

ReturnCode.Unstable

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the unstable_check function, as given by the unstable_check common keyword argument (or its default), give a true at the current state.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because u contains a NaN or Inf value. The default unstable_check only checks for these values.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.InitialFailureConstant

ReturnCode.InitialFailure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful because the initialization process failed.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the initialization process of a DAE solver failed to find consistent initial conditions, which can occur if the differentiation index of the DAE solver is too high. Most DAE solvers only allow for index-1 DAEs, and so an index-2 DAE will fail during this initialization. To solve this kind of problem, use ModelingToolkit.jl and its structural_simplify method to reduce the index of the DAE.
  • Another common reason for this return code is if the initial condition was not suitable for the numerical solve. For example, the initial point had a NaN or Inf. Or in optimization, this can occur if the initial point is outside of the bound constraints given by the user.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.ConvergenceFailureConstant

ReturnCode.ConvergenceFailure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful because internal nonlinear solver iterations failed to converge.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because an inappropriate nonlinear solver was chosen. If fixed point iteration is used on a stiff problem, it will be faster by avoiding the Jacobian but it will make a stiff ODE solver not stable for stiff problems!

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.FailureConstant

ReturnCode.Failure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful but no extra information is given.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the solver is a wrapped solver (i.e. a Fortran code) which does not provide any extra information about its exit state. If this is from a Julia-based solver, please open an issue.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.ExactSolutionLeftConstant

ReturnCode.ExactSolutionLeft

The success state of the solver. If this return code is given, then the solving process was successful, and the left solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a bracketing nonlinear solver, such as bisection, iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the first floating point value to the left for x.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.ExactSolutionRightConstant

ReturnCode.ExactSolutionRight

The success state of the solver. If this return code is given, then the solving process was successful, and the right solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a bracketing nonlinear solver, such as bisection, iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the first floating point value to the right for x.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.FloatingPointLimitConstant

ReturnCode.FloatingPointLimit

The success state of the solver. If this return code is given, then the solving process was successful, and the closest floating point value to the solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a nonlinear solver, such as Falsi,

iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the closest floating point value to the true solution for x.

Properties

  • successful_retcode = true
source

Solution Traits

AbstractSciMLSolution API

Abstract SciML Solutions

+SciMLSolutions · SciMLBase.jl

SciMLSolutions

Definition of the AbstractSciMLSolution Interface

All AbstractSciMLSolution types are a subset of some AbstractArray. Types with time series (like ODESolution) are subtypes of RecursiveArrayTools.AbstractVectorOfArray and RecursiveArrayTools.AbstractDiffEqArray where appropriate. Types without a time series (like OptimizationSolution) are directly subsets of AbstractArray.

Array Interface

Instead of working on the Vector{uType} directly, we can use the provided array interface.

sol[j]

to access the value at timestep j (if the timeseries was saved), and

sol.t[j]

to access the value of t at timestep j. For multi-dimensional systems, this will address first by component and lastly by time, and thus

sol[i,j]

will be the ith component at timestep j. Hence, sol[j][i] == sol[i, j]. This is done because Julia is column-major, so the leading dimension should be contiguous in memory. If the independent variables had shape (for example, was a matrix), then i is the linear index. We can also access solutions with shape:

sol[i,k,j]

gives the [i,k] component of the system at timestep j. The colon operator is supported, meaning that

sol[i,:]

gives the timeseries for the ith component.

Common Field Names

  • u: the solution values
  • t: the independent variable values, matching the length of the solution, if applicable
  • resid: the residual of the solution, if applicable
  • original: the solution object from the original solver, if it's a wrapper algorithm
  • retcode: see the documentation section on return codes
  • prob: the problem that was solved
  • alg: the algorithm used to solve the problem

Return Codes (RetCodes)

The solution types have a retcode field which returns a SciMLBase.ReturnCode.T (from EnumX.jl, see that package for the semantics of handling EnumX types) signifying the error or satisfaction state of the solution.

SciMLBase.ReturnCodeModule

SciML.ReturnCode

SciML.ReturnCode is the standard return code enum interface for the SciML interface. Return codes are notes given by the solvers to indicate the state of the solution, for example whether it successfully solved the equations, whether it failed to solve the equations, and importantly, why it exited.

Using SciML.ReturnCode

SciML.ReturnCode use the interface of EnumX.jl and thus inherits all of the behaviors of being an EnumX. This includes the Enum type itself being referred to as SciML.ReturnCode.T, and each of the constituent enum states being referred to via getproperty, i.e. SciML.ReturnCode.Success.

Note About Success Checking

Previous iterations of the interface suggested using sol.retcode == :Success, however, that is now not advised instead should be replaced with SciMLBase.successful_retcode(sol). The reason is that there are many different codes that can be interpreted as successful, such as ReturnCode.Terminated which means successfully used terminate!(integrator) to end an integration at a user-specified condition. As such, successful_retcode is the most general way to query for if the solver did not error.

Properties

  • successful_retcode(retcode::ReturnCode.T): Determines whether the output enum is considered a success state of the solver, i.e. the solver successfully solved the equations. ReturnCode.Success is the most basic form, simply declaring that it was successful, but many more informative success return codes exist as well.
source

Return Code Traits

SciMLBase.successful_retcodeFunction

successful_retcode(retcode::ReturnCode.T)::Bool successful_retcode(sol::AbstractSciMLSolution)::Bool

Returns a boolean for whether a return code should be interpreted as a form of success.

source

Specific Return Codes

SciMLBase.ReturnCode.DefaultConstant

ReturnCode.Default

The default state of the solver. If this return code is given, then the solving process is either still in process or the solver library has not been setup with the return code interface and thus the return code is undetermined.

Common Reasons for Seeing this Return Code

  • A common reason for Default return codes is that a solver is a non-SciML solver which does not fully conform to the interface. Please open an issue if this is seen and it will be improved.
  • Another common reason for a Default return code is if the solver is probed internally before the solving process is done, such as through the callback interface. Return codes are set to Default to start and are changed to Success and other return codes upon finishing the solving process or hitting a numerical difficulty.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.SuccessConstant

ReturnCode.Success

The success state of the solver. If this return code is given, then the solving process was successful, but no extra information about that success is given.

Common Reasons for Seeing this Return Code

  • This is the most common return code and most solvers will give this return code if the solving process went as expected without any errors or detected numerical issues.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.TerminatedConstant

ReturnCode.Terminated

The successful termination state of the solver. If this return code is given, then the solving process was successful at terminating the solve, usually through a callback affect! via terminate!(integrator).

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is if a user calls a callback which uses terminate!(integrator) to halt the integration at a user-chosen stopping point.
  • Another common reason for this return code is due to implicit terminate! statements in some library callbacks. For example, SteadyStateCallback uses terminate! internally, so solutions which reach steady state will have a ReturnCode.Terminated state instead of a ReturnCode.Success state. Similarly, problems solved via SteadyStateDiffEq.jl will have this ReturnCode.Terminated state if a timestepping method is used to solve to steady state.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.DtNaNConstant

ReturnCode.DtNaN

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the dt of the integration was determined to be NaN and thus the solver could not continue.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the automatic dt selection algorithm is used but the starting derivative has a NaN or Inf derivative term. Double check that the f(u0,p,t0) term is well-defined without NaN or Inf values.
  • Another common reason for this return code is because of a user set dt which is calculated to be a NaN. If solve(prob,alg,dt=x), double check that x is not NaN.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.MaxItersConstant

ReturnCode.MaxIters

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the solver's iterations hit the maxiters either set by default or by the user in the solve/init command.

Note about Nonlinear Optimization

In nonlinear optimization, many solvers (such as OptimizationOptimisers.Adam) do not have an exit criteria other than iters == maxiters. In this case, the solvers will iterate until maxiters and exit with a Success return code, as that is a successful run of the solver and not considered to be an error state. Solves with early termination criteria, such as Optim.BFGS exiting when the gradient is sufficiently close to zero, will give ReturnCode.MaxIters on exits which require the maximum iteration.

Common Reasons for Seeing this Return Code

  • This commonly occurs in ODE solving if a non-stiff method (e.g. Tsit5) is used in an algorithm choice for a stiff ODE. It is recommended that in such cases, one tries a stiff ODE solver.
  • This commonly occurs in optimization and nonlinear solvers if the tolerance on solve to too low and cannot be achieved due to floating point error or the condition number of the solver matrix. Double check that the chosen tolerance is numerically possible.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.DtLessThanMinConstant

ReturnCode.DtLessThanMin

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the dt of the integration was made to be less than dtmin, i.e. dt < dtmin.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the integration is going unstable. As f(u,p,t) -> infinity, the time steps required by the solver to accurately handle the dynamics decreases. When it gets sufficiently small, dtmin, an exit is thrown as the solution is likely unstable. dtmin is also chosen to be around the value where floating point issues cause t + dt == t, and thus a dt of that size is impossible at floating point precision.
  • Another common reason for this return code is if domain constraints are set, such as by using isoutofdomain, but the domain constraint is incorrect. For example, if one is solving the ODE f(u,p,t) = -u - 1, one may think "but I want a solution with u > 0 and thus I will set isoutofdomain(u,p,t) = u < 0. However, the true solution of this ODE is not positive, and thus what will occur is that the solver will try to decrease dt until it can give an accurate solution that is positive. As this is impossible, it will continue to shrink the dt until dt < dtmin and then exit with this return code.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.UnstableConstant

ReturnCode.Unstable

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful and exited early because the unstable_check function, as given by the unstable_check common keyword argument (or its default), give a true at the current state.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because u contains a NaN or Inf value. The default unstable_check only checks for these values.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.InitialFailureConstant

ReturnCode.InitialFailure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful because the initialization process failed.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the initialization process of a DAE solver failed to find consistent initial conditions, which can occur if the differentiation index of the DAE solver is too high. Most DAE solvers only allow for index-1 DAEs, and so an index-2 DAE will fail during this initialization. To solve this kind of problem, use ModelingToolkit.jl and its structural_simplify method to reduce the index of the DAE.
  • Another common reason for this return code is if the initial condition was not suitable for the numerical solve. For example, the initial point had a NaN or Inf. Or in optimization, this can occur if the initial point is outside of the bound constraints given by the user.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.ConvergenceFailureConstant

ReturnCode.ConvergenceFailure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful because internal nonlinear solver iterations failed to converge.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because an inappropriate nonlinear solver was chosen. If fixed point iteration is used on a stiff problem, it will be faster by avoiding the Jacobian but it will make a stiff ODE solver not stable for stiff problems!

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.FailureConstant

ReturnCode.Failure

A failure exit state of the solver. If this return code is given, then the solving process was unsuccessful but no extra information is given.

Common Reasons for Seeing this Return Code

  • The most common reason for seeing this return code is because the solver is a wrapped solver (i.e. a Fortran code) which does not provide any extra information about its exit state. If this is from a Julia-based solver, please open an issue.

Properties

  • successful_retcode = false
source
SciMLBase.ReturnCode.ExactSolutionLeftConstant

ReturnCode.ExactSolutionLeft

The success state of the solver. If this return code is given, then the solving process was successful, and the left solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a bracketing nonlinear solver, such as bisection, iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the first floating point value to the left for x.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.ExactSolutionRightConstant

ReturnCode.ExactSolutionRight

The success state of the solver. If this return code is given, then the solving process was successful, and the right solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a bracketing nonlinear solver, such as bisection, iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the first floating point value to the right for x.

Properties

  • successful_retcode = true
source
SciMLBase.ReturnCode.FloatingPointLimitConstant

ReturnCode.FloatingPointLimit

The success state of the solver. If this return code is given, then the solving process was successful, and the closest floating point value to the solution was given.

Common Reasons for Seeing this Return Code

  • The most common reason for this return code is via a nonlinear solver, such as Falsi,

iterating to convergence is unable to give the exact f(x)=0 solution due to floating point precision issues, and thus it gives the closest floating point value to the true solution for x.

Properties

  • successful_retcode = true
source

Solution Traits

AbstractSciMLSolution API

Abstract SciML Solutions