From 3f7c0577124bd3b3e95393d4bdd2c7b6e96db1f2 Mon Sep 17 00:00:00 2001
From: Sergio Ferraris <s.ferraris@opencfd.co.uk>
Date: Tue, 15 Jun 2021 17:09:01 +0100
Subject: [PATCH] ENH: Adding new permeable boundary conditions

- prghPermeableAlphaTotalPressure for p_rgh
- pressurePermeableAlphaInletOutletVelocity for U
- new helper class for pressure-related BCs: updateableSnGrad
---
 src/finiteVolume/Make/files                   |   2 +
 .../constrainPressure/constrainPressure.C     |  19 +-
 .../updateableSnGrad/updateableSnGrad.H       |  86 +++++
 .../fixedFluxPressureFvPatchScalarField.H     |   6 +-
 ...phaInletOutletVelocityFvPatchVectorField.C | 226 +++++++++++++
 ...phaInletOutletVelocityFvPatchVectorField.H | 255 +++++++++++++++
 ...ableAlphaTotalPressureFvPatchScalarField.C | 299 ++++++++++++++++++
 ...ableAlphaTotalPressureFvPatchScalarField.H | 254 +++++++++++++++
 8 files changed, 1135 insertions(+), 12 deletions(-)
 create mode 100644 src/finiteVolume/cfdTools/general/updateableSnGrad/updateableSnGrad.H
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.H
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.C
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.H

diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files
index be371512455..ef849f6dff0 100644
--- a/src/finiteVolume/Make/files
+++ b/src/finiteVolume/Make/files
@@ -238,6 +238,8 @@ $(derivedFvPatchFields)/plenumPressure/plenumPressureFvPatchScalarField.C
 $(derivedFvPatchFields)/interfaceCompression/interfaceCompressionFvPatchScalarField.C
 $(derivedFvPatchFields)/swirlFanVelocity/swirlFanVelocityFvPatchField.C
 $(derivedFvPatchFields)/acousticWaveTransmissive/acousticWaveTransmissiveFvPatchFields.C
+$(derivedFvPatchFields)/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.C
+$(derivedFvPatchFields)/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C
 
 $(derivedFvPatchFields)/mappedMixed/mappedMixedFvPatchFields.C
 $(derivedFvPatchFields)/mappedField/Sampled/makeSampledPatchFunction1s.C
diff --git a/src/finiteVolume/cfdTools/general/constrainPressure/constrainPressure.C b/src/finiteVolume/cfdTools/general/constrainPressure/constrainPressure.C
index a4410c7ea19..4006afc62fc 100644
--- a/src/finiteVolume/cfdTools/general/constrainPressure/constrainPressure.C
+++ b/src/finiteVolume/cfdTools/general/constrainPressure/constrainPressure.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2016 OpenFOAM Foundation
+    Copyright (C) 2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -29,7 +30,7 @@ License
 #include "volFields.H"
 #include "surfaceFields.H"
 #include "geometricOneField.H"
-#include "fixedFluxPressureFvPatchScalarField.H"
+#include "updateableSnGrad.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -51,21 +52,19 @@ void Foam::constrainPressure
     const volVectorField::Boundary& UBf = U.boundaryField();
     const surfaceScalarField::Boundary& phiHbyABf =
         phiHbyA.boundaryField();
-    const typename RAUType::Boundary& rhorAUBf =
-        rhorAU.boundaryField();
-    const surfaceVectorField::Boundary& SfBf =
-        mesh.Sf().boundaryField();
+    const typename RAUType::Boundary& rhorAUBf = rhorAU.boundaryField();
+    const surfaceVectorField::Boundary& SfBf = mesh.Sf().boundaryField();
     const surfaceScalarField::Boundary& magSfBf =
         mesh.magSf().boundaryField();
 
     forAll(pBf, patchi)
     {
-        if (isA<fixedFluxPressureFvPatchScalarField>(pBf[patchi]))
+        typedef updateablePatchTypes::updateableSnGrad snGradType;
+        const auto* snGradPtr = isA<snGradType>(pBf[patchi]);
+
+        if (snGradPtr)
         {
-            refCast<fixedFluxPressureFvPatchScalarField>
-            (
-                pBf[patchi]
-            ).updateSnGrad
+            const_cast<snGradType&>(*snGradPtr).updateSnGrad
             (
                 (
                     phiHbyABf[patchi]
diff --git a/src/finiteVolume/cfdTools/general/updateableSnGrad/updateableSnGrad.H b/src/finiteVolume/cfdTools/general/updateableSnGrad/updateableSnGrad.H
new file mode 100644
index 00000000000..a241db328ee
--- /dev/null
+++ b/src/finiteVolume/cfdTools/general/updateableSnGrad/updateableSnGrad.H
@@ -0,0 +1,86 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 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/>.
+
+Class
+    Foam::updateableSnGrad
+
+Description
+    Helper class to fix pressure flux
+    for pressure-related boundary conditions.
+
+See also
+  - Foam::prghPermeableAlphaTotalPressureFvPatchScalarField
+
+SourceFiles
+    updateableSnGrad.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef updateableSnGrad_H
+#define updateableSnGrad_H
+
+#include "primitiveFieldsFwd.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace updateablePatchTypes
+{
+/*---------------------------------------------------------------------------*\
+                        Class  updateableSnGrad declaration
+\*---------------------------------------------------------------------------*/
+
+class updateableSnGrad
+{
+public:
+
+    // Public Member Functions
+
+        //- Constructor
+        updateableSnGrad() = default;
+
+        //- Destructor
+        virtual ~updateableSnGrad() = default;
+
+
+    // Member Functions
+
+        //- Update snGrad
+        virtual void updateSnGrad(const scalarField& snGradp) = 0;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace updateablePatchTypes
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.H b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.H
index da46ce3fac7..cddfa8aa34c 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/fixedFluxPressure/fixedFluxPressureFvPatchScalarField.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016 OpenCFD Ltd.
+    Copyright (C) 2016-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -56,6 +56,7 @@ SourceFiles
 
 #include "fvPatchFields.H"
 #include "fixedGradientFvPatchFields.H"
+#include "updateableSnGrad.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -68,7 +69,8 @@ namespace Foam
 
 class fixedFluxPressureFvPatchScalarField
 :
-    public fixedGradientFvPatchScalarField
+    public fixedGradientFvPatchScalarField,
+    public updateablePatchTypes::updateableSnGrad
 {
     // Private data
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C
new file mode 100644
index 00000000000..d3914c1e9fb
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C
@@ -0,0 +1,226 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.H"
+#include "addToRunTimeSelectionTable.H"
+#include "fvPatchFieldMapper.H"
+#include "volFields.H"
+#include "surfaceFields.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+(
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF
+)
+:
+    mixedFvPatchVectorField(p, iF),
+    phiName_("phi"),
+    rhoName_("rho"),
+    alphaName_("none"),
+    alphaMin_(1.0)
+{
+    refValue() = Zero;
+    refGrad() = Zero;
+    valueFraction() = 1.0;
+}
+
+
+Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+(
+    const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField& ptf,
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF,
+    const fvPatchFieldMapper& mapper
+)
+:
+    mixedFvPatchVectorField(ptf, p, iF, mapper),
+    phiName_(ptf.phiName_),
+    rhoName_(ptf.rhoName_),
+    alphaName_(ptf.alphaName_),
+    alphaMin_(ptf.alphaMin_)
+{}
+
+
+Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+(
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF,
+    const dictionary& dict
+)
+:
+    mixedFvPatchVectorField(p, iF),
+    phiName_(dict.getOrDefault<word>("phi", "phi")),
+    rhoName_(dict.getOrDefault<word>("rho", "rho")),
+    alphaName_(dict.getOrDefault<word>("alpha", "none")),
+    alphaMin_(dict.getOrDefault<scalar>("alphaMin", 1))
+{
+    patchType() = dict.getOrDefault<word>("patchType", word::null);
+    fvPatchVectorField::operator=(vectorField("value", dict, p.size()));
+    refValue() = Zero;
+    refGrad() = Zero;
+    valueFraction() = 1.0;
+}
+
+
+Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+(
+    const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField& pivpvf
+)
+:
+    mixedFvPatchVectorField(pivpvf),
+    phiName_(pivpvf.phiName_),
+    rhoName_(pivpvf.rhoName_),
+    alphaName_(pivpvf.alphaName_),
+    alphaMin_(pivpvf.alphaMin_)
+{}
+
+
+Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+(
+    const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField& pivpvf,
+    const DimensionedField<vector, volMesh>& iF
+)
+:
+    mixedFvPatchVectorField(pivpvf, iF),
+    phiName_(pivpvf.phiName_),
+    rhoName_(pivpvf.rhoName_),
+    alphaName_(pivpvf.alphaName_),
+    alphaMin_(pivpvf.alphaMin_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+
+void Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::
+updateCoeffs()
+{
+    if (updated())
+    {
+        return;
+    }
+
+    const auto& phi = db().lookupObject<surfaceScalarField>(phiName_);
+
+    const fvsPatchField<scalar>& phip =
+        patch().patchField<surfaceScalarField, scalar>(phi);
+
+    const vectorField n(patch().nf());
+
+    if (phi.dimensions() == dimVelocity*dimArea)
+    {
+        refValue() = (phip/patch().magSf())*n;
+    }
+    else if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
+    {
+        const fvPatchField<scalar>& rhop =
+            patch().lookupPatchField<volScalarField, scalar>(rhoName_);
+
+        refValue() = (phip/(rhop*patch().magSf()))*n;
+    }
+    else
+    {
+        FatalErrorInFunction
+            << "dimensions of phi are not correct"
+            << "\n    on patch " << this->patch().name()
+            << " of field " << this->internalField().name()
+            << " in file " << this->internalField().objectPath()
+            << exit(FatalError);
+    }
+
+    valueFraction() = 1.0 - pos0(phip);
+
+    if (alphaName_ != "none")
+    {
+        const scalarField& alphap =
+            patch().lookupPatchField<volScalarField, scalar>(alphaName_);
+
+        const scalarField alphaCut(pos(alphap - alphaMin_));
+        valueFraction() = max(alphaCut, valueFraction());
+        forAll (*this, faceI)
+        {
+            if (valueFraction()[faceI] == 1.0)
+            {
+                refValue()[faceI] = Zero;
+            }
+        }
+    }
+
+    mixedFvPatchVectorField::updateCoeffs();
+}
+
+
+void Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField::write
+(
+    Ostream& os
+) const
+{
+    mixedFvPatchVectorField::write(os);
+    os.writeEntryIfDifferent<word>("phi", "phi", phiName_);
+    os.writeEntryIfDifferent<word>("rho", "rho", rhoName_);
+    os.writeEntryIfDifferent<word>("alpha", "none", alphaName_);
+    os.writeEntryIfDifferent<scalar>("alphaMin", 1, alphaMin_);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
+
+void Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+::operator=
+(
+    const fvPatchField<vector>& pvf
+)
+{
+    tmp<vectorField> n = patch().nf();
+
+    fvPatchField<vector>::operator=
+    (
+        valueFraction()*(n()*(n() & pvf))
+      + (1 - valueFraction())*pvf
+    );
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    makePatchTypeField
+    (
+        fvPatchVectorField,
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+    );
+}
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.H b/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.H
new file mode 100644
index 00000000000..f087b5cae5b
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/pressurePermeableAlphaInletOutletVelocity/pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.H
@@ -0,0 +1,255 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 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/>.
+
+Class
+    Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+
+Group
+    grpInletBoundaryConditions grpOutletBoundaryConditions
+
+Description
+    The \c pressurePermeableAlphaInletOutletVelocity is a velocity inlet-outlet
+    boundary condition which can be applied to velocity boundaries for
+    multiphase flows when the pressure boundary condition is specified.
+
+    In the \c pressurePermeableAlphaInletOutletVelocity, an open condition is
+    applied when \c alpha is under a user-defined \c alphaMin value and a wall
+    condition is applied when \c alpha is larger than the \c alphaMin.
+
+    This boundary condition can be used in conjunction with
+    \c prghPermeableAlphaTotalPressure for the \c p_rgh variable.
+
+Usage
+    Example of the boundary condition specification:
+    \verbatim
+    <patchName>
+    {
+        // Mandatory entries
+        type            pressurePermeableAlphaInletOutletVelocity;
+
+        // Optional entries
+        phi             phi;
+        rho             rho;
+        alpha           alpha.water;
+        alphaMin        0.01;
+
+        // Inherited entries
+        value           uniform (0 0 0);
+        ...
+    }
+    \endverbatim
+
+    where the entries mean:
+    \table
+      Property     | Description             | Type | Reqd | Deflt
+      phi          | Name of flux field      | word | no   | phi
+      rho          | Name of density field   | word | no   | rho
+      alpha        | Name of mixture field   | word | no   | none
+      alphaMin     | Minimum alpha           | scalar | no | 1
+    \endtable
+
+    The inherited entries are elaborated in:
+      - \link mixedFvPatchFields.H \endlink
+
+See also
+  - Foam::prghPermeableAlphaTotalPressureFvPatchScalarField
+  - Foam::mixedFvPatchVectorField
+
+SourceFiles
+    pressurePermeableAlphaInletOutletVelocityFvPatchVectorField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pressurePermeableAlphaInletOutletVelocityFvPatchVectorField_H
+#define pressurePermeableAlphaInletOutletVelocityFvPatchVectorField_H
+
+#include "fvPatchFields.H"
+#include "mixedFvPatchFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+Class pressurePermeableAlphaInletOutletVelocityFvPatchVectorField Declaration
+\*---------------------------------------------------------------------------*/
+
+class pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+:
+    public mixedFvPatchVectorField
+{
+    // Private Data
+
+        //- Name of flux field
+        word phiName_;
+
+        //- Name of density field
+        word rhoName_;
+
+        //- Name of the mixture VOF field (if used)
+        word alphaName_;
+
+        //- Minimum alpha value to outlet blockage
+        scalar alphaMin_;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("permeableAlphaPressureInletOutletVelocity");
+
+
+    // Constructors
+
+        //- Construct from patch and internal field
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        (
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        (
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given
+        //- pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        //- onto a new patch
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        (
+            const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField&,
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&,
+            const fvPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        (
+            const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField&
+        );
+
+        //- Construct and return a clone
+        virtual tmp<fvPatchVectorField> clone() const
+        {
+            return tmp<fvPatchVectorField>
+            (
+                new pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+                (
+                    *this
+                )
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+        (
+            const pressurePermeableAlphaInletOutletVelocityFvPatchVectorField&,
+            const DimensionedField<vector, volMesh>&
+        );
+
+        //- Construct and return a clone setting internal field reference
+        virtual tmp<fvPatchVectorField> clone
+        (
+            const DimensionedField<vector, volMesh>& iF
+        ) const
+        {
+            return tmp<fvPatchVectorField>
+            (
+                new pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+                (
+                    *this,
+                    iF
+                )
+            );
+        }
+
+
+    // Member Functions
+
+        // Attributes
+
+            //- Return true: this patch field is altered by assignment
+            virtual bool assignable() const
+            {
+                return true;
+            }
+
+
+        // Access
+
+            //- Return the name of rho
+            const word& rhoName() const noexcept
+            {
+                return rhoName_;
+            }
+
+            //- Return reference to the name of rho to allow adjustment
+            word& rhoName()
+            {
+                return rhoName_;
+            }
+
+            //- Return the name of phi
+            const word& phiName() const noexcept
+            {
+                return phiName_;
+            }
+
+            //- Return reference to the name of phi to allow adjustment
+            word& phiName()
+            {
+                return phiName_;
+            }
+
+
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
+
+        //- Write
+        virtual void write(Ostream&) const;
+
+
+    // Member Operators
+
+        //- Copy assignment
+        virtual void operator=(const fvPatchField<vector>& pvf);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.C b/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.C
new file mode 100644
index 00000000000..1141e88bcdf
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.C
@@ -0,0 +1,299 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 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/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "prghPermeableAlphaTotalPressureFvPatchScalarField.H"
+#include "addToRunTimeSelectionTable.H"
+#include "fvPatchFieldMapper.H"
+#include "gravityMeshObject.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::
+prghPermeableAlphaTotalPressureFvPatchScalarField
+(
+    const fvPatch& p,
+    const DimensionedField<scalar, volMesh>& iF
+)
+:
+    mixedFvPatchField<scalar>(p, iF),
+    p0_(nullptr),
+    phiName_("phi"),
+    rhoName_("rho"),
+    UName_("U"),
+    alphaName_("none"),
+    alphaMin_(1.0),
+    curTimeIndex_(-1)
+{
+    refValue() = 0.0;
+    refGrad() = 0.0;
+    valueFraction() = 0.0;
+}
+
+
+Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::
+prghPermeableAlphaTotalPressureFvPatchScalarField
+(
+    const fvPatch& p,
+    const DimensionedField<scalar, volMesh>& iF,
+    const dictionary& dict
+)
+:
+    mixedFvPatchField<scalar>(p, iF),
+    p0_(PatchFunction1<scalar>::New(p.patch(), "p", dict)),
+    phiName_(dict.getOrDefault<word>("phi", "phi")),
+    rhoName_(dict.getOrDefault<word>("rho", "rho")),
+    UName_(dict.getOrDefault<word>("U", "U")),
+    alphaName_(dict.getOrDefault<word>("alpha", "none")),
+    alphaMin_(dict.getOrDefault<scalar>("alphaMin", 1)),
+    curTimeIndex_(-1)
+{
+    refValue() = 1.0;
+    refGrad() = 0.0;
+    valueFraction() = 0.0;
+
+    if (dict.found("value"))
+    {
+        fvPatchField<scalar>::operator=
+        (
+            Field<scalar>("value", dict, p.size())
+        );
+    }
+    else
+    {
+        fvPatchField<scalar>::operator=(refValue());
+    }
+}
+
+
+Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::
+prghPermeableAlphaTotalPressureFvPatchScalarField
+(
+    const prghPermeableAlphaTotalPressureFvPatchScalarField& ptf,
+    const fvPatch& p,
+    const DimensionedField<scalar, volMesh>& iF,
+    const fvPatchFieldMapper& mapper
+)
+:
+    mixedFvPatchField<scalar>(ptf, p, iF, mapper),
+    p0_(ptf.p0_.clone(p.patch())),
+    phiName_(ptf.phiName_),
+    rhoName_(ptf.rhoName_),
+    UName_(ptf.UName_),
+    alphaName_(ptf.alphaName_),
+    alphaMin_(ptf.alphaMin_),
+    curTimeIndex_(-1)
+{}
+
+
+Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::
+prghPermeableAlphaTotalPressureFvPatchScalarField
+(
+    const prghPermeableAlphaTotalPressureFvPatchScalarField& tppsf
+)
+:
+    mixedFvPatchField<scalar>(tppsf),
+    p0_(tppsf.p0_.clone(this->patch().patch())),
+    phiName_(tppsf.phiName_),
+    rhoName_(tppsf.rhoName_),
+    UName_(tppsf.UName_),
+    alphaName_(tppsf.alphaName_),
+    alphaMin_(tppsf.alphaMin_),
+    curTimeIndex_(-1)
+{}
+
+
+Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::
+prghPermeableAlphaTotalPressureFvPatchScalarField
+(
+    const prghPermeableAlphaTotalPressureFvPatchScalarField& tppsf,
+    const DimensionedField<scalar, volMesh>& iF
+)
+:
+    mixedFvPatchField<scalar>(tppsf, iF),
+    p0_(tppsf.p0_.clone(this->patch().patch())),
+    phiName_(tppsf.phiName_),
+    rhoName_(tppsf.rhoName_),
+    UName_(tppsf.UName_),
+    alphaName_(tppsf.alphaName_),
+    alphaMin_(tppsf.alphaMin_),
+    curTimeIndex_(-1)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::autoMap
+(
+    const fvPatchFieldMapper& m
+)
+{
+    mixedFvPatchField<scalar>::autoMap(m);
+
+    if (p0_)
+    {
+        p0_->autoMap(m);
+    }
+}
+
+
+void Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::rmap
+(
+    const fvPatchScalarField& ptf,
+    const labelList& addr
+)
+{
+    mixedFvPatchField<scalar>::rmap(ptf, addr);
+
+    const auto& tptf =
+        refCast<const prghPermeableAlphaTotalPressureFvPatchScalarField>(ptf);
+
+    if (p0_)
+    {
+        p0_->rmap(tptf.p0_(), addr);
+    }
+}
+
+
+void Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::updateSnGrad
+(
+    const scalarField& snGradp
+)
+{
+    if (updated())
+    {
+        return;
+    }
+
+    const scalarField& rhop =
+        patch().lookupPatchField<volScalarField, scalar>(rhoName_);
+
+    const scalarField& phip =
+        patch().lookupPatchField<surfaceScalarField, scalar>(phiName_);
+
+    const vectorField& Up =
+        patch().lookupPatchField<volVectorField, vector>(UName_);
+
+    const uniformDimensionedVectorField& g =
+        meshObjects::gravity::New(db().time());
+
+    const auto& hRef =
+        db().lookupObject<uniformDimensionedScalarField>("hRef");
+
+    const dimensionedScalar ghRef
+    (
+        mag(g.value()) > SMALL
+      ? g & (cmptMag(g.value())/mag(g.value()))*hRef
+      : dimensionedScalar(g.dimensions()*dimLength, 0)
+    );
+
+    const scalar t = db().time().timeOutputValue();
+
+    tmp<scalarField> p
+    (
+        p0_->value(t)
+      - 0.5*rhop*(1.0 - pos0(phip))*magSqr(Up)
+      - rhop*((g.value() & patch().Cf()) - ghRef.value())
+    );
+
+    refValue() = p;
+
+    refGrad() = snGradp;
+
+    if (alphaName_ != "none")
+    {
+        const scalarField& alphap =
+            patch().lookupPatchField<volScalarField, scalar>(alphaName_);
+        tmp<scalarField> alphaCut(pos(alphap - alphaMin_));
+        valueFraction() = 1 - alphaCut;
+    }
+
+    if (debug)
+    {
+        const scalar phi = gSum(-phip);
+        Info<< valueFraction() << endl;
+        Info<< patch().boundaryMesh().mesh().name() << ':'
+            << patch().name() << ':'
+            << this->internalField().name() << " :"
+            << " mass flux[Kg/s]:" << phi
+            << endl;
+    }
+
+    curTimeIndex_ = this->db().time().timeIndex();
+
+    mixedFvPatchField<scalar>::updateCoeffs();
+}
+
+
+void Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::updateCoeffs()
+{
+    if (updated())
+    {
+        return;
+    }
+
+    if (curTimeIndex_ != this->db().time().timeIndex())
+    {
+        FatalErrorInFunction
+            << "updateCoeffs(const scalarField& snGradp) MUST be called before"
+               " updateCoeffs() or evaluate() to set the boundary gradient."
+            << exit(FatalError);
+    }
+}
+
+
+void Foam::prghPermeableAlphaTotalPressureFvPatchScalarField::write
+(
+    Ostream& os
+) const
+{
+    mixedFvPatchField<scalar>::write(os);
+    os.writeEntryIfDifferent<word>("phi", "phi", phiName_);
+    os.writeEntryIfDifferent<word>("rho", "rho", rhoName_);
+    os.writeEntryIfDifferent<word>("U", "U", UName_);
+    os.writeEntryIfDifferent<word>("alpha", "none", alphaName_);
+    os.writeEntryIfDifferent<scalar>("alphaMin", 1, alphaMin_);
+
+    if (p0_)
+    {
+        p0_->writeData(os);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    makePatchTypeField
+    (
+        fvPatchScalarField,
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+    );
+
+}
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.H b/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.H
new file mode 100644
index 00000000000..ca4f952cebf
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/prghPermeableAlphaTotalPressure/prghPermeableAlphaTotalPressureFvPatchScalarField.H
@@ -0,0 +1,254 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 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/>.
+
+Class
+    Foam::prghPermeableAlphaTotalPressureFvPatchScalarField
+
+Description
+    The \c prghPermeableAlphaTotalPressure is a mixed boundary condition
+    for the \c p_rgh variable in multiphase flows.
+
+    It switches between an open boundary using the \c prghTotalPressure
+    boundary condition and a wall condition using the \c fixedFluxPressure
+    boundary condition.
+
+    In the \c prghPermeableAlphaTotalPressure, an open condition is
+    applied when \c alpha is under a user-defined \c alphaMin value and a wall
+    condition is applied when \c alpha is larger than the \c alphaMin.
+
+    This boundary condition can be used in conjunction with
+    \c pressurePermeableAlphaInletOutletVelocity for the \c U variable.
+
+Usage
+    Example of the boundary condition specification:
+    \verbatim
+    <patchName>
+    {
+        // Mandatory entries
+        type            prghPermeableAlphaTotalPressure;
+        p               uniform 0;
+
+        // Optional entries
+        phi             phi;
+        rho             rho;
+        U               U;
+        alphaName       alpha.water;
+        alphaMin        0.01;
+
+        // Inherited entries
+        value           uniform 0;
+        ...
+    }
+    \endverbatim
+
+    where the entries mean:
+    \table
+      Property  | Description             | Type | Reqd | Deflt
+      p         | Total pressure          | PatchFunction1\<scalar\> | yes | -
+      phi       | Name of flux field      | word | no   | phi
+      rho       | Name of density field   | word | no   | rho
+      U         | Name of velocity field  | word | no   | U
+      alpha     | Name of mixture field   | word | no   | none
+      alphaMin  | Minimum alpha           | scalar | no | 1
+    \endtable
+
+    The inherited entries are elaborated in:
+      - \link mixedFvPatchFields.H \endlink
+      - \link PatchFunction1.H \endlink
+
+See also
+  - Foam::pressurePermeableAlphaInletOutletVelocityFvPatchVectorField
+  - Foam::mixedFvPatchVectorField
+  - Foam::prghTotalPressureFvPatchScalarField
+
+SourceFiles
+    prghPermeableAlphaTotalPressureFvPatchScalarField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef prghPermeableAlphaTotalPressureFvPatchScalarField_H
+#define prghPermeableAlphaTotalPressureFvPatchScalarField_H
+
+#include "mixedFvPatchField.H"
+#include "volFields.H"
+#include "surfaceFields.H"
+#include "updateableSnGrad.H"
+#include "PatchFunction1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+    Class prghPermeableAlphaTotalPressureFvPatchScalarField Declaration
+\*---------------------------------------------------------------------------*/
+
+class prghPermeableAlphaTotalPressureFvPatchScalarField
+:
+    public mixedFvPatchField<scalar>,
+    public updateablePatchTypes::updateableSnGrad
+{
+    // Private Data
+
+        //- Total pressure field
+        autoPtr<PatchFunction1<scalar>> p0_;
+
+        //- Name of the flux transporting the field
+        word phiName_;
+
+        //- Name of the density field used to normalise the mass flux
+        word rhoName_;
+
+         //- Name of the velocity field
+        word UName_;
+
+        //- Name of the mixture VOF field (if used)
+        word alphaName_;
+
+        //- Minimum alpha value to outlet blockage
+        scalar alphaMin_;
+
+        //- Current time index (used for updating)
+        label curTimeIndex_;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("prghPermeableAlphaTotalPressure");
+
+
+    // Constructors
+
+        //- Construct from patch and internal field
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+        (
+            const fvPatch&,
+            const DimensionedField<scalar, volMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+        (
+            const fvPatch&,
+            const DimensionedField<scalar, volMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given
+        //- prghPermeableAlphaTotalPressureFvPatchScalarField
+        //- onto a new patch
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+        (
+            const prghPermeableAlphaTotalPressureFvPatchScalarField&,
+            const fvPatch&,
+            const DimensionedField<scalar, volMesh>&,
+            const fvPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+        (
+            const prghPermeableAlphaTotalPressureFvPatchScalarField&
+        );
+
+        //- Construct and return a clone
+        virtual tmp<fvPatchField<scalar>> clone() const
+        {
+            return tmp<fvPatchField<scalar>>
+            (
+                new
+                prghPermeableAlphaTotalPressureFvPatchScalarField(*this)
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        prghPermeableAlphaTotalPressureFvPatchScalarField
+        (
+            const prghPermeableAlphaTotalPressureFvPatchScalarField&,
+            const DimensionedField<scalar, volMesh>&
+        );
+
+        //- Construct and return a clone setting internal field reference
+        virtual tmp<fvPatchField<scalar>> clone
+        (
+            const DimensionedField<scalar, volMesh>& iF
+        ) const
+        {
+            return tmp<fvPatchField<scalar>>
+            (
+                new
+                prghPermeableAlphaTotalPressureFvPatchScalarField
+                (
+                    *this,
+                    iF
+                )
+            );
+        }
+
+
+    // Member Functions
+
+        // Mapping
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap
+            (
+                const fvPatchFieldMapper&
+            );
+
+            //- Reverse map the given fvPatchField onto this fvPatchField
+            virtual void rmap
+            (
+                const fvPatchScalarField&,
+                const labelList&
+            );
+
+
+        // Evaluation
+
+            //- Update the coefficients associated with the patch field
+            virtual void updateCoeffs();
+
+            //- Update the patch pressure gradient field from the given snGradp
+            virtual void updateSnGrad(const scalarField& snGradp);
+
+
+        //- Write
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab