12#ifndef DUMUX_ZEROEQ_PROBLEM_HH
13#define DUMUX_ZEROEQ_PROBLEM_HH
17#include <dune/common/math.hh>
18#include <dune/common/stdstreams.hh>
39template<
class TypeTag>
45 using Grid =
typename GridView::Grid;
50 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
57 dim = Grid::dimension,
59 using DimVector = Dune::FieldVector<Scalar, dim>;
60 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
68 RANSProblemImpl(std::shared_ptr<const GridGeometry> gridGeometry,
const std::string& paramGroup =
"")
77 if (!ParentType::isFlatWallBounded())
79 DUNE_THROW(Dune::NotImplemented,
"\n Due to grid/geometric concerns, zero-eq models should only be used for flat channel geometries. "
80 <<
"\n If your geometry is a flat channel, please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
83 ParentType::updateStaticWallProperties();
86 kinematicEddyViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
87 additionalRoughnessLength_.resize(this->gridGeometry().elementMapper().size(), 0.0);
97 template<
class SolutionVector>
100 ParentType::updateDynamicWallProperties(curSol);
103 if (
hasParam(
"RANS.SandGrainRoughness"))
104 calculateRoughnessLength_(curSol);
107 if (eddyViscosityModel().compare(
"baldwinLomax") == 0)
108 updateBaldwinLomaxProperties();
116 std::vector<Scalar> kinematicEddyViscosityInner(this->gridGeometry().elementMapper().size(), 0.0);
117 std::vector<Scalar> kinematicEddyViscosityOuter(this->gridGeometry().elementMapper().size(), 0.0);
118 std::vector<Scalar> kinematicEddyViscosityDifference(this->gridGeometry().elementMapper().size(), 0.0);
119 std::vector<Scalar> switchingPosition(this->gridGeometry().elementMapper().size(), std::numeric_limits<Scalar>::max());
126 const Scalar aPlus = 26.0;
127 const Scalar k = 0.0168;
128 const Scalar cCP = 1.6;
129 const Scalar cWake = 0.25;
130 const Scalar cKleb = 0.3;
132 std::vector<Scalar> storedFMax;
133 std::vector<Scalar> storedYFMax;
134 storedFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
135 storedYFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
138 for (
const auto& element : elements(this->gridGeometry().gridView()))
140 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
141 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
142 unsigned int flowDirectionAxis = this->flowDirectionAxis(elementIdx);
143 unsigned int wallNormalAxis = this->wallNormalAxis(elementIdx);
145 Scalar omegaAbs = abs(this->velocityGradient(elementIdx, flowDirectionAxis, wallNormalAxis)
146 - this->velocityGradient(elementIdx, wallNormalAxis, flowDirectionAxis));
147 Scalar uStar = sqrt(this->kinematicViscosity(asImp_().wallElementIndex(elementIdx))
148 * abs(this->velocityGradient(asImp_().wallElementIndex(elementIdx), flowDirectionAxis, wallNormalAxis)));
149 Scalar yPlus = effectiveWallDistance * uStar / this->kinematicViscosity(elementIdx);
150 Scalar mixingLength = this->karmanConstant() * effectiveWallDistance * (1.0 - exp(-yPlus / aPlus));
151 kinematicEddyViscosityInner[elementIdx] = mixingLength * mixingLength * omegaAbs;
153 Scalar f = effectiveWallDistance * omegaAbs * (1.0 - exp(-yPlus / aPlus));
154 if (f > storedFMax[asImp_().wallElementIndex(elementIdx)])
156 storedFMax[asImp_().wallElementIndex(elementIdx)] = f;
157 storedYFMax[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
162 for (
const auto& element : elements(this->gridGeometry().gridView()))
164 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
165 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
167 Scalar maxVelocityNorm = 0.0;
168 Scalar minVelocityNorm = 0.0;
169 for (
unsigned axisIdx = 0; axisIdx < dim; ++axisIdx)
171 maxVelocityNorm += asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx]
172 * asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx];
173 minVelocityNorm += asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx]
174 * asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx];
177 Scalar deltaU = sqrt(maxVelocityNorm) - sqrt(minVelocityNorm);
178 Scalar yFMax = storedYFMax[asImp_().wallElementIndex(elementIdx)];
179 Scalar fMax = storedFMax[asImp_().wallElementIndex(elementIdx)];
180 Scalar fWake = min(yFMax * fMax, cWake * yFMax * deltaU * deltaU / fMax);
181 Scalar fKleb = 1.0 / (1.0 + 5.5 * power(cKleb * effectiveWallDistance / yFMax, 6));
182 kinematicEddyViscosityOuter[elementIdx] = k * cCP * fWake * fKleb;
184 kinematicEddyViscosityDifference[elementIdx]
185 = kinematicEddyViscosityInner[elementIdx] - kinematicEddyViscosityOuter[elementIdx];
189 for (
const auto& element : elements(this->gridGeometry().gridView()))
191 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
192 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
195 Scalar check = kinematicEddyViscosityDifference[asImp_().wallElementIndex(elementIdx)] * kinematicEddyViscosityDifference[elementIdx];
197 && switchingPosition[asImp_().wallElementIndex(elementIdx)] > effectiveWallDistance)
199 switchingPosition[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
204 for (
const auto& element : elements(this->gridGeometry().gridView()))
206 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
207 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
209 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityInner[elementIdx];
210 if (effectiveWallDistance >= switchingPosition[asImp_().wallElementIndex(elementIdx)])
212 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityOuter[elementIdx];
219 static const std::string eddyViscosityModel = getParamFromGroup<std::string>(this->paramGroup(),
"RANS.EddyViscosityModel",
"vanDriest");
220 return eddyViscosityModel;
224 {
return additionalRoughnessLength_[elementIdx]; }
227 {
return kinematicEddyViscosity_[elementIdx]; }
231 template<
class SolutionVector>
232 void calculateRoughnessLength_(
const SolutionVector& curSol)
234 bool printedRangeWarning =
false;
235 auto fvGeometry =
localView(this->gridGeometry());
236 for (
const auto& element : elements(this->gridGeometry().gridView()))
238 static const Scalar sandGrainRoughness = getParamFromGroup<Scalar>(this->paramGroup(),
"RANS.SandGrainRoughness");
239 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
240 fvGeometry.bindElement(element);
242 for (
auto&& scv : scvs(fvGeometry))
247 const int dofIdx = scv.dofIndex();
250 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
251 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
252 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
254 VolumeVariables volVars;
255 volVars.update(elemSol, asImp_(), element, scv);
257 Scalar ksPlus = sandGrainRoughness * volVars.uStar() / volVars.kinematicViscosity();
258 if (ksPlus > 0 && eddyViscosityModel().compare(
"baldwinLomax") == 0)
260 DUNE_THROW(Dune::NotImplemented,
"Roughness is not implemented for the Baldwin-Lomax model.");
264 std::cout <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
265 <<
" is not in the valid range (ksPlus < 2000),"
266 <<
" for high ksPlus values the roughness function reaches a turning point."<< std::endl;
267 DUNE_THROW(Dune::InvalidStateException,
"Unphysical roughness behavior.");
269 else if (ksPlus > 0.0 && ksPlus < 4.535 && !printedRangeWarning)
271 Dune::dinfo <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
272 <<
" is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl;
274 printedRangeWarning =
true;
276 additionalRoughnessLength_[elementIdx] = 0.9 / (volVars.uStar() / volVars.kinematicViscosity())
277 * (sqrt(ksPlus) - ksPlus * exp(-ksPlus / 6.0));
282 std::vector<Scalar> additionalRoughnessLength_;
283 std::vector<Scalar> kinematicEddyViscosity_;
286 Implementation &asImp_()
287 {
return *
static_cast<Implementation *
>(
this); }
290 const Implementation &asImp_()
const
291 {
return *
static_cast<const Implementation *
>(
this); }
Base class for all finite-volume problems.
Definition: common/fvproblem.hh:43
Reynolds-Averaged Navier-Stokes problem base class.
Definition: freeflow/rans/problem.hh:47
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) relations to the walls.
Definition: freeflow/rans/zeroeq/problem.hh:98
RANSProblemImpl(std::shared_ptr< const GridGeometry > gridGeometry, const std::string ¶mGroup="")
The constructor.
Definition: freeflow/rans/zeroeq/problem.hh:68
void updateStaticWallProperties()
Correct size of the static (solution independent) wall variables.
Definition: freeflow/rans/zeroeq/problem.hh:75
int additionalRoughnessLength(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:223
Scalar kinematicEddyViscosity(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:226
std::string eddyViscosityModel() const
Definition: freeflow/rans/zeroeq/problem.hh:217
void updateBaldwinLomaxProperties()
Update the relations and coefficients for the Baldwin-Lomax turbulence model.
Definition: freeflow/rans/zeroeq/problem.hh:114
forward declare
Definition: freeflow/rans/problem.hh:31
Defines all properties used in Dumux.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
TurbulenceModel
The available free flow turbulence models in Dumux.
Definition: turbulencemodel.hh:26
bool hasParam(const std::string ¶m)
Check whether a key exists in the parameter tree.
Definition: parameters.hh:157
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
Free function to get the local view of a grid cache object.
The available discretization methods in Dumux.
Adaption of the fully implicit scheme to the tracer transport model.
The local element solution class for staggered methods.
Base class for all staggered fv problems.
The available free flow turbulence models in Dumux.