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;
68 dim = Grid::dimension,
70 using DimVector = Dune::FieldVector<Scalar, dim>;
71 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
79 RANSProblemImpl(std::shared_ptr<const GridGeometry> gridGeometry,
const std::string& paramGroup =
"")
80 : ParentType(gridGeometry, paramGroup)
88 if (!ParentType::isFlatWallBounded())
90 DUNE_THROW(Dune::NotImplemented,
"\n Due to grid/geometric concerns, zero-eq models should only be used for flat channel geometries. "
91 <<
"\n If your geometry is a flat channel, please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
94 ParentType::updateStaticWallProperties();
97 kinematicEddyViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
98 additionalRoughnessLength_.resize(this->gridGeometry().elementMapper().size(), 0.0);
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 dimIdx = 0; dimIdx < dim; ++dimIdx)
181 maxVelocityNorm += asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[dimIdx]
182 * asImp_().velocityMaximum(asImp_().wallElementIndex(elementIdx))[dimIdx];
183 minVelocityNorm += asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[dimIdx]
184 * asImp_().velocityMinimum(asImp_().wallElementIndex(elementIdx))[dimIdx];
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 void calculateRoughnessLength_(
const SolutionVector& curSol)
243 bool printedRangeWarning =
false;
244 for (
const auto& element : elements(this->gridGeometry().gridView()))
246 static const Scalar sandGrainRoughness = getParamFromGroup<Scalar>(this->paramGroup(),
"Problem.SandGrainRoughness");
247 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
249 auto fvGeometry =
localView(this->gridGeometry());
250 fvGeometry.bindElement(element);
251 for (
auto&& scv : scvs(fvGeometry))
256 const int dofIdx = scv.dofIndex();
259 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
260 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
261 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
263 VolumeVariables volVars;
264 volVars.update(elemSol, asImp_(), element, scv);
266 Scalar ksPlus = sandGrainRoughness * volVars.uStar() / volVars.kinematicViscosity();
267 if (ksPlus > 0 && eddyViscosityModel().compare(
"baldwinLomax") == 0)
269 DUNE_THROW(Dune::NotImplemented,
"Roughness is not implemented for the Baldwin-Lomax model.");
273 std::cout <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
274 <<
" is not in the valid range (ksPlus < 2000),"
275 <<
" for high ksPlus values the roughness function reaches a turning point."<< std::endl;
276 DUNE_THROW(Dune::InvalidStateException,
"Unphysical roughness behavior.");
278 else if (ksPlus > 0.0 && ksPlus < 4.535 && !printedRangeWarning)
280 Dune::dinfo <<
"info: equivalent sand grain roughness ks+=" << ksPlus <<
" at " << asImp_().cellCenter(asImp_().wallElementIndex(elementIdx))
281 <<
" is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl;
283 printedRangeWarning =
true;
285 additionalRoughnessLength_[elementIdx] = 0.9 / (volVars.uStar() / volVars.kinematicViscosity())
286 * (sqrt(ksPlus) - ksPlus * exp(-ksPlus / 6.0));
291 std::vector<Scalar> additionalRoughnessLength_;
292 std::vector<Scalar> kinematicEddyViscosity_;
295 Implementation &asImp_()
296 {
return *
static_cast<Implementation *
>(
this); }
299 const Implementation &asImp_()
const
300 {
return *
static_cast<const Implementation *
>(
this); }
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
bool hasParam(const std::string ¶m)
Check whether a key exists in the parameter tree.
Definition: parameters.hh:366
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
forward declare
Definition: freeflow/rans/problem.hh:43
Reynolds-Averaged Navier-Stokes problem base class.
Definition: freeflow/rans/problem.hh:59
RANSProblemImpl(std::shared_ptr< const GridGeometry > gridGeometry, const std::string ¶mGroup="")
The constructor.
Definition: freeflow/rans/zeroeq/problem.hh:79
void updateStaticWallProperties()
Correct size of the static (solution independent) wall variables.
Definition: freeflow/rans/zeroeq/problem.hh:86
int additionalRoughnessLength(const int elementIdx) const
Definition: freeflow/rans/zeroeq/problem.hh:233
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) relations to the walls.
Definition: freeflow/rans/zeroeq/problem.hh:108
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
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.