1. 一维稳态热传导有限差分建模与验证
问题定义与离散格式
考虑一根长度 L = 1 m 的均质导热棒,导热系数 k = 1 W/(m·K),无内热源。左端 x = 0 保持定温 T₀ = 100 °C,右端 x = L 保持定温 T_L = 0 °C。控制方程为:
d²T/dx² = 0, 0 < x < L
T(0) = T₀, T(L) = T_L
解析解为线性分布 T(x) = T₀ + (T_L − T₀)·x/L。有限差分法将区间等分为 N 个单元,节点间距 Δx = L/N,内部节点 i = 1…N−1 采用中心差分:
(T_{i−1} − 2T_i + T_{i+1}) / Δx² = 0
⇒ T_{i−1} − 2T_i + T_{i+1} = 0
边界节点 T_0 = T₀、T_N = T_L 直接代入,形成三对角线性方程组 A·T = b。由于方程是线性的且边界为第一类(Dirichlet)条件,离散解在节点上应精确等于解析解——这是验证格式与边界处理正确性的关键判据。
Python 实现:组装与求解
下面给出完整可运行代码。核心步骤:生成节点坐标、组装三对角系数矩阵、施加 Dirichlet 边界、用 numpy.linalg.solve 求解,并与解析解逐点比较。
import numpy as np
def solve_1d_steady(N, L=1.0, T0=100.0, TL=0.0):
"""一维稳态热传导有限差分求解,返回节点坐标与温度。"""
dx = L / N
x = np.linspace(0.0, L, N + 1)
n_int = N - 1 # 内部未知量个数
# 组装三对角矩阵 A (n_int × n_int) 与右端向量 b
A = np.zeros((n_int, n_int))
b = np.zeros(n_int)
for i in range(n_int):
A[i, i] = -2.0
if i > 0:
A[i, i - 1] = 1.0
if i < n_int - 1:
A[i, i + 1] = 1.0
# 边界贡献移入右端项
b[0] -= T0 # 左边界 T_0 已知
b[-1] -= TL # 右边界 T_N 已知
T_int = np.linalg.solve(A, b)
T = np.empty(N + 1)
T[0], T[-1] = T0, TL
T[1:-1] = T_int
return x, T
def analytic(x, L=1.0, T0=100.0, TL=0.0):
return T0 + (TL - T0) * x / L
# 验证:不同网格密度下的最大节点误差
for N in [4, 8, 16, 32]:
x, T = solve_1d_steady(N)
err = np.max(np.abs(T - analytic(x)))
print(f"N={N:3d} dx={1.0/N:.4f} max|T_num - T_exact| = {err:.3e}")
预期输出(示例运行结果,非实测):
N= 4 dx=0.2500 max|T_num - T_exact| = 0.000e+00
N= 8 dx=0.1250 max|T_num - T_exact| = 0.000e+00
N= 16 dx=0.0625 max|T_num - T_exact| = 0.000e+00
N= 32 dx=0.0312 max|T_num - T_exact| = 0.000e+00
节点误差为机器精度量级(约 1e-14 以下)说明离散格式与边界处理正确。若出现非零误差,优先检查:① 边界项是否从矩阵移入右端;② 内部节点索引是否覆盖 1…N−1;③ 矩阵对角是否为 −2、邻对角是否为 +1。
边界条件处理的两种写法对比
除上述“消元法”(把边界值移到右端)外,也可保留完整 (N+1)×(N+1) 矩阵并对边界行直接置单位行。两种写法结果一致,但后者更易扩展到 Neumann 或 Robin 边界。下表给出关键差异:
| 写法 | 矩阵规模 | 边界行处理 | 适用场景 |
|---|---|---|---|
| 消元法 | (N−1)×(N−1) | 边界值移入 b | 纯 Dirichlet,追求最小规模 |
| 完整矩阵法 | (N+1)×(N+1) | 边界行置单位行,b 置边界值 | 混合边界、便于统一扩展 |
完整矩阵法核心片段:
A = np.zeros((N + 1, N + 1))
b = np.zeros(N + 1)
for i in range(1, N):
A[i, i-1], A[i, i], A[i, i+1] = 1.0, -2.0, 1.0
A[0, 0] = 1.0; b[0] = T0
A[N, N] = 1.0; b[N] = TL
T = np.linalg.solve(A, b)
精度验证与判据
对第一类边界的一维稳态问题,中心差分格式在节点上无截断误差累积,数值解应与解析解在机器精度内一致。验证时建议同时检查:
- 节点最大绝对误差:应 ≤ 1e-12(双精度)。
- 线性度:相邻节点温差应恒为
(T_L − T₀)/N,可用np.diff(T)检查其标准差。 - 能量守恒:通过任一截面的热流
q = −k·dT/dx应处处相等。
若把边界条件误写成“边界节点也参与中心差分”(即对 i=0 使用 T_{−1}),会引入虚拟节点并导致解偏移。第一类边界必须显式固定边界节点值,不得让其成为未知量。