Hand-wave / verify_comparison.py
Ahilan Kumaresan
Add all files from psi_solve2: notebooks, verification scripts, and logs
794cdea
import numpy as np
import psi_solve2.functions as f
import sys
# Try importing qmsolve
try:
from qmsolve import Hamiltonian, SingleParticle, init_visualization
except ImportError:
print("Error: qmsolve not found. Please install it via 'pip install qmsolve'")
sys.exit(1)
def run_comparison():
with open("comparison_log.txt", "w") as log_file:
sys.stdout = log_file
print("========================================")
print("CROSS-VERIFICATION: PSI_SOLVE2 vs QMSOLVE")
print("========================================")
# ---------------------------------------------------------
# CASE: Double Well Potential
# V(x) = depth * ( (x-center)**2 - separation )**2
# ---------------------------------------------------------
print("\n[TEST CASE] Double Well Potential")
# Parameters
L = 10.0
N = 512 # QMSolve default is often 512 or similar, let's match
depth = 2.0
separation = 1.0
center = 0.0
m_particle = 1.0
print(f"Parameters: L={L}, N={N}, depth={depth}, separation={separation}, m={m_particle}")
# ---------------------------------------------------------
# 1. Run psi_solve2
# ---------------------------------------------------------
print("\n--- Running psi_solve2 ---")
x_full, dx, x_internal = f.make_grid(L=L, N=N)
# Construct Potential
# Note: functions.V_double_well signature: (x, depth=20, separation=1, center=0.0)
V_internal = f.V_double_well(x_internal, depth=depth, separation=separation, center=center)
# Pad for solver
V_full = np.zeros_like(x_full)
V_full[1:-1] = V_internal
V_full[0] = 1e10
V_full[-1] = 1e10
T = f.kinetic_operator(N, dx, m=m_particle)
E_psi, psi_psi = f.solve(T, V_full, dx)
print(f"psi_solve2 Energies (first 5): {E_psi[:5]}")
# ---------------------------------------------------------
# 2. Run QMSolve
# ---------------------------------------------------------
print("\n--- Running QMSolve ---")
# Define potential function for QMSolve
def double_well(particle):
x = particle.x
return depth * ( (x - center)**2 - separation )**2
# Setup QMSolve
H = Hamiltonian(particles = SingleParticle(m = m_particle),
potential = double_well,
spatial_ndim = 1, N = N, extent = L)
# Diagonalize
eigenstates = H.solve(max_states = 10)
E_qm_eV = eigenstates.energies
# Convert QMSolve (eV) to Hartree
# 1 Hartree = 27.211386 eV
Hartree_to_eV = 27.211386
E_qm = E_qm_eV / Hartree_to_eV
print(f"QMSolve Energies (eV): {E_qm_eV[:5]}")
print(f"QMSolve Energies (Hartree): {E_qm[:5]}")
# ---------------------------------------------------------
# 3. Compare
# ---------------------------------------------------------
print("\n--- Comparison Results ---")
print("-" * 65)
print(f"| n | psi_solve2 E | QMSolve E | Diff | % Diff |")
print("-" * 65)
for i in range(5):
e1 = E_psi[i]
e2 = E_qm[i]
diff = abs(e1 - e2)
p_diff = (diff / e2) * 100 if e2 != 0 else 0.0
print(f"| {i:<1} | {e1:<12.6f} | {e2:<12.6f} | {diff:<12.2e} | {p_diff:<7.4f}% |")
print("-" * 65)
# ---------------------------------------------------------
# DEBUG CASE: Harmonic Oscillator
# ---------------------------------------------------------
print("\n[DEBUG CASE] Harmonic Oscillator (k=1)")
k_debug = 1.0
# psi_solve2
V_internal_HO = 0.5 * k_debug * x_internal**2
V_full_HO = np.zeros_like(x_full)
V_full_HO[1:-1] = V_internal_HO
V_full_HO[0] = 1e10
V_full_HO[-1] = 1e10
E_psi_HO, _ = f.solve(T, V_full_HO, dx)
print(f"psi_solve2 HO Energies: {E_psi_HO[:5]}")
# QMSolve
def harmonic_potential(particle):
return 0.5 * k_debug * particle.x**2
H_HO = Hamiltonian(particles = SingleParticle(m = m_particle),
potential = harmonic_potential,
spatial_ndim = 1, N = N, extent = L)
eigenstates_HO = H_HO.solve(max_states = 10)
E_qm_HO = eigenstates_HO.energies
print(f"QMSolve HO Energies: {E_qm_HO[:5]}")
sys.stdout = sys.__stdout__
if __name__ == "__main__":
run_comparison()