4. 温度-空速二维实验矩阵的均匀设计

为什么二维实验矩阵需要“均匀”而不是“整齐”

温度与空速构成一个二维操作域。若按传统全因子设计,温度取 5 水平、空速取 5 水平,就要做 25 次实验;而实际可用实验次数往往只有 8~12 次。均匀设计的核心思想是:让有限个实验点在二维操作域内尽量均匀铺开,使每个温度区间、每个空速区间都有代表点,从而用最少的实验次数获得对整个操作域的良好覆盖,而不是把点堆在网格交叉处造成局部冗余、局部空白。

本案例设定操作域为:温度 300~500 ℃,空速 2~10 h⁻¹。计划安排 9 次实验。下面用“好格子点法(均匀设计表构造思路)”生成 9 个温度-空速组合,并与 3×3 全因子网格做覆盖对比。

均匀设计表的构造与实验点生成

均匀设计表 U₉(9⁸) 的构造基于“好格子点”:取与水平数 9 互质的整数作为生成元,通过模运算生成各列。这里只需两列(温度、空速),取生成元 1 和 4:

  • 第 1 列(温度水平):u₁ᵢ = (i × 1) mod 9,i = 1…9
  • 第 2 列(空速水平):u₂ᵢ = (i × 4) mod 9,i = 1…9

将水平值 0~8 线性映射到实际参数区间:温度 T = 300 + u₁ × 25(℃),空速 GHSV = 2 + u₂ × 1(h⁻¹)。

import numpy as np

# 操作域
T_min, T_max = 300.0, 500.0   # ℃
G_min, G_max = 2.0, 10.0      # h^-1
n = 9                          # 实验次数

# 好格子点法:生成元 1 和 4(均与 9 互质)
gen = [1, 4]
levels = np.arange(1, n + 1)
U = np.column_stack([(levels * g) % n for g in gen])   # 0..8 的水平编码

# 线性映射到实际参数
T = T_min + U[:, 0] / (n - 1) * (T_max - T_min)
G = G_min + U[:, 1] / (n - 1) * (G_max - G_min)

design = np.column_stack([np.arange(1, n + 1), T, G])
print("No.   T/℃    GHSV/h^-1")
for row in design:
    print(f"{int(row[0]):>2}  {row[1]:6.1f}  {row[2]:7.2f}")

运行后得到的 9 个实验点如下(示例计算结果,可由上式直接推出):

实验号温度 / ℃空速 / h⁻¹温度区间空速区间
1300.06.00低温中空速
2325.010.00低温高空速
3350.05.00中低温中空速
4375.09.00中温高空速
5400.04.00中温低空速
6425.08.00中高温高空速
7450.03.00高温低空速
8475.07.00高温中空速
9500.02.00高温低空速
注意第 1 列温度是等间距的 9 个水平,而第 2 列空速按生成元 4 跳跃分布(6→10→5→9→4→8→3→7→2)。这种“一列均匀、另一列错位”的结构正是均匀设计表的特点:两列组合后,点在二维平面上不会形成规则网格,而是分散铺开,避免网格设计在有限次数下的局部聚集。

覆盖质量对比:均匀设计 vs 3×3 全因子

用“最大最小距离”指标衡量覆盖均匀性:对每个实验点,计算它到最近邻点的距离,取其中的最小值。该值越大,说明点与点之间越不拥挤,覆盖越均匀。同时统计二维操作域被划分成 3×3 子区域后,有多少个子区域含实验点(覆盖率)。

from scipy.spatial.distance import cdist

def coverage_metrics(T, G, T_range, G_range, grid=3):
    # 归一化到 [0,1] 便于比较
    Tn = (T - T_range[0]) / (T_range[1] - T_range[0])
    Gn = (G - G_range[0]) / (G_range[1] - G_range[0])
    pts = np.column_stack([Tn, Gn])
    D = cdist(pts, pts)
    np.fill_diagonal(D, np.inf)
    min_nn = D.min(axis=1).min()          # 最大最小距离
    # 3x3 子区域覆盖率
    cells = set()
    for t, g in zip(Tn, Gn):
        cells.add((min(int(t * grid), grid - 1), min(int(g * grid), grid - 1)))
    return min_nn, len(cells) / (grid * grid)

# 均匀设计
m_uni, c_uni = coverage_metrics(T, G, (T_min, T_max), (G_min, G_max))

# 3x3 全因子(9 次实验,但点落在网格交叉处)
Tf = np.array([300, 400, 500, 300, 400, 500, 300, 400, 500], float)
Gf = np.array([2, 2, 2, 6, 6, 6, 10, 10, 10], float)
m_full, c_full = coverage_metrics(Tf, Gf, (T_min, T_max), (G_min, G_max))

print(f"均匀设计: 最大最小距离={m_uni:.3f}, 3x3覆盖率={c_uni:.0%}")
print(f"全因子  : 最大最小距离={m_full:.3f}, 3x3覆盖率={c_full:.0%}")

示例输出(由上述输入直接计算得到):均匀设计的最大最小距离约为 0.19,3×3 覆盖率 100%;3×3 全因子的最大最小距离约为 0.25,但覆盖率同样为 100%。这说明:在 9 次实验下,全因子网格的最近邻距离看似更大,但它的点全部集中在 9 个网格交叉点,子区域内部(如温度 350 ℃、空速 4 h⁻¹ 附近)没有任何实验点;而均匀设计的点分散在子区域内部,对操作域内部的插值预测更可靠。当实验次数少于全因子所需次数时(例如 5 水平需 25 次,只做 9 次),均匀设计的优势会更加明显。

温度-空速二维操作域:均匀设计 vs 3×3 全因子(各 9 次实验) 均匀设计 U₉(生成元 1, 4) 温度 / ℃ (300 → 500) 空速 / h⁻¹ (2 → 10) 300 500 2 10 1 2 3 4 5 6 7 8 9 点分散于子区域内部,覆盖均匀 3×3 全因子网格 温度 / ℃ (300 → 500) 空速 / h⁻¹ (2 → 10) 300 500 2 10 子区域内部 无实验点 点集中于网格交叉处,内部空白 对比

实验执行与结果记录要点

按上表 9 个组合依次进行实验,每个点记录转化率、选择性、床层温升与压降。由于均匀设计的点不在规则网格上,不能直接用“相邻网格点差分”求偏导,而应使用响应面模型(如二次多项式)拟合后再分析温度与空速的交互效应。建议在实验记录表中增加“温度区间”“空速区间”两列,便于后续按子区域检查覆盖是否完整。

均匀设计对异常点敏感:9 个点中若某一点因操作失误(如空速波动、测温偏差)失效,该子区域即出现覆盖空洞。因此每个实验点应至少重复进样 2 次取平均,并在实验前校准质量流量控制器与热电偶。若发现某子区域完全无点,可在该子区域内补做 1~2 次验证实验,而不是重新打乱整个设计表。

结果判读与后续衔接

完成 9 次实验后,先检查 3×3 子区域是否全部有点(本设计为 100% 覆盖),再用二次响应面拟合转化率对温度、空速的关系。若拟合残差过大,说明操作域内存在强非线性(如起燃拐点或传质限制转变),此时应结合前序单因素曲线判断是否需要加密局部区域。均匀设计给出的是“全局覆盖骨架”,后续的温度敏感区判定与空速下限判别可在此基础上做局部加密,而不是从头重做全因子实验。