From fbf962d650a4e7f94590e49eb55f30dbdffe6f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 26 Apr 2024 23:00:38 +0200 Subject: [PATCH 01/39] just ideas for relaxation --- src/ideas_for_relaxation.jl | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/ideas_for_relaxation.jl diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl new file mode 100644 index 0000000000..ca34f26be8 --- /dev/null +++ b/src/ideas_for_relaxation.jl @@ -0,0 +1,66 @@ +# New structure + +abstract type PerformStepUpdate end + +struct Relaxation{OPT, INV} <: PerformStepUpdate + opt::OPT + inv::INV +end + +function (r::Relaxtion)(integrator, integrator.cache) + + γmin = integrator.dtmin / integrator.dt + γmax = integrator.dtmax / integrator.dt + + ## need to define or use a method find root with three main arguments : + # - a method to minimize + # - the function to minimize + # - interval where we look for + γ_opt = minimize(r.opt, γ -> norm(γ*integrator.dt*(integrator.u_propose-integrator.uprev)) + integrator.uprev, [γmin, γmax]) + + integrator.dt_changed = integrator.dt * γ_opt + integrator_dt_has_changed_in_performstep = true +end + + + +# In the solve function +while integrator.tdir * integrator.t < first(integrator.opts.tstops) + loopheader!(integrator) + if integrator.do_error_check && check_error!(integrator) != ReturnCode.Success + return integrator.sol + end + if isInTheNewSyntax(alg) + perform_step2!(integrator, integrator.cache) + else + perform_step!(integrator, integrator.cache) + end + loopfooter!(integrator) + if isempty(integrator.opts.tstops) + break + end +end + +# Change the perform_step function +function perform_step2!(integrator, integrator.cache, method) + integrator_dt_has_changed_in_performstep = false + + # Computations will really only contain the mathematical scheme + computations!(integrator, integrator.cache) + + user_update!(integrator, integrator.cache, method) + + if integrator_dt_has_changed_in_performstep + #check dt in [dtmin, dtmax] and no conflic with tstop + end + + # Recording will contain all update we need to do into the integrator + recording!(integrator) +end + +function user_update!(integrator, integrator.cache, method::PerformStepUpdate) + + +end + + From dc25f218df9dbe9e4c733357838dcf2bfb1d0bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 27 Apr 2024 00:16:37 +0200 Subject: [PATCH 02/39] Update ideas_for_relaxation.jl --- src/ideas_for_relaxation.jl | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl index ca34f26be8..1127748af5 100644 --- a/src/ideas_for_relaxation.jl +++ b/src/ideas_for_relaxation.jl @@ -19,7 +19,7 @@ function (r::Relaxtion)(integrator, integrator.cache) γ_opt = minimize(r.opt, γ -> norm(γ*integrator.dt*(integrator.u_propose-integrator.uprev)) + integrator.uprev, [γmin, γmax]) integrator.dt_changed = integrator.dt * γ_opt - integrator_dt_has_changed_in_performstep = true + end @@ -44,7 +44,7 @@ end # Change the perform_step function function perform_step2!(integrator, integrator.cache, method) integrator_dt_has_changed_in_performstep = false - + # Computations will really only contain the mathematical scheme computations!(integrator, integrator.cache) @@ -52,8 +52,11 @@ function perform_step2!(integrator, integrator.cache, method) if integrator_dt_has_changed_in_performstep #check dt in [dtmin, dtmax] and no conflic with tstop + else if integrator.dt_changed != zero(integrator.dt_changed) + # print error end - + integrator_dt_has_changed_in_performstep = true + # Recording will contain all update we need to do into the integrator recording!(integrator) end @@ -63,4 +66,17 @@ function user_update!(integrator, integrator.cache, method::PerformStepUpdate) end +function computations!(integrator, integrator.cache) + #= This fonction made all computations of the scheme + + =# +end + + +function recording!() + #= This fonction aims at containing all the informations we want to update/store in + the integrator + + =# +end From 575826addaded730cf2e887df3af48478a2276e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 27 Apr 2024 23:47:20 +0200 Subject: [PATCH 03/39] Update ideas_for_relaxation.jl --- src/ideas_for_relaxation.jl | 131 +++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 40 deletions(-) diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl index 1127748af5..917c5f6bf0 100644 --- a/src/ideas_for_relaxation.jl +++ b/src/ideas_for_relaxation.jl @@ -1,82 +1,133 @@ -# New structure +#= Hi. I come back with a suggestion regarding the discussion in the issue about the relaxation implementantation in code. -abstract type PerformStepUpdate end +It seems that relaxation need to be perform during perform_step! and lead to change of the timestep Δt. -struct Relaxation{OPT, INV} <: PerformStepUpdate - opt::OPT - inv::INV -end +Ranocha suggested in the issue the possibility to use Callback. +[ dire pourquoi pas satisfaisant et proposer mon approche] -function (r::Relaxtion)(integrator, integrator.cache) +New variables stored in the integrator : +- u_propose : like dt_propose, we update in the scheme u_propose instead of u and then if +- dt_has_changed : +=# - γmin = integrator.dtmin / integrator.dt - γmax = integrator.dtmax / integrator.dt - ## need to define or use a method find root with three main arguments : - # - a method to minimize - # - the function to minimize - # - interval where we look for - γ_opt = minimize(r.opt, γ -> norm(γ*integrator.dt*(integrator.u_propose-integrator.uprev)) + integrator.uprev, [γmin, γmax]) +#= Modification of the perform_step function into three part: + - computations + - modif_step + - finalize_step + Their role is described below +=# +function perform_step2!(integrator, cache) - integrator.dt_changed = integrator.dt * γ_opt - -end + # Variable to now if dt has changed during perform_step + integrator.dt_has_changed_in_performstep = false + + # computations! will only contain the mathematical scheme + # i.e the computations of the u(t+dt) + # the result is store not in integrator.u but integrator.u_propose + computations!(integrator, cache) + # modif_step! enables to modify the step like when we want to perform a relaxation + # for this we give a new struture that can be defined either by us for already known + # modification we want to do or by a user (see below) + modif_step!(integrator, cache, integrator.modif) + + # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal + # and register integrator.u + finalize_step!(integrator) +end -# In the solve function +# To not break all the code we can just add a function to know if the algorithms are +# written with the new form of perform_step! or not. while integrator.tdir * integrator.t < first(integrator.opts.tstops) loopheader!(integrator) if integrator.do_error_check && check_error!(integrator) != ReturnCode.Success return integrator.sol end - if isInTheNewSyntax(alg) + + # This is just to not break all the package + if isInTheNewFrameWork(integrator.alg) + # The new performstep! perform_step2!(integrator, integrator.cache) else + # The already existing perform_step! perform_step!(integrator, integrator.cache) end + loopfooter!(integrator) if isempty(integrator.opts.tstops) break end end -# Change the perform_step function -function perform_step2!(integrator, integrator.cache, method) - integrator_dt_has_changed_in_performstep = false - # Computations will really only contain the mathematical scheme - computations!(integrator, integrator.cache) +# modif_step! will look like : - user_update!(integrator, integrator.cache, method) +modif_step!(integrator, cache, ::Nothing) = nothing + +function modif_step!(integrator, cache, modif) + + # Perform the modifications + modif(integrator, cache) + # Here we check the validity of chaging dt if it has changed + # if it is valid integrator.changed_valid will be true, if not it will be false + integrator.changed_valid = true if integrator_dt_has_changed_in_performstep - #check dt in [dtmin, dtmax] and no conflic with tstop + # check dt in [dtmin, dtmax] + # replace dt by tstops-t if t+dt ≈ tstops + # surely other things + if integrator.changed_valid + integrator.u_propose = integrator.u_changed + integrator.dt = integrator.dt_changed + else + # print error or warning + end else if integrator.dt_changed != zero(integrator.dt_changed) # print error end - integrator_dt_has_changed_in_performstep = true - - # Recording will contain all update we need to do into the integrator - recording!(integrator) -end -function user_update!(integrator, integrator.cache, method::PerformStepUpdate) +end +###### +# The example of a modification will be like the relaxation : +struct Relaxation{OPT, INV} + opt::OPT + inv::INV end -function computations!(integrator, integrator.cache) - #= This fonction made all computations of the scheme +# Here is the modif function for relaxation +function (r::Relaxtion)(integrator, cache) + # We fix here the bounds of interval where we are going to look for the relaxation + # and taking accound the bounds [dtmin, dtmax] and the presence of tstops + γmin = integrator.dtmin / integrator.dt + γmax = min(integrator.dtmax / first(integrator.opts.tstops)) / integrator.dt + + S_u = integrator.dt*(integrator.u_propose-integrator.uprev) + ## need to define or use a method "minimize" with three main arguments : + # - a method to minimize + # - the function to minimize + # - interval where we look for + # - starting point (fix to 1) for the minimizing method + γ_opt = minimize( r.opt, + γ -> norm(r.inv(γ*S_u + integrator.uprev) - r.inv(integrator.uprev)), + [γmin, γmax], + 1.0) + # new dt + integrator.dt_changed = integrator.dt * γ_opt + integrator.dt_has_changed = true - =# + # update u + integrator.u_changed = integrator.uprev + γ_opt*S_u end -function recording!() - #= This fonction aims at containing all the informations we want to update/store in - the integrator +## example of a code + + + + - =# -end From cdb53c93abcc6aa2cce08a7fb951c8b8e20f8db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 28 Apr 2024 10:43:51 +0200 Subject: [PATCH 04/39] Update ideas_for_relaxation.jl --- src/ideas_for_relaxation.jl | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl index 917c5f6bf0..0dc1ecc2c5 100644 --- a/src/ideas_for_relaxation.jl +++ b/src/ideas_for_relaxation.jl @@ -1,25 +1,24 @@ -#= Hi. I come back with a suggestion regarding the discussion in the issue about the relaxation implementantation in code. +#= Hi. I come back with a suggestion regarding the discussion in the issue about implementing relaxation in code. + +Hendrick suggested in the issue the possibility to use Callback but it seems to be not really convenient as callback are handled +after accepting the state, storing t in tprev etc. -It seems that relaxation need to be perform during perform_step! and lead to change of the timestep Δt. +I may have another approach which is based on the splitting of perform_step! into several functions. +I do not know if such a thing has already been disccused or are even conceivable as it lead to a notable change in the structure of the code. +In any case, I put below a sketch of what I have in mind. -Ranocha suggested in the issue the possibility to use Callback. -[ dire pourquoi pas satisfaisant et proposer mon approche] - -New variables stored in the integrator : -- u_propose : like dt_propose, we update in the scheme u_propose instead of u and then if -- dt_has_changed : +Please let me know what you think of such changes. =# - #= Modification of the perform_step function into three part: - computations - modif_step - finalize_step Their role is described below =# -function perform_step2!(integrator, cache) +function perform_stepNEW!(integrator, cache) - # Variable to now if dt has changed during perform_step + # Variable to know if dt has changed during perform_step integrator.dt_has_changed_in_performstep = false # computations! will only contain the mathematical scheme @@ -34,7 +33,7 @@ function perform_step2!(integrator, cache) # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal # and register integrator.u - finalize_step!(integrator) + finalize_step!(integrator, cache) end @@ -49,7 +48,7 @@ while integrator.tdir * integrator.t < first(integrator.opts.tstops) # This is just to not break all the package if isInTheNewFrameWork(integrator.alg) # The new performstep! - perform_step2!(integrator, integrator.cache) + perform_stepNEW!(integrator, integrator.cache) else # The already existing perform_step! perform_step!(integrator, integrator.cache) @@ -76,7 +75,7 @@ function modif_step!(integrator, cache, modif) integrator.changed_valid = true if integrator_dt_has_changed_in_performstep # check dt in [dtmin, dtmax] - # replace dt by tstops-t if t+dt ≈ tstops + # things related to tstops # surely other things if integrator.changed_valid integrator.u_propose = integrator.u_changed @@ -87,8 +86,6 @@ function modif_step!(integrator, cache, modif) else if integrator.dt_changed != zero(integrator.dt_changed) # print error end - - end ###### @@ -106,14 +103,14 @@ function (r::Relaxtion)(integrator, cache) γmax = min(integrator.dtmax / first(integrator.opts.tstops)) / integrator.dt S_u = integrator.dt*(integrator.u_propose-integrator.uprev) - ## need to define or use a method "minimize" with three main arguments : - # - a method to minimize + ## need to define or use a method "minimize" with foure main arguments : + # - a method of minimization # - the function to minimize # - interval where we look for # - starting point (fix to 1) for the minimizing method γ_opt = minimize( r.opt, - γ -> norm(r.inv(γ*S_u + integrator.uprev) - r.inv(integrator.uprev)), - [γmin, γmax], + γ -> norm(r.inv(γ*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)), + (γmin, γmax), 1.0) # new dt integrator.dt_changed = integrator.dt * γ_opt From 7e2b73ad9ca3772318de14b7ba0a0b3fca6f1c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 28 Apr 2024 11:02:40 +0200 Subject: [PATCH 05/39] Update ideas_for_relaxation.jl --- src/ideas_for_relaxation.jl | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl index 0dc1ecc2c5..73fdf3deda 100644 --- a/src/ideas_for_relaxation.jl +++ b/src/ideas_for_relaxation.jl @@ -1,15 +1,3 @@ -#= Hi. I come back with a suggestion regarding the discussion in the issue about implementing relaxation in code. - -Hendrick suggested in the issue the possibility to use Callback but it seems to be not really convenient as callback are handled -after accepting the state, storing t in tprev etc. - -I may have another approach which is based on the splitting of perform_step! into several functions. -I do not know if such a thing has already been disccused or are even conceivable as it lead to a notable change in the structure of the code. -In any case, I put below a sketch of what I have in mind. - -Please let me know what you think of such changes. -=# - #= Modification of the perform_step function into three part: - computations - modif_step From d0f8a229d6195e03cbc4493356f51a9c62e3bf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:07:16 +0200 Subject: [PATCH 06/39] try_implementation_tsit5_for_relaxation --- src/alg_utils.jl | 1 + src/algorithms/explicit_rk.jl | 13 +++ .../test_for_relaxation_perform_step.jl | 92 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/perform_step/test_for_relaxation_perform_step.jl diff --git a/src/alg_utils.jl b/src/alg_utils.jl index 40a31190a8..6faae500c0 100644 --- a/src/alg_utils.jl +++ b/src/alg_utils.jl @@ -573,6 +573,7 @@ alg_order(alg::OwrenZen4) = 4 alg_order(alg::OwrenZen5) = 5 alg_order(alg::DP5) = 5 alg_order(alg::Tsit5) = 5 +alg_order(alg::Tsit5_for_relaxation) = 5 alg_order(alg::DP8) = 8 alg_order(alg::Vern6) = 6 alg_order(alg::Vern7) = 7 diff --git a/src/algorithms/explicit_rk.jl b/src/algorithms/explicit_rk.jl index 96846d52e5..4e5c99e45f 100644 --- a/src/algorithms/explicit_rk.jl +++ b/src/algorithms/explicit_rk.jl @@ -332,6 +332,19 @@ function Tsit5(stage_limiter!, step_limiter! = trivial_limiter!) Tsit5(stage_limiter!, step_limiter!, False()) end +Base.@kwdef struct Tsit5_for_relaxation{StageLimiter, StepLimiter, Thread} <: + OrdinaryDiffEqAdaptiveAlgorithm +stage_limiter!::StageLimiter = trivial_limiter! +step_limiter!::StepLimiter = trivial_limiter! +thread::Thread = False() +end + +# for backwards compatibility +function Tsit5_for_relaxation(stage_limiter!, step_limiter! = trivial_limiter!) +Tsit5_for_relaxation(stage_limiter!, step_limiter!, False()) +end + + @doc explicit_rk_docstring( "Hairer's 8/5/3 adaption of the Dormand-Prince Runge-Kutta method. (7th order interpolant).", "DP8", diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl new file mode 100644 index 0000000000..80787cccd1 --- /dev/null +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -0,0 +1,92 @@ + +function perform_step!(integrator, cache::Tsit5ConstantCache_for_relaxation, repeat_step = false) + + # Variable to know if dt has changed during perform_step + integrator.dt_has_changed_in_performstep = false + + # computations! will only contain the mathematical scheme + # i.e the computations of the u(t+dt) + # the result is store not in integrator.u but integrator.u_propose + computations!(integrator, cache, repeat_step) + + # modif_step! enables to modify the step like when we want to perform a relaxation + # for this we give a new struture that can be defined either by us for already known + # modification we want to do or by a user (see below) + modif_step!(integrator) + + # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal + # and register integrator.u + finalize_step!(integrator, cache) +end + + +@muladd function computations!(integrator, cache::Tsit5ConstantCache_for_relaxation, repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator + T = constvalue(recursive_unitless_bottom_eltype(u)) + T2 = constvalue(typeof(one(t))) + @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + k1 = integrator.fsalfirst + a = dt * a21 + k2 = f(uprev + a * k1, p, t + c1 * dt) + k3 = f(uprev + dt * (a31 * k1 + a32 * k2), p, t + c2 * dt) + k4 = f(uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3), p, t + c3 * dt) + k5 = f(uprev + dt * (a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4), p, t + c4 * dt) + g6 = uprev + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) + k6 = f(g6, p, t + dt) + u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) + + integrator.k[1] = k1 + integrator.k[2] = k2 + integrator.k[3] = k3 + integrator.k[4] = k4 + integrator.k[5] = k5 + integrator.k[6] = k6 + + integrator.u_propose = u +end + + +function modif_step!(integrator) + + # Perform the modifications + modif(integrator) + + # Here we check the validity of chaging dt if it has changed + # if it is valid integrator.changed_valid will be true, if not it will be false + integrator.changed_valid = true + if integrator_dt_has_changed_in_performstep + # check dt in [dtmin, dtmax] + # things related to tstops + # surely other things + if integrator.changed_valid + integrator.u_propose = integrator.u_changed + integrator.dt = integrator.dt_changed + else + # print error or warning + end + elseif integrator.dt_changed != zero(integrator.dt_changed) + # print error + end +end + + +function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) + @unpack t, dt, uprev, u, u_propose, f, p = integrator + integrator.u = u_propose + integrator.fsallast = f(u_propose, p, t + dt) + k7 = integrator.fsallast + integrator.k[7] = k7 + T = constvalue(recursive_unitless_bottom_eltype(u)) + T2 = constvalue(typeof(one(t))) + @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + if integrator.opts.adaptive + utilde = dt * + (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * k5 + + btilde6 * integrator.k[6] + btilde7 * integrator.k[7]) + atmp = calculate_residuals(utilde, uprev, u_propose, integrator.opts.abstol, + integrator.opts.reltol, integrator.opts.internalnorm, t) + integrator.EEst = integrator.opts.internalnorm(atmp, t) + end + + integrator.stats.nf += 6 +end \ No newline at end of file From 229438fcc2f1bace1a42a3784bab235bebdd00cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:32:40 +0200 Subject: [PATCH 07/39] progress relaxation --- src/caches/low_order_rk_caches.jl | 38 +++++++++++++++++++ .../test_for_relaxation_perform_step.jl | 9 +++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/caches/low_order_rk_caches.jl b/src/caches/low_order_rk_caches.jl index 5cc0120def..30b8478174 100644 --- a/src/caches/low_order_rk_caches.jl +++ b/src/caches/low_order_rk_caches.jl @@ -448,6 +448,44 @@ if isdefined(Base, :Experimental) && isdefined(Base.Experimental, :silence!) Base.Experimental.silence!(Tsit5Cache) end +@cache struct Tsit5Cache_for_relaxation{uType, rateType, uNoUnitsType, StageLimiter, StepLimiter, + Thread} <: OrdinaryDiffEqMutableCache + u::uType + uprev::uType + k1::rateType + k2::rateType + k3::rateType + k4::rateType + k5::rateType + k6::rateType + k7::rateType + utilde::uType + tmp::uType + atmp::uNoUnitsType + stage_limiter!::StageLimiter + step_limiter!::StepLimiter + thread::Thread +end + +function alg_cache(alg::Tsit5_for_relaxation, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} + k1 = zero(rate_prototype) + k2 = zero(rate_prototype) + k3 = zero(rate_prototype) + k4 = zero(rate_prototype) + k5 = zero(rate_prototype) + k6 = zero(rate_prototype) + k7 = zero(rate_prototype) + utilde = zero(u) + atmp = similar(u, uEltypeNoUnits) + recursivefill!(atmp, false) + tmp = zero(u) + Tsit5Cache_for_relaxation(u, uprev, k1, k2, k3, k4, k5, k6, k7, utilde, tmp, atmp, + alg.stage_limiter!, alg.step_limiter!, alg.thread) +end + @cache struct RK46NLCache{uType, rateType, TabType, StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqMutableCache u::uType diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 80787cccd1..4418954920 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -34,14 +34,14 @@ end g6 = uprev + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) k6 = f(g6, p, t + dt) u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) - + k7 = f(u_propose, p, t + dt) integrator.k[1] = k1 integrator.k[2] = k2 integrator.k[3] = k3 integrator.k[4] = k4 integrator.k[5] = k5 integrator.k[6] = k6 - + integrator.k[7] = k7 integrator.u_propose = u end @@ -74,11 +74,12 @@ function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) @unpack t, dt, uprev, u, u_propose, f, p = integrator integrator.u = u_propose integrator.fsallast = f(u_propose, p, t + dt) - k7 = integrator.fsallast - integrator.k[7] = k7 + + # We ask the Tableau again but this might be improve by option to ask only the wanted part of the tableau T = constvalue(recursive_unitless_bottom_eltype(u)) T2 = constvalue(typeof(one(t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + if integrator.opts.adaptive utilde = dt * (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * k5 + From a79615799b522a6a70103cb91a55d6596da4034e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 28 Apr 2024 23:03:23 +0200 Subject: [PATCH 08/39] all implement but failed compilation Modif file : - integrators\type.jl + solve.jl: add u_propose, u_changed, dt_has_changed, dt_changed + initialisation - OrdinaryDiffEq.jl : add file and method - add cache - add a new file for performstep - add alg_order in alg.utils --- src/OrdinaryDiffEq.jl | 3 ++- src/ideas_for_relaxation.jl | 2 +- src/integrators/type.jl | 11 +++++++++-- src/perform_step/test_for_relaxation_perform_step.jl | 8 +++----- src/solve.jl | 6 +++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index e83089e464..8a1c741755 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -212,6 +212,7 @@ include("perform_step/prk_perform_step.jl") include("perform_step/pdirk_perform_step.jl") include("perform_step/dae_perform_step.jl") include("perform_step/qprk_perform_step.jl") +include("perform_step/test_for_relaxation_perform_step.jl") include("dense/generic_dense.jl") include("dense/interpolants.jl") @@ -354,7 +355,7 @@ export FunctionMap, Euler, Heun, Ralston, Midpoint, RK4, ExplicitRK, OwrenZen3, OwrenZen5, BS3, BS5, RK46NL, DP5, Tsit5, DP8, Vern6, Vern7, Vern8, TanYam7, TsitPap8, Vern9, Feagin10, Feagin12, Feagin14, CompositeAlgorithm, Anas5, RKO65, FRK65, PFRK87, - RKM, MSRK5, MSRK6, Stepanov5, SIR54, QPRK98 + RKM, MSRK5, MSRK6, Stepanov5, SIR54, QPRK98, Tsit5_for_relaxation export SSPRK22, SSPRK33, KYKSSPRK42, SSPRK53, SSPRK53_2N1, SSPRK53_2N2, SSPRK53_H, SSPRK63, SSPRK73, SSPRK83, SSPRK43, SSPRK432, diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl index 73fdf3deda..511dbfdf41 100644 --- a/src/ideas_for_relaxation.jl +++ b/src/ideas_for_relaxation.jl @@ -84,7 +84,7 @@ struct Relaxation{OPT, INV} end # Here is the modif function for relaxation -function (r::Relaxtion)(integrator, cache) +function (r::Relaxtion)(integrator) # We fix here the bounds of interval where we are going to look for the relaxation # and taking accound the bounds [dtmin, dtmax] and the presence of tstops γmin = integrator.dtmin / integrator.dt diff --git a/src/integrators/type.jl b/src/integrators/type.jl index a361302f9e..ca1b666637 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -134,6 +134,12 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori stats::SciMLBase.DEStats initializealg::IA differential_vars::DV + + u_propose::uType + u_changed::uType + dt_has_changed::Bool + dt_changed::tType + fsalfirst::FSALType fsallast::FSALType @@ -155,7 +161,8 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori accept_step, isout, reeval_fsal, u_modified, reinitialize, isdae, opts, stats, - initializealg, differential_vars) where {algType, IIP, uType, + initializealg, differential_vars, + u_propose, u_changed, dt_has_changed, dt_changed) where {algType, IIP, uType, duType, tType, pType, eigenType, EEstT, tTypeNoUnits, tdirType, @@ -177,7 +184,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori do_error_check, event_last_time, vector_event_last_time, last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitialize, isdae, - opts, stats, initializealg, differential_vars) # Leave off fsalfirst and last + opts, stats, initializealg, differential_vars, u_propose, u_changed, dt_has_changed, dt_changed) # Leave off fsalfirst and last end end diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 4418954920..6923996283 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -49,23 +49,21 @@ end function modif_step!(integrator) # Perform the modifications - modif(integrator) + #integrator.modif(integrator) # Here we check the validity of chaging dt if it has changed # if it is valid integrator.changed_valid will be true, if not it will be false - integrator.changed_valid = true + changed_valid = true if integrator_dt_has_changed_in_performstep # check dt in [dtmin, dtmax] # things related to tstops # surely other things - if integrator.changed_valid + if changed_valid integrator.u_propose = integrator.u_changed integrator.dt = integrator.dt_changed else # print error or warning end - elseif integrator.dt_changed != zero(integrator.dt_changed) - # print error end end diff --git a/src/solve.jl b/src/solve.jl index e29136450e..d11db694cd 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -160,6 +160,8 @@ function DiffEqBase.__init( else u = recursivecopy(prob.u0) end + u_propose = recursivecopy(u) + u_changed = recursivecopy(u) if _alg isa DAEAlgorithm if alias_du0 @@ -443,6 +445,8 @@ function DiffEqBase.__init( tprev = t dtcache = tType(dt) dtpropose = tType(dt) + dt_has_changed = false + dt_changed = tType(dt) iter = 0 kshortsize = 0 reeval_fsal = false @@ -490,7 +494,7 @@ function DiffEqBase.__init( last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitiailize, isdae, - opts, stats, initializealg, differential_vars) + opts, stats, initializealg, differential_vars, u_propose, u_changed, dt_has_changed, dt_changed) if initialize_integrator if isdae || SciMLBase.has_initializeprob(prob.f) From b3617ad58eefe272747f9a2abb100ec18bab24bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:56:15 +0200 Subject: [PATCH 09/39] compilation works but not tests --- src/caches/low_order_rk_caches.jl | 7 +++++ .../test_for_relaxation_perform_step.jl | 17 ++++++++++- src/tableaus/low_order_rk_tableaus.jl | 1 + test/regression/regression_tests.jl | 29 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 test/regression/regression_tests.jl diff --git a/src/caches/low_order_rk_caches.jl b/src/caches/low_order_rk_caches.jl index 30b8478174..bb9ef7df1f 100644 --- a/src/caches/low_order_rk_caches.jl +++ b/src/caches/low_order_rk_caches.jl @@ -585,6 +585,13 @@ function alg_cache(alg::Tsit5, u, rate_prototype, ::Type{uEltypeNoUnits}, Tsit5ConstantCache() end +function alg_cache(alg::Tsit5_for_relaxation, u, rate_prototype, ::Type{uEltypeNoUnits}, + ::Type{uBottomEltypeNoUnits}, ::Type{tTypeNoUnits}, uprev, uprev2, f, t, + dt, reltol, p, calck, + ::Val{false}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} +Tsit5ConstantCache_for_relaxation() +end + @cache struct DP5Cache{uType, rateType, uNoUnitsType, StageLimiter, StepLimiter, Thread} <: OrdinaryDiffEqMutableCache u::uType diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 6923996283..eaf8271ff9 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -1,8 +1,23 @@ +function initialize!(integrator, cache::Tsit5ConstantCache_for_relaxation) + integrator.kshortsize = 7 + integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) + integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + integrator.stats.nf += 1 + + # Avoid undefined entries if k is an array of arrays + integrator.fsallast = zero(integrator.fsalfirst) + integrator.k[1] = integrator.fsalfirst + @inbounds for i in 2:(integrator.kshortsize - 1) + integrator.k[i] = zero(integrator.fsalfirst) + end + integrator.k[integrator.kshortsize] = integrator.fsallast +end + function perform_step!(integrator, cache::Tsit5ConstantCache_for_relaxation, repeat_step = false) # Variable to know if dt has changed during perform_step - integrator.dt_has_changed_in_performstep = false + integrator.dt_has_changed = false # computations! will only contain the mathematical scheme # i.e the computations of the u(t+dt) diff --git a/src/tableaus/low_order_rk_tableaus.jl b/src/tableaus/low_order_rk_tableaus.jl index 5883bb6f63..56765db150 100644 --- a/src/tableaus/low_order_rk_tableaus.jl +++ b/src/tableaus/low_order_rk_tableaus.jl @@ -499,6 +499,7 @@ function OwrenZen5ConstantCache(T, T2) end struct Tsit5ConstantCache <: OrdinaryDiffEqConstantCache end +struct Tsit5ConstantCache_for_relaxation <: OrdinaryDiffEqConstantCache end struct Tsit5ConstantCacheActual{T, T2} c1::T2 c2::T2 diff --git a/test/regression/regression_tests.jl b/test/regression/regression_tests.jl new file mode 100644 index 0000000000..188473fa8c --- /dev/null +++ b/test/regression/regression_tests.jl @@ -0,0 +1,29 @@ +using OrdinaryDiffEq, DiffEqDevTools, Test + +import ODEProblemLibrary: prob_ode_linear, + prob_ode_2Dlinear + + +probnum = prob_ode_linear +prob = prob_ode_2Dlinear + +dts = (1 / 2) .^ (7:-1:4) +testTol = 0.2 + +### Tsit5() + +println("Tsit5") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +sim = test_convergence(dts, prob, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 + +### Tsit5 with relaxation + +println("Tsit5 with relaxation") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 \ No newline at end of file From ef5238b8218fcea688ff3ddbd42505670b6a64bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:50:19 +0200 Subject: [PATCH 10/39] code change structure works --- src/perform_step/test_for_relaxation_perform_step.jl | 4 ++-- test/regression/regression_tests.jl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index eaf8271ff9..d16206104d 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -49,7 +49,7 @@ end g6 = uprev + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) k6 = f(g6, p, t + dt) u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) - k7 = f(u_propose, p, t + dt) + k7 = f(u, p, t + dt) integrator.k[1] = k1 integrator.k[2] = k2 integrator.k[3] = k3 @@ -69,7 +69,7 @@ function modif_step!(integrator) # Here we check the validity of chaging dt if it has changed # if it is valid integrator.changed_valid will be true, if not it will be false changed_valid = true - if integrator_dt_has_changed_in_performstep + if integrator.dt_has_changed # check dt in [dtmin, dtmax] # things related to tstops # surely other things diff --git a/test/regression/regression_tests.jl b/test/regression/regression_tests.jl index 188473fa8c..58d26d7647 100644 --- a/test/regression/regression_tests.jl +++ b/test/regression/regression_tests.jl @@ -25,5 +25,5 @@ println("Tsit5 with relaxation") dts = (1 / 2) .^ (7:-1:3) sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -sim = test_convergence(dts, prob, Tsit5_for_relaxation()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 \ No newline at end of file +#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 \ No newline at end of file From 4323a6804692dfb0e44d60e2f6795828ca715950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:50:53 +0200 Subject: [PATCH 11/39] fix mistakes --- src/perform_step/test_for_relaxation_perform_step.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index d16206104d..1cb91dc4b2 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -95,7 +95,7 @@ function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) if integrator.opts.adaptive utilde = dt * - (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * k5 + + (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + btilde6 * integrator.k[6] + btilde7 * integrator.k[7]) atmp = calculate_residuals(utilde, uprev, u_propose, integrator.opts.abstol, integrator.opts.reltol, integrator.opts.internalnorm, t) From 12e4a7add2f37e52d5a100ff944cc120f22582ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Wed, 1 May 2024 14:18:04 +0200 Subject: [PATCH 12/39] improvement for regression --- src/integrators/type.jl | 3 +- .../test_for_relaxation_perform_step.jl | 61 +++++++------ src/solve.jl | 6 +- test/regression/regression_tests.jl | 86 ++++++++++++++++++- 4 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/integrators/type.jl b/src/integrators/type.jl index ca1b666637..ed88a45e83 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -1,6 +1,6 @@ mutable struct DEOptions{absType, relType, QT, tType, Controller, F1, F2, F3, F4, F5, F6, F7, tstopsType, discType, ECType, SType, MI, tcache, savecache, - disccache} + disccache, MT} maxiters::MI save_everystep::Bool adaptive::Bool @@ -46,6 +46,7 @@ mutable struct DEOptions{absType, relType, QT, tType, Controller, F1, F2, F3, F4 force_dtmin::Bool advance_to_tstop::Bool stop_at_next_tstop::Bool + modif::MT end TruncatedStacktraces.@truncate_stacktrace DEOptions diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 1cb91dc4b2..cc1b7a1742 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -1,4 +1,4 @@ -function initialize!(integrator, cache::Tsit5ConstantCache_for_relaxation) +function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) integrator.kshortsize = 7 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal @@ -35,7 +35,7 @@ function perform_step!(integrator, cache::Tsit5ConstantCache_for_relaxation, rep end -@muladd function computations!(integrator, cache::Tsit5ConstantCache_for_relaxation, repeat_step = false) +@muladd function computations!(integrator, ::Tsit5ConstantCache_for_relaxation, repeat_step = false) @unpack t, dt, uprev, u, f, p = integrator T = constvalue(recursive_unitless_bottom_eltype(u)) T2 = constvalue(typeof(one(t))) @@ -58,49 +58,46 @@ end integrator.k[6] = k6 integrator.k[7] = k7 integrator.u_propose = u + + if integrator.opts.adaptive + utilde = dt * + (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + + btilde6 * integrator.k[6] + btilde7 * integrator.k[7]) + atmp = calculate_residuals(utilde, uprev, u, integrator.opts.abstol, + integrator.opts.reltol, integrator.opts.internalnorm, t) + integrator.EEst = integrator.opts.internalnorm(atmp, t) + end end function modif_step!(integrator) # Perform the modifications - #integrator.modif(integrator) - - # Here we check the validity of chaging dt if it has changed - # if it is valid integrator.changed_valid will be true, if not it will be false - changed_valid = true - if integrator.dt_has_changed - # check dt in [dtmin, dtmax] - # things related to tstops - # surely other things - if changed_valid - integrator.u_propose = integrator.u_changed - integrator.dt = integrator.dt_changed - else - # print error or warning + if !(integrator.opts.modif isa Nothing) + integrator.opts.modif(integrator) + + # Here we check the validity of chaging dt if it has changed + # if it is valid integrator.changed_valid will be true, if not it will be false + changed_valid = true + if integrator.dt_has_changed + # check dt in [dtmin, dtmax] + # things related to tstops + # surely other things + if changed_valid + integrator.u_propose = integrator.u_changed + integrator.dt = integrator.dt_changed + else + # print error or warning + end end end end function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) - @unpack t, dt, uprev, u, u_propose, f, p = integrator + @unpack t, dt, uprev, u_propose, f, p = integrator integrator.u = u_propose integrator.fsallast = f(u_propose, p, t + dt) - # We ask the Tableau again but this might be improve by option to ask only the wanted part of the tableau - T = constvalue(recursive_unitless_bottom_eltype(u)) - T2 = constvalue(typeof(one(t))) - @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 - - if integrator.opts.adaptive - utilde = dt * - (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + - btilde6 * integrator.k[6] + btilde7 * integrator.k[7]) - atmp = calculate_residuals(utilde, uprev, u_propose, integrator.opts.abstol, - integrator.opts.reltol, integrator.opts.internalnorm, t) - integrator.EEst = integrator.opts.internalnorm(atmp, t) - end - - integrator.stats.nf += 6 + integrator.stats.nf += 7 end \ No newline at end of file diff --git a/src/solve.jl b/src/solve.jl index d11db694cd..d9e7918292 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -72,6 +72,7 @@ function DiffEqBase.__init( alias_u0 = false, alias_du0 = false, initializealg = DefaultInit(), + modif = nothing, kwargs...) where {recompile_flag} if prob isa DiffEqBase.AbstractDAEProblem && alg isa OrdinaryDiffEqAlgorithm error("You cannot use an ODE Algorithm with a DAEProblem") @@ -379,7 +380,7 @@ function DiffEqBase.__init( typeof(d_discontinuities_internal), typeof(userdata), typeof(save_idxs), typeof(maxiters), typeof(tstops), - typeof(saveat), typeof(d_discontinuities)}(maxiters, save_everystep, + typeof(saveat), typeof(d_discontinuities), typeof(modif)}(maxiters, save_everystep, adaptive, abstol_internal, reltol_internal, QT(gamma), QT(qmax), @@ -411,7 +412,8 @@ function DiffEqBase.__init( unstable_check, verbose, calck, force_dtmin, advance_to_tstop, - stop_at_next_tstop) + stop_at_next_tstop, + modif) stats = SciMLBase.DEStats(0) differential_vars = prob isa DAEProblem ? prob.differential_vars : diff --git a/test/regression/regression_tests.jl b/test/regression/regression_tests.jl index 58d26d7647..411319ee4a 100644 --- a/test/regression/regression_tests.jl +++ b/test/regression/regression_tests.jl @@ -19,11 +19,91 @@ sim = test_convergence(dts, probnum, Tsit5()) sim = test_convergence(dts, prob, Tsit5()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -### Tsit5 with relaxation +### Tsit5() with new structure println("Tsit5 with relaxation") dts = (1 / 2) .^ (7:-1:3) sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) -#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 \ No newline at end of file +#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache +#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache + + +sol1 = solve(probnum, Tsit5()) +sol2 = solve(probnum, Tsit5_for_relaxation()) + +using Plots +plot(sol1, label = "Old") +plot!(sol2, label = "New") + +######################################################### +## Trying relaxation +######################################################### +using Optimization +using OptimizationOptimJL +using LinearAlgebra + +struct Relaxation{OPT, INV} + opt::OPT + inv::INV +end + +function (r::Relaxation)(integrator) + # We fix here the bounds of interval where we are going to look for the relaxation + # and taking accound the bounds [dtmin, dtmax] and the presence of tstops + γmin = integrator.opts.dtmin / integrator.dt + γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt + + S_u = integrator.dt*(integrator.u_propose-integrator.uprev) + + ## minimization + target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)) + γ0 = [1.0] + prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) + γ_opt = solve(prob_optim, r.opt).u[1] + + # new dt + integrator.dt_changed = integrator.dt * γ_opt + integrator.dt_has_changed = true + + # update u + integrator.u_changed = integrator.uprev + integrator.dt_changed*S_u +end + + +function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) + + @show γmin = dtmin / dt + @show γmax = min(dtmax / first(tstops)) / dt + @show S_u = dt*(u_propose-uprev) + target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ uprev) .- r.inv(uprev)) + γ0 = [1.0] + @show prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) + @show γ_opt = solve(prob_optim, r.opt).u[1] + # new dt + @show dt_changed = dt * γ_opt + @show dt_has_changed = true + # update u + @show uprev + dt_changed*S_u +end + +r = Relaxation(SAMIN(), x->x.^2) + +#x = r(0.1, 0.2, 0.15, [1], 0.8, 0.9) + + +## Tests regressions + +dts = BigFloat.(1 .// 2 .^ (6:-1:2)) +testTol = 0.35 + +# Tests on simple problem + +f = (u, p, t) -> cos(t) +prob_regression = ODEProblem( + ODEFunction(f; analytic = (u0, p, t) -> sin(t)), + 0.0, + (0.0, 1.0)) + + +sol = solve(probnum, Tsit5_for_relaxation(); modif = r) \ No newline at end of file From e35d9fa0c48df787296fc957a70a240b32746ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Mon, 27 May 2024 19:50:09 +0200 Subject: [PATCH 13/39] clean up --- src/ideas_for_relaxation.jl | 118 ---------------------------- test/regression/regression_tests.jl | 109 ------------------------- 2 files changed, 227 deletions(-) delete mode 100644 src/ideas_for_relaxation.jl delete mode 100644 test/regression/regression_tests.jl diff --git a/src/ideas_for_relaxation.jl b/src/ideas_for_relaxation.jl deleted file mode 100644 index 511dbfdf41..0000000000 --- a/src/ideas_for_relaxation.jl +++ /dev/null @@ -1,118 +0,0 @@ -#= Modification of the perform_step function into three part: - - computations - - modif_step - - finalize_step - Their role is described below -=# -function perform_stepNEW!(integrator, cache) - - # Variable to know if dt has changed during perform_step - integrator.dt_has_changed_in_performstep = false - - # computations! will only contain the mathematical scheme - # i.e the computations of the u(t+dt) - # the result is store not in integrator.u but integrator.u_propose - computations!(integrator, cache) - - # modif_step! enables to modify the step like when we want to perform a relaxation - # for this we give a new struture that can be defined either by us for already known - # modification we want to do or by a user (see below) - modif_step!(integrator, cache, integrator.modif) - - # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal - # and register integrator.u - finalize_step!(integrator, cache) -end - - -# To not break all the code we can just add a function to know if the algorithms are -# written with the new form of perform_step! or not. -while integrator.tdir * integrator.t < first(integrator.opts.tstops) - loopheader!(integrator) - if integrator.do_error_check && check_error!(integrator) != ReturnCode.Success - return integrator.sol - end - - # This is just to not break all the package - if isInTheNewFrameWork(integrator.alg) - # The new performstep! - perform_stepNEW!(integrator, integrator.cache) - else - # The already existing perform_step! - perform_step!(integrator, integrator.cache) - end - - loopfooter!(integrator) - if isempty(integrator.opts.tstops) - break - end -end - - -# modif_step! will look like : - -modif_step!(integrator, cache, ::Nothing) = nothing - -function modif_step!(integrator, cache, modif) - - # Perform the modifications - modif(integrator, cache) - - # Here we check the validity of chaging dt if it has changed - # if it is valid integrator.changed_valid will be true, if not it will be false - integrator.changed_valid = true - if integrator_dt_has_changed_in_performstep - # check dt in [dtmin, dtmax] - # things related to tstops - # surely other things - if integrator.changed_valid - integrator.u_propose = integrator.u_changed - integrator.dt = integrator.dt_changed - else - # print error or warning - end - else if integrator.dt_changed != zero(integrator.dt_changed) - # print error - end -end - -###### -# The example of a modification will be like the relaxation : -struct Relaxation{OPT, INV} - opt::OPT - inv::INV -end - -# Here is the modif function for relaxation -function (r::Relaxtion)(integrator) - # We fix here the bounds of interval where we are going to look for the relaxation - # and taking accound the bounds [dtmin, dtmax] and the presence of tstops - γmin = integrator.dtmin / integrator.dt - γmax = min(integrator.dtmax / first(integrator.opts.tstops)) / integrator.dt - - S_u = integrator.dt*(integrator.u_propose-integrator.uprev) - ## need to define or use a method "minimize" with foure main arguments : - # - a method of minimization - # - the function to minimize - # - interval where we look for - # - starting point (fix to 1) for the minimizing method - γ_opt = minimize( r.opt, - γ -> norm(r.inv(γ*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)), - (γmin, γmax), - 1.0) - # new dt - integrator.dt_changed = integrator.dt * γ_opt - integrator.dt_has_changed = true - - # update u - integrator.u_changed = integrator.uprev + γ_opt*S_u -end - - -## example of a code - - - - - - diff --git a/test/regression/regression_tests.jl b/test/regression/regression_tests.jl deleted file mode 100644 index 411319ee4a..0000000000 --- a/test/regression/regression_tests.jl +++ /dev/null @@ -1,109 +0,0 @@ -using OrdinaryDiffEq, DiffEqDevTools, Test - -import ODEProblemLibrary: prob_ode_linear, - prob_ode_2Dlinear - - -probnum = prob_ode_linear -prob = prob_ode_2Dlinear - -dts = (1 / 2) .^ (7:-1:4) -testTol = 0.2 - -### Tsit5() - -println("Tsit5") -dts = (1 / 2) .^ (7:-1:3) -sim = test_convergence(dts, probnum, Tsit5()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -sim = test_convergence(dts, prob, Tsit5()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 - -### Tsit5() with new structure - -println("Tsit5 with relaxation") -dts = (1 / 2) .^ (7:-1:3) -sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache -#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache - - -sol1 = solve(probnum, Tsit5()) -sol2 = solve(probnum, Tsit5_for_relaxation()) - -using Plots -plot(sol1, label = "Old") -plot!(sol2, label = "New") - -######################################################### -## Trying relaxation -######################################################### -using Optimization -using OptimizationOptimJL -using LinearAlgebra - -struct Relaxation{OPT, INV} - opt::OPT - inv::INV -end - -function (r::Relaxation)(integrator) - # We fix here the bounds of interval where we are going to look for the relaxation - # and taking accound the bounds [dtmin, dtmax] and the presence of tstops - γmin = integrator.opts.dtmin / integrator.dt - γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt - - S_u = integrator.dt*(integrator.u_propose-integrator.uprev) - - ## minimization - target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)) - γ0 = [1.0] - prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) - γ_opt = solve(prob_optim, r.opt).u[1] - - # new dt - integrator.dt_changed = integrator.dt * γ_opt - integrator.dt_has_changed = true - - # update u - integrator.u_changed = integrator.uprev + integrator.dt_changed*S_u -end - - -function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) - - @show γmin = dtmin / dt - @show γmax = min(dtmax / first(tstops)) / dt - @show S_u = dt*(u_propose-uprev) - target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ uprev) .- r.inv(uprev)) - γ0 = [1.0] - @show prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) - @show γ_opt = solve(prob_optim, r.opt).u[1] - # new dt - @show dt_changed = dt * γ_opt - @show dt_has_changed = true - # update u - @show uprev + dt_changed*S_u -end - -r = Relaxation(SAMIN(), x->x.^2) - -#x = r(0.1, 0.2, 0.15, [1], 0.8, 0.9) - - -## Tests regressions - -dts = BigFloat.(1 .// 2 .^ (6:-1:2)) -testTol = 0.35 - -# Tests on simple problem - -f = (u, p, t) -> cos(t) -prob_regression = ODEProblem( - ODEFunction(f; analytic = (u0, p, t) -> sin(t)), - 0.0, - (0.0, 1.0)) - - -sol = solve(probnum, Tsit5_for_relaxation(); modif = r) \ No newline at end of file From 653436be91a99c7022112ea0e7d61d3ea9b1b7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Tue, 28 May 2024 22:08:48 +0200 Subject: [PATCH 14/39] try test without relaxation --- test/regression/test_regression.jl | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/regression/test_regression.jl diff --git a/test/regression/test_regression.jl b/test/regression/test_regression.jl new file mode 100644 index 0000000000..f2467434c5 --- /dev/null +++ b/test/regression/test_regression.jl @@ -0,0 +1,37 @@ +using OrdinaryDiffEq, DiffEqDevTools, Test + +import ODEProblemLibrary: prob_ode_linear, + prob_ode_2Dlinear + + +probnum = prob_ode_linear +prob = prob_ode_2Dlinear + +dts = (1 / 2) .^ (7:-1:4) +testTol = 0.2 + +### Tsit5() + +println("Tsit5") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +sim = test_convergence(dts, prob, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 + +### Tsit5() with new structure + +println("Tsit5 with relaxation") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache +#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache + + +sol1 = solve(probnum, Tsit5()) +sol2 = solve(probnum, Tsit5_for_relaxation()) + +using Plots +plot(sol1, label = "Old") +plot!(sol2, label = "New") \ No newline at end of file From 730d4e1b11c1c772063a6e561f516370762905e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Thu, 30 May 2024 21:21:43 +0200 Subject: [PATCH 15/39] copy tist5 for non constant cache --- .../test_for_relaxation_perform_step.jl | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index cc1b7a1742..9b343a9d88 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -100,4 +100,100 @@ function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) integrator.fsallast = f(u_propose, p, t + dt) integrator.stats.nf += 7 -end \ No newline at end of file +end + + +## Non Constant cache +function initialize!(integrator, cache::Tsit5Cache_for_relaxation) + integrator.kshortsize = 7 + integrator.fsalfirst = cache.k1 + integrator.fsallast = cache.k7 # setup pointers + resize!(integrator.k, integrator.kshortsize) + # Setup k pointers + integrator.k[1] = cache.k1 + integrator.k[2] = cache.k2 + integrator.k[3] = cache.k3 + integrator.k[4] = cache.k4 + integrator.k[5] = cache.k5 + integrator.k[6] = cache.k6 + integrator.k[7] = cache.k7 + integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + integrator.stats.nf += 1 + return nothing +end + + +function perform_step!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) + + # Variable to know if dt has changed during perform_step + integrator.dt_has_changed = false + + # computations! will only contain the mathematical scheme + # i.e the computations of the u(t+dt) + # the result is store not in integrator.u but integrator.u_propose + computations!(integrator, cache, repeat_step) + + # modif_step! enables to modify the step like when we want to perform a relaxation + # for this we give a new struture that can be defined either by us for already known + # modification we want to do or by a user (see below) + modif_step!(integrator) + + # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal + # and register integrator.u + finalize_step!(integrator, cache) +end + +@muladd functioncomputations!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) + @unpack t, dt, uprev, u_propose, f, p = integrator + T = constvalue(recursive_unitless_bottom_eltype(u)) + T2 = constvalue(typeof(one(t))) + @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + @unpack k1, k2, k3, k4, k5, k6, k7, utilde, tmp, atmp, stage_limiter!, step_limiter!, thread = cache + a = dt * a21 + @.. broadcast=false thread=thread tmp=uprev + a * k1 + stage_limiter!(tmp, f, p, t + c1 * dt) + f(k2, tmp, p, t + c1 * dt) + @.. broadcast=false thread=thread tmp=uprev + dt * (a31 * k1 + a32 * k2) + stage_limiter!(tmp, f, p, t + c2 * dt) + f(k3, tmp, p, t + c2 * dt) + @.. broadcast=false thread=thread tmp=uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3) + stage_limiter!(tmp, f, p, t + c3 * dt) + f(k4, tmp, p, t + c3 * dt) + @.. broadcast=false thread=thread tmp=uprev + + dt * (a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4) + stage_limiter!(tmp, f, p, t + c4 * dt) + f(k5, tmp, p, t + c4 * dt) + @.. broadcast=false thread=thread tmp=uprev + + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + + a65 * k5) + stage_limiter!(tmp, f, p, t + dt) + f(k6, tmp, p, t + dt) + @.. broadcast=false thread=thread u_propose = uprev + + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + + a75 * k5 + a76 * k6) + stage_limiter!(u_propose, integrator, p, t + dt) + step_limiter!(u_propose, integrator, p, t + dt) + + f(k7, u_propose, p, t + dt) + + if integrator.opts.adaptive + @.. broadcast=false thread=thread utilde=dt * (btilde1 * k1 + btilde2 * k2 + + btilde3 * k3 + btilde4 * k4 + + btilde5 * k5 + btilde6 * k6 + + btilde7 * k7) + calculate_residuals!(atmp, utilde, uprev, u_propose, integrator.opts.abstol, + integrator.opts.reltol, integrator.opts.internalnorm, t, + thread) + integrator.EEst = integrator.opts.internalnorm(atmp, t) + end + return nothing +end + +function finalize_step!(integrator, ::Tsit5Cache_for_relaxation) + @unpack t, dt, uprev, u_propose, f, p = integrator + @.. broadcast=false thread=thread u = u_propose + stage_limiter!(u, integrator, p, t + dt) + step_limiter!(u, integrator, p, t + dt) + f(k7, u_propose, p, t + dt) + integrator.stats.nf += 7 +end From db28be6fce0d2f47ca8ada7217f904b61c8a782f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Thu, 30 May 2024 22:45:21 +0200 Subject: [PATCH 16/39] fix tsit5_for_relaxation with non constant cache --- .../test_for_relaxation_perform_step.jl | 9 +++++---- test/regression/test_regression.jl | 14 +++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 9b343a9d88..56c2a4bacc 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -143,9 +143,9 @@ function perform_step!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step finalize_step!(integrator, cache) end -@muladd functioncomputations!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) +@muladd function computations!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) @unpack t, dt, uprev, u_propose, f, p = integrator - T = constvalue(recursive_unitless_bottom_eltype(u)) + T = constvalue(recursive_unitless_bottom_eltype(u_propose)) T2 = constvalue(typeof(one(t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 @unpack k1, k2, k3, k4, k5, k6, k7, utilde, tmp, atmp, stage_limiter!, step_limiter!, thread = cache @@ -189,8 +189,9 @@ end return nothing end -function finalize_step!(integrator, ::Tsit5Cache_for_relaxation) - @unpack t, dt, uprev, u_propose, f, p = integrator +function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) + @unpack t, dt, u_propose, u, f, p = integrator + @unpack k7, stage_limiter!, step_limiter!, thread = cache @.. broadcast=false thread=thread u = u_propose stage_limiter!(u, integrator, p, t + dt) step_limiter!(u, integrator, p, t + dt) diff --git a/test/regression/test_regression.jl b/test/regression/test_regression.jl index f2467434c5..1a876cd699 100644 --- a/test/regression/test_regression.jl +++ b/test/regression/test_regression.jl @@ -25,8 +25,8 @@ println("Tsit5 with relaxation") dts = (1 / 2) .^ (7:-1:3) sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -#sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache -#@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache sol1 = solve(probnum, Tsit5()) @@ -34,4 +34,12 @@ sol2 = solve(probnum, Tsit5_for_relaxation()) using Plots plot(sol1, label = "Old") -plot!(sol2, label = "New") \ No newline at end of file +plot!(sol2, label = "New") + +sol1 = solve(prob, Tsit5()) +sol2 = solve(prob, Tsit5_for_relaxation()) + +plot(sol1, label = "Old") +plot!(sol2, label = "New") + + From 2ffd004336db299cde25efd1e171f9b7cd897798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Mon, 3 Jun 2024 22:20:02 +0200 Subject: [PATCH 17/39] first try of implementation of the relaxation step --- Project.toml | 1 + test/regression/test_regression.jl | 45 ------------- test/regression/test_relaxation.jl | 105 +++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 45 deletions(-) delete mode 100644 test/regression/test_regression.jl create mode 100644 test/regression/test_relaxation.jl diff --git a/Project.toml b/Project.toml index b84a1259e3..1815629278 100644 --- a/Project.toml +++ b/Project.toml @@ -27,6 +27,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +ODEProblemLibrary = "fdc4e326-1af4-4b90-96e7-779fcce2daa5" Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" diff --git a/test/regression/test_regression.jl b/test/regression/test_regression.jl deleted file mode 100644 index 1a876cd699..0000000000 --- a/test/regression/test_regression.jl +++ /dev/null @@ -1,45 +0,0 @@ -using OrdinaryDiffEq, DiffEqDevTools, Test - -import ODEProblemLibrary: prob_ode_linear, - prob_ode_2Dlinear - - -probnum = prob_ode_linear -prob = prob_ode_2Dlinear - -dts = (1 / 2) .^ (7:-1:4) -testTol = 0.2 - -### Tsit5() - -println("Tsit5") -dts = (1 / 2) .^ (7:-1:3) -sim = test_convergence(dts, probnum, Tsit5()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -sim = test_convergence(dts, prob, Tsit5()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 - -### Tsit5() with new structure - -println("Tsit5 with relaxation") -dts = (1 / 2) .^ (7:-1:3) -sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache - - -sol1 = solve(probnum, Tsit5()) -sol2 = solve(probnum, Tsit5_for_relaxation()) - -using Plots -plot(sol1, label = "Old") -plot!(sol2, label = "New") - -sol1 = solve(prob, Tsit5()) -sol2 = solve(prob, Tsit5_for_relaxation()) - -plot(sol1, label = "Old") -plot!(sol2, label = "New") - - diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl new file mode 100644 index 0000000000..b796695ec0 --- /dev/null +++ b/test/regression/test_relaxation.jl @@ -0,0 +1,105 @@ +using OrdinaryDiffEq, DiffEqDevTools, Test + +import ODEProblemLibrary: prob_ode_linear, + prob_ode_2Dlinear + + +probnum = prob_ode_linear +prob = prob_ode_2Dlinear + +dts = (1 / 2) .^ (7:-1:4) +testTol = 0.2 + +### Tsit5() + +println("Tsit5") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +sim = test_convergence(dts, prob, Tsit5()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 + +### Tsit5() with new structure + +println("Tsit5 with relaxation") +dts = (1 / 2) .^ (7:-1:3) +sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache + + +sol1 = solve(probnum, Tsit5()) +sol2 = solve(probnum, Tsit5_for_relaxation()) + +using Plots +plot(sol1, label = "Old") +plot!(sol2, label = "New") + +sol1 = solve(prob, Tsit5()) +sol2 = solve(prob, Tsit5_for_relaxation()) + +plot(sol1, label = "Old") +plot!(sol2, label = "New") + + +######################################################### +## Trying relaxation +######################################################### +using Optimization +using OptimizationOptimJL +using LinearAlgebra + +struct Relaxation{OPT, INV} + opt::OPT + inv::INV +end + +function (r::Relaxation)(integrator) + # We fix here the bounds of interval where we are going to look for the relaxation + # and taking accound the bounds [dtmin, dtmax] and the presence of tstops + γmin = integrator.opts.dtmin / integrator.dt + γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt + + S_u = integrator.dt*(integrator.u_propose-integrator.uprev) + + ## minimization + target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)) + γ0 = [1.0] + prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) + γ_opt = solve(prob_optim, r.opt).u[1] + + # new dt + integrator.dt_changed = integrator.dt * γ_opt + integrator.dt_has_changed = true + + # update u + integrator.u_changed = integrator.uprev + integrator.dt_changed*S_u +end + + +function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) + + @show γmin = dtmin / dt + @show γmax = min(dtmax / first(tstops)) / dt + @show S_u = dt*(u_propose-uprev) + target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ uprev) .- r.inv(uprev)) + γ0 = [1.0] + @show prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) + @show γ_opt = solve(prob_optim, r.opt).u[1] + # new dt + @show dt_changed = dt * γ_opt + @show dt_has_changed = true + # update u + @show uprev + dt_changed*S_u +end + +r = Relaxation(SAMIN(), x->x.^2) + +#x = r(0.1, 0.2, 0.15, [1], 0.8, 0.9) + + +## Tests relaxation + +dts = BigFloat.(1 .// 2 .^ (6:-1:2)) +testTol = 0.35 \ No newline at end of file From a180073121399fd0948e549942466360f030ce31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Thu, 6 Jun 2024 00:11:00 +0200 Subject: [PATCH 18/39] add notes on some thoughts --- src/note on a new structure for perform_step | 24 ++++++++++++++++++ test/regression/test_relaxation.jl | 26 +++++++++++++++----- 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/note on a new structure for perform_step diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step new file mode 100644 index 0000000000..93b736f975 --- /dev/null +++ b/src/note on a new structure for perform_step @@ -0,0 +1,24 @@ +Here is few notes about having a new structure of the code concerning the step perform_step! : + +News parameters to integrator: +- u_propose +- u_changed +- dt_has_changed -> just a bool +- dt_changed -> +- u_has_changed (not implemented yet) -> just a bool + +New DEOptions +- modif : a callable object to custom computation right after perform_step + +Possible function to implement +- modify_dt(integrator, dt) --> set dt_has_changed to true by the same occasion +- dt_has_changed(integrator) -> to set true for dt_has_changed +- u_has_changed(integrator) -> to set true for u_has_changed +- + +Note : +- Prefer "modified" as kee word instead of "changed" +- maybe should create a cache for modify function to have best performance +--> in that way it could be possible to run once the user modification to get basic element of the cas as u_changed, instead of storing it directly + + diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index b796695ec0..4f96cdb2a4 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -10,6 +10,10 @@ prob = prob_ode_2Dlinear dts = (1 / 2) .^ (7:-1:4) testTol = 0.2 +# Check that the code with the new structure without modification asked +# by the user gives the same result +# Comparaison on Tist5 + ### Tsit5() println("Tsit5") @@ -25,8 +29,8 @@ println("Tsit5 with relaxation") dts = (1 / 2) .^ (7:-1:3) sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 -sim = test_convergence(dts, prob, Tsit5_for_relaxation()) # need to implement perform_step for not constant cache -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 # need to implement perform_step for not constant cache +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 sol1 = solve(probnum, Tsit5()) @@ -44,7 +48,7 @@ plot!(sol2, label = "New") ######################################################### -## Trying relaxation +## Trying relaxation step ######################################################### using Optimization using OptimizationOptimJL @@ -52,24 +56,34 @@ using LinearAlgebra struct Relaxation{OPT, INV} opt::OPT - inv::INV + invariant::INV end function (r::Relaxation)(integrator) + # We fix here the bounds of interval where we are going to look for the relaxation # and taking accound the bounds [dtmin, dtmax] and the presence of tstops + + # Fix of dt interval + # should be good to have a function that gives good bound for dt taking accound dtmin explicit + # and not γmin = integrator.opts.dtmin / integrator.dt γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt + S_u = integrator.dt*(integrator.u_propose-integrator.uprev) ## minimization - target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ integrator.uprev) .- r.inv(integrator.uprev)) + target_fun(γ,p) = norm(r.invariant(γ[1]*S_u .+ integrator.uprev) .- r.invariant(integrator.uprev)) γ0 = [1.0] prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) γ_opt = solve(prob_optim, r.opt).u[1] # new dt + # instead of explicit change a parameter like dt_changed, because there can be many confusion, + # it should be a better solution to just have a set function + # for exemple propose_dt!(integrator, dt) + integrator.dt_changed = integrator.dt * γ_opt integrator.dt_has_changed = true @@ -83,7 +97,7 @@ function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) @show γmin = dtmin / dt @show γmax = min(dtmax / first(tstops)) / dt @show S_u = dt*(u_propose-uprev) - target_fun(γ,p) = norm(r.inv(γ[1]*S_u .+ uprev) .- r.inv(uprev)) + target_fun(γ,p) = norm(r.invariant(γ[1]*S_u .+ uprev) .- r.invariant(uprev)) γ0 = [1.0] @show prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) @show γ_opt = solve(prob_optim, r.opt).u[1] From 52f446137f468951bafa8192168fa53c59b8912b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 7 Jun 2024 22:31:57 +0200 Subject: [PATCH 19/39] add some tools --- src/OrdinaryDiffEq.jl | 2 ++ src/integrators/integrator_interface.jl | 14 ++++++++++++++ src/integrators/type.jl | 5 +++-- src/note on a new structure for perform_step | 5 +---- src/solve.jl | 3 ++- test/regression/test_relaxation.jl | 17 +++++------------ 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index cf69de6b69..d433f90f3f 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -77,6 +77,8 @@ import DiffEqBase: resize!, deleteat!, addat!, full_cache, user_cache, u_cache, add_saveat!, set_reltol!, set_abstol!, postamble!, last_step_failed, isautodifferentiable + +export change_u!, change_dt! using DiffEqBase: check_error!, @def, _vec, _reshape diff --git a/src/integrators/integrator_interface.jl b/src/integrators/integrator_interface.jl index 4ba6935cb3..b9a7c686ac 100644 --- a/src/integrators/integrator_interface.jl +++ b/src/integrators/integrator_interface.jl @@ -506,3 +506,17 @@ function DiffEqBase.set_u!(integrator::ODEIntegrator, u) end DiffEqBase.has_stats(i::ODEIntegrator) = true + + +function change_dt!(integrator::ODEIntegrator, dt) + integrator.dt_has_changed = true + integrator.dt_changed = dt +end + +function change_u!(integrator::ODEIntegrator, u) + integrator.u_has_changed = true + integrator.u_changed = u +end + + + diff --git a/src/integrators/type.jl b/src/integrators/type.jl index ed88a45e83..a1d9ee3f96 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -138,6 +138,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori u_propose::uType u_changed::uType + u_has_changed::Bool dt_has_changed::Bool dt_changed::tType @@ -163,7 +164,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori reinitialize, isdae, opts, stats, initializealg, differential_vars, - u_propose, u_changed, dt_has_changed, dt_changed) where {algType, IIP, uType, + u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) where {algType, IIP, uType, duType, tType, pType, eigenType, EEstT, tTypeNoUnits, tdirType, @@ -185,7 +186,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori do_error_check, event_last_time, vector_event_last_time, last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitialize, isdae, - opts, stats, initializealg, differential_vars, u_propose, u_changed, dt_has_changed, dt_changed) # Leave off fsalfirst and last + opts, stats, initializealg, differential_vars, u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) # Leave off fsalfirst and last end end diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step index 93b736f975..f5de609717 100644 --- a/src/note on a new structure for perform_step +++ b/src/note on a new structure for perform_step @@ -11,10 +11,7 @@ New DEOptions - modif : a callable object to custom computation right after perform_step Possible function to implement -- modify_dt(integrator, dt) --> set dt_has_changed to true by the same occasion -- dt_has_changed(integrator) -> to set true for dt_has_changed -- u_has_changed(integrator) -> to set true for u_has_changed -- +- change_u, change_dt Note : - Prefer "modified" as kee word instead of "changed" diff --git a/src/solve.jl b/src/solve.jl index 6085b64376..1794819b9c 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -163,6 +163,7 @@ function DiffEqBase.__init( end u_propose = recursivecopy(u) u_changed = recursivecopy(u) + u_has_changed = false if _alg isa DAEAlgorithm if alias_du0 @@ -495,7 +496,7 @@ function DiffEqBase.__init( last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitiailize, isdae, - opts, stats, initializealg, differential_vars, u_propose, u_changed, dt_has_changed, dt_changed) + opts, stats, initializealg, differential_vars, u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) if initialize_integrator if isdae || SciMLBase.has_initializeprob(prob.f) diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 4f96cdb2a4..48c366748f 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -70,25 +70,18 @@ function (r::Relaxation)(integrator) γmin = integrator.opts.dtmin / integrator.dt γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt - + S_u = integrator.dt*(integrator.u_propose-integrator.uprev) - ## minimization + ## Minimization target_fun(γ,p) = norm(r.invariant(γ[1]*S_u .+ integrator.uprev) .- r.invariant(integrator.uprev)) γ0 = [1.0] prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) γ_opt = solve(prob_optim, r.opt).u[1] - # new dt - # instead of explicit change a parameter like dt_changed, because there can be many confusion, - # it should be a better solution to just have a set function - # for exemple propose_dt!(integrator, dt) - - integrator.dt_changed = integrator.dt * γ_opt - integrator.dt_has_changed = true - - # update u - integrator.u_changed = integrator.uprev + integrator.dt_changed*S_u + # Updates + change_dt!(integrator, integrator.dt * γ_opt) + changed_u!(integrator, integrator.uprev + γ_opt*S_u) end From b4d9c40d4b0e16ab74732efc2925a5365222f784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 7 Jun 2024 23:49:09 +0200 Subject: [PATCH 20/39] add some tools --- Project.toml | 1 + src/note on a new structure for perform_step | 9 +-- test/regression/test_relaxation.jl | 60 +++++++++++--------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/Project.toml b/Project.toml index 1815629278..b6d6522f45 100644 --- a/Project.toml +++ b/Project.toml @@ -44,6 +44,7 @@ SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804" StaticArrayInterface = "0d7ed370-da01-4f52-bd93-41d350b8b718" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" TruncatedStacktraces = "781d530d-4396-4725-bb49-402e4bee1e77" +UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" [compat] ADTypes = "0.2, 1" diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step index f5de609717..0c384846d3 100644 --- a/src/note on a new structure for perform_step +++ b/src/note on a new structure for perform_step @@ -3,15 +3,16 @@ Here is few notes about having a new structure of the code concerning the step p News parameters to integrator: - u_propose - u_changed -- dt_has_changed -> just a bool -- dt_changed -> -- u_has_changed (not implemented yet) -> just a bool +- dt_has_changed +- dt_changed +- u_has_changed New DEOptions - modif : a callable object to custom computation right after perform_step Possible function to implement -- change_u, change_dt +- change_u, change_dt DONE +- dt_interval should be implemented Note : - Prefer "modified" as kee word instead of "changed" diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 48c366748f..3a763b8f81 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -3,17 +3,17 @@ using OrdinaryDiffEq, DiffEqDevTools, Test import ODEProblemLibrary: prob_ode_linear, prob_ode_2Dlinear - probnum = prob_ode_linear prob = prob_ode_2Dlinear dts = (1 / 2) .^ (7:-1:4) testTol = 0.2 + +######################################################################### # Check that the code with the new structure without modification asked # by the user gives the same result # Comparaison on Tist5 - ### Tsit5() println("Tsit5") @@ -32,70 +32,76 @@ sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) sim = test_convergence(dts, prob, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 +### Compareason of interpolation sol1 = solve(probnum, Tsit5()) sol2 = solve(probnum, Tsit5_for_relaxation()) +sol3 = solve(prob, Tsit5()) +sol4 = solve(prob, Tsit5_for_relaxation()) + using Plots plot(sol1, label = "Old") plot!(sol2, label = "New") +plot(sol3, label = "Old") +plot!(sol4, label = "New") -sol1 = solve(prob, Tsit5()) -sol2 = solve(prob, Tsit5_for_relaxation()) - -plot(sol1, label = "Old") -plot!(sol2, label = "New") +######################################################################### +## Trying relaxation step -######################################################### -## Trying relaxation step -######################################################### using Optimization using OptimizationOptimJL using LinearAlgebra +using UnPack struct Relaxation{OPT, INV} opt::OPT invariant::INV end + function (r::Relaxation)(integrator) + @unpack dt, uprev, u_propose = integrator + @unpack dtmin, dtmax, tstops = integrator.opts + # We fix here the bounds of interval where we are going to look for the relaxation # and taking accound the bounds [dtmin, dtmax] and the presence of tstops # Fix of dt interval # should be good to have a function that gives good bound for dt taking accound dtmin explicit # and not - γmin = integrator.opts.dtmin / integrator.dt - γmax = min(integrator.opts.dtmax / first(integrator.opts.tstops)) / integrator.dt + gamma_min = dtmin + gamma_max = min(dtmax, first(tstops)) - - S_u = integrator.dt*(integrator.u_propose-integrator.uprev) + S_u = dt*(u_propose-uprev) ## Minimization - target_fun(γ,p) = norm(r.invariant(γ[1]*S_u .+ integrator.uprev) .- r.invariant(integrator.uprev)) - γ0 = [1.0] - prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) - γ_opt = solve(prob_optim, r.opt).u[1] + prob_optim = OptimizationProblem( + (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), + [dt]; + lb = [gamma_min], + ub = [gamma_max]) + gamma_opt = solve(prob_optim, r.opt).u[1] # Updates - change_dt!(integrator, integrator.dt * γ_opt) - changed_u!(integrator, integrator.uprev + γ_opt*S_u) + change_dt!(integrator, dt * gamma_opt) + changed_u!(integrator, uprev + gamma_opt*S_u) end function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) - @show γmin = dtmin / dt - @show γmax = min(dtmax / first(tstops)) / dt + @show gamma_min = dtmin / dt + @show gamma_max = min(dtmax, first(tstops)) / dt @show S_u = dt*(u_propose-uprev) - target_fun(γ,p) = norm(r.invariant(γ[1]*S_u .+ uprev) .- r.invariant(uprev)) - γ0 = [1.0] - @show prob_optim = OptimizationProblem(target_fun, γ0; lb = [γmin], ub = [γmax]) - @show γ_opt = solve(prob_optim, r.opt).u[1] + target_fun(gamma_,p) = norm(r.invariant(gamma_[1]*S_u .+ uprev) .- r.invariant(uprev)) + gamma_0 = [1.0] + @show prob_optim = OptimizationProblem(target_fun, gamma_0; lb = [gamma_min], ub = [gamma_max]) + @show gamma__opt = solve(prob_optim, r.opt).u[1] # new dt - @show dt_changed = dt * γ_opt + @show dt_changed = dt * gamma__opt @show dt_has_changed = true # update u @show uprev + dt_changed*S_u From a01bc2a931a586eba3366da9738b3d88fcf88be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 8 Jun 2024 11:34:03 +0200 Subject: [PATCH 21/39] bound_dt --- src/OrdinaryDiffEq.jl | 2 +- .../test_for_relaxation_perform_step.jl | 14 +++++++++++++- test/regression/test_relaxation.jl | 17 +++++------------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index d433f90f3f..2cae4c536d 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -78,7 +78,7 @@ import DiffEqBase: resize!, deleteat!, addat!, full_cache, user_cache, u_cache, set_abstol!, postamble!, last_step_failed, isautodifferentiable -export change_u!, change_dt! +export change_u!, change_dt!, apriori_bounds_dt using DiffEqBase: check_error!, @def, _vec, _reshape diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 56c2a4bacc..fe75c00a25 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -81,7 +81,8 @@ function modif_step!(integrator) changed_valid = true if integrator.dt_has_changed # check dt in [dtmin, dtmax] - # things related to tstops + + # surely other things if changed_valid integrator.u_propose = integrator.u_changed @@ -198,3 +199,14 @@ function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) f(k7, u_propose, p, t + dt) integrator.stats.nf += 7 end + + +function apriori_bounds_dt(integrator) + dt_sup = if has_tstop(integrator) + integrator.tdir * min(abs(integrator.opts.dtmax) , abs(first_tstop(integrator) - integrator.t)) + else + integrator.tdir * abs(integrator.opts.dtmax) + end + dt_inf = integrator.tdir * timedepentdtmin(integrator) + (dt_inf,dt_sup) +end \ No newline at end of file diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 3a763b8f81..6dd15442d5 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -63,21 +63,14 @@ end function (r::Relaxation)(integrator) - @unpack dt, uprev, u_propose = integrator - @unpack dtmin, dtmax, tstops = integrator.opts + @unpack t, dt, uprev, u_propose = integrator # We fix here the bounds of interval where we are going to look for the relaxation - # and taking accound the bounds [dtmin, dtmax] and the presence of tstops + (gamma_min, gamma_max) = apriori_bounds_dt(integrator) - # Fix of dt interval - # should be good to have a function that gives good bound for dt taking accound dtmin explicit - # and not - gamma_min = dtmin - gamma_max = min(dtmax, first(tstops)) + @. S_u = u_propose-uprev - S_u = dt*(u_propose-uprev) - - ## Minimization + # Minimization prob_optim = OptimizationProblem( (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), [dt]; @@ -86,7 +79,7 @@ function (r::Relaxation)(integrator) gamma_opt = solve(prob_optim, r.opt).u[1] # Updates - change_dt!(integrator, dt * gamma_opt) + change_dt!(integrator, gamma_opt) changed_u!(integrator, uprev + gamma_opt*S_u) end From 3fd63fdd2ef085ed1f818ea255698e435967059d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 9 Jun 2024 19:02:22 +0200 Subject: [PATCH 22/39] trying to use Roots.jl instead of OptimizationOptimJL.jl --- src/note on a new structure for perform_step | 1 + test/regression/test_relaxation.jl | 30 +++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step index 0c384846d3..ec5c91b1a2 100644 --- a/src/note on a new structure for perform_step +++ b/src/note on a new structure for perform_step @@ -9,6 +9,7 @@ News parameters to integrator: New DEOptions - modif : a callable object to custom computation right after perform_step +--> a beter name could be "modif_step" Possible function to implement - change_u, change_dt DONE diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 6dd15442d5..1fb83ad93c 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -52,6 +52,7 @@ plot!(sol4, label = "New") using Optimization using OptimizationOptimJL +using Roots using LinearAlgebra using UnPack @@ -68,19 +69,25 @@ function (r::Relaxation)(integrator) # We fix here the bounds of interval where we are going to look for the relaxation (gamma_min, gamma_max) = apriori_bounds_dt(integrator) - @. S_u = u_propose-uprev + S_u = u_propose - uprev # Minimization + # first method tried (seems to not work) + #= prob_optim = OptimizationProblem( (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), [dt]; lb = [gamma_min], ub = [gamma_max]) gamma_opt = solve(prob_optim, r.opt).u[1] + =# + # second method + gamma_opt = find_zero( gamma -> norm(r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev)), + r.opt()) # Updates change_dt!(integrator, gamma_opt) - changed_u!(integrator, uprev + gamma_opt*S_u) + change_u!(integrator, uprev + gamma_opt*S_u) end @@ -100,12 +107,21 @@ function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) @show uprev + dt_changed*S_u end -r = Relaxation(SAMIN(), x->x.^2) +#r = Relaxation(SAMIN(), x->x.^2) -#x = r(0.1, 0.2, 0.15, [1], 0.8, 0.9) +r = Relaxation(AlefeldPotraShi(), x-> norm(x)) +## Tests relaxation on problem -## Tests relaxation +# Harmonic Oscillator -dts = BigFloat.(1 .// 2 .^ (6:-1:2)) -testTol = 0.35 \ No newline at end of file +f_oscillator = (u, p, t) -> [-u[2],u[1]] +prob_oscillator = ODEProblem( + ODEFunction(f_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), + [1.0, 0.0], + (0.0, 1.0)) + +sol_oscillator = solve(probnum, Tsit5_for_relaxation(); modif = r) + + +# From e926a611166ea41c338f5afdf568cbbd80f2c963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 9 Jun 2024 21:54:00 +0200 Subject: [PATCH 23/39] test relaxation on oscillator --- test/regression/test_relaxation.jl | 31 +++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 1fb83ad93c..9492e2fbcb 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -50,8 +50,8 @@ plot!(sol4, label = "New") ######################################################################### ## Trying relaxation step -using Optimization -using OptimizationOptimJL +#using Optimization +#using OptimizationOptimJL using Roots using LinearAlgebra using UnPack @@ -67,7 +67,7 @@ function (r::Relaxation)(integrator) @unpack t, dt, uprev, u_propose = integrator # We fix here the bounds of interval where we are going to look for the relaxation - (gamma_min, gamma_max) = apriori_bounds_dt(integrator) + @show (gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt S_u = u_propose - uprev @@ -82,12 +82,25 @@ function (r::Relaxation)(integrator) gamma_opt = solve(prob_optim, r.opt).u[1] =# # second method - gamma_opt = find_zero( gamma -> norm(r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev)), - r.opt()) + gamma_min = 0.5 + gamma_max = 1.5 + terminate_integrator = false + if (r.invariant(gamma_min*S_u .+ uprev) .- r.invariant(uprev)) * (r.invariant(gamma_max*S_u .+ uprev) .- r.invariant(uprev)) > 0 + gamma_opt = one(td) + terminate_integrator = true + else + @show gamma_opt = find_zero( gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), + (max(gamma_min,0.5), min(gamma_max,1.5)), + r.opt()) + end # Updates - change_dt!(integrator, gamma_opt) + change_dt!(integrator, gamma_opt*dt) change_u!(integrator, uprev + gamma_opt*S_u) + + #if terminate_integrator + # terminate!(integrator) + #end end @@ -109,7 +122,7 @@ end #r = Relaxation(SAMIN(), x->x.^2) -r = Relaxation(AlefeldPotraShi(), x-> norm(x)) +r = Relaxation(AlefeldPotraShi, x-> norm(x)) ## Tests relaxation on problem @@ -121,7 +134,7 @@ prob_oscillator = ODEProblem( [1.0, 0.0], (0.0, 1.0)) -sol_oscillator = solve(probnum, Tsit5_for_relaxation(); modif = r) +sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r, maxiters = 5) -# +plot(sol_oscillator.u) From 2789e9ff9f715ac10187d6790b3e28e170cc64c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 9 Jun 2024 22:28:42 +0200 Subject: [PATCH 24/39] work at the beginning for harmonic oscillator but there is bug in long time --- test/regression/test_relaxation.jl | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 9492e2fbcb..261afe6261 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -67,7 +67,7 @@ function (r::Relaxation)(integrator) @unpack t, dt, uprev, u_propose = integrator # We fix here the bounds of interval where we are going to look for the relaxation - @show (gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt + (gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt S_u = u_propose - uprev @@ -89,7 +89,7 @@ function (r::Relaxation)(integrator) gamma_opt = one(td) terminate_integrator = true else - @show gamma_opt = find_zero( gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), + gamma_opt = find_zero( gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), (max(gamma_min,0.5), min(gamma_max,1.5)), r.opt()) end @@ -103,31 +103,12 @@ function (r::Relaxation)(integrator) #end end - -function (r::Relaxation)(dtmin, dtmax, dt, tstops, u_propose, uprev) - - @show gamma_min = dtmin / dt - @show gamma_max = min(dtmax, first(tstops)) / dt - @show S_u = dt*(u_propose-uprev) - target_fun(gamma_,p) = norm(r.invariant(gamma_[1]*S_u .+ uprev) .- r.invariant(uprev)) - gamma_0 = [1.0] - @show prob_optim = OptimizationProblem(target_fun, gamma_0; lb = [gamma_min], ub = [gamma_max]) - @show gamma__opt = solve(prob_optim, r.opt).u[1] - # new dt - @show dt_changed = dt * gamma__opt - @show dt_has_changed = true - # update u - @show uprev + dt_changed*S_u -end - #r = Relaxation(SAMIN(), x->x.^2) - r = Relaxation(AlefeldPotraShi, x-> norm(x)) ## Tests relaxation on problem # Harmonic Oscillator - f_oscillator = (u, p, t) -> [-u[2],u[1]] prob_oscillator = ODEProblem( ODEFunction(f_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), @@ -135,6 +116,9 @@ prob_oscillator = ODEProblem( (0.0, 1.0)) sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r, maxiters = 5) +sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] +niter = length(sol_oscillator.t) - -plot(sol_oscillator.u) +plot(sol_oscillator) +plot!(sol_oscillator.t, [sol_exact[i][1] for i in 1:niter], label = "exact u[1]", lw = 4) +plot!(sol_oscillator.t, [sol_exact[i][2] for i in 1:niter], label = "exact u[2]", lw = 4) \ No newline at end of file From 89c10f3ac505093834dae66c675353de7938e60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:11:42 +0200 Subject: [PATCH 25/39] add some problem for later --- test/regression/test_relaxation.jl | 37 ++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 261afe6261..e192a9667c 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -104,7 +104,7 @@ function (r::Relaxation)(integrator) end #r = Relaxation(SAMIN(), x->x.^2) -r = Relaxation(AlefeldPotraShi, x-> norm(x)) +r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) ## Tests relaxation on problem @@ -115,10 +115,43 @@ prob_oscillator = ODEProblem( [1.0, 0.0], (0.0, 1.0)) +r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) + sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r, maxiters = 5) sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] niter = length(sol_oscillator.t) plot(sol_oscillator) plot!(sol_oscillator.t, [sol_exact[i][1] for i in 1:niter], label = "exact u[1]", lw = 4) -plot!(sol_oscillator.t, [sol_exact[i][2] for i in 1:niter], label = "exact u[2]", lw = 4) \ No newline at end of file +plot!(sol_oscillator.t, [sol_exact[i][2] for i in 1:niter], label = "exact u[2]", lw = 4) + +# Non Linear Oscillator +#= +f_nonlinear_oscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] +prob_nonlinear_oscillator = ODEProblem( + ODEFunction(f_nonlinear_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), + [1.0, 0.0], + (0.0, 1.0)) + +r_nonlinear_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) + +sol_nonlinear_oscillator = solve(prob_nonlinear_oscillator, Tsit5_for_relaxation()) +sol_exact = [prob_oscillator.f.analytic(prob_nonlinear_oscillator.u0, prob_nonlinear_oscillator.p, t) for t in sol_nonlinear_oscillator.t] +niter = length(sol_nonlinear_oscillator.t) + + +# Non Linear Pendulum +f_nonlinear_pendulum = (u, p, t) -> [-sin(u[2]), u[1]] +prob_nonlinear_pendulum = ODEProblem( + f_nonlinear_pendulum, + [1.0, 0.0], + (0.0, 1.0)) + +r_nonlinear_pendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) + +sol_nonlinear_pendulum = solve(prob_nonlinear_pendulum, Tsit5_for_relaxation()) + +sol_ref = solve(prob_nonlinear_pendulum, Vern9()) + +niter = length(sol_nonlinear_pendulum.t) +=# \ No newline at end of file From 2c387d8644563da312e0c874089341a25391351e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Tue, 11 Jun 2024 23:28:43 +0200 Subject: [PATCH 26/39] some change in the modif_step! --- .../test_for_relaxation_perform_step.jl | 90 ++++++++++--------- test/regression/test_relaxation.jl | 12 ++- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index fe75c00a25..e7e806195b 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -14,7 +14,7 @@ function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) end -function perform_step!(integrator, cache::Tsit5ConstantCache_for_relaxation, repeat_step = false) +function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5ConstantCache_for_relaxation}, repeat_step = false) # Variable to know if dt has changed during perform_step integrator.dt_has_changed = false @@ -72,34 +72,65 @@ end function modif_step!(integrator) - # Perform the modifications if !(integrator.opts.modif isa Nothing) + + # Perform the modifications integrator.opts.modif(integrator) - # Here we check the validity of chaging dt if it has changed - # if it is valid integrator.changed_valid will be true, if not it will be false - changed_valid = true + # Here we carry of the dt modified by the user in this step, if it has been changed. + if integrator.dt_has_changed - # check dt in [dtmin, dtmax] + # Memory of the current user dt_changed + tmp = integrator.dt_changed - # surely other things - if changed_valid - integrator.u_propose = integrator.u_changed - integrator.dt = integrator.dt_changed + # match dt in [dtmin, dtmax] + if integrator.tdir > 0 + integrator.dt_changed = min(integrator.opts.dtmax, integrator.dt_changed) else - # print error or warning + integrator.dt_changed = max(integrator.opts.dtmax, integrator.dt_changed) + end + dtmin = timedepentdtmin(integrator) + if integrator.tdir > 0 + integrator.dt_changed = max(integrator.dt_changed, dtmin) + else + integrator.dt_changed = min(integrator.dt_changed, dtmin) + end + + if tmp != integrator.dt_has_changed + @warning "The modification of dt during the user modification step was not in [dtmin, dtmax]. + As a consequence, it has been projected onto [dtmin, dtmax]." + end + + # Memory of the current user dt_changed + tmp = integrator.dt_changed + + # match dt with tstops + if has_tstop(integrator) + tdir_t = integrator.tdir * integrator.t + tdir_tstop = first_tstop(integrator) + integrator.dt_changed = integrator.tdir * min(abs(integrator.dt_changed), abs(tdir_tstop - tdir_t)) + end + + if tmp != integrator.dt_has_changed + @warning "The modification of dt during the user modification step " end + + integrator.dt = integrator.dt_changed + end + + if integrator.u_has_changed + integrator.u = integrator.u_changed + else + integrator.u = integrator.u_propose end end end -function finalize_step!(integrator, cache::Tsit5ConstantCache_for_relaxation) - @unpack t, dt, uprev, u_propose, f, p = integrator - integrator.u = u_propose - integrator.fsallast = f(u_propose, p, t + dt) - +function finalize_step!(integrator, ::Tsit5ConstantCache_for_relaxation) + @unpack t, dt, u, f, p = integrator + integrator.fsallast = f(u, p, t + dt) integrator.stats.nf += 7 end @@ -124,26 +155,6 @@ function initialize!(integrator, cache::Tsit5Cache_for_relaxation) end -function perform_step!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) - - # Variable to know if dt has changed during perform_step - integrator.dt_has_changed = false - - # computations! will only contain the mathematical scheme - # i.e the computations of the u(t+dt) - # the result is store not in integrator.u but integrator.u_propose - computations!(integrator, cache, repeat_step) - - # modif_step! enables to modify the step like when we want to perform a relaxation - # for this we give a new struture that can be defined either by us for already known - # modification we want to do or by a user (see below) - modif_step!(integrator) - - # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal - # and register integrator.u - finalize_step!(integrator, cache) -end - @muladd function computations!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) @unpack t, dt, uprev, u_propose, f, p = integrator T = constvalue(recursive_unitless_bottom_eltype(u_propose)) @@ -191,12 +202,11 @@ end end function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) - @unpack t, dt, u_propose, u, f, p = integrator - @unpack k7, stage_limiter!, step_limiter!, thread = cache - @.. broadcast=false thread=thread u = u_propose + @unpack t, dt, u, f, p = integrator + @unpack k7, stage_limiter!, step_limiter!, thread = cache stage_limiter!(u, integrator, p, t + dt) step_limiter!(u, integrator, p, t + dt) - f(k7, u_propose, p, t + dt) + f(k7, u_cache, p, t + dt) integrator.stats.nf += 7 end diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index e192a9667c..2e6e94cf7f 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -34,17 +34,18 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation()) ### Compareason of interpolation +using Plots + sol1 = solve(probnum, Tsit5()) sol2 = solve(probnum, Tsit5_for_relaxation()) sol3 = solve(prob, Tsit5()) sol4 = solve(prob, Tsit5_for_relaxation()) -using Plots + plot(sol1, label = "Old") plot!(sol2, label = "New") -plot(sol3, label = "Old") -plot!(sol4, label = "New") + ######################################################################### @@ -104,10 +105,11 @@ function (r::Relaxation)(integrator) end #r = Relaxation(SAMIN(), x->x.^2) -r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) ## Tests relaxation on problem +#= + # Harmonic Oscillator f_oscillator = (u, p, t) -> [-u[2],u[1]] prob_oscillator = ODEProblem( @@ -125,6 +127,8 @@ plot(sol_oscillator) plot!(sol_oscillator.t, [sol_exact[i][1] for i in 1:niter], label = "exact u[1]", lw = 4) plot!(sol_oscillator.t, [sol_exact[i][2] for i in 1:niter], label = "exact u[2]", lw = 4) +=# + # Non Linear Oscillator #= f_nonlinear_oscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] From 83bd06ceede526b0f6b6fba91843abbf6a71a2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:18:42 +0200 Subject: [PATCH 27/39] fix bug --- .../test_for_relaxation_perform_step.jl | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index e7e806195b..649bd94ebb 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -18,6 +18,7 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C # Variable to know if dt has changed during perform_step integrator.dt_has_changed = false + integrator.u_has_changed = false # computations! will only contain the mathematical scheme # i.e the computations of the u(t+dt) @@ -98,7 +99,7 @@ function modif_step!(integrator) end if tmp != integrator.dt_has_changed - @warning "The modification of dt during the user modification step was not in [dtmin, dtmax]. + @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. As a consequence, it has been projected onto [dtmin, dtmax]." end @@ -113,18 +114,18 @@ function modif_step!(integrator) end if tmp != integrator.dt_has_changed - @warning "The modification of dt during the user modification step " + @warn "The modification of dt during the user modification step " end integrator.dt = integrator.dt_changed end - - if integrator.u_has_changed - integrator.u = integrator.u_changed - else - integrator.u = integrator.u_propose - end end + if integrator.u_has_changed + integrator.u = integrator.u_changed + else + integrator.u = integrator.u_propose + end + end @@ -206,7 +207,7 @@ function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) @unpack k7, stage_limiter!, step_limiter!, thread = cache stage_limiter!(u, integrator, p, t + dt) step_limiter!(u, integrator, p, t + dt) - f(k7, u_cache, p, t + dt) + f(k7, u, p, t + dt) integrator.stats.nf += 7 end From 8ff5be9f4084ffe035a7aab34a756e97820864c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Wed, 12 Jun 2024 23:57:17 +0200 Subject: [PATCH 28/39] first test to compare relaxation with no relaxation --- src/note on a new structure for perform_step | 14 ++ .../test_for_relaxation_perform_step.jl | 7 +- test/regression/test_relaxation.jl | 125 ++++++++++-------- 3 files changed, 84 insertions(+), 62 deletions(-) diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step index ec5c91b1a2..6096fbcd11 100644 --- a/src/note on a new structure for perform_step +++ b/src/note on a new structure for perform_step @@ -21,3 +21,17 @@ Note : --> in that way it could be possible to run once the user modification to get basic element of the cas as u_changed, instead of storing it directly + +#### + #using Optimization + #using OptimizationOptimJL + # first method tried (seems to not work) + #= + prob_optim = OptimizationProblem( + (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), + [dt]; + lb = [gamma_min], + ub = [gamma_max]) + gamma_opt = solve(prob_optim, r.opt).u[1] + #r = Relaxation(SAMIN(), x->x.^2) + =# diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 649bd94ebb..a4f6f2bb91 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -98,9 +98,8 @@ function modif_step!(integrator) integrator.dt_changed = min(integrator.dt_changed, dtmin) end - if tmp != integrator.dt_has_changed - @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. - As a consequence, it has been projected onto [dtmin, dtmax]." + if tmp != integrator.dt_changed + @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. As a consequence, it has been projected onto [dtmin, dtmax]." end # Memory of the current user dt_changed @@ -113,7 +112,7 @@ function modif_step!(integrator) integrator.dt_changed = integrator.tdir * min(abs(integrator.dt_changed), abs(tdir_tstop - tdir_t)) end - if tmp != integrator.dt_has_changed + if tmp != integrator.dt_changed @warn "The modification of dt during the user modification step " end diff --git a/test/regression/test_relaxation.jl b/test/regression/test_relaxation.jl index 2e6e94cf7f..1406c5c44a 100644 --- a/test/regression/test_relaxation.jl +++ b/test/regression/test_relaxation.jl @@ -51,8 +51,7 @@ plot!(sol2, label = "New") ######################################################################### ## Trying relaxation step -#using Optimization -#using OptimizationOptimJL + using Roots using LinearAlgebra using UnPack @@ -68,94 +67,104 @@ function (r::Relaxation)(integrator) @unpack t, dt, uprev, u_propose = integrator # We fix here the bounds of interval where we are going to look for the relaxation - (gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt + #(gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt S_u = u_propose - uprev - # Minimization - # first method tried (seems to not work) - #= - prob_optim = OptimizationProblem( - (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), - [dt]; - lb = [gamma_min], - ub = [gamma_max]) - gamma_opt = solve(prob_optim, r.opt).u[1] - =# - # second method + # Find relaxation paramter gamma gamma_min = 0.5 gamma_max = 1.5 - terminate_integrator = false - if (r.invariant(gamma_min*S_u .+ uprev) .- r.invariant(uprev)) * (r.invariant(gamma_max*S_u .+ uprev) .- r.invariant(uprev)) > 0 - gamma_opt = one(td) - terminate_integrator = true - else - gamma_opt = find_zero( gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), - (max(gamma_min,0.5), min(gamma_max,1.5)), + + if (r.invariant(gamma_min*S_u .+ uprev) .- r.invariant(uprev)) * (r.invariant(gamma_max*S_u .+ uprev) .- r.invariant(uprev)) ≤ 0 + gamma = find_zero(gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), + (gamma_min, gamma_max), r.opt()) + + change_dt!(integrator, gamma*dt) + change_u!(integrator, uprev + gamma*S_u) end - # Updates - change_dt!(integrator, gamma_opt*dt) - change_u!(integrator, uprev + gamma_opt*S_u) + # println("###################### Print of dt time") + # @show integrator.dt + # @show integrator.dt_changed + # @show integrator.opts.dtmin + # @show integrator.opts.dtmax + # if has_tstop(integrator) + # @show first_tstop(integrator) - integrator.t + # end - #if terminate_integrator - # terminate!(integrator) - #end end -#r = Relaxation(SAMIN(), x->x.^2) -## Tests relaxation on problem +######################################################## +# TEST 1 : Harmonic Oscillator +printstyled("Harmonic Oscillator\n"; bold = true) -#= - -# Harmonic Oscillator f_oscillator = (u, p, t) -> [-u[2],u[1]] prob_oscillator = ODEProblem( ODEFunction(f_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), [1.0, 0.0], (0.0, 1.0)) - r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) -sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r, maxiters = 5) -sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] -niter = length(sol_oscillator.t) +#sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) +#sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] +#plot(sol_oscillator) +#plot!(sol_oscillator.t, [sol_exact[i][1] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[1]", lw = 4) +#plot!(sol_oscillator.t, [sol_exact[i][2] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[2]", lw = 4) -plot(sol_oscillator) -plot!(sol_oscillator.t, [sol_exact[i][1] for i in 1:niter], label = "exact u[1]", lw = 4) -plot!(sol_oscillator.t, [sol_exact[i][2] for i in 1:niter], label = "exact u[2]", lw = 4) +sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) +sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) +sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) +println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) -=# -# Non Linear Oscillator -#= -f_nonlinear_oscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] -prob_nonlinear_oscillator = ODEProblem( - ODEFunction(f_nonlinear_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), + +######################################################## +# TEST 2 : Non Linear Oscillator +printstyled("Non linear Harmonic Oscillator\n"; bold = true) + +f_nloscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] +prob_nloscillator = ODEProblem( + ODEFunction(f_nloscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), [1.0, 0.0], (0.0, 1.0)) +r_nloscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) + +sol_nloscillator = solve(prob_nloscillator, Tsit5_for_relaxation()) +sol_exact = [prob_oscillator.f.analytic(prob_nloscillator.u0, prob_nloscillator.p, t) for t in sol_nloscillator.t] -r_nonlinear_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) +sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) +sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) +sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) +println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) -sol_nonlinear_oscillator = solve(prob_nonlinear_oscillator, Tsit5_for_relaxation()) -sol_exact = [prob_oscillator.f.analytic(prob_nonlinear_oscillator.u0, prob_nonlinear_oscillator.p, t) for t in sol_nonlinear_oscillator.t] -niter = length(sol_nonlinear_oscillator.t) +######################################################## +# TEST 3 : Non Linear Pendulum +printstyled("Non linear Pendulum\n"; bold = true) -# Non Linear Pendulum -f_nonlinear_pendulum = (u, p, t) -> [-sin(u[2]), u[1]] -prob_nonlinear_pendulum = ODEProblem( - f_nonlinear_pendulum, +f_nlpendulum = (u, p, t) -> [-sin(u[2]), u[1]] +prob_nlpendulum = ODEProblem( + f_nlpendulum, [1.0, 0.0], (0.0, 1.0)) +r_nlpendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) -r_nonlinear_pendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) +#sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = f_nlpendulum) +#sol_ref = solve(prob_nlpendulum, Vern9()) -sol_nonlinear_pendulum = solve(prob_nonlinear_pendulum, Tsit5_for_relaxation()) - -sol_ref = solve(prob_nonlinear_pendulum, Vern9()) +#= +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(); modif = r_nlpendulum) +println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) +=# -niter = length(sol_nonlinear_pendulum.t) =# \ No newline at end of file From 513820228b0ebb4bddc1c2bc340031b9d913e192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Thu, 13 Jun 2024 22:08:04 +0200 Subject: [PATCH 29/39] Create benchmark in time.ipynb --- test/relaxation/benchmark in time.ipynb | 164 ++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 test/relaxation/benchmark in time.ipynb diff --git a/test/relaxation/benchmark in time.ipynb b/test/relaxation/benchmark in time.ipynb new file mode 100644 index 0000000000..660a0e7ea0 --- /dev/null +++ b/test/relaxation/benchmark in time.ipynb @@ -0,0 +1,164 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### **Check if the new structure is not slowing down the code**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools\n", + "\n", + "import ODEProblemLibrary: prob_ode_linear,\n", + " prob_ode_2Dlinear\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the previous structure :" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 10000 samples with 10 evaluations.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.710 μs\u001b[22m\u001b[39m … \u001b[35m979.630 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 99.17%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m2.250 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.679 μs\u001b[22m\u001b[39m ± \u001b[32m 15.179 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m14.44% ± 2.94%\n", + "\n", + " \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▅\u001b[34m▅\u001b[39m\u001b[39m█\u001b[39m▅\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", + " \u001b[39m▁\u001b[39m▃\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m█\u001b[39m▆\u001b[39m▄\u001b[39m▅\u001b[39m▃\u001b[39m▅\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m▃\u001b[39m▃\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[32m▂\u001b[39m\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▂\n", + " 1.71 μs\u001b[90m Histogram: frequency by time\u001b[39m 3.95 μs \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m4.47 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m36\u001b[39m." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@benchmark solve(prob_ode_linear, Tsit5())" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 10000 samples with 6 evaluations.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.867 μs\u001b[22m\u001b[39m … \u001b[35m356.233 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 93.58%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.583 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.681 μs\u001b[22m\u001b[39m ± \u001b[32m 11.279 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.93% ± 4.01%\n", + "\n", + " \u001b[39m▂\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m▇\u001b[39m\u001b[39m▅\u001b[39m▄\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[32m▃\u001b[39m\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m \u001b[39m█\n", + " 5.87 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 15.1 μs \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m14.70 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m110\u001b[39m." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@benchmark solve(prob_ode_2Dlinear, Tsit5())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the new structure :" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 10000 samples with 10 evaluations.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.700 μs\u001b[22m\u001b[39m … \u001b[35m341.160 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 98.25%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m1.980 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.502 μs\u001b[22m\u001b[39m ± \u001b[32m 9.108 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m11.15% ± 3.09%\n", + "\n", + " \u001b[39m▂\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m▆\u001b[34m▅\u001b[39m\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▃\u001b[39m▂\u001b[32m▁\u001b[39m\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▂\u001b[39m▆\u001b[39m \u001b[39m█\n", + " 1.7 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 4.79 μs \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m4.47 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m36\u001b[39m." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@benchmark solve(prob_ode_linear, Tsit5_for_relaxation())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 10000 samples with 5 evaluations.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.920 μs\u001b[22m\u001b[39m … \u001b[35m360.880 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 95.21%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.380 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.246 μs\u001b[22m\u001b[39m ± \u001b[32m 12.212 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.50% ± 3.80%\n", + "\n", + " \u001b[39m \u001b[39m▄\u001b[39m█\u001b[39m█\u001b[34m▇\u001b[39m\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▄\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▂\u001b[39m▂\u001b[39m▅\u001b[39m▃\u001b[39m▂\u001b[39m▄\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m \u001b[39m█\n", + " 5.92 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 12.2 μs \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m14.70 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m110\u001b[39m." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@benchmark solve(prob_ode_2Dlinear, Tsit5_for_relaxation())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.10.2", + "language": "julia", + "name": "julia-1.10" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.10.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From c88413251d3130c224d1670e4f054da3d00a9b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Thu, 13 Jun 2024 23:12:12 +0200 Subject: [PATCH 30/39] Test FSAL-R --- .../test_for_relaxation_perform_step.jl | 20 ++-- test/relaxation/benchmark in time.ipynb | 56 +++++------ .../convergence.jl} | 95 ++++--------------- test/relaxation/relaxation.jl | 43 +++++++++ 4 files changed, 99 insertions(+), 115 deletions(-) rename test/{regression/test_relaxation.jl => relaxation/convergence.jl} (70%) create mode 100644 test/relaxation/relaxation.jl diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index a4f6f2bb91..7b8a3d8b89 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -41,9 +41,9 @@ end T = constvalue(recursive_unitless_bottom_eltype(u)) T2 = constvalue(typeof(one(t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + k1 = integrator.fsalfirst - a = dt * a21 - k2 = f(uprev + a * k1, p, t + c1 * dt) + k2 = f(uprev + dt * a21 * k1, p, t + c1 * dt) k3 = f(uprev + dt * (a31 * k1 + a32 * k2), p, t + c2 * dt) k4 = f(uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3), p, t + c3 * dt) k5 = f(uprev + dt * (a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4), p, t + c4 * dt) @@ -51,6 +51,9 @@ end k6 = f(g6, p, t + dt) u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) k7 = f(u, p, t + dt) + + integrator.fsallast = k7 + integrator.k[1] = k1 integrator.k[2] = k2 integrator.k[3] = k3 @@ -58,8 +61,9 @@ end integrator.k[5] = k5 integrator.k[6] = k6 integrator.k[7] = k7 - integrator.u_propose = u + integrator.u_propose = u + if integrator.opts.adaptive utilde = dt * (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + @@ -68,8 +72,9 @@ end integrator.opts.reltol, integrator.opts.internalnorm, t) integrator.EEst = integrator.opts.internalnorm(atmp, t) end -end + integrator.stats.nf += 6 +end function modif_step!(integrator) @@ -127,11 +132,10 @@ function modif_step!(integrator) end - function finalize_step!(integrator, ::Tsit5ConstantCache_for_relaxation) - @unpack t, dt, u, f, p = integrator - integrator.fsallast = f(u, p, t + dt) - integrator.stats.nf += 7 + + + end diff --git a/test/relaxation/benchmark in time.ipynb b/test/relaxation/benchmark in time.ipynb index 660a0e7ea0..f3ee147a55 100644 --- a/test/relaxation/benchmark in time.ipynb +++ b/test/relaxation/benchmark in time.ipynb @@ -28,20 +28,20 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "BenchmarkTools.Trial: 10000 samples with 10 evaluations.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.710 μs\u001b[22m\u001b[39m … \u001b[35m979.630 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 99.17%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m2.250 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.679 μs\u001b[22m\u001b[39m ± \u001b[32m 15.179 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m14.44% ± 2.94%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.740 μs\u001b[22m\u001b[39m … \u001b[35m540.050 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 98.64%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m2.300 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.801 μs\u001b[22m\u001b[39m ± \u001b[32m 10.732 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m11.27% ± 3.09%\n", "\n", - " \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▅\u001b[34m▅\u001b[39m\u001b[39m█\u001b[39m▅\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[32m \u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \n", - " \u001b[39m▁\u001b[39m▃\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m█\u001b[39m▆\u001b[39m▄\u001b[39m▅\u001b[39m▃\u001b[39m▅\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m▃\u001b[39m▃\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[32m▂\u001b[39m\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▂\n", - " 1.71 μs\u001b[90m Histogram: frequency by time\u001b[39m 3.95 μs \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m \u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▇\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m▇\u001b[39m▅\u001b[39m▄\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[32m▃\u001b[39m\u001b[39m▂\u001b[39m▃\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▃\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m▃\u001b[39m▅\u001b[39m▂\u001b[39m▆\u001b[39m \u001b[39m█\n", + " 1.74 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 5.16 μs \u001b[0m\u001b[1m<\u001b[22m\n", "\n", " Memory estimate\u001b[90m: \u001b[39m\u001b[33m4.47 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m36\u001b[39m." ] @@ -56,20 +56,20 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "BenchmarkTools.Trial: 10000 samples with 6 evaluations.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.867 μs\u001b[22m\u001b[39m … \u001b[35m356.233 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 93.58%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.583 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.681 μs\u001b[22m\u001b[39m ± \u001b[32m 11.279 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.93% ± 4.01%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.933 μs\u001b[22m\u001b[39m … \u001b[35m397.350 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 94.93%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.567 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.658 μs\u001b[22m\u001b[39m ± \u001b[32m 11.116 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.87% ± 4.02%\n", "\n", - " \u001b[39m▂\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m▇\u001b[39m\u001b[39m▅\u001b[39m▄\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[32m▃\u001b[39m\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", - " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m \u001b[39m█\n", - " 5.87 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 15.1 μs \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m▃\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m▅\u001b[34m▅\u001b[39m\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▅\u001b[32m▅\u001b[39m\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▄\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▄\u001b[39m \u001b[39m█\n", + " 5.93 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 13.6 μs \u001b[0m\u001b[1m<\u001b[22m\n", "\n", " Memory estimate\u001b[90m: \u001b[39m\u001b[33m14.70 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m110\u001b[39m." ] @@ -91,20 +91,20 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "BenchmarkTools.Trial: 10000 samples with 10 evaluations.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.700 μs\u001b[22m\u001b[39m … \u001b[35m341.160 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 98.25%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m1.980 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.502 μs\u001b[22m\u001b[39m ± \u001b[32m 9.108 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m11.15% ± 3.09%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m1.770 μs\u001b[22m\u001b[39m … \u001b[35m505.320 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 97.31%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m2.000 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m2.572 μs\u001b[22m\u001b[39m ± \u001b[32m 10.111 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m11.65% ± 3.08%\n", "\n", - " \u001b[39m▂\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m▆\u001b[34m▅\u001b[39m\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▃\u001b[39m▂\u001b[32m▁\u001b[39m\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", - " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▂\u001b[39m▆\u001b[39m \u001b[39m█\n", - " 1.7 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 4.79 μs \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m▃\u001b[39m▇\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m▆\u001b[39m\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▅\u001b[39m▆\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▃\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▄\u001b[39m \u001b[39m█\n", + " 1.77 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 4.57 μs \u001b[0m\u001b[1m<\u001b[22m\n", "\n", " Memory estimate\u001b[90m: \u001b[39m\u001b[33m4.47 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m36\u001b[39m." ] @@ -119,20 +119,20 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "BenchmarkTools.Trial: 10000 samples with 5 evaluations.\n", - " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.920 μs\u001b[22m\u001b[39m … \u001b[35m360.880 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 95.21%\n", - " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.380 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", - " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.246 μs\u001b[22m\u001b[39m ± \u001b[32m 12.212 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m6.50% ± 3.80%\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m5.920 μs\u001b[22m\u001b[39m … \u001b[35m366.900 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m0.00% … 95.12%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m6.760 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m7.733 μs\u001b[22m\u001b[39m ± \u001b[32m 12.003 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m5.79% ± 3.68%\n", "\n", - " \u001b[39m \u001b[39m▄\u001b[39m█\u001b[39m█\u001b[34m▇\u001b[39m\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▃\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", - " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▄\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▄\u001b[39m▂\u001b[39m▂\u001b[39m▅\u001b[39m▃\u001b[39m▂\u001b[39m▄\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m \u001b[39m█\n", - " 5.92 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 12.2 μs \u001b[0m\u001b[1m<\u001b[22m\n", + " \u001b[39m▁\u001b[39m▆\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[34m▆\u001b[39m\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[32m▅\u001b[39m\u001b[39m▆\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▃\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▇\u001b[39m▆\u001b[39m▅\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m \u001b[39m█\n", + " 5.92 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 13.3 μs \u001b[0m\u001b[1m<\u001b[22m\n", "\n", " Memory estimate\u001b[90m: \u001b[39m\u001b[33m14.70 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m110\u001b[39m." ] diff --git a/test/regression/test_relaxation.jl b/test/relaxation/convergence.jl similarity index 70% rename from test/regression/test_relaxation.jl rename to test/relaxation/convergence.jl index 1406c5c44a..b5b7c3434d 100644 --- a/test/regression/test_relaxation.jl +++ b/test/relaxation/convergence.jl @@ -1,19 +1,21 @@ -using OrdinaryDiffEq, DiffEqDevTools, Test +using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools import ODEProblemLibrary: prob_ode_linear, prob_ode_2Dlinear +include("relaxation.jl") + +######################################################################### +# Check that the code with the new structure without modification asked +# by the user gives the same result +# Comparaison on Tsit5 + probnum = prob_ode_linear prob = prob_ode_2Dlinear dts = (1 / 2) .^ (7:-1:4) testTol = 0.2 - -######################################################################### -# Check that the code with the new structure without modification asked -# by the user gives the same result -# Comparaison on Tist5 ### Tsit5() println("Tsit5") @@ -30,71 +32,11 @@ dts = (1 / 2) .^ (7:-1:3) sim = test_convergence(dts, probnum, Tsit5_for_relaxation()) @test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 sim = test_convergence(dts, prob, Tsit5_for_relaxation()) -@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 - -### Compareason of interpolation - -using Plots - -sol1 = solve(probnum, Tsit5()) -sol2 = solve(probnum, Tsit5_for_relaxation()) - -sol3 = solve(prob, Tsit5()) -sol4 = solve(prob, Tsit5_for_relaxation()) - - -plot(sol1, label = "Old") -plot!(sol2, label = "New") - +@test abs.(sim.𝒪est[:l2] - 5) < testTol + 0.2 ######################################################################### -## Trying relaxation step - - -using Roots -using LinearAlgebra -using UnPack - -struct Relaxation{OPT, INV} - opt::OPT - invariant::INV -end - - -function (r::Relaxation)(integrator) - - @unpack t, dt, uprev, u_propose = integrator - - # We fix here the bounds of interval where we are going to look for the relaxation - #(gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt - - S_u = u_propose - uprev - - # Find relaxation paramter gamma - gamma_min = 0.5 - gamma_max = 1.5 - - if (r.invariant(gamma_min*S_u .+ uprev) .- r.invariant(uprev)) * (r.invariant(gamma_max*S_u .+ uprev) .- r.invariant(uprev)) ≤ 0 - gamma = find_zero(gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), - (gamma_min, gamma_max), - r.opt()) - - change_dt!(integrator, gamma*dt) - change_u!(integrator, uprev + gamma*S_u) - end - - # println("###################### Print of dt time") - # @show integrator.dt - # @show integrator.dt_changed - # @show integrator.opts.dtmin - # @show integrator.opts.dtmax - # if has_tstop(integrator) - # @show first_tstop(integrator) - integrator.t - # end - -end - +## With Relaxation ######################################################## # TEST 1 : Harmonic Oscillator @@ -120,8 +62,6 @@ println("order of convergence of new perform_step! without relaxation: "*string( sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) - - ######################################################## # TEST 2 : Non Linear Oscillator printstyled("Non linear Harmonic Oscillator\n"; bold = true) @@ -143,7 +83,6 @@ println("order of convergence of new perform_step! without relaxation: "*string( sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) - ######################################################## # TEST 3 : Non Linear Pendulum printstyled("Non linear Pendulum\n"; bold = true) @@ -158,13 +97,11 @@ r_nlpendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) #sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = f_nlpendulum) #sol_ref = solve(prob_nlpendulum, Vern9()) -#= -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation()) +test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14) + +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5(), test_setup) println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation()) +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup) println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(); modif = r_nlpendulum) -println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) -=# - -=# \ No newline at end of file +sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup; modif = r_nlpendulum) +println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/relaxation.jl b/test/relaxation/relaxation.jl new file mode 100644 index 0000000000..e15edffc47 --- /dev/null +++ b/test/relaxation/relaxation.jl @@ -0,0 +1,43 @@ +using Roots +using LinearAlgebra +using UnPack + +struct Relaxation{OPT, INV} + opt::OPT + invariant::INV +end + +function (r::Relaxation)(integrator) + + @unpack t, dt, uprev, u_propose = integrator + + # We fix here the bounds of interval where we are going to look for the relaxation + #(gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt + + S_u = u_propose - uprev + + # Find relaxation paramter gamma + gamma_min = 0.5 + gamma_max = 1.5 + + if (r.invariant(gamma_min*S_u .+ uprev) .- r.invariant(uprev)) * (r.invariant(gamma_max*S_u .+ uprev) .- r.invariant(uprev)) ≤ 0 + gamma = find_zero(gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), + (gamma_min, gamma_max), + r.opt()) + + change_dt!(integrator, gamma*dt) + change_u!(integrator, uprev + gamma*S_u) + + integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) + end + + # println("###################### Print of dt time") + # @show integrator.dt + # @show integrator.dt_changed + # @show integrator.opts.dtmin + # @show integrator.opts.dtmax + # if has_tstop(integrator) + # @show first_tstop(integrator) - integrator.t + # end + +end \ No newline at end of file From fa0d5c35bc3a31e3e1e1fd04d05a31aa733d6a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 14 Jun 2024 00:02:55 +0200 Subject: [PATCH 31/39] add more examples exponential entropy doesn't work --- test/relaxation/benchmark in time.ipynb | 97 ++++++++++++++++++++++++- test/relaxation/convergence.jl | 71 +++++++++++++++--- 2 files changed, 153 insertions(+), 15 deletions(-) diff --git a/test/relaxation/benchmark in time.ipynb b/test/relaxation/benchmark in time.ipynb index f3ee147a55..5b45287870 100644 --- a/test/relaxation/benchmark in time.ipynb +++ b/test/relaxation/benchmark in time.ipynb @@ -4,25 +4,30 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### **Check if the new structure is not slowing down the code**" + "### Study on time for solving" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools\n", "\n", "import ODEProblemLibrary: prob_ode_linear,\n", - " prob_ode_2Dlinear\n" + " prob_ode_2Dlinear\n", + "\n", + "\n", + "include(\"relaxation.jl\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "#### Check if the new structure is not slowing down the code\n", + "\n", "For the previous structure :" ] }, @@ -144,6 +149,92 @@ "source": [ "@benchmark solve(prob_ode_2Dlinear, Tsit5_for_relaxation())" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Compare time solving without and with relaxation steps\n", + "\n", + "We do the compareason on the non linear harmonic oscillator : " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Relaxation{DataType, var\"#21#22\"}(AlefeldPotraShi, var\"#21#22\"())" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f_nloscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)]\n", + "prob_nloscillator = ODEProblem(\n", + " ODEFunction(f_nloscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]),\n", + " [1.0, 0.0],\n", + " (0.0, 1.0))\n", + "r_nloscillator = Relaxation(AlefeldPotraShi, x-> norm(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "Without :" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "BenchmarkTools.Trial: 10000 samples with 1 evaluation.\n", + " Range \u001b[90m(\u001b[39m\u001b[36m\u001b[1mmin\u001b[22m\u001b[39m … \u001b[35mmax\u001b[39m\u001b[90m): \u001b[39m\u001b[36m\u001b[1m22.700 μs\u001b[22m\u001b[39m … \u001b[35m 4.386 ms\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmin … max\u001b[90m): \u001b[39m 0.00% … 97.69%\n", + " Time \u001b[90m(\u001b[39m\u001b[34m\u001b[1mmedian\u001b[22m\u001b[39m\u001b[90m): \u001b[39m\u001b[34m\u001b[1m26.700 μs \u001b[22m\u001b[39m\u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmedian\u001b[90m): \u001b[39m 0.00%\n", + " Time \u001b[90m(\u001b[39m\u001b[32m\u001b[1mmean\u001b[22m\u001b[39m ± \u001b[32mσ\u001b[39m\u001b[90m): \u001b[39m\u001b[32m\u001b[1m33.164 μs\u001b[22m\u001b[39m ± \u001b[32m116.550 μs\u001b[39m \u001b[90m┊\u001b[39m GC \u001b[90m(\u001b[39mmean ± σ\u001b[90m): \u001b[39m11.43% ± 3.25%\n", + "\n", + " \u001b[39m▃\u001b[39m▇\u001b[39m█\u001b[39m▇\u001b[39m▆\u001b[39m▅\u001b[34m▅\u001b[39m\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▄\u001b[39m▂\u001b[39m▁\u001b[32m▁\u001b[39m\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m▁\u001b[39m \u001b[39m \u001b[39m▁\u001b[39m▁\u001b[39m▂\u001b[39m▁\u001b[39m▁\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m▂\n", + " \u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[34m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[32m█\u001b[39m\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m█\u001b[39m▇\u001b[39m▇\u001b[39m▇\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▇\u001b[39m▅\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▆\u001b[39m▅\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m▆\u001b[39m▅\u001b[39m▅\u001b[39m \u001b[39m█\n", + " 22.7 μs\u001b[90m \u001b[39m\u001b[90mHistogram: \u001b[39m\u001b[90m\u001b[1mlog(\u001b[22m\u001b[39m\u001b[90mfrequency\u001b[39m\u001b[90m\u001b[1m)\u001b[22m\u001b[39m\u001b[90m by time\u001b[39m 63.9 μs \u001b[0m\u001b[1m<\u001b[22m\n", + "\n", + " Memory estimate\u001b[90m: \u001b[39m\u001b[33m50.98 KiB\u001b[39m, allocs estimate\u001b[90m: \u001b[39m\u001b[33m622\u001b[39m." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@benchmark solve(prob_nloscillator, Tsit5())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With :" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@benchmark solve(prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator)" + ] } ], "metadata": { diff --git a/test/relaxation/convergence.jl b/test/relaxation/convergence.jl index b5b7c3434d..59828f5571 100644 --- a/test/relaxation/convergence.jl +++ b/test/relaxation/convergence.jl @@ -13,7 +13,7 @@ include("relaxation.jl") probnum = prob_ode_linear prob = prob_ode_2Dlinear -dts = (1 / 2) .^ (7:-1:4) + testTol = 0.2 ### Tsit5() @@ -38,6 +38,8 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation()) ######################################################################### ## With Relaxation +dts = (1 / 2) .^ (6:-1:4) + ######################################################## # TEST 1 : Harmonic Oscillator printstyled("Harmonic Oscillator\n"; bold = true) @@ -55,12 +57,12 @@ r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) #plot!(sol_oscillator.t, [sol_exact[i][1] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[1]", lw = 4) #plot!(sol_oscillator.t, [sol_exact[i][2] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[2]", lw = 4) -sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) -println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) -sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) -println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) -sim = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) -println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) +sim_oscillator_old = test_convergence(dts, prob_oscillator, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim_oscillator_old.𝒪est[:final])) +sim_oscillator_new = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim_oscillator_new.𝒪est[:final])) +sim_oscillator_relax = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) +println("order of convergence of new perform_step! with relaxation: "*string(sim_oscillator_relax.𝒪est[:final])) ######################################################## # TEST 2 : Non Linear Oscillator @@ -73,10 +75,10 @@ prob_nloscillator = ODEProblem( (0.0, 1.0)) r_nloscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) -sol_nloscillator = solve(prob_nloscillator, Tsit5_for_relaxation()) -sol_exact = [prob_oscillator.f.analytic(prob_nloscillator.u0, prob_nloscillator.p, t) for t in sol_nloscillator.t] +#sol_nloscillator = solve(prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) +#sol_exact = [prob_oscillator.f.analytic(prob_nloscillator.u0, prob_nloscillator.p, t) for t in sol_nloscillator.t] -sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation()) +sim = test_convergence(dts, prob_nloscillator, Tsit5()) println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation()) println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) @@ -94,7 +96,7 @@ prob_nlpendulum = ODEProblem( (0.0, 1.0)) r_nlpendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) -#sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = f_nlpendulum) +#sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = r_nlpendulum) #sol_ref = solve(prob_nlpendulum, Vern9()) test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14) @@ -104,4 +106,49 @@ println("order of convergence of older perform_step! : "*string(sim.𝒪est[:fin sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup) println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup; modif = r_nlpendulum) -println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) \ No newline at end of file +println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) + + +@benchmark solve(prob_nloscillator, Tsit5_for_relaxation()) + +############################################################################ +# TEST 4 : Time dependent harmonic oscillator with bounded angular velocity + +printstyled("Time dependent harmonic oscillator\n"; bold = true) + +f_td_oscillator = (u, p, t) -> [-(1+0.5 * sin(t))*u[2], (1+0.5 * sin(t))*u[1]] +prob_td_oscillator = ODEProblem( + ODEFunction(f_td_oscillator; + analytic = (u0, p, t)->[cos(0.5)*cos(t-0.5*cos(t))-sin(0.5)*sin(t-0.5*cos(t)), + sin(0.5)*cos(t-0.5*cos(t))+cos(0.5)*sin(t-0.5*cos(t))]), + [1.0, 0.0], + (0.0, 1.0)) +r_td_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) + +sim_td_oscillator_old = test_convergence(dts, prob_td_oscillator, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim_td_oscillator_old.𝒪est[:final])) +sim_td_oscillator_new = test_convergence(dts, prob_td_oscillator, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim_td_oscillator_new.𝒪est[:final])) +sim_td_oscillator_relax = test_convergence(dts, prob_td_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) +println("order of convergence of new perform_step! with relaxation: "*string(sim_td_oscillator_relax.𝒪est[:final])) + +############################################################################ +# TEST 5 : Conserved exponential entropy + +printstyled("Conserved exponential entropy\n"; bold = true) + +f_cee = (u, p, t) -> [-exp(u[2]), exp(u[1])] +prob_cee = ODEProblem( + ODEFunction(f_cee ; + analytic = (u0, p, t)->[log(exp(1) + exp(0.5)) - log(exp(0.5) + exp((exp(0.5)+exp(1))*t)), + log(exp((exp(0.5)+exp(1))*t)*(exp(0.5)+exp(1)))/(exp(0.5) + exp((exp(0.5)+exp(1))*t))]), + [1.0, 0.5], + (0.0, 1.0)) +r_cee = Relaxation(AlefeldPotraShi, x-> exp(x[1]) + exp(x[2])) + +sim_cee_old = test_convergence(dts, prob_cee, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim_cee_old.𝒪est[:final])) +sim_cee_new = test_convergence(dts, prob_cee, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim_cee_new.𝒪est[:final])) +sim_cee_relax = test_convergence(dts, prob_cee, Tsit5_for_relaxation(); modif = r_oscillator) +println("order of convergence of new perform_step! with relaxation: "*string(sim_cee_relax.𝒪est[:final])) \ No newline at end of file From 3287f82d1d659255d72836686dd5baffa167b295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:02:45 +0200 Subject: [PATCH 32/39] Relaxation v2 --- .../test_for_relaxation_perform_step.jl | 164 ++++++++++-------- 1 file changed, 91 insertions(+), 73 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 7b8a3d8b89..060a05741a 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -3,7 +3,6 @@ function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) integrator.fsalfirst = integrator.f(integrator.uprev, integrator.p, integrator.t) # Pre-start fsal integrator.stats.nf += 1 - # Avoid undefined entries if k is an array of arrays integrator.fsallast = zero(integrator.fsalfirst) integrator.k[1] = integrator.fsalfirst @@ -13,6 +12,24 @@ function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) integrator.k[integrator.kshortsize] = integrator.fsallast end +function initialize!(integrator, cache::Tsit5Cache_for_relaxation) + integrator.kshortsize = 7 + integrator.fsalfirst = cache.k1 + integrator.fsallast = cache.k7 # setup pointers + resize!(integrator.k, integrator.kshortsize) + # Setup k pointers + integrator.k[1] = cache.k1 + integrator.k[2] = cache.k2 + integrator.k[3] = cache.k3 + integrator.k[4] = cache.k4 + integrator.k[5] = cache.k5 + integrator.k[6] = cache.k6 + integrator.k[7] = cache.k7 + integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # Pre-start fsal + integrator.stats.nf += 1 + return nothing +end + function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5ConstantCache_for_relaxation}, repeat_step = false) @@ -20,10 +37,19 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C integrator.dt_has_changed = false integrator.u_has_changed = false - # computations! will only contain the mathematical scheme - # i.e the computations of the u(t+dt) - # the result is store not in integrator.u but integrator.u_propose - computations!(integrator, cache, repeat_step) + # Caculate uₙ₊₁ + calculate_nextstep!(integrator, cache, repeat_step) + + # Calculate f(uₙ₊₁) if the aglortihm has the FSAL property + if isfsal(integrator.alg) + calculate_fsal!(integrator, cache) + end + + # Calculate the error estimate needed for PID controller + if integrator.opts.adaptive + calculate_EEst!(integrator, cache) + end + # modif_step! enables to modify the step like when we want to perform a relaxation # for this we give a new struture that can be defined either by us for already known @@ -36,7 +62,8 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C end -@muladd function computations!(integrator, ::Tsit5ConstantCache_for_relaxation, repeat_step = false) +@muladd function calculate_nextstep!(integrator, ::Tsit5ConstantCache_for_relaxation, repeat_step = false) + @unpack t, dt, uprev, u, f, p = integrator T = constvalue(recursive_unitless_bottom_eltype(u)) T2 = constvalue(typeof(one(t))) @@ -47,33 +74,39 @@ end k3 = f(uprev + dt * (a31 * k1 + a32 * k2), p, t + c2 * dt) k4 = f(uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3), p, t + c3 * dt) k5 = f(uprev + dt * (a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4), p, t + c4 * dt) - g6 = uprev + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) - k6 = f(g6, p, t + dt) + k6 = f(uprev + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5), p, t + dt) u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) - k7 = f(u, p, t + dt) - integrator.fsallast = k7 - integrator.k[1] = k1 integrator.k[2] = k2 integrator.k[3] = k3 integrator.k[4] = k4 integrator.k[5] = k5 integrator.k[6] = k6 - integrator.k[7] = k7 - integrator.u_propose = u - - if integrator.opts.adaptive - utilde = dt * - (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + - btilde6 * integrator.k[6] + btilde7 * integrator.k[7]) - atmp = calculate_residuals(utilde, uprev, u, integrator.opts.abstol, - integrator.opts.reltol, integrator.opts.internalnorm, t) - integrator.EEst = integrator.opts.internalnorm(atmp, t) - end - integrator.stats.nf += 6 + integrator.stats.nf += 5 +end + +@muladd function calculate_fsal!(integrator, ::Tsit5ConstantCache_for_relaxation) + @unpack t, dt, u, f, p = integrator + k7 = f(u, p, t + dt) + integrator.k[7] = k7 + integrator.fsallast = k7 + integrator.stats.nf += 1 +end + +@muladd function calculate_EEst!(integrator, ::Tsit5ConstantCache_for_relaxation) + T = constvalue(recursive_unitless_bottom_eltype(u)) + T2 = constvalue(typeof(one(t))) + @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + utilde = integrator.dt * (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + + btilde5 * integrator.k[5] + btilde6 * integrator.k[6] + + btilde7 * integrator.k[7]) + atmp = calculate_residuals(utilde, integrator.uprev, integrator.u, integrator.opts.abstol, + integrator.opts.reltol, integrator.opts.internalnorm, integrator.t) + integrator.EEst = integrator.opts.internalnorm(atmp, integrator.t) end function modif_step!(integrator) @@ -133,88 +166,73 @@ function modif_step!(integrator) end function finalize_step!(integrator, ::Tsit5ConstantCache_for_relaxation) - - - + end ## Non Constant cache -function initialize!(integrator, cache::Tsit5Cache_for_relaxation) - integrator.kshortsize = 7 - integrator.fsalfirst = cache.k1 - integrator.fsallast = cache.k7 # setup pointers - resize!(integrator.k, integrator.kshortsize) - # Setup k pointers - integrator.k[1] = cache.k1 - integrator.k[2] = cache.k2 - integrator.k[3] = cache.k3 - integrator.k[4] = cache.k4 - integrator.k[5] = cache.k5 - integrator.k[6] = cache.k6 - integrator.k[7] = cache.k7 - integrator.f(integrator.fsalfirst, integrator.uprev, integrator.p, integrator.t) # Pre-start fsal - integrator.stats.nf += 1 - return nothing -end - -@muladd function computations!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) +@muladd function calculate_nextstep!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) + @unpack t, dt, uprev, u_propose, f, p = integrator T = constvalue(recursive_unitless_bottom_eltype(u_propose)) T2 = constvalue(typeof(one(t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 @unpack k1, k2, k3, k4, k5, k6, k7, utilde, tmp, atmp, stage_limiter!, step_limiter!, thread = cache - a = dt * a21 - @.. broadcast=false thread=thread tmp=uprev + a * k1 + + @.. broadcast=false thread=thread tmp = uprev + dt * a21 * k1 stage_limiter!(tmp, f, p, t + c1 * dt) f(k2, tmp, p, t + c1 * dt) - @.. broadcast=false thread=thread tmp=uprev + dt * (a31 * k1 + a32 * k2) + @.. broadcast=false thread=thread tmp = uprev + dt * (a31 * k1 + a32 * k2) stage_limiter!(tmp, f, p, t + c2 * dt) f(k3, tmp, p, t + c2 * dt) - @.. broadcast=false thread=thread tmp=uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3) + @.. broadcast=false thread=thread tmp = uprev + dt * (a41 * k1 + a42 * k2 + a43 * k3) stage_limiter!(tmp, f, p, t + c3 * dt) f(k4, tmp, p, t + c3 * dt) - @.. broadcast=false thread=thread tmp=uprev + + @.. broadcast=false thread=thread tmp = uprev + dt * (a51 * k1 + a52 * k2 + a53 * k3 + a54 * k4) stage_limiter!(tmp, f, p, t + c4 * dt) f(k5, tmp, p, t + c4 * dt) - @.. broadcast=false thread=thread tmp=uprev + - dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + - a65 * k5) + @.. broadcast=false thread=thread tmp = uprev + + dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) stage_limiter!(tmp, f, p, t + dt) f(k6, tmp, p, t + dt) @.. broadcast=false thread=thread u_propose = uprev + - dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + - a75 * k5 + a76 * k6) + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) stage_limiter!(u_propose, integrator, p, t + dt) step_limiter!(u_propose, integrator, p, t + dt) - f(k7, u_propose, p, t + dt) - - if integrator.opts.adaptive - @.. broadcast=false thread=thread utilde=dt * (btilde1 * k1 + btilde2 * k2 + - btilde3 * k3 + btilde4 * k4 + - btilde5 * k5 + btilde6 * k6 + - btilde7 * k7) - calculate_residuals!(atmp, utilde, uprev, u_propose, integrator.opts.abstol, - integrator.opts.reltol, integrator.opts.internalnorm, t, - thread) - integrator.EEst = integrator.opts.internalnorm(atmp, t) - end + integrator.stats.nf += 5 return nothing end -function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) +@muladd function calculate_fsal!(integrator, cache::Tsit5Cache_for_relaxation) @unpack t, dt, u, f, p = integrator - @unpack k7, stage_limiter!, step_limiter!, thread = cache - stage_limiter!(u, integrator, p, t + dt) - step_limiter!(u, integrator, p, t + dt) - f(k7, u, p, t + dt) - integrator.stats.nf += 7 + f(cache.k7, u, p, t + dt) + integrator.stats.nf += 1 end +@muladd function calculate_EEst!(integrator, cache::Tsit5Cache_for_relaxation) + T = constvalue(recursive_unitless_bottom_eltype(u)) + T2 = constvalue(typeof(one(t))) + @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 + @unpack k1, k2, k3, k4, k5, k6, k7, utilde, atmp, thread = cache + @.. broadcast = false thread = threa utilde = integrator.dt * + (btilde1 * k1 + btilde2 * k2 + btilde3 * k3 + btilde4 * k4 + + btilde5 * k5 + btilde6 * k6 + btilde7 * k7) + calculate_residuals!(atmp, utilde, integrator.uprev, integrator.u_propose, + integrator.opts.abstol, integrator.opts.reltol, + integrator.opts.internalnorm, integrator.t, thread) + integrator.EEst = integrator.opts.internalnorm(atmp, integrator.t) +end + +function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) + +end + + +# Is this useful ? function apriori_bounds_dt(integrator) dt_sup = if has_tstop(integrator) integrator.tdir * min(abs(integrator.opts.dtmax) , abs(first_tstop(integrator) - integrator.t)) From 1111c380f0eb175c0cff991582fa162863668e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Fri, 14 Jun 2024 23:50:20 +0200 Subject: [PATCH 33/39] New way with PerformStepCallBack --- src/OrdinaryDiffEq.jl | 4 + src/integrators/integrator_interface.jl | 4 +- src/integrators/type.jl | 2 +- src/note on a new structure for perform_step | 37 ---- .../test_for_relaxation_perform_step.jl | 171 +++++++++++------- src/performstep_callback.jl | 28 +++ src/solve.jl | 2 +- 7 files changed, 140 insertions(+), 108 deletions(-) delete mode 100644 src/note on a new structure for perform_step create mode 100644 src/performstep_callback.jl diff --git a/src/OrdinaryDiffEq.jl b/src/OrdinaryDiffEq.jl index 2cae4c536d..d0d017dfc1 100644 --- a/src/OrdinaryDiffEq.jl +++ b/src/OrdinaryDiffEq.jl @@ -130,6 +130,10 @@ import Preferences DEFAULT_PRECS(W, du, u, p, t, newW, Plprev, Prprev, solverdata) = nothing, nothing +export AbstractPerformStepCallback, NoPerformStepCallback, PerformStepCallback + +include("performstep_callback.jl") + include("doc_utils.jl") include("misc_utils.jl") diff --git a/src/integrators/integrator_interface.jl b/src/integrators/integrator_interface.jl index b9a7c686ac..5cb34f3005 100644 --- a/src/integrators/integrator_interface.jl +++ b/src/integrators/integrator_interface.jl @@ -518,5 +518,7 @@ function change_u!(integrator::ODEIntegrator, u) integrator.u_changed = u end - +has_poststep_callback(integrator::ODEIntegrator) = has_poststep_callback(integrator.opts.performstepcallback) +has_postfsal_callback(integrator::ODEIntegrator) = has_postfsal_callback(integrator.opts.performstepcallback) +has_postEEst_callback(integrator::ODEIntegrator) = has_postEEst_callback(integrator.opts.performstepcallback) diff --git a/src/integrators/type.jl b/src/integrators/type.jl index a1d9ee3f96..5d225958ec 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -46,7 +46,7 @@ mutable struct DEOptions{absType, relType, QT, tType, Controller, F1, F2, F3, F4 force_dtmin::Bool advance_to_tstop::Bool stop_at_next_tstop::Bool - modif::MT + modif::AbstractPerformStepCallback end TruncatedStacktraces.@truncate_stacktrace DEOptions diff --git a/src/note on a new structure for perform_step b/src/note on a new structure for perform_step deleted file mode 100644 index 6096fbcd11..0000000000 --- a/src/note on a new structure for perform_step +++ /dev/null @@ -1,37 +0,0 @@ -Here is few notes about having a new structure of the code concerning the step perform_step! : - -News parameters to integrator: -- u_propose -- u_changed -- dt_has_changed -- dt_changed -- u_has_changed - -New DEOptions -- modif : a callable object to custom computation right after perform_step ---> a beter name could be "modif_step" - -Possible function to implement -- change_u, change_dt DONE -- dt_interval should be implemented - -Note : -- Prefer "modified" as kee word instead of "changed" -- maybe should create a cache for modify function to have best performance ---> in that way it could be possible to run once the user modification to get basic element of the cas as u_changed, instead of storing it directly - - - -#### - #using Optimization - #using OptimizationOptimJL - # first method tried (seems to not work) - #= - prob_optim = OptimizationProblem( - (gamma,p) -> norm(r.invariant(gamma[1]*S_u .+ uprev) .- r.invariant(uprev)), - [dt]; - lb = [gamma_min], - ub = [gamma_max]) - gamma_opt = solve(prob_optim, r.opt).u[1] - #r = Relaxation(SAMIN(), x->x.^2) - =# diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 060a05741a..d175e9cee2 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -1,3 +1,4 @@ + function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) integrator.kshortsize = 7 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) @@ -30,37 +31,127 @@ function initialize!(integrator, cache::Tsit5Cache_for_relaxation) return nothing end - function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5ConstantCache_for_relaxation}, repeat_step = false) - # Variable to know if dt has changed during perform_step - integrator.dt_has_changed = false - integrator.u_has_changed = false - # Caculate uₙ₊₁ calculate_nextstep!(integrator, cache, repeat_step) + # Perform customize modification right after the step, i.e modify uₙ₊₁ + if has_poststep_callback(integrator) + apply_poststep_callback(integrator) + end + # Calculate f(uₙ₊₁) if the aglortihm has the FSAL property if isfsal(integrator.alg) calculate_fsal!(integrator, cache) end + # Perform customize modification right after fsal, i.e modify f(uₙ₊₁) + if has_postfsal_callback(integrator) + apply_postfsal_callback(integrator) + end + # Calculate the error estimate needed for PID controller if integrator.opts.adaptive calculate_EEst!(integrator, cache) end + #Perform customized modification right after error estimate + if has_postEEst_callback(integrator) + apply_postEEst_callback(integrator) + end - # modif_step! enables to modify the step like when we want to perform a relaxation - # for this we give a new struture that can be defined either by us for already known - # modification we want to do or by a user (see below) - modif_step!(integrator) - - # finalize_step! will do staff related to the solver like integrator.stats, register integrator.fsal - # and register integrator.u + # finalize_step (useless for the moment) finalize_step!(integrator, cache) end +function apply_poststep_callback!(integrator) + + # Variable to know if dt has changed during perform_step + integrator.dt_has_changed = false + integrator.u_has_changed = false + + integrator.opts.performstepcallback.poststep(integrator) + + handle_dt_bound_and_tstop!(integrator) + update_u_changed!(integrator) +end + +function apply_postfsal_callback!(integrator) + + # Variable to know if dt has changed during perform_step + integrator.dt_has_changed = false + integrator.u_has_changed = false + + integrator.opts.performstepcallback.postfsal(integrator) + + handle_dt_bound_and_tstop!(integrator) + update_u_changed!(integrator) +end + +function apply_postEEst_callback!(integrator) + + # Variable to know if dt has changed during perform_step + integrator.dt_has_changed = false + integrator.u_has_changed = false + + integrator.opts.performstepcallback.postEEst(integrator) + + handle_dt_bound_and_tstop!(integrator) + update_u_changed!(integrator) +end + +function handle_dt_bound_and_tstop!(integrator) + + # Here we carry of the dt modified by the user in this step, if it has been changed. + + if integrator.dt_has_changed + + # Memory of the current user dt_changed + tmp = integrator.dt_changed + + # match dt in [dtmin, dtmax] + if integrator.tdir > 0 + integrator.dt_changed = min(integrator.opts.dtmax, integrator.dt_changed) + else + integrator.dt_changed = max(integrator.opts.dtmax, integrator.dt_changed) + end + dtmin = timedepentdtmin(integrator) + if integrator.tdir > 0 + integrator.dt_changed = max(integrator.dt_changed, dtmin) + else + integrator.dt_changed = min(integrator.dt_changed, dtmin) + end + + #if tmp != integrator.dt_changed + # @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. As a consequence, it has been projected onto [dtmin, dtmax]." + #end + + # Memory of the current user dt_changed + tmp = integrator.dt_changed + + # Match dt with tstops + if has_tstop(integrator) + tdir_t = integrator.tdir * integrator.t + tdir_tstop = first_tstop(integrator) + integrator.dt_changed = integrator.tdir * min(abs(integrator.dt_changed), abs(tdir_tstop - tdir_t)) + end + + if tmp != integrator.dt_changed + @warn "The modification of dt during the user modification step " + end + + integrator.dt = integrator.dt_changed + end +end + +function update_u_changed!(integrator) + if integrator.u_has_changed + integrator.u = integrator.u_changed + else + integrator.u = integrator.u_propose + end +end @muladd function calculate_nextstep!(integrator, ::Tsit5ConstantCache_for_relaxation, repeat_step = false) @@ -109,62 +200,6 @@ end integrator.EEst = integrator.opts.internalnorm(atmp, integrator.t) end -function modif_step!(integrator) - - if !(integrator.opts.modif isa Nothing) - - # Perform the modifications - integrator.opts.modif(integrator) - - # Here we carry of the dt modified by the user in this step, if it has been changed. - - if integrator.dt_has_changed - - # Memory of the current user dt_changed - tmp = integrator.dt_changed - - # match dt in [dtmin, dtmax] - if integrator.tdir > 0 - integrator.dt_changed = min(integrator.opts.dtmax, integrator.dt_changed) - else - integrator.dt_changed = max(integrator.opts.dtmax, integrator.dt_changed) - end - dtmin = timedepentdtmin(integrator) - if integrator.tdir > 0 - integrator.dt_changed = max(integrator.dt_changed, dtmin) - else - integrator.dt_changed = min(integrator.dt_changed, dtmin) - end - - if tmp != integrator.dt_changed - @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. As a consequence, it has been projected onto [dtmin, dtmax]." - end - - # Memory of the current user dt_changed - tmp = integrator.dt_changed - - # match dt with tstops - if has_tstop(integrator) - tdir_t = integrator.tdir * integrator.t - tdir_tstop = first_tstop(integrator) - integrator.dt_changed = integrator.tdir * min(abs(integrator.dt_changed), abs(tdir_tstop - tdir_t)) - end - - if tmp != integrator.dt_changed - @warn "The modification of dt during the user modification step " - end - - integrator.dt = integrator.dt_changed - end - end - if integrator.u_has_changed - integrator.u = integrator.u_changed - else - integrator.u = integrator.u_propose - end - -end - function finalize_step!(integrator, ::Tsit5ConstantCache_for_relaxation) end diff --git a/src/performstep_callback.jl b/src/performstep_callback.jl new file mode 100644 index 0000000000..7632147d7c --- /dev/null +++ b/src/performstep_callback.jl @@ -0,0 +1,28 @@ +abstract type AbstractPerformStepCallback end + +struct NoPerformStepCallback <:AbstractPerformStepCallback end + +has_poststep_callback(::AbstractPerformStepCallback) = false +has_postfsal_callback(::AbstractPerformStepCallback) = false +has_postEEst_callback(::AbstractPerformStepCallback) = false + +struct PerformStepCallback <: AbstractPerformStepCallback + poststep_cb + has_poststep_cb::Bool + postfsal_cb + has_postfsal_cb::Bool + postEEst_cb + has_postEEst_cb::Bool + + function PerformStepCallBack(;poststep = nothing, postfsal = nothing, postEEst = nothing) + has_poststep_cb = poststep isa Nothing ? false : true + has_postfsal_cb = postfsal isa Nothing ? false : true + has_postEEst_cb = postEEst isa Nothing ? false : true + new(poststep, has_poststep_cb, postfsal_cb, has_postfsal_cb, postEEst_cb, has_postEEst_cb) + end +end + +has_poststep_callback(pscb::PerformStepCallback) = pscb.has_poststep_cb +has_postfsal_callback(pscb::PerformStepCallback) = pscb.has_postfsal_cb +has_postEEst_callback(pscb::PerformStepCallback) = pscb.has_postEEst_cb + diff --git a/src/solve.jl b/src/solve.jl index 1794819b9c..5c426d65cf 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -72,7 +72,7 @@ function DiffEqBase.__init( alias_u0 = false, alias_du0 = false, initializealg = DefaultInit(), - modif = nothing, + modif = NoPerformStepCallback(), kwargs...) where {recompile_flag} if prob isa DiffEqBase.AbstractDAEProblem && alg isa OrdinaryDiffEqAlgorithm error("You cannot use an ODE Algorithm with a DAEProblem") From 44ea89d28b5547cf187d57179324076ee6b8f529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:39:27 +0200 Subject: [PATCH 34/39] new structure runs --- src/integrators/integrator_interface.jl | 2 +- src/integrators/type.jl | 2 +- .../test_for_relaxation_perform_step.jl | 67 +++++-------------- src/performstep_callback.jl | 4 +- test/relaxation/convergence.jl | 10 +-- test/relaxation/relaxation.jl | 14 +--- 6 files changed, 30 insertions(+), 69 deletions(-) diff --git a/src/integrators/integrator_interface.jl b/src/integrators/integrator_interface.jl index 5cb34f3005..ac86c1a679 100644 --- a/src/integrators/integrator_interface.jl +++ b/src/integrators/integrator_interface.jl @@ -515,7 +515,7 @@ end function change_u!(integrator::ODEIntegrator, u) integrator.u_has_changed = true - integrator.u_changed = u + integrator.u = u end has_poststep_callback(integrator::ODEIntegrator) = has_poststep_callback(integrator.opts.performstepcallback) diff --git a/src/integrators/type.jl b/src/integrators/type.jl index 5d225958ec..8f07805bcb 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -46,7 +46,7 @@ mutable struct DEOptions{absType, relType, QT, tType, Controller, F1, F2, F3, F4 force_dtmin::Bool advance_to_tstop::Bool stop_at_next_tstop::Bool - modif::AbstractPerformStepCallback + performstepcallback::AbstractPerformStepCallback end TruncatedStacktraces.@truncate_stacktrace DEOptions diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index d175e9cee2..9cec3d05d1 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -1,4 +1,3 @@ - function initialize!(integrator, ::Tsit5ConstantCache_for_relaxation) integrator.kshortsize = 7 integrator.k = typeof(integrator.k)(undef, integrator.kshortsize) @@ -38,7 +37,7 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C # Perform customize modification right after the step, i.e modify uₙ₊₁ if has_poststep_callback(integrator) - apply_poststep_callback(integrator) + apply_poststep_callback!(integrator) end # Calculate f(uₙ₊₁) if the aglortihm has the FSAL property @@ -48,7 +47,7 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C # Perform customize modification right after fsal, i.e modify f(uₙ₊₁) if has_postfsal_callback(integrator) - apply_postfsal_callback(integrator) + apply_postfsal_callback!(integrator) end # Calculate the error estimate needed for PID controller @@ -58,7 +57,7 @@ function perform_step!(integrator, cache::Union{Tsit5Cache_for_relaxation,Tsit5C #Perform customized modification right after error estimate if has_postEEst_callback(integrator) - apply_postEEst_callback(integrator) + apply_postEEst_callback!(integrator) end # finalize_step (useless for the moment) @@ -69,36 +68,30 @@ function apply_poststep_callback!(integrator) # Variable to know if dt has changed during perform_step integrator.dt_has_changed = false - integrator.u_has_changed = false - integrator.opts.performstepcallback.poststep(integrator) + integrator.opts.performstepcallback.poststep_cb(integrator) handle_dt_bound_and_tstop!(integrator) - update_u_changed!(integrator) end function apply_postfsal_callback!(integrator) # Variable to know if dt has changed during perform_step integrator.dt_has_changed = false - integrator.u_has_changed = false - integrator.opts.performstepcallback.postfsal(integrator) + integrator.opts.performstepcallback.postfsal_cb(integrator) handle_dt_bound_and_tstop!(integrator) - update_u_changed!(integrator) end function apply_postEEst_callback!(integrator) # Variable to know if dt has changed during perform_step integrator.dt_has_changed = false - integrator.u_has_changed = false - integrator.opts.performstepcallback.postEEst(integrator) + integrator.opts.performstepcallback.postEEst_cb(integrator) handle_dt_bound_and_tstop!(integrator) - update_u_changed!(integrator) end function handle_dt_bound_and_tstop!(integrator) @@ -107,10 +100,7 @@ function handle_dt_bound_and_tstop!(integrator) if integrator.dt_has_changed - # Memory of the current user dt_changed - tmp = integrator.dt_changed - - # match dt in [dtmin, dtmax] + # Match dt in [dtmin, dtmax] if integrator.tdir > 0 integrator.dt_changed = min(integrator.opts.dtmax, integrator.dt_changed) else @@ -122,34 +112,15 @@ function handle_dt_bound_and_tstop!(integrator) else integrator.dt_changed = min(integrator.dt_changed, dtmin) end - - #if tmp != integrator.dt_changed - # @warn "The modification of dt during the user modification step was not in [dtmin, dtmax]. As a consequence, it has been projected onto [dtmin, dtmax]." - #end - - # Memory of the current user dt_changed - tmp = integrator.dt_changed - # Match dt with tstops if has_tstop(integrator) tdir_t = integrator.tdir * integrator.t tdir_tstop = first_tstop(integrator) integrator.dt_changed = integrator.tdir * min(abs(integrator.dt_changed), abs(tdir_tstop - tdir_t)) end - - if tmp != integrator.dt_changed - @warn "The modification of dt during the user modification step " - end - + integrator.dt = integrator.dt_changed - end -end - -function update_u_changed!(integrator) - if integrator.u_has_changed - integrator.u = integrator.u_changed - else - integrator.u = integrator.u_propose + integrator.dt_has_changed = false end end @@ -174,7 +145,7 @@ end integrator.k[4] = k4 integrator.k[5] = k5 integrator.k[6] = k6 - integrator.u_propose = u + integrator.u = u integrator.stats.nf += 5 end @@ -188,8 +159,8 @@ end end @muladd function calculate_EEst!(integrator, ::Tsit5ConstantCache_for_relaxation) - T = constvalue(recursive_unitless_bottom_eltype(u)) - T2 = constvalue(typeof(one(t))) + T = constvalue(recursive_unitless_bottom_eltype(integrator.u)) + T2 = constvalue(typeof(one(integrator.t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 utilde = integrator.dt * (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] @@ -209,8 +180,8 @@ end @muladd function calculate_nextstep!(integrator, cache::Tsit5Cache_for_relaxation, repeat_step = false) - @unpack t, dt, uprev, u_propose, f, p = integrator - T = constvalue(recursive_unitless_bottom_eltype(u_propose)) + @unpack t, dt, uprev, u, f, p = integrator + T = constvalue(recursive_unitless_bottom_eltype(u)) T2 = constvalue(typeof(one(t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 @unpack k1, k2, k3, k4, k5, k6, k7, utilde, tmp, atmp, stage_limiter!, step_limiter!, thread = cache @@ -232,10 +203,10 @@ end dt * (a61 * k1 + a62 * k2 + a63 * k3 + a64 * k4 + a65 * k5) stage_limiter!(tmp, f, p, t + dt) f(k6, tmp, p, t + dt) - @.. broadcast=false thread=thread u_propose = uprev + + @.. broadcast=false thread=thread u = uprev + dt * (a71 * k1 + a72 * k2 + a73 * k3 + a74 * k4 + a75 * k5 + a76 * k6) - stage_limiter!(u_propose, integrator, p, t + dt) - step_limiter!(u_propose, integrator, p, t + dt) + stage_limiter!(u, integrator, p, t + dt) + step_limiter!(u, integrator, p, t + dt) integrator.stats.nf += 5 return nothing @@ -255,7 +226,7 @@ end @.. broadcast = false thread = threa utilde = integrator.dt * (btilde1 * k1 + btilde2 * k2 + btilde3 * k3 + btilde4 * k4 + btilde5 * k5 + btilde6 * k6 + btilde7 * k7) - calculate_residuals!(atmp, utilde, integrator.uprev, integrator.u_propose, + calculate_residuals!(atmp, utilde, integrator.uprev, integrator.u, integrator.opts.abstol, integrator.opts.reltol, integrator.opts.internalnorm, integrator.t, thread) integrator.EEst = integrator.opts.internalnorm(atmp, integrator.t) @@ -265,8 +236,6 @@ function finalize_step!(integrator, cache::Tsit5Cache_for_relaxation) end - - # Is this useful ? function apriori_bounds_dt(integrator) dt_sup = if has_tstop(integrator) diff --git a/src/performstep_callback.jl b/src/performstep_callback.jl index 7632147d7c..85908f7c56 100644 --- a/src/performstep_callback.jl +++ b/src/performstep_callback.jl @@ -14,11 +14,11 @@ struct PerformStepCallback <: AbstractPerformStepCallback postEEst_cb has_postEEst_cb::Bool - function PerformStepCallBack(;poststep = nothing, postfsal = nothing, postEEst = nothing) + function PerformStepCallback(;poststep = nothing, postfsal = nothing, postEEst = nothing) has_poststep_cb = poststep isa Nothing ? false : true has_postfsal_cb = postfsal isa Nothing ? false : true has_postEEst_cb = postEEst isa Nothing ? false : true - new(poststep, has_poststep_cb, postfsal_cb, has_postfsal_cb, postEEst_cb, has_postEEst_cb) + new(poststep, has_poststep_cb, postfsal, has_postfsal_cb, postEEst, has_postEEst_cb) end end diff --git a/test/relaxation/convergence.jl b/test/relaxation/convergence.jl index 59828f5571..8efda7768a 100644 --- a/test/relaxation/convergence.jl +++ b/test/relaxation/convergence.jl @@ -49,7 +49,7 @@ prob_oscillator = ODEProblem( ODEFunction(f_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), [1.0, 0.0], (0.0, 1.0)) -r_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) +r_oscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) #sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) #sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] @@ -73,7 +73,7 @@ prob_nloscillator = ODEProblem( ODEFunction(f_nloscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), [1.0, 0.0], (0.0, 1.0)) -r_nloscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) +r_nloscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) #sol_nloscillator = solve(prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) #sol_exact = [prob_oscillator.f.analytic(prob_nloscillator.u0, prob_nloscillator.p, t) for t in sol_nloscillator.t] @@ -94,7 +94,7 @@ prob_nlpendulum = ODEProblem( f_nlpendulum, [1.0, 0.0], (0.0, 1.0)) -r_nlpendulum = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2])) +r_nlpendulum = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2]))) #sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = r_nlpendulum) #sol_ref = solve(prob_nlpendulum, Vern9()) @@ -123,7 +123,7 @@ prob_td_oscillator = ODEProblem( sin(0.5)*cos(t-0.5*cos(t))+cos(0.5)*sin(t-0.5*cos(t))]), [1.0, 0.0], (0.0, 1.0)) -r_td_oscillator = Relaxation(AlefeldPotraShi, x-> norm(x)) +r_td_oscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) sim_td_oscillator_old = test_convergence(dts, prob_td_oscillator, Tsit5()) println("order of convergence of older perform_step! : "*string(sim_td_oscillator_old.𝒪est[:final])) @@ -144,7 +144,7 @@ prob_cee = ODEProblem( log(exp((exp(0.5)+exp(1))*t)*(exp(0.5)+exp(1)))/(exp(0.5) + exp((exp(0.5)+exp(1))*t))]), [1.0, 0.5], (0.0, 1.0)) -r_cee = Relaxation(AlefeldPotraShi, x-> exp(x[1]) + exp(x[2])) +r_cee = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> exp(x[1]) + exp(x[2]))) sim_cee_old = test_convergence(dts, prob_cee, Tsit5()) println("order of convergence of older perform_step! : "*string(sim_cee_old.𝒪est[:final])) diff --git a/test/relaxation/relaxation.jl b/test/relaxation/relaxation.jl index e15edffc47..4be1d98546 100644 --- a/test/relaxation/relaxation.jl +++ b/test/relaxation/relaxation.jl @@ -28,16 +28,8 @@ function (r::Relaxation)(integrator) change_dt!(integrator, gamma*dt) change_u!(integrator, uprev + gamma*S_u) - integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) + #integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) end + +end - # println("###################### Print of dt time") - # @show integrator.dt - # @show integrator.dt_changed - # @show integrator.opts.dtmin - # @show integrator.opts.dtmax - # if has_tstop(integrator) - # @show first_tstop(integrator) - integrator.t - # end - -end \ No newline at end of file From 3d068949cabbf4953f339cd5cad201725d5bc8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 15 Jun 2024 23:04:40 +0200 Subject: [PATCH 35/39] all last modif --- src/integrators/type.jl | 3 -- .../test_for_relaxation_perform_step.jl | 2 +- src/solve.jl | 5 +-- test/relaxation/harmonic_oscillator.jl | 43 +++++++++++++++++++ test/relaxation/relaxation.jl | 11 +++-- 5 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 test/relaxation/harmonic_oscillator.jl diff --git a/src/integrators/type.jl b/src/integrators/type.jl index 8f07805bcb..9e29f75761 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -136,9 +136,6 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori initializealg::IA differential_vars::DV - u_propose::uType - u_changed::uType - u_has_changed::Bool dt_has_changed::Bool dt_changed::tType diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index 9cec3d05d1..e8aac1db64 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -165,7 +165,7 @@ end utilde = integrator.dt * (btilde1 * integrator.k[1] + btilde2 * integrator.k[2] + btilde3 * integrator.k[3] + btilde4 * integrator.k[4] + btilde5 * integrator.k[5] + btilde6 * integrator.k[6] - + btilde7 * integrator.k[7]) + + btilde7 * integrator.fsallast) atmp = calculate_residuals(utilde, integrator.uprev, integrator.u, integrator.opts.abstol, integrator.opts.reltol, integrator.opts.internalnorm, integrator.t) integrator.EEst = integrator.opts.internalnorm(atmp, integrator.t) diff --git a/src/solve.jl b/src/solve.jl index 5c426d65cf..e7afc32133 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -161,9 +161,6 @@ function DiffEqBase.__init( else u = recursivecopy(prob.u0) end - u_propose = recursivecopy(u) - u_changed = recursivecopy(u) - u_has_changed = false if _alg isa DAEAlgorithm if alias_du0 @@ -496,7 +493,7 @@ function DiffEqBase.__init( last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitiailize, isdae, - opts, stats, initializealg, differential_vars, u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) + opts, stats, initializealg, differential_vars, dt_has_changed, dt_changed) if initialize_integrator if isdae || SciMLBase.has_initializeprob(prob.f) diff --git a/test/relaxation/harmonic_oscillator.jl b/test/relaxation/harmonic_oscillator.jl new file mode 100644 index 0000000000..59cb32a737 --- /dev/null +++ b/test/relaxation/harmonic_oscillator.jl @@ -0,0 +1,43 @@ +using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools + +include("relaxation.jl") + +printstyled("Harmonic Oscillator\n"; bold = true) + +dts = (1 / 2) .^ (6:-1:4) + +f = (u, p, t) -> [-u[2],u[1]] +prob = ODEProblem( + ODEFunction(f; analytic = (u0, p, t) -> [cos(t), sin(t)]), + [1.0, 0.0], + (0.0, 1.0)) + + + +# Convergence with the old method Tsit5() +sim = test_convergence(dts, prob, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) + +# Convergence with the new method Tsit5_fors_relaxation() without relaxation +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x)), false) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x)), false) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) +r = PerformStepCallback(;postfEEst = Relaxation(AlefeldPotraShi, x-> norm(x)), true) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ) ) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/relaxation.jl b/test/relaxation/relaxation.jl index 4be1d98546..e193f9e004 100644 --- a/test/relaxation/relaxation.jl +++ b/test/relaxation/relaxation.jl @@ -5,16 +5,17 @@ using UnPack struct Relaxation{OPT, INV} opt::OPT invariant::INV + fsal::Bool end function (r::Relaxation)(integrator) - @unpack t, dt, uprev, u_propose = integrator + @unpack t, dt, uprev, u = integrator # We fix here the bounds of interval where we are going to look for the relaxation #(gamma_min, gamma_max) = apriori_bounds_dt(integrator) ./ dt - S_u = u_propose - uprev + S_u = u - uprev # Find relaxation paramter gamma gamma_min = 0.5 @@ -28,8 +29,10 @@ function (r::Relaxation)(integrator) change_dt!(integrator, gamma*dt) change_u!(integrator, uprev + gamma*S_u) - #integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) + if r.fsal + integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) end - end + + From ac1943db8cbdcf93eb25c3c6f66a2ef182c2d4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sat, 15 Jun 2024 23:59:01 +0200 Subject: [PATCH 36/39] almost all work well except R-FSAL which needs --- src/integrators/integrator_interface.jl | 5 ++++- src/integrators/type.jl | 5 ++--- test/relaxation/convergence.jl | 2 +- test/relaxation/harmonic_oscillator.jl | 16 ++++++++-------- test/relaxation/relaxation.jl | 15 +++++++++++---- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/integrators/integrator_interface.jl b/src/integrators/integrator_interface.jl index ac86c1a679..484dbe934c 100644 --- a/src/integrators/integrator_interface.jl +++ b/src/integrators/integrator_interface.jl @@ -514,10 +514,13 @@ function change_dt!(integrator::ODEIntegrator, dt) end function change_u!(integrator::ODEIntegrator, u) - integrator.u_has_changed = true integrator.u = u end +function change_fsallast!(integrator::ODEIntegrator, fsallast) + integrator.fsallast = fsallast +end + has_poststep_callback(integrator::ODEIntegrator) = has_poststep_callback(integrator.opts.performstepcallback) has_postfsal_callback(integrator::ODEIntegrator) = has_postfsal_callback(integrator.opts.performstepcallback) has_postEEst_callback(integrator::ODEIntegrator) = has_postEEst_callback(integrator.opts.performstepcallback) diff --git a/src/integrators/type.jl b/src/integrators/type.jl index 9e29f75761..c958138842 100644 --- a/src/integrators/type.jl +++ b/src/integrators/type.jl @@ -160,8 +160,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori accept_step, isout, reeval_fsal, u_modified, reinitialize, isdae, opts, stats, - initializealg, differential_vars, - u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) where {algType, IIP, uType, + initializealg, differential_vars, dt_has_changed, dt_changed) where {algType, IIP, uType, duType, tType, pType, eigenType, EEstT, tTypeNoUnits, tdirType, @@ -183,7 +182,7 @@ mutable struct ODEIntegrator{algType <: Union{OrdinaryDiffEqAlgorithm, DAEAlgori do_error_check, event_last_time, vector_event_last_time, last_event_error, accept_step, isout, reeval_fsal, u_modified, reinitialize, isdae, - opts, stats, initializealg, differential_vars, u_propose, u_changed, u_has_changed, dt_has_changed, dt_changed) # Leave off fsalfirst and last + opts, stats, initializealg, differential_vars, dt_has_changed, dt_changed) # Leave off fsalfirst and last end end diff --git a/test/relaxation/convergence.jl b/test/relaxation/convergence.jl index 8efda7768a..b54aadac54 100644 --- a/test/relaxation/convergence.jl +++ b/test/relaxation/convergence.jl @@ -1,4 +1,4 @@ -using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools +using OrdinaryDiffEq, DiffEqDevTools, Test import ODEProblemLibrary: prob_ode_linear, prob_ode_2Dlinear diff --git a/test/relaxation/harmonic_oscillator.jl b/test/relaxation/harmonic_oscillator.jl index 59cb32a737..bc4f74b32c 100644 --- a/test/relaxation/harmonic_oscillator.jl +++ b/test/relaxation/harmonic_oscillator.jl @@ -1,4 +1,4 @@ -using OrdinaryDiffEq, DiffEqDevTools, Test, BenchmarkTools +using OrdinaryDiffEq, DiffEqDevTools include("relaxation.jl") @@ -12,8 +12,6 @@ prob = ODEProblem( [1.0, 0.0], (0.0, 1.0)) - - # Convergence with the old method Tsit5() sim = test_convergence(dts, prob, Tsit5()) println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) @@ -23,21 +21,23 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation()) println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) # Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst -r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x)), false) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) # Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst -r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x)), false) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x))) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) # Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) -r = PerformStepCallback(;postfEEst = Relaxation(AlefeldPotraShi, x-> norm(x)), true) +fsal_r(gamma, fsalfirst, fsallast) = fsalfirst + gamma * (fsallast - fsalfirst) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x), fsal_r)) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) -# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ) ) -r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) +r_fsal(gamma, fsalfirst, fsallast) = fsalfirst + 1/gamma * (fsallast - fsalfirst) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x), r_fsal), postEEst = fsal_r) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/relaxation.jl b/test/relaxation/relaxation.jl index e193f9e004..c078bf6721 100644 --- a/test/relaxation/relaxation.jl +++ b/test/relaxation/relaxation.jl @@ -2,10 +2,13 @@ using Roots using LinearAlgebra using UnPack -struct Relaxation{OPT, INV} +struct Relaxation{OPT, INV, FSAL} opt::OPT invariant::INV - fsal::Bool + has_fsal::Bool + update_fsal::FSAL + + Relaxation(opt, inv, fsal = nothing) = new{typeof(opt), typeof(inv), typeof(fsal)}(opt, inv, fsal isa Nothing ? false : true, fsal) end function (r::Relaxation)(integrator) @@ -29,10 +32,14 @@ function (r::Relaxation)(integrator) change_dt!(integrator, gamma*dt) change_u!(integrator, uprev + gamma*S_u) - if r.fsal - integrator.fsallast = integrator.fsalfirst + gamma*(integrator.fsallast - integrator.fsalfirst) + if r.has_fsal + integrator.fsallast = r.update_fsal(gamma, integrator.fsalfirst, integrator.fsallast) + end end end +fsal_r(gamma, fsalfirst, fsallast) = fsalfirst + gamma * (fsallast - fsalfirst) +r_fsal(gamma, fsalfirst, fsallast) = fsalfirst + 1/gamma * (fsallast - fsalfirst) +fsal_r_int(integrator) = integrator.fsalllast = fsal_r(gamma, fsalfirst, fsallast) From 5c9b8e619e50952e85247b9ef4040b8837201211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 16 Jun 2024 00:09:05 +0200 Subject: [PATCH 37/39] find a way to make R-FSAL work --- test/relaxation/harmonic_oscillator.jl | 4 +--- test/relaxation/relaxation.jl | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/test/relaxation/harmonic_oscillator.jl b/test/relaxation/harmonic_oscillator.jl index bc4f74b32c..664bb2b3d2 100644 --- a/test/relaxation/harmonic_oscillator.jl +++ b/test/relaxation/harmonic_oscillator.jl @@ -31,13 +31,11 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) # Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) -fsal_r(gamma, fsalfirst, fsallast) = fsalfirst + gamma * (fsallast - fsalfirst) r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x), fsal_r)) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) # Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) -r_fsal(gamma, fsalfirst, fsallast) = fsalfirst + 1/gamma * (fsallast - fsalfirst) -r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x), r_fsal), postEEst = fsal_r) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x), r_fsal), postEEst = fsal_r_int) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/relaxation.jl b/test/relaxation/relaxation.jl index c078bf6721..41c1a3c725 100644 --- a/test/relaxation/relaxation.jl +++ b/test/relaxation/relaxation.jl @@ -2,13 +2,13 @@ using Roots using LinearAlgebra using UnPack -struct Relaxation{OPT, INV, FSAL} +mutable struct Relaxation{OPT, INV, FSAL} opt::OPT invariant::INV has_fsal::Bool update_fsal::FSAL - - Relaxation(opt, inv, fsal = nothing) = new{typeof(opt), typeof(inv), typeof(fsal)}(opt, inv, fsal isa Nothing ? false : true, fsal) + γ + Relaxation(opt, inv, fsal = nothing) = new{typeof(opt), typeof(inv), typeof(fsal)}(opt, inv, fsal isa Nothing ? false : true, fsal, 1.0) end function (r::Relaxation)(integrator) @@ -28,7 +28,7 @@ function (r::Relaxation)(integrator) gamma = find_zero(gamma -> r.invariant(gamma*S_u .+ uprev) .- r.invariant(uprev), (gamma_min, gamma_max), r.opt()) - + r.γ = gamma change_dt!(integrator, gamma*dt) change_u!(integrator, uprev + gamma*S_u) @@ -41,5 +41,5 @@ end fsal_r(gamma, fsalfirst, fsallast) = fsalfirst + gamma * (fsallast - fsalfirst) r_fsal(gamma, fsalfirst, fsallast) = fsalfirst + 1/gamma * (fsallast - fsalfirst) -fsal_r_int(integrator) = integrator.fsalllast = fsal_r(gamma, fsalfirst, fsallast) +fsal_r_int(integrator) = integrator.fsallast = fsal_r(integrator.opts.performstepcallback.poststep_cb.γ, integrator.fsalfirst, integrator.fsallast) From 2b0fb0adde1c8d7861d26af3c6a4c8c75d48da61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Sun, 16 Jun 2024 21:03:23 +0200 Subject: [PATCH 38/39] do each examples of the paper with different FSAL --- .../conserved_exponential_entropy.jl | 45 ++++++++ test/relaxation/convergence.jl | 105 +----------------- test/relaxation/harmonic_oscillator.jl | 10 +- test/relaxation/non_linear_oscillator.jl | 43 +++++++ test/relaxation/non_linear_pendulum.jl | 45 ++++++++ .../time_dependant_harmonic_oscillator.jl | 45 ++++++++ 6 files changed, 189 insertions(+), 104 deletions(-) create mode 100644 test/relaxation/conserved_exponential_entropy.jl create mode 100644 test/relaxation/non_linear_oscillator.jl create mode 100644 test/relaxation/non_linear_pendulum.jl create mode 100644 test/relaxation/time_dependant_harmonic_oscillator.jl diff --git a/test/relaxation/conserved_exponential_entropy.jl b/test/relaxation/conserved_exponential_entropy.jl new file mode 100644 index 0000000000..6829b588af --- /dev/null +++ b/test/relaxation/conserved_exponential_entropy.jl @@ -0,0 +1,45 @@ +using OrdinaryDiffEq, DiffEqDevTools + +include("relaxation.jl") + +printstyled("Conserved exponential entropy\n"; bold = true) + +dts = (1 / 2) .^ (6:-1:4) + +f = (u, p, t) -> [-exp(u[2]), exp(u[1])] +prob = ODEProblem( + ODEFunction(f ; + analytic = (u0, p, t)->[log(exp(1) + exp(0.5)) - log(exp(0.5) + exp((exp(0.5)+exp(1))*t)), + log(exp((exp(0.5)+exp(1))*t)*(exp(0.5)+exp(1)))/(exp(0.5) + exp((exp(0.5)+exp(1))*t))]), + [1.0, 0.5], + (0.0, 1.0)) + +invariant(x) = exp(x[1]) + exp(x[2]) + +# Convergence with the old method Tsit5() +sim = test_convergence(dts, prob, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) + +# Convergence with the new method Tsit5_fors_relaxation() without relaxation +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant, fsal_r)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant, r_fsal), postEEst = fsal_r_int) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/convergence.jl b/test/relaxation/convergence.jl index b54aadac54..192760eed6 100644 --- a/test/relaxation/convergence.jl +++ b/test/relaxation/convergence.jl @@ -38,117 +38,22 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation()) ######################################################################### ## With Relaxation -dts = (1 / 2) .^ (6:-1:4) - ######################################################## # TEST 1 : Harmonic Oscillator -printstyled("Harmonic Oscillator\n"; bold = true) - -f_oscillator = (u, p, t) -> [-u[2],u[1]] -prob_oscillator = ODEProblem( - ODEFunction(f_oscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), - [1.0, 0.0], - (0.0, 1.0)) -r_oscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) - -#sol_oscillator = solve(prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) -#sol_exact = [prob_oscillator.f.analytic(prob_oscillator.u0, prob_oscillator.p, t) for t in sol_oscillator.t] -#plot(sol_oscillator) -#plot!(sol_oscillator.t, [sol_exact[i][1] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[1]", lw = 4) -#plot!(sol_oscillator.t, [sol_exact[i][2] for i ∈ 1:length(sol_oscillator.t)], label = "exact u[2]", lw = 4) - -sim_oscillator_old = test_convergence(dts, prob_oscillator, Tsit5()) -println("order of convergence of older perform_step! : "*string(sim_oscillator_old.𝒪est[:final])) -sim_oscillator_new = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation()) -println("order of convergence of new perform_step! without relaxation: "*string(sim_oscillator_new.𝒪est[:final])) -sim_oscillator_relax = test_convergence(dts, prob_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) -println("order of convergence of new perform_step! with relaxation: "*string(sim_oscillator_relax.𝒪est[:final])) +include("harmonic_oscillator.jl") ######################################################## # TEST 2 : Non Linear Oscillator -printstyled("Non linear Harmonic Oscillator\n"; bold = true) - -f_nloscillator = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] -prob_nloscillator = ODEProblem( - ODEFunction(f_nloscillator; analytic = (u0, p, t) -> [cos(t), sin(t)]), - [1.0, 0.0], - (0.0, 1.0)) -r_nloscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) - -#sol_nloscillator = solve(prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) -#sol_exact = [prob_oscillator.f.analytic(prob_nloscillator.u0, prob_nloscillator.p, t) for t in sol_nloscillator.t] - -sim = test_convergence(dts, prob_nloscillator, Tsit5()) -println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) -sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation()) -println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) -sim = test_convergence(dts, prob_nloscillator, Tsit5_for_relaxation(); modif = r_nloscillator) -println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) +include("non_linear_oscillator.jl") ######################################################## # TEST 3 : Non Linear Pendulum -printstyled("Non linear Pendulum\n"; bold = true) - -f_nlpendulum = (u, p, t) -> [-sin(u[2]), u[1]] -prob_nlpendulum = ODEProblem( - f_nlpendulum, - [1.0, 0.0], - (0.0, 1.0)) -r_nlpendulum = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> x[1]^2/2 - cos(x[2]))) - -#sol_nlpendulum = solve(prob_nlpendulum, Tsit5_for_relaxation(); modif = r_nlpendulum) -#sol_ref = solve(prob_nlpendulum, Vern9()) - -test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14) - -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5(), test_setup) -println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup) -println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) -sim = analyticless_test_convergence(dts, prob_nlpendulum, Tsit5_for_relaxation(), test_setup; modif = r_nlpendulum) -println("order of convergence of new perform_step! with relaxation: "*string(sim.𝒪est[:final])) - - -@benchmark solve(prob_nloscillator, Tsit5_for_relaxation()) +include("non_linear_pendulum.jl") ############################################################################ # TEST 4 : Time dependent harmonic oscillator with bounded angular velocity - -printstyled("Time dependent harmonic oscillator\n"; bold = true) - -f_td_oscillator = (u, p, t) -> [-(1+0.5 * sin(t))*u[2], (1+0.5 * sin(t))*u[1]] -prob_td_oscillator = ODEProblem( - ODEFunction(f_td_oscillator; - analytic = (u0, p, t)->[cos(0.5)*cos(t-0.5*cos(t))-sin(0.5)*sin(t-0.5*cos(t)), - sin(0.5)*cos(t-0.5*cos(t))+cos(0.5)*sin(t-0.5*cos(t))]), - [1.0, 0.0], - (0.0, 1.0)) -r_td_oscillator = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) - -sim_td_oscillator_old = test_convergence(dts, prob_td_oscillator, Tsit5()) -println("order of convergence of older perform_step! : "*string(sim_td_oscillator_old.𝒪est[:final])) -sim_td_oscillator_new = test_convergence(dts, prob_td_oscillator, Tsit5_for_relaxation()) -println("order of convergence of new perform_step! without relaxation: "*string(sim_td_oscillator_new.𝒪est[:final])) -sim_td_oscillator_relax = test_convergence(dts, prob_td_oscillator, Tsit5_for_relaxation(); modif = r_oscillator) -println("order of convergence of new perform_step! with relaxation: "*string(sim_td_oscillator_relax.𝒪est[:final])) +include("time_dependant_harmonic_oscillator.jl") ############################################################################ # TEST 5 : Conserved exponential entropy - -printstyled("Conserved exponential entropy\n"; bold = true) - -f_cee = (u, p, t) -> [-exp(u[2]), exp(u[1])] -prob_cee = ODEProblem( - ODEFunction(f_cee ; - analytic = (u0, p, t)->[log(exp(1) + exp(0.5)) - log(exp(0.5) + exp((exp(0.5)+exp(1))*t)), - log(exp((exp(0.5)+exp(1))*t)*(exp(0.5)+exp(1)))/(exp(0.5) + exp((exp(0.5)+exp(1))*t))]), - [1.0, 0.5], - (0.0, 1.0)) -r_cee = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> exp(x[1]) + exp(x[2]))) - -sim_cee_old = test_convergence(dts, prob_cee, Tsit5()) -println("order of convergence of older perform_step! : "*string(sim_cee_old.𝒪est[:final])) -sim_cee_new = test_convergence(dts, prob_cee, Tsit5_for_relaxation()) -println("order of convergence of new perform_step! without relaxation: "*string(sim_cee_new.𝒪est[:final])) -sim_cee_relax = test_convergence(dts, prob_cee, Tsit5_for_relaxation(); modif = r_oscillator) -println("order of convergence of new perform_step! with relaxation: "*string(sim_cee_relax.𝒪est[:final])) \ No newline at end of file +include("conserved_exponential_entropy.jl") \ No newline at end of file diff --git a/test/relaxation/harmonic_oscillator.jl b/test/relaxation/harmonic_oscillator.jl index 664bb2b3d2..f431019dcf 100644 --- a/test/relaxation/harmonic_oscillator.jl +++ b/test/relaxation/harmonic_oscillator.jl @@ -12,6 +12,8 @@ prob = ODEProblem( [1.0, 0.0], (0.0, 1.0)) +invariant(x) = norm(x) + # Convergence with the old method Tsit5() sim = test_convergence(dts, prob, Tsit5()) println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) @@ -21,21 +23,21 @@ sim = test_convergence(dts, prob, Tsit5_for_relaxation()) println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) # Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst -r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x))) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant)) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) # Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst -r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x))) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant)) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) # Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) -r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, x-> norm(x), fsal_r)) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant, fsal_r)) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) # Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) -r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, x-> norm(x), r_fsal), postEEst = fsal_r_int) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant, r_fsal), postEEst = fsal_r_int) sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/non_linear_oscillator.jl b/test/relaxation/non_linear_oscillator.jl new file mode 100644 index 0000000000..63b51f6128 --- /dev/null +++ b/test/relaxation/non_linear_oscillator.jl @@ -0,0 +1,43 @@ +using OrdinaryDiffEq, DiffEqDevTools + +include("relaxation.jl") + +printstyled("Non linear harmonic oscillator\n"; bold = true) + +dts = (1 / 2) .^ (6:-1:4) + +f = (u, p, t) -> [-u[2]/(u[1]^2 + u[2]^2),u[1]/(u[1]^2 + u[2]^2)] +prob = ODEProblem( + ODEFunction(f; analytic = (u0, p, t) -> [cos(t), sin(t)]), + [1.0, 0.0], + (0.0, 1.0)) + +invariant(x) = norm(x) + +# Convergence with the old method Tsit5() +sim = test_convergence(dts, prob, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) + +# Convergence with the new method Tsit5_fors_relaxation() without relaxation +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant, fsal_r)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant, r_fsal), postEEst = fsal_r_int) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/non_linear_pendulum.jl b/test/relaxation/non_linear_pendulum.jl new file mode 100644 index 0000000000..15c61995dd --- /dev/null +++ b/test/relaxation/non_linear_pendulum.jl @@ -0,0 +1,45 @@ +using OrdinaryDiffEq, DiffEqDevTools + +include("relaxation.jl") + +printstyled("Non Linear Pendulum\n"; bold = true) + +dts = (1 / 2) .^ (6:-1:4) + +f = (u, p, t) -> [-sin(u[2]), u[1]] +prob = ODEProblem( + f, + [1.0, 0.0], + (0.0, 1.0)) + +invariant(x) = x[1]^2/2 - cos(x[2]) + +test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14) + +# Convergence with the old method Tsit5() +sim = analyticless_test_convergence(dts, prob, Tsit5(), test_setup) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) + +# Convergence with the new method Tsit5_fors_relaxation() without relaxation +sim = analyticless_test_convergence(dts, prob, Tsit5_for_relaxation(), test_setup) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant)) +sim = analyticless_test_convergence(dts, prob, Tsit5_for_relaxation(), test_setup; modif = r) +println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant)) +sim = analyticless_test_convergence(dts, prob, Tsit5_for_relaxation(), test_setup; modif = r) +println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant, fsal_r)) +sim = analyticless_test_convergence(dts, prob, Tsit5_for_relaxation(), test_setup; modif = r) +println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant, r_fsal), postEEst = fsal_r_int) +sim = analyticless_test_convergence(dts, prob, Tsit5_for_relaxation(), test_setup; modif = r) +println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file diff --git a/test/relaxation/time_dependant_harmonic_oscillator.jl b/test/relaxation/time_dependant_harmonic_oscillator.jl new file mode 100644 index 0000000000..afa2b7bab1 --- /dev/null +++ b/test/relaxation/time_dependant_harmonic_oscillator.jl @@ -0,0 +1,45 @@ +using OrdinaryDiffEq, DiffEqDevTools + +include("relaxation.jl") + +printstyled("Time-dependent harmonic oscillator\n"; bold = true) + +dts = (1 / 2) .^ (6:-1:4) + +f = (u, p, t) -> [-(1+0.5 * sin(t))*u[2], (1+0.5 * sin(t))*u[1]] +prob = ODEProblem( + ODEFunction(f; + analytic = (u0, p, t)->[cos(0.5)*cos(t-0.5*cos(t))-sin(0.5)*sin(t-0.5*cos(t)), + sin(0.5)*cos(t-0.5*cos(t))+cos(0.5)*sin(t-0.5*cos(t))]), + [1.0, 0.0], + (0.0, 1.0)) + +invariant(x) = norm(x) + +# Convergence with the old method Tsit5() +sim = test_convergence(dts, prob, Tsit5()) +println("order of convergence of older perform_step! : "*string(sim.𝒪est[:final])) + +# Convergence with the new method Tsit5_fors_relaxation() without relaxation +sim = test_convergence(dts, prob, Tsit5_for_relaxation()) +println("order of convergence of new perform_step! without relaxation: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ₊₁), before EEst +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification before EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation without FSAL modification, i.e f(uᵧ,ₙ₊₁) ≈ f(uₙ₊₁) , after EEst +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation without FSAL modification after EEst: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with FSAL-R, i.e f(uᵧ,ₙ₊₁) ≈ f(uᵧ,ₙ) + γ ( f(uₙ₊₁) - f(uᵧ,ₙ)) +r = PerformStepCallback(;postEEst = Relaxation(AlefeldPotraShi, invariant, fsal_r)) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with FSAL-R modification: "*string(sim.𝒪est[:final])) + +# Convergence with relaxation with R-FSAL, i.e f(uₙ₊₁) ≈ f(uᵧ,ₙ) + 1/γ ( f(uᵧ,ₙ₊₁) - f(uᵧ,ₙ) ) +r = PerformStepCallback(;poststep = Relaxation(AlefeldPotraShi, invariant, r_fsal), postEEst = fsal_r_int) +sim = test_convergence(dts, prob, Tsit5_for_relaxation(); modif = r) +println("order with relaxation with R-FSAL modification: "*string(sim.𝒪est[:final])) \ No newline at end of file From f208a53c883a3a67e56f522a2b931c995a44aea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Duez?= <42682941+Theozeud@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:32:51 +0200 Subject: [PATCH 39/39] small fix --- src/perform_step/test_for_relaxation_perform_step.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/perform_step/test_for_relaxation_perform_step.jl b/src/perform_step/test_for_relaxation_perform_step.jl index e8aac1db64..42193c1c99 100644 --- a/src/perform_step/test_for_relaxation_perform_step.jl +++ b/src/perform_step/test_for_relaxation_perform_step.jl @@ -219,8 +219,8 @@ end end @muladd function calculate_EEst!(integrator, cache::Tsit5Cache_for_relaxation) - T = constvalue(recursive_unitless_bottom_eltype(u)) - T2 = constvalue(typeof(one(t))) + T = constvalue(recursive_unitless_bottom_eltype(integrator.u)) + T2 = constvalue(typeof(one(integrator.t))) @OnDemandTableauExtract Tsit5ConstantCacheActual T T2 @unpack k1, k2, k3, k4, k5, k6, k7, utilde, atmp, thread = cache @.. broadcast = false thread = threa utilde = integrator.dt *