[OpenFOAM] 변경 수법 추가 처리 ③: 함수 또는 클래스로 추가 처리

CAE 추가 캘린더 열기 8일째 신청이다.

개시하다


"OpenFOAM" 변경 수법 추가 처리 ②: 구해기에서 추가 처리 "의 계속.
OpenFOAM의 계산에서 수법을 바꾸어 추가 처리하다.지난번에 구해기의main () 함수에서 처리를 설명했습니다.
이번에 소개한 것은 이 처리를 함수나 클래스로 만들고main() 함수로 호출하는 방법이다.


방법 일람


이 기사는 다양한 기법을 소개하는 시리즈 중 하나로 전체적으로 다음과 같은 방법으로 진행될 예정이다.실행이 확인된 파일은 GitHub에 공개됩니다.
  • 예제 준비(키워드: pimpleFoam)
  • 기존 기능(키워드: functionObjects)
  • 컴퓨팅 파일에 쓰기 처리(키워드: codedFunctionObject)
  • 해결기에 처리 추가
  • 함수와 클래스로 처리 추가 ★지금 여기
  • 상속 클래스에 처리 추가
  • 설정 항목 실행 시 읽기(키워드: IOdictionary
  • 상속 클래스를 실행할 때 상속 클래스를 선택합니다(키워드: runTimeSelectionTable
  • 추가 컴파일 클래스(키워드: wmake libso
  • 계승 클래스 중 하나로 코드드 추가(키워드: codedTemplete
  • 작업 환경

  • OS : Ubuntu 20.04 LTS (WSL2 on Windows 10)
  • OpenFOAM: ESI 버전 v2006(from source)
  • gcc : 9.3.0
  • 함수 추가 처리


    우선 처리의 함수화를 시도해 보자.따라서 여러 곳에서 호출 처리를 할 때 코드가 대폭 간소화된다.

    미리 준비하다


    다음 스크립트를 만들고 실행합니다.이것에 따라 원래pimpleFoam와 그 강좌가 복제되었다.앞으로 이 스크립트를 실행했다는 전제로 진행될 겁니다.prepareFuncCase.sh
    #!/bin/bash
    
    # (任意) 今回作成するディレクトリとソルバーとケースに名前をつける
    dirName=$FOAM_RUN/003.class
    solverName=scoreFuncPimpleFoam
    caseName=funcCase
    
    mkdir -p $dirName
    
    # ソルバーのコピー
    cp -r $FOAM_SOLVERS/incompressible/pimpleFoam $dirName/$solverName
    rm -r $dirName/$solverName/overPimpleDyMFoam $dirName/$solverName/SRFPimpleFoam 
    sed -i -e "s/APPBIN)\/pimpleFoam/USER\_APPBIN)\/${solverName}/g" $dirName/$solverName/Make/files
    cp $FOAM_SRC/finiteVolume/cfdTools/general/CorrectPhi/CorrectPhi.H $dirName/$solverName/cpCorrectPhi.H
    sed -i -e "s/CorrectPhi.H/cpCorrectPhi.H/" $dirName/$solverName/pimpleFoam.C
    echo "Solver : $dirName/$solverName"
    
    # チュートリアルのコピー
    cp -r $FOAM_TUTORIALS/incompressible/pimpleFoam/RAS/TJunction $dirName/$caseName
    sed -i -e "s/pimpleFoam/${solverName}/" ${dirName}/${caseName}/system/controlDict
    # 元々の1.5秒を計算する必要は無いので減らす
    sed -i -e "s/^endTime.*/endTime         0.3;/" ${dirName}/${caseName}/system/controlDict
    # functionObjectの記述を削除
    startLine=`cat ${dirName}/${caseName}/system/controlDict | grep -n "^functions" | sed -e 's/:.*//g'`
    endLine=`cat ${dirName}/${caseName}/system/controlDict | wc -l`
    sed -i -e "${startLine},${endLine}d" ${dirName}/${caseName}/system/controlDict
    echo "Case   : $dirName/$caseName"
    

    함수 정의


    함수는main () 함수 앞에 정의됩니다.다음은 pimpleFoam입니다.함수가 C의 #includemain() 사이에서 어떻게 움직이는지 기술하다.
    다음은 getScore라는 함수를 정의했다.fvMesh는 클래스를 매개 변수로 하고 출입구 유량의 총계를 scalar클래스로 정의한다.
    #include "fvCFD.H"
    #include "dynamicFvMesh.H"
    #include "singlePhaseTransportModel.H"
    #include "turbulentTransportModel.H"
    #include "pimpleControl.H"
    #include "cpCorrectPhi.H"
    #include "fvOptions.H"
    
    // 85行目付近 ここを追加
    scalar getScore(const fvMesh& mesh_)
    {
        const surfaceScalarField& phi = mesh_.lookupObject<surfaceScalarField>("phi");
        scalar score_ = 0.0;
    
        forAll(phi.boundaryField(), patchI)
        {
            const fvPatch& patch = phi.boundaryField()[patchI].patch();
            const scalarField& pphi =  phi.boundaryField()[patchI];
            if (!(patch.name()=="inlet" || patch.name()=="outlet1" || patch.name()=="outlet2")) continue;
            Info << "    sum(" << patch.name() << ") of phi = " << gSum(pphi) << endl;
            score_ += gSum(pphi);
        }
    
        return score_;
    }
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    int main(int argc, char *argv[])
    {
    

    호출 함수


    이 정의의 함수를 호출하기 위해 pimpleFoam.Cmain() 함수에서 다음과 같다.
                if (pimple.turbCorr())
                {
                    laminarTransport.correct();
                    turbulence->correct();
                }
            }
    
            // 187行目付近。この2行を追加する。
            const scalar score = getScore(mesh);
            Info << nl << "score: " << runTime.value() << tab << score << nl << endl;
    
            runTime.write();
    
    에서 score이라는 변수에 getScore() 함수로 계산된 유량 총계를 저장하고 Info로 출력한다.

    컴파일 및 테스트


    다음과 같이 컴파일합니다.
    $ cd $FOAM_RUN/003.class/scoreFuncPimpleFoam
    $ wclean
    $ wmake
    
    출력이 잘못되지 않으면 다음과 같이 해답을 실행해 보십시오.
    $ cd $FOAM_RUN/003.class/funcCase
    $ foamCleanTutorials
    $ foamRunTutorials
    
    는 다음과 같다log.scoreFuncPimpleFoamscore를 출력했는지 확인한다.
    $ cat $FOAM_RUN/003.class/funcCase/log.scoreFuncPimpleFoam | grep -e "score:" | sed "s/score: //"
    0.00120482      7.00171e-10
    0.00265769      1.88353e-10
    0.00439595      -7.65986e-10
    0.00647429      2.55232e-09
    0.0089355       3.27205e-09
    0.0118731       -1.48406e-09
    0.0153981       2.49265e-09
    0.0196282       2.54628e-09
    0.0246515       -9.17793e-09
    0.0304475       -6.57753e-09
    0.0374028       -4.7443e-09
    0.0452274       5.67256e-09
    0.0543562       -5.79236e-09
    0.0619635       -3.46103e-09
    0.0695708       -4.28805e-09
    0.0756566       -5.23626e-09
    0.0817425       2.75405e-09
    ...
    
    위의 그림과 같이 출력하면 됩니다.

    클래스에 처리 추가


    다음엔 처리용 클래스를 만들어 보자.

    미리 준비하다


    다음 스크립트를 실행하여 이전 이름과 다른 구해기scoreClassPimpleFoam와 상황funcCase을 만듭니다.아까 대본과 다른 건 첫 번째밖에 없어요.prepareClassCase.sh
    #!/bin/bash
    
    # (任意) 今回作成するディレクトリとソルバーとケースに名前をつける
    dirName=$FOAM_RUN/003.class
    solverName=scoreClassPimpleFoam #scoreFuncPimpleFoam
    caseName=classCase #funcCase
    
    mkdir -p $dirName
    
    # ソルバーのコピー
    cp -r $FOAM_SOLVERS/incompressible/pimpleFoam $dirName/$solverName
    rm -r $dirName/$solverName/overPimpleDyMFoam $dirName/$solverName/SRFPimpleFoam 
    sed -i -e "s/APPBIN)\/pimpleFoam/USER\_APPBIN)\/${solverName}/g" $dirName/$solverName/Make/files
    cp $FOAM_SRC/finiteVolume/cfdTools/general/CorrectPhi/CorrectPhi.H $dirName/$solverName/cpCorrectPhi.H
    sed -i -e "s/CorrectPhi.H/cpCorrectPhi.H/" $dirName/$solverName/pimpleFoam.C
    echo "Solver : $dirName/$solverName"
    
    # チュートリアルのコピー
    cp -r $FOAM_TUTORIALS/incompressible/pimpleFoam/RAS/TJunction $dirName/$caseName
    sed -i -e "s/pimpleFoam/${solverName}/" ${dirName}/${caseName}/system/controlDict
    # 元々の1.5秒を計算する必要は無いので減らす
    sed -i -e "s/^endTime.*/endTime         0.3;/" ${dirName}/${caseName}/system/controlDict
    # functionObjectの記述を削除
    startLine=`cat ${dirName}/${caseName}/system/controlDict | grep -n "^functions" | sed -e 's/:.*//g'`
    endLine=`cat ${dirName}/${caseName}/system/controlDict | wc -l`
    sed -i -e "${startLine},${endLine}d" ${dirName}/${caseName}/system/controlDict
    echo "Case   : $dirName/$caseName"
    

    .C 및.H


    오픈봄은 학급을 만들면서 선언과 정의를 분리하는 데 익숙해졌기 때문에 이번에도 그것대로 만들었다.즉, 구성은 다음과 같다.
  • 동명.C.H(예: getScore.CgetScore.H
  • 만들기

  • 설명: .H에서 "어떤 함수 변수 매개 변수가 있는지 설명합니다.

  • 정의: .C에서'함수 등 어떻게 동작하는지'를 기술합니다.
  • 구해기에서.H.
  • include 구해기와 분리하여 컴파일하고 구해기와 연결
  • 이것들을 어떻게 번역했는지에 대해Qita[OpenFOAM] 뭐 하는 거야?로 정리했으니 여기를 참조하세요.
    그렇다면 이 구성을 답습해 먼저 제작.CgetScore.H를 진행한다.

    디렉토리 구조


    이번 목표는 다음 목록 구성을 목표로 한다.
    ├── getScore
    │   ├── getScore.C
    │   └── getScore.H
    ├── Make
    │   ├── files
    │   └── options
    ├── UEqn.H
    ├── correctPhi.H
    ├── cpCorrectPhi.H
    ├── createFields.H
    ├── pEqn.H
    └── pimpleFoam.C
    
    따라서 다음과 같이 구해기의 디렉터리에 getScore.C 디렉터리를 만듭니다.
    $ mkdir -p $FOAM_RUN/003.class/scoreClassPimpleFoam/getScore
    
    아래에서 제작getScoregetScore.C.

    getScore/getScore.H


    먼저 아래와 같이 제작getScore.H.
    #ifndef getScore_H
    #define getScore_H
    
    #include "fvMesh.H"
    
    namespace Foam
    {
    class getScore
    {
    protected:
        // Protected data
            const fvMesh& mesh_;
            scalar score_;
    public:
        // Constructors
            getScore(const fvMesh& mesh);
        //- Destructor
            ~getScore()
            {}
        // Member Functions
            void calculate();
    
            const scalar& value() const
            {
                return score_;
            }
    };
    }
    
    #endif
    
    우선 이 반의 골격은 다음과 같다.
    namespace Foam
    {
        class getScore
        {
        public:
            // Constructors
                getScore(const fvMesh& mesh);
            //- Destructor
                ~getScore()
                {}
        };
    }
    
    getScore/getScore.H라는 OpenFOAM의namespace에서 getScore라는 반을 발표했다.또 구조기는 분석기Foam에 대해서도'아무것도 하지 않는다'는 정의를 내렸다고 밝혔다.
    또한 다음 부분에서 이 분류에 저장된 변수를 정의합니다.
    protected:
        // Protected data
            const fvMesh& mesh_;
            scalar score_;
    
    {}이기 때문에 이 종류에서만 protectedmesh_를 호출할 수 있다.
    다음 섹션에서는 함수를 설명합니다.
    public:
        // Member Functions
            void calculate();
    
            const scalar& value() const
            {
                return score_;
            }
    
    이 함수들score_이기 때문에 클래스 밖, 즉 구해기 등에서 호출할 수 있다.이번public에 점수 계산calculate()을 해서 그 값과 같은 구성을 되돌려줍니다.또한 value()는 간단한 함수이기 때문에 여기에 정의합니다.
    또한 본 클래스value()클래스는 변수로 사용되며, fvMesh클래스 성명을 읽기 위해 먼저 다음과 같다.
    #include "fvMesh.H"
    
    다음 부분은 다른 곳에fvMesh 성명 유형의 기술이 있을 때 중복을 피하는 데 쓰인다.이 경우 이전에 읽은 getScore를 사용합니다.하지만 신중하게 보기 위해서다. 원래 이름은 중복하지 않는 것이 좋으니 이름은 중복하지 않는 것이 좋다.
    #ifndef getScore_H
    #define getScore_H
    
    ...
    
    #endif
    

    getScore/getScore.C


    다음과 같이 정의 섹션을 생성합니다.
    #include "getScore.H"
    #include "surfaceFields.H"
    
    Foam::getScore::getScore
    (
        const fvMesh& mesh
    )
    :
        mesh_(mesh)
    {
    }
    
    void Foam::getScore::calculate()
    {
    
        Info << "Running calculate()" << endl;
    
        const surfaceScalarField& phi = mesh_.lookupObject<surfaceScalarField>("phi");
        score_ = 0.0;
    
        forAll(phi.boundaryField(), patchI)
        {
            const fvPatch& patch = phi.boundaryField()[patchI].patch();
            const scalarField& pphi =  phi.boundaryField()[patchI];
            if (!(patch.name()=="inlet" || patch.name()=="outlet1" || patch.name()=="outlet2")) continue;
            Info << "    sum(" << patch.name() << ") of phi = " << gSum(pphi) << endl;
            score_ += gSum(pphi);
        }
    }
    
    
    이 종류는 구조기, 분석기, 함수getScore, 함수calculate()가 있지만 분석기와 함수value()는 이미 value()에 정의되었고 나머지 구조기와 **함수getScore.Hcalculate()**에 의해 정의되었다.
    먼저 다음과 같이 구조기를 정의했다.
    Foam::getScore::getScore
    (
        const fvMesh& mesh
    )
    :
        mesh_(mesh)
    {
    }
    
    getScore.C 수신 클래스 지침은 클래스 내 변수fvMesh의 정의로 한다.이렇게 하면 구해기 옆의 격자에 접근할 수 있다.OpenFOAM의 경우 mesh_에 접근할 수 있다면 기본적으로 모든 것이 가능하지만 다른 구해기 측의 변수와 정보 등이 있다면 매개 변수와 변수를 만들 수 있다.
    이하fvMesh는 이번 목적의'출입구 유량의 총계를 구하는 것'으로 처리하고 있다.되돌아오는 값은 calculate()이기 때문에 이 함수 자체는 되돌아오지 않고'갱신 클래스 내 변수void'이다.
    void Foam::getScore::calculate()
    {
    
        Info << "Running calculate()" << endl;
    
        const surfaceScalarField& phi = mesh_.lookupObject<surfaceScalarField>("phi");
        score_ = 0.0;
    
        forAll(phi.boundaryField(), patchI)
        {
            const fvPatch& patch = phi.boundaryField()[patchI].patch();
            const scalarField& pphi =  phi.boundaryField()[patchI];
            if (!(patch.name()=="inlet" || patch.name()=="outlet1" || patch.name()=="outlet2")) continue;
            Info << "    sum(" << patch.name() << ") of phi = " << gSum(pphi) << endl;
            score_ += gSum(pphi);
        }
    }
    
    
    최초score_에서 이#include류의 선언으로 된 getScore.H와getScore 내 등장calculate()이 선언된surfaceFields.H를 불러오는 중입니다.surfaceScalarField 중 다른 사용하고 싶은 종류가 있을 때도 선언문을 읽어야 한다.
    #include "getScore.H"
    #include "surfaceFields.H"
    

    pimpleFoam.C

    calculate() 함수에서 위에서 설명한 getScore.CgetScore.H를 호출합니다.이를 위해 다음과 같이 3곳main()을 변경한다.
    pimpleFoam.C: 110번째 줄 근처
    (前略)
    #include "fvCFD.H"
    #include "dynamicFvMesh.H"
    #include "singlePhaseTransportModel.H"
    #include "turbulentTransportModel.H"
    #include "pimpleControl.H"
    #include "cpCorrectPhi.H"
    #include "fvOptions.H"
    
    // 85行目付近
    #include "getScore.H" // ★これを追加
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    int main(int argc, char *argv[])
    {
        #incl...(略)
        #include "CourantNo.H"
        #include "setInitialDeltaT.H"
    
        // 110行目付近
        getScore myScore(mesh); // ★これを追加
    
        turbulence->validate();
    
        // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
        Info<< "\nStarting time loop\n" << endl;
    
        while (runTime.run())
        {
    (中略)
    
                if (pimple.turbCorr())
                {
                    laminarTransport.correct();
                    turbulence->correct();
                }
            }
    
            // ★この2行を追加
            myScore.calculate();
            Info << nl << "score: " << runTime.value() << tab << myScore.value() << nl << endl;
    
            runTime.write();
    
            runTime.printExecutionTime(Info);
        }
    (後略)
    
    는 다음과 같이 pimpleFoam.C의 이름으로 클래스 대상을 만든다.
            getScore myScore(mesh);
    
    getScore 함수 업데이트myScorecalculate() 변수
            myScore.calculate();
    
    함수 호출 변수myScore.
            Info << nl << "score: " << runTime.value() << tab << myScore.value() << nl << endl;
    
    따라서 다음과 같이 구성된다.

    getScore.C의 컴파일


    이러다 getScoreC와 관련된 정보를 읽을 수 없습니다.getScore.C를 컴파일하기 위해 다음과 같이 score_ 디렉터리의 내용을 수정합니다.
    Make/files
    getScore/getScore.C # ★ここを追加
    pimpleFoam.C
    
    EXE = $(FOAM_USER_APPBIN)/scoreClassPimpleFoam
    
    Make/options
    EXE_INC = \
        -IgetScore \ # ★ここを追加
        -I$(LIB_SRC)/finiteVolume/lnInclude \
        -I$(LIB_SRC)/meshTools/lnInclude \
        -I$(LIB_SRC)/sampling/lnInclude \
        -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
        -I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
        -I$(LIB_SRC)/transportModels \
        -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
        -I$(LIB_SRC)/dynamicMesh/lnInclude \
        -I$(LIB_SRC)/dynamicFvMesh/lnInclude
    
    EXE_LIBS = \
        -lfiniteVolume \
        -lfvOptions \
        -lmeshTools \
        -lsampling \
        -lturbulenceModels \
        -lincompressibleTurbulenceModels \
        -lincompressibleTransportModels \
        -ldynamicMesh \
        -ldynamicFvMesh \
        -ltopoChangerFvMesh \
        -latmosphericModels
    

    컴파일 및 테스트


    다음과 같이 컴파일합니다.
    $ cd $FOAM_RUN/003.class/scoreClassPimpleFoam
    $ wclean
    $ wmake
    
    출력이 잘못되지 않으면 다음과 같이 해답을 실행해 보십시오.
    $ cd $FOAM_RUN/003.class/classCase
    $ foamCleanTutorials
    $ foamRunTutorials
    
    는 다음과 같다value()score를 출력했는지 확인한다.
    $ cat $FOAM_RUN/003.class/classCase/log.scoreClassPimpleFoam | grep -e "score:" | sed "s/score: //"
    0.00120482      7.00171e-10
    0.00265769      1.88353e-10
    0.00439595      -7.65986e-10
    0.00647429      2.55232e-09
    0.0089355       3.27205e-09
    0.0118731       -1.48406e-09
    0.0153981       2.49265e-09
    0.0196282       2.54628e-09
    0.0246515       -9.17793e-09
    0.0304475       -6.57753e-09
    0.0374028       -4.7443e-09
    0.0452274       5.67256e-09
    0.0543562       -5.79236e-09
    0.0619635       -3.46103e-09
    0.0695708       -4.28805e-09
    0.0756566       -5.23626e-09
    0.0817425       2.75405e-09
    ...
    
    위의 그림과 같이 출력하면 됩니다.

    최후


    이번에는 함수와 반을 추가하는 방법을 소개했다.


    처리가 복잡해진 상황에서 이처럼 함수나 클래스로 만들면 관리와 변경 등이 쉬워진다.
    다음에 이 반에 관해서 이 기능을 계승하는 것을 소개합니다.

    좋은 웹페이지 즐겨찾기