Tutorial To Simulate Isotropic Two Dimensional Harmonic Oscillator
Create simulation directory
First of all we need to create a specific directory to save this specific simulation results
@prompt:~$ mkdir ~/my_directory_path/QHO2D
@prompt:~$ cd ~/my_directory_path/QHO2D
Create function potential
We need to create a specific function potential for quantum harmonic oscillator 2D as following:
@prompt:~/my_directory_path/QHO2D$ vi adhoc_potential_function.jl
Inside adhoc_potential_function
write the following:
export qho_2d
"""
qho_2d(x,params)
# Aim:
This function is a simple implementation of the 2D quantum harmonic oscillator
potential.
It is used to test the simulation of the isotropic quantum harmonic oscillator in 2D.
# Arguments
x::Array{Float64,1} : The position of the particle in 2D.
params::Tuple : A tuple containing the parameters of the potential.
params[1]::Float64 : The frequency of the oscillator.
params[2]::Float64 : The position of the minimum of the potential in the x
direction.
params[3]::Float64 : The position of the minimum of the potential in the y
direction.
"""
function qho_2d(x,params::Tuple)
ω,x₁,y₁=params
return 0.5*(ω*ω)*((x[1]-x₁)*(x[1]-x₁)+(x[2]-y₁)*(x[2]-y₁))
end
Input file
We need to create an input file to simulate using default solver function inside FEMTISE package
@prompt:~/my_directory_path/QHO2D$ vi input.dat
Inside input.dat
we need to write the following.
full_path_name = ~/my_directory_path/QHO2D/name_output_file
dom_type = s
nev = 10
dimension = 2D
sigma = 0.0
adhoc_file_name = ~/my_directory_path/QHO2D/adhoc_potential_function
potential_function_name = qho_2d
params_potential_types = f f f
params_potential = 1.0 0.0 0.0
analysis_param = false
output_format_type = jld2 eigen
## ONLY FOR 1D EIGENPROBLEMS
L =
Δx =
## ONLY FOR 2D EIGENPROBLEMS
Lx = 10
Ly = 10
nx = 100
ny = 100
different_masses = false
reduced_density = false
Note that ~/my_path_repo/
is the directory path where we can find FEMTISE.jl package.
Run script
Create Julia code as
@prompt:~/my_directory_path/QHO2D$ vi run.jl
Inside run.jl
we need to write the following.
begin
using Pkg
Pkg.activate("~/my_directory_path/QHO2D/")
develop_package = true; develop_package ? Pkg.develop(path="~/my_path_repo/FEMTISE.jl") : nothing
Pkg.instantiate()
using FEMTISE;
run_default_eigen_problem(set_type_potential("~/my_directory_path/QHO2D/input.dat"))
end
After this we can run the simulation using Julia compiler (for example: using multithread running with four threads)
@prompt:~/my_directory_path/QHO2D$ julia -t 4 run.jl
Analysis
After running we obtain an output data file in jld2 format called name_output_file_eigen_data.jld2
.
Then using Jupyter Notebook (by intermediate Visual Studio Code) we can analyse output file so:
@prompt:~/my_directory_path/QHO2D$ code QHO2D.ipynb
Inside QHO2D.ipynb
we need to write the following:
Environment
Activate Julia environment
using Pkg
Pkg.activate("~/my_directory_path/QHO2D/")
Pkg.instantiate()
Is necessary to mark FEMTISE package as developed package using specific path repository:
develop_package = true; develop_package ? Pkg.develop(path="~/my_path_repo/FEMTISE.jl") : nothing
Now we install package (if it is nesseary) and use specific packages to analyse output data:
install_pkg = true
if install_pkg
Pkg.add("Plots")
Pkg.add("PlotlyJS")
end
using FEMTISE;
using Plots;
Read output data
All the information that we need to specify is where we find input file then using specific functions we can collect output data
path_input_file_name="~/my_directory_path/QHO2D/input.dat"
simulation_info, output_data = collect_result_data(true,path_input_file_name)
Plotting figures
Defining functions to plot data we have:
"""
plot_eigenvalues(id,results;<keyword arguments>)
# Aim
- Plot the eigenvalues of the Hamiltonian operator.
The eigenvalues are obtained from the diagonalization of the Hamiltonian operator.
The keyword arguments are used to set the title, xlabel, ylabel, and legend of the plot.
# Arguments
- `id`: InputData or InputData1D or InputData2D object.
- `results`: Results object.
- `keyword arguments`:
- `set_title::String`: Title of the plot.
- `set_xlabel::String`: Label of the x-axis.
- `set_ylabel::String`: Label of the y-axis.
- `set_legend::Symbol`: Position of the legend.
"""
function plot_eigenvalues(id,results;
set_title::String="",
set_xlabel::String="Energy level (n)",set_ylabel::String="Eigen-energies (ϵn [au])",set_legend::Symbol=:bottomright)
if id.analysis_param == false
plotlyjs()
figure = scatter(real(results.ϵ),title=set_title,xlabel=set_xlabel,ylabel=set_ylabel,legend=set_legend)
else
println("PLOT ERROR.")
println("Check attributes, you are using the wrong function method. Analysis parameter is activated.")
figure = nothing
end
return figure
end
"""
density2D(x,y,phi_n)
# Aim
- Calculate the probability density of the eigenstates in 2D.
# Arguments
- `x::Array{Float64,1}`: Array of x-coordinates.
- `y::Array{Float64,1}`: Array of y-coordinates.
- `phi_n::Array{Complex{Float64},1}`: Array of eigenstates.
"""
function density2D(x,y,phi_n)
density=zeros(length(y),length(x))
for i in eachindex(y)
for j in eachindex(x)
index=(j-1)*length(y)+i
density[i,j]=real.(conj.(phi_n[index]).*phi_n[index])
end
end
return density
end
"""
plot_eigenstates(id,results,index_nev;<keyword arguments>)
# Aim
- Plot the eigenstates of the Hamiltonian operator.
The eigenstates are obtained from the diagonalization of the Hamiltonian operator.
The eigenstates are plotted for the energy level specified by the index_nev variable.
The keyword arguments are used to set the color map of the plot (only for 2D plot).
# Arguments
- `id`: InputData or InputData1D or InputData2D object.
- `results`: Results object.
- `index_nev::Int`: Energy level to plot.
- `keyword arguments`:
- `mapcolor::Symbol=:rainbow1`: Color map of the plot (only for 2D plot).
"""
function plot_eigenstates(id,results,index_nev::Int;mapcolor::Symbol=:rainbow1)
if id.analysis_param == false
if id.params.dimension == "1D"
plotlyjs();
if ((typeof(id) <: InputData) || (typeof(id) <: InputData1D && id.
output_format_type == ("bin","eigen")))
rho = real.(conj.(results.ϕ[:,index_nev]).*(results.ϕ[:,index_nev]))
elseif (typeof(id) <: InputData1D && id.output_format_type in [("jld2","eigen"),
("jld2","all")])
rho = real.(conj.(results.ϕ[index_nev].(results.pts)).*(results.ϕ
[index_nev].(results.pts)))
end
figure = plot(results.r,rho,lw=2,lc=:black,label="")
figure = scatter!(results.r,rho,label="n=$(index_nev)",lw=0.1)
figure = plot!(xlabel="Coordinate (x [au])",ylabel="Probability density (ρn(x))
",ticks = :native)
elseif id.params.dimension == "2D"
gr();
if ((typeof(id) <: InputData) || (typeof(id) <: InputData2D && id.
output_format_type == ("bin","eigen")))
if id.params.nx==id.params.ny
rho = density2D(results.r[:,1],results.r[:,2],results.ϕ[:,index_nev])
figure1 = contour(results.r[:,1],results.r[:,2],rho,levels=10,
color=mapcolor, fill=true,lw=0)
else
rho = density2D(results.r[1:id.params.nx,1],results.r[1:id.params.ny,2],
results.ϕ[:,index_nev])
figure1 = contour(results.r[1:id.params.nx,1],results.r[1:id.params.ny,
2],rho, levels=10, color=mapcolor, fill=true,lw=0)
end
elseif (typeof(id) <: InputData2D && id.output_format_type in [("jld2","eigen"),
("jld2","all")])
rho = density2D(results.r[1],results.r[2],results.ϕ[index_nev].(results.
pts))
figure1 = contour(results.r[1],results.r[2],rho,levels=10, color=mapcolor,
fill=true,lw=0)
end
figure1 = plot(figure1,title="Probability density (ρ$(index_nev)(x))",
xlabel="Coordinate (x [au])", ylabel="Coordinate (y [au])")
if id.reduced_density
plotlyjs()
if ((typeof(id) <: InputData) || (typeof(id) <: InputData1D && id.
output_format_type == ("bin","eigen")))
if id.params.nx==id.params.ny
figure2=plot(results.r[:,1],results.rhoDOF1[:,index_nev],label="ρn
(x)")
figure2=plot!(results.r[:,2],results.rhoDOF2[:,index_nev],label="ρn
(y)")
else
figure2=plot(results.r[1:id.params.nx,1],results.rhoDOF1[:,
index_nev],label="ρn(x)")
figure2=plot!(results.r[1:id.params.ny,2],results.rhoDOF2[:,
index_nev],label="ρn(y)")
end
elseif (typeof(id) <: InputData2D && id.output_format_type in [("jld2",
"eigen"),("jld2","all")])
figure2 = plot(results.r[1],results.rhoDOF1[:,index_nev],label="ρn(x)")
figure2 = plot!(results.r[2],results.rhoDOF2[:,index_nev],label="ρn(y)")
end
figure2=plot!(title="Reduced probability density for level n=$(index_nev)")
figure2=plot!(xlabel="Coordinate (x or y [au])",ylabel="",ticks = :native)
figure = plot(figure1,figure2,layout=2)
else
figure = figure1
end
end
else
println("PLOT ERROR.")
println("You can not plot eigenstate with activated analysis params.")
figure = nothing
end
return figure
end
Now we can plot eigenenergies:
fig1 = plot_eigenvalues(simulation_info, output_data)
display(fig1)
Also, we can export figures as *pdf
format using
savefig(fig1,"./eigen_energies.pdf")
and eigenfunctions:
eigenstate_to_show=1
fig2=plot_eigenstates(simulation_info, output_data,eigenstate_to_show;mapcolor=:turbo)
display(fig2)
eigenstate_to_show=2
fig2=plot_eigenstates(simulation_info, output_data,eigenstate_to_show;mapcolor=:turbo)
display(fig2)