Custom Noise Process for DifferentialEquations.jl

I’m trying to define my own noise process for usage with the SDEProblem function.
Mathematically its defined like this: take a Brownian motion on [0,1]. Stick the path on [0,1] at its own tail (continuously) to get a process on [0,2]. Keep repeating this to get a process on [0, epochs], where epochs is an integer.

One way to generate a path of this process is to choose a grid size dt and then generate (and save) the increments for the first epoch ([0,1]) and reuse them.

I can define this using NoiseGrid in dimension 1, like this:

epochs = 2^4
dt = 1/2^7

increments = [sqrt(dt) * randn() for i in 1:Int(1/dt)]
ssbm_values = cumsum([0; repeat(increments, epochs)])
X = NoiseGrid(0:dt:epochs, ssbm_values)

I can plot the path like this:

b(u, p, t) = 0
σ(u, p, t) = 1
prob = SDEProblem(b, σ, 0, (0.0, epochs), noise = X)
sol = solve(prob, EM(), dt = dt)
plot(sol)

Now I want to do it in higher dimensions. After some tinkering the following code runs:

epochs = 2^4
dt = 1/2^10

increments = sqrt(dt) * randn(d, Int(1/dt))
ssbm_values = cumsum(hcat(zeros(d), transpose(repeat(transpose(increments), epochs))), dims = 2)
X = NoiseGrid(0:dt:epochs, [ssbm_values[i,:] for i in 1:size(ssbm_values,1)])

However, the following throws a “BoundsError” only when using X as the noise in SDEProblem:

function b(du, u, p, t)
    du = zeros(2)
end

function σ(du, u, p, t)
    du[1] = 1.0
    du[2] = 1.0
end

prob = SDEProblem(b, σ, zeros(2), (0.0, epochs), noise = X)
sol = solve(prob, EM(), dt = 1/2^10)

How do I need to define X to make this work?

(Note that there is potentially a more elegant solution which I have no clue how to make work either: draw a standard Gaussian N, take an independent Brownian Bridge B from 0 to 0. Then define X_t = B_{\{t\}} + t N.)

If it’s a scalar noise process then it should be an array of scalars. Otherwise you have a diagonal noise definition so you need an array of length two vectors.

Ahhh, thank you for the tip. I didn’t even question that line because it ran without errors. But the increments/dimensions were arranged the wrong way. The correct line is actually:

X = NoiseGrid(0:dt:epochs, [ssbm_values[:,i] for i in 1:size(ssbm_values)[2]])

and then everything works :slight_smile: