Skip to content

Commit 822ae90

Browse files
catch bad initdt
1 parent 114f8c2 commit 822ae90

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

src/initdt.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,38 @@
1010
f₀ = zeros(u0./t)
1111
f(t,u0,f₀)
1212

13+
14+
#=
15+
Try/catch around the linear solving. This will catch singular matrices defined
16+
by DAEs and thus we use the tType(1//10^(6)) default from Hairer. Note that
17+
this will not always catch singular matrices, an example from Andreas:
18+
19+
julia> A = fill(rand(), 2, 2)
20+
2×2 Array{Float64,2}:
21+
0.637947 0.637947
22+
0.637947 0.637947
23+
24+
julia> inv(A)
25+
2×2 Array{Float64,2}:
26+
9.0072e15 -9.0072e15
27+
-9.0072e15 9.0072e15
28+
29+
The only way to make this more correct is to check
30+
31+
issingular(A) = rank(A) < min(size(A)...)
32+
33+
but that would introduce another svdfact in rank (which may not be possible
34+
anyways if the mass_matrix is not actually an array). Instead we stick to the
35+
user-chosen factorization. Sometimes this will cause `ftmp` to be absurdly
36+
large like shown there, but that later gets caught in the quick estimates
37+
below which then makes it spit out the default
38+
39+
dt₀ = tType(1//10^(6))
40+
41+
so that is a a cheaper way to get to the same place than an svdfact and
42+
still works for matrix-free definitions of the mass matrix.
43+
=#
44+
1345
if prob.mass_matrix != I
1446
ftmp = similar(f₀)
1547
try
@@ -33,6 +65,13 @@
3365
dt₀ = tType((d₀/d₁)/100)
3466
end
3567
dt₀ = min(dt₀,dtmax_tdir)
68+
69+
if tType <: AbstractFloat && dt₀ < 10eps(tType)
70+
# This catches Andreas' non-singular example
71+
# should act like it's singular
72+
return tType(1//10^(6))
73+
end
74+
3675
dt₀_tdir = tdir*dt₀
3776

3877
u₁ = similar(u0) # required by DEDataArray

test/mass_matrix_tests.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,35 @@ sol = solve(prob, TRBDF2(),adaptive=false,dt=1/10)
8989
sol2 = solve(prob2, TRBDF2(),adaptive=false,dt=1/10)
9090
9191
=#
92+
93+
# Singular mass matrices
94+
95+
function f!(t, u, du)
96+
du[1] = u[2]
97+
du[2] = u[2] - 1.
98+
return
99+
end
100+
101+
u0 = [0.,1.]
102+
tspan = (0.0, 1.0)
103+
104+
M = zeros(2,2)
105+
M[1,1] = 1.
106+
107+
m_ode_prob = ODEProblem(f!, u0, tspan, mass_matrix=M)
108+
sol = solve(m_ode_prob, Rosenbrock23())
109+
110+
M = [0.637947 0.637947
111+
0.637947 0.637947]
112+
113+
inv(M) # not caught as singular
114+
115+
function f2!(t, u, du)
116+
du[1] = u[2]
117+
du[2] = u[1]
118+
return
119+
end
120+
u0 = zeros(2)
121+
122+
m_ode_prob = ODEProblem(f2!, u0, tspan, mass_matrix=M)
123+
sol = solve(m_ode_prob, Rosenbrock23())

0 commit comments

Comments
 (0)