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); }
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: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
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.