Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1029f09
Add radau solver
YingboMa Jul 5, 2016
adb4857
Small changes
YingboMa Jul 5, 2016
08fdd57
optional order
obiajulu Jul 5, 2016
9627da7
updated done()
obiajulu Jul 5, 2016
8db6176
change unwrap to unpack
obiajulu Jul 5, 2016
ace77bf
added setting up state and trialstep function
obiajulu Jul 5, 2016
68567c7
added types to radau state
obiajulu Jul 5, 2016
05b0e33
outline comments for trialstep
obiajulu Jul 5, 2016
60b5df6
add basic errorcontrol! function
YingboMa Jul 5, 2016
23a3d09
fix conflict
obiajulu Jul 6, 2016
4ca32e3
Fix the conflicts
YingboMa Jul 6, 2016
7ab6965
return structure for errorcontrol
obiajulu Jul 6, 2016
5882320
added framework for tableau
obiajulu Jul 6, 2016
8ac9f13
Add ordercontrol
YingboMa Jul 6, 2016
a8e155e
more modifications to tableau
obiajulu Jul 6, 2016
3283b8e
more organization in structure
obiajulu Jul 6, 2016
fc04524
Add using Polynomials
YingboMa Jul 6, 2016
a76a14f
Add b in raduaTable
YingboMa Jul 6, 2016
361831e
removed conflict
obiajulu Jul 6, 2016
41f4f5f
Add prototype of constRadauTableau function
YingboMa Jul 6, 2016
333d62a
Fix bugs and optimize constRadauTableau function
YingboMa Jul 7, 2016
db9a8f3
further progress in trialstep
obiajulu Jul 7, 2016
4b5f62d
Add some documents
YingboMa Jul 8, 2016
9fdeed5
Improve constRadauTableau() function and add bt_radau5 table
YingboMa Jul 8, 2016
a846d88
Netwon iteration framework working
obiajulu Jul 8, 2016
0a39b32
radau state working, tableau as well. Also done() and constRadauTable…
obiajulu Jul 8, 2016
b8a898c
a working, though incorrect, Netwon iteration
obiajulu Jul 8, 2016
8b503c8
Add .gitignore and avoid deprecated warnings
YingboMa Jul 25, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### Julia ###
*.jl.cov
*.jl.*.cov
*.jl.mem
*.ipynb_checkpoints
deps/deps.jl
378 changes: 378 additions & 0 deletions src/radau.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
#=
✓(1) done()
(2) trialstep!()
(3) errorcontol!()
(4) odercontrol!()
(5) rollback!()
(6) status()
=#

###########################################
# Tableaus for implicit Runge-Kutta methods
###########################################
using Polynomials
using ForwardDiff
using ODE
using Parameters
using Compat


immutable TableauRKImplicit{Name, S, T} <: ODE.Tableau{Name, S, T}
order::Integer # the order of the method
a::Matrix{T}
# one or several row vectors. First row is used for the step,
# second for error calc.
b::Matrix{T}
c::Vector{T}
function TableauRKImplicit(order,a,b,c)
@assert isa(S,Integer)
@assert isa(Name,Symbol)
@assert S==length(c)==length(b)
@assert length(b)==(order+1)/2
@assert norm(sum(a,2)-c'',Inf)<1e-10 # consistency.
new(order,a,b,c)
end
end

function TableauRKImplicit{T}(name::Symbol, order::Integer,
a::Matrix{T}, b::Matrix{T}, c::Vector{T})
TableauRKImplicit{name,length(c),T}(order, a, b, c)
end
function TableauRKImplicit(name::Symbol, order::Integer, T::Type,
a::Matrix, b::Matrix, c::Vector)
TableauRKImplicit{name,length(c),T}(order, convert(Matrix{T},a),
convert(Matrix{T},b), convert(Vector{T},c) )
end

## Tableaus for implicit RK methods
const bt_radau3 = TableauRKImplicit(:radau3,3, Float64,
[5//12 -1//12
3//4 1//4],
[3//4, 1//4]',
[1//3, 1])

const bt_radau5 = TableauRKImplicit(:radau5,5, Float64,
[11/45-7*√(6)/360 37/225-169*√(6)/1800 -2/225 + √(6)/75
37/225+169*√(6)/1800 11/45+7*√(6)/360 -2/225 - √(6)/75
4/9-√(6)/36 4/9+√(6)/36 1/9 ],
[4/9-√(6)/36 4/9+√(6)/36 1/9 ]',
[2/5-√(6)/10, 2/5+√(6)/10, 1 ])


###########################################
# State for Radau Solver
###########################################
type RadauState{T,Y}
f:: Function
tfinal ::T
tdir :: Integer
minstep ::Float64

h::T # (proposed) next time step

t::T # current time
y::Y # current solution
dy::Y # current derivative

tpre::T # time t-1
ypre::Y # solution at t-1
dypre::Y # derivative at t-1

step::Int # current step number
finished::Bool # true if last step was taken

btab #<:TableauRKImplicit # tableau according to stage number
stageNum ::Integer
M ::Array{Float64,2}
reltol::Float64
abstol::Float64

# work arrays
end

###########################################
# Radau Solver
###########################################
function ode_radau(f, y0, tspan, order ::Integer = 5; M = eye(length(y0),length(y0)),
minstep = abs(tspan[length(tspan)]-tspan[1])/10^12,
reltol = 1.0e-5,
abstol = 1.0e-8,
)
# Set up
stageNum = Integer((order+1)/2)
T = eltype(tspan)
Y = typeof(y0)
EY = eltype(Y)
dof = length(y0)

# TODO: h = hinit()
tfinal = tspan[length(tspan)]
tdir = sign(tfinal - tspan[1])
h = .01
t = tspan[1]
y = deepcopy(y0)
dy = f(t, y)

## previous data set to null to begin
tpre = tspan[1]
ypre = deepcopy(y0)
dypre = f(t, y)

step = 1
finished = false

# get right tableau for stage number
if order ==3
btab = bt_radau3
elseif order ==5
btab = bt_radau5
else
btab = constRadauTableau(stageNum)
end

## intialize state
st = RadauState{T,Y}(f, tfinal,tdir, minstep,h,
t, y, dy,
tpre, ypre, dypre,
step, finished,
btab, stageNum, M,
reltol, abstol)

# Time stepping loop
while !done_radau(st)
@show st.step
stats = trialstep!(st)
#=err, stats, st = errorcontrol!(st) # (1) adaptive stepsize (2) error
if err < 1
stats, st = ordercontrol!()
accept = true
else
rollback!()
end

return status()=#
end
end


function f(t, y)
# Extract the components of the y vector
(x, v) = y

# Our system of differential equations
x_prime = v
v_prime = -x

# Return the derivatives as a vector
[x_prime; v_prime]
end


# Initial condtions -- x(0) and x'(0)
y = [0.0; 0.1]

# Time vector going from 0 to 2*PI in 0.01 increments
t = 0:0.1:4*pi;

ode_radau(f,y,t,5)
###########################################
# iterator like helper functions
###########################################
"done function for when to stop radau time stepping loop"
function done_radau(st)
@unpack st: h, t, tfinal, minstep, tdir
if h < minstep || tdir*t >= tdir*tfinal
return true
else
return false
end
end

"trial step for ODE with mass matrix with Radau IIA solver"
function trialstep!(st)
@unpack st: h, t,y,dy, tfinal, btab, f, stageNum,M,reltol,abstol, ypre
dof = length(y)
# Form ⃗z from y
z = zeros(stageNum) #TODO: use better initial values for z
zpre = zeros(stageNum)
Δzpre = zeros(stageNum)
Δz = zeros(stageNum)
κ = .01 # See Harier Vol II pg 121

# Calculate Jacobian at (t_n, y_n)
g(y_val) = f(t,y_val)
J = ForwardDiff.jacobian(g, y)

# Use to form simplied Netwon iteration matrix
# _ _
# |M - h*a[11]*h*f(tn,yn) ... -h*a[1s]*f(tn,yn) |
# G= | ⋮ ⋱ ⋮ |
# | - h*a[1s]*h*f(tn,yn) ... M-h*a[ss]*f(tn,yn) |
# |_ _|
#
I_N = eye(dof,dof)
I_s = eye(stageNum,stageNum)
AoplusJ = kron(btab.a,J)
IoplusM = kron(I_s,M)
G = IoplusM-h*AoplusJ

# Use Netwon interation (TODO: use the transformation T^(-1)A^(-1)T = Λ,
# W^k = (T^-1 ⊕ I)Z^k version of iteration)

## Matrices used for one round of iteration
Ginv = inv(G)
Ginv_block = Array{Float64,2}[Ginv[i*dof + [1:dof;], j*dof+[1:dof;]] for i = 0:stageNum-1, j= 0:stageNum-1]
AoplusI_block = Array{Float64,2}[btab.a[i,j]*I_N for i=1:stageNum, j=1:stageNum]

iterate = true
count = 0
while iterate && count<=7
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make into a separate function

Δz = Ginv_block*(-zpre + h*AoplusI_block*F(f,z,y,t,btab.c,h))
z = zpre + Δz # ⃗z^(k+1) = ⃗z ^ (k) - Δ⃗z^(k)

# Stop condition for the Netwon iteration
if (count >=2)
Θ = norm(Δz)/norm(Δzpre)
η = Θ/(1-Θ)
if η*norm(Δz) <= κ*min(reltol,abstol)
iterate = false
break
end
end

zpre = z
Δzpre = Δz

@show count+=1
end

# Once Netwon method converges after some m steps, estimated next step size
#
# y = ypre + h ∑b_i*k_i^{m}
#
d = inv(btab.a)*btab.b
ynext = ypre
for i = 1 : stageNum
ynext += z[i]*d[i]
end

#update state
st.ypre = y
st.dypre = dy
st.tpre = t

st.y = ynext
st.t = t+h
st.dy = f(t+h,ynext)

st.step = st.step+1
return (count)
end

function errorcontrol!(st)
@unpack st:M, h, A, J, tpre, ypre, b̂, b, c, g, order_number, fac
γ0 = filter(λ -> imag(λ)==0, eig(inv(A)))

for i = 1:order_number
sum_part += (b̂[i] - b[i]) * h *f(xpre + c[i] * h, g[i])
end

yhat_y = γ0 * h * f(tpre, ypre) + sum_part
err = norm( inv(M - h * λ * J) * (yhat_y) )

hnew = fac * h * err_norm^(-1/4)

# Update state
st.hnew = hnew

return err, Nothing, st
end

function ordercontrol!(st)
@unpack st:W, step, order

if step < 10
# update state
st.order = 5

else
θk = norm(W[ ]) / norm(W[ ])
θk_1 = norm(W[ ]) / norm(W[ ])

Φ_k = √(θk * θk_1)
end

end
###########################################
# Other help functions
###########################################
function constRadauTableau(stageNum)
# Calculate c_i, which are the zeros of
# s-1
# d s-1 s
# --- (x * (x-1) )
# s-1
# dx
roots = zeros(Float64, stageNum - 1)
append!(roots, [1 for i= 1:stageNum])
poly = Polynomials.poly([roots;])
for i = 1 : stageNum-1
poly = Polynomials.polyder(poly)
end
C = Polynomials.roots(poly)
Copy link
Copy Markdown
Collaborator

@YingboMa YingboMa Jul 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Polynomials package has been 3 years didn't update, and Polynomials package has serious performance and the returning type issues. Maybe need to rewrite this part.


################# Calculate b_i #################
# s
# ___
# \ 1
# / bᵢcᵢ^(m - 1) = --- m = 1, ..., s
# --- m ,
# i=1
#
# Construct a matrix C_meta to calculate B
C_meta = Array(Float64, stageNum, stageNum)
for i = 1:stageNum
C_meta[i, :] = C .^ (i - 1)
end

# Construct a matrix 1 / stageNum
B_meta = Array(Float64, stageNum, 1)
for i = 1:stageNum
B_meta[i, 1] = 1 / i
end

# Calculate b_i
C_big = inv( C_meta )
B = C_big * B_meta
################# Calculate a_ij ################
# s
# ___
# \ cᵢ^m
# / aₐⱼcᵢ^(m - 1) = ------- m = 1, ..., s
# --- m , j = 1, ..., s
# j=1
#
# Construct matrix A
A = Array(Float64, stageNum, stageNum)

# Construct matrix A_meta
A_meta = Array(Float64, stageNum, stageNum)
for i = 1:stageNum
for j = 1:stageNum
A_meta[i,j] = B_meta[i] * C[j]^i
end
end

# Calculate a_ij
for i = 1:stageNum
A[i,:] = C_big * A_meta[:,i]
end
order = 2*stageNum-1
return TableauRKImplicit(symbol("radau$(order)"),order, A, B, C)
end


" Calculates the array of derivative values between t and tnext"
function F(f,z,y,t,c,h)
return Array{Float64,1}[f(t+c[i]*h, y+z[i]) for i=1:length(z)]
end