Visualization
Recipes
NonlinearSchrodinger.jl
provides recipes for Plots.jl
to make plotting easy. You can simply call any plotting function on a ::Sim
or ::Calc
object, as shown in the examples pages.
Visualizing Algorithms
We can visualize the time-stepping of the algorithms graphically as follows. We first have to figure out the coefficients of the integrators, which is straightforward from the literature (see the paper) or the code
function coeff_dict()
d = Dict()
####################################
s = 3
p = 2
γ = zeros(1,s)
γ[1] = 1/(2-2^(1/(p+1)))
γ[2] = -γ[1]*2^(1/(p+1))
γ[3] = γ[1]
push!(d, :T4_TJ=> γ)
####################################
sp = 3
s = sp^2
p = 4
γ = zeros(1,s)
γp = zeros(1,sp)
γp[1] = 1/(2-2^(1/(p-1)))
γp[2] = -γp[1]*2^(1/(p-1))
γp[3] = γp[1]
γ[1:3] = 1/(2-2^(1/(p+1)))*γp[1:3]
γ[4:6] = -2^(1/(p+1))*γ[1:3]
γ[7:9] = γ[1:3]
push!(d, :T6_TJ=> γ)
####################################
spp = 3
sp = spp^2
s = spp^3
p = 8
γ = zeros(1,s)
γp = zeros(1,sp)
γpp = zeros(1,spp)
γpp[1] = 1/(2-2^(1/(p-3)))
γpp[2] = -γpp[1]*2^(1/(p-3))
γpp[3] = γpp[1]
γp[1:3] = 1/(2-2^(1/(p-1))).*γpp[1:3]
γp[4:6] = -2^(1/(p-1))*γp[1:3]
γp[7:9] = γp[1:3]
γ[1:9] = 1/(2-2^(1/(p+1)))*γp[1:9]
γ[10:18] = -2^(1/(p+1))*γ[1:9]
γ[19:27] = γ[1:9]
push!(d, :T8_TJ=> γ)
####################################
s = 5
p = 2
γ = zeros(1,s)
γ[1] = 1/(4-4^(1/(p+1)))
γ[2] = γ[1]
γ[3] = -γ[1]*4^(1/(p+1))
γ[4] = γ[1]
γ[5] = γ[1]
push!(d, :T4_SF=> γ)
####################################
sp = 5
s = sp^2
p = 4
γ = zeros(1,s)
γp = zeros(1, sp)
γp[1] = 1/(4-4^(1/(p-1)))
γp[2] = γp[1]
γp[3] = -γp[1]*4^(1/(p-1))
γp[4] = γp[1]
γp[5] = γp[1]
γ[1:5] = 1/(4-4^(1/(p+1)))*γp[1:5]
γ[6:10] = γ[1:5]
γ[11:15] = -4^(1/(p+1))*γ[1:5]
γ[16:20] = γ[1:5]
γ[21:25] = γ[1:5]
push!(d, :T6_SF=> γ)
####################################
spp = 5
sp = spp^2
s = spp^3
p = 6
γ = zeros(1,s)
γp = zeros(1, sp)
γpp = zeros(1, spp)
γpp[1] = 1/(4-4^(1/(p-3)))
γpp[2] = γpp[1]
γpp[3] = -γpp[1]*4^(1/(p-3))
γpp[4] = γpp[1]
γpp[5] = γpp[1]
γp[1:5] = 1/(4-4^(1/(p-1)))*γpp[1:5]
γp[6:10] = γp[1:5]
γp[11:15] = -4^(1/(p-1))*γp[1:5]
γp[16:20] = γp[1:5]
γp[21:25] = γp[1:5]
γ[1:25] = 1/(4-4^(1/(p+1)))*γp[1:25]
γ[26:50] = γ[1:25]
γ[51:75] = -4^(1/(p+1))/(4-4^(1/(p+1)))*γp[1:25]
γ[76:100] = γ[1:25]
γ[101:125] = γ[1:25]
push!(d, :T8_SF=> γ)
####################################
s = 7
γ = zeros(1,s)
γ[1] = 0.78451361047755726381949763
γ[2] = 0.23557321335935813368479318
γ[3] =-1.17767998417887100694641568
γ[4] = 1.31518632068391121888424973
γ[7] = γ[1]
γ[6] = γ[2]
γ[5] = γ[3]
push!(d, :T6_Ys7 => γ)
###################################
s = 9
γ = zeros(1, s)
γ[1] = 0.39216144400731413927925056
γ[2] = 0.33259913678935943859974864
γ[3] = -0.70624617255763935980996482
γ[4] = 0.08221359629355080023149045
γ[5] = 0.79854399093482996339895035
γ[9] = γ[1]
γ[8] = γ[2]
γ[7] = γ[3]
γ[6] = γ[4]
push!(d, :T6_KLs9 => γ)
##################################
s = 14
γ = zeros(1,s)
γ[1] = 0.392256805238773
γ[2] = γ[1]
γ[13] = γ[1]
γ[14] = γ[1]
γ[3] = 0.1177866066796810
γ[4] = γ[3]
γ[11] = γ[3]
γ[12] = γ[3]
γ[5] = -0.5888399920894384
γ[6] = γ[5]
γ[9] = γ[5]
γ[10] = γ[5]
γ[7] = 0.6575931603419684
γ[8] = γ[7]
push!(d, :T6_Ss14 => γ)
##################################
s = 15
γ = zeros(1,s)
γ[1] = 0.7416703643506129534482278
γ[2] = -0.409100825800031593997300
γ[3] = 0.1907547102962383799538763
γ[4] = -0.5738624711160822666563877
γ[5] = 0.2990641813036559238444635
γ[6] = 0.3346249182452981837849580
γ[7] = 0.3152930923967665966320567
γ[8] = -0.7968879393529163540197888
γ[9] = γ[7]
γ[10] = γ[6]
γ[11] = γ[5]
γ[12] = γ[4]
γ[13] = γ[3]
γ[14] = γ[2]
γ[15] = γ[1]
push!(d, :T8_Ss15 => γ)
##################################
s = 17
γ = zeros(1,s)
γ[1] = 0.13020248308889008087881763
γ[2] = 0.56116298177510838456196441
γ[3] = -0.38947496264484728640807860
γ[4] = 0.15884190655515560089621075
γ[5] = -0.39590389413323757733623154
γ[6] = 0.18453964097831570709183254
γ[7] = 0.25837438768632204729397911
γ[8] = 0.29501172360931029887096624
γ[9] = -0.60550853383003451169892108
γ[17] = γ[1]
γ[16] = γ[2]
γ[15] = γ[3]
γ[14] = γ[4]
γ[13] = γ[5]
γ[12] = γ[6]
γ[11] = γ[7]
γ[10] = γ[8]
push!(d, :T8_KLs17 => γ)
##################################
return d
end
coeff_dict (generic function with 1 method)
Then we plot them
using Plots
using LaTeXStrings
function plot_algo(algo)
d = coeff_dict()
γ = d[algo]
s = length(γ)
y = range(0, stop=1, length=s+1)
x = zeros(1, s+1)
x[2:end] = [sum(γ[1:i]) for i in 1:s]
if algo === :T8_SF
ms = 0.7
else
ms = 3
end
plot(x', y, marker=:circ, linewidth=1.5, markersize=ms, dpi=120, label="", markercolor=:red)
plot!([0], seriestype=:vline, linestyle=:dash, label="", linewidth=0.5, linecolor=:black)
plot!([1], seriestype=:vline, linestyle=:dash, label="", linewidth=0.5, linecolor=:black)
title!(string(algo))
plot!(grid=false, xtick=([0, 1], [L"0", L"dx"]), ytick=[], yaxis=false, fontfamily="Computer Modern", titlefontsize=12, tickdir=:out)
end
p1 = plot_algo(:T4_TJ)
p2 = plot_algo(:T6_TJ)
p3 = plot_algo(:T8_TJ)
p4 = plot_algo(:T4_SF)
p5 = plot_algo(:T6_SF)
p6 = plot_algo(:T8_SF)
p7 = plot_algo(:T6_Ys7)
p8 = plot_algo(:T6_KLs9)
p9 = plot_algo(:T6_Ss14)
p10 = plot_algo(:T8_Ss15)
p11 = plot_algo(:T8_KLs17)
p1 = plot(p1, p2, p3, p4, p5, p6, link=:x)
p2 = plot(p7, p10, p8, p11, link=:x)
/home/runner/.julia/packages/GR/G9I5v/src/../deps/gr/bin/gksqt: error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory connect: Connection refused GKS: can't connect to GKS socket application GKS: Open failed in routine OPEN_WS GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS /home/runner/.julia/packages/GR/G9I5v/src/../deps/gr/bin/gksqt: error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory connect: Connection refused GKS: can't connect to GKS socket application GKS: Open failed in routine OPEN_WS GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS
Visualizing Recursion
We can visualize the DT recursion as follows. We acknowledge the major assistance provided by Simon Schoelly (@simonschoelly) in writing this code.
using LightGraphs, MetaGraphs, Plots, GraphRecipes, LaTeXStrings
default(size=(1000,1000))
function gen_rec_graph(N, pal)
function DT_recurse(n, p, g, N, pal)
if !haskey(g[:name], (n, p)) # if there is not already a node with name (n, p)
# add a new vertex and set it's name to (n, p)
# the most recent added vertex always has the index nv(g)
add_vertex!(g)
set_prop!(g, nv(g), :name, (n, p))
set_prop!(g, nv(g), :size, N)
set_prop!(g, nv(g), :col, pal[N])
end
if n != 1
# recurse as usual
DT_recurse(n-1, 1, g, N-1, pal)
DT_recurse(n-1, p+1, g, N-1, pal)
# at this point, the vertices with the names (n, p), (n-1, 1) and (n-1, p+1) already exist
# so we look them up by their name
v1 = g[(n, p), :name]
v2 = g[(n-1, 1), :name]
v3 = g[(n-1, p+1), :name]
# add edges (n, p) -> (n-1, 1) and (n, p) -> (n-1, p+1)
add_edge!(g, v1, v2)
add_edge!(g, v1, v3)
end
return nothing
end
g = MetaDiGraph() # empty graph
set_indexing_prop!(g, :name) # allows one to look up nodes by the attribute :name
DT_recurse(N, 1, g, N, pal)
return g
end
N = 4
pal = palette(:heat, Int(floor(1.5*N)))
g = gen_rec_graph(N, pal)
using Random
Random.seed!(320) # this guarantrees fixed placement of the nodes in the plot, not mandatory
p = graphplot(g, names = [latexstring(get_prop(g, v, :name)) for v in vertices(g)],
arrow=:arrow,
nodeshape=:circle,
curvature_scalar=0.0,
nodeweights=[get_prop(g, v, :size) for v in vertices(g)],
markercolor=[get_prop(g, v, :col) for v in vertices(g)],
fontsize=14,
markersize=0.04,
linewidth=2,
method=:tree,
curves=false)
/home/runner/.julia/packages/GR/G9I5v/src/../deps/gr/bin/gksqt: error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory connect: Connection refused GKS: can't connect to GKS socket application GKS: Open failed in routine OPEN_WS GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS