# fixedpoint.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from math import exp, sqrt
def g(x):
return exp(x - sqrt(x))
def fixedpoint(g,xold,kmax=200,tol=1.e-8):
for k in range(1,kmax):
xnew = g(xold)
xdiff = xnew - xold
print("{0:2d} {1:1.16f} {2:1.16f}".format(k,xnew,xdiff))
if abs(xdiff/xnew) < tol:
break
xold = xnew
else:
xnew = None
return xnew
if __name__ == '__main__':
for xold in (0.99, 2.499):
x = fixedpoint(g,xold)
print(x)
# bisection.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from math import exp, sqrt
def f(x):
return exp(x - sqrt(x)) - x
def bisection(f,x0,x1,kmax=200,tol=1.e-8):
f0 = f(x0)
for k in range(1,kmax):
x2 = (x0+x1)/2
f2 = f(x2)
if f0*f2 < 0:
x1 = x2
else:
x0, f0 = x2, f2
x2new = (x0+x1)/2
xdiff = abs(x2new-x2)
rowf = "{0:2d} {1:1.16f} {2:1.16f} {3:1.16f}"
print(rowf.format(k,x2new,xdiff,abs(f(x2new))))
if abs(xdiff/x2new) < tol:
break
else:
x2new = None
return x2new
if __name__ == '__main__':
root = bisection(f,0.,1.5)
print(root); print("")
root = bisection(f,1.5,3.)
print(root)
# secant.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from bisection import f
def secant(f,x0,x1,kmax=200,tol=1.e-8):
f0 = f(x0)
for k in range(1,kmax):
f1 = f(x1)
ratio = (x1 - x0)/(f1 - f0)
x2 = x1 - f1*ratio
xdiff = abs(x2-x1)
x0, x1 = x1, x2
f0 = f1
rowf = "{0:2d} {1:1.16f} {2:1.16f} {3:1.16f}"
print(rowf.format(k,x2,xdiff,abs(f(x2))))
if abs(xdiff/x2) < tol:
break
else:
x2 = None
return x2
if __name__ == '__main__':
root = secant(f,0.,1.7); print(root); print("")
root = secant(f,2.,2.1); print(root)
# legroots.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from legendre import legendre
import numpy as np
def legnewton(n,xold,kmax=200,tol=1.e-8):
for k in range(1,kmax):
val, dval = legendre(n,xold)
xnew = xold - val/dval
xdiff = xnew - xold
if abs(xdiff/xnew) < tol:
break
xold = xnew
else:
xnew = None
return xnew
def legroots(n):
roots = np.zeros(n)
npos = n//2
for i in range(npos):
xold = np.cos(np.pi*(4*i+3)/(4*n+2))
root = legnewton(n,xold)
roots[i] = -root
roots[-1-i] = root
return roots
if __name__ == '__main__':
roots = legroots(9); print(roots)
# multi_newton.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from gauelim_pivot import gauelim_pivot
from jacobi import termcrit
import numpy as np
def fs(xs):
x0, x1 = xs
f0 = x0**2 - 2*x0 + x1**4 - 2*x1**2 + x1
f1 = x0**2 + x0 + 2*x1**3 - 2*x1**2 - 1.5*x1 - 0.05
return np.array([f0,f1])
def jacobian(fs,xs,h=1.e-4):
n = xs.size
iden = np.identity(n)
Jf = np.zeros((n,n))
fs0 = fs(xs)
for j in range(n):
fs1 = fs(xs+iden[:,j]*h)
Jf[:,j] = (fs1 - fs0)/h
return Jf, fs0
def multi_newton(fs,jacobian,xolds,kmax=200,tol=1.e-8):
for k in range(1,kmax):
Jf, fs_xolds = jacobian(fs, xolds)
xnews = xolds + gauelim_pivot(Jf, -fs_xolds)
err = termcrit(xolds,xnews)
print(k, xnews, err)
if err < tol:
break
xolds = np.copy(xnews)
else:
xnews = None
return xnews
if __name__ == '__main__':
xolds = np.array([1.,1.])
xnews = multi_newton(fs,jacobian,xolds)
print(xnews); print(fs(xnews))
# golden.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from bisection import f as phi
from math import sqrt
def golden(phi, x0, x1, kmax=200, tol=1.e-8):
varphi = 0.5*(1 + sqrt(5))
for k in range(1,kmax):
x2 = x0 + (x1-x0)/(varphi+1)
x3 = x0 + (x1-x0)*varphi/(varphi+1)
if phi(x3) < phi(x2):
x0 = x2
else:
x1 = x3
xnew = (x0+x1)/2
xdiff = abs(x1-x0)
rowf = "{0:2d} {1:1.16f} {2:1.16f} {3:1.16f}"
print(rowf.format(k, xnew, xdiff, phi(xnew)))
if abs(xdiff) < tol:
break
else:
xnew = None
return xnew
if __name__ == '__main__':
val = golden(phi,0.,3.5); print(val)
# descent.py
# # Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from jacobi import termcrit
import numpy as np
def phi(xs):
x0, x1 = xs
return x0**2 - 2*x0 + x1**4 - 2*x1**2 + x1
def gradient(phi,xs,h=1.e-6):
n = xs.size
phi0 = phi(xs)
Xph = (xs*np.ones((n,n))).T + np.identity(n)*h
grad = (phi(Xph) - phi0)/h
return grad
def descent(phi,gradient,xolds,gamma=0.15,kmax=200,tol=1.e-8):
for k in range(1,kmax):
xnews = xolds - gamma*gradient(phi,xolds)
err = termcrit(xolds,xnews)
print(k, xnews, err, phi(xnews))
if err < tol:
break
xolds = np.copy(xnews)
else:
xnews = None
return xnews
if __name__ == '__main__':
xolds = np.array([2.,0.25])
xnews = descent(phi, gradient, xolds)
print(xnews)
# powell.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from jacobi import termcrit
from golden import golden
from descent import phi
import numpy as np
def powell(phi,xolds,nreset=4,cycmax=200,tol=1.e-8):
n = xolds.size
for icyc in range(cycmax):
xnews = np.copy(xolds)
if icyc%nreset==0:
U = np.identity(n)
for k in range(n):
ga = golden(lambda g: phi(xnews+g*U[:,k]),-10.,+10.)
xnews += ga*U[:,k]
U[:,:-1] = U[:,1:]
U[:,-1] = xnews - xolds
ga = golden(lambda g: phi(xolds+g*U[:,-1]),-10.,+10.)
xolds += ga*U[:,-1]
err = termcrit(xolds,xnews)
#print(icyc, xnews, err, phi(xnews))
if err < tol:
break
else:
xnews = None
return xnews
if __name__ == '__main__':
xolds = np.array([2.,0.25])
xnews = powell(phi, xolds); print(xnews)
# action.py
# Author: Alex Gezerlis
# Numerical Methods in Physics with Python (2nd ed., CUP, 2023)
from multi_newton import multi_newton
import numpy as np
def params():
nvar = 99; m = 1.
xini, xfin = 2., 0.
tt = 1.; dt = tt/(nvar+1)
return nvar, m, xini, xfin, dt
def fod(der,x):
return -x**3 if der==0 else -3*x**2
def actfs(xs):
nvar, m, xini, xfin, dt = params()
arr = np.zeros(nvar)
arr[0] = (m/dt)*(2*xs[0]-xini-xs[1]) + dt*fod(0,xs[0])
arr[1:-1] = (m/dt)*(2*xs[1:-1] - xs[:-2] - xs[2:])
arr[1:-1] += dt*fod(0,xs[1:-1])
arr[-1] = (m/dt)*(2*xs[-1]-xs[-2]-xfin) + dt*fod(0,xs[-1])
return arr
def actjac(actfs,xs):
nvar, m, xini, xfin, dt = params()
Jf = np.zeros((nvar,nvar))
np.fill_diagonal(Jf, 2*m/dt + fod(1,xs)*dt)
np.fill_diagonal(Jf[1:,:], -m/dt)
np.fill_diagonal(Jf[:,1:], -m/dt)
actfs_xs = actfs(xs)
return Jf, actfs_xs
if __name__ == '__main__':
nvar, m, xini, xfin, dt = params()
xolds = np.array([2-0.02*i for i in range(1,nvar+1)])
xnews = multi_newton(actfs, actjac, xolds); print(xnews)