/
interpolvsi.py
327 lines (209 loc) · 7.38 KB
/
interpolvsi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#imports usual modules
import numpy
import scipy
from scipy import linalg
import matplotlib
# matplotlib.use('Agg')
import matplotlib.pyplot as plt
import re
'''This module will calculate the reciprocal lattice vecotrs and plot the energies for silicon (fcc) and maybe bcc and simple'''
############################################################
'''constants are input here'''
prop=0
asil = 5.43*10**-10
ager = 5.65*10**-10
a = ((1-prop)*asil) + (prop*ager)
#lattice constant of material
c =2*numpy.pi/a
#lattice constant divided by half bc python likes integers
melec= 9.11*10**-31
#mass of an electron
e = 1.61*10**-19
#elementary charge
hbar= 1.0534*10**-34
#hbar
c_energy = c**2*(hbar**2)/(2*melec*e)
#constant in front of the delta funtcion in the s.e
############################################################
'''reciprocal lattice vectors are genertaed here'''
#a function to find the magnitude of a vector
def mags(value):
return numpy.sqrt(abs(value.dot(value)))
#a function to generate reciprocal lattice vectors
def RLVS(N,struc):
rlvs = []
nxs=[]
for i in range(-N,N+1):
nxs.append(i)
nys,nzs=nxs,nxs
if struc == numpy.str('fcc'):
#for face centred cubic
for nx in nxs:
for ny in nys:
for nz in nzs:
g = numpy.array([-nx+ny+nz, nx-ny+nz, nx+ny-nz])
rlvs.append(g)
elif struc == 'bcc':
#for body centred cubic
for nx in nxs:
for ny in nys:
for nz in nzs:
g = numpy.array([nx+ny, nx+nz, ny+nz])
rlvs.append(g)
elif struc == 'simple cubic':
#for simple cubic
for nx in nxs:
for ny in nys:
for nz in nzs:
g = numpy.array([nx, ny, nz])
rlvs.append(g)
else:
#those are the only ones I know
print('Invalid input')
rlvs.sort(key=mags)
# sorts the rlvs in order of magnitude
return(rlvs[:51])
#for the purpose of the first excercise, this only returns the first 15 rlvs
############################################################
'''potential are defined here'''
convert = 13.6056980659
#form factors germanium
V3G = -0.238 * convert
V8G = 0.0038 * convert
V11G = 0.068 * convert
ffg = numpy.array([V3G, V8G, V11G])
#form factors silicon
# V3S = -3.04768
# V8S = 0.74831
# V11S = 0.97961
V3S = -0.224 * convert
V8S = 0.055 * convert
V11S = 0.072 * convert
ffs = numpy.array([V3S, V8S, V11S])
ffg = ffg*(prop)
ffs = ffs*(1-prop)
ffc = numpy.add(ffg,ffs)
#compound form factor
#a function to caluculate structure factor
def strucfact(g):
nxprime, nyprime, nzprime = g
#this g will be the vector g - gprime; corresponds to the position in the matrix
sf = numpy.cos((numpy.pi/4)*(nxprime + nyprime + nzprime))
return sf
############################################################
'''schrodinger equation is calculated here'''
def matrix(N,struc,k,V):
#utilise a matrix formulation to find the energies of the bands
gs = RLVS(N,struc)
gprimes = gs
pop = []
#a list of numbers that we be reshaped to become the appropriate matrix as numpy doesn't like using matrices.
for i in range(0,len(gs)):
for j in range(0,len(gprimes)):
#indexes the coordinates within the matrix
deltag = gs[i] - gprimes[j]
#g'' in the notes
energy = 0
#initialises energy value
if deltag.dot(deltag) == 0:
# this calculates the diagonal energy terms with the condition if g = grpime
modkgs = (k+(gs[i])).dot(k+(gs[i]))
energy += c_energy*abs(modkgs)
#adds the potential terms with the condiditon that g'' has a certain value
if deltag.dot(deltag) == 3:
energy += (V[0] * strucfact(deltag))
if deltag.dot(deltag) == 8:
energy += (V[1] * strucfact(deltag))
if deltag.dot(deltag) == 11:
energy += (V[2] * strucfact(deltag))
#all other terms are appended with 0
pop.append(energy)
matrix = numpy.matrix(numpy.array(pop).reshape(len(gs),len(gprimes)))
#creates a matrix of size g x gprime with the appropriate values in each spot
return (matrix)
# print(matrix(3,'fcc', numpy.array([1,0,0]), ffs))
############################################################
'''this finds the eignenvalues of the s.e. matrix'''
#a function that calculates the eigenvalues of a matrix
def eigenvalues(N, struc, k, V):
se = matrix(N, struc, k, V)
#extra line of code to make it look a bit cleaner
eigenvalues = numpy.real(numpy.sort(scipy.linalg.eigvals(se)))
return(eigenvalues)
print(eigenvalues(3,'fcc', numpy.array([1,0,0]), ffs))
############################################################
'''graph'''
alpha = numpy.arange(0.0,1, 0.01)
#defines the delineation of the k values
kxs = []
kls = []
kks = []
#empty lists to be filled with vectors of k for calculating eigenvectors
plotkx = []
plotkl = []
plotkk = []
#empty lists to be filled with magnitudes of k for plotting
for i in range(len(alpha)):
#loop that generates k vectors in the x direction
kx = (numpy.array([1,0,0])*alpha[i])
magkx = mags(kx)
kxs.append(kx)
plotkx.append(magkx)
kl = numpy.array([.5,.5,.5])*alpha[i]
magkl = (-1)*mags(kl)
kls.append(kl)
plotkl.append(magkl)
kk = numpy.array([.75,.75,.75])*alpha[i]
magkk = mags(kk)
kks.append(kk)
plotkk.append(magkk)
###### ###### ###### ###### ###### ######
N = 3
#declares the range of N values (and hence the number of reciprocal lattice vectors)
for rlv in range(len(RLVS(N, 'fcc'))):
xenergies = []
#an empty list to be filled with energies for each reciprocal lattice vector
for x in range(len(kxs)):
#loop calculates energies for each k vector
xenergy = eigenvalues(N, 'fcc', kxs[x], ffc)
xenergies.append(xenergy)
#appends the energy values to the energy list
#repeats for lambda axis
lenergies = []
for l in range(len(kls)):
lenergy = eigenvalues(N, 'fcc', kls[l], ffc)
lenergies.append(lenergy)
lenergies.reverse()
energies = lenergies + xenergies
#places all energy values in one list for the plot
energies = numpy.array(energies)
#converts the list of energies to an array so it can be enumaerated
plote = [energies[:,i] for i,e in enumerate(energies[0])]
#enumarates the list to separate the different energies out for different values of k to be plotted
plotks = (plotkl + plotkx)
plotks.sort()
#creates a list of odered ks to plot against
######### ######### ######### #########
plt.figure(figsize=(6,6))
#graph time
# for e in plote:
# plt.plot(plotks,e,label='j')
#plots the energies over each k value
#usual graph stuffs
plt.xlabel('k')
plt.ylabel('Energy')
plt.legend()
# plt.savefig('interpolv.png')
############################################################
'bandgap is determined here'
#analytically
l4 = numpy.max(plote[3])
plt.plot(plotks, plote[3])
max_k = plotks[plote[3].argmax()]
l5 = numpy.min(plote[4])
plt.plot(plotks,plote[4])
min_k = plotks[plote[4].argmin()]
l5d = plote[4]
gap = l5-l4
print(gap, max_k, min_k)
plt.show()