欢迎光临
我们一直在努力

OpenFOAM: fvOptions框架详解

文章目录

    • OpenFOAM `fvOptions` 框架详解:CFD 中的原生插件系统
    • 一、核心架构设计
      • 1. 三层架构
      • 2. 关键类关系
      • 3. 三种插件类型
    • 二、内置插件使用示例
      • 案例1:风机盘模型(`actuationDiskSource`)
      • 案例2:局部热源(`scalarSemiImplicitSource`)
      • 案例3:运行时编译自定义源项(`codedSource`)
    • 三、开发自定义 fvOption 插件(完整流程)
      • 步骤1:创建插件目录结构
      • 步骤2:实现插件类(`myCustomSource.H`)
      • 步骤3:实现核心逻辑(`myCustomSource.C`)
      • 步骤4:编译规则(`Make/files`)
      • 步骤5:编译与使用
    • 四、高级特性:运行时动态控制
      • 1. 运行时重载配置(v2312+)
      • 2. 插件间数据交换
      • 3. 优先级控制
    • 五、与通用 Fortran 插件系统的对比
    • 六、典型工业应用场景
    • 七、最佳实践建议

OpenFOAM fvOptions 框架详解:CFD 中的原生插件系统

fvOptions 是 OpenFOAM 内置的、生产级的插件架构,自 v2.2 (2013) 引入 [[3]],专为在不修改求解器源码的前提下向控制方程动态注入物理模型而设计。它本质上是一个运行时可选择(run-time selectable)的有限体积选项框架,完美契合插件化需求。


一、核心架构设计

1. 三层架构

┌─────────────────────────────────────────────────────┐
│ 求解器 (e.g., pisoFoam, buoyantSimpleFoam) │
│ fvOptions(optionList) → operator()(eqn) │
└───────────────┬─────────────────────────────────────┘
│ 调用接口
┌───────────────▼─────────────────────────────────────┐
│ fv::optionList (插件管理器) │
│ • 按优先级排序插件 │
│ • 管理区域选择 (cellZone/cellSet) │
│ • 调度插件执行 (pre/post/apply) │
└───────────────┬─────────────────────────────────────┘
│ 派发到具体插件
┌───────────────▼─────────────────────────────────────┐
│ 具体 fvOption 插件 (继承 fv::option) │
│ • Sources: 源项 (actuationDiskSource) │
│ • Constraints: 约束 (fixedTemperatureConstraint) │
│ • Corrections: 修正 (porosityModel) │
└─────────────────────────────────────────────────────┘

2. 关键类关系

class fv::option // 抽象基类:定义插件接口
{
virtual void addSup(fvMatrix<scalar>& eqn, ...) = 0; // 显式源项
virtual void addSup(fvMatrix<vector>& eqn, ...) = 0;
virtual void constrain(fvMatrix<scalar>& eqn) = 0; // 约束(如固定值)
virtual bool read(const dictionary& dict); // 运行时重载配置
};

class fv::optionList : public PtrList<fv::option> // 插件容器
{
// 重载 () 运算符:求解器通过 fvOptions() 调用
template<class Type>
tmp<fvMatrix<Type>> operator()(fvMatrix<Type>& eqn) const;
};

3. 三种插件类型

类型作用典型应用调用时机
Sources 向方程添加源项 风机盘、热源、化学反应 addSup() – 求解前
Constraints 强制约束解 固定温度、速度边界 constrain() – 求解后修正
Corrections 修正通量/梯度 多孔介质阻力 correct() – 通量修正阶段

💡 关键特性:插件通过 selectionMode 精确控制作用区域(cellZone/cellSet/points/all),实现空间局部化 [[1]]。


二、内置插件使用示例

案例1:风机盘模型(actuationDiskSource)

场景:模拟风力机对流场的推力作用,无需几何建模

constant/fvOptions 配置:

actuationDisk1
{
type actuationDiskSource; // 插件类型(运行时选择)
active true; // 启用开关

selectionMode cellSet; // 作用区域:cellSet
cellSet actuationDiskZone; // 区域名称

fields (U); // 作用于速度场 U

actuationDiskSourceCoeffs
{
diskDir (–1 0 0); // 盘面法向(来流反向)
Cp 0.8; // 功率系数
Ct 0.6; // 推力系数
diskArea 12.566; // 盘面积 π*2²
upstreamPoint (–5 0 0); // 盘上游参考点
upstreamCellSet upstreamCells; // 上游监测区域(用于速度采样)
}
}

求解器集成(以 pisoFoam 为例):

// pisoFoam.C 片段
fvVectorMatrix UEqn
(
fvm::ddt(U)
+ fvm::div(phi, U)
– fvm::laplacian(nu, U)
);
UEqn.relax();

// === 关键:自动注入所有注册的 fvOption ===
fvOptions.constrain(UEqn); // 约束类插件(如固定速度)
UEqn.solve();

// 动量方程求解后,源项类插件自动生效
fvOptions.correct(U); // 修正类插件(如多孔介质)

效果:在 actuationDiskZone 区域内,速度方程自动添加推力源项

−

1

2

ρ

C

T

A

U

2

-\\frac{1}{2}\\rho C_T A U^2

−21​ρCT​AU2,无需修改 pisoFoam 源码 [[30]]。


案例2:局部热源(scalarSemiImplicitSource)

场景:电子设备散热模拟,芯片区域添加 100W 热源

constant/fvOptions 配置:

heatSource1
{
type scalarSemiImplicitSource;
active true;

selectionMode cellZone; // 作用区域:cellZone
cellZone chipZone; // 芯片区域

fields (h); // 作用于焓场 h

scalarSemiImplicitSourceCoeffs
{
volumeMode absolute; // 模式:absolute=总功率, specific=单位体积
injectionRateSuSp
{
h (100 0); // (源强, 系数) → 100W 恒定热源
}
}
}

物理意义:

  • volumeMode absolute:总功率 100W 均匀分布到 chipZone 所有网格 [[40]]
  • injectionRateSuSp (h (100 0)):源项形式

    S

    =

    S

    u

    +

    S

    p

    ⋅

    h

    S = S_u + S_p \\cdot h

    S=Su​+Sp​⋅h,此处

    S

    u

    =

    100

    S_u=100

    Su​=100,

    S

    p

    =

    0

    S_p=0

    Sp​=0(显式源项)

  • 若设为 (100 -10) 则为半隐式:

    S

    =

    100

    −

    10

    ⋅

    h

    S = 100 – 10 \\cdot h

    S=100−10⋅h,提升稳定性


案例3:运行时编译自定义源项(codedSource)

场景:快速原型开发,无需编译独立库

constant/fvOptions 配置:

customSource1
{
type codedSource;
active true;

selectionMode all; // 作用于全场

fields (U); // 作用于速度场

// === 内嵌 C++ 代码(运行时自动编译)===
codeInclude
#{
#include "fvMatrix.H"
#};

codeCorrect
#{
Pout<< "Custom source applied at time " << mesh.time().value() << endl;
#};

codeAddSup
#{
const scalar magU = mag(U).internalField();
const vectorField& C = mesh.C().internalField();

// 添加与速度平方成正比的阻力:F = -0.1 * |U| * U
forAll(C, i)
{
if (magU[i] > 0.1) // 仅当速度>0.1m/s时生效
{
eqn.source()[i] -= 0.1 * magU[i] * U[i] * mesh.V()[i];
}
}
#};

codeSetValue // 约束类插件使用
#{
// 固定特定区域速度
#};
}

工作流程:

  • 首次运行时,OpenFOAM 自动将 codeAddSup 等代码段写入临时 .C 文件
  • 调用 wmake 编译为动态库 libcustomSource1.so
  • 通过 dlopen 加载并注册到 fv::optionList
  • 后续运行直接加载已编译库,无性能损失 [[11]]
  • ⚠️ 注意:codedSource 适合快速验证,生产环境建议开发独立插件(见下文)。


    三、开发自定义 fvOption 插件(完整流程)

    步骤1:创建插件目录结构

    $FOAM_USER_SRC/fvOptions/myCustomSource/
    ├── myCustomSource.H # 头文件
    ├── myCustomSource.C # 实现文件
    ├── createFields.H # (可选)创建插件私有场
    └── Make/
    ├── files # 编译规则
    └── options # 依赖库

    步骤2:实现插件类(myCustomSource.H)

    #ifndef myCustomSource_H
    #define myCustomSource_H

    #include "fvOption.H" // 基类

    namespace Foam
    {
    namespace fv
    {

    class myCustomSource
    :
    public option // 继承 fv::option
    {
    // 私有数据成员
    scalar strength_; // 源项强度
    vector direction_; // 方向向量
    scalarField alpha_; // 空间权重场(预计算)

    // 私有方法
    void calculateAlpha(); // 计算空间分布

    public:
    // 运行时类型信息(关键:实现插件注册)
    TypeName("myCustomSource");

    // 构造函数
    myCustomSource
    (
    const word& name,
    const word& modelType,
    const dictionary& dict,
    const fvMesh& mesh
    );

    // 重载基类虚函数
    virtual void addSup
    (
    fvMatrix<vector>& eqn,
    const label fieldi
    );

    virtual bool read(const dictionary& dict); // 支持运行时重载
    };

    } // End namespace fv
    } // End namespace Foam

    #endif

    步骤3:实现核心逻辑(myCustomSource.C)

    #include "myCustomSource.H"
    #include "fvMatrices.H"
    #include "DimensionedField.H"

    // 注册到运行时选择表(关键:使插件可被 fvOptions 识别)
    makeFvOption(myCustomSource);

    namespace Foam
    {
    namespace fv
    {

    myCustomSource::myCustomSource
    (
    const word& name,
    const word& modelType,
    const dictionary& dict,
    const fvMesh& mesh
    )
    :
    option(name, modelType, dict, mesh),
    strength_(dict.get<scalar>("strength")),
    direction_(dict.get<vector>("direction"))
    {
    // 从 dict 读取区域选择(自动处理 cellZone/cellSet)
    read(dict);

    // 预计算空间权重(如高斯分布)
    calculateAlpha();
    }

    void myCustomSource::calculateAlpha()
    {
    // 根据 selectionMode 获取作用单元
    const labelList& cells = cells_;

    alpha_.setSize(mesh_.nCells(), 0.0);
    forAll(cells, i)
    {
    label celli = cells[i];
    const vector& C = mesh_.C()[celli];
    // 高斯分布:中心在 (0.5,0.5,0),标准差 0.1
    scalar dx = C.x() – 0.5;
    scalar dy = C.y() – 0.5;
    alpha_[celli] = exp(–(dx*dx + dy*dy) / (2.0*0.1*0.1));
    }
    }

    // 重载:向矢量方程添加源项
    void myCustomSource::addSup
    (
    fvMatrix<vector>& eqn,
    const label fieldi
    )
    {
    // 仅作用于指定场(如 U)
    if (fieldNames_[fieldi] != "U") return;

    const labelList& cells = cells_;
    forAll(cells, i)
    {
    label celli = cells[i];
    // 源项 = 强度 * 方向 * 空间权重 * 体积
    eqn.source()[celli] += strength_ * direction_ * alpha_[celli] * mesh_.V()[celli];
    }
    }

    // 支持运行时重载配置(OpenFOAM v2312+ 增强)
    bool myCustomSource::read(const dictionary& dict)
    {
    if (option::read(dict))
    {
    strength_ = dict.get<scalar>("strength");
    direction_ = dict.get<vector>("direction");
    calculateAlpha(); // 重算空间分布
    return true;
    }
    return false;
    }

    } // End namespace fv
    } // End namespace Foam

    步骤4:编译规则(Make/files)

    myCustomSource.C

    LIB = $(FOAM_USER_LIBBIN)/libmyFvOptions

    Make/options:

    EXE_INC = \\
    -I$(LIB_SRC)/finiteVolume/lnInclude \\
    -I$(LIB_SRC)/fvOptions/lnInclude

    LIB_LIBS = \\
    -lfiniteVolume \\
    -lfvOptions

    步骤5:编译与使用

    # 编译插件
    cd $FOAM_USER_SRC/fvOptions/myCustomSource
    wmake libso

    # 在 case 中启用
    echo "libs (\\"libmyFvOptions.so\\");" >> system/controlDict

    # 配置 fvOptions
    cat > constant/fvOptions << EOF
    mySource1
    {
    type myCustomSource; // 运行时通过 TypeName 匹配
    active true;
    selectionMode all;
    strength 10.0; // 自定义参数
    direction (1 0 0);
    }
    EOF

    # 运行求解器(自动加载插件)
    pisoFoam


    四、高级特性:运行时动态控制

    1. 运行时重载配置(v2312+)

    OpenFOAM v2312 支持 运行时更新区域选择 [[5]]:

    // 在求解器循环中
    if (runTime.timeIndex() % 100 == 0)
    {
    // 动态修改源项强度
    dictionary newDict = fvOptions.dict().subDict("mySource1");
    newDict.set("strength", 20.0);
    fvOptions.read(newDict); // 触发插件 read() 重载
    }

    2. 插件间数据交换

    通过 mesh.thisDb().lookupObject<volScalarField>("T") 访问其他插件生成的场,实现插件协作链:

    温度源项插件 → 生成 T_field → 湍流源项插件读取 T_field → 计算浮力源项

    3. 优先级控制

    在 fvOptions 字典中通过 priority 字段控制执行顺序:

    sourceA { priority 10; ... } // 先执行
    sourceB { priority 20; ... } // 后执行


    五、与通用 Fortran 插件系统的对比

    特性OpenFOAM fvOptions通用 Fortran 插件系统
    集成度 深度集成求解器框架,自动调度 需手动在求解循环中插入触发点
    区域管理 内置 selectionMode(cellZone/cellSet) 需自行实现网格遍历逻辑
    类型安全 通过模板 fvMatrix<Type> 保证 依赖 c_funptr + 手动类型转换
    配置驱动 原生支持 dictionary 运行时重载 需额外解析 JSON/YAML
    调试支持 Pout/Info 自动关联时间步 需自行实现日志路由
    跨平台 仅限 OpenFOAM 生态 通用(Linux/Windows)
    学习曲线 需掌握 OpenFOAM 对象模型 仅需 ISO_C_BINDING 基础

    💡 建议:在 OpenFOAM 项目中优先使用 fvOptions,避免重复造轮子;通用 Fortran 插件系统适用于非 OpenFOAM 的 HPC 代码(如自研求解器)。


    六、典型工业应用场景

  • 风电场仿真:

    • actuationDiskSource 模拟多台风机(避免几何建模)
    • radialActuationDiskSource 支持径向变化的推力分布 [[24]]
  • 电子散热:

    • scalarSemiImplicitSource 添加芯片热源
    • fixedTemperatureConstraint 固定散热器温度
  • 燃烧模拟:

    • 自定义 chemistrySource 插件实现简化化学反应
    • 与 reactingFoam 求解器无缝集成
  • 多孔介质:

    • porosityModel 修正动量方程(Darcy-Forchheimer 阻力)
    • thermalPorosity 添加热传导修正
  • 主动流动控制:

    • syntheticJetSource 模拟合成射流(周期性源项)
    • 通过 codedSource 快速验证控制律

  • 七、最佳实践建议

  • 优先使用内置插件:actuationDiskSource, semiImplicitSource 已高度优化
  • 开发独立插件而非 codedSource:提升可维护性和团队协作
  • 利用 selectionMode all + 空间权重:避免创建额外的 cellSet
  • 半隐式源项提升稳定性:SuSp(Su, Sp) 中

    S

    p

    <

    0

    S_p<0

    Sp​<0 可增强对角占优

  • 监控插件贡献:在 addSup() 中累加源项积分,输出到 log 文件
  • 版本兼容性:v2006+ 的 fvOptions API 有变动,开发前检查目标版本文档 [[8]]
  • 🔍 深入学习:参考 $FOAM_SRC/fvOptions 源码,重点阅读:

    • sources/general/semiImplicitSource/:通用源项模板
    • sources/derived/actuationDiskSource/:复杂物理模型实现
    • constraints/fixedTemperature/:约束类插件范例

    通过 fvOptions,OpenFOAM 实现了高度模块化、可扩展的物理模型注入机制,是 CFD 领域插件化架构的典范设计,完全满足用户对"在程序特定位置执行计算"的精细化控制需求。

    赞(0)
    未经允许不得转载:171主机测评 » OpenFOAM: fvOptions框架详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址