3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
dumux/freeflow/rans/zeroeq/problem.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_ZEROEQ_PROBLEM_HH
25#define DUMUX_ZEROEQ_PROBLEM_HH
26
27#include <string>
28
36
37#include "model.hh"
38
39namespace Dumux {
40
48template<class TypeTag>
49class RANSProblemImpl<TypeTag, TurbulenceModel::zeroeq> : public RANSProblemBase<TypeTag>
50{
51 using ParentType = RANSProblemBase<TypeTag>;
52 using Implementation = GetPropType<TypeTag, Properties::Problem>;
54 using Grid = typename GridView::Grid;
56
58 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
59 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
63 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
65
66 enum {
67 dim = Grid::dimension,
68 };
69 using DimVector = Dune::FieldVector<Scalar, dim>;
70 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
71
72public:
78 RANSProblemImpl(std::shared_ptr<const GridGeometry> gridGeometry, const std::string& paramGroup = "")
79 : ParentType(gridGeometry, paramGroup)
80 {
81 eddyViscosityModel_ = getParamFromGroup<std::string>(paramGroup, "RANS.EddyViscosityModel", "vanDriest");
82 }
83
88 {
89 ParentType::updateStaticWallProperties();
90
91 // update size and initial values of the global vectors
92 kinematicEddyViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
93 additionalRoughnessLength_.resize(this->gridGeometry().elementMapper().size(), 0.0);
94 }
95
103 void updateDynamicWallProperties(const SolutionVector& curSol)
104 {
105 ParentType::updateDynamicWallProperties(curSol);
106
107 // calculate additional roughness
108 bool printedRangeWarning = false;
109 for (const auto& element : elements(this->gridGeometry().gridView()))
110 {
111 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
112
113 auto fvGeometry = localView(this->gridGeometry());
114 fvGeometry.bindElement(element);
115 for (auto&& scv : scvs(fvGeometry))
116 {
117 using std::sqrt;
118 using std::exp;
119
120 const int dofIdx = scv.dofIndex();
121
122 // construct a privars object from the cell center solution vector
123 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
124 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
125 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
126
127 VolumeVariables volVars;
128 volVars.update(elemSol, asImp_(), element, scv);
129
130 Scalar ksPlus = this->sandGrainRoughness_[elementIdx] * volVars.uStar() / volVars.kinematicViscosity();
131 if (ksPlus > 0 && eddyViscosityModel_.compare("baldwinLomax") == 0)
132 {
133 DUNE_THROW(Dune::NotImplemented, "Roughness is not implemented for the Baldwin-Lomax model.");
134 }
135 if (ksPlus > 2000.)
136 {
137 std::cout << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << this->cellCenter_[this->wallElementIdx_[elementIdx]]
138 << " is not in the valid range (ksPlus < 2000),"
139 << " for high ksPlus values the roughness function reaches a turning point."<< std::endl;
140 DUNE_THROW(Dune::InvalidStateException, "Unphysical roughness behavior.");
141 }
142 else if (ksPlus > 0.0 && ksPlus < 4.535 && !printedRangeWarning)
143 {
144 Dune::dinfo << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << this->cellCenter_[this->wallElementIdx_[elementIdx]]
145 << " is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl;
146 ksPlus = 0.0;
147 printedRangeWarning = true;
148 }
149 additionalRoughnessLength_[elementIdx] = 0.9 / (volVars.uStar() / volVars.kinematicViscosity())
150 * (sqrt(ksPlus) - ksPlus * exp(-ksPlus / 6.0));
151 }
152 }
153
154 // update routine for specfic models
155 if (eddyViscosityModel_.compare("baldwinLomax") == 0)
156 updateBaldwinLomaxProperties();
157 }
158
163 {
164 std::vector<Scalar> kinematicEddyViscosityInner(this->gridGeometry().elementMapper().size(), 0.0);
165 std::vector<Scalar> kinematicEddyViscosityOuter(this->gridGeometry().elementMapper().size(), 0.0);
166 std::vector<Scalar> kinematicEddyViscosityDifference(this->gridGeometry().elementMapper().size(), 0.0);
167 std::vector<Scalar> switchingPosition(this->gridGeometry().elementMapper().size(), std::numeric_limits<Scalar>::max());
168
169 using std::abs;
170 using std::exp;
171 using std::min;
172 using std::pow;
173 using std::sqrt;
174 const Scalar aPlus = 26.0;
175 const Scalar k = 0.0168;
176 const Scalar cCP = 1.6;
177 const Scalar cWake = 0.25;
178 const Scalar cKleb = 0.3;
179
180 std::vector<Scalar> storedFMax;
181 std::vector<Scalar> storedYFMax;
182 storedFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
183 storedYFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
184
185 // (1) calculate inner viscosity and Klebanoff function
186 for (const auto& element : elements(this->gridGeometry().gridView()))
187 {
188 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
189 unsigned int wallElementIdx = this->wallElementIdx_[elementIdx];
190 Scalar wallDistance = this->wallDistance_[elementIdx] + additionalRoughnessLength_[elementIdx];
191 unsigned int flowNormalAxis = this->flowNormalAxis_[elementIdx];
192 unsigned int wallNormalAxis = this->wallNormalAxis_[elementIdx];
193
194 Scalar omegaAbs = abs(this->velocityGradients_[elementIdx][flowNormalAxis][wallNormalAxis]
195 - this->velocityGradients_[elementIdx][wallNormalAxis][flowNormalAxis]);
196 Scalar uStar = sqrt(this->kinematicViscosity_[wallElementIdx]
197 * abs(this->velocityGradients_[wallElementIdx][flowNormalAxis][wallNormalAxis]));
198 Scalar yPlus = wallDistance * uStar / this->kinematicViscosity_[elementIdx];
199 Scalar mixingLength = this->karmanConstant() * wallDistance * (1.0 - exp(-yPlus / aPlus));
200 kinematicEddyViscosityInner[elementIdx] = mixingLength * mixingLength * omegaAbs;
201
202 Scalar f = wallDistance * omegaAbs * (1.0 - exp(-yPlus / aPlus));
203 if (f > storedFMax[wallElementIdx])
204 {
205 storedFMax[wallElementIdx] = f;
206 storedYFMax[wallElementIdx] = wallDistance;
207 }
208 }
209
210 // (2) calculate outer viscosity
211 for (const auto& element : elements(this->gridGeometry().gridView()))
212 {
213 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
214 unsigned int wallElementIdx = this->wallElementIdx_[elementIdx];
215 Scalar wallDistance = this->wallDistance_[elementIdx] + additionalRoughnessLength_[elementIdx];
216
217 Scalar maxVelocityNorm = 0.0;
218 Scalar minVelocityNorm = 0.0;
219 for (unsigned dimIdx = 0; dimIdx < dim; ++dimIdx)
220 {
221 maxVelocityNorm += this->velocityMaximum_[wallElementIdx][dimIdx]
222 * this->velocityMaximum_[wallElementIdx][dimIdx];
223 minVelocityNorm += this->velocityMinimum_[wallElementIdx][dimIdx]
224 * this->velocityMinimum_[wallElementIdx][dimIdx];
225 }
226 Scalar deltaU = sqrt(maxVelocityNorm) - sqrt(minVelocityNorm);
227 Scalar yFMax = storedYFMax[wallElementIdx];
228 Scalar fMax = storedFMax[wallElementIdx];
229 Scalar fWake = min(yFMax * fMax, cWake * yFMax * deltaU * deltaU / fMax);
230 Scalar fKleb = 1.0 / (1.0 + 5.5 * pow(cKleb * wallDistance / yFMax, 6.0));
231 kinematicEddyViscosityOuter[elementIdx] = k * cCP * fWake * fKleb;
232
233 kinematicEddyViscosityDifference[elementIdx]
234 = kinematicEddyViscosityInner[elementIdx] - kinematicEddyViscosityOuter[elementIdx];
235 }
236
237 // (3) switching point
238 for (const auto& element : elements(this->gridGeometry().gridView()))
239 {
240 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
241 unsigned int wallElementIdx = this->wallElementIdx_[elementIdx];
242 Scalar wallDistance = this->wallDistance_[elementIdx] + additionalRoughnessLength_[elementIdx];
243
244 // checks if sign switches, by multiplication
245 Scalar check = kinematicEddyViscosityDifference[wallElementIdx] * kinematicEddyViscosityDifference[elementIdx];
246 if (check < 0 // means sign has switched
247 && switchingPosition[wallElementIdx] > wallDistance)
248 {
249 switchingPosition[wallElementIdx] = wallDistance;
250 }
251 }
252
253 // (4) finally determine eddy viscosity
254 for (const auto& element : elements(this->gridGeometry().gridView()))
255 {
256 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
257 unsigned int wallElementIdx = this->wallElementIdx_[elementIdx];
258 Scalar wallDistance = this->wallDistance_[elementIdx] + additionalRoughnessLength_[elementIdx];
259
260 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityInner[elementIdx];
261 if (wallDistance >= switchingPosition[wallElementIdx])
262 {
263 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityOuter[elementIdx];
264 }
265 }
266 }
267
268public:
270 std::vector<Scalar> kinematicEddyViscosity_;
271 std::vector<Scalar> additionalRoughnessLength_;
272
273private:
275 Implementation &asImp_()
276 { return *static_cast<Implementation *>(this); }
277
279 const Implementation &asImp_() const
280 { return *static_cast<const Implementation *>(this); }
281};
282
283} // end namespace Dumux
284
285#endif
Free function to get the local view of a grid cache object.
The available discretization methods in Dumux.
The available free flow turbulence models in Dumux.
Base class for all staggered fv problems.
TurbulenceModel
The available free flow turbulence models in Dumux.
Definition: turbulencemodel.hh:37
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
forward declare
Definition: dumux/freeflow/rans/problem.hh:41
Reynolds-Averaged Navier-Stokes problem base class.
Definition: dumux/freeflow/rans/problem.hh:57
std::vector< Scalar > additionalRoughnessLength_
Definition: dumux/freeflow/rans/zeroeq/problem.hh:271
RANSProblemImpl(std::shared_ptr< const GridGeometry > gridGeometry, const std::string &paramGroup="")
The constructor.
Definition: dumux/freeflow/rans/zeroeq/problem.hh:78
std::string eddyViscosityModel_
Definition: dumux/freeflow/rans/zeroeq/problem.hh:269
void updateStaticWallProperties()
Correct size of the static (solution independent) wall variables.
Definition: dumux/freeflow/rans/zeroeq/problem.hh:87
std::vector< Scalar > kinematicEddyViscosity_
Definition: dumux/freeflow/rans/zeroeq/problem.hh:270
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) relations to the walls.
Definition: dumux/freeflow/rans/zeroeq/problem.hh:103
void updateBaldwinLomaxProperties()
Update the relations and coefficients for the Baldwin-Lomax turbulence model.
Definition: dumux/freeflow/rans/zeroeq/problem.hh:162
The local element solution class for staggered methods.
Declares all properties used in Dumux.
Adaption of the fully implicit scheme to the tracer transport model.