# Abstract-type field in struct for solving an ODE problem

Hi, 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.

It assumes concrete types, because you’ll want that if you want your code to be fast anyways. Mutability is checked for how it does recursive copying. You can open up an issue if you want and I can take a deeper look if there’s a good solution here, but I won’t get to it soon. My suggestion would just be to use concrete types.