Challenge

Project 1- Creating your own openFOAM solver

Objective

Create an OpenFoam solver from an existing solver icoFoam by adding passive scalar transport equation.
Check the compiled solver to test cavity case and analysis the results.
Theory -

Introduction:

icoFoam is transient solver for incompressible and laminar flows. It solves the Navier-Stokes equation using the PISO(Pressure Iimplicit with Spliting of Operators) algorithm. The need of Pressure-Velocity Coupling alogrithms like SIMPLE and PISO arise from the fact that there is no Transport Equation for Pressure.

Procedure:

Copy the icoFoam solver and rename it to scalarFoam :

~/OpenFOAM-v2106/applications/solvers/incompressible/icoFoam scalarFoam


Followed by appropriate changes to the name of the .C file

scalar2Foam.C

Passive Scalar Transport Equation:

    fvScalarMatrix sEqn
        (
            fvm::ddt(s)               //Time derivative
          + fvm::div(phi, s)          //convective term
          - fvm::laplacian(su, s)     //diffusion term
        );

        sEqn.relax();  //Considering under relaxing factor
        sEqn.solve();  //Calling in Public member function Solve

Here we solve for scalar term s. The LHS of sEqn is stored in an fvScalarMatrix, inside which all the terms (time derivative, convection and diffusion) are treated implicitly. Following this, we apply relaxation factor based on user input and finally solve it(equate to 0).

On LHS side,

First term is a time derivative of scalar s.
Second term is a linearized convection term i.e. volume intergral of divergence of the vector field is converted into to surface integral of that vector, which is flux phi.
Last term is diffusion term with diffusion cofficient su and the diffusion term is subtracted from the LHS.


scalar2Foam.C - This file contains the source code of the solver

/*---------------------------------------------------------------------------*
  =========                 |
  \      /  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
    scalarFoam

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

    Adding passive Scalar Transport equation
    f[
            ddt{scalar{s}}
          + div left( vec{phi} scalar{s} right)
          - div left(scalar su grad scalar{s} right)
          = - grad s
    f]
*---------------------------------------------------------------------------*/

#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 loopn" << 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();
        }

       //Passive Scalar Transport Eqn
        fvScalarMatrix sEqn
        (
            fvm::ddt(s)
          + fvm::div(phi, s)
          - fvm::laplacian(su, s)
        );

        sEqn.relax();  //Considering under relaxing factor
        sEqn.solve();  //Calling in Public member function Solve


        runTime.write();

        runTime.printExecutionTime(Info);
    }

    Info<< "Endn" << endl;

    return 0;
}


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

createFields.H - This file contains all IOObjects.

Here we add an additional volScalarField s and dimensionedScalar su

nfo<< "Reading transportPropertiesn" << endl;

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

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

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

Info<< "Reading field pn" << endl;
volScalarField p
(
    IOobject
    (
        "p",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ,
        IOobject::AUTO_WRITE
    ),
    mesh
);


Info<< "Reading field Un" << endl;
volVectorField U
(
    IOobject
    (
        "U",
        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());

Info<< "Reading field sn" << endl;
volScalarField s
(
    IOobject
    (
        "s",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ,
        IOobject::AUTO_WRITE
    ),
    mesh
);

 

Make/Files -

scalar2Foam.C //Souce File

EXE = $(FOAM_USER_APPBIN)/scalar2Foam //Particular Path to store the excutable and Exceutable Name

Make/Options

EXE_INC = 
    -I$(LIB_SRC)/finiteVolume/lnInclude 
    -I$(LIB_SRC)/meshTools/lnInclude

EXE_LIBS = 
    -lfiniteVolume 
    -lmeshTools

Now run the wmake command to compile the solver.

Copy the test case named cavity from the OpenFoam Tutorials folder

$FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity/
The Cavity tutorial presents the modeling of the flow driven by a moving lid in a square cavity (lid-driven cavity flow). This fluid mechanics problem is a typical validation test case for CFD codes.

In order to illustrate the possibility of adding a passive scalar to an OpenFOAM simulation, it is assumed that there is an inert chemical species (called s, for example a rare gas) and modeled by a scalar field whose evolution is governed by the convection / diffusion equation

`(∂s)/(∂t)+∇(Us)=∇^2(Ds)`

setFieldsDict

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

defaultFieldValues
(
    volScalarFieldValue s 0
);

regions
(
    sphereToCell
    {
        centre (0.05 0.05 0);
        radius 0.03;
        fieldValues
        (
            volScalarFieldValue s 1
        );
    }
    
);

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

0/s - This file is a copy of pressure with specify changes such as:

dimension is zero since s is a scalar quantity
Internal field value is also uniformly zero.

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
| \      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \    /   O peration     | Version:  v2106                                 |
|   \  /    A nd           | Website:  www.openfoam.com                      |
|    \/     M anipulation  |                                                 |
*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    arch        "LSB;label=32;scalar=64";
    class       volScalarField;
    location    "0";
    object      s;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions      [0 0 0 0 0 0 0];

internalField   uniform 0;

boundaryField
{
    movingWall
    {
        type            zeroGradient;
    }
    fixedWalls
    {
        type            zeroGradient;
    }
    frontAndBack
    {
        type            empty;
    }
}


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

consatnt/transportProperties

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

nu              [0 2 -1 0 0 0 0] 0.01;
su              [0 2 -1 0 0 0 0] 0.01;

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

system/fvSchemes

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
| \      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \    /   O peration     | Version:  v2106                                 |
|   \  /    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 upwind;
}

laplacianSchemes
{
    default         Gauss linear corrected;
}

interpolationSchemes
{
    default         linear;
}

snGradSchemes
{
    default         orthogonal;
}

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

system/fvSolutions

Here we must specify particular Linear Solver that is to be used for scalar matrix.Moreover, for scalar s we cannot use PCG as its already been specified for the pressure term.

PCG is meant for symmetric matrices.
PBiCG is for asymmetric matrices.
smoothSolver for any of them.

/*--------------------------------*- C++ -*----------------------------------*
| =========                 |                                                 |
| \      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \    /   O peration     | Version:  v2106                                 |
|   \  /    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;
    }

    s
    {
        solver          PBiCGStab;
        preconditioner  DILU;
        tolerance       1e-08;
        relTol          0;
        minIter	        1;
    }

    pFinal
    {
        $p;
        relTol          0;
    }

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

}

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


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

Post-Processing

blockMesh - Creates the mesh as specified in blockMeshDict.
checkMesh - A utility which analyzes and evaluates mesh statistics and quality parameters.
setFields - It sets the field as specified in setFieldsDict.
scalarFoam - Executable to run the simulation case.

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.

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.