From c0338acb1c6b76fe77ca23c106a7ebd9169c7214 Mon Sep 17 00:00:00 2001
From: Thomas Fetzer <thomas.fetzer@iws.uni-stuttgart.de>
Date: Wed, 14 Mar 2018 14:43:42 +0100
Subject: [PATCH] [rans][zeroeq] First version of velocity gradients

---
 dumux/freeflow/rans/problem.hh                | 85 +++++++++++++++++--
 dumux/freeflow/rans/volumevariables.hh        |  7 +-
 dumux/freeflow/rans/vtkoutputfields.hh        |  2 +
 dumux/freeflow/rans/zeroeq/volumevariables.hh |  8 +-
 test/freeflow/rans/pipelauferproblem.hh       | 16 +---
 test/freeflow/rans/test_pipe_laufer.input     |  3 +-
 6 files changed, 98 insertions(+), 23 deletions(-)

diff --git a/dumux/freeflow/rans/problem.hh b/dumux/freeflow/rans/problem.hh
index c188fd9f60..c49b403825 100644
--- a/dumux/freeflow/rans/problem.hh
+++ b/dumux/freeflow/rans/problem.hh
@@ -116,12 +116,15 @@ public:
         // update size and initial values of the global vectors
         wallElementIDs_.resize(this->fvGridGeometry().elementMapper().size());
         wallDistances_.resize(this->fvGridGeometry().elementMapper().size());
+        neighborIDs_.resize(this->fvGridGeometry().elementMapper().size());
+        cellCenters_.resize(this->fvGridGeometry().elementMapper().size());
         velocity_.resize(this->fvGridGeometry().elementMapper().size());
         velocityGradients_.resize(this->fvGridGeometry().elementMapper().size());
         kinematicViscosity_.resize(this->fvGridGeometry().elementMapper().size());
         for (unsigned int i = 0; i < wallElementIDs_.size(); ++i)
         {
             wallDistances_[i] = std::numeric_limits<Scalar>::max();
+            cellCenters_[i] = GlobalPosition(0.0);
             velocity_[i] = DimVector(0.0);
             velocityGradients_[i] = DimMatrix(0.0);
             kinematicViscosity_[i] = 0.0;
@@ -148,11 +151,12 @@ public:
         // search for shortest distance to wall for each element
         for (const auto& element : elements(gridView))
         {
+            unsigned int elementID = this->fvGridGeometry().elementMapper().index(element);
+            cellCenters_[elementID] = element.geometry().center();
             for (unsigned int i = 0; i < wallPositions.size(); ++i)
             {
                 GlobalPosition global = element.geometry().center();
                 global -= wallPositions[i];
-                unsigned int elementID = this->fvGridGeometry().elementMapper().index(element);
                 if (global.two_norm() < wallDistances_[elementID])
                 {
                     wallDistances_[elementID] = global.two_norm();
@@ -160,6 +164,50 @@ public:
                 }
             }
         }
+
+        // search for neighbor IDs
+        for (const auto& element : elements(gridView))
+        {
+            unsigned int elementID = this->fvGridGeometry().elementMapper().index(element);
+            std::array<std::array<Scalar, 2>, dim> distances;
+            for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
+            {
+                neighborIDs_[elementID][dimIdx][0] = elementID;
+                neighborIDs_[elementID][dimIdx][1] = elementID;
+                distances[dimIdx][0] = std::numeric_limits<Scalar>::max();
+                distances[dimIdx][1] = -std::numeric_limits<Scalar>::max();
+            }
+            for (const auto& neighbor : elements(gridView))
+            {
+                unsigned int neighborID = this->fvGridGeometry().elementMapper().index(neighbor);
+                for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
+                {
+                    if (elementID == neighborID)
+                        continue;
+//                     std::cout << elementID << " " << neighborID << std::endl;
+
+                    for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
+                    {
+                        Scalar distanceTemp = cellCenters_[elementID][dimIdx] - cellCenters_[neighborID][dimIdx];
+//                         std::cout << distanceTemp
+//                                   << " " << distances[dimIdx][0]
+//                                   << " " << distances[dimIdx][1]
+//                                   << std::endl;
+                        if (distanceTemp < distances[dimIdx][0] && distanceTemp > 1e-8)
+                        {
+                            neighborIDs_[elementID][dimIdx][0] = neighborID;
+                            distances[dimIdx][0] = distanceTemp;
+                        }
+
+                        if (distanceTemp > distances[dimIdx][1] && distanceTemp < -1e-8)
+                        {
+                            neighborIDs_[elementID][dimIdx][1] = neighborID;
+                            distances[dimIdx][1] = distanceTemp;
+                        }
+                    }
+                }
+            }
+        }
     }
 
     /*!
@@ -186,7 +234,29 @@ public:
             }
             for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
                 velocity_[elementID][dimIdx] = velocityTemp[dimIdx] * 0.5; // faces are equidistant to cell center
+        }
 
+        for (const auto& element : elements(this->fvGridGeometry().gridView()))
+        {
+            unsigned int elementID = this->fvGridGeometry().elementMapper().index(element);
+            for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
+            {
+                for (unsigned int velIdx = 0; velIdx < dim; ++velIdx)
+                {
+                    velocityGradients_[elementID][velIdx][dimIdx]
+                        = (velocity_[neighborIDs_[elementID][dimIdx][1]][velIdx]
+                              - velocity_[neighborIDs_[elementID][dimIdx][0]][velIdx])
+                          / (cellCenters_[neighborIDs_[elementID][dimIdx][1]][dimIdx]
+                              - cellCenters_[neighborIDs_[elementID][dimIdx][0]][dimIdx]);
+//                     std::cout << " velocity_[1][velIdx] " << velocity_[neighborIDs_[elementID][dimIdx][1]][velIdx]
+//                               << " velocity_[0][velIdx] " << velocity_[neighborIDs_[elementID][dimIdx][0]][velIdx]
+//                               << " cellCenters_[1][velIdx] " << cellCenters_[neighborIDs_[elementID][dimIdx][1]][dimIdx]
+//                               << " cellCenters_[0][velIdx] " << cellCenters_[neighborIDs_[elementID][dimIdx][0]][dimIdx]
+//                               << " velocityGradients_[elementID][" << velIdx << "][" << dimIdx << "] " << velocityGradients_[elementID][velIdx][dimIdx];
+                }
+            }
+//             std::cout << std::endl;
+        }
 //             // TODO: calculate velocity gradients
 //             for (auto&& scv : scvs(fvGeometry))
 //             {
@@ -218,12 +288,15 @@ public:
 //                     velocityTemp[scvf.directionIndex()] += numericalSolutionFace;
 //                 }
 //             }
-            for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
-                for (unsigned int velIdx = 0; velIdx < dim; ++velIdx)
-                    velocityGradients_[elementID][velIdx][dimIdx] = 0.12345;
+//             for (unsigned int dimIdx = 0; dimIdx < dim; ++dimIdx)
+//                 for (unsigned int velIdx = 0; velIdx < dim; ++velIdx)
+//                     velocityGradients_[elementID][velIdx][dimIdx] = 0.12345;
 
 //             // TODO calculate or call all secondary variables
 //             // TODO call kinematic viscosity value from vol vars
+        for (const auto& element : elements(this->fvGridGeometry().gridView()))
+        {
+            unsigned int elementID = this->fvGridGeometry().elementMapper().index(element);
             kinematicViscosity_[elementID] = 15e-6;
         }
     }
@@ -231,7 +304,7 @@ public:
     /*!
      * \brief Returns whether a given point is on a wall
      */
-    const bool isOnWall(GlobalPosition &globalPos) const
+    bool isOnWall(const GlobalPosition &globalPos) const
     {
         // Throw an exception if no walls are implemented
         DUNE_THROW(Dune::InvalidStateException,
@@ -281,6 +354,8 @@ public:
 public:
     mutable std::vector<unsigned int> wallElementIDs_;
     mutable std::vector<Scalar> wallDistances_;
+    mutable std::vector<std::array<std::array<unsigned int, 2>, dim>> neighborIDs_;
+    mutable std::vector<GlobalPosition> cellCenters_;
     mutable std::vector<DimVector> velocity_;
     mutable std::vector<DimMatrix> velocityGradients_;
     mutable std::vector<Scalar> kinematicViscosity_;
diff --git a/dumux/freeflow/rans/volumevariables.hh b/dumux/freeflow/rans/volumevariables.hh
index 9851545ba0..d0df6196b9 100644
--- a/dumux/freeflow/rans/volumevariables.hh
+++ b/dumux/freeflow/rans/volumevariables.hh
@@ -87,6 +87,8 @@ public:
                 const Element &element,
                 const SubControlVolume& scv)
     {
+        using std::abs;
+        using std::max;
         using std::sqrt;
         ParentType::update(elemSol, problem, element, scv);
 
@@ -95,10 +97,11 @@ public:
         wallElementID_ = problem.wallElementIDs_[elementID_];
         wallDistance_ = problem.wallDistances_[elementID_];
         velocity_ = problem.velocity_[elementID_];
+        velocityGradients_ = problem.velocityGradients_[elementID_];
         Scalar uStar = sqrt(problem.kinematicViscosity_[wallElementID_]
-                            * problem.velocityGradients_[wallElementID_][0][1]); // TODO: flow and wallnormalaxis
+                            * abs(problem.velocityGradients_[wallElementID_][0][1])); // TODO: flow and wallnormalaxis
         yPlus_ = wallDistance_ * uStar / asImp_().kinematicViscosity();
-        uPlus_ = velocity_[0] / uStar; // TODO: flow and wallnormalaxis
+        uPlus_ = velocity_[0] / max(uStar, 1e-8); // TODO: flow and wallnormalaxis
 
         // calculate the eddy viscosity based on the implemented RANS model
         asImp_().calculateEddyViscosity(elemSol, problem, element, scv);
diff --git a/dumux/freeflow/rans/vtkoutputfields.hh b/dumux/freeflow/rans/vtkoutputfields.hh
index 40d5a8c472..631bb23006 100644
--- a/dumux/freeflow/rans/vtkoutputfields.hh
+++ b/dumux/freeflow/rans/vtkoutputfields.hh
@@ -52,6 +52,8 @@ public:
     static void init(VtkOutputModule& vtk)
     {
         vtk.addVolumeVariable([](const auto& v){ return v.velocity()[0]; }, "v_x [m/s]");
+        vtk.addVolumeVariable([](const auto& v){ return v.velocityGradients()[0][0]; }, "dv_x/dx [m/s]");
+        vtk.addVolumeVariable([](const auto& v){ return v.velocityGradients()[0][1]; }, "dv_x/dy [m/s]");
         vtk.addVolumeVariable([](const auto& v){ return v.pressure(); }, "p [Pa]");
         vtk.addVolumeVariable([](const auto& v){ return v.pressure() - 1e5; }, "p_rel [Pa]");
         vtk.addVolumeVariable([](const auto& v){ return v.density(); }, "rho [kg/m^3]");
diff --git a/dumux/freeflow/rans/zeroeq/volumevariables.hh b/dumux/freeflow/rans/zeroeq/volumevariables.hh
index d6555dd72f..fca4665c89 100644
--- a/dumux/freeflow/rans/zeroeq/volumevariables.hh
+++ b/dumux/freeflow/rans/zeroeq/volumevariables.hh
@@ -105,9 +105,12 @@ public:
                                 const Element &element,
                                 const SubControlVolume& scv)
     {
+        using std::abs;
         using std::exp;
+        using std::sqrt;
         Scalar kinematicEddyViscosity = 0.0;
         const Scalar karmanConstant = 0.41; // TODO make karman constant a property
+        Scalar velGrad = abs(asImp_().velocityGradients()[0][1]); // TODO: flow and wallnormalaxis
         if (eddyViscosityModel_ == Indices::noEddyViscosityModel)
         {
             // kinematicEddyViscosity = 0.0
@@ -115,14 +118,13 @@ public:
         else if (eddyViscosityModel_ == Indices::prandtl)
         {
             Scalar mixingLength = karmanConstant * asImp_().wallDistance();
-            Scalar velGrad = asImp_().velocityGradients()[0][1]; // TODO: flow and wallnormalaxis
             kinematicEddyViscosity = mixingLength * mixingLength * velGrad;
         }
         else if (eddyViscosityModel_ == Indices::modifiedVanDriest)
         {
             Scalar mixingLength = karmanConstant * asImp_().wallDistance()
-                                  * (1.0 - exp(-asImp_().yPlus() / 26.0));
-            Scalar velGrad = asImp_().velocityGradients()[0][1]; // TODO: flow and wallnormalaxis
+                                  * (1.0 - exp(-asImp_().yPlus() / 26.0))
+                                  / sqrt(1.0 - exp(-0.26 * asImp_().yPlus()));
             kinematicEddyViscosity = mixingLength * mixingLength * velGrad;
         }
         else
diff --git a/test/freeflow/rans/pipelauferproblem.hh b/test/freeflow/rans/pipelauferproblem.hh
index 8a9ba994d3..8da07e74df 100644
--- a/test/freeflow/rans/pipelauferproblem.hh
+++ b/test/freeflow/rans/pipelauferproblem.hh
@@ -112,7 +112,7 @@ public:
      */
     // \{
 
-    const bool isOnWall(GlobalPosition &globalPos) const
+    bool isOnWall(const GlobalPosition &globalPos) const
     {
         Scalar localEps_ = 1e-6; // cannot use the epsilon, because ParentType is initialized first
         return globalPos[1] < this->fvGridGeometry().bBoxMin()[1] + localEps_
@@ -180,14 +180,7 @@ public:
      */
     PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
     {
-        PrimaryVariables values = initialAtPos(globalPos);
-
-        if(isInlet(globalPos))
-        {
-            values[velocityXIdx] = inletVelocity_;
-        }
-
-        return values;
+        return initialAtPos(globalPos);
     }
 
     // \}
@@ -204,13 +197,12 @@ public:
      */
     PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
     {
-        PrimaryVariables values;
+        PrimaryVariables values(0.0);
         values[pressureIdx] = 1.0e+5;
-        if(isInlet(globalPos))
+        if(!isOnWall(globalPos))
         {
             values[velocityXIdx] = inletVelocity_;
         }
-        values[velocityYIdx] = 0.0;
 
         return values;
     }
diff --git a/test/freeflow/rans/test_pipe_laufer.input b/test/freeflow/rans/test_pipe_laufer.input
index 46ac807569..c3e018c3fd 100644
--- a/test/freeflow/rans/test_pipe_laufer.input
+++ b/test/freeflow/rans/test_pipe_laufer.input
@@ -1,5 +1,5 @@
 [TimeLoop]
-DtInitial = 1 # [s]
+DtInitial = 1e-1 # [s]
 TEnd = 100 # [s]
 
 [Grid]
@@ -23,6 +23,7 @@ EddyViscosityModel = 1
 [Newton]
 MaxSteps = 10
 MaxRelativeShift = 1e-5
+TargetSteps = 8
 
 [Vtk]
 AddVelocity = true
-- 
GitLab