import numpy as np import matplotlib.pyplot as plt import torch import torch.nn as nn import torch.optim as optim # ========================================================== # SETTINGS # ========================================================== torch.manual_seed(42) np.random.seed(42) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print("Device:", device) # ========================================================== # PHYSICAL PARAMETERS # ========================================================== L = 1.0; alpha = 0.01; T_left = 100.0; T_right = 0.0; T_max = 10.0 # ========================================================== # ANALYTICAL SOLUTION # ========================================================== def analytical_solution(x, t, n_terms=300): x = np.asarray(x) steady = 100.0 * (1.0 - x) transient = np.zeros_like(x, dtype=np.float64) for n in range(1, n_terms + 1): transient += ( -200.0/(n*np.pi) * np.sin(n*np.pi*x) * np.exp( -alpha*(n*np.pi)**2*t ) ) return steady + transient # ========================================================== # CRANK NICOLSON SOLVER # ========================================================== def crank_nicolson(): Nx = 101; Nt = 1000 dx = L/(Nx-1) dt = T_max/(Nt-1) r = alpha*dt/dx**2 x = np.linspace(0,L,Nx) t = np.linspace(0,T_max,Nt) u = np.zeros((Nt,Nx)) u[:,0] = T_left u[:,-1] = T_right N = Nx-2 A = np.zeros((N,N)) B = np.zeros((N,N)) for i in range(N): A[i,i] = 1+r B[i,i] = 1-r if i>0: A[i,i-1] = -r/2 B[i,i-1] = r/2 if i