The AbstractVectorOfArray and AbstractDiffEqArray Interfaces

RecursiveArrayTools.AbstractVectorOfArrayType
AbstractVectorOfArray{T, N, A}

An AbstractVectorOfArray is an object which represents arrays of arrays, and arbitrary recursive nesting of arrays, as a single array-like object. Thus a canonical example of an AbstractVectorOfArray is something of the form VectorOfArray([[1,2],[3,4]]), which "acts" like the matrix [1 3; 2 4] where the data is stored and accessed in a column-ordered fashion (as is typical in Julia), but the actual matrix is never constructed and instead lazily represented through the type.

An AbstractVectorOfArray subtype should match the following behaviors.

Note

As of v4.0, AbstractVectorOfArray <: AbstractArray. Linear indexing A[i] now returns the ith element in column-major order, matching standard Julia AbstractArray behavior. To access the ith inner array, use A.u[i] or A[:, i]. For ragged arrays (inner arrays of different sizes), size(A) reports the maximum size in each dimension and out-of-bounds elements are interpreted as zero (sparse representation). This means all standard linear algebra operations work out of the box.

Fields

An AbstractVectorOfArray has the following fields:

  • u which holds the Vector of values at each timestep

Array Interface

The general operations are as follows. Use

A.u[j]

to access the jth array. For multidimensional systems, this will address first by component and lastly by time, and thus

A[i, j]

will be the ith component at array j. Hence, A[j][i] == A[i, j]. This is done because Julia is column-major, so the leading dimension should be contiguous in memory. If the independent variables had shape (for example, was a matrix), then i is the linear index. We can also access solutions with shape:

A[i, k, j]

gives the [i,k] component of the system at array j. The colon operator is supported, meaning that

A[i, :]

gives the timeseries for the ith component.

Using the AbstractArray Interface

The AbstractArray interface can be directly used. For example, for a vector system of variables A[i,j] is a matrix with rows being the variables and columns being the timepoints. Operations like A' will transpose the solution type. Functionality written for AbstractArrays can directly use this. For example, the Base cov function computes correlations amongst columns, and thus:

cov(A)

computes the correlation of the system state in time, whereas

cov(A, 2)

computes the correlation between the variables. Similarly, mean(A,2) is the mean of the variable in time, and var(A,2) is the variance. Other statistical functions and packages which work on AbstractArray types will work on the solution type.

Conversions

At anytime, a true Array can be created using Array(A), or more generally stack(A) to make the array type match the internal array type (for example, if A is an array of GPU arrays, stack(A) will be a GPU array).

source
RecursiveArrayTools.AbstractDiffEqArrayType
AbstractDiffEqArray{T, N, A} <: AbstractVectorOfArray{T, N, A}

An AbstractVectorOfArray object which has extra information of a time array A.t in order to specify a time series. A canonical AbstractDiffEqArray is for example the pairing DiffEqArray([[1,2],[3,4]],[1.0,2.0]) which means that at time 1.0 the values were [1,2] and at time 2.0 the values were [3,4].

An AbstractDiffEqArray has all of the same behaviors as an AbstractVectorOfArray with the additional properties:

Fields

An AbstractDiffEqArray adds the following fields:

  • t which holds the times of each timestep.
  • p which holds the parameter values.
  • sys which holds the symbolic system (e.g. SymbolCache).
  • discretes which holds discrete parameter timeseries.
  • interp which holds an interpolation object for dense output (default nothing).
  • dense which indicates whether dense interpolation is available (default false).

Callable Interface

When interp is not nothing, the array supports callable syntax for interpolation:

da(t)                           # interpolate at time t
da(t, Val{1})                   # first derivative at time t
da(t; idxs=1)                   # interpolate component 1
da(t; idxs=[1,2])              # interpolate components 1 and 2
da(t; continuity=:right)        # right-continuity at discontinuities

The interpolation object is called as interp(t, idxs, deriv, p, continuity).

source