From fa95951b6d96f67f5a26124deae79513a53405e6 Mon Sep 17 00:00:00 2001
From: Ned Coltman <edward.coltman@iws.uni-stuttgart.de>
Date: Fri, 23 Nov 2018 15:28:45 +0100
Subject: [PATCH] [fluxvariables] check for dirichlet boundary conditions
 within lateral flux calc

---
 .../navierstokes/staggered/fluxvariables.hh   | 101 ++++++++++--------
 1 file changed, 59 insertions(+), 42 deletions(-)

diff --git a/dumux/freeflow/navierstokes/staggered/fluxvariables.hh b/dumux/freeflow/navierstokes/staggered/fluxvariables.hh
index f308c4607b..80cbd2f99f 100644
--- a/dumux/freeflow/navierstokes/staggered/fluxvariables.hh
+++ b/dumux/freeflow/navierstokes/staggered/fluxvariables.hh
@@ -291,20 +291,23 @@ public:
             // Get the face normal to the face the dof lives on. The staggered sub face conincides with half of this normal face.
             const auto& normalFace = fvGeometry.scvf(eIdx, scvf.pairData()[localSubFaceIdx].localNormalFaceIdx);
 
-            // Construct a temporary scvf which corresponds to the staggered sub face, featuring the location
-            // the sub faces's center.
-            auto localSubFaceCenter = scvf.pairData(localSubFaceIdx).virtualOuterParallelFaceDofPos - normalFace.center();
-            localSubFaceCenter *= 0.5;
-            localSubFaceCenter += normalFace.center();
-            const auto localSubFace = makeGhostFace_(normalFace, localSubFaceCenter);
-
-            // Retrieve the boundary types that correspond to the sub face.
-            const auto bcTypes = problem.boundaryTypes(element, localSubFace);
+            bool lateralFaceHasDirichletPressure = false; // check for Dirichlet boundary condition for the pressure
+            bool lateralFaceHasBJS = false; // check for Beavers-Joseph-Saffman boundary condition
 
             // Check if there is face/element parallel to our face of interest where the dof lives on. If there is no parallel neighbor,
             // we are on a boundary where we have to check for boundary conditions.
             if(!scvf.hasParallelNeighbor(localSubFaceIdx))
             {
+                // Construct a temporary scvf which corresponds to the staggered sub face, featuring the location
+                // the sub faces's center.
+                auto localSubFaceCenter = scvf.pairData(localSubFaceIdx).virtualOuterParallelFaceDofPos - normalFace.center();
+                localSubFaceCenter *= 0.5;
+                localSubFaceCenter += normalFace.center();
+                const auto localSubFace = makeGhostFace_(normalFace, localSubFaceCenter);
+
+                // Retrieve the boundary types that correspond to the sub face.
+                const auto bcTypes = problem.boundaryTypes(element, localSubFace);
+
                 // Check if we have a symmetry boundary condition. If yes, the tangential part of the momentum flux can be neglected
                 // and we may skip any further calculations for the given sub face.
                 if(bcTypes.isSymmetry())
@@ -321,13 +324,23 @@ public:
                 // Handle wall-function fluxes (only required for RANS models)
                 if (incorporateWallFunction_(normalFlux, problem, element, fvGeometry, scvf, normalFace, localSubFace, elemVolVars, elemFaceVars))
                     continue;
+
+                // Check if we have a Beavers-Joseph-Saffman condition or a Dirichlet condition for the velocity or a Dirichlet condition for the pressure.
+                // Then the parallel velocity at the boundary is calculated accordingly for the advective part and the diffusive part of the normal momentum flux.
+                if (bcTypes.isDirichlet(Indices::pressureIdx))
+                    lateralFaceHasDirichletPressure = true;
+                else if (bcTypes.isBJS(Indices::velocity(scvf.directionIndex())))
+                    lateralFaceHasBJS = true;
+                else if (bcTypes.isDirichlet(Indices::velocity(scvf.directionIndex())) == false)
+                    DUNE_THROW(Dune::InvalidStateException,  "Something went wrong with the boundary conditions "
+                           "for the momentum equations at global position " << localSubFaceCenter);
             }
 
             // If there is no symmetry or Neumann boundary condition for the given sub face, proceed to calculate the tangential momentum flux.
             if (problem.enableInertiaTerms())
-                normalFlux += computeAdvectivePartOfLateralMomentumFlux_(problem, element, scvf, normalFace, elemVolVars, faceVars, localSubFaceIdx, bcTypes);
+                normalFlux += computeAdvectivePartOfLateralMomentumFlux_(problem, element, scvf, normalFace, elemVolVars, faceVars, localSubFaceIdx, lateralFaceHasDirichletPressure, lateralFaceHasBJS);
 
-            normalFlux += computeDiffusivePartOfLateralMomentumFlux_(problem, element, scvf, normalFace, elemVolVars, faceVars, localSubFaceIdx, bcTypes);
+            normalFlux += computeDiffusivePartOfLateralMomentumFlux_(problem, element, scvf, normalFace, elemVolVars, faceVars, localSubFaceIdx, lateralFaceHasDirichletPressure, lateralFaceHasBJS);
         }
         return normalFlux;
     }
@@ -362,7 +375,8 @@ private:
                                                                     const ElementVolumeVariables& elemVolVars,
                                                                     const FaceVariables& faceVars,
                                                                     const int localSubFaceIdx,
-                                                                    const BoundaryTypes& bcTypes)
+                                                                    const bool lateralFaceHasDirichletPressure,
+                                                                    const bool lateralFaceHasBJS)
     {
         // Get the transporting velocity, located at the scvf perpendicular to the current scvf where the dof
         // of interest is located.
@@ -378,12 +392,18 @@ private:
         // and therefore have no neighbor. Calls the problem to retrieve a fixed value set on the boundary.
         auto getParallelVelocityFromBoundary = [&]()
         {
-            const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
+            // If there is a Dirichlet condition for the pressure we assume zero gradient for the velocity,
+            // so the velocity at the boundary equal to that on the scvf.
+            if (lateralFaceHasDirichletPressure)
+                return velocitySelf;
 
             // Check if we have a Beavers-Joseph-Saffman condition.
             // If yes, the parallel velocity at the boundary is calculated accordingly.
-            if (bcTypes.isBJS(Indices::velocity(scvf.directionIndex())))
+            if (lateralFaceHasBJS)
                 return problem.bjsVelocity(scvf, normalFace, localSubFaceIdx, velocitySelf);
+
+            const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
+
             return problem.dirichlet(element, ghostFace)[Indices::velocity(scvf.directionIndex())];
         };
 
@@ -446,7 +466,8 @@ private:
                                                                     const ElementVolumeVariables& elemVolVars,
                                                                     const FaceVariables& faceVars,
                                                                     const int localSubFaceIdx,
-                                                                    const BoundaryTypes& bcTypes)
+                                                                    const bool lateralFaceHasDirichletPressure,
+                                                                    const bool lateralFaceHasBJS)
     {
         FacePrimaryVariables normalDiffusiveFlux(0.0);
 
@@ -489,39 +510,35 @@ private:
             }
         }
 
-        // For the parallel derivative, get the velocities at the current (own) scvf
-        // and at the parallel one at the neighboring scvf.
-        const Scalar innerParallelVelocity = faceVars.velocitySelf();
-
-        // Lambda to conveniently get the outer parallel velocity for normal faces that are on the boundary
-        // and therefore have no neighbor. Calls the problem to retrieve a fixed value set on the boundary.
-        auto getParallelVelocityFromBoundary = [&]()
+        // If we have a Dirichlet condition for the pressure we assume to have zero parallel gradient
+        // so we can skip the computation.
+        if (!lateralFaceHasDirichletPressure)
         {
-            const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
-
-            // Check if we have a Beavers-Joseph-Saffman condition.
-            // If yes, the parallel velocity at the boundary is calculated accordingly.
-            if(bcTypes.isBJS(Indices::velocity(scvf.directionIndex())))
-                return problem.bjsVelocity(scvf, normalFace, localSubFaceIdx, innerParallelVelocity);
+            // For the parallel derivative, get the velocities at the current (own) scvf
+            // and at the parallel one at the neighboring scvf.
+            const Scalar innerParallelVelocity = faceVars.velocitySelf();
 
-            else if(bcTypes.isDirichlet(Indices::velocity(scvf.directionIndex())))
+            // Lambda to conveniently get the outer parallel velocity for normal faces that are on the boundary
+            // and therefore have no neighbor. Calls the problem to retrieve a fixed value set on the boundary.
+            auto getParallelVelocityFromBoundary = [&]()
+            {
+                const auto ghostFace = makeParallelGhostFace_(scvf, localSubFaceIdx);
+                if (lateralFaceHasBJS)
+                    return problem.bjsVelocity(scvf, normalFace, localSubFaceIdx, innerParallelVelocity);
                 return problem.dirichlet(element, ghostFace)[Indices::velocity(scvf.directionIndex())];
+            };
 
-            //bcTypes.isDirichlet(Indices::pressureIdx) is assumed to be true now
-            else
-                return innerParallelVelocity;
-        };
-
-        const Scalar outerParallelVelocity = scvf.hasParallelNeighbor(localSubFaceIdx)
-                                             ? faceVars.velocityParallel(localSubFaceIdx)
-                                             : getParallelVelocityFromBoundary();
+            const Scalar outerParallelVelocity = scvf.hasParallelNeighbor(localSubFaceIdx)
+                                                 ? faceVars.velocityParallel(localSubFaceIdx)
+                                                 : getParallelVelocityFromBoundary();
 
-        // The velocity gradient already accounts for the orientation
-        // of the staggered face's outer normal vector.
-        const Scalar parallelGradient = (outerParallelVelocity - innerParallelVelocity)
-                                        / scvf.pairData(localSubFaceIdx).parallelDistance;
+            // The velocity gradient already accounts for the orientation
+            // of the staggered face's outer normal vector.
+            const Scalar parallelGradient = (outerParallelVelocity - innerParallelVelocity)
+                                            / scvf.pairData(localSubFaceIdx).parallelDistance;
 
-        normalDiffusiveFlux -= muAvg * parallelGradient;
+            normalDiffusiveFlux -= muAvg * parallelGradient;
+        }
 
         // Account for the area of the staggered normal face (0.5 of the coinciding scfv).
         return normalDiffusiveFlux * normalFace.area() * 0.5 * extrusionFactor_(elemVolVars, normalFace);
-- 
GitLab