# triang.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
import numpy as np
def forsub(L,bs):
n = bs.size
xs = np.zeros(n)
for i in range(n):
xs[i] = (bs[i] - L[i,:i]@xs[:i])/L[i,i]
return xs
def backsub(U,bs):
n = bs.size
xs = np.zeros(n)
for i in reversed(range(n)):
xs[i] = (bs[i] - U[i,i+1:]@xs[i+1:])/U[i,i]
return xs
def testcreate(n,val):
A = np.arange(val,val+n*n).reshape(n,n)
A = np.sqrt(A)
bs = (A[0,:])**2.1
return A, bs
def testsolve(f,A,bs):
xs = f(A,bs); print(xs)
xs = np.linalg.solve(A,bs); print(xs)
if __name__ == '__main__':
A, bs = testcreate(4,21)
L = np.tril(A)
testsolve(forsub,L,bs)
print(" ")
U = np.triu(A)
testsolve(backsub,U,bs)
# gauelim.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import backsub, testcreate, testsolve
import numpy as np
def gauelim(inA,inbs):
A = np.copy(inA)
bs = np.copy(inbs)
n = bs.size
for j in range(n-1):
for i in range(j+1,n):
coeff = A[i,j]/A[j,j]
A[i,j:] -= coeff*A[j,j:]
bs[i] -= coeff*bs[j]
xs = backsub(A,bs)
return xs
if __name__ == '__main__':
A, bs = testcreate(4,21)
testsolve(gauelim,A,bs)
# ludec.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import forsub, backsub, testcreate, testsolve
import numpy as np
def ludec(A):
n = A.shape[0]
U = np.copy(A)
L = np.identity(n)
for j in range(n-1):
for i in range(j+1,n):
coeff = U[i,j]/U[j,j]
U[i,j:] -= coeff*U[j,j:]
L[i,j] = coeff
return L, U
def lusolve(A,bs):
L, U = ludec(A)
ys = forsub(L,bs)
xs = backsub(U,ys)
return xs
if __name__ == '__main__':
A, bs = testcreate(4,21)
testsolve(lusolve,A,bs)
# gauelim_pivot.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import backsub, testcreate, testsolve
import numpy as np
def gauelim_pivot(inA,inbs):
A = np.copy(inA)
bs = np.copy(inbs)
n = bs.size
for j in range(n-1):
k = np.argmax(np.abs(A[j:,j])) + j
if k != j:
A[j,:], A[k,:] = A[k,:], A[j,:].copy()
bs[j], bs[k] = bs[k], bs[j]
for i in range(j+1,n):
coeff = A[i,j]/A[j,j]
A[i,j:] -= coeff*A[j,j:]
bs[i] -= coeff*bs[j]
xs = backsub(A,bs)
return xs
if __name__ == '__main__':
A, bs = testcreate(4,21)
testsolve(gauelim_pivot,A,bs)
# jacobi.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import testcreate, testsolve
import numpy as np
def termcrit(xolds,xnews):
errs = np.abs((xnews - xolds)/xnews)
return np.sum(errs)
def jacobi(A,bs,kmax=50,tol=1.e-6):
n = bs.size
xnews = np.zeros(n)
for k in range(1,kmax):
xs = np.copy(xnews)
for i in range(n):
slt = A[i,:i]@xs[:i]
sgt = A[i,i+1:]@xs[i+1:]
xnews[i] = (bs[i] - slt - sgt)/A[i,i]
err = termcrit(xs,xnews)
print(k, xnews, err)
if err < tol:
break
else:
xnews = None
return xnews
if __name__ == '__main__':
n = 4; val = 21
A, bs = testcreate(n,val)
A += val*np.identity(n)
testsolve(jacobi,A,bs)
# power.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import testcreate
import numpy as np
def mag(xs):
return np.sqrt(np.sum(xs*xs))
def power(A,kmax=6):
zs = np.ones(A.shape[0])
qs = zs/mag(zs)
for k in range(1,kmax):
zs = A@qs
qs = zs/mag(zs)
print(k,qs)
lam = qs@A@qs
return lam, qs
def testeigone(f,A,indx=0):
eigval, eigvec = f(A)
print(" "); print(eigval); print(eigvec)
npeigvals, npeigvecs = np.linalg.eig(A)
print(" ")
print(npeigvals[indx]); print(npeigvecs[:,indx])
if __name__ == '__main__':
A, bs = testcreate(4,21)
testeigone(power,A)
# invpowershift.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import forsub, backsub, testcreate
from ludec import ludec
from jacobi import termcrit
from power import mag, testeigone
import numpy as np
#def invpowershift(A,shift=20,kmax=200,tol=1.e-2):
def invpowershift(A,shift=20,kmax=200,tol=1.e-8):
n = A.shape[0]
znews = np.ones(n)
qnews = znews/mag(znews)
Astar = A - np.identity(n)*shift
L, U = ludec(Astar)
for k in range(1,kmax):
qs = np.copy(qnews)
ys = forsub(L,qs)
znews = backsub(U,ys)
qnews = znews/mag(znews)
if qs@qnews<0:
qnews = -qnews
err = termcrit(qs,qnews)
print(k, qnews, err)
if err < tol:
lam = qnews@A@qnews
break
else:
lam = qnews = None
return lam, qnews
if __name__ == '__main__':
A, bs = testcreate(4,21)
testeigone(invpowershift,A)
# qrdec.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import testcreate
from power import mag
import numpy as np
def qrdec(A):
n = A.shape[0]
Ap = np.copy(A)
Q = np.zeros((n,n))
R = np.zeros((n,n))
for j in range(n):
for i in range(j):
R[i,j] = Q[:,i]@A[:,j]
Ap[:,j] -= R[i,j]*Q[:,i]
R[j,j] = mag(Ap[:,j])
Q[:,j] = Ap[:,j]/R[j,j]
return Q, R
def testqrdec(A):
n = A.shape[0]
Q, R = qrdec(A)
diffa = A - Q@R
diffq = np.transpose(Q)@Q - np.identity(n)
print(n, mag(diffa), mag(diffq))
if __name__ == '__main__':
for n in range(4,10,2):
A, bs = testcreate(n,21)
testqrdec(A)
# qrmet.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import testcreate
from qrdec import qrdec
import numpy as np
def qrmet(inA,kmax=100):
A = np.copy(inA)
for k in range(1,kmax):
Q, R = qrdec(A)
A = R@Q
print(k, np.diag(A))
qreigvals = np.diag(A)
return qreigvals
if __name__ == '__main__':
A, bs = testcreate(4,21)
qreigvals = qrmet(A,6)
print(" ")
npeigvals, npeigvecs = np.linalg.eig(A); print(npeigvals)
# eig.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from triang import testcreate
from invpowershift import invpowershift
from qrmet import qrmet
import numpy as np
def eig(A,eps=1.e-12):
n = A.shape[0]
eigvals = np.zeros(n)
eigvecs = np.zeros((n,n))
qreigvals = qrmet(A)
for i, qre in enumerate(qreigvals):
eigvals[i], eigvecs[:,i] = invpowershift(A,qre+eps)
return eigvals, eigvecs
def testeigall(f,A):
eigvals, eigvecs = f(A)
npeigvals, npeigvecs = np.linalg.eig(A)
print(eigvals); print(npeigvals)
print(" ")
for eigvec, npeigvec in zip(eigvecs.T,npeigvecs.T):
print(eigvec); print(npeigvec)
print(" ")
if __name__ == '__main__':
A, bs = testcreate(4,21)
testeigall(eig,A)
# kron.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
import numpy as np
def paulimatrices():
sigx = np.array([0.,1,1,0]).reshape(2,2)
sigy = np.array([0.,-1j,1j,0]).reshape(2,2)
sigz = np.array([1.,0,0,-1]).reshape(2,2)
return sigx, sigy, sigz
def kron(U,V):
n = U.shape[0]
p = V.shape[0]
W = np.zeros((n*p,n*p), dtype=np.complex64)
for i in range(n):
for k in range(n):
for j in range(p):
for l in range(p):
W[p*i+j,p*k+l] = U[i,k]*V[j,l]
return W
if __name__ == '__main__':
sigx, sigy, sigz = paulimatrices()
allones = np.ones((3,3))
kronprod = kron(sigx,allones); print(kronprod.real)
# twospins.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from kron import paulimatrices, kron
from qrmet import qrmet
import numpy as np
def twospins(omI,omII,gam):
hbar = 1.
paulis = paulimatrices()
iden = np.identity(2)
SIs = [hbar*kron(pa,iden)/2 for pa in paulis]
SIIs = [hbar*kron(iden,pa)/2 for pa in paulis]
SIdotII = sum([SIs[i]@SIIs[i] for i in range(3)])
H = -omI*SIs[2] - omII*SIIs[2] + gam*SIdotII
H = H.real
return H
if __name__ == '__main__':
H = twospins(1.,2.,0.5)
qreigvals = qrmet(H); print(qreigvals)
# threespins.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (CUP, 2020)
from qrmet import qrmet
from kron import paulimatrices, kron
import numpy as np
def threespins(omI,omII,omIII,gam):
hbar = 1.
paulis = paulimatrices()
iden = np.identity(2)
SIs = [hbar*kron(kron(pa,iden),iden)/2 for pa in paulis]
SIIs = [hbar*kron(kron(iden,pa),iden)/2 for pa in paulis]
SIIIs = [hbar*kron(kron(iden,iden),pa)/2 for pa in paulis]
SIdotII = sum([SIs[i]@SIIs[i] for i in range(3)])
SIdotIII = sum([SIs[i]@SIIIs[i] for i in range(3)])
SIIdotIII = sum([SIIs[i]@SIIIs[i] for i in range(3)])
H = -omI*SIs[2] - omII*SIIs[2] - omIII*SIIIs[2]
H += gam*(SIdotII+SIdotIII+SIIdotIII)
H = H.real
return H
if __name__ == '__main__':
np.set_printoptions(precision=3)
H = threespins(1.,2.,3.,0.5)
qreigvals = qrmet(H); print(qreigvals)