Julia: Abstract-type field in struct for solving an ODE problem

227 Views Asked by At

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 myRegions. 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.

0

There are 0 best solutions below