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>;
 
   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");
 
   86        kinematicEddyViscosity_.resize(this->
gridGeometry().elementMapper().size(), 0.0);
 
   87        additionalRoughnessLength_.resize(this->
gridGeometry().elementMapper().size(), 0.0);
 
 
   97    template<
class SolutionVector>
 
  103        if (
hasParam(
"RANS.SandGrainRoughness"))
 
  104            calculateRoughnessLength_(curSol);
 
 
  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);
 
  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));
 
  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);
 
  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]
 
  173                minVelocityNorm += 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);
 
  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);
 
  209            kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityInner[elementIdx];
 
  210            if (effectiveWallDistance >= switchingPosition[asImp_().
wallElementIndex(elementIdx)])
 
  212                kinematicEddyViscosity_[elementIdx] = kinematicEddyViscosityOuter[elementIdx];
 
 
  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()))
 
  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];
 
  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); }
 
 
const std::string & paramGroup() const
The parameter group in which to retrieve runtime parameters.
Definition common/fvproblem.hh:524
const GridGeometry & gridGeometry() const
The finite volume grid geometry.
Definition common/fvproblem.hh:520
unsigned int wallElementIndex(const int elementIdx) const
Definition freeflow/rans/problem.hh:242
int flowDirectionAxis(const int elementIdx) const
Definition freeflow/rans/problem.hh:232
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) turbulence parameters.
Definition freeflow/rans/problem.hh:131
void updateStaticWallProperties()
Update the static (solution independent) relations to the walls and neighbors.
Definition freeflow/rans/problem.hh:115
Scalar velocityGradient(const int elementIdx, const int i, const int j) const
Definition freeflow/rans/problem.hh:280
Scalar kinematicViscosity(const int elementIdx) const
Definition freeflow/rans/problem.hh:295
int wallNormalAxis(const int elementIdx) const
Definition freeflow/rans/problem.hh:222
RANSProblemBase(std::shared_ptr< const GridGeometry > gridGeometry, const std::string ¶mGroup="")
The constructor.
Definition freeflow/rans/problem.hh:90
bool isFlatWallBounded() const
Returns whether a given sub control volume face is on a wall.
Definition freeflow/rans/problem.hh:184
const Scalar karmanConstant() const
Returns the Karman constant.
Definition freeflow/rans/problem.hh:193
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
Defines all properties used in Dumux.
the turbulence-model-specfic RANS problem
A single-phase, isothermal Reynolds-Averaged Navier-Stokes 0-Eq. model.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition cellcentered/elementsolution.hh:101
TurbulenceModel
The available free flow turbulence models in Dumux.
Definition turbulencemodel.hh:26
@ zeroeq
Definition turbulencemodel.hh:27
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:149
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
PrimaryVariables makePriVarsFromCellCenterPriVars(const CellCenterPrimaryVariables &cellCenterPriVars)
Helper function to create a PrimaryVariables object from CellCenterPrimaryVariables.
Definition staggered/elementsolution.hh:29
Free function to get the local view of a grid cache object.
The available discretization methods in Dumux.
The local element solution class for staggered methods.
Base class for all staggered fv problems.
The available free flow turbulence models in Dumux.