Skip to content

Commit a7634b7

Browse files
authored
Fixed incorrect λ of fixed points for continuous time (#340)
* fix fixed point being incorrect all due to the evolution not being exact... wow! * changelog * Update src/chaosdetection/lyapunovs/lyapunov.jl
1 parent a9b834c commit a7634b7

File tree

4 files changed

+14
-7
lines changed

4 files changed

+14
-7
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# main
22

3+
# v3.3.1
4+
5+
After 7 years, we only now realized that `lyapunov` gave incorrect results for fixed points of continuous time systems. We've now fixed that. Unfortunately this decreases the computational performance of the function overall, but correctness is more important.
6+
37
# v3.3
48

59
- Updated IntervalRootFinding.jl to v0.6 which [has breaking changes](https://github.com/JuliaIntervals/IntervalRootFinding.jl/releases/tag/v0.6.0) regarding

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ChaosTools"
22
uuid = "608a59af-f2a3-5ad4-90b4-758bdf3122a7"
33
repo = "https://github.com/JuliaDynamics/ChaosTools.jl.git"
4-
version = "3.3.0"
4+
version = "3.3.1"
55

66
[deps]
77
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"

src/chaosdetection/lyapunovs/lyapunov.jl

+7-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ See also [`lyapunovspectrum`](@ref), [`local_growth_rates`](@ref).
2121
* `d0_lower = 1e-3*d0`: Lower distance threshold for rescaling.
2222
* `d0_upper = 1e+3*d0`: Upper distance threshold for rescaling.
2323
* `Δt = 1`: Time of evolution between each check rescaling of distance.
24-
For continuous time systems this is approximate.
2524
* `inittest = (u1, d0) -> u1 .+ d0/sqrt(length(u1))`: A function that given `(u1, d0)`
2625
initializes the test state with distance `d0` from the given state `u1`
2726
(`D` is the dimension of the system). This function can be used when you want to avoid
@@ -31,7 +30,7 @@ See also [`lyapunovspectrum`](@ref), [`local_growth_rates`](@ref).
3130
## Description
3231
3332
Two neighboring trajectories with initial distance `d0` are evolved in time.
34-
At time ``t_i`` if their distance ``d(t_i)`` either exceeds the `d0_upper`,
33+
At time ``t_i = t_{i-1} + \\Delta t``, if their distance ``d(t_i)`` either exceeds the `d0_upper`,
3534
or is lower than `d0_lower`, the test trajectory is rescaled back to having distance
3635
`d0` from the reference one, while the rescaling keeps the difference vector along the maximal
3736
expansion/contraction direction: `` u_2 \\to u_1+(u_2−u_1)/(d(t_i)/d_0)``.
@@ -47,6 +46,10 @@ The maximum Lyapunov exponent is the average of the time-local Lyapunov exponent
4746
This function simply initializes a [`ParallelDynamicalSystem`](@ref) and calls
4847
the method below.
4948
49+
The reason we only conditionally rescale the neighboring trajectories is computational:
50+
the averaging will give correct result overall if the trajectories
51+
never diverge or converge (i.e., for periodic orbits).
52+
5053
[^Benettin1976]: G. Benettin *et al.*, Phys. Rev. A **14**, pp 2338 (1976)
5154
"""
5255
function lyapunov(ds::DynamicalSystem, T;
@@ -102,15 +105,15 @@ function lyapunov(pds::ParallelDynamicalSystem, T;
102105
end
103106
# evolve until rescaling
104107
while d0_lower d d0_upper
105-
step!(pds, Δt)
108+
step!(pds, Δt, true)
106109
d = λdist(pds)
107110
current_time(pds) t0 + T && break
111+
ProgressMeter.update!(progress, round(Int, current_time(pds)-t0))
108112
end
109113
# local lyapunov exponent is the relative distance of the trajectories
110114
a = d/d0
111115
λ += log(a)
112116
λrescale!(pds, a)
113-
ProgressMeter.update!(progress, round(Int, current_time(pds)))
114117
end
115118
# Do final rescale, in case no other happened
116119
d = λdist(pds)

test/chaosdetection/lyapunovs.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ end
5151
@testset "Negative λ, continuous" begin
5252
f(u, p, t) = -0.9u
5353
ds = ContinuousDynamicalSystem(f, rand(SVector{3}), nothing)
54-
λ1 = lyapunov(ds, 1000)
55-
@test λ1 < 0
54+
λ1 = lyapunov(ds, 10000)
55+
@test λ1 -0.9 atol = 1e-2 rtol = 1e-2
5656

5757
@testset "Lorenz stable" begin
5858
function lorenz_rule(u, p, t)

0 commit comments

Comments
 (0)