Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions do not properly redefine with FunctionWrappers in v1.10? #52635

Open
ChrisRackauckas opened this issue Dec 26, 2023 · 6 comments
Open

Comments

@ChrisRackauckas
Copy link
Member

ChrisRackauckas commented Dec 26, 2023

I don't quite understand what's going on here so it's a bit hard to title it. I found it in a test regression in OrdinaryDiffEq.jl SciML/OrdinaryDiffEq.jl#2093 which started giving the wrong error. Seems innocuous, but digging in made it weirder. The MWE I cam up with is:

# Setup
using FunctionWrappers, ForwardDiff, OrdinaryDiffEq

const a = Float64[1.0]
function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = t
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
u = [1.0; 0.0; 0.0]
du = copy(u)
t = 0.0
dualgen(::Type{T}) where {T} = ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, T}, T, 1}
T = Float64
T1 = Float64
dualT = dualgen(T)

# Version 1
R = Nothing
A = Tuple{Vector{dualgen(T)}, Vector{dualgen(T)}, SciMLBase.NullParameters, Float64}
ff = FunctionWrappers.FunctionWrapper{R, A}(SciMLBase.Void(lorenz!))

ff(du,u,SciMLBase.NullParameters(),t)

Which gives:

julia> ff(du,u,SciMLBase.NullParameters(),t)
ERROR: TypeError: in cfunction, expected Union{}, got a value of type Nothing
Stacktrace:
 [1] macro expansion
   @ FunctionWrappers C:\Users\accou\.julia\packages\FunctionWrappers\Q5cBx\src\FunctionWrappers.jl:137 [inlined]
 [2] do_ccall(f::FunctionWrappers.FunctionWrapper{…}, args::Tuple{…})
   @ FunctionWrappers C:\Users\accou\.julia\packages\FunctionWrappers\Q5cBx\src\FunctionWrappers.jl:125
 [3] (::FunctionWrappers.FunctionWrapper{Nothing, Tuple{…}})(::Vector{Float64}, ::Vararg{Any})
   @ FunctionWrappers C:\Users\accou\.julia\packages\FunctionWrappers\Q5cBx\src\FunctionWrappers.jl:144
 [4] top-level scope
   @ REPL[27]:1
Some type information was truncated. Use `show(err)` to see complete types.

And you might go, that's not an MWE! Delete stuff. Well... deleting stuff and replacing it with the same thing... is fine. Here's the definition of Void: https://github.com/SciML/SciMLBase.jl/blob/v2.11.7/src/utils.jl#L477-L483 . Let's just remove a bit of package code by copy pasting that into the MWE:

struct Void{F}
    f::F
end
function (f::Void)(args...)
    f.f(args...)
    nothing
end
ff = FunctionWrappers.FunctionWrapper{R, A}(Void(lorenz!))
ff(du,u,SciMLBase.NullParameters(),t)

Tada! That works fine. What about getting rid of SciMLBase.NullParameters, that's just a singleton so what about nothing:

R = Nothing
A = Tuple{Vector{dualgen(T)}, Vector{dualgen(T)}, Nothing, Float64}
ff = FunctionWrappers.FunctionWrapper{R, A}(SciMLBase.Void(lorenz!))

ff(du,u,nothing,t)

That works fine too!

So it seems this exact combination of arguments, and only using the version of things in the precompiled (?) package, causes the error. And I don't know what this error really is. It's a v1.10 only issue, so I'm posting here though it's also maybe FunctionWrappers.jl related?

@ChrisRackauckas
Copy link
Member Author

Umm it went away now. Even more confused, but okay.

@ChrisRackauckas
Copy link
Member Author

Okay nope, even more confused. You have to run the failing test before running the MWE?

using FunctionWrappers, ForwardDiff, OrdinaryDiffEq, Test

const a = Float64[1.0]
function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = u[2]
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
u0 = [1.0; 0.0; 0.0]
tspan = (0.0, 1.0)
prob = ODEProblem(lorenz!, u0, tspan)
@test_throws OrdinaryDiffEq.FirstAutodiffJacError solve(prob, Rosenbrock23())

function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = t
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
prob = ODEProblem(lorenz!, u0, tspan)

# Throws the wrong error
@test_throws OrdinaryDiffEq.FirstAutodiffTgradError solve(prob, Rosenbrock23())

u = [1.0; 0.0; 0.0]
du = copy(u)
t = 0.0
dualgen(::Type{T}) where {T} = ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, T}, T, 1}
T = Float64
T1 = Float64
dualT = dualgen(T)

# Version 1
R = Nothing
A = Tuple{Vector{dualgen(T)}, Vector{dualgen(T)}, SciMLBase.NullParameters, Float64}
ff = FunctionWrappers.FunctionWrapper{R, A}(SciMLBase.Void(lorenz!))

ff(du,u,SciMLBase.NullParameters(),t)

If you omit the test runs before it, it will not error.

@ChrisRackauckas
Copy link
Member Author

using FunctionWrappers, ForwardDiff, OrdinaryDiffEq, Test

const a = Float64[1.0]
function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = u[2]
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end

function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = t
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
u0 = [1.0; 0.0; 0.0]
tspan = (0.0,1.0)
prob = ODEProblem(lorenz!, u0, tspan)

# Throws the wrong error
@test_throws OrdinaryDiffEq.FirstAutodiffTgradError solve(prob, Rosenbrock23())

This throws the right error and the subsequent call works fine, but the following does not:

using FunctionWrappers, ForwardDiff, OrdinaryDiffEq, Test

const a = Float64[1.0]
function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = u[2]
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
u0 = [1.0; 0.0; 0.0]
tspan = (0.0, 1.0)
prob = ODEProblem(lorenz!, u0, tspan)
@test_throws OrdinaryDiffEq.FirstAutodiffJacError solve(prob, Rosenbrock23())

function lorenz!(du, u, p, t)
    du[1] = 10.0(u[2] - u[1])
    a[1] = t
    du[2] = u[1] * (28.0 - u[3]) - u[2]
    du[3] = u[1] * u[2] - (8 / 3) * u[3]
end
u0 = [1.0; 0.0; 0.0]
tspan = (0.0,1.0)
prob = ODEProblem(lorenz!, u0, tspan)

# Throws the wrong error
@test_throws OrdinaryDiffEq.FirstAutodiffTgradError solve(prob, Rosenbrock23())

and the subsequent call errors like in the OP.

I think what this is suggesting is that function re-definition #265 stuff with FunctionWrappers somehow broke. It requires that the internal function wrapper with SciMLBase.Void(lorenz!) is called with the first function, and then when the function is re-defined and the function wrapper is rebuilt it does not seem to be correctly using the redefinition of the function, but instead reverts back to the first definition.

@ChrisRackauckas ChrisRackauckas changed the title Inference-related error with FunctionWrappers and package compilation in v1.10? Functions do not properly redefine with FunctionWrappers in v1.10? Dec 26, 2023
ChrisRackauckas added a commit to SciML/OrdinaryDiffEq.jl that referenced this issue Dec 26, 2023
@vtjnash
Copy link
Sponsor Member

vtjnash commented Dec 27, 2023

Sounds like a FunctionWrappers issue then? I don't think it ever gained full correct support for #265

@ChrisRackauckas
Copy link
Member Author

It wasn't miscompiling on v1.9. You can see from our AD and ModelingToolkit downstream tests here https://github.com/SciML/OrdinaryDiffEq.jl/actions/runs/7333458887/job/19968912271?pr=2093 that it's a v1.10 only issue and not v1.9. I'm not sure if that requires a fix here or in FunctionWrappers.jl but this is the kind of issue I'd like to find a way to patch ASAP.

@pablosanjose
Copy link
Contributor

pablosanjose commented Jan 20, 2024

Perhaps related to the issue yuyichao/FunctionWrappers.jl#30 ?
There the problem takes the form of a segfault upon running this snippet in 1.10 (linux)

using LinearAlgebra, FunctionWrappers
function test()
    function sfunc()
        e = eigen([1.0 + 0im ;;])
        return e
    end
    E = LinearAlgebra.Eigen{Complex{Float64}, Complex{Float64}, Matrix{Complex{Float64}}, Vector{Complex{Float64}}}
    asolver = FunctionWrappers.FunctionWrapper{E,Tuple{}}(sfunc)
    return asolver
end
s = test()
s()
using Symbolics
s()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants