# DifferentialEquations v7.13.0 FunctionWrappersWrappers Error

**URL:** https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612
**Category:** Modelling & Simulations
**Tags:** question
**Created:** [May 23, 2024, 7:52am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612 "2024-05-23T07:52:49Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![rebetz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rebetz/32/209471_2.png) [@rebetz](https://discourse.julialang.org/u/rebetz)
#### Post date: [May 23, 2024, 7:52am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/1 "2024-05-23T07:52:49Z")

</div>

Hello,

I have existing code that uses the DifferentialEquations package that was working fine yesterday, but when run today (23/5/2024) it is giving a message from the solver code:

`ERROR: FunctionWrappersWrappers.NoFunctionWrapperFoundError() Stacktrace: [1] _call(::Tuple{}, arg::Tuple{…}, fww::FunctionWrappersWrappers.FunctionWrappersWrapper{…}) @ FunctionWrappersWrappers ~/.julia/packages/FunctionWrappersWrappers/9XR0m/src/FunctionWrappersWrappers.jl:23 etc, etc`

I have tried several different unrelated programs which were previously working, and they all give the same error message.

I am using Julia v1.10.3, DifferentialEquations v7.13.0.

Does anyone have any idea what is going on?

One code example appears below. It is a simple DC machine control program that uses the differential equation ODE solver and a callback to calculate the control.

UPDATE May 24: DifferentialEquations v7.11.0 works OK, so something has happened in v7.12.0 and v7.13.0 to cause this error.

```julia
#=
This file simulates a DC machine equations in ODE format
and applies a current and speed controller around the equations.

=#

using Plots: plot, plot!, plotlyjs, display
using DifferentialEquations
plotlyjs()

#=
        --- PARAMETER SETUP SECTION ---
=#

# Now set up the control equations and times for the
# control to occur
const START_TIME = 2.0
const END_TIME = 10.0
const Δt = 200e-6
const NUM_SETPOINTS = 2 # Number of ωᵣ setpoints
const CONTROL_DELAY = false # true if a control is delayed

ctrl_t = [i for i in 0.0 : Δt : END_TIME]

# Set up parameters for DC machine differential equations
const Rf = 240.0
const ra = 0.6
const Laa = 0.012
const Lff = 120.0
const Laf = 1.8
const J = 1.0
const Bm = 0.0
const vf = 240.0
const va = 0.0
const Tl = 0.0

const p = [Rf, ra, Laa, Lff, Laf, J, Bm, vf, va, Tl]

const Te_max = 29.2 # Nm
const Ia_max = Te_max / (Laf * vf / Rf) # Amps
const Va_max = 240.0 # Volts

#=
The matrix below is used to store the time, reference
pair for the ωᵣ set points.
=#
setP_ωᵣ = zeros(Float64, NUM_SETPOINTS, 2)

setP_ωᵣ = [START_TIME 100.0;
            6.0 25.0]

#=
        --- GLOBALS USED IN control! ---
=#

# The following array is used to store the set points
# for later plotting
ωᵣ_sp_arr = zeros(length(ctrl_t)) # The ωᵣ setpoint value array
ia_sp_arr = zeros(length(ctrl_t)) # the ia set point array
ctrl_va_arr = zeros(length(ctrl_t)) # The control voltage array

# Index used to store the setpoint values
setP_array_idx = 0

# The current global ωᵣ setpoint value
setpt_ωᵣ = 0.0

# For the integral error of the controller
integErr_ωᵣ = 0.0

#= ωᵣ control array
    • ctrl[1] - the desired torque control value
    • ctrl[2] - integral error
    • ctrl[3] - ωᵣ reference error
=#
ctrl_ωᵣ = zeros(Float64, 3)

# For the integral error of the controller
integErr_ia = 0.0

#= ia control array
    • ctrl[1] - desired voltage value
    • ctrl[2] - integral error
    • ctrl[3] - ia reference error
=#
ctrl_ia = zeros(Float64, 3)

# Global variable used to store the previous control if 
# control delay of one time period is being used.
va_km1 = 0.0

#=
       --- END OF control! GLOBALS ---
=#

#=

The parameters for the ωᵣ controller

p_ωᵣ - a parameter list containing
    • [1] Δt - the control time step
    • [2] Kp_ωᵣ - the proportional gain
    • [3] Ti_ωᵣ - integrator time constant
    • [4] High saturation level for the torque
    • [5] Low saturation level for the torque   
=#
ϕₘ_ωᵣ = 0.698 # the desired phase margin in rad
ωc_ωᵣ = (π/2.0 - ϕₘ_ωᵣ) / Δt # approximate cross-over freq rad/sec

Kp_ωᵣ = ωc_ωᵣ * J / Te_max
Ti_ωᵣ = 10.0 / ωc_ωᵣ
p_ωᵣ = zeros(Float64, 5)
p_ωᵣ = (Δt, Kp_ωᵣ, Ti_ωᵣ, Te_max, -Te_max)

#=

The parameters of the ia controller

p_ia - a parameter list containing
    • [1] Δt - the control time step
    • [2] Kp_ia - the proportional gain
    • [3] Ti_ia - integrator time constant
    • [4] High saturation level for ia
    • [5] Low saturation level for ia
=#

ϕₘ_ia = 0.698 # the desired phase margin in rad
ωc_ia = (π/2.0 - ϕₘ_ia) / Δt # approximate cross-over freq rad/sec

Kp_ia = ωc_ia * Laa
Ti_ia = 10.0 / ωc_ia
p_ia = zeros(Float64, 5)
p_ia = (Δt, Kp_ia, Ti_ia, Va_max, -Va_max)

#=
        --- FUNCTION DECLARATIONS ---
=# 

"""
dc_mach

@brief Standard form of a differential equation representation for
            the DifferentialEquations.jl package for Julia.

            The u vector has the following values:
                • u[1] - i_f the field current
                • u[2] - i_a the armature current
                • u[3] - ωᵣ the rotor angular velocity

@params • du - the derivative of u 
            • u - the state vector defined above
            • p - the parameter vector
            • t - the current value of time

@returns • du array
"""
function dc_mach!(du, u, p, t)
    Rf, ra, Laa, Lff, Laf, J, Bm, vf, va, Tl = p

    du[1] = -Rf/Lff * u[1] + 1/Lff * vf
    du[2] = -ra/Laa * u[2] - Laf/Laa * u[1] * u[3] + 1/Laa * va
    du[3] = -Bm/J * u[3] + Laf/J * u[1] * u[2] - Tl
    nothing
end

"""
pi!

@brief This function implements an anti-windup PI
            control algorithm.

            The first parameter is an array, and is therefore
            effectively passed by reference. This allows the
            function to be called by multiple controllers.
            
@params • u - array containing:
                • [1] - the control value
                • [2] - the integral error 
                • [3] - the present time error
            • ymeas - the measurement to be controlled.
            • yref - the desired value for the measurement
            • feedFwd - the feedforward term
            • p - a parameter list containing
                • [1] Δt - the control time step
                • [2] Kp - the proportional gain
                • [3] Ti - integrator time constant
                • [4] SatH - high saturation level
                • [5] SatL - low saturation level

@returns • u array:
                • [1] - the calculated control value
                • [2] - the integral error
                • [3] - the present time error
"""
function pi!(u::Vector{Float64}, ymeas::Float64, yref::Float64, feedFwd::Float64, p::Tuple{Vararg{Float64,5}})
# function pi!(u, ymeas, yref, feedFwd, p)
    Δt, Kp, Ti, SatH, SatL = p

    u[3] = yref - ymeas
    integErrTmp = u[2] + Δt / Ti * u[3]
    u[1] = Kp * (u[3] + integErrTmp) + feedFwd

    # Now check on saturation
    if u[1] > SatH
        u[1] = SatH

        # If the error does no increase saturation then
        # update the integral error
        if u[3] < 0.0
           u[2] = integErrTmp
        end
    elseif u[1] < SatL
        u[1] = SatL

        # If the error does no increase saturation then
        # update the integral error
        if u[3] > 0.0
            u[2] = integErrTmp
        end
    else
        u[2] = integErrTmp
    end
end

"""
control!

@brief This function is called upon a discrete time event
            from the integrator. These events occur upon the
            control time period, and result in this function 
            being called to executed the control strategy.

            This function accesses global variables for the
            set points of the relevant controllers as well as
            the control parameters returned from the pi!
            controller algorithm.

@params The integrator object

@returns Changes to the integrator object.
"""
function control!(integrator)

    global setP_array_idx, setP_ωᵣ, ωᵣ_sp_arr, ia_sp_arr
    global ctrl_va_arr, ctrl_ωᵣ, ctrl_ia, integErr_ωᵣ, integErr_ia
    global p_ωᵣ, p_ia, setpt_ωᵣ, START_TIME
    global va_km1

    setP_array_idx += 1

    if integrator.t >= START_TIME
        integrator.p[10] = 10.0
        # The first controller is the angular velocity controller
        # Find the reference value
        setp_idx = findall(x -> x == integrator.t, setP_ωᵣ[:,1])
        if setp_idx != []
            setpt_ωᵣ = setP_ωᵣ[setp_idx[1], 2]
        end
        ωᵣ_sp_arr[setP_array_idx] = setpt_ωᵣ # save the setpoint

        # Now call the ωᵣ controller
        feedFwd = 0.0
        ctrl_ωᵣ[2] = integErr_ωᵣ
        pi!(ctrl_ωᵣ, integrator.u[3], setpt_ωᵣ, feedFwd, p_ωᵣ)

        # setpt_ia = ctrl_ωᵣ[1] / (integrator.p[5] * integrator.u[1])
        setpt_ia = ctrl_ωᵣ[1]
        integErr_ωᵣ = ctrl_ωᵣ[2]

        # Now limit setpt_ia - could be larger than Ia_max if
        # field current is at incorrect level.
        if setpt_ia > Ia_max
            setpt_ia = Ia_max
        elseif setpt_ia < -Ia_max
            setpt_ia = -Ia_max
        end
        ia_sp_arr[setP_array_idx] = setpt_ia # save the set point

        # Now call the ia current controller
        # Feed forward the back-emf of the machine
        feedFwd = integrator.p[5] * integrator.u[1] * integrator.u[3]
        ctrl_ia[2] = integErr_ia
        pi!(ctrl_ia, integrator.u[2], setpt_ia, feedFwd, p_ia)

        # Save the control integral error
        integErr_ia = ctrl_ia[2]

        # now limit the control voltage
        if ctrl_ia[1] > Va_max
            va = Va_max
        elseif ctrl_ia[1] < -Va_max
            va = -Va_max
        else
            va = ctrl_ia[1]
        end
        va_km1 = va
        # Put the control out with a delay if selected
        @static if CONTROL_DELAY == true
                
            # save the control voltage
            ctrl_va_arr[setP_array_idx] = va_km1

            # apply the control voltage to the machine
            integrator.p[9] = va_km1
        end
        @static if CONTROL_DELAY == false
            # There is no control delay so output the current
            # value of the control.

            # save the control voltage for later plotting
            ctrl_va_arr[setP_array_idx] = va

            # apply the control voltage to the machine
            integrator.p[9] = va
        end
    else
        ωᵣ_sp_arr[setP_array_idx] = 0.0
        ia_sp_arr[setP_array_idx] = 0.0
        ctrl_va_arr[setP_array_idx] = 0.0
    end
    nothing
end

#=
        --- MAIN PROGRAM ---
=#

# Initial conditions for DE solution

u0 = [0.0, 0.0, 0.0]
tspan = (0.0, 10.0)
prob = ODEProblem(dc_mach!, u0, tspan, p)

# condition(u, t, integrator) = t ∈ ctrl_t
# cb = DiscreteCallback(condition, control!)
cb = PresetTimeCallback(ctrl_t, control!)

# Start the solution and control problem
sol = solve(prob, callback = cb, tstops = ctrl_t)

# Plot out the results
plot1 = plot(sol, title="DC Machine Main Performance Parameters", linewidth = 2, label=["if" "ia" "ωᵣ"])
display(plot1)

plot2 = plot(sol.t, [sol.u[i][1] for i in 1:length(sol.t)], linewidth = 2, label = "i_f")
display(plot2)

plot3 = plot(sol.t, [sol.u[i][2] for i in 1:length(sol.t)], linewidth=2, label = "iₐ", xlim = (0.0, 10.0))
plot!(ctrl_t, ia_sp_arr, linestyle = :dash, label = "iₐ Set Points", linewidth = 2,)
display(plot3)

plot4 = plot(sol.t, [sol.u[i][3] for i in 1:length(sol.t)], linewidth = 2, label = "ωᵣ")
plot!(ctrl_t, ωᵣ_sp_arr, label = "ωᵣ Set Points", linestyle = :dash, linewidth = 2,)
display(plot4)

plot5 = plot(ctrl_t, ctrl_va_arr, label = "Applied vₐ", linewidth = 2,)
display(plot5)

```

---

<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: [May 25, 2024, 3:51pm UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/2 "2024-05-25T15:51:42Z")

</div>

If you use `ODEProblem{true, SciMLBase.FullSpecialize}(...)` is it fine?

---

<div class="post-metadata">

### Author: ![rebetz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rebetz/32/209471_2.png) [@rebetz](https://discourse.julialang.org/u/rebetz)
#### Post date: [May 26, 2024, 8:38am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/3 "2024-05-26T08:38:14Z")

</div>

> [@ChrisRackauckas](#):
>
> {true, SciMLBase.FullSpecialize}

Chris, Thanks for replying. I tried the change you suggested in the simple DC machin program in the original post and I can a different error. I have put the stack trace below.

For the time being I have rolled back to v7.11.0 of the DE package on my main Mac machine so that things will still work. For testing I have installed a Julia/Visual Code system in a Ubuntu virtual machine.

```julia
ERROR: MethodError: no method matching dc_mach!(::Vector{Float64}, ::Vector{Float64}, ::Float64)

Closest candidates are:
  dc_mach!(::Any, ::Any, ::Any, ::Any)
   @ Main /media/psf/Home/Documents/Working_copies/DST/Large_Motor_Project/Support_Docs/Developed_Docs/Technical_Reports/BLDCM_Sim_Model/Sims/Julia_Sims/SPM_BLDCM_Sim/Test_Programs/dc_mach_ctrl.jl:169

Stacktrace:
  [1] (::ODEFunction{…})(::Vector{…}, ::Vararg{…})
    @ SciMLBase ~/.julia/packages/SciMLBase/JUp1I/src/scimlfunctions.jl:2296
  [2] reset_fsal!(integrator::OrdinaryDiffEq.ODEIntegrator{…})
    @ OrdinaryDiffEq ~/.julia/packages/OrdinaryDiffEq/k912u/src/integrators/integrator_utils.jl:493
  [3] apply_step!(integrator::OrdinaryDiffEq.ODEIntegrator{…})
    @ OrdinaryDiffEq ~/.julia/packages/OrdinaryDiffEq/k912u/src/integrators/integrator_utils.jl:404
  [4] loopheader!(integrator::OrdinaryDiffEq.ODEIntegrator{…})
    @ OrdinaryDiffEq ~/.julia/packages/OrdinaryDiffEq/k912u/src/integrators/integrator_utils.jl:14
  [5] solve!(integrator::OrdinaryDiffEq.ODEIntegrator{…})
    @ OrdinaryDiffEq ~/.julia/packages/OrdinaryDiffEq/k912u/src/solve.jl:549
  [6] #__solve#799
    @ ~/.julia/packages/OrdinaryDiffEq/k912u/src/solve.jl:7 [inlined]
  [7] __solve
    @ ~/.julia/packages/OrdinaryDiffEq/k912u/src/solve.jl:1 [inlined]
  [8] solve_call(_prob::ODEProblem{…}, args::CompositeAlgorithm{…}; merge_callbacks::Bool, kwargshandle::Nothing, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:612
  [9] solve_up(prob::ODEProblem{…}, sensealg::Nothing, u0::Vector{…}, p::Vector{…}, args::CompositeAlgorithm{…}; kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1080
 [10] solve_up
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1066 [inlined]
 [11] #solve#51
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1003 [inlined]
 [12] solve
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:993 [inlined]
 [13] #__solve#804
    @ ~/.julia/packages/OrdinaryDiffEq/k912u/src/solve.jl:542 [inlined]
 [14] __solve
    @ ~/.julia/packages/OrdinaryDiffEq/k912u/src/solve.jl:541 [inlined]
 [15] #__solve#72
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1394 [inlined]
 [16] __solve
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1386 [inlined]
 [17] solve_call(::ODEProblem{…}; merge_callbacks::Bool, kwargshandle::Nothing, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:612
 [18] solve_up(::ODEProblem{…}, ::Nothing, ::Vector{…}, ::Vector{…}; kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1072
 [19] solve_up
    @ ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1066 [inlined]
 [20] solve(::ODEProblem{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{…})
    @ DiffEqBase ~/.julia/packages/DiffEqBase/PBhFc/src/solve.jl:1003
 [21] top-level scope
    @ /media/psf/Home/Documents/Working_copies/DST/Large_Motor_Project/Support_Docs/Developed_Docs/Technical_Reports/BLDCM_Sim_Model/Sims/Julia_Sims/SPM_BLDCM_Sim/Test_Programs/dc_mach_ctrl.jl:354
Some type information was truncated. Use `show(err)` to see complete types.

julia> 

```

---

<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: [May 26, 2024, 11:13am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/4 "2024-05-26T11:13:45Z")

</div>

@Oscar_Smith the new defaulter has tests for out of place?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [May 26, 2024, 12:35pm UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/5 "2024-05-26T12:35:06Z")

</div>

it does. I’ll investigate what’s going on here.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [May 26, 2024, 2:27pm UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/6 "2024-05-26T14:27:41Z")

</div>

What version of `OrdinaryDiffEq` do you have? If you update to the latest version (v6.80.0), I believe this is resolved. Note also that now that `OrdinaryDiffEq` has the default solver, you should no longer need `DifferentialEquations` at all, and can just use `OrdinaryDiffEq` which will take a lot less time to precompile and will bring in fewer dependencies.

---

<div class="post-metadata">

### Author: ![rebetz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rebetz/32/209471_2.png) [@rebetz](https://discourse.julialang.org/u/rebetz)
#### Post date: [May 28, 2024, 12:22am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/7 "2024-05-28T00:22:14Z")

</div>

Oscar,

I tried using the OrdinaryDIffEq but the PresetTimeCallback does not work with OrdinaryDiffEq. I then tried re-updating all of the packages, and V6.80.1 of OrdinaryDiffEq was loaded together with DifferentialEquations v7.13.0. The programs that had the problem now work, so there must have been a fix in these updates for the original problem.

Thanks for your assistance.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [May 28, 2024, 12:36am UTC](https://discourse.julialang.org/t/differentialequations-v7-13-0-functionwrapperswrappers-error/114612/8 "2024-05-28T00:36:10Z")

</div>

v6.80.1 fixed the issue, for `PresetTimeCallback` you would also need `DiffEqCallbacks`.
