From 5db676551b3a6614cc4b9a5b9cd4011df04e760b Mon Sep 17 00:00:00 2001
From: Henry Weller <http://openfoam.org>
Date: Mon, 17 Jul 2017 15:48:39 +0100
Subject: [PATCH] matchedFlowRateOutletVelocity: New flow-rate outlet BC

Velocity outlet boundary condition which corrects the extrapolated velocity
to match the flow rate of the specified corresponding inlet patch.
---
 ...FlowRateOutletVelocityFvPatchVectorField.C | 271 ++++++++++++++++++
 ...FlowRateOutletVelocityFvPatchVectorField.H | 189 ++++++++++++
 2 files changed, 460 insertions(+)
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.C
 create mode 100644 src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.H

diff --git a/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.C b/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.C
new file mode 100644
index 0000000000..4ea359ee5b
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.C
@@ -0,0 +1,271 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 "matchedFlowRateOutletVelocityFvPatchVectorField.H"
+#include "volFields.H"
+#include "one.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::matchedFlowRateOutletVelocityFvPatchVectorField::
+matchedFlowRateOutletVelocityFvPatchVectorField
+(
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF
+)
+:
+    fixedValueFvPatchField<vector>(p, iF),
+    inletPatchName_(),
+    volumetric_(false),
+    rhoName_("rho")
+{}
+
+
+Foam::matchedFlowRateOutletVelocityFvPatchVectorField::
+matchedFlowRateOutletVelocityFvPatchVectorField
+(
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF,
+    const dictionary& dict
+)
+:
+    fixedValueFvPatchField<vector>(p, iF, dict, false),
+    inletPatchName_(dict.lookup("inletPatch")),
+    volumetric_(dict.lookupOrDefault("volumetric", true))
+{
+    if (volumetric_)
+    {
+        rhoName_ = "none";
+    }
+    else
+    {
+        rhoName_ = word(dict.lookupOrDefault<word>("rho", "rho"));
+    }
+
+    // Value field require if mass based
+    if (dict.found("value"))
+    {
+        fvPatchField<vector>::operator=
+        (
+            vectorField("value", dict, p.size())
+        );
+    }
+    else
+    {
+        evaluate(Pstream::commsTypes::blocking);
+    }
+}
+
+
+Foam::matchedFlowRateOutletVelocityFvPatchVectorField::
+matchedFlowRateOutletVelocityFvPatchVectorField
+(
+    const matchedFlowRateOutletVelocityFvPatchVectorField& ptf,
+    const fvPatch& p,
+    const DimensionedField<vector, volMesh>& iF,
+    const fvPatchFieldMapper& mapper
+)
+:
+    fixedValueFvPatchField<vector>(ptf, p, iF, mapper),
+    inletPatchName_(ptf.inletPatchName_),
+    volumetric_(ptf.volumetric_),
+    rhoName_(ptf.rhoName_)
+{}
+
+
+Foam::matchedFlowRateOutletVelocityFvPatchVectorField::
+matchedFlowRateOutletVelocityFvPatchVectorField
+(
+    const matchedFlowRateOutletVelocityFvPatchVectorField& ptf
+)
+:
+    fixedValueFvPatchField<vector>(ptf),
+    inletPatchName_(ptf.inletPatchName_),
+    volumetric_(ptf.volumetric_),
+    rhoName_(ptf.rhoName_)
+{}
+
+
+Foam::matchedFlowRateOutletVelocityFvPatchVectorField::
+matchedFlowRateOutletVelocityFvPatchVectorField
+(
+    const matchedFlowRateOutletVelocityFvPatchVectorField& ptf,
+    const DimensionedField<vector, volMesh>& iF
+)
+:
+    fixedValueFvPatchField<vector>(ptf, iF),
+    inletPatchName_(ptf.inletPatchName_),
+    volumetric_(ptf.volumetric_),
+    rhoName_(ptf.rhoName_)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class RhoType>
+void Foam::matchedFlowRateOutletVelocityFvPatchVectorField::updateValues
+(
+    const label inletPatchID,
+    const RhoType& rhoOutlet,
+    const RhoType& rhoInlet
+)
+{
+    const fvPatch& p = patch();
+    const fvPatch& inletPatch = p.boundaryMesh()[inletPatchID];
+
+    const vectorField n(p.nf());
+
+    // Extrapolate patch velocity
+    vectorField Up(patchInternalField());
+
+    // Patch normal extrapolated velocity
+    scalarField nUp(n & Up);
+
+    // Remove the normal component of the extrapolate patch velocity
+    Up -= nUp*n;
+
+    // Remove any reverse flow
+    nUp = max(nUp, scalar(0));
+
+    // Lookup non-const access to velocity field
+    volVectorField& U
+    (
+        const_cast<volVectorField&>
+        (
+            dynamic_cast<const volVectorField&>(internalField())
+        )
+    );
+
+    // Get the corresponding inlet velocity patch field
+    fvPatchVectorField& inletPatchU = U.boundaryFieldRef()[inletPatchID];
+
+    // Ensure that the corresponding inlet velocity patch field is up-to-date
+    inletPatchU.updateCoeffs();
+
+    // Calculate the inlet patch flow rate
+    const scalar flowRate = -gSum(rhoInlet*(inletPatch.Sf() & inletPatchU));
+
+    // Calculate the extrapolated outlet patch flow rate
+    const scalar estimatedFlowRate = gSum(rhoOutlet*(patch().magSf()*nUp));
+
+    if (estimatedFlowRate/flowRate > 0.5)
+    {
+        nUp *= (mag(flowRate)/mag(estimatedFlowRate));
+    }
+    else
+    {
+        nUp += ((flowRate - estimatedFlowRate)/gSum(rhoOutlet*patch().magSf()));
+    }
+
+    // Add the corrected normal component of velocity to the patch velocity
+    Up += nUp*n;
+
+    // Correct the patch velocity
+    operator==(Up);
+}
+
+
+void Foam::matchedFlowRateOutletVelocityFvPatchVectorField::updateCoeffs()
+{
+    if (updated())
+    {
+        return;
+    }
+
+    // Find corresponding inlet patch
+    const label inletPatchID =
+        patch().patch().boundaryMesh().findPatchID(inletPatchName_);
+
+    if (inletPatchID < 0)
+    {
+        FatalErrorInFunction
+            << "Unable to find inlet patch " << inletPatchName_
+            << exit(FatalError);
+    }
+
+    if (volumetric_)
+    {
+        updateValues(inletPatchID, one(), one());
+    }
+    else
+    {
+        // Mass flow-rate
+        if (db().foundObject<volScalarField>(rhoName_))
+        {
+            const volScalarField& rho = db().lookupObject<volScalarField>
+            (
+                rhoName_
+            );
+
+            updateValues
+            (
+                inletPatchID,
+                rho.boundaryField()[patch().index()],
+                rho.boundaryField()[inletPatchID]
+            );
+        }
+        else
+        {
+            FatalErrorInFunction
+                << "Cannot find density field " << rhoName_ << exit(FatalError);
+        }
+    }
+
+    fixedValueFvPatchVectorField::updateCoeffs();
+}
+
+
+void Foam::matchedFlowRateOutletVelocityFvPatchVectorField::write
+(
+    Ostream& os
+) const
+{
+    fvPatchField<vector>::write(os);
+    os.writeKeyword("inletPatch")
+        << inletPatchName_ << token::END_STATEMENT << nl;
+    if (!volumetric_)
+    {
+        os.writeKeyword("volumetric")
+            << volumetric_ << token::END_STATEMENT << nl;
+        writeEntryIfDifferent<word>(os, "rho", "rho", rhoName_);
+    }
+    writeEntry("value", os);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+   makePatchTypeField
+   (
+       fvPatchVectorField,
+       matchedFlowRateOutletVelocityFvPatchVectorField
+   );
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.H b/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.H
new file mode 100644
index 0000000000..2442e081f5
--- /dev/null
+++ b/src/finiteVolume/fields/fvPatchFields/derived/matchedFlowRateOutletVelocity/matchedFlowRateOutletVelocityFvPatchVectorField.H
@@ -0,0 +1,189 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenFOAM Foundation
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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::matchedFlowRateOutletVelocityFvPatchVectorField
+
+Group
+    grpOutletBoundaryConditions
+
+Description
+    Velocity outlet boundary condition which corrects the extrapolated velocity
+    to match the flow rate of the specified corresponding inlet patch.
+
+Usage
+    \table
+        Property     | Description             | Required    | Default value
+        inletPatch   | Corresponding inlet patch name | yes  |
+        volumetric   | Set volumetric or mass flow-rate | no | false
+        rho          | density field name      | no          | rho
+    \endtable
+
+    Example of the boundary condition specification for a volumetric flow rate:
+    \verbatim
+    <patchName>
+    {
+        type                matchedFlowRateOutletVelocity;
+        inletPatch          inlet;
+        value               uniform (0 0 0);
+    }
+    \endverbatim
+
+See also
+    Foam::fixedValueFvPatchField
+
+SourceFiles
+    matchedFlowRateOutletVelocityFvPatchVectorField.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef matchedFlowRateOutletVelocityFvPatchVectorField_H
+#define matchedFlowRateOutletVelocityFvPatchVectorField_H
+
+#include "fixedValueFvPatchFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+           Class matchedFlowRateOutletVelocityFvPatchVectorField Declaration
+\*---------------------------------------------------------------------------*/
+
+class matchedFlowRateOutletVelocityFvPatchVectorField
+:
+    public fixedValueFvPatchVectorField
+{
+    // Private data
+
+        //- Inlet patch name from which the corresponding flow rate is obtained
+        word inletPatchName_;
+
+        //- Is volumetric?
+        bool volumetric_;
+
+        //- Name of the density field used to normalize the mass flux
+        word rhoName_;
+
+
+    // Private member functions
+
+        //- Update the patch values given the appropriate density type and value
+        template<class RhoType>
+        void updateValues
+        (
+            const label inletPatchID,
+            const RhoType& rhoOutlet,
+            const RhoType& rhoInlet
+        );
+
+
+public:
+
+   //- Runtime type information
+   TypeName("matchedFlowRateOutletVelocity");
+
+
+   // Constructors
+
+        //- Construct from patch and internal field
+        matchedFlowRateOutletVelocityFvPatchVectorField
+        (
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&
+        );
+
+        //- Construct from patch, internal field and dictionary
+        matchedFlowRateOutletVelocityFvPatchVectorField
+        (
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&,
+            const dictionary&
+        );
+
+        //- Construct by mapping given
+        //  matchedFlowRateOutletVelocityFvPatchVectorField
+        //  onto a new patch
+        matchedFlowRateOutletVelocityFvPatchVectorField
+        (
+            const matchedFlowRateOutletVelocityFvPatchVectorField&,
+            const fvPatch&,
+            const DimensionedField<vector, volMesh>&,
+            const fvPatchFieldMapper&
+        );
+
+        //- Construct as copy
+        matchedFlowRateOutletVelocityFvPatchVectorField
+        (
+            const matchedFlowRateOutletVelocityFvPatchVectorField&
+        );
+
+        //- Construct and return a clone
+        virtual tmp<fvPatchVectorField> clone() const
+        {
+            return tmp<fvPatchVectorField>
+            (
+                new matchedFlowRateOutletVelocityFvPatchVectorField(*this)
+            );
+        }
+
+        //- Construct as copy setting internal field reference
+        matchedFlowRateOutletVelocityFvPatchVectorField
+        (
+            const matchedFlowRateOutletVelocityFvPatchVectorField&,
+            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 matchedFlowRateOutletVelocityFvPatchVectorField(*this, iF)
+            );
+        }
+
+
+    // Member functions
+
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
+
+        //- Write
+        virtual void write(Ostream&) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab