From 31a439dc994eaa121f163b477049d3240385526d Mon Sep 17 00:00:00 2001
From: Andrew Heather <>
Date: Mon, 3 Dec 2018 15:27:42 +0000
Subject: [PATCH] ENH: freestream BC: allow inlet value to be specified by
 another patch

The freestreamFvPatchField previously employed a fixed value when supplying
the inlet values.  This commit extends the BC so that users can use another
patch to supply the values via the new freestreamBC entry, e.g. to set the
velocity to an atmospheric boundary layer profile:

    inlet
    {
        type            freestream;
        freestreamBC
        {
            type            atmBoundaryLayerInletVelocity;
            flowDir         (1 0 0);
            zDir            (0 0 1);
            Uref            20;
            Zref            20;
            z0              uniform 0.1;
            zGround         uniform 935;
        }
    }

The earlier specification is also maintained for backwards compatibility, e.g.

    inlet
    {
        type            freestream;
        freestreamValue uniform (300 0 0);
    }
---
 .../freestream/freestreamFvPatchField.C       | 129 +++++++++++++++---
 .../freestream/freestreamFvPatchField.H       |  53 ++++++-
 2 files changed, 160 insertions(+), 22 deletions(-)

diff --git a/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.C b/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.C
index eac0fe4feb0..8dcccfd4227 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.C
+++ b/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2017-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,7 +34,8 @@ Foam::freestreamFvPatchField<Type>::freestreamFvPatchField
     const DimensionedField<Type, volMesh>& iF
 )
 :
-    inletOutletFvPatchField<Type>(p, iF)
+    inletOutletFvPatchField<Type>(p, iF),
+    freestreamBCPtr_()
 {}
 
 
@@ -46,25 +47,43 @@ Foam::freestreamFvPatchField<Type>::freestreamFvPatchField
     const dictionary& dict
 )
 :
-    inletOutletFvPatchField<Type>(p, iF)
+    inletOutletFvPatchField<Type>(p, iF),
+    freestreamBCPtr_()
 {
     this->patchType() = dict.lookupOrDefault<word>("patchType", word::null);
 
     this->phiName_ = dict.lookupOrDefault<word>("phi","phi");
 
-    freestreamValue() = Field<Type>("freestreamValue", dict, p.size());
-
-    if (dict.found("value"))
+    if (dict.found("freestreamValue"))
+    {
+        freestreamValue() =
+            Field<Type>("freestreamValue", dict, p.size());
+
+        if (dict.found("value"))
+        {
+            fvPatchField<Type>::operator=
+            (
+                Field<Type>("value", dict, p.size())
+            );
+        }
+        else
+        {
+            fvPatchField<Type>::operator=(freestreamValue());
+        }
+    }
+    else
     {
+        // Freestream value provided by another patch
+        freestreamBCPtr_ =
+            fvPatchField<Type>::New(p, iF, dict.subDict("freestreamBC"));
+
+        // Force user to supply an initial value
+        // - we do not know if the supplied BC has all dependencies available
         fvPatchField<Type>::operator=
         (
             Field<Type>("value", dict, p.size())
         );
     }
-    else
-    {
-        fvPatchField<Type>::operator=(freestreamValue());
-    }
 }
 
 
@@ -77,8 +96,15 @@ Foam::freestreamFvPatchField<Type>::freestreamFvPatchField
     const fvPatchFieldMapper& mapper
 )
 :
-    inletOutletFvPatchField<Type>(ptf, p, iF, mapper)
-{}
+    inletOutletFvPatchField<Type>(ptf, p, iF, mapper),
+    freestreamBCPtr_()
+{
+    if (ptf.freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_ =
+            fvPatchField<Type>::New(ptf.freestreamBCPtr_(), p, iF, mapper);
+    }
+}
 
 
 template<class Type>
@@ -87,8 +113,14 @@ Foam::freestreamFvPatchField<Type>::freestreamFvPatchField
     const freestreamFvPatchField<Type>& ptf
 )
 :
-    inletOutletFvPatchField<Type>(ptf)
-{}
+    inletOutletFvPatchField<Type>(ptf),
+    freestreamBCPtr_()
+{
+    if (ptf.freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_ = ptf.freestreamBCPtr_->clone();
+    }
+}
 
 
 template<class Type>
@@ -98,18 +130,81 @@ Foam::freestreamFvPatchField<Type>::freestreamFvPatchField
     const DimensionedField<Type, volMesh>& iF
 )
 :
-    inletOutletFvPatchField<Type>(ptf, iF)
-{}
+    inletOutletFvPatchField<Type>(ptf, iF),
+    freestreamBCPtr_()
+{
+    if (ptf.freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_ = ptf.freestreamBCPtr_->clone();
+    }
+}
 
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+template<class Type>
+void Foam::freestreamFvPatchField<Type>::autoMap(const fvPatchFieldMapper& m)
+{
+    inletOutletFvPatchField<Type>::autoMap(m);
+    if (freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_->autoMap(m);
+    }
+}
+
+
+template<class Type>
+void Foam::freestreamFvPatchField<Type>::rmap
+(
+    const fvPatchField<Type>& ptf,
+    const labelList& addr
+)
+{
+    inletOutletFvPatchField<Type>::rmap(ptf, addr);
+
+    const auto& fsptf = refCast<const freestreamFvPatchField<Type>>(ptf);
+
+    if (fsptf.freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_->rmap(fsptf.freestreamBCPtr_(), addr);
+    }
+}
+
+
+template<class Type>
+void Foam::freestreamFvPatchField<Type>::updateCoeffs()
+{
+    if (this->updated())
+    {
+        return;
+    }
+
+    if (freestreamBCPtr_.valid())
+    {
+        freestreamBCPtr_->evaluate();
+        freestreamValue() = freestreamBCPtr_();
+    }
+
+    inletOutletFvPatchField<Type>::updateCoeffs();
+}
+
+
 template<class Type>
 void Foam::freestreamFvPatchField<Type>::write(Ostream& os) const
 {
     fvPatchField<Type>::write(os);
     os.writeEntryIfDifferent<word>("phi", "phi", this->phiName_);
-    freestreamValue().writeEntry("freestreamValue", os);
+
+    if (freestreamBCPtr_.valid())
+    {
+        os.beginBlock("freestreamBC");
+        freestreamBCPtr_->write(os);
+        os.endBlock();
+    }
+    else
+    {
+        freestreamValue().writeEntry("freestreamValue", os);
+    }
     this->writeEntry("value", os);
 }
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.H
index 15757c90cf1..ff860522d84 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/freestream/freestreamFvPatchField.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2018 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,12 +35,14 @@ Description
 
 Usage
     \table
-        Property     | Description             | Required    | Default value
-        freestreamValue   | freestream velocity          | yes         |
-        phi          | flux field name         | no          | phi
+        Property        | Description           | Required    | Default value
+        freestreamValue | freestream velocity   | no          |
+        freestreamBC    | patchField providing the inlet field | no  |
+        phi             | flux field name       | no          | phi
     \endtable
 
-    Example of the boundary condition specification:
+    Example of the boundary condition specification using a fixed value
+    inlet condition:
     \verbatim
     <patchName>
     {
@@ -49,6 +51,26 @@ Usage
     }
     \endverbatim
 
+    Example of the boundary condition specification using a separate condition
+    to proveide the inlet condition:
+    \verbatim
+    <patchName>
+    {
+        type            freestream;
+        freestreamBC
+        {
+            type            atmBoundaryLayerInletVelocity;
+            flowDir         (1 0 0);
+            zDir            (0 0 1);
+            Uref            20;
+            Zref            20;
+            z0              uniform 0.1;
+            zGround         uniform 935;
+        }
+    }
+    \endverbatim
+
+
 See also
     Foam::mixedFvPatchField
     Foam::inletOutletFvPatchField
@@ -77,6 +99,11 @@ class freestreamFvPatchField
 :
     public inletOutletFvPatchField<Type>
 {
+    // Private data
+
+        //- BC to supply the freestream value
+        tmp<fvPatchField<Type>> freestreamBCPtr_;
+
 
 public:
 
@@ -147,6 +174,22 @@ public:
 
     // Member functions
 
+        // Mapping functions
+
+            //- Map (and resize as needed) from self given a mapping object
+            virtual void autoMap(const fvPatchFieldMapper& mapper);
+
+            //- Reverse map the given fvPatchField onto this fvPatchField
+            virtual void rmap
+            (
+                const fvPatchField<Type>& ptf,
+                const labelList& addr
+            );
+
+
+        //- Update the coefficients associated with the patch field
+        virtual void updateCoeffs();
+
         // Return defining fields
 
             const Field<Type>& freestreamValue() const
-- 
GitLab