Dynamic Mode Decomposition

The (Exact) Dynamic Mode Decomposition is a method for generating an approximating linear differential equation directly from the observed data. If X and Y are data matrices containing points of the same trajectory, than DMD approximates

\[K = Y~X^{\dagger}\]

where $\dagger$ denotes the Moore-Penrose pseudoinverse and K is the approximation of the Koopman Operator.

DMD approximates discrete time systems of the form

\[u_{i+1} = K ~ u_{i}\]

gDMD approximates continuous time systems of the form

\[\frac{d}{dt}u = K_{G} ~ u\]

where $K_{G}$ is the generator of the Koopman Operator.

Functions

DataDrivenDiffEq.DMDFunction
DMD(X; alg)
DMD(X, Y; alg)

Approximates a 'LinearKoopman' with the AbstractKoopmanAlgorithm 'alg' from the data matrices X or X and Y, respectively. If only X is given, the data is split into X[:, 1:end-1] and X[:, 2:end].

Example

alg = DMDPINV()
koopman = DMD(X, alg = alg)

koopman = DMD(X[:, 1:end-1], X[:, 2:end], alg = alg)
source
DataDrivenDiffEq.gDMDFunction
gDMD(X, Y; alg)
gDMD(t, X ; dt, alg, fdm, itp)

Approximates a 'LinearKoopman' with the AbstractKoopmanAlgorithm 'alg' from the data matrices X and Y. X should contain the state trajectory and Y the differential state trajectory.

If no measurements of the differential state are available, gDMD can be called with measurement time points t as the first argument. It will then create an interpolation using the interpolation method from DataInterpolations.jl defined in itp. The trajectory will then be resampled to equidistant measurements over time corresponding to the mean of diff(t) or dt, if given. The differential state measurements will be computed via 'FiniteDifferences.jl', given a FiniteDifferenceMethod in fdm.

Example

koopman = gDMD(X, Y)

fdm = backward_fdm(5,1)
itp = CubicSpline
koopman = gDMD(t, X, fdm = fdm, itp = itp)
source

Examples

using DataDrivenDiffEq
using OrdinaryDiffEq
using LinearAlgebra
using Plots
gr()

function linear_discrete(du, u, p, t)
    du[1] = 0.9u[1]
    du[2] = 0.05u[2] + 0.1u[1]
end

u0 = [10.0; -2.0]
tspan = (0.0, 20.0)
problem = DiscreteProblem(linear_discrete, u0, tspan)
solution = solve(problem, FunctionMap())
retcode: Success
Interpolation: left-endpoint piecewise constant
t: 21-element Array{Float64,1}:
  0.0
  1.0
  2.0
  3.0
  4.0
  5.0
  6.0
  7.0
  8.0
  9.0
  ⋮
 12.0
 13.0
 14.0
 15.0
 16.0
 17.0
 18.0
 19.0
 20.0
u: 21-element Array{Array{Float64,1},1}:
 [10.0, -2.0]
 [9.0, 0.9]
 [8.1, 0.9450000000000001]
 [7.29, 0.8572500000000001]
 [6.561, 0.7718625000000001]
 [5.9049000000000005, 0.694693125]
 [5.3144100000000005, 0.6252246562500001]
 [4.7829690000000005, 0.5627022328125001]
 [4.3046721, 0.5064320116406251]
 [3.8742048900000006, 0.4557888105820313]
 ⋮
 [2.82429536481, 0.33227004291882284]
 [2.541865828329, 0.2990430386269412]
 [2.2876792454961, 0.2691387347642471]
 [2.05891132094649, 0.2422248612878224]
 [1.853020188851841, 0.21800237515904014]
 [1.6677181699666568, 0.1962021376431361]
 [1.5009463529699911, 0.1765819238788225]
 [1.350851717672992, 0.15892373149094025]
 [1.2157665459056928, 0.14303135834184622]
X = Array(solution)

approx = DMD(X[:,1:3])

prob_approx = DiscreteProblem(approx, u0, tspan)
approx_sol = solve(prob_approx, FunctionMap())

function linear_discrete_2(du, u, p, t)
    du[1] = 0.9u[1] + 0.05u[2]
    du[2] = 0.1u[1]
end

problem = DiscreteProblem(linear_discrete_2, u0, tspan)
solution = solve(problem, FunctionMap())

X = Array(solution)

update!(approx, X[:, 4:end-1], X[:, 5:end])

prob_approx = DiscreteProblem(approx, u0, tspan)
approx_sol = solve(prob_approx, FunctionMap())

# Show solutions