24#ifndef DUMUX_ZEROEQ_PROBLEM_HH
25#define DUMUX_ZEROEQ_PROBLEM_HH
29#include <dune/common/math.hh>
49template<
class TypeTag>
55 using Grid =
typename GridView::Grid;
60 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
67 dim = Grid::dimension,
69 using DimVector = Dune::FieldVector<Scalar, dim>;
70 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
78 RANSProblemImpl(std::shared_ptr<const GridGeometry> gridGeometry,
const std::string& paramGroup =
"")
87 if (!ParentType::isFlatWallBounded())
89 DUNE_THROW(Dune::NotImplemented,
"\n Due to grid/geometric concerns, zero-eq models should only be used for flat channel geometries. "
90 <<
"\n If your geometry is a flat channel, please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
93 ParentType::updateStaticWallProperties();
96 kinematicEddyViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
97 additionalRoughnessLength_.resize(this->gridGeometry().elementMapper().size(), 0.0);
107 template<
class SolutionVector>
110 ParentType::updateDynamicWallProperties(curSol);
113 if (
hasParam(
"Problem.SandGrainRoughness"))
114 calculateRoughnessLength_(curSol);
117 if (eddyViscosityModel().compare(
"baldwinLomax") == 0)
118 updateBaldwinLomaxProperties();
126 std::vector<Scalar> kinematicEddyViscosityInner(this->gridGeometry().elementMapper().size(), 0.0);
127 std::vector<Scalar> kinematicEddyViscosityOuter(this->gridGeometry().elementMapper().size(), 0.0);
128 std::vector<Scalar> kinematicEddyViscosityDifference(this->gridGeometry().elementMapper().size(), 0.0);
129 std::vector<Scalar> switchingPosition(this->gridGeometry().elementMapper().size(), std::numeric_limits<Scalar>::max());
136 const Scalar aPlus = 26.0;
137 const Scalar k = 0.0168;
138 const Scalar cCP = 1.6;
139 const Scalar cWake = 0.25;
140 const Scalar cKleb = 0.3;
142 std::vector<Scalar> storedFMax;
143 std::vector<Scalar> storedYFMax;
144 storedFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
145 storedYFMax.resize(this->gridGeometry().elementMapper().size(), 0.0);
148 for (
const auto& element : elements(this->gridGeometry().gridView()))
150 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
151 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
152 unsigned int flowDirectionAxis = this->flowDirectionAxis(elementIdx);
153 unsigned int wallNormalAxis = this->wallNormalAxis(elementIdx);
155 Scalar omegaAbs = abs(this->velocityGradient(elementIdx, flowDirectionAxis, wallNormalAxis)
156 - this->velocityGradient(elementIdx, wallNormalAxis, flowDirectionAxis));
157 Scalar uStar = sqrt(this->kinematicViscosity(asImp_().wallElementIndex(elementIdx))
158 * abs(this->velocityGradient(asImp_().wallElementIndex(elementIdx), flowDirectionAxis, wallNormalAxis)));
159 Scalar yPlus = effectiveWallDistance * uStar / this->kinematicViscosity(elementIdx);
160 Scalar mixingLength = this->karmanConstant() * effectiveWallDistance * (1.0 - exp(-yPlus / aPlus));
161 kinematicEddyViscosityInner[elementIdx] = mixingLength * mixingLength * omegaAbs;
163 Scalar f = effectiveWallDistance * omegaAbs * (1.0 - exp(-yPlus / aPlus));
164 if (f > storedFMax[asImp_().wallElementIndex(elementIdx)])
166 storedFMax[asImp_().wallElementIndex(elementIdx)] = f;
167 storedYFMax[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
172 for (
const auto& element : elements(this->gridGeometry().gridView()))
174 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
175 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
177 Scalar maxVelocityNorm = 0.0;
178 Scalar minVelocityNorm = 0.0;
179 for (
unsigned axisIdx = 0; axisIdx < dim; ++axisIdx)
181 maxVelocityNorm += asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx]
182 * asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[axisIdx];
183 minVelocityNorm += asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx]
184 * asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[axisIdx];
187 Scalar deltaU = sqrt(maxVelocityNorm) - sqrt(minVelocityNorm);
188 Scalar yFMax = storedYFMax[asImp_().wallElementIndex(elementIdx)];
189 Scalar fMax = storedFMax[asImp_().wallElementIndex(elementIdx)];
190 Scalar fWake = min(yFMax * fMax, cWake * yFMax * deltaU * deltaU / fMax);
191 Scalar fKleb = 1.0 / (1.0 + 5.5 * power(cKleb * effectiveWallDistance / yFMax, 6));
192 kinematicEddyViscosityOuter[elementIdx] = k * cCP * fWake * fKleb;
194 kinematicEddyViscosityDifference[elementIdx]
195 = kinematicEddyViscosityInner[elementIdx] - kinematicEddyViscosityOuter[elementIdx];
199 for (
const auto& element : elements(this->gridGeometry().gridView()))
201 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
202 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
205 Scalar check = kinematicEddyViscosityDifference[asImp_().wallElementIndex(elementIdx)] * kinematicEddyViscosityDifference[elementIdx];
207 && switchingPosition[asImp_().wallElementIndex(elementIdx)] > effectiveWallDistance)
209 switchingPosition[asImp_().wallElementIndex(elementIdx)] = effectiveWallDistance;
214 for (
const auto& element : elements(this->gridGeometry().gridView()))
216 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
217 Scalar effectiveWallDistance = asImp_().wallDistance(elementIdx) + additionalRoughnessLength(elementIdx);
219 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityInner[elementIdx];
220 if (effectiveWallDistance >= switchingPosition[asImp_().wallElementIndex(elementIdx)])
222 kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityOuter[elementIdx];
229 static const std::string eddyViscosityModel = getParamFromGroup<std::string>(this->paramGroup(),
"RANS.EddyViscosityModel",
"vanDriest");
230 return eddyViscosityModel;
234 {
return additionalRoughnessLength_[elementIdx]; }
237 {
return kinematicEddyViscosity_[elementIdx]; }
241 template<
class SolutionVector>
242 void calculateRoughnessLength_(
const SolutionVector& curSol)
244 bool printedRangeWarning =
false;
245 auto fvGeometry =
localView(this->gridGeometry());
246 for (
const auto& element : elements(this->gridGeometry().gridView()))
248 static const Scalar sandGrainRoughness = getParamFromGroup<Scalar>(this->paramGroup(),
"Problem.SandGrainRoughness");
249 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
250 fvGeometry.bindElement(element);
252 for (
auto&& scv : scvs(fvGeometry))
257 const int dofIdx = scv.dofIndex();
260 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
261 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
262 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
264 VolumeVariables volVars;
265 volVars.update(elemSol, asImp_(), element, scv);
267 Scalar ksPlus = sandGrainRoughness * volVars.uStar() / volVars.kinematicViscosity();
268 if (ksPlus > 0 && eddyViscosityModel().compare(
"baldwinLomax") == 0)
270 DUNE_THROW(Dune::NotImplemented,
"Roughness is not implemented for the Baldwin-Lomax model.");
274 std::cout <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
275 <<
" is not in the valid range (ksPlus < 2000),"
276 <<
" for high ksPlus values the roughness function reaches a turning point."<< std::endl;
277 DUNE_THROW(Dune::InvalidStateException,
"Unphysical roughness behavior.");
279 else if (ksPlus > 0.0 && ksPlus < 4.535 && !printedRangeWarning)
281 Dune::dinfo <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
282 <<
" is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl;
284 printedRangeWarning =
true;
286 additionalRoughnessLength_[elementIdx] = 0.9 / (volVars.uStar() / volVars.kinematicViscosity())
287 * (sqrt(ksPlus) - ksPlus * exp(-ksPlus / 6.0));
292 std::vector<Scalar> additionalRoughnessLength_;
293 std::vector<Scalar> kinematicEddyViscosity_;
296 Implementation &asImp_()
297 {
return *
static_cast<Implementation *
>(
this); }
300 const Implementation &asImp_()
const
301 {
return *
static_cast<const Implementation *
>(
this); }
Base class for all staggered fv problems.
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.
TurbulenceModel
The available free flow turbulence models in Dumux.
Definition: turbulencemodel.hh:38
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
bool hasParam(const std::string ¶m)
Check whether a key exists in the parameter tree.
Definition: parameters.hh:169
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:180
Base class for all finite-volume problems.
Definition: common/fvproblem.hh:55
forward declare
Definition: freeflow/rans/problem.hh:43
Reynolds-Averaged Navier-Stokes problem base class.
Definition: freeflow/rans/problem.hh:59
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) relations to the walls.
Definition: freeflow/rans/zeroeq/problem.hh:108
RANSProblemImpl(std::shared_ptr< const GridGeometry > gridGeometry, const std::string ¶mGroup="")
The constructor.
Definition: freeflow/rans/zeroeq/problem.hh:78
void updateStaticWallProperties()
Correct size of the static (solution independent) wall variables.
Definition: freeflow/rans/zeroeq/problem.hh:85
int additionalRoughnessLength(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:233
Scalar kinematicEddyViscosity(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:236
std::string eddyViscosityModel() const
Definition: freeflow/rans/zeroeq/problem.hh:227
void updateBaldwinLomaxProperties()
Update the relations and coefficients for the Baldwin-Lomax turbulence model.
Definition: freeflow/rans/zeroeq/problem.hh:124
Declares all properties used in Dumux.
Adaption of the fully implicit scheme to the tracer transport model.
The local element solution class for staggered methods.