Skip to content

Commit bb403dd

Browse files
committed
detect fewer brownians than equations, but noise still diag
1 parent 0726a4d commit bb403dd

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

src/systems/diffeqs/sdesystem.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,11 @@ function Base.:(==)(sys1::SDESystem, sys2::SDESystem)
245245
all(s1 == s2 for (s1, s2) in zip(get_systems(sys1), get_systems(sys2)))
246246
end
247247

248-
function __num_isdiag(mat)
249-
for i in axes(mat, 1), j in axes(mat, 2)
250-
i == j || isequal(mat[i, j], 0) || return false
251-
end
252-
return true
248+
function __num_isdiag_noise(mat)
249+
all(col -> count(!iszero, col) <= 1, eachcol(mat))
250+
end
251+
function __get_num_diag_noise(mat)
252+
vec(sum(mat; dims = 2))
253253
end
254254

255255
function generate_diffusion_function(sys::SDESystem, dvs = unknowns(sys),
@@ -258,7 +258,7 @@ function generate_diffusion_function(sys::SDESystem, dvs = unknowns(sys),
258258
if isdde
259259
eqs = delay_to_function(sys, eqs)
260260
end
261-
if eqs isa AbstractMatrix && __num_isdiag(eqs)
261+
if eqs isa AbstractMatrix && __num_isdiag_noise(eqs)
262262
eqs = diag(eqs)
263263
end
264264
u = map(x -> time_varying_as_func(value(x), sys), dvs)

src/systems/systems.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,11 @@ function __structural_simplify(sys::AbstractSystem, io = nothing; simplify = fal
133133
# we get a Nx1 matrix of noise equations, which is a special case known as scalar noise
134134
noise_eqs = sorted_g_rows[:, 1]
135135
is_scalar_noise = true
136-
elseif isdiag(sorted_g_rows)
137-
# If the noise matrix is diagonal, then the solver just takes a vector column of equations
138-
# and it interprets that as diagonal noise.
139-
noise_eqs = diag(sorted_g_rows)
136+
elseif __num_isdiag_noise(sorted_g_rows)
137+
# If each column of the noise matrix has either 0 or 1 non-zero entry, then this is "diagonal noise".
138+
# In this case, the solver just takes a vector column of equations and it interprets that to
139+
# mean that each noise process is independant
140+
noise_eqs = __get_num_diag_noise(sorted_g_rows)
140141
is_scalar_noise = false
141142
else
142143
noise_eqs = sorted_g_rows

test/sdesystem.jl

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,12 +725,12 @@ end
725725

726726
@testset "Non-diagonal noise check" begin
727727
@parameters σ ρ β
728-
@variables x(t) y(t) z(t)
728+
@variables x(tt) y(tt) z(tt)
729729
@brownian a b c
730730
eqs = [D(x) ~ σ * (y - x) + 0.1a * x + 0.1b * y,
731731
D(y) ~ x *- z) - y + 0.1b * y,
732732
D(z) ~ x * y - β * z + 0.1c * z]
733-
@mtkbuild de = System(eqs, t)
733+
@mtkbuild de = System(eqs, tt)
734734

735735
u0map = [
736736
x => 1.0,
@@ -746,5 +746,32 @@ end
746746

747747
prob = SDEProblem(de, u0map, (0.0, 100.0), parammap)
748748
# SOSRI only works for diagonal and scalar noise
749+
@test_throws ErrorException solve(prob, SOSRI()).retcode==ReturnCode.Success
750+
# ImplictEM does work for non-diagonal noise
749751
@test solve(prob, ImplicitEM()).retcode == ReturnCode.Success
750752
end
753+
754+
@testset "Diagonal noise, less brownians than equations" begin
755+
@parameters σ ρ β
756+
@variables x(tt) y(tt) z(tt)
757+
@brownian a b
758+
eqs = [D(x) ~ σ * (y - x) + 0.1a * x, # One brownian
759+
D(y) ~ x *- z) - y + 0.1b * y, # Another brownian
760+
D(z) ~ x * y - β * z] # no brownians -- still diagonal
761+
@mtkbuild de = System(eqs, tt)
762+
763+
u0map = [
764+
x => 1.0,
765+
y => 0.0,
766+
z => 0.0
767+
]
768+
769+
parammap = [
770+
σ => 10.0,
771+
β => 26.0,
772+
ρ => 2.33
773+
]
774+
775+
prob = SDEProblem(de, u0map, (0.0, 100.0), parammap)
776+
@test solve(prob, SOSRI()).retcode == ReturnCode.Success
777+
end

0 commit comments

Comments
 (0)