4. 学科分析模型构建

在MDO流程中,各学科分析工具往往由不同团队用不同语言、不同求解器开发:气动用CFD求解器,结构用有限元,控制用MATLAB/Simulink,热用热网络或有限差分。若优化器每次迭代都直接调用这些原始工具,会面临三个致命问题:接口不统一、调用开销巨大、梯度信息缺失。因此,学科分析模型构建的核心任务,是把每个学科分析封装成一个输入输出契约明确、可重复调用、支持灵敏度计算的计算模块。

一、封装的三层结构

一个合格的学科模块通常由三层构成。最内层是求解器层,即原始的CFD、FEM或ODE求解代码;中间层是适配层,负责参数映射、单位换算、网格/模型更新和结果提取;最外层是接口层,向MDO框架暴露统一的调用签名。以气动模块为例,接口层接收设计变量(如机翼后掠角、展弦比、迎角),适配层据此重建几何并生成网格,求解器层执行CFD计算,最后适配层从流场中提取升力系数、阻力系数和结构载荷分布,返回给优化器。

这种分层的关键价值在于:当求解器更换时,只需重写适配层,接口层和优化流程保持不变。工程上常把接口层实现为函数句柄或类方法,例如在MATLAB中定义为 y = aero(x),在Python中定义为 def aero(x): return y,在商业框架中则注册为组件。

二、输入输出契约的定义

封装前必须先定义契约,即明确每个模块的输入向量、输出向量及其物理含义、单位和量纲。这是MDO中最容易被忽视却最影响成败的环节。一个典型的多学科契约如下表所示(示例参数,用于说明格式):

学科模块输入变量(示例)输出变量(示例)单位约定
气动后掠角 Λ、展弦比 AR、迎角 α、马赫数 Ma升力系数 CL、阻力系数 CD、翼根弯矩 Mroot角度用度,力用N,系数无量纲
结构翼根弯矩 Mroot、蒙皮厚度 t、材料弹性模量 E最大应力 σmax、翼尖位移 δtip、结构质量 mstr应力用MPa,位移用mm,质量用kg
控制翼尖位移 δtip、舵面效率、控制增益 Kp/Ki稳定裕度 GM、超调量 σ%、控制功耗 Pctrl裕度用dB,超调用%,功耗用W
热马赫数 Ma、热流密度 q、冷却流量 ṁ壁面温度 Tw、热应力 σth、冷却效率 η温度用K,热流用kW/m²

契约一旦确定,各学科团队即可并行开发,互不阻塞。需要强调的是,输入输出必须无状态:同一组输入无论调用多少次,都应返回相同输出,否则优化器无法收敛。

三、调用与数据流关系

下图展示了一个四学科模块在MDO框架中的封装结构与数据流关系。气动模块的输出同时驱动结构、控制、热三个模块,结构输出又反馈给控制模块,形成耦合链。每个模块内部都包含“适配层→求解器→结果提取”的封装路径。

学科分析模块封装结构与数据流 MDO优化器 / 框架 设计变量 x 气动模块 aero(x) 适配层:几何重建 + 网格生成 求解器:CFD → 提取 CL, CD, Mroot Mroot 结构模块 struct(Mroot, t, E) 适配层:载荷映射 + 边界条件 求解器:FEM → 提取 σmax, δtip, mstr δtip 控制模块 ctrl(δtip, Kp, Ki) 适配层:状态空间装配 求解器:ODE → 提取 GM, σ%, Pctrl 热模块 thermal(Ma, q, ṁ) 适配层:热网络建模 求解器:热差分 → Tw, σth, η Ma, q 输出向量 y = [CL, CD, σmax, δtip, GM, Tw, mstr] 封装三要素 ① 接口层:统一调用签名 y = module(x) ② 适配层:参数映射、单位换算 网格/模型更新、结果提取 ③ 求解器层:原始CFD/FEM/ODE 保持无状态、可重复调用 关键约束: · 输入输出量纲一致 · 支持有限差分/复步长求导 · 异常返回统一错误码

四、灵敏度与梯度封装

MDO优化器若采用梯度算法,模块还必须提供输出对输入的偏导数。工程上有三种做法:有限差分最简单,对每个输入扰动ε(如取1e-4倍设计变量),重新调用模块,用 (y(x+ε)-y(x))/ε 近似梯度,代价是调用次数翻倍;复步长法精度更高,用 Im(y(x+iε))/ε 求导,但要求求解器支持复数运算;解析/伴随法效率最高,需要修改求解器源码,对每个输出只需一次伴随求解即可得到对所有输入的梯度,适合设计变量多、输出少的气动问题。

封装时应在接口层预留梯度开关,例如 [y, dy] = aero(x, 'grad', true),让优化器按需选择。若模块无法提供梯度,则应在框架中标记为“黑箱”,由优化器自动降级为无梯度算法。

五、实操示例:气动模块的封装代码骨架

以下给出一个Python封装骨架(示例,非实测代码),展示适配层如何把设计变量转换为CFD输入并提取结果:

def aero_module(x, grad=False):
    # x = [Lambda, AR, alpha, Ma]
    Lambda, AR, alpha, Ma = x
    # 适配层:重建几何、生成网格
    geom = rebuild_wing(Lambda, AR)
    mesh = generate_mesh(geom, alpha, Ma)
    # 求解器层:调用CFD
    flow = run_cfd(mesh)
    # 结果提取
    CL = extract_lift(flow)
    CD = extract_drag(flow)
    Mroot = extract_root_moment(flow)
    y = np.array([CL, CD, Mroot])
    if grad:
        dy = finite_difference(x, aero_module, eps=1e-4)
        return y, dy
    return y

注意 finite_difference 会递归调用 aero_module,因此模块必须保证无状态,且每次调用都从干净的工作目录开始,避免网格文件或中间结果互相污染。

六、封装质量的判断依据

一个封装好的模块,应满足以下可检验的标准:同一输入连续调用三次,输出差异小于1e-10;输入向量中任一分量扰动1%,输出变化方向符合物理直觉(如迎角增大,CL应增大);模块在异常输入(如负厚度、超范围马赫数)下返回明确错误码而非崩溃;单次调用耗时稳定,且可被并行调度。只有通过这四项检查,模块才真正具备被MDO框架反复调用的资格。

封装不是简单写一个函数,而是建立一份跨学科团队共同遵守的“计算契约”。契约越清晰,后续的耦合、优化和灵敏度分析就越可靠。