CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (http://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Understanding code of inletOutlet / outletInlet (http://www.cfd-online.com/Forums/openfoam-programming-development/117202-understanding-code-inletoutlet-outletinlet.html)

fredo490 May 4, 2013 10:54

Understanding code of inletOutlet / outletInlet
 
Hello everybody,
I would like to create a new boundary condition derived from the outletInlet. I want a "zeroGradient" as outlet and a "slip" / "symmetry" as inlet. But before coding this, I went to study the source code of inletOutlet and outletInlet.

I know that depending of the sign of "phi" (flux on the patch field), the code switch from one or the other boundary. However, I cannot understand the piece of code in charge of this process.

For the inletOutlet:
(opt/openfoam220/src/finiteVolume/fields/fvPatchFields/derived/inletOutlet/inletOutletFvPatchField.C)
Code:

template<class Type>
Foam::inletOutletFvPatchField<Type>::inletOutletFvPatchField
(
    const fvPatch& p,
    const DimensionedField<Type, volMesh>& iF,
    const dictionary& dict
)
:
    mixedFvPatchField<Type>(p, iF),
    phiName_(dict.lookupOrDefault<word>("phi", "phi")) // get the flux name
{
    this->refValue() = Field<Type>("inletValue", dict, p.size()); // get the desired fixed value at the inlet

    if (dict.found("value")) // ??? if the flux go outside the domain ???
    {
        fvPatchField<Type>::operator=
        (
            Field<Type>("value", dict, p.size()) // the patch get the field value
        );
    }
    else // ??? if the flux go inside the domain ???
    {
        fvPatchField<Type>::operator=(this->refValue()); // the patch get the desired fixed value
    }

    this->refGrad() = pTraits<Type>::zero; // set the zero gradient vector
    this->valueFraction() = 0.0; // ??? for multiphase flow ? ???
}

And for the outletInlet
(opt/openfoam220/src/finiteVolume/fields/fvPatchFields/derived/inletOutlet/inletOutletFvPatchField.C)
Code:

template<class Type>
Foam::outletInletFvPatchField<Type>::outletInletFvPatchField
(
    const fvPatch& p,
    const DimensionedField<Type, volMesh>& iF,
    const dictionary& dict
)
:
    mixedFvPatchField<Type>(p, iF),
    phiName_(dict.lookupOrDefault<word>("phi", "phi")) // get the flux name
{
    this->refValue() = Field<Type>("outletValue", dict, p.size()); // get the desired fixed value at the inlet

    if (dict.found("value")) // ??? if the flux go inside the domain ???
    {
        fvPatchField<Type>::operator=
        (
            Field<Type>("value", dict, p.size()) // the patch get the field value
        );
    }
    else // ??? if the flux go outside the domain ???
    {
        fvPatchField<Type>::operator=(this->refValue()); // the patch get the desired fixed value
    }

    this->refGrad() = pTraits<Type>::zero;  // set the zero gradient vector
    this->valueFraction() = 0.0; // ??? for multiphase flow ? ???
}

My problem is that the same code should do two opposite things:
inletOutlet:
Code:

if (dict.found("value")) // ??? if the flux go outside the domain ???
outletInlet:
Code:

if (dict.found("value")) // ??? if the flux go inside the domain ???
The only difference I have found is in the member function.
inletOutlet:
Code:

template<class Type>
void Foam::inletOutletFvPatchField<Type>::updateCoeffs()
{
    if (this->updated())
    {
        return;
    }

    const Field<scalar>& phip =
        this->patch().template lookupPatchField<surfaceScalarField, scalar>
        (
            phiName_
        );

    this->valueFraction() = 1.0 - pos(phip); // The difference is here

    mixedFvPatchField<Type>::updateCoeffs();
}

outletInlet
Code:

template<class Type>
void Foam::outletInletFvPatchField<Type>::updateCoeffs()
{
    if (this->updated())
    {
        return;
    }

    const fvsPatchField<scalar>& phip =
        this->patch().template lookupPatchField<surfaceScalarField, scalar>
        (
            phiName_
        );

    this->valueFraction() = pos(phip); // The difference is here

    mixedFvPatchField<Type>::updateCoeffs();
}

Does anyone know how this code works ? I am a bit lost :(

fredo490 May 6, 2013 13:54

a small up :rolleyes:

pastilha June 12, 2013 07:10

Hi,

I just started looking into this BC and I am also struggling a bit with the code.

In my case, I would like to apply a profile (which is dependant on patch point coordinates) when the flux is positive (entering the domain) and keep zeroGradient when the flux is negative (exiting the domain). I have already implemented the profile boundary condition as an fvPatchVectorField, but now I would like to (ambitiously) merge it with inletOutlet.

Frédéric, have you been able to shed some light into this? Anyone? Any help would be kindly appreciated. I will share anything I can work out on my own!

I've had a couple of half-witted yet successful atempts at customizing boundary conditions in the past (fvPatchVectorFields and fvPatchFields mostly), but clearly my feeble OpenFoam/C++ skills have reached a wall with this one...

Cheers,

Pedro

fredo490 June 12, 2013 07:17

Sorry, I haven't been able to learn more about it... I didn't really have time so I gave up. But if you succeed, please leave me a comment ;)

Tobi June 12, 2013 07:57

Hi all,

that code you posted it not the code you Need couse you posted the Constructor of that function :D

Code:


// Constructor type with three arguments
 
Foam::inletOutletFvPatchField<Type>::inletOutletFvPatchField
(
    constfvPatch& ,                            // Argument 1                         
    const DimensionedField<Type, volMesh>& iF, // Argument 2
    const dictionary& dict                    // Argument 3
)
:
    mixedFvPatchField<Type>(p, iF),                        // init var
    phiName_(dict.lookupOrDefault<word>("phi", "phi"))    // init var
 
// Constructor functions - what to do at the beginning (if you create that class)
{
    this->refValue() = Field<Type>("inletValue", dict, p.size()); // inletOultet value
 
    if (dict.found("value"))        // looking if the user that the initial value; if yes do the following
    {
        fvPatchField<Type>::operator=
        (
            Field<Type>("value", dict, p.size())
        );
    }
    else      // if no - set the inletOutlet value
    {
        fvPatchField<Type>::operator=(this->refValue());
    }
 
    this->refGrad() = pTraits<Type>::zero;   
    this->valueFraction() = 0.0;                 
}
// Constructor functions end
 
Here are the member functions for the class like:
 
Foam::inletOutletFvPatchField<Type>::calculate()
{
              // Here is the function you are searching for!
}

This step is working at the beginning of your solver. After you get into the iterations this steps never repeat.

What you Need is the correct or calculate function!!!

PS: You should learn how C++ and functions or classes are working. With that knowledge it s very easy to read the code!

So far
Tobi

fredo490 June 12, 2013 08:54

The member functions are given at the end of my first post (the 2 last code quotes):
Code:

void Foam::inletOutletFvPatchField<Type>::updateCoeffs()
...

And I can read and reread the functions, I still don't get how the function switch from one case of the other.

Edit, it is the OF 2.2 source code

Tobi June 12, 2013 12:57

/* - - - */

fredo490 June 12, 2013 13:09

No problem, thx anyway for trying to help me !
I will take a look again this summer when I have some free time.

ngj June 12, 2013 14:56

Hello Frederic,

All the "magic" happen in the parent class mixed<something>, which you will probably be able to find in the fvPatchField/basic folder, if I am not mistaken.

You are indeed pointing to the important point in the code, because the valueFraction field is essentially a switch between the Dirichlet and Neumann conditions. Again, if I recall correctly, then if the valueFraction takes a value of 1, then the Dirichlet condition is used, where the Neumann is used for a value of 0.

The
Code:

pos(phi)
returns either 0 or 1 depending on the sign of the argument, so the code does the spatial switch between Dirichlet and Neumann automatically for you each time step. Remember that on a boundary a positive flux (phi) means that the flux is outbound.

I hope that this has clarified some things.

Kind regards

Niels

Tobi June 13, 2013 08:02

Hi Niels,

thanks for the replay.

Here I found the Definition of pos():
Code:

Positive (boolean)    http://www.foamcfd.org/Nabla/guides/...sGuide241x.gif    pos(s)
scalar.H
Code:

00115 inline Scalar pos(const Scalar s)
00116 {
00117    return (s >= 0)? 1: 0;
00118 }


ngj June 13, 2013 13:45

Hi

I do know that some of the functions are outdated, but the following document (especially pp. 23-25) give a nice overview of the different functionalities and their return value:

http://sourceforge.net/p/openfoam-ex...mmersGuide.pdf

Kind regards

NIels


All times are GMT -4. The time now is 14:01.