-
-
Notifications
You must be signed in to change notification settings - Fork 259
Expand file tree
/
Copy pathOrdinaryDiffEqRosenbrock.jl
More file actions
302 lines (279 loc) · 14.1 KB
/
OrdinaryDiffEqRosenbrock.jl
File metadata and controls
302 lines (279 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
module OrdinaryDiffEqRosenbrock
import OrdinaryDiffEqCore: alg_order, alg_adaptive_order, isWmethod, isfsal, _unwrap_val,
DEFAULT_PRECS, OrdinaryDiffEqRosenbrockAlgorithm, @cache,
alg_cache, initialize!,
calculate_residuals!, OrdinaryDiffEqMutableCache,
OrdinaryDiffEqConstantCache, _ode_interpolant, _ode_interpolant!,
_vec, _reshape, perform_step!, trivial_limiter!,
OrdinaryDiffEqRosenbrockAdaptiveAlgorithm,
OrdinaryDiffEqRosenbrockAlgorithm, generic_solver_docstring,
initialize!, perform_step!, get_fsalfirstlast,
constvalue, only_diagonal_mass_matrix,
calculate_residuals, has_stiff_interpolation, ODEIntegrator,
resize_non_user_cache!, _ode_addsteps!, full_cache,
DerivativeOrderNotPossibleError, _bool_to_ADType,
_process_AD_choice, LinearAliasSpecifier, copyat_or_push!,
find_algebraic_vars_eqs
using MuladdMacro, FastBroadcast, RecursiveArrayTools
import MacroTools: namify
using MacroTools: @capture
using DiffEqBase: @def
import DifferentiationInterface as DI
import LinearSolve
import LinearSolve: UniformScaling
import ForwardDiff
using FiniteDiff
using LinearAlgebra: mul!, diag, diagm, I, Diagonal, norm, lu, lu!
using ADTypes
import OrdinaryDiffEqCore, OrdinaryDiffEqDifferentiation
using OrdinaryDiffEqDifferentiation: TimeDerivativeWrapper, TimeGradientWrapper,
UDerivativeWrapper, UJacobianWrapper,
wrapprecs, calc_tderivative, build_grad_config,
build_jac_config, issuccess_W, jacobian2W!,
resize_jac_config!, resize_grad_config!,
calc_W, calc_rosenbrock_differentiation!, build_J_W,
UJacobianWrapper, dolinsolve, WOperator, resize_J_W!
using Reexport
@reexport using SciMLBase
import OrdinaryDiffEqCore: alg_autodiff
import OrdinaryDiffEqCore
function rosenbrock_wolfbrandt_docstring(
description::String,
name::String;
references::String = "",
extra_keyword_description = "",
extra_keyword_default = "",
with_step_limiter = false
)
keyword_default = """
chunk_size = Val{0}(),
standardtag = Val{true}(),
autodiff = AutoForwardDiff(),
concrete_jac = nothing,
diff_type = Val{:forward}(),
linsolve = nothing,
precs = DEFAULT_PRECS,
""" * extra_keyword_default
keyword_default_description = """
- `standardtag`: Specifies whether to use package-specific tags instead of the
ForwardDiff default function-specific tags. For more information, see
[this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/).
Defaults to `Val{true}()`.
- `autodiff`: Uses [ADTypes.jl](https://sciml.github.io/ADTypes.jl/stable/)
to specify whether to use automatic differentiation via
[ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite
differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl).
Defaults to `AutoForwardDiff()` for automatic differentiation, which by default uses
`chunksize = 0`, and thus uses the internal ForwardDiff.jl algorithm for the choice.
To use `FiniteDiff.jl`, the `AutoFiniteDiff()` ADType can be used, which has a keyword argument
`fdtype` with default value `Val{:forward}()`, and alternatives `Val{:central}()` and `Val{:complex}()`.
- `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to
`nothing`, which means it will be chosen true/false depending on circumstances
of the solver, such as whether a Krylov subspace method is used for `linsolve`.
- `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver.
For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify
`$name(linsolve = KLUFactorization()`).
When `nothing` is passed, uses `DefaultLinearSolver`.
- `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/)
can be used as a left or right preconditioner.
Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)`
function where the arguments are defined as:
- `W`: the current Jacobian of the nonlinear system. Specified as either
``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will
commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy
representation of the operator. Users can construct the W-matrix on demand
by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching
the `jac_prototype`.
- `du`: the current ODE derivative
- `u`: the current ODE state
- `p`: the ODE parameters
- `t`: the current ODE time
- `newW`: a `Bool` which specifies whether the `W` matrix has been updated since
the last call to `precs`. It is recommended that this is checked to only
update the preconditioner when `newW == true`.
- `Plprev`: the previous `Pl`.
- `Prprev`: the previous `Pr`.
- `solverdata`: Optional extra data the solvers can give to the `precs` function.
Solver-dependent and subject to change.
The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners.
To specify one-sided preconditioning, simply return `nothing` for the preconditioner
which is not used. Additionally, `precs` must supply the dispatch:
```julia
Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata)
```
which is used in the solver setup phase to construct the integrator
type with the preconditioners `(Pl,Pr)`.
The default is `precs=DEFAULT_PRECS` where the default preconditioner function
is defined as:
```julia
DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing
```
""" * extra_keyword_description
if with_step_limiter
keyword_default *= "step_limiter! = OrdinaryDiffEq.trivial_limiter!,\n"
keyword_default_description *= "- `step_limiter!`: function of the form `limiter!(u, integrator, p, t)`\n"
end
return generic_solver_docstring(
description, name, "Rosenbrock-Wanner-W(olfbrandt) Method. ", references,
keyword_default_description, keyword_default
)
end
function rosenbrock_docstring(
description::String,
name::String;
references::String = "",
extra_keyword_description = "",
extra_keyword_default = "",
with_step_limiter = false
)
keyword_default = """
- `standardtag`: Specifies whether to use package-specific tags instead of the
ForwardDiff default function-specific tags. For more information, see
[this blog post](https://www.stochasticlifestyle.com/improved-forwarddiff-jl-stacktraces-with-package-tags/).
Defaults to `Val{true}()`.
- `autodiff`: Uses [ADTypes.jl](https://sciml.github.io/ADTypes.jl/stable/)
to specify whether to use automatic differentiation via
[ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) or finite
differencing via [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl).
Defaults to `AutoForwardDiff()` for automatic differentiation, which by default uses
`chunksize = 0`, and thus uses the internal ForwardDiff.jl algorithm for the choice.
To use `FiniteDiff.jl`, the `AutoFiniteDiff()` ADType can be used, which has a keyword argument
`fdtype` with default value `Val{:forward}()`, and alternatives `Val{:central}()` and `Val{:complex}()`.
- `concrete_jac`: Specifies whether a Jacobian should be constructed. Defaults to
`nothing`, which means it will be chosen true/false depending on circumstances
of the solver, such as whether a Krylov subspace method is used for `linsolve`.
- `linsolve`: Any [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl) compatible linear solver.
For example, to use [KLU.jl](https://github.com/JuliaSparse/KLU.jl), specify
`$name(linsolve = KLUFactorization()`).
When `nothing` is passed, uses `DefaultLinearSolver`.
- `precs`: Any [LinearSolve.jl-compatible preconditioner](https://docs.sciml.ai/LinearSolve/stable/basics/Preconditioners/)
can be used as a left or right preconditioner.
Preconditioners are specified by the `Pl,Pr = precs(W,du,u,p,t,newW,Plprev,Prprev,solverdata)`
function where the arguments are defined as:
- `W`: the current Jacobian of the nonlinear system. Specified as either
``I - \\gamma J`` or ``I/\\gamma - J`` depending on the algorithm. This will
commonly be a `WOperator` type defined by OrdinaryDiffEq.jl. It is a lazy
representation of the operator. Users can construct the W-matrix on demand
by calling `convert(AbstractMatrix,W)` to receive an `AbstractMatrix` matching
the `jac_prototype`.
- `du`: the current ODE derivative
- `u`: the current ODE state
- `p`: the ODE parameters
- `t`: the current ODE time
- `newW`: a `Bool` which specifies whether the `W` matrix has been updated since
the last call to `precs`. It is recommended that this is checked to only
update the preconditioner when `newW == true`.
- `Plprev`: the previous `Pl`.
- `Prprev`: the previous `Pr`.
- `solverdata`: Optional extra data the solvers can give to the `precs` function.
Solver-dependent and subject to change.
The return is a tuple `(Pl,Pr)` of the LinearSolve.jl-compatible preconditioners.
To specify one-sided preconditioning, simply return `nothing` for the preconditioner
which is not used. Additionally, `precs` must supply the dispatch:
```julia
Pl, Pr = precs(W, du, u, p, t, ::Nothing, ::Nothing, ::Nothing, solverdata)
```
which is used in the solver setup phase to construct the integrator
type with the preconditioners `(Pl,Pr)`.
The default is `precs=DEFAULT_PRECS` where the default preconditioner function
is defined as:
```julia
DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing
```
""" * extra_keyword_default
keyword_default_description = """
- `chunk_size`: TBD
- `standardtag`: TBD
- `autodiff`: boolean to control if the Jacobian should be computed via AD or not
- `concrete_jac`: function of the form `jac!(J, u, p, t)`
- `diff_type`: TBD
- `linsolve`: custom solver for the inner linear systems
- `precs`: custom preconditioner for the inner linear solver
""" * extra_keyword_description
if with_step_limiter
keyword_default *= "step_limiter! = OrdinaryDiffEq.trivial_limiter!,\n"
keyword_default_description *= "- `step_limiter!`: function of the form `limiter!(u, integrator, p, t)`\n"
end
return generic_solver_docstring(
description, name, "Rosenbrock-Wanner Method. ", references,
keyword_default_description, keyword_default
)
end
include("algorithms.jl")
include("alg_utils.jl")
include("rosenbrock_caches.jl")
include("rosenbrock_tableaus.jl")
include("interp_func.jl")
include("rosenbrock_interpolants.jl")
include("stiff_addsteps.jl")
include("rosenbrock_perform_step.jl")
include("integrator_interface.jl")
import PrecompileTools
import Preferences
PrecompileTools.@compile_workload begin
lorenz = OrdinaryDiffEqCore.lorenz
lorenz_oop = OrdinaryDiffEqCore.lorenz_oop
solver_list = [Rosenbrock23(), Rodas5P()]
prob_list = []
if Preferences.@load_preference("PrecompileDefaultSpecialize", true)
push!(prob_list, ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0)))
push!(prob_list, ODEProblem(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0), Float64[]))
end
if Preferences.@load_preference("PrecompileAutoSpecialize", false)
push!(
prob_list,
ODEProblem{true, SciMLBase.AutoSpecialize}(
lorenz, [1.0; 0.0; 0.0],
(0.0, 1.0)
)
)
push!(
prob_list,
ODEProblem{true, SciMLBase.AutoSpecialize}(
lorenz, [1.0; 0.0; 0.0],
(0.0, 1.0), Float64[]
)
)
end
if Preferences.@load_preference("PrecompileFunctionWrapperSpecialize", false)
push!(
prob_list,
ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(
lorenz, [1.0; 0.0; 0.0],
(0.0, 1.0)
)
)
push!(
prob_list,
ODEProblem{true, SciMLBase.FunctionWrapperSpecialize}(
lorenz, [1.0; 0.0; 0.0],
(0.0, 1.0), Float64[]
)
)
end
if Preferences.@load_preference("PrecompileNoSpecialize", false)
push!(
prob_list,
ODEProblem{true, SciMLBase.NoSpecialize}(lorenz, [1.0; 0.0; 0.0], (0.0, 1.0))
)
push!(
prob_list,
ODEProblem{true, SciMLBase.NoSpecialize}(
lorenz, [1.0; 0.0; 0.0], (0.0, 1.0),
Float64[]
)
)
end
for prob in prob_list, solver in solver_list
solve(prob, solver)(5.0)
end
prob_list = nothing
solver_list = nothing
end
export Rosenbrock23, Rosenbrock32, RosShamp4, Veldd4, Velds4, GRK4T, GRK4A,
Ros4LStab, ROS3P, Rodas3, Rodas23W, Rodas3P, Rodas4, Rodas42, Rodas4P, Rodas4P2,
Rodas5, Rodas5P, Rodas5Pe, Rodas5Pr, Rodas6P, HybridExplicitImplicitRK, Tsit5DA,
RosenbrockW6S4OS, ROS34PW1a, ROS34PW1b, ROS34PW2, ROS34PW3, ROS34PRw, ROS3PRL,
ROS3PRL2, ROK4a,
ROS2, ROS2PR, ROS2S, ROS3, ROS3PR, Scholz4_7
end