Challenge

Project 1- Creating your own openFOAM solver

Aim: Creating your own OpenFOAM solver, and Running a cavity test case with the created solver

Procedure: Here in this challenge we are trying to solve the scalar transport equation in the solver, we are using icoFoam solver for this challenge

The scalar transport equation is defined as:



where s is the scalar quantity being transported by the velocity u.

Temperature is a scalar property we are using for this challenge

Step by step Procedure is explained below with the respective images.

Step 1: Make a Working Directory

Step 2: Parallelly go to the Openfoam Solvers folder and find the incompressible folder and then find the icoFoam solver Folder

Step 3: Copy the icoFoam solver folder to your working directory

Step 4: Rename the Solver folder to your Choice (In my case NewIcoFoam)

Step 5: Go inside the solver (NewIcoFoam) folder, We can see .C file and .H file.

We are going to edit all the Folder and files Step by step

Step 6: First go Inside your icoFoam.C file, We can see the equations of momentum, pressure, and velocity is been solved in the code. Copy the Momentum predictor code and paste the code just after the velocity calculation loop. As shown in the figure (Line 158 - 167)

/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | www.openfoam.com
     \\/     M anipulation  |
-------------------------------------------------------------------------------
    Copyright (C) 2011-2016 OpenFOAM Foundation
    Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.

Application
    NewIcoFoam

Group 
    grpIncompressibleSolvers

Description
    Transient solver for incompressible, laminar flow of Newtonian fluids.

    \heading Solver details
    The solver uses the PISO algorithm to solve the continuity equation:

        \f[
            \div \vec{U} = 0
        \f]

    and momentum equation:

        \f[
            \ddt{\vec{U}}
          + \div \left( \vec{U} \vec{U} \right)
          - \div \left(\nu \grad \vec{U} \right)
          = - \grad p
        \f]

    Where:
    \vartable
        \vec{U} | Velocity
        p       | Pressure
    \endvartable

    \heading Required fields
    \plaintable
        U       | Velocity [m/s]
        p       | Kinematic pressure, p/rho [m2/s2]
    \endplaintable

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

#include "fvCFD.H"
#include "pisoControl.H"

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

int main(int argc, char *argv[])
{
    argList::addNote
    (
        "Transient solver for incompressible, laminar flow"
        " of Newtonian fluids."
    );

    #include "postProcess.H"

    #include "addCheckCaseOptions.H"
    #include "setRootCaseLists.H"
    #include "createTime.H"
    #include "createMesh.H"

    pisoControl piso(mesh);

    #include "createFields.H"
    #include "initContinuityErrs.H"

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

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

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

        #include "CourantNo.H"

        // Momentum predictor

        fvVectorMatrix UEqn
        (
            fvm::ddt(U)
          + fvm::div(phi, U)
          - fvm::laplacian(nu, U)
        );

        if (piso.momentumPredictor())
        {
            solve(UEqn == -fvc::grad(p));
        }

        // --- PISO loop
        while (piso.correct())
        {
            volScalarField rAU(1.0/UEqn.A());
            volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
            surfaceScalarField phiHbyA
            (
                "phiHbyA",
                fvc::flux(HbyA)
              + fvc::interpolate(rAU)*fvc::ddtCorr(U, phi)
            );

            adjustPhi(phiHbyA, U, p);

            // Update the pressure BCs to ensure flux consistency
            constrainPressure(p, U, phiHbyA, rAU);

            // Non-orthogonal pressure corrector loop
            while (piso.correctNonOrthogonal())
            {
                // Pressure corrector

                fvScalarMatrix pEqn
                (
                    fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
                );

                pEqn.setReference(pRefCell, pRefValue);

                pEqn.solve(mesh.solver(p.select(piso.finalInnerIter())));

                if (piso.finalNonOrthogonalIter())
                {
                    phi = phiHbyA - pEqn.flux();
                }
            }

            #include "continuityErrs.H"

            U = HbyA - rAU*fvc::grad(p);
            U.correctBoundaryConditions();

        }
        //Scalar Equation Solver 
        fvScalarMatrix SEqn
        (
            fvm::ddt(S)
          + fvm::div(phi, S)       //Flux Term
          - fvm::laplacian(DS, S)  //Diffusive Term
        );

        SEqn.solve();
        S.correctBoundaryConditions();

        runTime.write();

        runTime.printExecutionTime(Info);
    }

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

    return 0;
}


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

Explanation: Here we Are typing to solve a scaler quantity S, S can be any Scalar quantity. So using the Finite Volume Method scheme we are trying to solve time derivative, flux Term, and Diffusive term.

Step 7: Updating The createFields.H, adding scalar Field, and creating Scalar IOobject. adding lines from 58-71. Scalar IOobject is created

Info<< "Reading transportProperties\n" << endl;

IOdictionary transportProperties
(
    IOobject
    (
        "transportProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ_IF_MODIFIED,
        IOobject::NO_WRITE
    )
);

dimensionedScalar nu
(
    "nu",
    dimViscosity,
    transportProperties
);

dimensionedScalar DS
(
    "DS",
    dimViscosity,
    transportProperties
);

Info<< "Reading field p\n" << endl;
volScalarField p
(
    IOobject
    (
        "p",
        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
);

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

#include "createPhi.H"


label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("PISO"), pRefCell, pRefValue);
mesh.setFluxRequired(p.name());

Step 8: Now we need to edit the "make" file. Edit the "files" file in the make file by changing the Name of the .C (icoFoam.C) file to NewIcoFoam.C which we saved outside the make file

Step 9: Everything is set, For making your own Solver for the test case.

Check Table

Name of the files Checked
NewIcoFoam.C Done
icoFoam.H Done
Make/files Done

Step 10: Run "wmake" command. If it is a successful run, Then the created solver along with the scalar field is compiled successfully. (In My case it's successful)

Step 11: It's the second Phase of setting the file for the solver. copy the "p" file and paste it into the same folder by changing the name of the file to S. This is to set up the dimensions and boundary condition for the scalar vector.

Step 12: In this case, we are considering the Temperature of the scalar quantity. so set the dimension to

dimensions [0 0 0 1 0 0 0];
and change the internal field to a uniform temperature of 500K. and also change the Moving wall and fixed wall boundary conditions. Here Moving wall is driven with some velocity and fixed walls are stationary so the moving wall temperature is set to be higher than the fixed wall
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  v2112                                 |
|   \\  /    A nd           | Website:  www.openfoam.com                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      S;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions      [0 0 0 1 0 0 0];

internalField   uniform 500;

boundaryField
{
    movingWall
    {
        type            fixedValue;
        value           uniform 550.0;
    }

    fixedWalls
    {
        type            fixedValue;
        value           uniform 500.0;
    }

    frontAndBack
    {
        type            empty;
    }
}


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

Step 13: Once the scalar dimensions are given properly, we need to edit the transportporperties file in the constants folder. We need to add the dS coefficient in the transportporperties file so that the governing equation which we gave in the solver can be solved.

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

nu              0.01;
DS              0.0025;


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

Step 14: Once the transportproperties are set properly, we need to edit the controlDict file, By changing the application name and also the simulation time if needed. (In my case the application name will be NewIcoFoam and the simulation time will be 1.0 sec)

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

application     NewIcoFoam;

startFrom       startTime;

startTime       0;

stopAt          endTime;

endTime         1.0;

deltaT          0.005;

writeControl    timeStep;

writeInterval   20;

purgeWrite      0;

writeFormat     ascii;

writePrecision  6;

writeCompression off;

timeFormat      general;

timePrecision   6;

runTimeModifiable true;


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

Step 15: Once all the inputs in the controldict are given properly, we should look into the fvSchemes file where we need to add the type of fvScheme that should be used to solve the scalar transport equation. (In My case I used Gauss linear scheme) to solve the Transport Equation

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

ddtSchemes
{
    default         Euler;
}

gradSchemes
{
    default         Gauss linear;
    grad(p)         Gauss linear;
}

divSchemes
{
    default         none;
    div(phi,U)      Gauss linear;
    div(phi,S)      Gauss linear;
}

laplacianSchemes
{
    default         Gauss linear orthogonal;
}

interpolationSchemes
{
    default         linear;
}

snGradSchemes
{
    default         orthogonal;
}


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

Step 16: once the fvScheme is set properly, we need to look into fvSolutions files, in this file we need to set the solver, preconditioner, Tolerance, and reltol values so that the solution will take place with the given values.

Parameter Value
Solver
PBiCG
Preconditioner
DILU
Tolerance
1e-09
reltol
0
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  v2112                                 |
|   \\  /    A nd           | Website:  www.openfoam.com                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

solvers
{
    p
    {
        solver          PCG;
        preconditioner  DIC;
        tolerance       1e-06;
        relTol          0.05;
    }

    pFinal
    {
        $p;
        relTol          0;
    }

    U
    {
        solver          smoothSolver;
        smoother        symGaussSeidel;
        tolerance       1e-05;
        relTol          0;
    }

    S
    {
        solver          PBiCG;
        preconditioner  DILU;
        tolerance       1e-09;
        relTol          0;
    }
}

PISO
{
    nCorrectors     2;
    nNonOrthogonalCorrectors 0;
    pRefCell        0;
    pRefValue       0;
}


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

Step 17: Once all the settings are made properly, Run "BlockMesh" command, and the run the "chechMesh" command. Once the mesh is ok we can now run the executable inside the test case folder

Step 18: Run the executable. In my case ./NewIcoFoam . We can see the Simulation is carried out sucessfully for 1.0 sec and the saclar quantity is been calculated at every time step.

Step 19: Run "foamToVTK" Command to view the results in Paraview.

Step 20: Now run "explorer.exe ." and then open VTK Folder and then open cavity.vtk.series file in paraview

Results :

Initial Condition

Final Condition

Discussion: From the above results we can see the simulation is run for 10 sec with given boundary conditions along with the given scalar transport Equation

Note: The scalar quantity we used here is Temperature

Changes in the solver:

• Replace the main working equation with:

Answer: Added the transport equation in the .C file where the main Equation is been solved

• What change will you make in the create fields.H file (Hint: the p field is originally created here)

Answer: In The createFields.H, add scalar Field, and create Scalar IOobject. We can see in the "step 7" images, adding lines from 58-71. Scalar IOobject is created

• Compile scalarFoam using wmake. How are the Make/files modified?

Answer: Edit the "files" file in the make file by changing the Name of the .C (icoFoam.C) file to NewIcoFoam.C which we saved outside the make file. It is clearly explained in Step 8

Changes in the case:

• Use the $FOAM_TUTORIALS/incompressible/icoFoam/cavity case to test out your solver. Rename it scalarCavity.

Answer : I used the same test case for the Scalar solver.

• The scalar transport equation has no pressure p to solve, instead a scalar s. What changes will you make in the 0 folders?

Answer : Copy the "p" file and paste it into the same folder by changing the name of the file to S. This is to set up the dimensions and boundary condition for the scalar vector.

In this case, we are considering the Temperature of the scalar quantity. so set the dimension to

dimensions [0 0 0 1 0 0 0];
and change the internal field to a uniform temperature of 500K. and also change the Moving wall and fixed wall boundary conditions. Here Moving wall is driven with some velocity and fixed walls are stationary so the moving wall temperature is set to be higher than the fixed wall

• You will have to change the interpolation scheme in fvSchemes to account for the ∇ · (us) term. How will you do this?

Answer: we need to add the type of fvScheme that should be used to solve the scalar transport equation. (In My case I used Gauss linear scheme) to solve the Transport Equation. It is explained in step 15 clearly.

• In fvSolutions, a solver has to be specified for the quantity s. Can you just replace this with the solver used for p?

Answer: fvSolutions files, in this file we need to set the solver, preconditioner, Tolerance, and reltol values so that the solution will take place with the given values.

Parameter Value
Solver
PBiCG
Preconditioner
DILU
Tolerance
1e-09
reltol
0

• Run this case by making the appropriate change in controlDict.

Answer: changing the application name and also the simulation time if needed. (In my case the application name will be NewIcoFoam and the simulation time will be 1.0 sec) in step 14 it was clearly explained

Conclusion: Hence The Cavity test case is solved by using the Scalar transport equation (In this case scalar quantity is temperature ) where the scalar quantity being transported by the velocity u.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.