select_arrow
Shinji_Nakagawa
64
0
0

OpenFOAMカスタマイズの始め方

Published at November 8, 2019 8:21 p.m.
Edited at November 15, 2019 2:31 p.m.

OpenFOAMカスタマイズの始め方

2019年11月16日オープンCAE勉強会@富山(富山県立大学 中川慎二)

Disclaimer

OPENFOAM® is a registered trade mark of OpenCFD Limited, the producer of the OpenFOAM software and owner of the OPENFOAM® and OpenCFD® trade marks. This offering is not approved or endorsed by OpenCFD Limited.

注意

 本資料の内容は,OpenFOAMユーザーガイド,プログラマーズガイド,OpenFOAM Wiki,CFD Online,その他多くの情報を参考にしています。開発者,情報発信者の皆様に深い謝意を表します。
 
 内容は,講師の個人的な経験(主に,卒研生等とのコードリーディング)から得た知識を共有するものです。この内容の正確性を保証することはできません。この情報を使用したことによって問題が生じた場合,その責任は負いかねますので,予めご了承ください。

はじめに

OpenFOAMをはじめてカスタマイズする初心者を想定し,基礎の基礎をハンズオン形式で学びます。OpenFOAMの改造をどこからはじめて良いか分からないといった人が,元のコードをコピーして,新たな名前のモデルやライブラリを作る手順を確認していきます。

参考サイト1:オープンCAE勉強会@富山(第34回2015年7月25日)「OpenFOAM 非ニュートンモデル カスタマイズ(秋山氏)」

参考サイト2:上記の補足説明とコード

上記参考サイトの情報と,本演習との違いを考えることで,同じ結果を得るための複数のカスタマイズ方法を知ることができます。

下記の内容の一部や,ライブラリによる違いについても説明する予定です。
参考サイト3

基本方針

改造は少しずつ。改造・コンパイル・テストを細かくくり返す。

エラーが発生した場合には,エラーメッセージをしっかりと読む。1番はじめのエラーへ対応する。

使用環境の確認

使用するマシンのOpenFOAMの環境を確認する。

bash
user@user-VirtualBox:~$ echo $WM_PROJECT_DIR 
/home/user/OpenFOAM/OpenFOAM-v1812
user@user-VirtualBox:~$ echo $FOAM_SRC 
/home/user/OpenFOAM/OpenFOAM-v1812/src
user@user-VirtualBox:~$ echo $FOAM_SOLVERS 
/home/user/OpenFOAM/OpenFOAM-v1812/applications/solvers
user@user-VirtualBox:~$ echo $FOAM_TUTORIALS 
/home/user/OpenFOAM/OpenFOAM-v1812/tutorials

user@user-VirtualBox:~$ echo $WM_PROJECT_USER_DIR 
/home/user/OpenFOAM/user-v1812
user@user-VirtualBox:~$ echo $FOAM_RUN 
/home/user/OpenFOAM/user-v1812/run
user@user-VirtualBox:~$ echo $FOAM_USER_APPBIN 
/home/user/OpenFOAM/user-v1812/platforms/linux64GccDPInt32Opt/bin
user@user-VirtualBox:~$ echo $FOAM_USER_LIBBIN 
/home/user/OpenFOAM/user-v1812/platforms/linux64GccDPInt32Opt/lib

ソルバのカスタマイズ手順の確認

既存のソルバをコピー,名前の変更,コンパイル

copy original files (solver)

コピー元: $FOAM_SOLVERS/incompressible/simpleFoam/

コピー先: $WM_PROJECT_USER_DIR/solvers/

bash
cp -r $FOAM_SOLVERS/incompressible/simpleFoam/ $WM_PROJECT_USER_DIR/solvers/

今回は不要な3つのディレクトリ(overSimpleFoam porousSimpleFoam SRFSimpleFoam)を削除する。

bash
cd $WM_PROJECT_USER_DIR/solvers/simpleFoam
rm -r *Foam

名前の変更

ディレクトリ名,ファイル名,ファイル中のクラス名や関数名を変更する。

変更前: simpleFoam

変更後: mySimpleFoam

ディレクトリ名を simpleFoam から mySimpleFoam に変更する。

bash
cd $WM_PROJECT_USER_DIR/solvers/
mv simpleFoam mySimpleFoam

ファイル名を simpleFoam.C から mySimpleFoam.C に変更する。

bash
cd mySimpleFoam
mv simpleFoam.C mySimpleFoam.C

mySimpleFoam.CMake/files の中に現れる simpleFoammySimpleFoam に変更する。さらに,Make/files の中で,コンパイル後のファイル保存先を FOAM_APPBIN から FOAM_USER_APPBIN に変更する。

bash
sed -i s/simpleFoam/mySimpleFoam/g mySimpleFoam.C
sed -i s/simpleFoam/mySimpleFoam/g Make/files
sed -i s/FOAM_APPBIN/FOAM_USER_APPBIN/g Make/files

コンパイル

正しく変更できたかを確認するため,コンパイルする。端末上で $WM_PROJECT_USER_DIR/solvers/mySimpleFoam に移動し,wmake コマンドを実行する。wmake は,OpenFOAMに付属するスクリプトであり,一般的にコンパイルに使われる make コマンドにOpenFOAMに必要な設定などが追加されている。

bash
cd $WM_PROJECT_USER_DIR/solvers/mySimpleFoam
wclean
wmake

エラーがないことを確認する。さらに,ディレクトリ $FOAM_USER_APPBIN (これは $WM_PROJECT_USER_DIR/platforms/linux64GccDPInt32Opt/bin/と同じ。コンパイルオプションによって異なる場合がある。) に ファイル mySimpleFoam が作成されていることを確認する。

bash
cd $FOAM_USER_APPBIN
ls -al

テスト用例題(ケース)の作成

copy original files (tutorial)

標準例題を複製し,作成したソルバが動作することを確認するための例題を作成する。

コピー元: $FOAM_TUTORIALS/incompressible/simpleFoam/bump2D/

コピー先: $FOAM_RUN

bash
cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/bump2D/ $FOAM_RUN

system/controlDictの編集(application名の変更)

作業先の bump2D ディレクトリに移動する。system/controlDictファイル内のsimpleFoammySimpleFoam に変更する。

bash
cd $FOAM_RUN/bump2D
sed -i s/simpleFoam/mySimpleFoam/g system/controlDict

計算実行と結果の確認

過去の実行結果を削除し,改めて,Allrunスクリプトにより計算を実行する。

bash
foamCleanTutorials
./Allrun

ケースディレクトリに log.mySimpleFoam が作成されていることを確認する。そのファイルを開き,mySimpleFoam が実行されていることを確認する。(ファイル冒頭部分の Exec: 欄にソルバ名が記録されている。)

計算が完了するまでは時間がかかる。途中で停止したい場合には,計算を実行した端末上で Ctrl + C キーを入力する。

ライブラリのカスタマイズ手順の確認(ライブラリ全体の複製)

ここでは,OpenFOAMの全ライブラリを格納する src ディレクトリ全体をコピーし,その中で改造が必要な部分だけを変更する方法について説明する。

大まかな作業手順は,既存の全ライブラリをコピー,改造部分の名前の変更,コンパイルとなる。

copy original files (library)

コピー元: $FOAM_SRC

コピー先: $WM_PROJECT_USER_DIR/src/

OpenFOAMのsrcディレクトリ全体を,ユーザのディレクトリにコピーする。ファイル数が多いので,少し時間がかかる。

bash
cp -r $FOAM_SRC  $WM_PROJECT_USER_DIR/src/

モデルの複製と名前の変更

OpenFOAMに標準で作成されているCrossPowerLaw(非ニュートン粘性モデル)から,myCrossPowerLawモデルを作成する。ファイル名,ファイル中のクラス名や関数名を変更する。

コピー元 $WM_PROJECT_USER_DIR/src/transportModels/incompressible/viscosityModels/CrossPowerLaw

コピー先 $WM_PROJECT_USER_DIR/src/transportModels/incompressible/viscosityModels/myCrossPowerLaw

bash
cp -r $WM_PROJECT_USER_DIR/src/transportModels/incompressible/viscosityModels/CrossPowerLaw  $WM_PROJECT_USER_DIR/src/transportModels/incompressible/viscosityModels/myCrossPowerLaw

新しく作成されたmyCrossPowerLawディレクトリへ移動する。そこに格納されている2つのファイル名を,CrossPowerLawからmyCrossPowerLawへ変更する。

bash
cd $WM_PROJECT_USER_DIR/src/transportModels/incompressible/viscosityModels/myCrossPowerLaw
mv CrossPowerLaw.C myCrossPowerLaw.C
mv CrossPowerLaw.H myCrossPowerLaw.H

上記の作業で作成された myCrossPowerLaw.H および myCrossPowerLaw.C ファイルの中で,CrossPowerLaw とかかれた部分を,myCrossPowerLaw に書き換える。(ファイルを開いて,エディタの検索と置換機能を使う。あるいは,下記コマンドを実行する。)

bash
sed -i s/CrossPowerLaw/myCrossPowerLaw/g myCrossPowerLaw.H
sed -i s/CrossPowerLaw/myCrossPowerLaw/g myCrossPowerLaw.C

myCrossPowerLaw関連ファイルがコンパイルされるように,$WM_PROJECT_USER_DIR/src/transportModels/incompressible/Make の中にあるfiles ファイルを修正する。

5行目をコピーし,6行目に貼り付けて次のように修正する。
viscosityModels/myCrossPowerLaw/myCrossPowerLaw.C

さらに,コンパイル後の保存先を FOAM_LIBBIN から FOAM_USER_LIBBIN に変更する。

bash
cd $WM_PROJECT_USER_DIR/src/transportModels/incompressible/Make
sed -i -e '/CrossPowerLaw.C$/a viscosityModels\/myCrossPowerLaw\/myCrossPowerLaw.C' files
sed -i s/FOAM_LIBBIN/FOAM_USER_LIBBIN/g files

コンパイル

ディレクトリ $WM_PROJECT_USER_DIR/src/transportModels/incompressible から,wmake コマンドを実行して,ソースコードをコンパイルする。

bash
cd $WM_PROJECT_USER_DIR/src/transportModels/incompressible
wclean
wmake

コンパイルに成功すると,$FOAM_USER_LIBBINlibincompressibleTransportModels.so というファイルが生成される。[ 講習会用マシンでは, home/user/OpenFOAM/user-v1812/platforms/linux64GccDPInt32Opt/lib/libincompressibleTransportModels.so となる。]

動作確認

例題

先ほど作成した例題 $FOAM_RUN/bump2D を使って,作成したモデルの実行を確認する。

例題で使用する粘性モデルをmyCrossPowerLawに変更する。constant/transportProperties
ファイルを開き,transportModel に myCrossPowerLaw を指定する。myCrossPowerLawCoeffsを次のように指定する。($FOAM_TUTORIALS/incompressible/nonNewtonianIcoFoam/offsetCylinder/constant/transportProperties を参考にしてもよい。)

transportModel  myCrossPowerLaw;
myCrossPowerLawCoeffs
{
    nu0         0.01;
    nuInf       10;
    m           0.4;
    n           3;
}

例題を実行し,ログを確認して,問題ないことを確認する。ログの冒頭付近に,下記の記述があり,作成したモデルが使用されていることを確認する。

Selecting incompressible transport model myCrossPowerLaw

ライブラリのカスタマイズ(新しい粘性モデルだけを含むライブラリの作成)

copy original files

OpenFOAM標準のCrossPowerLawモデルのコードだけを,$WM_PROJECT_USER_DIR/src ディレクトリにコピーする。

bash
cp -r $FOAM_SRC/transportModels/incompressible/viscosityModels/CrossPowerLaw/  $WM_PROJECT_USER_DIR/src/newCrossPowerLaw/

コピーしたファイルの名前を,CrossPowerLawからnewCrossPowerLawに変更する。CrossPowerLaw.depファイルが存在する場合には削除する。

bash
cd $WM_PROJECT_USER_DIR/src/newCrossPowerLaw/
mv CrossPowerLaw.H newCrossPowerLaw.H
mv CrossPowerLaw.C newCrossPowerLaw.C

同じディレクトリ内に,コンパイルに必要な情報をコピーする。非ニュートン粘性モデルライブラリのためのMakeディレクトリ($FOAM_SRC/transportModels/incompressible/Make/)を,$WM_PROJECT_USER_DIR/src/newCrossPowerLaw/ にコピーする。

bash
cp -R $FOAM_SRC/transportModels/incompressible/Make/  $WM_PROJECT_USER_DIR/src/newCrossPowerLaw/

modify source files

ファイル内のモデル名をnewCrossPowerLawに変更する。

bash
sed -i s/CrossPowerLaw/newCrossPowerLaw/g newCrossPowerLaw.H
sed -i s/CrossPowerLaw/newCrossPowerLaw/g newCrossPowerLaw.C

Make ディレクトリの files と options ファイルを修正

新たなモデルを独立したライブラリとしてコンパイルするために,コンパイルに必要な情報を修正する。この情報は,$WM_PROJECT_USER_DIR/src/newCrossPowerLaw/Make ディレクトリ内に格納されている。

bash
cd $WM_PROJECT_USER_DIR/src/newCrossPowerLaw/Make

Make/files

新しく作成したソースコード newCrossPowerLaw.C だけをコンパイルし,libnewCrossPowerLawという名前のライブラリを作成する。filesファイルの内容を下記に書き換える。

C++
newCrossPowerLaw.C

LIB = $(FOAM_USER_LIBBIN)/libnewCrossPowerLaw

Make/options

新しく作成したソースコード newCrossPowerLaw.C のコンパイルに必要なインクルードファイルの場所を指定する。また,newCrossPowerLawモデルを通常の非ニュートンモデルと入れ替えて使えるように,incompressibleTransportModelsライブラリを指定する。

EXE_INC = \
    -I$(LIB_SRC)/transportModels/incompressible/lnInclude \
    -I$(LIB_SRC)/finiteVolume/lnInclude
LIB_LIBS = \
   -lincompressibleTransportModels \
   -lfiniteVolume

compile

bash
cd $WM_PROJECT_USER_DIR/src/newCrossPowerLaw
wmake

ライブラリなので,wmake libso としてもよい。wmake を実行するだけでも,自動的にそうなっている。

コンパイルに成功すると,$FOAM_USER_LIBBINlibnewCrossPowerLaw.so というファイルが生成される。

create a tutarial case

先ほど作成した例題 $FOAM_RUN/bump2D を使って,作成したライブラリとモデルの実行を確認する。

testCrossLaw 例題ディレクトリに移動する。不要な情報を削除して,まっさらな状態に戻すため,foamCleanTutorials を実行する。

bash
cd $FOAM_RUN/bump2D/
foamCleanTutorials

作成したライブラリを使用するために,controlDictにライブラリを登録する。下記の内容を,controlDict最後に追加する。

C++
libs
(
    "libnewCrossPowerLaw.so"
);

newCrossPowerLawモデルを使うように,constant/transportPropertiesを変更する。元のファイルにおいて,myCrossPowerLawをnewCrossPowerLawに書き換える。

bash
sed -i s/myCrossPowerLaw/newCrossPowerLaw/g ./constant/transportProperties

blockMesh でメッシュを生成,Allrunスクリプト を実行する。

bash
./Allrun

ログを確認して,問題ないことを確認する。ログの冒頭付近に,下記の記述があり,作成したモデルが使用されていることを確認する。

Selecting incompressible transport model newCrossPowerLaw

考察

src 丸ごとコピーと,クラス単位の改造,どちらが良いの?

手っ取り早いのは、丸ごとコピー。

ただし,標準ディレクトリとユーザーディレクトリに,重複した同一コードが多数存在する状態となる。これは,危険をはらむ。

クラス単位の場合,直接改造した部分以外は,標準のコードが使われる。思わぬコード違いが防げる。

個人の意見:クラス単位の改造を推奨する。バージョン変更への追随も容易になるか?

乱流モデルとtransportModelとの違い

Make/files を見て確認する。

乱流モデルは,マクロを活用して,1組のコードから複数の種類(圧縮性/非圧縮性)のクラスを生成する。そのため,複雑に見える。

乱流モデルの生成に使われるマクロや,単独の乱流モデルをライブラリにする方法などは,下記に説明がある。
参考サイト3

モデルのさらなる改造

非ニュートン粘性モデルの検証に使えるように,ひずみ速度を出力するための変更を加える。

newCrossPowerLaw.H の修正

newCrossPowerLaw.H の70行目付近に,volScalarFieldクラスの変数として,変数 strainRate_ を宣言する。OpenFOAMの流儀に従って,クラス内の変数名最後にはアンダーバー_を付している。

なお,strainRate_ の宣言は,変数 nu_ の前に書くことが必要である。これは,後ほど確認する初期化方法に関連している。

さらに,同じファイル内で,関数 calcNu() のconst指定をコメントアウトする。これは,この関数内で歪み速度を計算して,変数 strainRate_ の値を変更するためである。コードの該当部分を下にしめす。

C++
protected:

    // Protected data

        volScalarField strainRate_; // newly added
        volScalarField nu_;

    // Protected Member Functions

        //- Calculate and return the laminar viscosity
        tmp<volScalarField> calcNu(); //"const" is commented out.

newCrossPowerLaw.C の修正

newCrossPowerLaw.C の51行目付近で,calcNu() 関数のconst指定をコメントアウトする。

この関数の中で,変数 strainRate_ に,関数 strainRate() で求めた値を代入する。returnする値の計算式ないで,関数 strainRate() を呼び出していた部分を,先に値を定めた変数 strainRate_ に置き換える。改訂する部分を下記に示す。

なお,ここで使用する strainRate() 関数は,newCrossPowerLawクラスが継承している元のクラス viscosityModel で定義されている。

C++
Foam::tmp<Foam::volScalarField>
Foam::viscosityModels::newCrossPowerLaw::calcNu() //const//const is commented out.
{
    strainRate_ = strainRate(); 
    return (nu0_ - nuInf_)/(scalar(1) + pow(m_*strainRate_, n_)) + nuInf_;
    //return (nu0_ - nuInf_)/(scalar(1) + pow(m_*strainRate(), n_)) + nuInf_;
}

さらに,newCrossPowerLaw.C の78行目付近で,Constructor の初期化部分に,変数 strainRate_ を加える。初期化リストは,変数を宣言した順に並べる必要がある。そのため,,strainRate_ の初期化を,変数 nu_ の前に記述する。

ここで,変数 nu_ の初期化方法を見ると,calcNu() 関数が使われている。今回のプログラム改造では,この関数内でstrainRate_ 変数を扱うため,strainRate_ を先に初期化した。

C++
    strainRate_
    (
        IOobject
        (
            "strainRate",
            U_.time().timeName(),
            U_.db(),
            IOobject::NO_READ,
            IOobject::AUTO_WRITE
        ),
        U_.mesh(),
        dimensionedScalar("strainRate", dimVelocity/dimLength, Zero) //or strainRate()
    ),
    nu_
    (
        IOobject
        (
            name,
            U_.time().timeName(),
            U_.db(),
            IOobject::NO_READ,
            IOobject::AUTO_WRITE
        ),
        calcNu()
    )

参考のために,作成したコード類を圧縮して添付する。

newCrossPowerLaw.zip

コンパイル

bash
cd $WM_PROJECT_USER_DIR/src/newCrossPowerLaw
wmake

動作確認

例題を実行する。結果の時刻ディレクトリに,strainRateというファイルが書き出されていることを確認する。そのファイル内の情報が正しいことを確認する。

参考情報:クリックで折りたたみ表示の設定/解除が切り替えられます。

参考情報

ソルバからの書き出しにfunctionObjectが使えるのか?

OpenFOAMのバージョン2.0.0から追加された runtimeCodeCompilation 機能によって,ソルバを改造せずに,歪み速度を書き出すことを検討する。下記サイトの紹介では,簡単な使用例が記載されている。

http://www.openfoam.org/version2.0.0/runtime-control.php#runtimeCodeCompilation

functions 
( 
    pAverage 
    { 
        functionObjectLibs ("libutilityFunctionObjects.so"); 
        type coded; 
        redirectType average; 
        outputControl outputTime; 
        code 
        #{ 
            const volScalarField& p = 
                mesh().lookupObject<volScalarField>("p"); 
            Info<<"p avg:" << average(p) << endl;
        #}; 
    } 
); 

OpenFOAMユーザーガイドにも,説明がある。

OpenFOAM User Guide: 6.2 Function Objects
http://cfd.direct/openfoam/user-guide/function-objects/

ソルバ内に作成されている変数を書き出すためには,writeRegisteredObject タイプを使用する。変数を新たに定義して書き出すためには,これは使えない。少し込み入ったコードを作成する必要がある。

CFD-Online に,関連するディスカッションが存在する。下記のポスト#9を参考にして,サンプルを作成した。
http://www.cfd-online.com/Forums/openfoam-programming-development/99207-create-registered-object-runtime-using-functionobject.html#post384295

functions 
( 
    str 
    { 
        functionObjectLibs ("libutilityFunctionObjects.so"); 
        type coded; 
        redirectType strRate; // arbitrary name

        //outputControl outputTime;    // for Info
    
        outputControl   timeStep;   // for Info
        outputInterval  1;          // strRate avg will be written every time step
    
        code 
        #{ 
            const volVectorField& U = mesh().lookupObject<volVectorField>("U");
            static autoPtr<volScalarField> pField;
    
            if(!pField.valid())
            {
                Info << "Creating strRatio" << nl;
                pField.set
                (
                        new volScalarField
                        (
                             IOobject
                             (
                                 "strRatio",
                                  mesh().time().timeName(),
                                  U.mesh(),
                                  IOobject::NO_READ,
                                  IOobject::AUTO_WRITE
                             ),
                             Foam::sqrt(2.0)*mag(symm(fvc::grad(U)))
                        )
                );
            }
    
            volScalarField &strRatio = pField();
    
            strRatio.checkIn();
    
            strRatio = Foam::sqrt(2.0)*mag(symm(fvc::grad(U)));
    
            Info<<"strRate avg:" << average(strRatio) << endl; 
    
        #}; 
    } 
); 

function objects に関する参考サイト

function objects
http://www.geocities.co.jp/penguinitis2002/study/OpenFOAM/function_objects.html

Tip Function Object writeRegisteredObject
https://openfoamwiki.net/index.php/Tip_Function_Object_writeRegisteredObject

cfd-online
http://www.cfd-online.com/Forums/openfoam/75049-how-get-density-field-compressible-flow.html#post254920