自定义viscosityModel的实现是基于粘度取决于剪切速率的示例构建的。

以血液作为流体示例,粘度与剪切速率相关的实验数据见[1,图2]。使用engauge数字化仪将[1]中的实验数据数字化为CSV文件,第一列为应变率,第二列为相应的有效动力粘度

注:该示例侧重于在OpenFOAM中实现新的粘度模型,而不是模型的物理正确性。

运动粘度通过除以室温下血液的近似密度得到,如图11.4所示。

图11.4 非牛顿流体的实验有效粘度分布

本示例介绍如何实现一个新的粘度模型类,该模型类读取运动粘度和局部应变率,并返回有效粘度。这种基于数据表的方法与其他更常见的粘度模型形成对比,后者使用应变率与粘度关系的解析表达式。图11.4显示了剪切流变仪的一组测量值示例(有效粘度与应变率)。由于流变仪表中只有离散的数据点,因此必须使用插值方案在它们之间进行插值,并将粘度分配给任何给定的应变率。OpenFOAM提供了可用于此目的基于二维样条的插值:插值XY样条线。此库的源代码可在示例存储库中找到,位于:

ofbook/ofprimer/src/ofBookTransportModels

这里,仅涉及负责粘度计算的虚拟成员函数的实现。源代码中提供了有关实现的更多信息。

新的粘度模型继承了viscosityModel,因此新的粘度模型必须满足清单69中所示的viscosityModel的接口。

//清单69
//- Return the laminar viscosity
virtual tmp<volScalarField>  nu() const = 0;
//- Return the laminar viscosity for patch
virtual tmp<scalarField>  nu(const label patchi) const = 0;
//- Correct the laminar viscosity
virtual void correct() = 0;
//- Read transportProperties dictionary
virtual bool read(const dictionary& viscosityProperties) = 0;

correct成员函数执行运动粘度的计算(更新),而nu成员函数提供访问。

注:在OpenFOAM中,就像在其他大规模面向对象软件中一样,虚函数的替代实现扩展了库的功能。换句话说,在OpenFOAM中扩展库时,要了解虚函数在其他派生类中的作用,因为这些成员函数也很可能在新类中被修改。

粘度模型扩展从viscosityModel的公共继承和私有数据成员的定义开始,这是粘度计算所必需的,如清单70所示。清单70中的私有成员函数loadViscosityTable负责从CSV文件中阅读实验数据,该数据被转换为标量场rheologyTableX和rheologyTableY,用作OpenFOAM中基于样条的插值的输入。

//清单70
class interpolatedSplineViscosityModel
:
    public viscosityModel
{
    // Private data
    //Dictionary for the viscosity model
    dictionary modelDict_;
    //x and y entries of the rheology data for
    // use with the spline interpolator
    fileName dataFileName_;
    scalarField rheologyTableX_;
    scalarField rheologyTableY_;
    tmp<volScalarField>  nuPtr_;
    // Private Member Functions
    // Load the viscosity data table
    void loadViscosityTable();

从viscosityModel继承的纯虚成员函数的声明如清单71所示。运动粘度字段是私有数据成员(包装在tmp智能指针中),因此粘度字段和补丁粘度字段可以轻松返回。因此,模型实现的主要部分在于loadViscosityTable并校正。

// 清单71
//- Return the laminar viscosity
tmp<volScalarField>  nu() const
{
    return nuPtr_;
}
//- Return the laminar viscosity for patch
virtual tmp<scalarField>  nu(const label patchi) const
{
    return nuPtr_-> boundaryField()[patchi];
}
//- Correct the laminar viscosity
virtual void correct();
//- Read transportProperties dictionary
bool read(const dictionary& viscosityProperties);

csvTableReader类用于读取包含图11.4中实验数据的CSV文件。loadViscosityTable在构造函数体中调用一次,在读取成员函数中调用一次。正确的成员函数从每个单元中的viscosityModel获取应变率,然后使用基于样条的插值法从loadViscosityTable读取的实验数据中插值表观运动粘度。清单72概述了实现。

void interpolatedSplineViscosityModel::loadViscosityTable()
{
    csvTableReader<scalar>  reader(modelDict_);
    List<Tuple2<scalar, scalar> >  data;
    reader(dataFileName_, data);
    // Resize to experimental data
    rheologyTableX_.resize(data.size());
    rheologyTableY_.resize(data.size());
    forAll(data, lineI)
    {
        const auto& dataTuple = data[lineI];
        rheologyTableX_[lineI] = dataTuple.first();
        rheologyTableY_[lineI] = dataTuple.second();
    }

新粘度模型的定义位于constant/transportProperties字典文件中:

transportModel interpolatedSplineViscosityModel;
interpolatedSplineViscosityModelCoeffs
{
    dataFileName "constant/viscosityData/anand2004kinematic.csv";
    hasHeaderLine false;
    refColumn 0;
    componentColumns (1);
}
rho        1060;

新粘度模型的输入包含实验数据文件的路径,以及定义CSV文件结构的信息。CSV文件不包含标题,参考列为0,只有单个组分列1,表观运动粘度来自[1]。

成员函数correct代码如下所示:

void interpolatedSplineViscosityModel::correct()
{
    // Interpolate kinematic viscosity in each cell from tabular data.
    volScalarField& nu = nuPtr_.ref();
    const volScalarField cellStrainRate = strainRate();
    forAll(cellStrainRate, cellI)
    {
        nu[cellI] = interpolateSplineXY
        (
            cellStrainRate[cellI],
            rheologyTableX_,
            rheologyTableY_
        );
    }
    nu.correctBoundaryConditions();
}

11.3.1 示例案例

一个下落的“血液”液滴撞击一个无法穿透的壁面是样条粘性模型的例子。 案例本身包含在存储库中,位于

ofbook/ofprimer/cases/chapter11/falling-droplet-2D

两相VoF解算器interIsoFoam [2]用于模拟非牛顿液滴通过空气下落并撞击固体表面。注意,该模拟是二维的并且在空间上是欠分辨的;但它仍然很好地用作示例模拟。正方形区域有三个不可穿透的壁和一个开放大气边界条件,如图11.5所示。可使用需要4个CPU内核的准备好的Allrun脚本运行案例直至完成。

图11.5 求解域的例子案例

直径为1毫米的液滴从零速度开始,在畴中居中。 重力加速液滴向下,最终冲击无滑移壁面。 当液滴冲击壁面时,高的局部应变率改变了液体中的有效粘度。 非牛顿效应可视化在图11.6。

图11.6 冲击壁面液滴的体积分数和局部剪切粘度的比较