0% found this document useful (0 votes)
8 views

Ass 7

The document contains Python code implementing various numerical integration techniques, including Romberg integration, Simpson's rule, and the adaptive trapezoidal rule, along with visualizations of quantum harmonic oscillator wavefunctions. It also includes a Gaussian quadrature method for computing integrals related to quantum mechanics. The results of several integrals and the quantum uncertainty for a specific state are printed at the end.

Uploaded by

Sougata Halder
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Ass 7

The document contains Python code implementing various numerical integration techniques, including Romberg integration, Simpson's rule, and the adaptive trapezoidal rule, along with visualizations of quantum harmonic oscillator wavefunctions. It also includes a Gaussian quadrature method for computing integrals related to quantum mechanics. The results of several integrals and the quantum uncertainty for a specific state are printed at the end.

Uploaded by

Sougata Halder
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Ass 7

March 6, 2025

[25]: import numpy as np


import matplotlib.pyplot as plt
from math import factorial
import numpy as np
from math import factorial, sqrt, pi, tan, cos, sin

[26]: def f(x): return np.sin(x)

# Define a small epsilon to avoid the singularity exactly at pi/2


epsilon = 1e-1
a, b = 0.0, np.pi
# singularity = (np.pi)/2

def romberg_integration(f, a, b, tol=1e-6, max_iter=100):


# Create a list of lists to store Romberg table rows.
R = [[0.5 * (b - a) * (f(a) + f(b))]] # R[0][0] from one trapezoid

n = 1
while n < max_iter:
h = (b - a) / (2**n)
# Compute the trapezoidal rule estimate with 2^n subintervals.
sum_f = sum(f(a + (2 * k - 1) * h) for k in range(1, 2**(n-1) + 1))
Rn0 = 0.5 * R[n-1][0] + h * sum_f
R.append([Rn0])
# Apply Richardson extrapolation to improve the estimate.
for m in range(1, n + 1):
factor = 4**m
Rnm = R[n][m-1] + (R[n][m-1] - R[n-1][m-1]) / (factor - 1)
R[n].append(Rnm)
# Check if the last two estimates have converged.
if abs(R[n][n] - R[n-1][n-1]) < tol:
return R[n][n]
n += 1
# If max_iter is reached, return the best estimate.
return R[n-1][n-1]

# integral1 = romberg_integration(f, a, singularity - epsilon)

1
# integral2 = romberg_integration(f, singularity + epsilon, b)

# total_integral = integral1 + integral2


# print("Improper integral estimate:", total_integral)

approx = round(romberg_integration(f, a, b, tol=1e-8, max_iter=10),4)


print("Romberg integration estimate:", approx)

Romberg integration estimate: 2.0

[27]: # Given data points


x = np.array([0, np.pi/4, np.pi/2, 3*np.pi/4, np.pi])
f_x = np.array([1.0000, 0.3431, 0.2500, 0.3431, 1.0000])

# Step size (since x is evenly spaced)


h = (x[-1] - x[0]) / (len(x) - 1)

# Applying Simpson's 1/3 Rule


integral = (h/3) * (f_x[0] + 4 * sum(f_x[1:-1:2]) + 2 * sum(f_x[2:-2:2]) +␣
↪f_x[-1])

print(f"Estimated integral: {integral:.6f}")

Estimated integral: 1.373085

[29]: # Function to integrate


def f(x, y):
return np.cos((np.pi * x) / 2) * np.cos((np.pi * y) / 2)

# Adaptive Trapezoidal Rule


def adaptive_trapezoidal_2D(f, a, b, c, d, tol=1e-6, max_iter=10):
nx, ny = 2, 2 # Initial number of intervals

def trapezoidal_2D(nx, ny):


x = np.linspace(a, b, nx + 1)
y = np.linspace(c, d, ny + 1)
hx = (b - a) / nx
hy = (d - c) / ny

integral = 0
for i in range(nx + 1):
for j in range(ny + 1):
weight = 1
if i in (0, nx): weight *= 0.5
if j in (0, ny): weight *= 0.5
integral += weight * f(x[i], y[j])

return integral * hx * hy

2
prev_integral = trapezoidal_2D(nx, ny)

for _ in range(max_iter):
nx *= 2
ny *= 2
new_integral = trapezoidal_2D(nx, ny)

# Check for convergence


if abs(new_integral - prev_integral) < tol:
return new_integral

prev_integral = new_integral

return new_integral # Return last computed integral if max_iter is reached

# Compute the integral


result = adaptive_trapezoidal_2D(f, -1, 1, -1, 1)
print(f"Estimated integral: {result:.6f}")

Estimated integral: 1.621138

[30]: # Define the Hermite polynomial recursively


def H(n, x):
if n == 0:
return 1
elif n == 1:
return 2 * x
else:
return 2 * x * H(n - 1, x) - 2 * (n - 1) * H(n - 2, x)

# Define the quantum harmonic oscillator wavefunction


def psi(n, x):
coeff = 1 / np.sqrt(2**n * factorial(n) * np.sqrt(np.pi))
return coeff * np.exp(-x**2 / 2) * H(n, x)

# Generate x values
x_values = np.linspace(-4, 4, 400)

# Compute and plot wavefunctions for n = 0,1,2,3


plt.figure(figsize=(8, 6))

for n in range(4):
y_values = [psi(n, x) for x in x_values]
plt.plot(x_values, y_values, label=f"n = {n}")

# Customize the plot

3
plt.title("Quantum Harmonic Oscillator Wavefunctions")
plt.xlabel("x")
plt.ylabel(r"$\psi_n(x)$")
plt.legend()
plt.grid()
plt.show()

[31]: # Generate x values from -10 to 10


x_values = np.linspace(-10, 10, 500)

# Compute wavefunction for n = 30


y_values = psi(30, x_values)

# Plot the wavefunction for n = 30


plt.figure(figsize=(8, 6))
plt.plot(x_values, y_values, label="n = 30", color="red")
plt.title("Quantum Harmonic Oscillator Wavefunction (n = 30)")
plt.xlabel("x")
plt.ylabel(r"$\psi_{30}(x)$")

4
plt.grid()
plt.legend()
plt.show()

[32]: # Gaussian quadrature functions (provided)


def gaussxw(N):
a = np.linspace(3, 4*N - 1, N) / (4*N + 2)
x = np.cos(pi * a + 1/(8*N*N*np.tan(a)))

epsilon = 1e-15
delta = 1.0
while delta > epsilon:
p0 = np.ones(N)
p1 = np.copy(x)
for k in range(1, N):
p0, p1 = p1, ((2*k+1)*x*p1 - k*p0)/(k+1)
dp = (N+1)*(p0 - x*p1)/(1-x*x)
dx = p1/dp
x -= dx

5
delta = max(abs(dx))

w = 2*(N+1)**2/(N**2 * (1-x*x)*dp*dp)
return x, w

def gaussxwab(N, a, b):


x, w = gaussxw(N)
return 0.5*(b-a)*x + 0.5*(b+a), 0.5*(b-a)*w

# Compute �x²� using Gaussian quadrature with 100 points and the mapping x =␣
↪tan((�/2)*t)

def compute_x2(n):
N = 100 # number of Gaussian quadrature points
t, w = gaussxwab(N, -1, 1) # integration over t in [-1,1]

# Transformation: x = tan((�/2)*t)
x = np.tan((pi/2)*t)
# Jacobian: dx/dt = (�/2)*sec^2((�/2)*t)
dxdt = (pi/2) * (1/np.cos((pi/2)*t)**2)

# The integrand: x² * |�_n(x)|² * dx/dt


integrand = x**2 * (psi(n, x)**2) * dxdt
# Gaussian quadrature sum
integral = np.sum(w * integrand)

return integral

# Calculate the uncertainty √<x²> for n=5


n = 5
x2_avg = compute_x2(n)
uncertainty = sqrt(x2_avg)

print(f"Quantum uncertainty (√�x²�) for n={n}: {uncertainty:.6f}")

Quantum uncertainty (√�x²�) for n=5: 2.345208

[ ]:

You might also like