Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
2 views

Assignment 7

The document contains Python code implementing various numerical integration methods, including Romberg integration and Simpson's rule, to estimate integrals of functions. It also includes a section on the quantum harmonic oscillator, detailing the computation and visualization of wavefunctions using Hermite polynomials. Additionally, the document calculates quantum uncertainty for a specific state using Gaussian quadrature methods.

Uploaded by

Sougata Halder
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Assignment 7

The document contains Python code implementing various numerical integration methods, including Romberg integration and Simpson's rule, to estimate integrals of functions. It also includes a section on the quantum harmonic oscillator, detailing the computation and visualization of wavefunctions using Hermite polynomials. Additionally, the document calculates quantum uncertainty for a specific state using Gaussian quadrature methods.

Uploaded by

Sougata Halder
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Assignment-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