扩散 Fick定律 热传导 LBM
扩散是无处不在的物理过程:墨水在水中扩散、热量在金属中传导、信息在社交网络中传播。它们都遵循相同的数学框架——扩散方程。
扩散方程(Fick第二定律):
∂c/∂t = D∇²c
其中 c = 浓度/温度/信息密度,D = 扩散系数
离散化:c_i(t+1) = c_i(t) + D·Δt/Δx² × Σ_neighbors(c_j - c_i)
// ============================================================================
// diffusion_ca.v - 扩散过程CA引擎
// 使用定点数表示浓度,Moore邻域Laplacian
// 支持多种边界条件和源项
// ============================================================================
module diffusion_ca #(
parameter WIDTH = 64,
parameter HEIGHT = 64,
parameter FRAC_W = 8, // 小数部分位宽
parameter [15:0] DIFF_COEFF = 16'h0100 // 扩散系数 D (8.8定点)
)(
input wire clk,
input wire rst_n,
input wire enable,
input wire init,
// 浓度输入(8位整数+8位小数 = 16位/元胞)
output wire [WIDTH*HEIGHT*16-1:0] concentration,
output wire [31:0] step_count,
output wire [15:0] total_mass // 总质量守恒验证
);
// 每格点16位浓度(8.8定点)
reg [15:0] conc [0:WIDTH*HEIGHT-1];
reg [15:0] conc_nxt [0:WIDTH*HEIGHT-1];
reg [31:0] steps;
integer idx, x, y;
reg signed [19:0] laplacian; // 20位有符号,足够容纳累加
always @(*) begin
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
x = idx % WIDTH;
y = idx / WIDTH;
// 计算Laplacian: Σ(c_neighbor - c_center)
laplacian = 0;
// 8个Moore邻居
if (y > 0) begin
laplacian = laplacian + $signed({1'b0, conc[(y-1)*WIDTH+x]}) - $signed({1'b0, conc[idx]});
if (x > 0) laplacian = laplacian + $signed({1'b0, conc[(y-1)*WIDTH+x-1]}) - $signed({1'b0, conc[idx]});
if (x < WIDTH-1) laplacian = laplacian + $signed({1'b0, conc[(y-1)*WIDTH+x+1]}) - $signed({1'b0, conc[idx]});
end
if (y < HEIGHT-1) begin
laplacian = laplacian + $signed({1'b0, conc[(y+1)*WIDTH+x]}) - $signed({1'b0, conc[idx]});
if (x > 0) laplacian = laplacian + $signed({1'b0, conc[(y+1)*WIDTH+x-1]}) - $signed({1'b0, conc[idx]});
if (x < WIDTH-1) laplacian = laplacian + $signed({1'b0, conc[(y+1)*WIDTH+x+1]}) - $signed({1'b0, conc[idx]});
end
if (x > 0) laplacian = laplacian + $signed({1'b0, conc[y*WIDTH+x-1]}) - $signed({1'b0, conc[idx]});
if (x < WIDTH-1) laplacian = laplacian + $signed({1'b0, conc[y*WIDTH+x+1]}) - $signed({1'b0, conc[idx]});
// 扩散更新: c_new = c + D * laplacian
// D是8.8定点,laplacian是~16位
conc_nxt[idx] = conc[idx] + (laplacian >>> FRAC_W);
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
steps <= 32'd0;
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
conc[idx] <= 16'd0;
end else if (init) begin
steps <= 32'd0;
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
conc[idx] <= 16'd0;
end else if (enable) begin
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
conc[idx] <= conc_nxt[idx];
steps <= steps + 32'd1;
end
end
genvar gi;
generate
for (gi = 0; gi < WIDTH*HEIGHT; gi = gi + 1)
assign concentration[gi*16 +: 16] = conc[gi];
endgenerate
reg [31:0] mass;
always @(*) begin
mass = 0;
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
mass = mass + conc[idx];
end
assign step_count = steps;
assign total_mass = mass[15:0];
endmodule
扩散方程与热传导方程在数学上等价——只需将"浓度"替换为"温度"。
热传导方程:∂T/∂t = α∇²T
其中α是热扩散率
经典问题:正方形区域的稳态温度分布,四边固定不同温度
解析解可用Fourier级数展开
数值方法对比:
1. 前向Euler(显式):c^{n+1} = c^n + D·Δt·∇²c^n
稳定性:D·Δt/Δx² ≤ 0.25 (2D)
优点:简单,每步只需1次评估
缺点:时间步受限制
2. 后向Euler(隐式):c^{n+1} - D·Δt·∇²c^{n+1} = c^n
稳定性:无条件稳定
优点:可以大时间步
缺点:需要解线性方程组(硬件不友好)
3. Crank-Nicolson:c^{n+1} - D·Δt/2·∇²c^{n+1} = c^n + D·Δt/2·∇²c^n
稳定性:无条件稳定
精度:O(Δt²),比Euler的O(Δt)高
硬件实现推荐:前向Euler,因为只需要1次Laplacian计算
// 隐式扩散求解器的简化版 - 用迭代法近似
module diffusion_iterative #(
parameter WIDTH = 64,
parameter HEIGHT = 64,
parameter ITERATIONS = 4
)(
input wire clk,
input wire rst_n,
input wire enable,
input wire [15:0] conc [0:WIDTH*HEIGHT-1],
output wire [15:0] conc_out [0:WIDTH*HEIGHT-1]
);
// Jacobi迭代:c_new[i] = (c[left]+c[right]+c[up]+c[down]) / 4
reg [15:0] buf_a [0:WIDTH*HEIGHT-1];
reg [15:0] buf_b [0:WIDTH*HEIGHT-1];
integer iter, idx, x, y;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 初始化
end else if (enable) begin
// 复制输入到buf_a
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
buf_a[idx] <= conc[idx];
// 迭代
for (iter = 0; iter < ITERATIONS; iter = iter + 1) begin
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
x = idx % WIDTH; y = idx / WIDTH;
buf_b[idx] = (buf_a[(y>0?(y-1)*WIDTH+x:(HEIGHT-1)*WIDTH+x)] +
buf_a[(y0?x-1:WIDTH-1)] +
buf_a[y*WIDTH+(x> 2;
end
for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
buf_a[idx] <= buf_b[idx];
end
end
end
endmodule
扩散的应用:
1. 图像处理:高斯模糊=各向同性扩散,边缘保护平滑=各向异性扩散
2. 热管理:芯片热仿真的核心——每个计算单元产生热量,通过扩散散开
3. 金融数学:Black-Scholes方程本质上是扩散方程
4. 神经科学:神经递质在突触间隙的扩散
在进行CA实验时,科学的方法论至关重要。以下是一些通用的实验指导原则:
实验设计三要素:
系统性地扫描参数空间是理解CA行为的关键技术:
| 参数 | 范围 | 步长 | 测量指标 |
|---|---|---|---|
| 规则号 | 0-255 | 1 | 种群密度/周期 |
| 初始密度 | 0.1-0.9 | 0.1 | 收敛时间 |
| 网格大小 | 16-256 | ×2 | 有限尺寸效应 |
| 边界条件 | 环形/固定/镜像 | 离散 | 边界效应 |
CA实验产生的数据通常是高维的(空间+时间+状态)。有效的可视化对于理解至关重要:
自相关分析:
时间自相关:R(τ) = ⟨n(t)·n(t+τ)⟩ / ⟨n²⟩
空间自相关:C(r) = ⟨n(x)·n(x+r)⟩ / ⟨n²⟩
如果R(τ)以周期T振荡 → 系统有周期T的行为
如果C(r)幂律衰减 → 系统处于临界状态
将CA从理论变为可运行的硬件系统需要解决许多工程细节。以下是基于实践经验的详细指南:
CA系统通常需要多个时钟域:
跨时钟域同步使用双触发器或异步FIFO
| 优化项 | 方法 | 节省量 |
|---|---|---|
| 邻居计数器 | 增量更新替代全加法 | ~40% LUT |
| 状态存储 | BRAM替代分布式RAM | ~60% FF |
| 规则查找 | 硬编码XOR替代MUX | ~75% LUT(XOR规则) |
| 显示输出 | 行缓冲替代全帧缓冲 | ~50% BRAM |
| 边界处理 | 环形替代固定(零开销) | 0 |
CA系统的调试有其特殊性:
为CA引擎建立性能基准:
关键性能指标:
理论峰值PPS = f_clk × W × H(全并行)
实际PPS取决于架构——行缓冲约为理论值的1/H
元胞自动机课程 · 从Conway到Langton到Lattice Gas