# How to extract the right-hand side function from a differential equation solution?

**URL:** <https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764>\
**Category:** Numerics\
**Tags:** diffeq\
**Created:** [September 4, 2022, 4:24pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764 "2022-09-04T16:24:54Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![zekeriya.sari](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zekeriya.sari/32/13695_2.png) [@zekeriya.sari](https://discourse.julialang.org/u/zekeriya.sari)\
**Post date:** [September 4, 2022, 4:24pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/1 "2022-09-04T16:24:54Z")

</div>

Hey,

Basically, I want to extract the right hand side function f from the solution of a differential equation \dot{x} = f(x). For a minimum working example consider the following

```julia

julia> using DifferentialEquations

julia> myfunc(dx, x, u, t) = (dx .= -x)

myfunc (generic function with 1 method)

julia> prob = ODEProblem(myfunc, rand(1), (0.0, 1.0))

ODEProblem with uType Vector{Float64} and tType Float64. In-place: true

timespan: (0.0, 1.0)

u0: 1-element Vector{Float64}:

0.848128719065019

julia> sol = solve(prob)

retcode: Success

Interpolation: specialized 4th order "free" interpolation, specialized 2nd order "free" stiffness-aware interpolation

t: 5-element Vector{Float64}:

0.0

0.10002357021250141

0.34209643917644617

0.6554220498434524

1.0

u: 5-element Vector{Vector{Float64}}:

[0.848128719065019]

[0.7674005123680626]

[0.6024086282879929]

[0.4403679037389535]

[0.3120092483176733]

```

I remember that it was once possible to extract the function f from `sol` as

```julia

f = sol.prob.f.f

```

(maybe wrong, not hundred percent sure!). However, for `DifferentialEquations@v7.3.0`, the type of `sol.prob.f.f` is

```julia

julia> typeof(sol.prob.f.f)

FunctionWrappersWrappers.FunctionWrappersWrapper{Tuple{FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{Float64}, Vector{Float64}, SciMLBase.NullParameters, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Vector{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, SciMLBase.NullParameters, Float64}}, FunctionWrappers.FunctionWrapper{Nothing, Tuple{Vector{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}, Vector{Float64}, SciMLBase.NullParameters, ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}, Float64, 1}}}}, false}

```

not `typeof(myufunc)` as I expected. So, I defined the following function

```julia

extract_f(sol) = first(sol.prob.f.f.fw).obj[].f.f

```

to extract f from `sol`.

```julia

julia> extract_f(sol) = first(sol.prob.f.f.fw).obj[].f.f

extract_f (generic function with 1 method)

julia> extract_f(sol)

myfunc (generic function with 1 method)

```

What I want to ask is this: Is there a simpler and maybe tidier way of getting f from `sol`?

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 4, 2022, 6:25pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/2 "2022-09-04T18:25:35Z")

</div>

You could use the [Integrator interface](https://diffeq.sciml.ai/stable/basics/integrator/)

```julia
julia> integrator = init(sol.prob, sol.alg)

```

`integrator.f` is the rhs.

---

<div class="post-metadata">

**Author:** ![zekeriya.sari](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zekeriya.sari/32/13695_2.png) [@zekeriya.sari](https://discourse.julialang.org/u/zekeriya.sari)\
**Post date:** [September 4, 2022, 6:33pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/3 "2022-09-04T18:33:07Z")

</div>

It is definitely a little bit tidier approach, it initializes a new integrator though. ☹

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [September 4, 2022, 6:45pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/4 "2022-09-04T18:45:40Z")

</div>

`SciMLBase.unwrapped_f(sol.prob.f)`, though using undocumented internals is always bound to change.

---

<div class="post-metadata">

**Author:** ![zekeriya.sari](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zekeriya.sari/32/13695_2.png) [@zekeriya.sari](https://discourse.julialang.org/u/zekeriya.sari)\
**Post date:** [September 4, 2022, 6:50pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/5 "2022-09-04T18:50:01Z")

</div>

> [@ChrisRackauckas](#):
>
> though using undocumented internals is always bound to change.

Sure. That is why I am having problems now 😄

---

<div class="post-metadata">

**Author:** ![zekeriya.sari](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zekeriya.sari/32/13695_2.png) [@zekeriya.sari](https://discourse.julialang.org/u/zekeriya.sari)\
**Post date:** [September 4, 2022, 7:11pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/6 "2022-09-04T19:11:51Z")

</div>

> [@ChrisRackauckas](#):
>
> `SciMLBase.unwrapped_f(sol.prob.f)`, though using undocumented internals is always bound to change.

I think I should take some more steps to access `f` from here

```julia
f = SciMLBase.unwrapped_f(sol.prob.f) # ODEFunction
f.f.f # myfunc 

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [September 5, 2022, 3:54pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/7 "2022-09-05T15:54:55Z")

</div>

> [@zekeriya.sari](#):
>
> `SciMLBase.unwrapped_f(sol.prob.f)`

That will generate an unwrapped ODEFunction. `SciMLBase.unwrapped_f(sol.prob.f.f)` is probably as far as you’d ever want to go.

---

<div class="post-metadata">

**Author:** ![zekeriya.sari](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zekeriya.sari/32/13695_2.png) [@zekeriya.sari](https://discourse.julialang.org/u/zekeriya.sari)\
**Post date:** [September 8, 2022, 6:51pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/8 "2022-09-08T18:51:04Z")

</div>

Thank you @ChrisRackauckas for your help. But, for the completeness of the thread, I just want to point out this.

> [@ChrisRackauckas](#):
>
> That will generate an unwrapped ODEFunction. `SciMLBase.unwrapped_f(sol.prob.f.f)` is probably as far as you’d ever want to go.

Actually, `SciMLBase.unwrapped_f(sol.prob.f.f)` is not quite the final point that I wanted to reach. Being different than the MWE given above, in my use case the right-hand function f was actually a functor, e.g.

```julia
mutable struct MyFunc{T}
    a::T 
end 

```

and I wanted to reach an instance `myfunc` of `MyFunc` from the solution `sol` for the mutation of its parameter `myfunc.a` . So, what I wanted was not the `ODEFunction`, but `myfunc` instead.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [September 8, 2022, 8:26pm UTC](https://discourse.julialang.org/t/how-to-extract-the-right-hand-side-function-from-a-differential-equation-solution/86764/9 "2022-09-08T20:26:31Z")

</div>

Ahh okay, and for completeness of the thread we found an issue with the setup before, fixed it ([Fix and better test wrapping levels for AutoSpecialize by ChrisRackauckas · Pull Request #820 · SciML/DiffEqBase.jl · GitHub](https://github.com/SciML/DiffEqBase.jl/pull/820)), and now have tests and documentation on such unwrapping functionality.
