# What is the "interface" necessary for DifferentialEquations.jl if your data type does not subclass AbstractArray?

**URL:** <https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480>\
**Category:** Modelling & Simulations\
**Tags:** diffeq, interface\
**Created:** [April 3, 2021, 2:58am UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480 "2021-04-03T02:58:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 3, 2021, 2:58am UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/1 "2021-04-03T02:58:23Z")

</div>

There are a few similar conversation from previous years in this forum (e.g. [JuliaDiffEq with custom types - #24 by mzilhao](https://discourse.julialang.org/t/juliadiffeq-with-custom-types/16294/24)), but I was not able to find official documentation on the topic, and I am uncertain how much of this information is out of date. Implementing the interface suggested in older conversations does not currently work for me (it seems `vec` or `safevec` might be required, which confuses me?).

Hence my question: For a completely arbitrary type (that permits 1D indexing and has an `eltype` of some reasonable scalar type, but does not subclass `AbstractArray`), what is the officially required interface for it to work with `DifferentialEquations.jl`? Or are we advised to not use completely custom objects?

---

<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:** [April 3, 2021, 11:02am UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/2 "2021-04-03T11:02:01Z")

</div>

> [@Krastanov](#):
>
> Hence my question: For a completely arbitrary type (that permits 1D indexing and has an `eltype` of some reasonable scalar type, but does not subclass `AbstractArray` ), what is the officially required interface for it to work with `DifferentialEquations.jl` ? Or are we advised to not use completely custom objects?

It depends on the solver. With OrdinaryDiffEq, you just need a valid broadcast. Here’s a tested type which doesn’t even have indexing and works with non-stiff solvers in OrdinaryDiffEq:

> <https://github.com/SciML/OrdinaryDiffEq.jl/blob/master/test/interface/noindex_tests.jl>

For implicit methods you need linear algebraic operations.

---

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 3, 2021, 10:22pm UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/3 "2021-04-03T22:22:03Z")

</div>

This seems to work for `in-place: false` problems, but when I try to set up an `in-place: true` problem, I get the following error:

```julia
LoadError: MethodError: no method matching recursivecopy!(::MyType{,,,}, ::MyType{...})

```

Does this mean that my package **has to depend on RecursiveArrayTools** so that I can define a `recursivecopy!` method? Or is there a way to define this interface without importing extra packages?

---

<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:** [April 3, 2021, 10:37pm UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/4 "2021-04-03T22:37:37Z")

</div>

You probably will need RecursiveArrayTools because it defines some things that really all packages need. The definition of `recursivecopy!` could probably move to ArrayInterface.jl and then to Base.

---

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 5, 2021, 3:48am UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/5 "2021-04-05T03:48:28Z")

</div>

Now I have the weirdest problem with “ghost” allocations for this new type that implements this interface.

An `in-place:false` problem makes **fewer** allocations than an `in-place:true` version of the same problem!? This is not a typo, it should indeed be the opposite. And it does not seem to be an issue with broadcasting mis-implementation, as broadcasting on its own does not cause allocations.

Debugging this has been a mess, as each of the functions in `perform_step!` do not allocate when tested with `@time`, but `@time perform_step!` shows a very large number of allocations.

`perform_step!(i, c::Tsit5Cache)` is being used for the in-place operations. Testing each of its statements by hand (of the form `integrator.f(du, u)` and `u .+ a .* k`) **do not allocate**. By testing the `perform_step!` as a whole, it allocates. But then, profiling with `julia --track-allocation=user` (or `=all`) **does not show allocations**. Is there some caveats I should be aware of when using `--track-allocation`? The `perform_step/*.jl.mem` files showed very minimal allocation, **not** what the `@time` or `@btime` macros show in REPL (it was not allocations due to compilation).

---

<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:** [April 5, 2021, 10:26am UTC](https://discourse.julialang.org/t/what-is-the-interface-necessary-for-differentialequations-jl-if-your-data-type-does-not-subclass-abstractarray/58480/6 "2021-04-05T10:26:38Z")

</div>

> [@Krastanov](#):
>
> `perform_step!(i, c::Tsit5Cache)` is being used for the in-place operations. Testing each of its statements by hand (of the form `integrator.f(du, u)` and `u .+ a .* k` ) **do not allocate**. By testing the `perform_step!` as a whole, it allocates. But then, profiling with `julia --track-allocation=user` (or `=all` ) **does not show allocations**. Is there some caveats I should be aware of when using `--track-allocation` ? The `perform_step/*.jl.mem` files showed very minimal allocation, **not** what the `@time` or `@btime` macros show in REPL (it was not allocations due to compilation).

I think that’s a general problem with allocation tracking. `--track-allocation` should be correct IIRC.
