1
- using Plots
2
- pyplot ()
1
+ # ------------split_op.jl-------------------------------------------------------#
2
+ #
3
+ # Plotting: to plot individual timesteps, use gnuplot like so:
4
+ # p "output00000.dat" u 1:2 w l
5
+ # rep "output00000.dat" u 1:3 w l
6
+ #
7
+ # ------------------------------------------------------------------------------#
3
8
4
- # struct to hold all parameters for simulation
5
9
struct Param
6
10
xmax:: Float64
7
11
res:: Int64
@@ -11,34 +15,48 @@ struct Param
11
15
x:: Vector{Float64}
12
16
dk:: Float64
13
17
k:: Vector{Float64}
18
+ im_time:: Bool
14
19
15
20
Param () = new (10.0 , 512 , 0.05 , 1000 , 2 * 10.0 / 512 ,
16
21
Vector {Float64} (- 10.0 + 10.0 / 512 : 20.0 / 512 : 10.0 ),
17
- pi / 10.0 ,
18
- Vector {Float64} (vcat (0 : 512 / 2 - 1 , - 512 / 2 : - 1 ) * pi / 10.0 ))
19
- Param (xmax:: Float64 , res:: Int64 , dt:: Float64 , timesteps:: Int64 ) = new (
22
+ pi / 10.0 ,
23
+ Vector {Float64} (vcat (0 : 512 / 2 - 1 , - 512 / 2 : - 1 ) * pi / 10.0 ),
24
+ false )
25
+ Param (xmax:: Float64 , res:: Int64 , dt:: Float64 , timesteps:: Int64 ,
26
+ im_val:: Bool ) = new (
20
27
xmax, res, dt, timesteps,
21
28
2 * xmax/ res, Vector {Float64} (- xmax+ xmax/ res: 2 * xmax/ res: xmax),
22
- pi / xmax, Vector {Float64} (vcat (0 : res/ 2 - 1 , - res/ 2 : - 1 )* pi / xmax)
29
+ pi / xmax, Vector {Float64} (vcat (0 : res/ 2 - 1 , - res/ 2 : - 1 )* pi / (xmax)),
30
+ im_val
23
31
)
24
32
end
25
33
26
- # struct to hold all operators
27
34
mutable struct Operators
28
35
V:: Vector{Complex{Float64}}
29
36
PE:: Vector{Complex{Float64}}
30
37
KE:: Vector{Complex{Float64}}
31
38
wfc:: Vector{Complex{Float64}}
39
+
40
+ Operators (res) = new (Vector {Complex{Float64}} (res),
41
+ Vector {Complex{Float64}} (res),
42
+ Vector {Complex{Float64}} (res),
43
+ Vector {Complex{Float64}} (res))
32
44
end
33
45
34
46
# Function to initialize the wfc and potential
35
47
function init (par:: Param , voffset:: Float64 , wfcoffset:: Float64 )
36
- V = 0.5 * (par. x - voffset). ^ 2
37
- wfc = 3 * exp .(- (par. x - wfcoffset). ^ 2 / 2 )
38
- PE = exp .(- 0.5 * im* V* par. dt)
39
- KE = exp .(- 0.5 * im* par. k.^ 2 * par. dt)
48
+ opr = Operators (length (par. x))
49
+ opr. V = 0.5 * (par. x - voffset). ^ 2
50
+ opr. wfc = exp .(- (par. x - wfcoffset). ^ 2 / 2 )
51
+ if (par. im_time)
52
+ opr. = exp .(- 0.5 * par. k.^ 2 * par. dt)
53
+ opr. PE = exp .(- 0.5 * opr. V* par. dt)
54
+ else
55
+ opr. = exp .(- im* 0.5 * par. k.^ 2 * par. dt)
56
+ opr. PE = exp .(- im* 0.5 * opr. V* par. dt)
57
+ end
40
58
41
- opr = Operators (V, PE, KE, wfc)
59
+ return opr
42
60
end
43
61
44
62
# Function for the split-operator loop
@@ -48,32 +66,78 @@ function split_op(par::Param, opr::Operators)
48
66
# Half-step in real space
49
67
opr. wfc = opr. wfc .* opr. PE
50
68
51
- # fft to phase space
69
+ # fft to momentum space
52
70
opr. wfc = fft (opr. wfc)
53
71
54
- # Full step in phase space
55
- opr. wfc = opr. wfc .* opr. KE
72
+ # Full step in momentum space
73
+ opr. wfc = opr. wfc .* opr.
56
74
57
75
# ifft back
58
76
opr. wfc = ifft (opr. wfc)
59
77
60
78
# final half-step in real space
61
79
opr. wfc = opr. wfc .* opr. PE
62
80
63
- # plotting density and potential
81
+ # density for plotting and potential
64
82
density = abs2 .(opr. wfc)
65
83
66
- plot ([density, real (opr. V)])
67
- savefig (" density" * string (lpad (i, 5 , 0 )) * " .png" )
68
- println (i)
84
+ # renormalizing for imaginary time
85
+ if (par. im_time)
86
+ renorm_factor = sum (density) * par. dx
87
+
88
+ for j = 1 : length (opr. wfc)
89
+ opr. wfc[j] /= sqrt (renorm_factor)
90
+ end
91
+ end
92
+
93
+ # Outputting data to file. Plotting can also be done in a similar way
94
+ # This is set to output exactly 100 files, no matter how many timesteps
95
+ if ((i- 1 ) % div (par. timesteps, 100 ) == 0 )
96
+ outfile = open (" output" * string (lpad (i- 1 , 5 , 0 ))* " .dat" ," w" )
97
+
98
+ # Outputting for gnuplot. Any plotter will do.
99
+ for j = 1 : length (density)
100
+ write (outfile, string (par. x[j]) * " \t "
101
+ * string (density[j]) * " \t "
102
+ * string (real (opr. V[j])) * " \n " )
103
+ end
104
+
105
+ close (outfile)
106
+ println (" Outputting step: " , i)
107
+ end
69
108
end
70
109
end
71
110
111
+ # We are calculating the energy to check <Psi|H|Psi>
112
+ function calculate_energy (par, opr)
113
+ # Creating real, momentum, and conjugate wavefunctions
114
+ wfc_r = opr. wfc
115
+ wfc_k = fft (wfc_r)
116
+ wfc_c = conj (wfc_r)
117
+
118
+ # Finding the momentum and real-space energy terms
119
+ energy_k = 0.5 * wfc_c.* ifft ((par. k.^ 2 ) .* wfc_k)
120
+ energy_r = wfc_c.* opr. V .* wfc_r
121
+
122
+ # Integrating over all space
123
+ energy_final = 0
124
+ for i = 1 : length (energy_k)
125
+ energy_final += real (energy_k[i] + energy_r[i])
126
+ end
127
+
128
+ return energy_final* par. dx
129
+ end
130
+
72
131
# main function
73
132
function main ()
74
- par = Param (10.0 , 512 , 0.05 , 1000 )
75
- opr = init (par, 0.0 , 1.0 )
133
+ par = Param (5.0 , 256 , 0.05 , 100 , true )
134
+
135
+ # Starting wavefunction slightly offset so we can see it change
136
+ opr = init (par, 0.0 , - 1.00 )
76
137
split_op (par, opr)
138
+
139
+ energy = calculate_energy (par, opr)
140
+ println (" Energy is: " , energy)
77
141
end
78
142
79
143
main ()
0 commit comments