# KdV Pseudospectral Methods Work-Precision Diagrams

##### HAO HAO
using ApproxFun, OrdinaryDiffEq, Sundials, BenchmarkTools, DiffEqOperators

ERROR: ArgumentError: Package DiffEqOperators not found in current path:
- Run import Pkg; Pkg.add("DiffEqOperators") to install the DiffEqOperators package.


using DiffEqDevTools
using LinearAlgebra
using Plots; gr()


Here is the Burgers equation using Fourier spectral methods.

S = Fourier()
n = 512
x = points(S, n)
D2 = Derivative(S,2)[1:n,1:n]
D  = (Derivative(S) → S)[1:n,1:n]
T = ApproxFun.plan_transform(S, n)
Ti = ApproxFun.plan_itransform(S, n)

D3  = (Derivative(S,3) → S)[1:n,1:n]
û₀ = T*cos.(x)
δ=0.022
tmp = similar(û₀)
p = (D,T,Ti,similar(tmp),tmp)
function kdv(dû,û,p,t)
D,T,Ti,u,tmp = p
mul!(u,D,û)
mul!(tmp,Ti,u)
mul!(u,Ti,û)
@. tmp=u*tmp
mul!(u,T,tmp)
@.dû = 6*u
end

kdv (generic function with 1 method)


Reference solution using RadauIIA5 is below:

prob = SplitODEProblem(DiffEqArrayOperator(-D3), kdv, û₀, (0.0,5.0), p)
test_sol = TestSolution(sol)

tslices=[0.0 1.0 2.0 3.0 5.0]
ys=hcat((Ti*sol(t) for t in tslices)...)
labels=["t=\$t" for t in tslices]
plot(x,ys,label=labels)


## In-family comparisons

1.IMEX methods (diagonal linear solver)

abstols = 0.1 .^ (5:8)
reltols = 0.1 .^ (1:4)
multipliers =  0.5 .^ (0:3)
setups = [Dict(:alg => IMEXEuler(linsolve=diag_linsolve), :dts => 1e-5 * multipliers),
Dict(:alg => CNAB2(linsolve=diag_linsolve), :dts => 5e-7 * multipliers),
Dict(:alg => CNLF2(linsolve=diag_linsolve), :dts => 5e-7 * multipliers),
Dict(:alg => SBDF2(linsolve=diag_linsolve), :dts => 1e-5 * multipliers)]

ERROR: UndefVarError: diag_linsolve not defined

labels = ["IMEXEuler" "CNAB2" "CNLF2" "SBDF2"]
@time wp1 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true,names=labels,
numruns=5,seconds=5,
save_everystop=false,appxsol=test_sol,maxiters=Int(1e5));

ERROR: UndefVarError: setups not defined

plot(wp1,label=labels,markershape=:auto,title="IMEX methods, diagonal linsolve, low order")

ERROR: UndefVarError: wp1 not defined

1. ExpRK methods

abstols = 0.1 .^ (5:8) # all fixed dt methods so these don't matter much
reltols = 0.1 .^ (1:4)
multipliers = 0.5 .^ (0:3)
setups = [Dict(:alg => NorsettEuler(), :dts => 1e-3 * multipliers),
Dict(:alg => ETDRK2(), :dts => 1e-2 * multipliers)]
labels = hcat("NorsettEuler",
"ETDRK2 (caching)")
@time wp2 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true, names=labels,
numruns=5,
save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));

NorsettEuler
ETDRK2 (caching)
787.130203 seconds (23.23 M allocations: 122.193 GiB, 9.11% gc time)

plot(wp2, label=labels, markershape=:auto, title="ExpRK methods, low order")


## Between family comparisons

abstols = 0.1 .^ (5:8) # all fixed dt methods so these don't matter much
reltols = 0.1 .^ (1:4)
multipliers = 0.5 .^ (0:3)
setups = [Dict(:alg => CNAB2(linsolve=diag_linsolve), :dts => 5e-5 * multipliers),
Dict(:alg => ETDRK2(), :dts => 1e-2 * multipliers)]

ERROR: UndefVarError: diag_linsolve not defined

labels = ["CNAB2 (diagonal linsolve)" "ETDRK2"]
@time wp3 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true, names=labels,
numruns=5, error_estimate=:l2,
save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));

CNAB2 (diagonal linsolve)
ETDRK2
772.699130 seconds (274.81 k allocations: 121.001 GiB, 9.01% gc time)

plot(wp3, label=labels, markershape=:auto, title="Between family, low orders")


## In-family comparisons

1.IMEX methods (band linear solver)

abstols = 0.1 .^ (7:13)
reltols = 0.1 .^ (4:10)
setups = [Dict(:alg => ARKODE(Sundials.Implicit(), order=3, linear_solver=:Band, jac_upper=1, jac_lower=1)),
Dict(:alg => ARKODE(Sundials.Implicit(), order=4, linear_solver=:Band, jac_upper=1, jac_lower=1)),
Dict(:alg => ARKODE(Sundials.Implicit(), order=5, linear_solver=:Band, jac_upper=1, jac_lower=1))]
labels = hcat("ARKODE3", "ARKODE4", "ARKODE5")
@time wp4 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true, names=labels,
numruns=5, error_estimate=:l2,
save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));

ARKODE3

ERROR: InterruptException:

plot(wp4, label=labels, markershape=:auto, title="IMEX methods, band linsolve, medium order")

ERROR: UndefVarError: wp4 not defined


2.ExpRK methods

abstols = 0.1 .^ (7:11) # all fixed dt methods so these don't matter much
reltols = 0.1 .^ (4:8)
multipliers = 0.5 .^ (0:4)
setups = [Dict(:alg => ETDRK3(), :dts => 1e-2 * multipliers),
Dict(:alg => ETDRK4(), :dts => 1e-2 * multipliers),
Dict(:alg => HochOst4(), :dts => 1e-2 * multipliers)]
labels = hcat("ETDRK3 (caching)", "ETDRK4 (caching)",
"HochOst4 (caching)")#,"ETDRK4 (m=5)" "ETDRK3 (m=5)" "HochOst4 (m=5)")
@time wp5 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true, names=labels,
numruns=5, error_estimate=:l2,
save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));

ETDRK3 (caching)

ERROR: InterruptException:

plot(wp5, label=labels, markershape=:auto, title="ExpRK methods, medium order")

ERROR: UndefVarError: wp5 not defined


## Between family comparisons

abstols = 0.1 .^ (7:11)
reltols = 0.1 .^ (4:8)
multipliers = 0.5 .^ (0:4)
setups = [Dict(:alg => ARKODE(Sundials.Implicit(), order=5, linear_solver=:Band, jac_upper=1, jac_lower=1)),
Dict(:alg => ETDRK3(), :dts => 1e-2 * multipliers),
Dict(:alg => ETDRK4(), :dts => 1e-2 * multipliers)]
labels = hcat("ARKODE (nondiagonal linsolve)", "ETDRK3 ()", "ETDRK4 ()")
@time wp6 = WorkPrecisionSet(prob,abstols,reltols,setups;
print_names=true, names=labels,
numruns=5, error_estimate=:l2,
save_everystep=false, appxsol=test_sol, maxiters=Int(1e5));

ARKODE (nondiagonal linsolve)

ERROR: InterruptException:

plot(wp6, label=labels, markershape=:auto, title="Between family, medium order")

ERROR: UndefVarError: wp6 not defined

using DiffEqBenchmarks
DiffEqBenchmarks.bench_footer(WEAVE_ARGS[:folder],WEAVE_ARGS[:file])


## Appendix

These benchmarks are a part of the DiffEqBenchmarks.jl repository, found at: https://github.com/JuliaDiffEq/DiffEqBenchmarks.jl

To locally run this tutorial, do the following commands:

using DiffEqBenchmarks
DiffEqBenchmarks.weave_file("MOLPDE","kdv_spectral_wpd.jmd")

Computer Information:

Julia Version 1.2.0
Commit c6da87ff4b (2019-08-20 00:03 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.1 (ORCJIT, haswell)
Environment:


Package Information:

Status: /home/crackauckas/.julia/dev/DiffEqBenchmarks/Project.toml
[28f2ccd6-bb30-5033-b560-165f7b14dc2f] ApproxFun 0.11.7
[a134a8b2-14d6-55f6-9291-3336d3ab0209] BlackBoxOptim 0.5.0
[eb300fae-53e8-50a0-950c-e21f52c2b7e0] DiffEqBiological 3.11.0
[f3b72e0c-5b89-59e1-b016-84e28bfd966d] DiffEqDevTools 2.15.0
[1130ab10-4a5a-5621-a13d-e4788d82bd4c] DiffEqParamEstim 1.8.0
[a077e3f3-b75c-5d7f-a0c6-6bc4c8ec64a9] DiffEqProblemLibrary 4.5.1
[ef61062a-5684-51dc-bb67-a0fcdec5c97d] DiffEqUncertainty 1.2.0
[7f56f5a3-f504-529b-bc02-0b1fe5e64312] LSODA 0.6.1
[76087f3c-5699-56af-9a33-bf431cd00edd] NLopt 0.5.1
[c030b06c-0b6d-57c2-b091-7029874bd033] ODE 2.5.0
[54ca160b-1b9f-5127-a996-1867f4bc2a2c] ODEInterface 0.4.6
[09606e27-ecf5-54fc-bb29-004bd9f985bf] ODEInterfaceDiffEq 3.4.0
[1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] OrdinaryDiffEq 5.17.2
[65888b18-ceab-5e60-b2b9-181511a3b968] ParameterizedFunctions 4.2.1
[91a5bcdd-55d7-5caf-9e0b-520d859cae80] Plots 0.26.3
[b4db0fb7-de2a-5028-82bf-5021f5cfa881] ReactionNetworkImporters 0.1.5
[f2c3362d-daeb-58d1-803e-2bc74f2840b4] RecursiveFactorization 0.1.0
[9a3f8284-a2c9-5f02-9a11-845980a1fd5c] Random