LCOV - code coverage report
Current view: top level - src - evaldy.jl (source / functions) Hit Total Coverage
Test: on branch nothing Lines: 33 40 82.5 %
Date: 2025-02-26 15:13:49 Functions: 0 0 -

          Line data    Source code
       1     1272178 : undefined(::Type{SVector{N, T}}) where {N, T<:Real} =
       2     2570303 :     SVector{N, T}(ntuple(i -> T(NaN), N))
       3             : 
       4           1 : undefined(x::SVector{N, T}) where {T<:Real, N} = undefined(SVector{N, T})
       5             : 
       6             : """
       7             :     val = undefined(x)
       8             :     val = undefined(tyepof(x))
       9             : 
      10             : Helper tthat ceates undefined value of `typeof(x)`.
      11             : 
      12             : See also [`Maybe`](@ref)
      13             : """ undefined
      14             : 
      15             : """
      16             : Encode value of a computation of the ODE solver or failed
      17             : execution [`RK43.State`](@ref).
      18             : 
      19             : See also [`maybe`](@ref), [`RK43.State`](@ref)
      20             : """
      21             : struct Maybe{V}
      22             :     value::V
      23             :     state::State
      24             : 
      25     8656852 :     Maybe{V}(value::V, state::State=Ok) where {V} = new(value, state)
      26             : 
      27      809182 :     function Maybe{V}(state::State) where {V}
      28           0 :         @massert !issuccess(state) "missing value"
      29      809182 :         new(undefined(V), state)
      30             :     end
      31             : 
      32     3888779 :     Maybe{V}(val::Maybe{V}) where {V}= new(val.value, val.state)
      33             : end
      34             : 
      35           2 : function Base.show(io::IO, v::Maybe{V}) where {V}
      36           2 :     issuccess(v) && return show(io, v[])
      37           0 :     show(io, state(v))
      38             : end
      39             : 
      40          22 : maybe(value::V, state::State=Ok,::Type{V}=V) where {V} = Maybe{V}(value, state)
      41           2 : maybe(state::State, ::Type{V}) where {V} = Maybe{V}(state)
      42             : # NOTE: make sure to not confuse the two methods above
      43           2 : maybe(state::State) = error("missing type")
      44             : 
      45     5163322 : state(value::Maybe) = value.state
      46             : 
      47           4 : isundefined(value::Maybe) = !issuccess(value.state)
      48     1284120 : issuccess(value::Maybe) = issuccess(value.state)
      49             : 
      50      879287 : function Base.getindex(value::Maybe{V}) where {V}
      51           0 :     @massert !isundefined(value) "missing value, state=$(state(value))"
      52      879287 :     value.value
      53             : end
      54             : 
      55           0 : requirefinite(val::Maybe{V}) where {V} = val
      56             : 
      57      404590 : function requirefinite(s::State)
      58           0 :     @massert s != Ok "missing value"
      59      404590 :     s
      60             : end
      61             : 
      62     3888779 : @inline function requirefinite(val::SVector{N, T}) where {N, T}
      63     3888779 :     isfinite(sum(val)) && return Maybe{SVector{N, T}}(val)
      64           0 :     Maybe{SVector{N, T}}(Failed)
      65             : end
      66             : 
      67             : """
      68             :     requirefinite(s::State) == s        # requires s != Ok
      69             :     requirefinite(v::Maybe{...}) == v   # no checks
      70             : 
      71             :     v = requirefinite(v::SVector{...}}) :: Maybe{...}
      72             :     @massert isfinite(v.value) || !issucces(v)
      73             : 
      74             : Helper that checks result evaluated as `SVector` in [`WrapDy`](@ref).
      75             : 
      76             : See also [`WrapDy`](@ref)
      77             : """ requirefinite
      78             : 
      79             : 
      80             : """
      81             :     wdy = wrap(dy, solver)
      82             :     wdy(t, y) :: Maybe{...}
      83             : 
      84             : Warp function `dy` in type. `dy(t, y)` returns either
      85             : - an `SVector` (will be checked by  [`requirefinite`](@ref))
      86             : - a `State` other than `Ok` or
      87             : - [`Maybe`](@ref)
      88             : 
      89             : 
      90             : See also [`GuardDy`](@ref), [`Maybe`](@ref), [`requirefinite`](@ref)
      91             : """
      92             : struct WrapDy{F, N, T}
      93             :     dy::F
      94          28 :     WrapDy{F, N, T}(dy) where {F, N, T} = new(dy)
      95             : end
      96             : 
      97     4697959 : (dy::WrapDy{F, N, T})(t::T, y::SVector{N, T}) where {F, N, T} =
      98             :     dy.dy(t, y) |> requirefinite |> Maybe{SVector{N, T}}
      99             : 
     100             : # TODO: requirefinite is slow?!
     101             : 
     102          28 : wrap(dy::F, ::Type{SVector{N, T}}) where {F, N, T} = WrapDy{F, N, T}(dy)
     103           0 : wrap(dy::WrapDy{F, N, T}, ::Type{SVector{N, T}}) where {F, N, T} = dy
     104             : 
     105             : """
     106             :     gdy = guard(wrap(dy, solver))
     107             :     gdy = guard(dy, solver)        # not evaluated if above call failed
     108             : 
     109             :     gdy(t, y) :: SVector{...}
     110             : 
     111             :     issuccess(gdy)
     112             :     s = state(gdy)
     113             : 
     114             : Closure for lazy evaluations of `dy` (within the ODE solver's
     115             :  stepper): Evaluate only while [`issuccess`](@ref).
     116             : 
     117             : See also [`WrapDy`](@ref), [`guard`](@ref)
     118             : """
     119             : mutable struct GuardDy{F, N ,T}
     120             :     const dy::WrapDy{F, N ,T}
     121             :     thestate::State
     122             : 
     123     2616794 :     GuardDy{F, N, T}(dy::WrapDy{F, N, T}, s::State=Ok) where {F, N, T} =
     124             :         new(dy, s)
     125             : end
     126             : 
     127             : """
     128             :     guardedevaluation = guard(warp(dy))
     129             : 
     130             : Construct a [`GuardDy`](@ref) instance for a [`wrap`](@ref)ped
     131             : function `dy(t, y)`.
     132             : 
     133             : See also [`GuardDy`](@ref), [`wrap`](@ref)
     134             : """
     135     1308397 : guard(dy::WrapDy{F, N ,T}) where {F, N, T} = GuardDy{F, N, T}(dy)
     136             : 
     137     4755432 : function (c::GuardDy{F, N, T})(t::T, y::SVector{N, T})::SVector{N, T} where {F, N, T}
     138     4755432 :     (c.thestate != Ok) && return undefined(SVector{N, T})
     139             : 
     140     4697959 :     result = c.dy(t, y)
     141     4293369 :     c.thestate = state(result)
     142     4293369 :     result.value
     143             : end
     144             : 
     145     2187682 : issuccess(guard::GuardDy) = issuccess(state(guard))
     146     2592272 : state(guard::GuardDy) = guard.thestate

Generated by: LCOV version 1.16