11"""
2- set_discontinuity(u, uprev, integrator) -> dt
2+ set_discontinuity(integrator) -> dt
33
44Return the sub-step `Δt` at which a continuous callback's root lies within the
55current step (a discontinuity to stop at), or a negative value if there is none in
66`(0, 1)·dt`.
77"""
8- function set_discontinuity (u, uprev, integrator)
9- breakpointθ = find_discontinuity (u, uprev, integrator)
8+ function set_discontinuity (integrator)
9+ breakpointθ = find_discontinuity (integrator)
1010 dt = integrator. dt
11- if 1.0e-10 < breakpointθ < 1.0
12- return breakpointθ * dt
11+ if breakpointθ < one (breakpointθ)
12+ # below formula is equivalent to (0.5 + 0.4 * sin(π * (breakpointθ - 0.5))) * dt
13+ return (0.5 + 1.2372 * (breakpointθ - 0.5 ) - 1.7487 * (breakpointθ - 0.5 )^ 3 ) * dt
1314 end
1415 return - one (dt)
1516end
@@ -18,17 +19,21 @@ get_disco_probs(cache::AbstractControllerCache) = cache.controller.basic.disco_p
1819get_disco_probs (cache:: DummyControllerCache ) = cache. disco_probs
1920get_disco_probs (cache:: CompositeControllerCache ) = get_disco_probs (first (cache. caches))
2021
21- function find_discontinuity (u, uprev, integrator)
22+ function find_discontinuity (integrator)
2223 cb = integrator. opts. callback
2324 dt = integrator. dt
24- cb === nothing && return - one (dt)
25- isempty (cb. continuous_callbacks) && return - one (dt)
25+ u = integrator. u
26+ uprev = integrator. uprev
27+ integrator. is_disco_step = false
28+ cb === nothing && return one (dt)
29+ isempty (cb. continuous_callbacks) && return one (dt)
2630 p = integrator. p
2731 t = integrator. t
2832 k = integrator. k
29- breakpointθ = - one (dt)
33+ breakpointθ = one (dt)
3034 disco_probs = get_disco_probs (integrator. controller_cache)
3135 idx = 1
36+ addsteps_called = false
3237 for i in cb. continuous_callbacks
3338 if (! (i. maybe_discontinuity))
3439 continue
@@ -47,22 +52,38 @@ function find_discontinuity(u, uprev, integrator)
4752 i. condition (disco_zero. out_high, u, t + dt, integrator)
4853 for j in 1 : len_cb
4954 if (disco_zero. out_low[j] * disco_zero. out_high[j] < zero (disco_zero. out_low[j]))
55+ if (! addsteps_called)
56+ addsteps_called = true
57+ _ode_addsteps! (disco_zero. k, disco_zero. tprev, disco_zero. uprev, disco_zero. u,
58+ disco_zero. dt, disco_zero. f, disco_zero. p, disco_zero. cache, false , true , false )
59+ end
5060 disco_zero. ind = j
61+ disco_prob. tspan[2 ] = breakpointθ
5162 sol = solve (disco_prob)
5263 tmp = sol[]
53- if (! isnan (tmp) && (breakpointθ < zero (breakpointθ) || tmp < breakpointθ) )
64+ if (! isnan (tmp) && tmp < breakpointθ)
5465 breakpointθ = tmp
66+ integrator. is_disco_step = true
67+ integrator. disco_checkpoint = integrator. t + dt # our prev rejected step, we shouldn't step too far past this
5568 end
5669 end
5770 end
5871 else
59- out_prev = i. condition (uprev, t, integrator)
60- out_curr = i. condition (u, t + dt, integrator)
61- if (out_prev * out_curr < zero (out_prev))
72+ disco_zero. out_low[1 ] = i. condition (uprev, t, integrator)
73+ disco_zero. out_high[1 ] = i. condition (u, t + dt, integrator)
74+ if (disco_zero. out_low[1 ] * disco_zero. out_high[1 ] < zero (disco_zero. out_low[1 ]))
75+ if (! addsteps_called)
76+ addsteps_called = true
77+ _ode_addsteps! (disco_zero. k, disco_zero. tprev, disco_zero. uprev, disco_zero. u,
78+ disco_zero. dt, disco_zero. f, disco_zero. p, disco_zero. cache, false , true , false )
79+ end
80+ disco_prob. tspan[2 ] = breakpointθ
6281 sol = solve (disco_prob)
6382 tmp = sol[]
64- if (! isnan (tmp) && (breakpointθ < zero (breakpointθ) || tmp < breakpointθ) )
83+ if (! isnan (tmp) && tmp < breakpointθ)
6584 breakpointθ = tmp
85+ integrator. is_disco_step = true
86+ integrator. disco_checkpoint = integrator. t + dt # our prev rejected step, we shouldn't step past this
6687 end
6788 end
6889 end
0 commit comments