12#ifndef DUMUX_ZEROEQ_PROBLEM_HH
13#define DUMUX_ZEROEQ_PROBLEM_HH
17#include <dune/common/math.hh>
37template<
class TypeTag>
43 using Grid =
typename GridView::Grid;
48 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
55 dim = Grid::dimension,
57 using DimVector = Dune::FieldVector<Scalar, dim>;
58 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
66 RANSProblemImpl(std::shared_ptr<const GridGeometry> gridGeometry,
const std::string& paramGroup =
"")
75 if (!ParentType::isFlatWallBounded())
77 DUNE_THROW(Dune::NotImplemented,
"\n Due to grid/geometric concerns, zero-eq models should only be used for flat channel geometries. "
78 <<
"\n If your geometry is a flat channel, please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
81 ParentType::updateStaticWallProperties();
84 kinematicEddyViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
85 additionalRoughnessLength_.resize(this->gridGeometry().elementMapper().size(), 0.0);
95 template<
class SolutionVector>
98 ParentType::updateDynamicWallProperties(curSol);
101 if (
hasParam(
"Problem.SandGrainRoughness"))
102 calculateRoughnessLength_(curSol);
105 if (eddyViscosityModel().compare(
"baldwinLomax") == 0)
106 updateBaldwinLomaxProperties();
114 std::vector<Scalar> kinematicEddyViscosityInner(this->gridGeometry().elementMapper().size(), 0.0);
115 std::vector<Scalar> kinematicEddyViscosityOuter(this->gridGeometry().elementMapper().size(), 0.0);
116 std::vector<Scalar> kinematicEddyViscosityDifference(this->gridGeometry().elementMapper().size(), 0.0);
117 std::vector<Scalar> switchingPosition(this->gridGeometry().elementMapper().size(), std::numeric_limits<Scalar>::max());
124 const Scalar aPlus = 26.0;
125 const Scalar k = 0.0168;
126 const Scalar cCP = 1.6;
127 const Scalar cWake = 0.25;
128 const Scalar cKleb = 0.3;
130 std::vector<Scalar> storedFMax;
131 std::vector<Scalar> storedYFMax;
132 storedFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
133 storedYFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
136 for (
const auto& element : elements(this->gridGeometry().gridView()))
138 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
139 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
140 unsigned int flowDirectionAxis = this->flowDirectionAxis(elementIdx);
141 unsigned int wallNormalAxis = this->wallNormalAxis(elementIdx);
143 Scalar omegaAbs = abs(this->velocityGradient(elementIdx, flowDirectionAxis, wallNormalAxis)
144 - this->velocityGradient(elementIdx, wallNormalAxis, flowDirectionAxis));
145 Scalar uStar = sqrt(this->kinematicViscosity(asImp_().wallElementIndex(elementIdx))
146 * abs(this->velocityGradient(asImp_().wallElementIndex(elementIdx), flowDirectionAxis, wallNormalAxis)));
147 Scalar yPlus = effectiveWallDistance * uStar / this->kinematicViscosity(elementIdx);
148 Scalar mixingLength = this->karmanConstant() * effectiveWallDistance * (1.0 - exp(-yPlus / aPlus));
149 kinematicEddyViscosityInner[elementIdx] = mixingLength * mixingLength * omegaAbs;
151 Scalar f = effectiveWallDistance * omegaAbs * (1.0 - exp(-yPlus / aPlus));
152 if (f > storedFMax[asImp_().wallElementIndex(elementIdx)])
154 storedFMax[asImp_().wallElementIndex(elementIdx)] = f;
155 storedYFMax[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
160 for (
const auto& element : elements(this->gridGeometry().gridView()))
162 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
163 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
165 Scalar maxVelocityNorm = 0.0;
166 Scalar minVelocityNorm = 0.0;
167 for (
unsigned axisIdx = 0; axisIdx < dim; ++axisIdx)
169 maxVelocityNorm += asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx]
170 * asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx];
171 minVelocityNorm += asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx]
172 * asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx];
175 Scalar deltaU = sqrt(maxVelocityNorm) - sqrt(minVelocityNorm);
176 Scalar yFMax = storedYFMax[asImp_().wallElementIndex(elementIdx)];
177 Scalar fMax = storedFMax[asImp_().wallElementIndex(elementIdx)];
178 Scalar fWake = min(yFMax * fMax, cWake * yFMax * deltaU * deltaU / fMax);
179 Scalar fKleb = 1.0 / (1.0 + 5.5 * power(cKleb * effectiveWallDistance / yFMax, 6));
180 kinematicEddyViscosityOuter[elementIdx] = k * cCP * fWake * fKleb;
182 kinematicEddyViscosityDifference[elementIdx]
183 = kinematicEddyViscosityInner[elementIdx] - kinematicEddyViscosityOuter[elementIdx];
187 for (
const auto& element : elements(this->gridGeometry().gridView()))
189 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
190 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
193 Scalar check = kinematicEddyViscosityDifference[asImp_().wallElementIndex(elementIdx)] * kinematicEddyViscosityDifference[elementIdx];
195 && switchingPosition[asImp_().wallElementIndex(elementIdx)] > effectiveWallDistance)
197 switchingPosition[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
202 for (
const auto& element : elements(this->gridGeometry().gridView()))
204 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
205 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
207 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityInner[elementIdx];
208 if (effectiveWallDistance >= switchingPosition[asImp_().wallElementIndex(elementIdx)])
210 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityOuter[elementIdx];
217 static const std::string eddyViscosityModel = getParamFromGroup<std::string>(this->paramGroup(),
"RANS.EddyViscosityModel",
"vanDriest");
218 return eddyViscosityModel;
222 {
return additionalRoughnessLength_[elementIdx]; }
225 {
return kinematicEddyViscosity_[elementIdx]; }
229 template<
class SolutionVector>
230 void calculateRoughnessLength_(
const SolutionVector& curSol)
232 bool printedRangeWarning =
false;
233 auto fvGeometry =
localView(this->gridGeometry());
234 for (
const auto& element : elements(this->gridGeometry().gridView()))
236 static const Scalar sandGrainRoughness = getParamFromGroup<Scalar>(this->paramGroup(),
"Problem.SandGrainRoughness");
237 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
238 fvGeometry.bindElement(element);
240 for (
auto&& scv : scvs(fvGeometry))
245 const int dofIdx = scv.dofIndex();
248 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
249 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
250 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
252 VolumeVariables volVars;
253 volVars.update(elemSol, asImp_(), element, scv);
255 Scalar ksPlus = sandGrainRoughness * volVars.uStar() / volVars.kinematicViscosity();
256 if (ksPlus > 0 && eddyViscosityModel().compare(
"baldwinLomax") == 0)
258 DUNE_THROW(Dune::NotImplemented,
"Roughness is not implemented for the Baldwin-Lomax model.");
262 std::cout <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
263 <<
" is not in the valid range (ksPlus < 2000),"
264 <<
" for high ksPlus values the roughness function reaches a turning point."<< std::endl;
265 DUNE_THROW(Dune::InvalidStateException,
"Unphysical roughness behavior.");
267 else if (ksPlus > 0.0 && ksPlus < 4.535 && !printedRangeWarning)
269 Dune::dinfo <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
270 <<
" is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl;
272 printedRangeWarning =
true;
274 additionalRoughnessLength_[elementIdx] = 0.9 / (volVars.uStar() / volVars.kinematicViscosity())
275 * (sqrt(ksPlus) - ksPlus * exp(-ksPlus / 6.0));
280 std::vector<Scalar> additionalRoughnessLength_;
281 std::vector<Scalar> kinematicEddyViscosity_;
284 Implementation &asImp_()
285 {
return *
static_cast<Implementation *
>(
this); }
288 const Implementation &asImp_()
const
289 {
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:96
RANSProblemImpl(std::shared_ptr< const GridGeometry > gridGeometry, const std::string ¶mGroup="")
The constructor.
Definition: freeflow/rans/zeroeq/problem.hh:66
void updateStaticWallProperties()
Correct size of the static (solution independent) wall variables.
Definition: freeflow/rans/zeroeq/problem.hh:73
int additionalRoughnessLength(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:221
Scalar kinematicEddyViscosity(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:224
std::string eddyViscosityModel() const
Definition: freeflow/rans/zeroeq/problem.hh:215
void updateBaldwinLomaxProperties()
Update the relations and coefficients for the Baldwin-Lomax turbulence model.
Definition: freeflow/rans/zeroeq/problem.hh:112
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
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:267
Free function to get the local view of a grid cache object.
The available discretization methods in Dumux.
bool hasParam(const std::string ¶m)
Check whether a key exists in the parameter tree.
Definition: parameters.hh:157
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.