I’m learning Julia
and particularly interested in solving differential equations using the DifferentialEquations package. I’m having a trouble with understanding how to make a good type-stable struct that is integrated. For example, I have this mutable struct to be integrated.
mutable struct State{T} <: DEDataVector{T}
x::Vector{T}
r::Region
end
where Region
is custom-defined abstract type: abstract type Region end
The role of Region
is to parameterize my ODE function with Callback functions. For instance,
function myODE(du, u, p, t)
c = getCoeff(u.r)
du[1] = c*u[1]
end
which is a simplified version of my actual code but I believe it exhibits what I’m trying to say well enough. Especially, which region r::Region
should be in at each time t
should be determined by t
and it must be updated properly by Callback features.
I have a bunch of concrete-type structs whose supertype is Region
, for example
struct myRegion1 <: Region
property1::Int64
property2::Float64
...
end
and so on similarly for the other myRegion
s. And I have well-defined overloaded functions getCoeff(r::myRegion1), getCoeff(r::myRegion2), …
for each region. This woked fine, but I found the integration is not optimized unless I have type-stable fields in my State
struct. It’s tested with @code_warntype
on myODE function. Since Region
is an abstract type, the compiler has no solid inference on type, which leads to a performance hit for the integration.
After searching for the solution for this case, I found many people suggest to rather use parametric type struct or use Union of concrete-type structs. The former one can’t be the solution for this case, because I have a mixed type for r
in my State
struct. For instance, say r
is initialized to be myRegion1
. But as the integration proceeds, it should be updated to myRegion2
or another when Callback is called. Therefore, I must not use a parametric State struct in terms of Region
.
The second solution seemed like it’d work, but I end up facing another problem.
First I defined a Union
type as following:
const myRegions = Union{myRegion1, myRegion2, ...}
Then I modified the definition of my State
struct as
mutable struct State{T} <: DEDataVector{T}
x::Vector{T}
r::myRegions
end
and r
is no longer abstract type. But when I run the integration by
prob = ODEProblem(myODE, u0, timeSpan, p)
solve(prob, algorithm, callback=callbacks)
I got an unexpected error:
type Union has no field mutable
Apparently, the integrator checks whether type of every field of u is mutable or not, which is not even defined in Union
type. So I really got stuck here… any ideas or suggestions would be really appreciated. Thanks for reading this post.