From 90e5facccd47c154c8561bee24629b1c1f43b20e Mon Sep 17 00:00:00 2001 From: leios Date: Sun, 6 May 2018 08:53:36 +0900 Subject: [PATCH 1/7] adding smallscale changes. --- chapters/physics_solvers/quantum/split-op/split-op.md | 11 ++++++++++- update_site.sh | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/chapters/physics_solvers/quantum/split-op/split-op.md b/chapters/physics_solvers/quantum/split-op/split-op.md index e3c1a8e3c..a3031513d 100644 --- a/chapters/physics_solvers/quantum/split-op/split-op.md +++ b/chapters/physics_solvers/quantum/split-op/split-op.md @@ -19,7 +19,16 @@ At it's heart, the split-op method is nothing more than a pseudo-spectral differ In fact, there is a large class of spectral and pseudo-spectral methods used to solve a number of different physical systems, and we'll definitely be covering those in the future. For now, let's answer the obvious question, "How on Earth can FFT's be used to solve quantum systems?" -That is precisely the question we will answer here! +Well, looking at the equation above and using a bit of analyical differential equation knowledge, we can assume the solution will be divided into a number of basis functions like : + +$$ +\Psi(\mathbf{r},t) = \frac{1}{\sqrt{2 \pi}}\sum_n c_n(t) e^{2 \pi i n \mathbf{r}} +$$ + +where $$c_n$$ are some constants depending on "how much" of that basis function exists in the solved system. + +As a small concession here, using this method enforces periodic boundary conditions, where the wavefunction will simply slide from one side of your simulation box to the other, but that's fine for most cases. +In fact, for many cases (such as large-scale turbulence models) it's ideal. From 587d775d658e826421a0169d46ecb4af4bbadef7 Mon Sep 17 00:00:00 2001 From: leios Date: Sun, 13 May 2018 08:42:36 +0900 Subject: [PATCH 4/7] adding back split-op.jl file. --- .../quantum/split-op/code/julia/{split_step.jl => split_op.jl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename chapters/physics_solvers/quantum/split-op/code/julia/{split_step.jl => split_op.jl} (100%) diff --git a/chapters/physics_solvers/quantum/split-op/code/julia/split_step.jl b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl similarity index 100% rename from chapters/physics_solvers/quantum/split-op/code/julia/split_step.jl rename to chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl From 692e278c9f849cddb0f48f4de925c5beef0b7263 Mon Sep 17 00:00:00 2001 From: leios Date: Tue, 15 May 2018 05:31:49 +0900 Subject: [PATCH 5/7] fixing typo in split-op method. --- chapters/physics_solvers/quantum/split-op/split-op.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/physics_solvers/quantum/split-op/split-op.md b/chapters/physics_solvers/quantum/split-op/split-op.md index d2efe7ffa..fc0b6bdaf 100644 --- a/chapters/physics_solvers/quantum/split-op/split-op.md +++ b/chapters/physics_solvers/quantum/split-op/split-op.md @@ -22,7 +22,7 @@ In the hamiltonian shown above, we can split our system into real-space componen If we assume a somewhat general solution to our quantum system: $$ -\Psi(\mathbf{r},t + dt) = \left[e^{-\frac{i\hat{H}dt}{\hbar}}\Psi(\mathbf{r},t) = e^{-\frac{i(\hat{H}_R + \hat{H}_M)dt}{\hbar}}\right]\Psi(\mathbf{r},t) +\Psi(\mathbf{r},t + dt) = \left[e^{-\frac{i\hat{H}dt}{\hbar}}\right]\Psi(\mathbf{r},t) = \left[e^{-\frac{i(\hat{H}_R + \hat{H}_M)dt}{\hbar}}\right]\Psi(\mathbf{r},t) $$ and assume we are simulating our system by a series of small tiemsteps ($$dt$$), we can perform similar splitting by using the Baker-Campbell-Housdorff formula: From d28ec04238aaef57ed40e91e64ddae49d9097050 Mon Sep 17 00:00:00 2001 From: leios Date: Wed, 16 May 2018 06:55:56 +0900 Subject: [PATCH 6/7] turning the splitop param module into a struct --- .../quantum/split-op/code/julia/split_op.jl | 52 +++++++++++-------- .../quantum/split-op/split-op.md | 6 +-- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl index 6b689cd2d..b45280b65 100644 --- a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl +++ b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl @@ -1,20 +1,29 @@ using Plots pyplot() -# Module to hold all parameters for simulation -module Par - const xmax = 10.0 - const res = 512 - const dt = 0.05 - const timesteps = 1000 - const dx = 2*xmax / res - const x = -xmax+dx:dx:xmax - const dk = pi / xmax - const k = vcat(0:res/2-1, -res/2:-1)*dk +# struct to hold all parameters for simulation +struct Param + xmax::Float64 + res::Int64 + dt::Float64 + timesteps::Int64 + dx::Float64 + x::Vector{Float64} + dk::Float64 + k::Vector{Float64} + + Param() = new(10.0, 512, 0.05, 1000, 2*10.0 / 512, + Vector{Float64}(-10.0+10.0/512:20.0/512:10.0), pi / 10.0, + Vector{Float64}(vcat(0:512/2-1, -512/2:-1)*pi/10.0)) + Param(xmax::Float64, res::Int64, dt::Float64, timesteps::Int64) = new( + xmax, res, dt, timesteps, + 2*xmax/res, Vector{Float64}(-xmax+xmax/res:2*xmax/res:xmax), + pi/xmax, Vector{Float64}(vcat(0:res/2-1, -res/2:-1)*pi/xmax) + ) end -# Type to hold all operators -type Operators +# struct to hold all operators +mutable struct Operators V::Vector{Complex{Float64}} PE::Vector{Complex{Float64}} KE::Vector{Complex{Float64}} @@ -22,19 +31,19 @@ type Operators end # Function to initialize the wfc and potential -function init(voffset::Float64, wfcoffset::Float64) - V = 0.5 * (Par.x - voffset).^2 - wfc = 3* exp.(-(Par.x-wfcoffset).^2/2) - PE = exp.(-0.5*im*V*Par.dt) - KE = exp.(-0.5*im*Par.k.^2*Par.dt) +function init(par::Param, voffset::Float64, wfcoffset::Float64) + V = 0.5 * (par.x - voffset).^2 + wfc = 3* exp.(-(par.x-wfcoffset).^2/2) + PE = exp.(-0.5*im*V*par.dt) + KE = exp.(-0.5*im*par.k.^2*par.dt) opr = Operators(V, PE, KE, wfc) end # Function for the split-operator loop -function split_op(opr::Operators) +function split_op(par::Param, opr::Operators) - for i = 1:Par.timesteps + for i = 1:par.timesteps # Half-step in real space opr.wfc = opr.wfc.*opr.PE @@ -61,8 +70,9 @@ end # main function function main() - opr = init(0.0, 1.0) - split_op(opr) + par = Param(10.0, 512, 0.05, 1000) + opr = init(par, 0.0, 1.0) + split_op(par, opr) end main() diff --git a/chapters/physics_solvers/quantum/split-op/split-op.md b/chapters/physics_solvers/quantum/split-op/split-op.md index fc0b6bdaf..6a170e498 100644 --- a/chapters/physics_solvers/quantum/split-op/split-op.md +++ b/chapters/physics_solvers/quantum/split-op/split-op.md @@ -55,7 +55,7 @@ Frist, we need to set all the initial parameters, including the initial grids in {% method %} {% sample lang="jl" %} -[import:4-22, lang:"julia"](code/julia/split_op.jl) +[import:4-31, lang:"julia"](code/julia/split_op.jl) {% endmethod %} As a note, when we generate our grid in momentum space `k`, we need to split the grid into two lines, one that is going from `0` to `-kmax` and is then discontinuous and goes from `kmax` to `0`. @@ -64,7 +64,7 @@ Afterwards, we turn them into operators: {% method %} {% sample lang="jl" %} -[import:24-32, lang:"julia"](code/julia/split_op.jl) +[import:32-41, lang:"julia"](code/julia/split_op.jl) {% endmethod %} Here, we use a standard harmonic potential for the atoms to sit in and a gaussian distribution for an initial guess for the probability distribution. @@ -75,7 +75,7 @@ And finally go step-by-step through the simulation: {% method %} {% sample lang="jl" %} -[import:34-60, lang:"julia"](code/julia/split_op.jl) +[import:42-69, lang:"julia"](code/julia/split_op.jl) {% endmethod %} And that's it. From 239a60f61f8354f5bf51ba9ace53d7509bbbf318 Mon Sep 17 00:00:00 2001 From: leios Date: Sat, 19 May 2018 05:39:07 +0900 Subject: [PATCH 7/7] adding smallscale changes to spacing in split_op.jl --- .../quantum/split-op/code/julia/split_op.jl | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl index b45280b65..636f58af0 100644 --- a/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl +++ b/chapters/physics_solvers/quantum/split-op/code/julia/split_op.jl @@ -12,9 +12,10 @@ struct Param dk::Float64 k::Vector{Float64} - Param() = new(10.0, 512, 0.05, 1000, 2*10.0 / 512, - Vector{Float64}(-10.0+10.0/512:20.0/512:10.0), pi / 10.0, - Vector{Float64}(vcat(0:512/2-1, -512/2:-1)*pi/10.0)) + Param() = new(10.0, 512, 0.05, 1000, 2 * 10.0/512, + Vector{Float64}(-10.0 + 10.0/512 : 20.0/512 : 10.0), + pi / 10.0, + Vector{Float64}(vcat(0:512/2 - 1, -512/2 : -1) * pi/10.0)) Param(xmax::Float64, res::Int64, dt::Float64, timesteps::Int64) = new( xmax, res, dt, timesteps, 2*xmax/res, Vector{Float64}(-xmax+xmax/res:2*xmax/res:xmax), @@ -33,7 +34,7 @@ end # Function to initialize the wfc and potential function init(par::Param, voffset::Float64, wfcoffset::Float64) V = 0.5 * (par.x - voffset).^2 - wfc = 3* exp.(-(par.x-wfcoffset).^2/2) + wfc = 3 * exp.(-(par.x - wfcoffset).^2/2) PE = exp.(-0.5*im*V*par.dt) KE = exp.(-0.5*im*par.k.^2*par.dt) @@ -45,25 +46,25 @@ function split_op(par::Param, opr::Operators) for i = 1:par.timesteps # Half-step in real space - opr.wfc = opr.wfc.*opr.PE + opr.wfc = opr.wfc .* opr.PE # fft to phase space opr.wfc = fft(opr.wfc) # Full step in phase space - opr.wfc = opr.wfc.*opr.KE + opr.wfc = opr.wfc .* opr.KE # ifft back opr.wfc = ifft(opr.wfc) # final half-step in real space - opr.wfc = opr.wfc.*opr.PE + opr.wfc = opr.wfc .* opr.PE # plotting density and potential density = abs2.(opr.wfc) plot([density, real(opr.V)]) - savefig("density"*string(lpad(i, 5, 0))*".png") + savefig("density" * string(lpad(i, 5, 0)) * ".png") println(i) end end