Skip to content

Commit d392ddb

Browse files
committed
sync up
1 parent 5399821 commit d392ddb

1 file changed

Lines changed: 19 additions & 47 deletions

File tree

playground/2D_Cranky.py

Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import numpy as np
22
import matplotlib.pyplot as plt
3-
from scipy.sparse import diags, kron, eye, csr_matrix
3+
from scipy.sparse import diags
44
from scipy.sparse.linalg import spsolve
55
from matplotlib.animation import FuncAnimation
66

7-
# Global Constants - STABLE VERSION
7+
# Global Constants
88
xLength = 10
99
yLength = 10
1010
maxTime = 0.5
@@ -27,7 +27,7 @@
2727
# Crank-Nicolson parameters (following your notes)
2828
c = diffusivityConstant * timeStepSize / 2 # Note: factor of 2 for Crank-Nicolson
2929
cx = c / (spaceStepSize**2)
30-
cy = c / (spaceStepSize**2) # Same as cx since dx = dy
30+
cy = c / (spaceStepSize**2)
3131
alpha = 1 + 2*cx + 2*cy
3232
beta = 1 - 2*cx - 2*cy
3333

@@ -38,20 +38,10 @@
3838

3939
# Initial condition - a hot spot in the center
4040
u0 = lambda x, y: 10 * np.exp(-((x - xLength/2)**2 + (y - yLength/2)**2) / 2)
41-
42-
# Boundary conditions based on your MATLAB code
43-
44-
# left = @(t,y) 20 + 10*y*(Ly-y)*t^2;
4541
left = lambda t, y: 20 + 10 * y * (yLength - y) * t**2
46-
47-
# right = @(t, y) 20 + 100*y*(Ly-y)^3*(t-1)^2*(t>1);
4842
right = lambda t, y: 20 + 100 * y * (yLength - y)**3 * (t - 1)**2 * (t > 1)
49-
50-
# up = @(t, x) 20 + 5*x*(Lx-x)*t^4;
5143
top = lambda t, x: 20 + 5 * x * (xLength - x) * t**4
52-
53-
# down = @(t, x) 20;
54-
bottom = lambda t, x: 20 # Warm top boundary
44+
bottom = lambda t, x: 20
5545

5646
def initMatrix(t_nodes, x_nodes, y_nodes, left, right, bottom, top, u0, xDomain, yDomain, tDomain):
5747
"""Initialize matrix with boundary and initial conditions"""
@@ -80,29 +70,26 @@ def initMatrix(t_nodes, x_nodes, y_nodes, left, right, bottom, top, u0, xDomain,
8070

8171
def build_2d_crank_nicolson_matrix(nx, ny, cx, cy):
8272
"""
83-
Build G matrix for (I - c*Δ)U_{τ+1} = (I + c*Δ)U_τ
84-
Following notes: -cx*U[i-1,j] + α*U[i,j] - cx*U[i+1,j] - cy*U[i,j-1] - cy*U[i,j+1] = RHS
73+
Build sparse matrix G for: -cx*U[i-1,j] + α*U[i,j] - cx*U[i+1,j] - cy*U[i,j-1] - cy*U[i,j+1] = RHS
8574
"""
86-
n_interior_x = nx - 2 # Exclude boundaries
75+
n_interior_x = nx - 2
8776
n_interior_y = ny - 2
8877
n_total = n_interior_x * n_interior_y
8978

90-
alpha = 1 + 2*cx + 2*cy
91-
92-
# Build diagonals for the sparse matrix
79+
# Main diagonal: α coefficients
9380
main_diagonal = np.full(n_total, alpha)
9481

95-
# x-direction coupling (±1 in flattened index)
82+
# x-direction coupling: -cx coefficients (±1 in flattened index)
9683
x_off_diagonal = np.full(n_total - 1, -cx)
9784
# Zero out connections across y-boundaries
9885
for i in range(n_interior_x - 1, n_total - 1, n_interior_x):
9986
if i < len(x_off_diagonal):
10087
x_off_diagonal[i] = 0
10188

102-
# y-direction coupling (±n_interior_x in flattened index)
89+
# y-direction coupling: -cy coefficients (±n_interior_x in flattened index)
10390
y_off_diagonal = np.full(n_total - n_interior_x, -cy)
10491

105-
# Assemble matrix
92+
# Assemble sparse matrix
10693
diagonals = [y_off_diagonal, x_off_diagonal, main_diagonal,
10794
x_off_diagonal[:n_total-1], y_off_diagonal]
10895
offsets = [-n_interior_x, -1, 0, 1, n_interior_x]
@@ -112,42 +99,30 @@ def build_2d_crank_nicolson_matrix(nx, ny, cx, cy):
11299
return G, n_interior_x, n_interior_y
113100

114101
def calculateTemperatureCN(U):
115-
"""
116-
Crank-Nicolson time stepping: (I - c*Δ)U_{τ+1} = (I + c*Δ)U_τ + boundary_terms
117-
"""
102+
"""Crank-Nicolson time stepping"""
118103
nx, ny = numPointsSpace, numPointsSpace
119-
beta = 1 - 2*cx - 2*cy
120104

121105
G, n_interior_x, n_interior_y = build_2d_crank_nicolson_matrix(nx, ny, cx, cy)
122106

123107
for tau in range(numPointsTime - 1):
124-
# Extract interior points from previous time step
125-
# u_prev_interior = U[tau, 1:-1, 1:-1]
126-
127-
# Build RHS: (I + c*Δ)U_τ + boundary contributions
128108
rhs = np.zeros(n_interior_x * n_interior_y)
129109

130110
idx = 0
131-
for j in range(1, ny-1): # j is y-index
132-
for i in range(1, nx-1): # i is x-index
133-
# Main term: β*U_τ (comes from (1 - 2cx - 2cy)*U_τ)
111+
for j in range(1, ny-1):
112+
for i in range(1, nx-1):
113+
# RHS = β*U_τ + cx*(neighbors_x) + cy*(neighbors_y) + boundary_terms
134114
rhs[idx] = beta * U[tau, i, j]
135-
136-
# Explicit part: +c*Δ*U_τ
137-
# x-direction: +cx*(U[i-1,j] + U[i+1,j]) from previous time
138115
rhs[idx] += cx * (U[tau, i-1, j] + U[tau, i+1, j])
139-
# y-direction: +cy*(U[i,j-1] + U[i,j+1]) from previous time
140116
rhs[idx] += cy * (U[tau, i, j-1] + U[tau, i, j+1])
141117

142-
# Implicit boundary contributions (known at τ+1)
143-
# These come from -c*Δ*U_{τ+1} where boundary values are known
144-
if i == 1: # Left boundary
118+
# Boundary contributions
119+
if i == 1:
145120
rhs[idx] += cx * U[tau+1, 0, j]
146-
if i == nx-2: # Right boundary
121+
if i == nx-2:
147122
rhs[idx] += cx * U[tau+1, -1, j]
148-
if j == 1: # Bottom boundary
123+
if j == 1:
149124
rhs[idx] += cy * U[tau+1, i, 0]
150-
if j == ny-2: # Top boundary
125+
if j == ny-2:
151126
rhs[idx] += cy * U[tau+1, i, -1]
152127

153128
idx += 1
@@ -207,8 +182,5 @@ def animate(k):
207182
return plot_surface(tempMatrix[k], k, ax)
208183

209184
anim = FuncAnimation(fig, animate, interval=100, frames=min(numPointsTime, 200), repeat=True)
210-
211-
# Optionally save animation
212185
anim.save("heat_equation_2d_crank_nicolson.gif", writer='pillow', fps=10)
213-
214186
plt.show()

0 commit comments

Comments
 (0)