You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,11 @@
1
1
# v3.0
2
2
3
-
Complete rewrite of the package. The DynamicalSystems.jl v3 changelog summarizes the highlights. Here we will try to list all changes, but it will be difficult to provide a changelog given that everything was changed.
3
+
Complete rewrite of the package. The DynamicalSystems.jl v3 changelog summarizes the highlights. Here we will list all changes to _this specific package_.
4
+
5
+
## Majorly Breaking
6
+
- The `Discrete/ContinuousDynamicalSystem` constructors no longer accept a Jacobian. Use the dedicated `TangentDynamicalSystem` for something that represents the tangent space and can be given to downstream functions such as `lyapunovspectrum`. As a result, none of the predefined systems come with a hand coded Jacobian. The function is still available for manual use nevertheless.
7
+
- The keyword `diffeq` does not exist anymore and is not given to any downstream functions such as `lyapunovspectrum`. The only struct that cares about DifferentialEquations.jl arguments is `CoupledODEs` so it is the only one that accepts `diffeq` keyword.
8
+
-`trajectory` now returns the actual trajectory _and_ the time vector: `X, t = trajectory(ds, ...)`.
4
9
5
10
## Enhancements
6
11
-`DynamicalSystem` now defines a proper, well-thought-out interface that is implemented from all its concrete subtypes. See its docstring for details.
@@ -16,10 +21,6 @@ Complete rewrite of the package. The DynamicalSystems.jl v3 changelog summarizes
16
21
-`stroboscopicmap -> StroboscopicMap`
17
22
-`poincaremap -> PoincareMap`
18
23
19
-
## Majorly Breaking
20
-
- The `Discrete/ContinuousDynamicalSystem` constructors no longer accept a Jacobian. Use the dedicated `TangentDynamicalSystem` for something that represents the tangent space and can be given to downstream functions such as `lyapunovspectrum`. As a result, none of the predefined systems come with a hand coded Jacobian. The function is still available for manual use nevertheless.
21
-
- The keyword `diffeq` does not exist anymore and is not given to any downstream functions such as `lyapunovspectrum`. The only struct that cares about DifferentialEquations.jl arguments is `CoupledODEs` so it is the only one that accepts `diffeq` keyword.
22
-
-`trajectory` now returns the actual trajectory _and_ the time vector: `X, t = trajectory(ds, ...)`
23
24
24
25
# v2.9
25
26
- All code related to the poincare map integrator have been moved here from ChaosTools.jl.
Copy file name to clipboardExpand all lines: docs/src/index.md
+196-8Lines changed: 196 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -59,6 +59,15 @@ current_crossing_time
59
59
poincaresos
60
60
```
61
61
62
+
## `TangentDynamicalSystem`
63
+
```@docs
64
+
CoreDynamicalSystem
65
+
TangentDynamicalSystem
66
+
current_deviations
67
+
set_deviations!
68
+
orthonormal
69
+
```
70
+
62
71
## `ProjectedDynamicalSystem`
63
72
```@docs
64
73
ProjectedDynamicalSystem
@@ -71,21 +80,17 @@ initial_states
71
80
current_states
72
81
```
73
82
74
-
## `TangentDynamicalSystem`
83
+
## `ArbitrarySteppable`
75
84
```@docs
76
-
CoreDynamicalSystem
77
-
TangentDynamicalSystem
78
-
current_deviations
79
-
set_deviations!
80
-
orthonormal
85
+
ArbitrarySteppable
81
86
```
82
87
83
88
## Parallelization
84
89
85
-
Since `DynamicalSystem`s are mutable, one needs to copy them before parallelizing, to avoid having to deal with complicated race conditions etc. The simplest way is with `deepcopy`. Here is an example block that shows how to parallelize calling some expensive function (e.g., calculating the Lyapunov exponent) over a parameter range:
90
+
Since `DynamicalSystem`s are mutable, one needs to copy them before parallelizing, to avoid having to deal with complicated race conditions etc. The simplest way is with `deepcopy`. Here is an example block that shows how to parallelize calling some expensive function (e.g., calculating the Lyapunov exponent) over a parameter range using `Threads`:
86
91
87
92
```julia
88
-
ds =DynamicalSystem(f, u, p)
93
+
ds =DynamicalSystem(f, u, p)# some concrete implementation
89
94
parameters =0:0.01:1
90
95
outputs =zeros(length(parameters))
91
96
@@ -99,3 +104,186 @@ Threads.@threads for i in eachindex(parameters)
99
104
outputs[i] =expensive_function(system, args...)
100
105
end
101
106
```
107
+
108
+
## Examples
109
+
110
+
### Iterated map, out of place
111
+
112
+
Let's make the [Hénon map](https://en.wikipedia.org/wiki/H%C3%A9non_map) as an example.
This is an advanced example of making an in-place implementation of coupled [standard maps](https://en.wikipedia.org/wiki/Standard_map). It will utilize a handcoded Jacobian, a sparse matrix for the Jacobinan, a default initial Jacobian matrix, as well as function-like-objects as the dynamic rule.
167
+
168
+
Coupled standard maps is a deterministic iterated map that can have arbitrary number of equations of motion, since you can couple `N` standard maps which are 2D maps, like so:
We will now use this struct to define a [function-like-object](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects), a Type that also acts as a function
211
+
212
+
```@example MAIN
213
+
function (f::CoupledStandardMaps{N})(xnew::AbstractVector, x, p, n) where {N}
We will use *the same*`struct` to create a function for the Jacobian:
229
+
230
+
```@example MAIN
231
+
function (f::CoupledStandardMaps{M})(
232
+
J::AbstractMatrix, x, p, n) where {M}
233
+
234
+
ks, Γ = p
235
+
# x[i] ≡ θᵢ
236
+
# x[[idxsp1[i]]] ≡ θᵢ+₁
237
+
# x[[idxsm1[i]]] ≡ θᵢ-₁
238
+
@inbounds for i in f.idxs
239
+
cosθ = cos(x[i])
240
+
cosθp= cos(x[f.idxsp1[i]] - x[i])
241
+
cosθm= cos(x[f.idxsm1[i]] - x[i])
242
+
J[i+M, i] = ks[i]*cosθ + Γ*(cosθp + cosθm)
243
+
J[i+M, f.idxsm1[i]] = - Γ*cosθm
244
+
J[i+M, f.idxsp1[i]] = - Γ*cosθp
245
+
J[i, i] = 1 + J[i+M, i]
246
+
J[i, f.idxsm1[i]] = J[i+M, f.idxsm1[i]]
247
+
J[i, f.idxsp1[i]] = J[i+M, f.idxsp1[i]]
248
+
end
249
+
return nothing
250
+
end
251
+
```
252
+
253
+
This is possible because the system state is a `Vector` while the Jacobian is a `Matrix`, so multiple dispatch can differentiate between the two.
254
+
255
+
Notice in addition, that the Jacobian function accesses *only half the elements of the matrix*. This is intentional, and takes advantage of the fact that the
256
+
other half is constant. We can leverage this further, by making the Jacobian a sparse matrix. Because the `DynamicalSystem` constructors allow us to give in a pre-initialized Jacobian matrix, we take advantage of that and create:
257
+
```@example MAIN
258
+
using SparseArrays
259
+
J = zeros(eltype(u0), 2M, 2M)
260
+
# Set ∂/∂p entries (they are eye(M,M))
261
+
# And they dont change they are constants
262
+
for i in idxs
263
+
J[i, i+M] = 1
264
+
J[i+M, i+M] = 1
265
+
end
266
+
sparseJ = sparse(J)
267
+
268
+
csm(sparseJ, u0, p, 0) # apply Jacobian to initial state
269
+
sparseJ
270
+
```
271
+
272
+
Now we are ready to create our dynamical system
273
+
274
+
```@example MAIN
275
+
ds = DeterministicIteratedMap(csm, u0, p)
276
+
```
277
+
278
+
Of course, the reason we went through all this trouble was to make a [`TangentDynamicalSystem`](@ref), that can actually use the Jacobian function.
279
+
280
+
```@example MAIN
281
+
tands = TangentDynamicalSystem(ds; J = csm, J0 = sparseJ, k = M)
282
+
```
283
+
284
+
```@example MAIN
285
+
step!(tands, 5)
286
+
current_deviations(tands)
287
+
```
288
+
289
+
(the deviation vectors will increase in magnitude rapidly because the dynamical system is chaotic)
0 commit comments