はじめに(着手日:210916, HP更新日:221011)

OpenFOAMのver.が古いので,最新のに対応しているかわからない.

自作solverの制作 (interPhaseChangeFoamの利用)

公開solverが古いverのOpenFOAMで制作されており、(自分の)現在の環境では利用できなさそうであった。 そこで自作solverを制作する。 solverのオリジナルは"interPhaseChangeFoam"を利用する。 (解析対象はチュートリアルのcavitation bullet )。 解析環境
OpenFOAM 8 Fundation版 OS:Ubuntu 20.04.3 CPU:AMD® Ryzen 9 3900x 12-core processor × 24 メモリ:64 GB
参考サイト
▶ A interphaseChangeFoam tutorial http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2011/MartinAndersen/Tutorial_interPhaseChangeFoam.pdf


0 一連の流れ (solver非編集)

1 ディレクトリの準備(interPhaseChangeFoamをコピー)

$ cd run
$ cp -r $FOAM_SOLVERS/multiphase/interPhaseChangeFoam myiPCF_2
$ cd myiPCF
$ mv interPhaseChangeFoam.C myiPCF.C
自分のワークフォルダに既存のsolverをコピーしてくる (チュートリアルの"interPhaseChangeFoam")。 今回の自作solverの名前を"myiPCF"とした(my inter Phase Change Foam の略)。

2 "myiPCF.C" (自作solver.C)内のヘッダーの修正

.
├── Allwclean
├── Allwmake
├── Make
│   ├── files
│   └── options
├── UEqn.H
├── alphaControls.H
├── alphaEqn.H
├── alphaEqnSubCycle.H
├── correctPhi.H
├── createFields.H
├── initCorrectPhi.H
├── myiPCF.C  (もともとはinterPhaseChangeFoam.C)
├── pEqn.H
└── phaseChangeTwoPhaseMixtures
    ├── Kunz (略)
    ├── Make (略)
    ├── Merkle (略)
    ├── SchnerrSauer (略)
    ├── lnInclude (略)
    └── phaseChangeTwoPhaseMixture (略)
■ OpenFOAM8の場合 ("myiPCF.C"内のヘッダーを確認)
(上略)
#include "CorrectPhi.H"
(下略)
絶対参照がないのでOpenFoam8では修正必要なさそう

■ 古いOpenFOAMの場合 "interFoam"内の"correctPhi.H"をコピーする。
$ cp $FOAM_SOLVERS/multiphase/interFoam/correctPhi.H .
"myiPCF.C"内のヘッダーを修正する
修正前:(参照ディレクトリが記載している場合)
(上略)
#include "../interFoam/correctPhi.H"
(下略)
修正後:
(上略)
#include "correctPhi.H"
(下略)

3 "Make/files"の修正

修正前:
interPhaseChangeFoam.C

EXE = $(FOAM_APPBIN)/interPhaseChangeFoam
修正後:
myiPCF.C

EXE = $(FOAM_APPBIN)/myiPCF
古いverのOpenFOAMだと"Make/files"の記載内容が異なるが、基本は下記の通り。 ①どのファイルを読むか (〇〇.C) ②どんな名前のファイルを出力するか (EXE = $(FOAM_APPBIN)/〇〇)

4 コンパイル

$ wclean
$ wmake 2>&1 | tee log.wmake
■ エラー(outputを書き込み権限がない)
usr/bin/ld.bfd: cannot open output file openfoam
書き込む場所の権限を与える。
$ sudo chown -R tokudy /opt/openfoam8/platforms/
■ 他のエラー "$ less log.wmake"で各自解決してほしい。

5 solverの出力確認

$ cd $FOAM_APPBIN
$ ls
ここに制作した"myiPCF"が出力されているはず。

6 solverの動作確認

$ run
$ cp -r $FOAM_TUTORIALS/multiphase/interPhaseChangeFoam/cavitatingBullet cavitatingBullet_test
$ cd cavitatingBullet_test
$ vi system/controlDict
$ ./Allrun
チュートリアルの"cavitatingBullet"で確認を行う。 "system/controlDict"を制作したsolverで解くように修正する。 "application"を"myiPCF"(自作solver)とし、"endTime"と"writeInterval"を適切な範囲に設定する。 (下記の条件の計算時間:ExecutionTime = 4020.92 s ClockTime = 4025 s)
system/controlDict
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

application             myiPCF;

startFrom               latestTime;

startTime               0;

stopAt                  endTime;

endTime                 0.02;

deltaT                  1e-8;

writeControl            adjustableRunTime;

writeInterval           0.001;

purgeWrite              0;

writeFormat             binary;

writePrecision          6;

writeCompression        off;

timeFormat              general;

runTimeModifiable       yes;

adjustTimeStep          on;

maxCo                   5;
maxAlphaCo              2;

// ************************************************************************* //

7 結果

自作ソルバのコンパイルは通り解析結果まで出力できたのでOK。 これが物理的にどうのこうの、定性的、定量的にあーだこーだの議論は保留する。 一連の流れが確認できた、ヨシ!。 deltaT 0.001; endTime 0.02; paraViewで確認後、jpegで出力し動画制作。コマンドは以下
$ ffmpeg -r 30 -i myiPCF_alpha_water.%04d.jpeg -vcodec libx264 -pix_fmt yuv420p -r 60 210916_myiPCF_alpha_water.mp4

8 おまけ 解析log (最初と最後)

/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
Build  : 8-1c9b5879390b
Exec   : myiPCF
Date   : Sep 16 2021
Time   : 17:36:24
Host   : "tokudy-desktop"
PID    : 10259
I/O    : uncollated
Case   : /home/tokudy/OpenFOAM/tokudy-8/run/cavitatingBullet_test
nProcs : 1
sigFpe : Enabling floating point exception trapping (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster (fileModification
Skew 10)
allowSystemOperations : Allowing user-supplied system call operations

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time

Create mesh for time = 0


PIMPLE: No convergence criteria found


PIMPLE: Operating solver in transient mode with 1 outer corrector
PIMPLE: Operating solver in PISO mode


Reading field p_rgh

Reading field U

Reading/calculating face flux field phi

Creating phaseChangeTwoPhaseMixture

Selecting phaseChange model SchnerrSauer
Selecting incompressible transport model Newtonian
Selecting incompressible transport model Newtonian
Selecting turbulence model type laminar
Selecting laminar stress model Stokes

Reading g

Reading hRef
Calculating field g.h

No finite volume options present
GAMG:  Solving for pcorr, Initial residual = 1, Final residual = 9.71108e-09, No Iterations 19
time step continuity errors : sum local = 2.36612e-20, global = -7.53186e-21, cumulative = -7.53186e-21
Courant Number mean: 0.00013526 max: 0.00764258

Starting time loop

Courant Number mean: 0.00013526 max: 0.00764258
Interface Courant Number mean: 0 max: 0
deltaT = 1.19999e-08
Time = 1.19999e-08

smoothSolver:  Solving for alpha.water, Initial residual = 1, Final residual = 1.3889, No Iterations 10
Phase-1 volume fraction = 1  Min(alpha.water) = 1  Max(alpha.water) = 1
MULES: Correcting alpha.water
MULES: Correcting alpha.water
Liquid phase volume fraction = 1  Min(alpha.water) = 1  Max(alpha.water) = 1
GAMG:  Solving for p_rgh, Initial residual = 1, Final residual = 0.0343803, No Iterations 1
GAMG:  Solving for p_rgh, Initial residual = 0.572606, Final residual = 2.87102e-05, No Iterations 1
GAMGPCG:  Solving for p_rgh, Initial residual = 3.26599e-05, Final residual = 9.21097e-08, No Iterations 2
ExecutionTime = 3.1 s  ClockTime = 3 s


-----------------中略-----------------

smoothSolver:  Solving for alpha.water, Initial residual = 6.44222e-06, Final residual = 9.08914e-10, No Iterations 2
Phase-1 volume fraction = 0.970299  Min(alpha.water) = 3.13574e-05  Max(alpha.water) = 1
MULES: Correcting alpha.water
MULES: Correcting alpha.water
Liquid phase volume fraction = 0.970221  Min(alpha.water) = 3.13634e-05  Max(alpha.water) = 1.00039
GAMG:  Solving for p_rgh, Initial residual = 6.11211e-05, Final residual = 2.00492e-07, No Iterations 1
GAMG:  Solving for p_rgh, Initial residual = 1.63396e-05, Final residual = 7.53242e-08, No Iterations 1
GAMGPCG:  Solving for p_rgh, Initial residual = 5.73702e-06, Final residual = 1.72077e-08, No Iterations 1
ExecutionTime = 4019.57 s  ClockTime = 4023 s

Courant Number mean: 0.0908173 max: 2.12591
Interface Courant Number mean: 0.00579412 max: 1.98598
deltaT = 7.0893e-06
Time = 0.02

smoothSolver:  Solving for alpha.water, Initial residual = 6.45889e-06, Final residual = 9.11336e-10, No Iterations 2
Phase-1 volume fraction = 0.970295  Min(alpha.water) = 3.1736e-05  Max(alpha.water) = 1
MULES: Correcting alpha.water
MULES: Correcting alpha.water
Liquid phase volume fraction = 0.970218  Min(alpha.water) = 3.17365e-05  Max(alpha.water) = 1.00035
GAMG:  Solving for p_rgh, Initial residual = 6.1257e-05, Final residual = 1.99878e-07, No Iterations 1
GAMG:  Solving for p_rgh, Initial residual = 1.64261e-05, Final residual = 7.32739e-08, No Iterations 1
GAMGPCG:  Solving for p_rgh, Initial residual = 5.80019e-06, Final residual = 1.77596e-08, No Iterations 1
ExecutionTime = 4020.92 s  ClockTime = 4025 s

End


1 solverの中身の理解

状況の確認

前章までに一連の流れ (ディレクトリの作製〜solverのコンパイル〜テストケースの検証まで)を確認した。本章では、メイントピック(新たなヘッダーファイルを作成し、solverのコードを修正し、オリジナルのsolverをコンパイルする)の大前提となる"ソースコードの内容を理解"を試みる。まず、ソースコード "myiPCF.C" (自作コード)を見てみる。しかし、何が書いてあるかはよくわからない (一応解釈を試みるが各自調べてほしい)。

Useful Reference
▶ Description and utilization of interFoam multiphase solver
http://infofich.unl.edu.ar/upload/3be0e16065026527477b4b948c4caa7523c8ea52.pdf

▶ interFoam
http://penguinitis.g1.xrea.com/study/OpenFOAM/tankentai/22-interFoam.html

▶ 【OpenFOAM】手法を変えて処理を追加② : ソルバーに処理を追加する
https://zenn.dev/inabower/articles/bd0406a50919e6

▶ OpenFOAMライブラリリファレンス (株式会社テラバイト, 2020)
https://www.amazon.co.jp/dp/4627691610/

▶ OpenFOAMプログラミング (森北出版, 2017)
https://www.amazon.co.jp/dp/4627670915/

▶ 液体食品の充填製造プロセスにおける流動操作条件の最適化
file:///tmp/LID201704201006.pdf
https://repo.lib.tokushima-u.ac.jp/ja/110074


myiPCF.C
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Copyright (C) 2011-2020 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see .

Application
    interPhaseChangeFoam

Description
    Solver for 2 incompressible, isothermal immiscible fluids with phase-change
    (e.g. cavitation).  Uses a VOF (volume of fluid) phase-fraction based
    interface capturing approach, with optional mesh motion and mesh topology
    changes including adaptive re-meshing.

    The momentum and other fluid properties are of the "mixture" and a
    single momentum equation is solved.

    The set of phase-change models provided are designed to simulate cavitation
    but other mechanisms of phase-change are supported within this solver
    framework.

    Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected.

\*---------------------------------------------------------------------------*/

#include "fvCFD.H"
#include "dynamicFvMesh.H"
#include "CMULES.H"
#include "subCycle.H"
#include "interfaceProperties.H"
#include "phaseChangeTwoPhaseMixture.H"
#include "kinematicMomentumTransportModel.H"
#include "pimpleControl.H"
#include "fvOptions.H"
#include "CorrectPhi.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

int main(int argc, char *argv[])
{
    #include "postProcess.H"

    #include "setRootCaseLists.H"
    #include "createTime.H"
    #include "createDynamicFvMesh.H"
    #include "createDyMControls.H"
    #include "initContinuityErrs.H"
    #include "createFields.H"
    #include "initCorrectPhi.H"
    #include "createUfIfPresent.H"

    turbulence->validate();

    #include "CourantNo.H"
    #include "setInitialDeltaT.H"

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    Info<< "\nStarting time loop\n" << endl;

    while (pimple.run(runTime))
    {
        #include "readDyMControls.H"

        // Store divU from the previous mesh so that it can be mapped
        // and used in correctPhi to ensure the corrected phi has the
        // same divergence
        volScalarField divU("divU0", fvc::div(fvc::absolute(phi, U)));

        #include "CourantNo.H"
        #include "alphaCourantNo.H"
        #include "setDeltaT.H"

        runTime++;

        Info<< "Time = " << runTime.timeName() << nl << endl;

        // --- Pressure-velocity PIMPLE corrector loop
        while (pimple.loop())
        {
            if (pimple.firstPimpleIter() || moveMeshOuterCorrectors)
            {
                mesh.update();

                if (mesh.changing())
                {
                    gh = (g & mesh.C()) - ghRef;
                    ghf = (g & mesh.Cf()) - ghRef;

                    if (correctPhi)
                    {
                        // Calculate absolute flux
                        // from the mapped surface velocity
                        phi = mesh.Sf() & Uf();

                        #include "correctPhi.H"

                        // Make the flux relative to the mesh motion
                        fvc::makeRelative(phi, U);
                    }

                    mixture.correct();

                    if (checkMeshCourantNo)
                    {
                        #include "meshCourantNo.H"
                    }
                }
            }

            divU = fvc::div(fvc::absolute(phi, U));

            surfaceScalarField rhoPhi
            (
                IOobject
                (
                    "rhoPhi",
                    runTime.timeName(),
                    mesh
                ),
                mesh,
                dimensionedScalar(dimMass/dimTime, 0)
            );

            #include "alphaControls.H"
            #include "alphaEqnSubCycle.H"

            mixture.correct();

            #include "UEqn.H"

            // --- Pressure corrector loop
            while (pimple.correct())
            {
                #include "pEqn.H"
            }

            if (pimple.turbCorr())
            {
                turbulence->correct();
            }
        }

        runTime.write();

        Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
            << "  ClockTime = " << runTime.elapsedClockTime() << " s"
            << nl << endl;
    }

    Info<< "End\n" << endl;

    return 0;
}


// ************************************************************************* //
" while (pimple.run(runTime))"が数値解析の本体。中を見てみる。 まず、計算を開始する前に、メッシュ、時間、クーラン数などの基本的な値を確認する。
#include "readDyMControls.H"
"correctPhi", "checkMeshCourantNo", "moveMeshOuterCorrectors"の取得。 flux variableである\(\,\phi\)、クーラン数、移動メッシュ?を取得するっぽいがよくわからない。 型はboolだと思う。

▶ readDyMControls.H
https://cpp.openfoam.org/v8/readDyMControls_8H_source.html

readDyMControls.H

 #include "readTimeControls.H"
 
 correctPhi = pimple.dict().lookupOrDefault
 (
     "correctPhi",
     correctPhi
 );
 
 checkMeshCourantNo = pimple.dict().lookupOrDefault
 (
     "checkMeshCourantNo",
     checkMeshCourantNo
 );
 
 moveMeshOuterCorrectors = pimple.dict().lookupOrDefault
 (
     "moveMeshOuterCorrectors",
     moveMeshOuterCorrectors
 );


// Store divU from the previous mesh so that it can be mapped
// and used in correctPhi to ensure the corrected phi has the
// same divergence
volScalarField divU("divU0", fvc::div(fvc::absolute(phi, U)));

"volScalarField divU("divU0", fvc::div(fvc::absolute(phi, U)));"で値をコピーする。補正された\(\,\phi\)が同じ発散を有するように、前のメッシュから\(\,{\nabla}U\)を保存し、それをマッピングしてcorrectPhiで使用できるようにする。

"volScalarField"に関しては、下記に簡潔に書いてある。
▶ スカラーフィールド
http://penguinitis.g1.xrea.com/study/OpenFOAM/tankentai/07-sfield.html

▶ OpenFOAM プログラミングメモ
http://penguinitis.g1.xrea.com/study/OpenFOAM/programming_memo.html

#include "CourantNo.H"
#include "alphaCourantNo.H"
#include "setDeltaT.H"
ここもよくわからないが、クーラン数とタイムステップを調整している?
▶ 液体食品の充填製造プロセスにおける流動操作条件の最適化
file:///tmp/LID201704201006.pdf
https://repo.lib.tokushima-u.ac.jp/ja/110074

次に、時間の更新。
runTime++;

Info<< "Time = " << runTime.timeName() << nl << endl;

次に、速度と圧力の連成解析を行う。ここではPIMPLE法を使用している。PIMPLE法については後述。
// --- Pressure-velocity PIMPLE corrector loop
while (pimple.loop())
{
    if (pimple.firstPimpleIter() || moveMeshOuterCorrectors)
    {
        mesh.update();

        if (mesh.changing())
        {
            gh = (g & mesh.C()) - ghRef;
            ghf = (g & mesh.Cf()) - ghRef;

            if (correctPhi)
            {
                // Calculate absolute flux
                // from the mapped surface velocity
                phi = mesh.Sf() & Uf();

                #include "correctPhi.H"

                // Make the flux relative to the mesh motion
                fvc::makeRelative(phi, U);
            }

            mixture.correct();

            if (checkMeshCourantNo)
            {
                #include "meshCourantNo.H"
            }
        }
    }
}

次に、上記の連成解析で得られた圧力を用いて、仮の速度を出す。
    divU = fvc::div(fvc::absolute(phi, U));

次に、密度、flux?を更新する。
    surfaceScalarField rhoPhi
    (
        - 略 -
    );

"alpha"VOFパラメータ?に関してあれやこれやする。
    #include "alphaControls.H"
    #include "alphaEqnSubCycle.H"

たぶん混合密度、混合粘性の修正?
    mixture.correct();

速度について解く。
    #include "UEqn.H"

圧力について解く?修正?。
    // --- Pressure corrector loop
    while (pimple.correct())
    {
        #include "pEqn.H"
    }

よくわからん。乱流に関して修正?
    if (pimple.turbCorr())
    {
        turbulence->correct();
    }

以上を繰り返す。 PIMPLE法は"PIS0"と"SIMPLE"を組み合わせた方法で、アルゴリズムは、
① 現在の速度 (n-step)から仮の速度 (*-step)を算出する。 \begin{align} u_* = u_n + c_1(A_{AD,*} + A_{NU,*} + A_{p,n}) \end{align}
② 圧力の補正量を算出する。 \begin{align} {\nabla}{\cdot}u = 0 \end{align}
\begin{align} u_{n+1} = u_* - c_2(P_{correct}) \end{align}
\begin{align} {\nabla}{\cdot}(A_{p,*}) = \cfrac{1}{c_2}{\nabla}{\cdot}u_* \end{align}
③ 圧力と速度を補正補正する。 \begin{align} u_{n+1} = u_* - c_2(P_{correct}) \end{align} ④ 値が収束するまで繰り返す。


なお、実際の(数学的な)アルゴリズムは下記のようになる。OpenFOAMライブラリリファレンス (第15章 自由表面流れの解析手法, p648~650)を参考にした。

支配方程式

非圧縮性流体の運動保存式は、気液界面での表面張力と重量を考慮すると、 \begin{align} \cfrac{{\partial}({\rho}u_i)}{{\partial}t} + \cfrac{{\partial}({\rho}{u_i}{u_j})}{{\partial}x_j} = - \cfrac{{\partial}p_r}{{\partial}x_i} - g_j(x_j-r_j)\cfrac{{\partial}{\rho}}{{\partial}x_j} + \cfrac{\partial}{{\partial}x_j} \left[ {\mu} (\cfrac{{\partial}u_i}{{\partial}x_j} + \cfrac{{\partial}u_j}{{\partial}x_i}) \right] + F_{CSF,i} \end{align}
時間変化 + 移流項 = 圧力項 + 重力項 + 粘性項 + 表面張力項

\(\, r_i\)は参照座標。\(\, g_j\)は重力。 圧力\(\, p_r\)は静水圧の寄与を取り除いた値。 \begin{align} p_r = p - {\rho}g_j(x_j-r_j) \end{align} 右辺の最終項は表面張力項(単相流には無い)。CSF (Continuum SUrface Force)モデルとして扱われる。 \begin{align} F_{CSF,i} = {\sigma}{\kappa}\cfrac{{\partial}F}{{\partial}x_i} \end{align} \(\, \sigma\)は表面張力係数。界面の曲率\(\,\kappa\)は、 \begin{align} \kappa = - {\nabla}{\cdot}{\bf{n}} = {\nabla}{\cdot} \left( {\cfrac{{\nabla}F}{|{\nabla}F|}} \right) \end{align} 混合密度\(\,\rho\)と混合粘度\(\,\mu\)は、VOF関数体積率\(\,F\)を用いて、 \begin{align} \rho = \rho_2 + F(\rho_1 - \rho_2) \end{align} \begin{align} \mu = \mu_2 + F(\mu_1 - \mu_2) \end{align}

interFoamで実装されているPIMPLE方での計算手順


(1) 流速の初期値、体積率\(\,F\)を設定し、セル境界面のフラックス\(\,\phi(u_i^0)\)を計算。

(2) VOF関数の移流方程式を解いて、体積率\(\,F\)を算出 (MULES or CMULES)。 \begin{align} \cfrac{{\partial}F}{{\partial}t} + \cfrac{{\partial}(F{u_j})}{{\partial}x_j} = 0 \end{align}
(3) 運動量保存式を解く。 \begin{align} A_P u_{iP}^{m*} + {\sum\limits_{l}^{NC}} A_l u_{il}^{m*} = Q_{iP}^{m-1} - \left( \cfrac{{\delta}p^{m-1}} {{\delta} x_i} \right)_P \Delta V \end{align} (注:上式を解かない場合、fvSolutionファイルのPIMPLE辞書のmomentunPredictorキーワードにfalseを指定する。)

(4) 運動量保存式から得られた流速\(\,u_i^{m*}\)を用いて暫定流速を獲得 ((3)を解かない場合は前タイムステップの\(\,u_i^n\))。 \begin{align} \tilde{u}_{iP}^{**} = \cfrac{1}{A_P} \left( - \sum\limits_{l}^{NC} A_l u_{il}^{m*} + Q_{iP}^{m-1} \right) \end{align}
(5) 暫定流速を用いて、Rhie-Chow補間により暫定境界面流束を計算。 \begin{align} \phi_{\alpha}(\tilde{u}_i^{**}) = {\langle \tilde{u}_i^{**} \rangle}_{\alpha} S_{i \alpha} + \left\langle \cfrac{\rho \Delta V}{A_P} \right\rangle _{\alpha} \left( \cfrac{\phi _\alpha (u_i^{n-1}) - {\langle u_i^{n-1} \rangle}_\alpha S_{i\alpha}}{\Delta t} \right) L \left( \phi(u_i^{n-1}) \right) - \left\langle \cfrac{\Delta V}{A_P} \right\rangle _{\alpha} \left( F_{CSF,i\alpha} - g_j (x_j - r_j) \cfrac{\delta \rho}{\delta x_i} \right)_\alpha S_{i \alpha} \end{align} ここで、制限関数\(\, L \)は、
\begin{align} L \left( \phi(u_i^{n-1}) \right) = 1 - \min \left( \cfrac{ \left\lvert \phi (u_i^{n-1}) - {\langle u_i^{n-1} \rangle} S_i \right\rvert \Delta t}{d_{CF} \left\lvert \bf{S} \right\rvert} , 1 \right) \end{align}
(6) 圧力方程式をlaplacianスキーム (反復計算)で解く。 \begin{align} \sum\limits_{\alpha}^{NS} \left\langle \cfrac{\Delta V}{A_P} \right\rangle _{\alpha} \left( \cfrac{ \delta p^m }{ \delta x_i } \right)_{\alpha} S_{i \alpha} = \sum\limits_{\alpha}^{NS} \phi_{\alpha}(\tilde{u}_i^{**}) \end{align}
(7) 次サイクルで必要となるセル境界面流束を計算する。 \begin{align} \phi _\alpha (u_i^m) = \left\langle \tilde{u}_i^{**} \right\rangle _\alpha S_{i\alpha} - \left\langle \cfrac{\Delta V}{A_P} \right\rangle _{\alpha} \left( \cfrac{ \delta p^m }{ \delta x_i } \right)_{\alpha} S_{i \alpha} \end{align}
(8) 流速を更新する。 \begin{align} u_i^m = \tilde{u}_i^{**} - \cfrac{\Delta V}{A_P} \left( F_{CSF,i} - g_j (x_j - r_j) \cfrac{\delta \rho}{\delta x_i} \right)_\alpha - \cfrac{\Delta V}{A_P} \cfrac{\delta p^m}{\delta x_i} \end{align}

(9) 圧力補正と流速補正を繰り返す(PISOループ)ため、 \(\,u_i^{m*} = u_i^m\) として、STEP(4)に戻り、STEP(8)まで繰り返す。

(10) 運動量保存式の係数行列を更新する外部反復ループを実行するために、STEP(2)に戻り、 STEP(9)まで反復計算する。収束したと判断された場合、 \(\,u_i^{n+1} = u_i^m\) として次の計算ステップに進む。
実は移流方程式を解く方法 http://t2r2.star.titech.ac.jp/rrws/file/CTT100759558/ATD100000413/outline_15D31012_%E6%B1%A0%E7%AB%AF%E6%98%AD%E5%A4%AB.pdf http://i-rep.emu.edu.tr:8080/xmlui/bitstream/handle/11129/1610/EmadVahid.pdf?sequence=1 https://sites.google.com/site/trujillolabgroup/understanding-mules http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2017/ElinOlsson/Report_ElinOlsson_Updated050118.pdf

2 熱拡散方程式の追加


一連の実行コマンド (solver側)

$ run
$ cd myiPCF
$ wclean
$ vi createFields.H
$ touch TEqn.H
$ vi TEqn.H
$ vi myiPCF.C
$ wmake
    

追加内容: 熱拡散項・支配方程式の実装

熱拡散 (thermal diffusivity)を実装する。通常は\(\,\alpha\)で表されるがコーディングの都合上\(\, DT\)とする (\(\,\alpha\)はVOF値に取られてる)。
\(\, DT = \cfrac{k}{\rho c_p}\)
\(\, DT\): thermal diffusivity [m^2/S]
\(\, k\): thermal conductivity [W/(m*K)]
\(\, \rho\): density [kg/m^3]
\(\, c_p\): specific heat capacity [J/kg*K]


上式の内容を"createFields.H"の一番上 (おそらくどこでもよい)に書き足す。

createFields.H
Info<< "Reading transportProperties\n" << endl; IOdictionary transportPropertiesDict ( IOobject ( "transportProperties", runTime.constant(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE ) ); dimensionedScalar DT ( transportPropertiesDict.lookup("DT") ); Info<< "Reading field T\n" << endl; volScalarField T ( IOobject ( "T", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), mesh ); Info<< "Reading field p_rgh\n" << endl; volScalarField p_rgh ( IOobject ( "p_rgh", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), mesh ); Info<< "Reading field U\n" << endl; volVectorField U ( IOobject ( "U", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), mesh ); #include "createPhi.H" Info<< "Creating phaseChangeTwoPhaseMixture\n" << endl; autoPtr mixturePtr ( phaseChangeTwoPhaseMixture::New(U, phi) ); phaseChangeTwoPhaseMixture& mixture = mixturePtr(); volScalarField& alpha1(mixture.alpha1()); volScalarField& alpha2(mixture.alpha2()); const dimensionedScalar& rho1 = mixture.rho1(); const dimensionedScalar& rho2 = mixture.rho2(); // Need to store rho for ddt(rho, U) volScalarField rho ( IOobject ( "rho", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT ), alpha1*rho1 + alpha2*rho2 ); rho.oldTime(); // Construct incompressible turbulence model autoPtr turbulence ( incompressible::momentumTransportModel::New(U, phi, mixture) ); #include "readGravitationalAcceleration.H" #include "readhRef.H" #include "gh.H" volScalarField p ( IOobject ( "p", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE ), p_rgh + rho*gh ); label pRefCell = 0; scalar pRefValue = 0.0; setRefCell ( p, p_rgh, pimple.dict(), pRefCell, pRefValue ); if (p_rgh.needReference()) { p += dimensionedScalar ( "p", p.dimensions(), pRefValue - getRefCellValue(p, pRefCell) ); p_rgh = p - rho*gh; } mesh.setFluxRequired(p_rgh.name()); mesh.setFluxRequired(alpha1.name()); #include "createFvOptions.H"
2~17行はthermal diffusion (DTとして)の新しいtransport prppetyの記述。 18~30行は温度分布Tの生成。

支配方程式 (熱拡散方程式)

\begin{align} \cfrac{{\partial}T}{{\partial}t} + {\nabla}{\cdot}({\phi}T) = {\nabla}{\cdot}(DT{\nabla}T) \end{align} 上式をコードで表すと下記のようになる。新しく"TEqn.H"というファイルを作り、このコードを書き込む。

TEqn.H
{
    fvScalarMatrix TEqn
    (s
       fvm::ddt(T)
        + fvm::div(phi, T)
        - fvm::laplacian(DT, T)
    );
    TEqn.solve();
}

上記ファイルを作っただけではだめなので、自作solverの"myiPCF.C"にて #include をする。おそらく、#include のタイミングが重要であり、下記の箇所に書き込む ("UEqn.H"の後なのは速度の項を流用するからか?)。

myiPCF.C
 - 略 -   
while (pimple.run(runTime))
{
    - 略 -

    // --- Pressure-velocity PIMPLE corrector loop
    while (pimple.loop())
    {
        - 略 -
    }
    divU = fvc::div(fvc::absolute(phi, U));

    surfaceScalarField rhoPhi
    (
        - 略 -
    );

    #include "alphaControls.H"
    #include "alphaEqnSubCycle.H"

    mixture.correct();

    #include "UEqn.H"
    // ここに追加する↓ 
    #include "TEqn.H


    // --- Pressure corrector loop
    while (pimple.correct())
    {
        #include "pEqn.H"
    }


    if (pimple.turbCorr())
    {
        turbulence->correct();
    }
}
- 略 -

古いverのOpenFOAMは下記のように編集するっぽい。
flux variable \(\phi\)に関しては、 圧力のループ計算 (ポアソン方程式)のにおいて使用されている (それを流用するものだと思われる)。熱輸送は速度分布に依存するため、"Pressure-velocity PIMPLE corrector loop"のループ解析後に、TEqn.Hのファイルはincludeされる。phase changeはこのエネルギー方程式に依存し、"twoPhaseProperties->correct();:"(昔のOpenFOAMのコード)の前にincludeされなければならない。

一連の実行コマンド (case 側)

$ cp -r $FOAM_TUTORIALS/multiphase/interPhaseChangeFoam/cavitatingBullet $FOAM_RUN/temperatureTest
$ cd $FOAM_RUN/temperatureTest
$ vi Allrun
$ rm -r constant/triSurface system/snappyHexMeshDict
$ sed -i "/bullet/,/}/d" 0/*
$ vi constant/transportProperties
$ cp 0/p_rgh 0/T
$ vi 0/T
$ vi system/fvSchemes
$ vi system/fvSolution
$ vi sysetm/controlDict
$ ./Allrun
$ paraFoam
$ ffmpeg -r 30 -i 210919_cavitationBullet_myiPCF_T.%04d.jpeg -vcodec libx264 -pix_fmt yuv420p -r 60 210919_cavitationBullet_myiPCF_T.mp4


"cavitationBullet"のケースディレクトリをコピーしてくる。しかし、簡単に確認するために、bulletの部分は取り除いて自作solverのコンパイルの確認を行う。 まず、"Allrun"から、"potentialFoam"と"snappyHexMesh"の記述を取り除き下記のようにする。

Allrun
#!/bin/sh
cd ${0%/*} || exit 1    # Run from this directory

# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions

# Generate the base block mesh
runApplication blockMesh

# Run the solver
runApplication $(getApplication)

#------------------------------------------------------------------------------

次に、bulletのジオメトリやコードの記述を取り除く。
$ rm -r constant/triSurface system/snappyHexMeshDict
$ sed -i "/bullet/,/}/d" 0/*

メモ:
「sed」は「Stream EDitor」の略。「sed スクリプトコマンド ファイル名」で、指定したファイルをスクリプトコマンドに従って行単位に処理し、標準出力へ出力する。ファイル名を省略した場合は、標準入力からのデータを処理する。 「-i」 ファイルを直接編集する。 「s/置換前/置換後/」 [置換前]で指定した文字列にマッチした部分を[置換後]に置き換える。複数マッチした場合は先頭のみ置換、全てを置換したい場合は、「s/置換前/置換後/g」のように「g」オプションを指定する。


"transportProperties"に"DT"に関して定義する。 場所はどこでもよく、最後に追加した。
constant/transportProperties
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      transportProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

phases (water vapour);

phaseChangeTwoPhaseMixture SchnerrSauer;

pSat            2300;   // Saturation pressure

sigma           0.07;

water
{
    transportModel  Newtonian;
    nu              9e-07;
    rho             1000;
}

vapour
{
    transportModel  Newtonian;
    nu              4.273e-04;
    rho             0.02308;
}

KunzCoeffs
{
    UInf            U20.0;
    tInf            t0.005; // L = 0.1 m
    Cc              C1000;
    Cv              C1000;
}

MerkleCoeffs
{
    UInf            20.0;
    tInf            0.005;  // L = 0.1 m
    Cc              80;
    Cv              1e-03;
}

SchnerrSauerCoeffs
{
    n               1.6e+13;
    dNuc            2.0e-06;
    Cc              1;
    Cv              1;
}


DT   DT [0 2 -1 0 0 0 0] 0.002; // [m^2/s]


// ************************************************************************* //



"T"の設定。"0/p_rgh"をコピーして下記のように記述する。

0/T
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    location    "0";
    object      T;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions      [0 0 0 1 0];  // [K]

internalField   uniform 363.15;  // 90 deg. C

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 383.15;  // 110 deg. C
    }

    outlet
    {
        type            fixedValue;
        value           $internalField;
    }

    walls
    {
        type            symmetry;
    }

}

// ************************************************************************* //   


"system/fvSchemes"の設定。支配方程式を見ても明らかなように、"divSchemes"と"laplacianSchemes"の部分を修正する必要がある。

system/fvSchemes
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

ddtSchemes
{
    default             Euler;
}

interpolationSchemes
{
    default             linear;
}

divSchemes
{
    default             none;
    div(rhoPhi,U)       Gauss linearUpwind grad(U);
    div(phi,omega)      Gauss linearUpwind grad(omega);
    div(phi,k)          Gauss linearUpwind grad(k);
    div(phi,alpha)  Gauss interfaceCompression vanLeer 1;
    div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
    div(phi,T)          Gauss upwind;
}

gradSchemes
{
    default             Gauss linear;
}

laplacianSchemes
{
    default             Gauss linear limited corrected 0.5;
    laplacian(DT,T)     Gauss linear corrected;
}

snGradSchemes
{
    default             limited corrected 0.5;
}


// ************************************************************************* //


"system/fvSolution"の設定。最初は"T"で設定していたがコンパイル通らず、"TFinal"にしたらうまくいった。solverはとりあえず"PBiCG"にしたがどれが良いかは不明。

system/fvSchemes
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

solvers
{
    
TFinal { solver PBiCG; preconditioner DILU; tolerance 1e-7; relTol 0; }; "alpha.water.*" { nAlphaCorr 2; nAlphaSubCycles 1; MULESCorr yes; nLimiterIter 5; solver smoothSolver; smoother symGaussSeidel; tolerance 1e-8; relTol 0; maxIter 10; }; "U.*" { solver smoothSolver; smoother symGaussSeidel; tolerance 1e-6; relTol 0; }; p_rgh { solver GAMG; tolerance 1e-8; relTol 0.1; smoother DICGaussSeidel; maxIter 50; }; p_rghFinal { solver PCG; preconditioner { preconditioner GAMG; tolerance 1e-6; relTol 0; nVcycles 2; smoother DICGaussSeidel; }; tolerance 1e-7; relTol 0; maxIter 50; }; "pcorr.*" { $p_rgh; relTol 0; }; Phi { $p_rgh; relTol 0; }; } potentialFlow { nNonOrthogonalCorrectors 3; } PIMPLE { momentumPredictor no; nOuterCorrectors 1; nCorrectors 3; nNonOrthogonalCorrectors 0; } relaxationFactors { equations { ".*" 1; } } // ************************************************************************* //


"controlDict"で自作solverを設定することを忘れないように注意する。また、今回はbulletなしの簡単な解析のため、"endTime"は小さく、非定常解析のため"writeInterval"は細かく設定する。

system/controlDict

/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  8
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

application             myiPCF;  // 追加したところ

startFrom               latestTime;

startTime               0;

stopAt                  endTime;

endTime                 1e-3;  // 追加したところ

deltaT                  1e-8;

writeControl            adjustableRunTime;

writeInterval           1e-5;  // 追加したところ

purgeWrite              0;

writeFormat             binary;

writePrecision          6;

writeCompression        off;

timeFormat              general;

runTimeModifiable       yes;

adjustTimeStep          on;

maxCo                   5;
maxAlphaCo              2;

// ************************************************************************* //

Results

とりあえず熱拡散はうまくいってそう。 deltaT 1e-5; endTime 1e-3;


3 飽和蒸気圧曲線の追加 Psat(T)

August-Roche-Magnus formula solver内にて飽和蒸気圧は2つのループで計算されている (\alpha -loopと pressure-loop)。 計算の不必要なとき (高速化や非線形方程式を再研鑽するとき)、温度場が更新されたとき飽和蒸気圧だけで計算され、圧力場が再構築される。ただし、必ずしもすべてのタイムステップにおいてそれが実行されるとは限らない。
$ touch calcPSatField.H
$ vi calcPSatField.H
calcPSatField.H
{
    const dimensionedScalar t30_11("30.11", dimensionSet(0,0,0,1,0,0,0), 30.11);
    const dimensionedScalar t273_15("273.15", dimensionSet(0,0,0,1,0,0,0), 273.15);
    const dimensionedScalar t1("1", dimensionSet(0,0,0,1,0,0,0), 1);
    const dimensionedScalar p610_94("610.94", dimensionSet(1,-1,-2,0,0,0,0), 610.94);
    // dimensionSet( [kg], [m], [s], [K], [kg*mol], [A], [cd]), [kg/(m*S^2)]=[Pa]
    // August-Roche-Magnus formula
    pSat = p610_94 * exp( 17.625*(T-t273_15) / max(t1, T-t30_11) );
    //max(1,...) is included to avoid problems with devision by 0
}
単位が必ず必要。ここではまだPsatを決めてない。

    $ vi createFields.H
以下の一文を取り除く。
createFields.H
    const dimensionedScalar& pSat = twoPhaseProperties->pSat();
そして、"volScalarField T"の後にincludeする文を付け加える。
"volScalarField p_rgh"の後。(飽和蒸気圧場の初期化のために"volScalarField p_rgh"が"p_rgh"として用いられるので。)
"phaseChangeTwoPhaseMixture"の前。(飽和蒸気圧が"phaseChangeTwoPhaseMixture"に用いられるので。)
createFields.H
volScalarField pSat
(
    IOobject
    (
        "pSat",
        runTime.timeName(),
        mesh,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE
    ),
    p_rgh // initial value will be overwritten in calcPSatField.H
);
#include "calcPSatField.H"
温度"T"に依存する飽和蒸気圧を更新するには、"myiPCF.C"内に「#include "TEqn.H"」の後に、「#include "calcPSatField.H"」を記載する。

Info<< "Reading transportProperties\n" << endl;
IOdictionary transportPropertiesDict
(
    IOobject
    (
        "transportProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ,
        IOobject::NO_WRITE
    )
);
dimensionedScalar DT
(
    transportPropertiesDict.lookup("DT")
);
Info<< "Reading field T\n" << endl;
volScalarField T
(
    IOobject
    (
        "T",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ,
        IOobject::AUTO_WRITE
    ),
    mesh
);


Info<< "Reading field p_rgh\n" << endl;
volScalarField p_rgh
(
    IOobject
    (
        "p_rgh",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ,
        IOobject::AUTO_WRITE
    ),
    mesh
);


volScalarField pSat ( IOobject ( "pSat", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE ), p_rgh // initial value will be overwritten in calcPSatField.H ); #include "calcPSatField.H" Info<< "Reading field U\n" << endl; volVectorField U ( IOobject ( "U", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE ), mesh ); #include "createPhi.H" Info<< "Creating phaseChangeTwoPhaseMixture\n" << endl; autoPtr mixturePtr ( phaseChangeTwoPhaseMixture::New(U, phi) ); phaseChangeTwoPhaseMixture& mixture = mixturePtr(); volScalarField& alpha1(mixture.alpha1()); volScalarField& alpha2(mixture.alpha2()); const dimensionedScalar& rho1 = mixture.rho1(); const dimensionedScalar& rho2 = mixture.rho2(); // Need to store rho for ddt(rho, U) volScalarField rho ( IOobject ( "rho", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT ), alpha1*rho1 + alpha2*rho2 ); rho.oldTime(); // Construct incompressible turbulence model autoPtr turbulence ( incompressible::momentumTransportModel::New(U, phi, mixture) ); #include "readGravitationalAcceleration.H" #include "readhRef.H" #include "gh.H" volScalarField p ( IOobject ( "p", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE ), p_rgh + rho*gh ); label pRefCell = 0; scalar pRefValue = 0.0; setRefCell ( p, p_rgh, pimple.dict(), pRefCell, pRefValue ); if (p_rgh.needReference()) { p += dimensionedScalar ( "p", p.dimensions(), pRefValue - getRefCellValue(p, pRefCell) ); p_rgh = p - rho*gh; } mesh.setFluxRequired(p_rgh.name()); mesh.setFluxRequired(alpha1.name()); #include "createFvOptions.H"


/myiPCF/phaseChangeTwoPhaseMixtures
.
├── Kunz
│   ├── Kunz.C
│   └── Kunz.H
├── Make
│   ├── files
│   └── options
├── Merkle
│   ├── Merkle.C
│   └── Merkle.H
├── SchnerrSauer
│   ├── SchnerrSauer.C
│   └── SchnerrSauer.H
├── lnInclude
│   ├── Kunz.C -> ../Kunz/Kunz.C
│   ├── Kunz.H -> ../Kunz/Kunz.H
│   ├── Merkle.C -> ../Merkle/Merkle.C
│   ├── Merkle.H -> ../Merkle/Merkle.H
│   ├── SchnerrSauer.C -> ../SchnerrSauer/SchnerrSauer.C
│   ├── SchnerrSauer.H -> ../SchnerrSauer/SchnerrSauer.H
│   ├── phaseChangeTwoPhaseMixture.C -> ../phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.C
│   ├── phaseChangeTwoPhaseMixture.H -> ../phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.H
│   └── phaseChangeTwoPhaseMixtureNew.C -> ../phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixtureNew.C
└── phaseChangeTwoPhaseMixture
    ├── phaseChangeTwoPhaseMixture.C
    ├── phaseChangeTwoPhaseMixture.H
    └── phaseChangeTwoPhaseMixtureNew.C

6 directories, 20 files

stacic saturation pressure を取り除く。
    $ vi phaseChangeTwoPhaseMixtures/phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.H

次の記述
    //- Saturation vapour pressure
    dimensionedScalar pSat_;

■ OpenFOAM8
修正前:
//- Return const-access to the saturation vapour pressure
const dimensionedScalar& pSat() const
{
    return pSat_;
}

修正後:
//- Return const-access to the saturation vapour pressure
const volScalarField& pSat() const
{
    const volScalarField& pSat = alpha1_.db().lookupObject("pSat");
    return pSat_;
}

■ 古いOpenFOAM
修正前:
//- Return const-access to the saturation vapour pressure
const dimensionedScalar& pSat() const
{
    return pSat_;
}

修正後:
//- Return const-access to the saturation vapour pressure
const volScalarField& pSat() const
{
    const volScalarField& pSat = alpha1_.db().lookupObject("pSat");
    return pSat;
}

phaseChangeTwoPhaseMixtures/phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.H
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Copyright (C) 2011-2020 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see .

Class
    Foam::phaseChangeTwoPhaseMixture

Description

SourceFiles
    phaseChangeTwoPhaseMixture.C
    phaseChangeModelNew.C

\*---------------------------------------------------------------------------*/

#ifndef phaseChangeTwoPhaseMixture_H
#define phaseChangeTwoPhaseMixture_H

#include "immiscibleIncompressibleTwoPhaseMixture.H"
#include "typeInfo.H"
#include "runTimeSelectionTables.H"
#include "volFields.H"
#include "dimensionedScalar.H"
#include "autoPtr.H"
#include "Pair.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

/*---------------------------------------------------------------------------*\
                Class phaseChangeTwoPhaseMixture Declaration
\*---------------------------------------------------------------------------*/

class phaseChangeTwoPhaseMixture
:
    public immiscibleIncompressibleTwoPhaseMixture
{
protected:

    // Protected data

        dictionary phaseChangeTwoPhaseMixtureCoeffs_;

        //- Saturation vapour pressure
        dimensionedScalar pSat_;


public:

    //- Runtime type information
    TypeName("phaseChangeTwoPhaseMixture");


    // Declare run-time constructor selection table

        declareRunTimeSelectionTable
        (
            autoPtr,
            phaseChangeTwoPhaseMixture,
            components,
            (
                const volVectorField& U,
                const surfaceScalarField& phi
            ),
            (U, phi)
        );


    // Constructors

        //- Construct from components
        phaseChangeTwoPhaseMixture
        (
            const word& type,
            const volVectorField& U,
            const surfaceScalarField& phi
        );

        //- Disallow default bitwise copy construction
        phaseChangeTwoPhaseMixture(const phaseChangeTwoPhaseMixture&);


    // Selectors

        //- Return a reference to the selected phaseChange model
        static autoPtr New
        (
            const volVectorField& U,
            const surfaceScalarField& phi
        );


    //- Destructor
    virtual ~phaseChangeTwoPhaseMixture()
    {}


    // Member Functions

        //- Return const-access to the saturation vapour pressure
        const dimensionedScalar& pSat() const
        {
            return pSat_;
        }

        //- Return the mass condensation and vaporisation rates as a
        //  coefficient to multiply (1 - alphal) for the condensation rate
        //  and a coefficient to multiply  alphal for the vaporisation rate
        virtual Pair> mDotAlphal() const = 0;

        //- Return the mass condensation and vaporisation rates as coefficients
        //  to multiply (p - pSat)
        virtual Pair> mDotP() const = 0;

        //- Return the volumetric condensation and vaporisation rates as a
        //  coefficient to multiply (1 - alphal) for the condensation rate
        //  and a coefficient to multiply  alphal for the vaporisation rate
        Pair> vDotAlphal() const;

        //- Return the volumetric condensation and vaporisation rates as
        //  coefficients to multiply (p - pSat)
        Pair> vDotP() const;

        //- Correct the phaseChange model
        virtual void correct() = 0;

        //- Read the transportProperties dictionary and update
        virtual bool read() = 0;


    // Member Operators

        //- Disallow default bitwise assignment
        void operator=(const phaseChangeTwoPhaseMixture&) = delete;
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //


pSatに関係するすべての記述を消去。 以下の3行目と2行目最後のコンマを消す。
$ vi phaseChangeTwoPhaseMixtures/phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.C

■ OpenFOAM8
修正前:
immiscibleIncompressibleTwoPhaseMixture(U, phi),
phaseChangeTwoPhaseMixtureCoeffs_(optionalSubDict(type + "Coeffs")),
pSat_("pSat", dimPressure, lookup("pSat"))
{}

修正後:
immiscibleIncompressibleTwoPhaseMixture(U, phi),
phaseChangeTwoPhaseMixtureCoeffs_(optionalSubDict(type + "Coeffs"))
{}

■ 古いOpenFOAM
修正前:
twoPhaseMixture(U, phi, alpha1Name),
phaseChangeTwoPhaseMixtureCoeffs_(subDict(type + "Coeffs")),
pSat_(lookup("pSat"))
{}

修正後:
twoPhaseMixture(U, phi, alpha1Name),
phaseChangeTwoPhaseMixtureCoeffs_(subDict(type + "Coeffs"))
{}

次の記述を消す。
lookup("pSat") >> pSat_;

phaseChangeTwoPhaseMixtures/phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.C
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Copyright (C) 2011-2019 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see .

\*---------------------------------------------------------------------------*/

#include "phaseChangeTwoPhaseMixture.H"

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{
    defineTypeNameAndDebug(phaseChangeTwoPhaseMixture, 0);
    defineRunTimeSelectionTable(phaseChangeTwoPhaseMixture, components);
}

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::phaseChangeTwoPhaseMixture::phaseChangeTwoPhaseMixture
(
    const word& type,
    const volVectorField& U,
    const surfaceScalarField& phi
)
:
    immiscibleIncompressibleTwoPhaseMixture(U, phi),
    phaseChangeTwoPhaseMixtureCoeffs_(optionalSubDict(type + "Coeffs")),
    pSat_("pSat", dimPressure, lookup("pSat"))
{}


// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //

Foam::Pair>
Foam::phaseChangeTwoPhaseMixture::vDotAlphal() const
{
    volScalarField alphalCoeff(1.0/rho1() - alpha1()*(1.0/rho1() - 1.0/rho2()));
    Pair> mDotAlphal = this->mDotAlphal();

    return Pair>
    (
        alphalCoeff*mDotAlphal[0],
        alphalCoeff*mDotAlphal[1]
    );
}


Foam::Pair>
Foam::phaseChangeTwoPhaseMixture::vDotP() const
{
    dimensionedScalar pCoeff(1.0/rho1() - 1.0/rho2());
    Pair> mDotP = this->mDotP();

    return Pair>(pCoeff*mDotP[0], pCoeff*mDotP[1]);
}


void Foam::phaseChangeTwoPhaseMixture::correct()
{
    immiscibleIncompressibleTwoPhaseMixture::correct();
}


bool Foam::phaseChangeTwoPhaseMixture::read()
{
    if (immiscibleIncompressibleTwoPhaseMixture::read())
    {
        phaseChangeTwoPhaseMixtureCoeffs_ = optionalSubDict(type() + "Coeffs");
        lookup("pSat") >> pSat_;

        return true;
    }
    else
    {
        return false;
    }
}


// ************************************************************************* //


以上で修正終了。 $ wclean $ wmake


躓いたエラー


エラーログ
    Making dependency list for source file myiPCF.C
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3  -DNoRepository -ftemplate-depth-100 -I. -I/opt/openfoam8/src/transportModels/lnInclude -I/opt/openfoam8/src/twoPhaseModels/twoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/interfaceProperties/lnInclude -I/opt/openfoam8/src/twoPhaseModels/incompressibleTwoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude -IphaseChangeTwoPhaseMixtures/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/momentumTransportModels/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/incompressible/lnInclude -I/opt/openfoam8/src/finiteVolume/lnInclude -I/opt/openfoam8/src/dynamicFvMesh/lnInclude -I/opt/openfoam8/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam8/src/OpenFOAM/lnInclude -I/opt/openfoam8/src/OSspecific/POSIX/lnInclude   -fPIC -c myiPCF.C -o Make/linux64GccDPInt32Opt/myiPCF.o
In file included from myiPCF.C:49:
phaseChangeTwoPhaseMixtures/lnInclude/phaseChangeTwoPhaseMixture.H: In member function ‘const volScalarField& Foam::phaseChangeTwoPhaseMixture::pSat() const’:
phaseChangeTwoPhaseMixtures/lnInclude/phaseChangeTwoPhaseMixture.H:124:42: error: reference to ‘alpha1_’ is ambiguous
  124 |             const volScalarField& pSat = alpha1_.db().lookupObject("pSat");
      |                                          ^~~~~~~
In file included from myiPCF.C:48:
/opt/openfoam8/src/twoPhaseModels/interfaceProperties/lnInclude/interfaceProperties.H:69:31: note: candidates are: ‘const volScalarField& Foam::interfaceProperties::alpha1_’
   69 |         const volScalarField& alpha1_;
      |                               ^~~~~~~
In file included from /opt/openfoam8/src/twoPhaseModels/incompressibleTwoPhaseMixture/lnInclude/incompressibleTwoPhaseMixture.H:40,
                 from /opt/openfoam8/src/twoPhaseModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude/immiscibleIncompressibleTwoPhaseMixture.H:38,
                 from phaseChangeTwoPhaseMixtures/lnInclude/phaseChangeTwoPhaseMixture.H:38,
                 from myiPCF.C:49:
/opt/openfoam8/src/twoPhaseModels/twoPhaseMixture/lnInclude/twoPhaseMixture.H:58:24: note:                 ‘Foam::volScalarField Foam::twoPhaseMixture::alpha1_’
   58 |         volScalarField alpha1_;
      |                        ^~~~~~~
In file included from myiPCF.C:49:
phaseChangeTwoPhaseMixtures/lnInclude/phaseChangeTwoPhaseMixture.H:124:82: error: expected primary-expression before ‘>’ token
  124 |             const volScalarField& pSat = alpha1_.db().lookupObject("pSat");
      |                                                                                  ^
make: *** [/opt/openfoam8/wmake/rules/General/transform:26: Make/linux64GccDPInt32Opt/myiPCF.o] エラー 1
たぶん、‘alpha1_’ の定義がはっきりしてない。 "Foam::interfaceProperties::alpha1_"や"Foam::twoPhaseMixture::alpha1_"が候補として出ているが、ここではひとまず、"Foam::twoPhaseMixture::alpha1_"とした。

修正内容
phaseChangeTwoPhaseMixtures/phaseChangeTwoPhaseMixture/phaseChangeTwoPhaseMixture.H
    //- Return const-access to the saturation vapour pressure
    const volScalarField& pSat() const
    {
        const volScalarField& pSat = Foam::twoPhaseMixture::alpha1_.db().lookupObject("pSat");
        return pSat;
    }
以上で修正終了。 $ wclean $ wmake

コンパイルログ
    tokudy@tokudy-desktop:~/OpenFOAM/tokudy-8/run/myiPCFPsat$ wmake
Making dependency list for source file myiPCF.C
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3  -DNoRepository -ftemplate-depth-100 -I. -I/opt/openfoam8/src/transportModels/lnInclude -I/opt/openfoam8/src/twoPhaseModels/twoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/interfaceProperties/lnInclude -I/opt/openfoam8/src/twoPhaseModels/incompressibleTwoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude -IphaseChangeTwoPhaseMixtures/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/momentumTransportModels/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/incompressible/lnInclude -I/opt/openfoam8/src/finiteVolume/lnInclude -I/opt/openfoam8/src/dynamicFvMesh/lnInclude -I/opt/openfoam8/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam8/src/OpenFOAM/lnInclude -I/opt/openfoam8/src/OSspecific/POSIX/lnInclude   -fPIC -c myiPCF.C -o Make/linux64GccDPInt32Opt/myiPCF.o
g++ -std=c++11 -m64 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32 -Wall -Wextra -Wold-style-cast -Wnon-virtual-dtor -Wno-unused-parameter -Wno-invalid-offsetof -Wno-attributes -O3  -DNoRepository -ftemplate-depth-100 -I. -I/opt/openfoam8/src/transportModels/lnInclude -I/opt/openfoam8/src/twoPhaseModels/twoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/interfaceProperties/lnInclude -I/opt/openfoam8/src/twoPhaseModels/incompressibleTwoPhaseMixture/lnInclude -I/opt/openfoam8/src/twoPhaseModels/immiscibleIncompressibleTwoPhaseMixture/lnInclude -IphaseChangeTwoPhaseMixtures/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/momentumTransportModels/lnInclude -I/opt/openfoam8/src/MomentumTransportModels/incompressible/lnInclude -I/opt/openfoam8/src/finiteVolume/lnInclude -I/opt/openfoam8/src/dynamicFvMesh/lnInclude -I/opt/openfoam8/src/meshTools/lnInclude -IlnInclude -I. -I/opt/openfoam8/src/OpenFOAM/lnInclude -I/opt/openfoam8/src/OSspecific/POSIX/lnInclude   -fPIC -fuse-ld=bfd -Xlinker --add-needed -Xlinker --no-as-needed Make/linux64GccDPInt32Opt/myiPCF.o -L/opt/openfoam8/platforms/linux64GccDPInt32Opt/lib \
    -lphaseChangeTwoPhaseMixtures -ltwoPhaseMixture -linterfaceProperties -ltwoPhaseProperties -lincompressibleTransportModels -lmomentumTransportModels -lincompressibleMomentumTransportModels -lfiniteVolume -ldynamicFvMesh -ltopoChangerFvMesh -lfvOptions -lmeshTools -lOpenFOAM -ldl  \
     -lm -o /opt/openfoam8/platforms/linux64GccDPInt32Opt/bin/myiPCF
コンパイル通っているぽい。おk.