diff --git a/dumux/freeflow/stokes/fluxvariables.hh b/dumux/freeflow/stokes/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..6f9fe31b517a6ae41c54ca155c1584b1d00cae7c --- /dev/null +++ b/dumux/freeflow/stokes/fluxvariables.hh @@ -0,0 +1,287 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * the fluxes of the Stokes model over a face of a finite volume. + * + * This means pressure gradients, phase densities at the integration point, etc. + */ +#ifndef DUMUX_STOKES_FLUX_VARIABLES_HH +#define DUMUX_STOKES_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/common/valgrind.hh> + +#include "properties.hh" + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains the data which is required to + * calculate the mass and momentum fluxes over the face of a + * sub-control volume for the Stokes model. + * + * This means pressure gradients, phase densities, viscosities, etc. + * at the integration point of the sub-control-volume face. + */ +template <class TypeTag> +class StokesFluxVariables +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + + enum { dim = GridView::dimension }; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; + +public: + //! \brief The constructor + StokesFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : fvGeometry_(fvGeometry), onBoundary_(onBoundary), fIdx_(fIdx) + { + calculateValues_(problem, element, elemVolVars); + determineUpwindDirection_(elemVolVars); + } + +protected: + void calculateValues_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + // calculate gradients and secondary variables at IPs + DimVector tmp(0.0); + + density_ = Scalar(0); + dynamicViscosity_ = Scalar(0); + pressure_ = Scalar(0); + normalvelocity_ = Scalar(0); + velocity_ = Scalar(0); + pressureGrad_ = Scalar(0); + velocityGrad_ = Scalar(0); + + for (int scvIdx = 0; + scvIdx < fvGeometry_.numScv; + scvIdx++) // loop over adjacent vertices + { + // phase density and viscosity at IP + density_ += elemVolVars[scvIdx].density() * + face().shapeValue[scvIdx]; + dynamicViscosity_ += elemVolVars[scvIdx].dynamicViscosity() * + face().shapeValue[scvIdx]; + pressure_ += elemVolVars[scvIdx].pressure() * + face().shapeValue[scvIdx]; + + // velocity at the IP (fluxes) + DimVector velocityTimesShapeValue = elemVolVars[scvIdx].velocity(); + velocityTimesShapeValue *= face().shapeValue[scvIdx]; + velocity_ += velocityTimesShapeValue; + + // the pressure gradient + tmp = face().grad[scvIdx]; + tmp *= elemVolVars[scvIdx].pressure(); + pressureGrad_ += tmp; + // take gravity into account + tmp = problem.gravity(); + tmp *= density_; + // pressure gradient including influence of gravity + pressureGrad_ -= tmp; + + // the velocity gradients and divergence + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + { + tmp = face().grad[scvIdx]; + tmp *= elemVolVars[scvIdx].velocity()[dimIdx]; + velocityGrad_[dimIdx] += tmp; + } + } + + normalvelocity_ = velocity_ * face().normal; + + Valgrind::CheckDefined(density_); + Valgrind::CheckDefined(dynamicViscosity_); + Valgrind::CheckDefined(normalvelocity_); + Valgrind::CheckDefined(velocity_); + Valgrind::CheckDefined(pressureGrad_); + Valgrind::CheckDefined(velocityGrad_); + } + + void determineUpwindDirection_(const ElementVolumeVariables &elemVolVars) + { + + // set the upstream and downstream vertices + upstreamIdx_ = face().i; + downstreamIdx_ = face().j; + + if (normalVelocity() < 0) + std::swap(upstreamIdx_, downstreamIdx_); + } + +public: + /*! + * \brief The face of the current sub-control volume. This may be either + * an inner sub-control-volume face or a face on the boundary. + */ + const SCVFace &face() const + { + if (onBoundary_) + return fvGeometry_.boundaryFace[fIdx_]; + else + return fvGeometry_.subContVolFace[fIdx_]; + } + + /*! + * \brief Return the average volume of the upstream and the downstream sub-control volume; + * this is required for the stabilization. + */ + const Scalar averageSCVVolume() const + { + return 0.5*(fvGeometry_.subContVol[upstreamIdx_].volume + + fvGeometry_.subContVol[downstreamIdx_].volume); + } + + /*! + * \brief Return the pressure \f$\mathrm{[Pa]}\f$ at the integration + * point. + */ + Scalar pressure() const + { return pressure_; } + + /*! + * \brief Return the mass density \f$ \mathrm{[kg/m^3]} \f$ at the integration + * point. + */ + Scalar density() const + { return density_; } + + /*! + * \brief Return the dynamic viscosity \f$ \mathrm{[Pa\cdot s]} \f$ at the integration + * point. + */ + Scalar dynamicViscosity() const + { return dynamicViscosity_; } + + /*! + * \brief Returns the kinematic viscosity \f$ \frac{m^2}{s} \f$ of the fluid in + * the sub-control volume. + */ + Scalar kinematicViscosity() const + { return dynamicViscosity_ / density_; } + + /*! + * \brief Return the velocity \f$ \mathrm{[m/s]} \f$ at the integration + * point multiplied by the normal and the area. + */ + Scalar normalVelocity() const + { return normalvelocity_; } + + /*! + * \brief Return the pressure gradient at the integration point. + */ + const DimVector &pressureGrad() const + { return pressureGrad_; } + + /*! + * \brief Return the velocity vector at the integration point. + */ + const DimVector &velocity() const + { return velocity_; } + + /*! + * \brief Return the velocity gradient at the integration + * point of a face. + */ + const DimMatrix &velocityGrad() const + { return velocityGrad_; } + + /*! + * \brief Return the dynamic eddy viscosity + * \f$\mathrm{[Pa \cdot s]} = \mathrm{[N \cdot s/m^2]}\f$ (if implemented). + */ + const Scalar dynamicEddyViscosity() const + { return kinematicEddyViscosity() * density(); } + + /*! + * \brief Return the kinematic eddy viscosity + * \f$\mathrm{[m^2/s]}\f$ (if implemented). + */ + const Scalar kinematicEddyViscosity() const + { return 0; } + + /*! + * \brief Return the local index of the upstream sub-control volume. + */ + int upstreamIdx() const + { return upstreamIdx_; } + + /*! + * \brief Return the local index of the downstream sub-control volume. + */ + int downstreamIdx() const + { return downstreamIdx_; } + + /*! + * \brief Indicates if a face is on a boundary. Used for in the + * face() method (e.g. for outflow boundary conditions). + */ + bool onBoundary() const + { return onBoundary_; } + +protected: + const FVElementGeometry &fvGeometry_; + const bool onBoundary_; + + // values at the integration point + Scalar density_; + Scalar dynamicViscosity_; + Scalar pressure_; + Scalar normalvelocity_; + DimVector velocity_; + + // gradients at the IPs + DimVector pressureGrad_; + DimMatrix velocityGrad_; + + // local index of the upwind vertex + int upstreamIdx_; + // local index of the downwind vertex + int downstreamIdx_; + // the index of the considered face + int fIdx_; +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/stokes/indices.hh b/dumux/freeflow/stokes/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..6d9655c844a25f8bdd77f02dd82f5a0da1cf3215 --- /dev/null +++ b/dumux/freeflow/stokes/indices.hh @@ -0,0 +1,69 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * \brief Defines the indices required for the Stokes box model. + */ +#ifndef DUMUX_STOKES_INDICES_HH +#define DUMUX_STOKES_INDICES_HH + +#include "properties.hh" + +namespace Dumux +{ +// \{ + +/*! + * \ingroup BoxStokesModel + * \ingroup ImplicitIndices + * \brief The common indices for the isothermal stokes model. + * + * \tparam PVOffset The first index in a primary variable vector. + */ +template <class TypeTag, int PVOffset = 0> +struct StokesCommonIndices +{ + // number of dimensions + typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + static const int dim = Grid::dimension; + + // Primary variable indices + static const int momentumXIdx = PVOffset + 0; //!< Index of the x-component of the momentum equation + static const int momentumYIdx = PVOffset + 1; //!< Index of the y-component of the momentum equation + static const int momentumZIdx = PVOffset + 2; //!< Index of the z-component of the momentum equation + static const int lastMomentumIdx = momentumXIdx+dim-1; //!< Index of the last component of the momentum equation + + static const int dimXIdx = 0; //!< Index of the x-component of a vector of size dim + static const int dimYIdx = 1; //!< Index of the y-component of a vector of size dim + static const int dimZIdx = 2; //!< Index of the z-component of a vector of size dim + + static const int massBalanceIdx = dim; //!< Index of the mass balance equation + static const int conti0EqIdx = massBalanceIdx; //!< Index of first (for C-guys: 0th) mass conservation equation + + static const int pressureIdx = massBalanceIdx; //!< Index of the pressure in a solution vector + static const int velocityXIdx = momentumXIdx; //!< Index of the x-component of the velocity + static const int velocityYIdx = momentumYIdx; //!< Index of the y-component of the velocity + static const int velocityZIdx = momentumZIdx; //!< Index of the z-component of the velocity + + static const int phaseIdx = 0; //!< Index of the fluid phase (required to use the same fluid system in coupled models) +}; +} // end namespace + +#endif diff --git a/dumux/freeflow/stokes/localjacobian.hh b/dumux/freeflow/stokes/localjacobian.hh new file mode 100644 index 0000000000000000000000000000000000000000..5e4119fca880169dd486623f1c0e3c47f8f1dc1d --- /dev/null +++ b/dumux/freeflow/stokes/localjacobian.hh @@ -0,0 +1,60 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Element-wise calculation of the Jacobian matrix for the Stokes models. + */ +#ifndef DUMUX_STOKES_LOCAL_JACOBIAN_HH +#define DUMUX_STOKES_LOCAL_JACOBIAN_HH + +#include <dune/istl/matrix.hh> +#include "properties.hh" +#include <dumux/implicit/localjacobian.hh> + +namespace Dumux +{ +/*! + * \ingroup BoxStokesModel + * \ingroup ImplicitLocalJacobian + * \brief Element-wise calculation of the Jacobian matrix for the Stokes models. + * + * This overloads the numericEpsilon method of the ImplicitLocalJacobian. + * The momentum balance equation uses larger epsilons than the rest. + */ +template<class TypeTag> +class StokesLocalJacobian : public ImplicitLocalJacobian<TypeTag> +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + +public: + //! \copydoc ImplicitLocalJacobian::numericEpsilon() + Scalar numericEpsilon(const int scvIdx, + const int pvIdx) const + { + Scalar pv = this->curVolVars_[scvIdx].priVars()[pvIdx]; + if (pvIdx < GridView::dimension){ + return 1e-7*(std::abs(pv) + 1); + } + return 1e-9*(std::abs(pv) + 1); + } +}; +} + +#endif diff --git a/dumux/freeflow/stokes/localresidual.hh b/dumux/freeflow/stokes/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..e09ae9bb4719f558a1453adcd13366ab8126f414 --- /dev/null +++ b/dumux/freeflow/stokes/localresidual.hh @@ -0,0 +1,707 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Element-wise calculation of the Jacobian matrix for problems + * using the Stokes box model. + */ + +#ifndef DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH +#define DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH + +#include <dune/common/float_cmp.hh> +#include <dune/grid/common/grid.hh> + +#include <dumux/implicit/model.hh> +#include "properties.hh" +#include "volumevariables.hh" +#include "fluxvariables.hh" + +namespace Dumux +{ +/*! + * \ingroup BoxStokesModel + * \ingroup ImplicitLocalResidual + * \brief Element-wise calculation of the local Jacobian matrix for problems + * using the Stokes box model. + * + * This class is also used for the non-isothermal and the two-component Stokes + * model (static polymorphism). + */ +template<class TypeTag> +class StokesLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) +{ +protected: + typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; + typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + enum { + dim = GridView::dimension, + numEq = GET_PROP_VALUE(TypeTag, NumEq) + }; + enum { + massBalanceIdx = Indices::massBalanceIdx, //!< Index of the mass balance + momentumXIdx = Indices::momentumXIdx, //!< Index of the x-component of the momentum balance + lastMomentumIdx = Indices::lastMomentumIdx //!< Index of the last component of the momentum balance + }; + enum { pressureIdx = Indices::pressureIdx }; //!< Index of the pressure in a solution vector + + typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements; + typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement; + + typedef Dune::FieldVector<Scalar, dim> DimVector; + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; + + static const bool enableUnsymmetrizedVelocityGradient = GET_PROP_VALUE(TypeTag, EnableUnsymmetrizedVelocityGradient); + static const bool calculateNavierStokes = GET_PROP_VALUE(TypeTag, EnableNavierStokes); + static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + + public: + /*! + * \brief Constructor. Sets the upwind weight and the stabilization parameters. + */ + StokesLocalResidual() + { + // retrieve the upwind weight for the mass conservation equations. Use the value + // specified via the property system as default, and overwrite + // it by the run-time parameter from the Dune::ParameterTree + massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); + stabilizationAlpha_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Stokes, StabilizationAlpha); + stabilizationBeta_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Stokes, StabilizationBeta); + } + + /*! + * \brief Evaluates the amount of all conservation quantities + * (mass and momentum) within a sub-control volume. + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param scvIdx The SCV (sub-control-volume) index + * \param usePrevSol Evaluate function with solution of current or previous time step + */ + void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const + { + // if flag usePrevSol is set, the solution from the previous + // time step is used, otherwise the current solution is + // used. The secondary variables are used accordingly. This + // is required to compute the derivative of the storage term + // using the implicit Euler method. + const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() + : this->curVolVars_(); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + storage = 0.0; + + if(useMoles) + // mass balance mole fraction based + storage[massBalanceIdx] = volVars.molarDensity(); + else + // mass balance mass fraction based + storage[massBalanceIdx] = volVars.density(); + + // momentum balance + for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; ++momentumIdx) + storage[momentumIdx] = volVars.density() + * volVars.velocity()[momentumIdx-momentumXIdx]; + } + + /*! + * \brief Evaluates the total flux of all conservation quantities + * over a face of a sub-control volume. The face may be within + * an element (SCV face) or on the boundary. The advective and + * the diffusive fluxes are computed. + * + * \param flux The flux over the SCV (sub-control-volume) face + * \param fIdx The index of the SCV face (may also be a boundary face) + * \param onBoundary Indicates, if the flux is evaluated on a boundary face. If it is true, + * the created fluxVars object contains boundary variables evaluated at the IP of the + * boundary face + */ + void computeFlux(PrimaryVariables &flux, const int fIdx, const bool onBoundary=false) const + { + const FluxVariables fluxVars(this->problem_(), + this->element_(), + this->fvGeometry_(), + fIdx, + this->curVolVars_(), + onBoundary); + flux = 0.0; + + asImp_()->computeAdvectiveFlux(flux, fluxVars); + Valgrind::CheckDefined(flux); + asImp_()->computeDiffusiveFlux(flux, fluxVars); + Valgrind::CheckDefined(flux); + } + + /*! + * \brief Evaluates the advective fluxes over + * a face of a sub-control volume. + * + * \param flux The advective flux over the sub-control-volume face for each component + * \param fluxVars The flux variables at the current SCV/boundary face + */ + void computeAdvectiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // if the momentum balance has a dirichlet b.c., the mass balance + // is replaced, thus we do not need to calculate outflow fluxes here + if (fluxVars.onBoundary() && + momentumBalanceDirichlet_(this->bcTypes_(fluxVars.upstreamIdx()))) + { + return; + } + + // data attached to upstream and the downstream vertices + const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); + const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); + + DimVector massBalanceResidual = fluxVars.velocity(); + + if(useMoles) + { + massBalanceResidual *= (massUpwindWeight_ * up.molarDensity() + + (1.-massUpwindWeight_) * dn.molarDensity()); + } + else + { + massBalanceResidual *= (massUpwindWeight_ * up.density() + + (1.-massUpwindWeight_) * dn.density()); + } + + if (!fluxVars.onBoundary()) + { + // stabilization of the mass balance + // with 0.5*alpha*(V_i + V_j)*grad P + DimVector stabilizationTerm = fluxVars.pressureGrad(); + stabilizationTerm *= stabilizationAlpha_* + fluxVars.averageSCVVolume(); + massBalanceResidual += stabilizationTerm; + } + + flux[massBalanceIdx] += + massBalanceResidual*fluxVars.face().normal; + + // momentum balance - pressure is evaluated as volume term + // at the center of the SCV in computeSource + // dynamic viscosity is upwinded + + Dune::FieldMatrix<Scalar, dim, dim> velGrad = fluxVars.velocityGrad(); + if (enableUnsymmetrizedVelocityGradient) + { + // nothing has to be done in this case: + // grad v + } + else + { + // compute symmetrized gradient for the momentum flux: + // grad v + (grad v)^T + for (int i=0; i<dim; ++i) + for (int j=0; j<dim; ++j) + velGrad[i][j] += fluxVars.velocityGrad()[j][i]; + } + + DimVector velGradComp(0.); + for (int velIdx = 0; velIdx < dim; ++velIdx) + { + velGradComp = velGrad[velIdx]; + + // TODO: dilatation term has to be accounted for in outflow, coupling, neumann + // velGradComp[velIdx] += 2./3*fluxVars.velocityDiv; + + velGradComp *= fluxVars.dynamicViscosity() + fluxVars.dynamicEddyViscosity(); + + flux[momentumXIdx + velIdx] -= + velGradComp*fluxVars.face().normal; + + // gravity is accounted for in computeSource; alternatively: + // Scalar gravityTerm = fluxVars.density * + // this->problem_().gravity()[dim-1] * + // fluxVars.face().ipGlobal[dim-1]* + // fluxVars.face().normal[velIdx]; + // flux[momentumXIdx + velIdx] -= + // gravityTerm; + + } + + // this term changes the Stokes equation to the Navier-Stokes equation + // rho v (v*n) + // rho and first v are upwinded, second v is evaluated at the face + if (calculateNavierStokes) + { + for (int dimIndex = 0; dimIndex < dim; ++dimIndex) + flux[momentumXIdx + dimIndex] += + up.density() * up.velocity()[dimIndex] * fluxVars.normalVelocity(); + } + } + + /*! + * \brief Adds the diffusive flux to the flux vector over + * a SCV face or a boundary face. + * + * It doesn't do anything in the Stokes model but is used by the + * transport and non-isothermal models to calculate diffusive and + * conductive fluxes. + * + * \param flux The diffusive flux over the SCV face or boundary face for each component + * \param fluxVars The flux variables at the current SCV/boundary face + */ + void computeDiffusiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { } + + /*! + * \brief Calculate the source term of all equations. + * The pressure gradient at the center of a SCV is computed + * and the gravity term evaluated. + * + * \param source The source/sink in the sub control volume for each component + * \param scvIdx The local index of the sub-control volume + */ + void computeSource(PrimaryVariables &source, const int scvIdx) + { + const ElementVolumeVariables &elemVolVars = this->curVolVars_(); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + // retrieve the source term intrinsic to the problem + this->problem_().solDependentSource(source, + this->element_(), + this->fvGeometry_(), + scvIdx, + this->curVolVars_()); + + // ATTENTION: The source term of the mass balance has to be chosen as + // div (q_momentum) in the problem file + const Scalar alphaH2 = stabilizationAlpha_* + this->fvGeometry_().subContVol[scvIdx].volume; + source[massBalanceIdx] *= alphaH2; // stabilization of the source term + + // pressure gradient at the center of the SCV, + // the pressure is discretized as volume term, + // while -mu grad v is calculated in computeFlux + DimVector pressureGradAtSCVCenter(0.0); + DimVector grad(0.0); + + for (int scvIdx2 = 0; scvIdx2 < this->fvGeometry_().numScv; scvIdx2++) + { + grad = this->fvGeometry_().subContVol[scvIdx].gradCenter[scvIdx2]; + Valgrind::CheckDefined(grad); + grad *= elemVolVars[scvIdx2].pressure(); + + pressureGradAtSCVCenter += grad; + } + + // add the component of the pressure gradient to the respective part + // of the momentum equation and take the gravity term into account + // signs are inverted, since q is subtracted + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + { + source[momentumXIdx + dimIdx] -= pressureGradAtSCVCenter[dimIdx]; + source[momentumXIdx + dimIdx] += volVars.density()*this->problem_().gravity()[dimIdx]; + } + } + + /*! + * \brief The Stokes model needs a modified treatment of the boundary conditions as + * the common box models + */ + void evalBoundary_() + { + assert(this->residual_.size() == this->fvGeometry_().numScv); + const ReferenceElement &refElement = ReferenceElements::general(this->element_().geometry().type()); + + // loop over sub-control volums of the element + for (int scvIdx = 0; scvIdx < this->fvGeometry_().numScv; scvIdx++) + { + // consider only SCVs on the boundary + if (this->fvGeometry_().subContVol[scvIdx].inner) + continue; + + // important at corners of the grid + DimVector momentumResidual(0.0); + DimVector averagedNormal(0.0); + int numberOfOuterFaces = 0; + // evaluate boundary conditions for the intersections of + // the current element + const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); + for (const auto& intersection : Dune::intersections(this->gridView_(), this->element_())) + { + // handle only intersections on the boundary + if (!intersection.boundary()) + continue; + + // assemble the boundary for all vertices of the current face + const int fIdx = intersection.indexInInside(); + const int numFaceVertices = refElement.size(fIdx, 1, dim); + + // loop over the single vertices on the current face + for (int faceVertexIdx = 0; faceVertexIdx < numFaceVertices; ++faceVertexIdx) + { + // only evaluate, if we consider the same face vertex as in the outer + // loop over the element vertices + if (refElement.subEntity(fIdx, 1, faceVertexIdx, dim) + != scvIdx) + continue; + + const int boundaryFaceIdx = this->fvGeometry_().boundaryFaceIndex(fIdx, faceVertexIdx); + const FluxVariables boundaryVars(this->problem_(), + this->element_(), + this->fvGeometry_(), + boundaryFaceIdx, + this->curVolVars_(), + true); + + // the computed residual of the momentum equations is stored + // into momentumResidual for the replacement of the mass balance + // in case of Dirichlet conditions for the momentum balance; + // the fluxes at the boundary are added in the second step + if (momentumBalanceDirichlet_(bcTypes)) + { + const DimVector &boundaryFaceNormal = + boundaryVars.face().normal; + + Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); + + DimVector muGradVelNormal(0.0); + velGrad.umv(boundaryFaceNormal, muGradVelNormal); + muGradVelNormal *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); + + for (unsigned int i=0; i < this->residual_.size(); i++) + Valgrind::CheckDefined(this->residual_[i]); + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + momentumResidual[dimIdx] = this->residual_[scvIdx][momentumXIdx+dimIdx]; + + //Sign is right!!!: boundary flux: -mu grad v n + //but to compensate outernormal -> residual - (-mu grad v n) + momentumResidual += muGradVelNormal; + averagedNormal += boundaryFaceNormal; + } + + // evaluate fluxes at a single boundary segment + asImp_()->evalNeumannSegment_(&intersection, scvIdx, boundaryFaceIdx, boundaryVars); + asImp_()->evalOutflowSegment_(&intersection, scvIdx, boundaryFaceIdx, boundaryVars); + + // count the number of outer faces to determine, if we are on + // a corner point and if an interpolation should be done + numberOfOuterFaces++; + } // end loop over face vertices + } // end loop over intersections + + if(!bcTypes.isDirichlet(massBalanceIdx)) + { + // replace the mass balance by the sum of the residua of the momentum balance + if (momentumBalanceDirichlet_(bcTypes)) + replaceMassbalanceResidual_(momentumResidual, averagedNormal, scvIdx); + else // de-stabilize (remove alpha*grad p - alpha div f + // from computeFlux on the boundary) + removeStabilizationAtBoundary_(scvIdx); + } + if (numberOfOuterFaces == 2) + interpolateCornerPoints_(bcTypes, scvIdx); + } // end loop over element vertices + + // evaluate the dirichlet conditions of the element + if (this->bcTypes_().hasDirichlet()) + asImp_()->evalDirichlet_(); + } + +protected: + /*! + * \brief Evaluate and add Neumann boundary conditions for a single sub-control + * volume face to the local residual. + */ + template <class IntersectionIterator> + void evalNeumannSegment_(const IntersectionIterator &isIt, + const int scvIdx, + const int boundaryFaceIdx, + const FluxVariables &boundaryVars) + { + const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); + + if (bcTypes.hasNeumann()) + { + // call evalNeumannSegment_() of the base class first + ParentType::evalNeumannSegment_(isIt, scvIdx, boundaryFaceIdx); + + // temporary vector to store the Neumann boundary fluxes + PrimaryVariables values(0.0); + if (momentumBalanceHasNeumann_(bcTypes)) + { + // Neumann BC of momentum equation needs special treatment + // mathematically Neumann BC: p n - mu grad v n = q + // boundary terms: -mu grad v n + // implement q * A (from evalBoundarySegment) - p n(unity) A + DimVector pressureCorrection(boundaryVars.face().normal); + pressureCorrection *= this->curVolVars_(scvIdx).pressure(); + for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; momentumIdx++) + if(bcTypes.isNeumann(momentumIdx)) + this->residual_[scvIdx][momentumIdx] += pressureCorrection[momentumIdx]; + + // beta-stabilization at the boundary + // in case of neumann conditions for the momentum equation; + // calculate mu grad v t t + // center in the face of the reference element + DimVector tangent; + if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationBeta_, 0.0, 1.0e-30)) + { + if (dim == 3) + DUNE_THROW(Dune::NotImplemented, "The beta-stabilization is only implemented for 2D."); + + const DimVector& elementUnitNormal = isIt->centerUnitOuterNormal(); + + tangent[0] = elementUnitNormal[1]; //TODO: 3D + tangent[1] = -elementUnitNormal[0]; + + Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); + + DimVector muGradVelTangential(0.0); + velGrad.mv(tangent, muGradVelTangential); + muGradVelTangential *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); + + this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5* + this->curVolVars_(scvIdx).pressure(); + this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5* + (muGradVelTangential*tangent); + + for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; momentumIdx++) + this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5 + * values[momentumIdx]*elementUnitNormal[momentumIdx-momentumXIdx]; + } + Valgrind::CheckDefined(this->residual_); + } + } + } + + /*! + * \brief Evaluate outflow boundary conditions for a single SCV face on the boundary. + */ + template <class IntersectionIterator> + void evalOutflowSegment_(const IntersectionIterator &isIt, + const int scvIdx, + const int boundaryFaceIdx, + const FluxVariables &boundaryVars) + { + const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); + + if (bcTypes.hasOutflow()) + { + PrimaryVariables values(0.0); + + asImp_()->computeFlux(values, boundaryFaceIdx, /*onBoundary=*/true); + Valgrind::CheckDefined(values); + + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (!bcTypes.isOutflow(eqIdx) ) + continue; + // do not calculate outflow for the mass balance + // if the momentum balance is dirichlet - + // it is replaced in that case + if (eqIdx==massBalanceIdx && momentumBalanceDirichlet_(bcTypes)) + continue; + // deduce outflow + this->residual_[scvIdx][eqIdx] += values[eqIdx]; + } + + // beta-stabilization at the boundary in case of outflow condition + // for the momentum balance + if(momentumBalanceOutflow_(bcTypes) && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationBeta_, 0.0, 1.0e-30)) + { + // calculate mu grad v t t for beta-stabilization + // center in the face of the reference element + DimVector tangent; + const DimVector& elementUnitNormal = isIt->centerUnitOuterNormal(); + tangent[0] = elementUnitNormal[1]; + tangent[1] = -elementUnitNormal[0]; + + Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); + if (enableUnsymmetrizedVelocityGradient) + { + // nothing has to be done in this case: + // grad v + } + else + { + // compute symmetrized gradient for the momentum flux: + // mu (grad v + (grad v)^t) + for (int i=0; i<dim; ++i) + for (int j=0; j<dim; ++j) + velGrad[i][j] += boundaryVars.velocityGrad()[j][i]; + } + + DimVector muGradVelTangential(0.0); + velGrad.umv(tangent, muGradVelTangential); + muGradVelTangential *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); + + this->residual_[scvIdx][massBalanceIdx] -= 0.5*stabilizationBeta_ + * (muGradVelTangential*tangent); + } + } + } + + /*! + * \brief Remove the alpha stabilization at boundaries. + */ + void removeStabilizationAtBoundary_(const int scvIdx) + { + if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationAlpha_, 0.0, 1.0e-30)) + { + // loop over the edges of the element + for (int fIdx = 0; fIdx < this->fvGeometry_().numScvf; fIdx++) + { + const FluxVariables fluxVars(this->problem_(), + this->element_(), + this->fvGeometry_(), + fIdx, + this->curVolVars_()); + + const int i = this->fvGeometry_().subContVolFace[fIdx].i; + const int j = this->fvGeometry_().subContVolFace[fIdx].j; + + if (i != scvIdx && j != scvIdx) + continue; + + const Scalar alphaH2 = stabilizationAlpha_* + fluxVars.averageSCVVolume(); + Scalar stabilizationTerm = fluxVars.pressureGrad() * + this->fvGeometry_().subContVolFace[fIdx].normal; + + stabilizationTerm *= alphaH2; + + if (scvIdx == i) + this->residual_[i][massBalanceIdx] += stabilizationTerm; + if (scvIdx == j) + this->residual_[j][massBalanceIdx] -= stabilizationTerm; + } + + //destabilize source term + PrimaryVariables source(0.0); + this->problem_().solDependentSource(source, + this->element_(), + this->fvGeometry_(), + scvIdx, + this->curVolVars_()); + const Scalar alphaH2 = stabilizationAlpha_ * this->fvGeometry_().subContVol[scvIdx].volume; + this->residual_[scvIdx][massBalanceIdx] += alphaH2 * source[massBalanceIdx] * + this->fvGeometry_().subContVol[scvIdx].volume; + } + } + + /*! + * \brief Interpolate the pressure at corner points of the grid, thus taking the degree of freedom there. + * This is required due to stability reasons. + */ + void interpolateCornerPoints_(const BoundaryTypes &bcTypes, const int scvIdx) + { + if (dim == 3) + DUNE_THROW(Dune::NotImplemented, "The function interpolateCornerPoints_() is only implemented for 2D."); + + if (bcTypes.isCoupling(massBalanceIdx)) + { + if (scvIdx == 0 || scvIdx == 3) + this->residual_[scvIdx][massBalanceIdx] = + this->curPriVars_(0)[pressureIdx] - this->curPriVars_(3)[pressureIdx]; + if (scvIdx == 1 || scvIdx == 2) + this->residual_[scvIdx][massBalanceIdx] = + this->curPriVars_(1)[pressureIdx] - this->curPriVars_(2)[pressureIdx]; + } + else + { + if (!bcTypes.isDirichlet(massBalanceIdx)) // do nothing in case of dirichlet + this->residual_[scvIdx][massBalanceIdx] = + this->curPriVars_(0)[pressureIdx] + this->curPriVars_(3)[pressureIdx]- + this->curPriVars_(1)[pressureIdx] - this->curPriVars_(2)[pressureIdx]; + } + } + + /*! + * \brief Replace the local residual of the mass balance equation by + * the sum of the residuals of the momentum balance equation. + */ + void replaceMassbalanceResidual_(const DimVector& momentumResidual, + DimVector& averagedNormal, + const int scvIdx) + { + assert( (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(averagedNormal.two_norm(), 0.0, 1.0e-30)) ); + + // divide averagedNormal by its length + averagedNormal /= averagedNormal.two_norm(); + // replace the mass balance by the sum of the residuals of the momentum balances + this->residual_[scvIdx][massBalanceIdx] = momentumResidual*averagedNormal; + } + + /*! + * \brief Returns true, if all boundary conditions for the momentum balance + * at the considered vertex are Dirichlet. + */ + bool momentumBalanceDirichlet_(const BoundaryTypes& bcTypes) const + { + for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) + if (!bcTypes.isDirichlet(momentumIdx)) + return false; + return true; + } + + /*! + * \brief Returns true, if at least one boundary condition of the momentum balance is Neumann. + */ + bool momentumBalanceHasNeumann_(const BoundaryTypes& bcTypes) const + { + for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) + if (bcTypes.isNeumann(momentumIdx)) + return true; + return false; + } + + /*! + * \brief Returns true, if all boundary conditions for the momentum balance are outflow. + */ + bool momentumBalanceOutflow_(const BoundaryTypes& bcTypes) const + { + for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) + if (!bcTypes.isOutflow(momentumIdx)) + return false; + return true; + } + + Scalar massUpwindWeight_; + Scalar stabilizationAlpha_; + Scalar stabilizationBeta_; + + Implementation *asImp_() + { return static_cast<Implementation *>(this); } + const Implementation *asImp_() const + { return static_cast<const Implementation *>(this); } +}; + +} + +#endif diff --git a/dumux/freeflow/stokes/model.hh b/dumux/freeflow/stokes/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..0e96eb29e5f957f26b85fb529065c06a4562c39d --- /dev/null +++ b/dumux/freeflow/stokes/model.hh @@ -0,0 +1,201 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_STOKES_MODEL_HH +#define DUMUX_STOKES_MODEL_HH + +/*! + * \file + * \brief Base class for all models which use the Stokes box model. + */ + +#include <dumux/implicit/model.hh> + +#include "localresidual.hh" +#include "newtoncontroller.hh" +#include "localjacobian.hh" +#include "problem.hh" +#include "properties.hh" + +namespace Dumux +{ +/*! + * \ingroup BoxStokesModel + * \brief Adaption of the box scheme to the Stokes model. + * + * This model implements laminar Stokes flow of a single fluid, solving the momentum balance equation + * \f[ + * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} + * + \text{div} \left( p_g {\bf {I}} + * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g + * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) + * - \varrho_g {\bf g} = 0 + * \f] + * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes + * equation can be solved. In this case an additional term + * \f[ + * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) + * \f] + * is added to the momentum balance equation. + * + * The mass balance equation: + * \f[ + * \frac{\partial \varrho_g}{\partial t} + * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 + * \f] + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class StokesModel : public GET_PROP_TYPE(TypeTag, BaseModel) +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + enum { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld + }; + enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + +public: + /*! + * \brief Calculate the fluxes across a certain layer in the domain. + * The layer is situated perpendicular to the coordinate axis "coord" and cuts + * the axis at the value "coordVal". + * + * \param globalSol The global solution vector + * \param flux A vector to store the flux + * \param axis The dimension, perpendicular to which the layer is situated + * \param coordVal The (Scalar) coordinate on the axis, at which the layer is situated + */ + void calculateFluxAcrossLayer(const SolutionVector &globalSol, Dune::FieldVector<Scalar, numEq> &flux, int axis, Scalar coordVal) + { + GlobalPosition globalI, globalJ; + PrimaryVariables tmpFlux(0.0); + + FVElementGeometry fvGeometry; + ElementVolumeVariables elemVolVars; + + // Loop over elements + for (const auto& element : Dune::elements(this->problem_.gridView())) + { + if (element.partitionType() != Dune::InteriorEntity) + continue; + + fvGeometry.update(this->gridView_(), element); + elemVolVars.update(this->problem_(), element, fvGeometry); + this->localResidual().evalFluxes(element, elemVolVars); + + bool hasLeft = false; + bool hasRight = false; + for (int i = 0; i < fvGeometry.numScv; i++) { + const GlobalPosition &globalPos = fvGeometry.subContVol[i].global; + if (globalI[axis] < coordVal) + hasLeft = true; + else if (globalI[axis] >= coordVal) + hasRight = true; + } + if (!hasLeft || !hasRight) + continue; + + for (int i = 0; i < fvGeometry.numScv; i++) { + const GlobalPosition &globalPos = fvGeometry.subContVol[i].global; + if (globalI[axis] < coordVal) + flux += this->localResidual().residual(i); + } + } + + flux = this->problem_.gridView().comm().sum(flux); + } + + //! \copydoc ImplicitModel::addOutputVtkFields + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + ScalarField &pn = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + + unsigned numElements = this->gridView_().size(0); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + + FVElementGeometry fvGeometry; + VolumeVariables volVars; + ElementBoundaryTypes elemBcTypes; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int eIdx = this->elementMapper().index(element); + + rank[eIdx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + elemBcTypes.update(this->problem_(), element); + + int numLocalVerts = element.subEntities(dim); + + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pn[vIdxGlobal] = volVars.pressure(); + delP[vIdxGlobal] = volVars.pressure() - 1e5; + rho[vIdxGlobal] = volVars.density(); + mu[vIdxGlobal] = volVars.dynamicViscosity(); + velocity[vIdxGlobal] = volVars.velocity(); + } + } + writer.attachVertexData(pn, "P"); + writer.attachVertexData(delP, "delP"); + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(velocity, "v", dim); + } +}; +} + +#include "propertydefaults.hh" + +#endif diff --git a/dumux/freeflow/stokes/newtoncontroller.hh b/dumux/freeflow/stokes/newtoncontroller.hh new file mode 100644 index 0000000000000000000000000000000000000000..8e98c6181e0762866ee306e8ff8dba9d15113357 --- /dev/null +++ b/dumux/freeflow/stokes/newtoncontroller.hh @@ -0,0 +1,50 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief A Stokes specific controller for the newton solver. + */ +#ifndef DUMUX_STOKES_NEWTON_CONTROLLER_HH +#define DUMUX_STOKES_NEWTON_CONTROLLER_HH + +#include <dumux/nonlinear/newtoncontroller.hh> + +namespace Dumux { +/*! + * \ingroup BoxStokesModel + * \ingroup Newton + * \brief A Stokes-specific controller for the nonlinear Newton solver, which sets + * different parameters for the relative tolerance, target steps and maximum steps. + */ +template <class TypeTag> +class StokesNewtonController : public NewtonController<TypeTag> +{ + typedef NewtonController<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + +public: + StokesNewtonController(const Problem &problem) + : ParentType(problem) + { + Dune::FMatrixPrecision<>::set_singular_limit(1e-35); + } +}; +} // end namespace Dumux + +#endif diff --git a/dumux/freeflow/stokes/problem.hh b/dumux/freeflow/stokes/problem.hh new file mode 100644 index 0000000000000000000000000000000000000000..2919be5c11dec0dfcce52393b84218f8699223fb --- /dev/null +++ b/dumux/freeflow/stokes/problem.hh @@ -0,0 +1,135 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for all stokes problems which use the box scheme. + */ +#ifndef DUMUX_STOKES_PROBLEM_HH +#define DUMUX_STOKES_PROBLEM_HH + +#include <dumux/implicit/problem.hh> + +#include "properties.hh" + +namespace Dumux +{ +/*! + * \ingroup ImplicitBaseProblems + * \ingroup BoxStokesModel + * \brief Base class for all problems which use the Stokes box model. + * + * This implements gravity (if desired) and a function returning the temperature. + */ +template<class TypeTag> +class StokesProblem : public ImplicitProblem<TypeTag> +{ + typedef ImplicitProblem<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation; + + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; + typedef typename GridView::Grid Grid; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GridView::Intersection Intersection; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + + enum { + dim = Grid::dimension, + dimWorld = Grid::dimensionworld + }; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + +public: + StokesProblem(TimeManager &timeManager, const GridView &gridView) + : ParentType(timeManager, gridView), + gravity_(0) + { + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) + gravity_[dim-1] = -9.81; + } + + /*! + * \name Problem parameters + */ + // \{ + + + /*! + * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position. + * + * This is not specific to the discretization. By default it just + * calls temperature(). + * + * \param globalPos The position in global coordinates where the temperature should be specified. + */ + Scalar temperatureAtPos(const GlobalPosition &globalPos) const + { return asImp_().temperature(); } + + /*! + * \brief Returns the temperature within the domain. + * + * This method MUST be overwritten by the actual problem. + */ + Scalar temperature() const + { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); } + + /*! + * \brief Returns the acceleration due to gravity. + * + * If the <tt>EnableGravity</tt> property is true, this means + * \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$, else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$ + */ + const GlobalPosition &gravity() const + { return gravity_; } + + /*! + * \brief Evaluate the intrinsic permeability + * at the corner of a given element + * + * \return (Scalar) permeability + */ + DUNE_DEPRECATED_MSG("permeability() is deprecated.") + Scalar permeability(const Element &element, + const FVElementGeometry &fvGeometry, + const Intersection &intersection, + const int scvIdx, + const int boundaryFaceIdx) const + { DUNE_THROW(Dune::NotImplemented, "permeability()"); } + + // \} + +private: + //! Returns the implementation of the problem (i.e. static polymorphism) + Implementation &asImp_() + { return *static_cast<Implementation *>(this); } + + //! \copydoc asImp_() + const Implementation &asImp_() const + { return *static_cast<const Implementation *>(this); } + + GlobalPosition gravity_; +}; + +} + +#endif diff --git a/dumux/freeflow/stokes/properties.hh b/dumux/freeflow/stokes/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..14471f6608abcc25d30d55e521bf2f4ac9a67788 --- /dev/null +++ b/dumux/freeflow/stokes/properties.hh @@ -0,0 +1,68 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesModel + * + * \file + * + * \brief Defines the properties required for the Stokes box model. + */ + +#ifndef DUMUX_STOKESPROPERTIES_HH +#define DUMUX_STOKESPROPERTIES_HH + +#include <dumux/implicit/box/properties.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the stokes problems +NEW_TYPE_TAG(BoxStokes, INHERITS_FROM(BoxModel)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// + +NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem +NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the upwind parameter for the mobility +NEW_PROP_TAG(Indices); //!< Enumerations for the model +NEW_PROP_TAG(Fluid); +NEW_PROP_TAG(FluidSystem); //!< The employed fluid system +NEW_PROP_TAG(FluidState); +NEW_PROP_TAG(StokesStabilizationAlpha); //!< The parameter for the stabilization +NEW_PROP_TAG(StokesStabilizationBeta); //!< The parameter for the stabilization at boundaries +NEW_PROP_TAG(EnableUnsymmetrizedVelocityGradient); //!< Returns whether unsymmetrized velocity gradient for viscous term is used +NEW_PROP_TAG(EnableNavierStokes); //!< Returns whether Navier-Stokes should be solved instead of plain Stokes +NEW_PROP_TAG(UseMoles); //!< Defines whether molar (true) or mass (false) density is used + +NEW_PROP_TAG(PhaseIdx); //!< A phase index in case that a two-phase fluidsystem is used +NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters +NEW_PROP_TAG(Scaling); //!<Defines Scaling of the model +} +} + +#endif diff --git a/dumux/freeflow/stokes/propertydefaults.hh b/dumux/freeflow/stokes/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..75eddc98c1359517435622fec6ca435a25cd1527 --- /dev/null +++ b/dumux/freeflow/stokes/propertydefaults.hh @@ -0,0 +1,165 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesModel + * + * \file + * + * \brief Defines default properties for the Stokes box model. + * + * These can be overwritten at a different place or + * may be replaced by values of the input file. + */ + +#ifndef DUMUX_STOKES_PROPERTY_DEFAULTS_HH +#define DUMUX_STOKES_PROPERTY_DEFAULTS_HH + +#include "properties.hh" +#include "indices.hh" +#include "localjacobian.hh" +#include "localresidual.hh" +#include "model.hh" +#include "volumevariables.hh" +#include "fluxvariables.hh" +#include "newtoncontroller.hh" + +#include <dumux/material/fluidsystems/gasphase.hh> +#include <dumux/material/fluidsystems/liquidphase.hh> +#include <dumux/material/components/nullcomponent.hh> + +#include <dumux/material/fluidsystems/1pfluidsystem.hh> +#include <dumux/material/fluidstates/immisciblefluidstate.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +//! The local jacobian operator for the stokes box scheme +SET_TYPE_PROP(BoxStokes, LocalJacobian, Dumux::StokesLocalJacobian<TypeTag>); + +SET_PROP(BoxStokes, NumEq) //!< set the number of equations +{ + typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + static const int dim = Grid::dimension; + public: + static constexpr int value = 1 + dim; +}; + +SET_SCALAR_PROP(BoxStokes, Scaling, 1); //!< set scaling to 1 by default + +//! Use the Stokes local residual function for the Stokes model +SET_TYPE_PROP(BoxStokes, LocalResidual, StokesLocalResidual<TypeTag>); + +//! Use the Stokes specific newton controller for the Stokes model +SET_TYPE_PROP(BoxStokes, NewtonController, StokesNewtonController<TypeTag>); + +#if HAVE_SUPERLU +SET_TYPE_PROP(BoxStokes, LinearSolver, SuperLUBackend<TypeTag>); +#elif HAVE_UMFPACK +SET_TYPE_PROP(BoxStokes, LinearSolver, UMFPackBackend<TypeTag>); +#endif + +//! the Model property +SET_TYPE_PROP(BoxStokes, Model, StokesModel<TypeTag>); + +//! the VolumeVariables property +SET_TYPE_PROP(BoxStokes, VolumeVariables, StokesVolumeVariables<TypeTag>); + +//! the FluxVariables property +SET_TYPE_PROP(BoxStokes, FluxVariables, StokesFluxVariables<TypeTag>); + +//! the upwind factor. +SET_SCALAR_PROP(BoxStokes, ImplicitMassUpwindWeight, 1.0); + +//! The fluid system to use by default +SET_PROP(BoxStokes, FluidSystem) +{ private: + typedef typename GET_PROP_TYPE(TypeTag, Fluid) Fluid; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; +public: + typedef FluidSystems::OneP<Scalar, Fluid> type; +}; + +//! The fluid that is used in the single-phase fluidsystem +SET_PROP(BoxStokes, Fluid) +{ private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; +public: + typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type; +}; + +//! Set the indices used by the Stokes model +SET_TYPE_PROP(BoxStokes, Indices, StokesCommonIndices<TypeTag>); + +//! Choose the type of the employed fluid state. +SET_PROP(BoxStokes, FluidState) +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; +public: + typedef Dumux::ImmiscibleFluidState<Scalar, FluidSystem> type; + +}; + +//! Enable evaluation of shape function gradients at the sub-control volume center by default +// Used for the computation of the pressure gradients +SET_BOOL_PROP(BoxStokes, EvalGradientsAtSCVCenter, true); + +//! Set the phaseIndex per default to zero (for two-phase or two-component system imported +// from fluid systems, see property defaults in stokesnc model). +SET_INT_PROP(BoxStokes, PhaseIdx, 0); + +//! Use symmetrizedVelocityGradient by default +SET_BOOL_PROP(BoxStokes, EnableUnsymmetrizedVelocityGradient, false); + +//! Set calculation to Stokes, not Navier-Stokes +SET_BOOL_PROP(BoxStokes, EnableNavierStokes, false); + +//! The mass density is used in the continuity equation +SET_BOOL_PROP(BoxStokes, UseMoles, false); + +//! A stabilization factor. Set negative for stabilization and to zero for no stabilization +SET_SCALAR_PROP(BoxStokes, StokesStabilizationAlpha, 0.0); + +//! Stabilization factor for the boundaries +SET_SCALAR_PROP(BoxStokes, StokesStabilizationBeta, 0.0); + +//! Set gravity by default +SET_BOOL_PROP(BoxStokes, ProblemEnableGravity, true); + +//! Set the value for the maximum relative shift +SET_SCALAR_PROP(BoxStokes, NewtonMaxRelativeShift, 1e-6); + +//! Set the number of iterations at which the Newton method should aim at. +SET_INT_PROP(BoxStokes, NewtonTargetSteps, 10); + +//! Set the number of maximum iterations for the Newton method. +SET_INT_PROP(BoxStokes, NewtonMaxSteps, 18); +} + +} + +#endif diff --git a/dumux/freeflow/stokes/stokesfluxvariables.hh b/dumux/freeflow/stokes/stokesfluxvariables.hh index 1d118d17f86fff5deaba10752a34804226a5ffb6..911ca104b81ebc7a41c9949363d86180e4a58e4d 100644 --- a/dumux/freeflow/stokes/stokesfluxvariables.hh +++ b/dumux/freeflow/stokes/stokesfluxvariables.hh @@ -1,287 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * the fluxes of the Stokes model over a face of a finite volume. - * - * This means pressure gradients, phase densities at the integration point, etc. - */ -#ifndef DUMUX_STOKES_FLUX_VARIABLES_HH -#define DUMUX_STOKES_FLUX_VARIABLES_HH +#ifndef DUMUX_STOKES_FLUX_VARIABLES_HH_OLD +#define DUMUX_STOKES_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/common/valgrind.hh> +#warning this header is deprecated, use dumux/freeflow/stokes/fluxvariables.hh instead -#include "stokesproperties.hh" - -namespace Dumux -{ - -/*! - * \ingroup BoxStokesModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains the data which is required to - * calculate the mass and momentum fluxes over the face of a - * sub-control volume for the Stokes model. - * - * This means pressure gradients, phase densities, viscosities, etc. - * at the integration point of the sub-control-volume face. - */ -template <class TypeTag> -class StokesFluxVariables -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - - enum { dim = GridView::dimension }; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename FVElementGeometry::SubControlVolumeFace SCVFace; - -public: - //! \brief The constructor - StokesFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : fvGeometry_(fvGeometry), onBoundary_(onBoundary), fIdx_(fIdx) - { - calculateValues_(problem, element, elemVolVars); - determineUpwindDirection_(elemVolVars); - } - -protected: - void calculateValues_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - // calculate gradients and secondary variables at IPs - DimVector tmp(0.0); - - density_ = Scalar(0); - dynamicViscosity_ = Scalar(0); - pressure_ = Scalar(0); - normalvelocity_ = Scalar(0); - velocity_ = Scalar(0); - pressureGrad_ = Scalar(0); - velocityGrad_ = Scalar(0); - - for (int scvIdx = 0; - scvIdx < fvGeometry_.numScv; - scvIdx++) // loop over adjacent vertices - { - // phase density and viscosity at IP - density_ += elemVolVars[scvIdx].density() * - face().shapeValue[scvIdx]; - dynamicViscosity_ += elemVolVars[scvIdx].dynamicViscosity() * - face().shapeValue[scvIdx]; - pressure_ += elemVolVars[scvIdx].pressure() * - face().shapeValue[scvIdx]; - - // velocity at the IP (fluxes) - DimVector velocityTimesShapeValue = elemVolVars[scvIdx].velocity(); - velocityTimesShapeValue *= face().shapeValue[scvIdx]; - velocity_ += velocityTimesShapeValue; - - // the pressure gradient - tmp = face().grad[scvIdx]; - tmp *= elemVolVars[scvIdx].pressure(); - pressureGrad_ += tmp; - // take gravity into account - tmp = problem.gravity(); - tmp *= density_; - // pressure gradient including influence of gravity - pressureGrad_ -= tmp; - - // the velocity gradients and divergence - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - { - tmp = face().grad[scvIdx]; - tmp *= elemVolVars[scvIdx].velocity()[dimIdx]; - velocityGrad_[dimIdx] += tmp; - } - } - - normalvelocity_ = velocity_ * face().normal; - - Valgrind::CheckDefined(density_); - Valgrind::CheckDefined(dynamicViscosity_); - Valgrind::CheckDefined(normalvelocity_); - Valgrind::CheckDefined(velocity_); - Valgrind::CheckDefined(pressureGrad_); - Valgrind::CheckDefined(velocityGrad_); - } - - void determineUpwindDirection_(const ElementVolumeVariables &elemVolVars) - { - - // set the upstream and downstream vertices - upstreamIdx_ = face().i; - downstreamIdx_ = face().j; - - if (normalVelocity() < 0) - std::swap(upstreamIdx_, downstreamIdx_); - } - -public: - /*! - * \brief The face of the current sub-control volume. This may be either - * an inner sub-control-volume face or a face on the boundary. - */ - const SCVFace &face() const - { - if (onBoundary_) - return fvGeometry_.boundaryFace[fIdx_]; - else - return fvGeometry_.subContVolFace[fIdx_]; - } - - /*! - * \brief Return the average volume of the upstream and the downstream sub-control volume; - * this is required for the stabilization. - */ - const Scalar averageSCVVolume() const - { - return 0.5*(fvGeometry_.subContVol[upstreamIdx_].volume + - fvGeometry_.subContVol[downstreamIdx_].volume); - } - - /*! - * \brief Return the pressure \f$\mathrm{[Pa]}\f$ at the integration - * point. - */ - Scalar pressure() const - { return pressure_; } - - /*! - * \brief Return the mass density \f$ \mathrm{[kg/m^3]} \f$ at the integration - * point. - */ - Scalar density() const - { return density_; } - - /*! - * \brief Return the dynamic viscosity \f$ \mathrm{[Pa\cdot s]} \f$ at the integration - * point. - */ - Scalar dynamicViscosity() const - { return dynamicViscosity_; } - - /*! - * \brief Returns the kinematic viscosity \f$ \frac{m^2}{s} \f$ of the fluid in - * the sub-control volume. - */ - Scalar kinematicViscosity() const - { return dynamicViscosity_ / density_; } - - /*! - * \brief Return the velocity \f$ \mathrm{[m/s]} \f$ at the integration - * point multiplied by the normal and the area. - */ - Scalar normalVelocity() const - { return normalvelocity_; } - - /*! - * \brief Return the pressure gradient at the integration point. - */ - const DimVector &pressureGrad() const - { return pressureGrad_; } - - /*! - * \brief Return the velocity vector at the integration point. - */ - const DimVector &velocity() const - { return velocity_; } - - /*! - * \brief Return the velocity gradient at the integration - * point of a face. - */ - const DimMatrix &velocityGrad() const - { return velocityGrad_; } - - /*! - * \brief Return the dynamic eddy viscosity - * \f$\mathrm{[Pa \cdot s]} = \mathrm{[N \cdot s/m^2]}\f$ (if implemented). - */ - const Scalar dynamicEddyViscosity() const - { return kinematicEddyViscosity() * density(); } - - /*! - * \brief Return the kinematic eddy viscosity - * \f$\mathrm{[m^2/s]}\f$ (if implemented). - */ - const Scalar kinematicEddyViscosity() const - { return 0; } - - /*! - * \brief Return the local index of the upstream sub-control volume. - */ - int upstreamIdx() const - { return upstreamIdx_; } - - /*! - * \brief Return the local index of the downstream sub-control volume. - */ - int downstreamIdx() const - { return downstreamIdx_; } - - /*! - * \brief Indicates if a face is on a boundary. Used for in the - * face() method (e.g. for outflow boundary conditions). - */ - bool onBoundary() const - { return onBoundary_; } - -protected: - const FVElementGeometry &fvGeometry_; - const bool onBoundary_; - - // values at the integration point - Scalar density_; - Scalar dynamicViscosity_; - Scalar pressure_; - Scalar normalvelocity_; - DimVector velocity_; - - // gradients at the IPs - DimVector pressureGrad_; - DimMatrix velocityGrad_; - - // local index of the upwind vertex - int upstreamIdx_; - // local index of the downwind vertex - int downstreamIdx_; - // the index of the considered face - int fIdx_; -}; - -} // end namespace +#include <dumux/freeflow/stokes/fluxvariables.hh> #endif diff --git a/dumux/freeflow/stokes/stokesindices.hh b/dumux/freeflow/stokes/stokesindices.hh index a47b574523aef3f91fc3b78c3fbf1dc7aee9b12a..0f6682181b4d25d438c3a372889f648365e08db8 100644 --- a/dumux/freeflow/stokes/stokesindices.hh +++ b/dumux/freeflow/stokes/stokesindices.hh @@ -1,69 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_STOKES_INDICES_HH_OLD +#define DUMUX_STOKES_INDICES_HH_OLD -/*! - * \file - * \brief Defines the indices required for the Stokes box model. - */ -#ifndef DUMUX_STOKES_INDICES_HH -#define DUMUX_STOKES_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/stokes/indices.hh instead -#include "stokesproperties.hh" - -namespace Dumux -{ -// \{ - -/*! - * \ingroup BoxStokesModel - * \ingroup ImplicitIndices - * \brief The common indices for the isothermal stokes model. - * - * \tparam PVOffset The first index in a primary variable vector. - */ -template <class TypeTag, int PVOffset = 0> -struct StokesCommonIndices -{ - // number of dimensions - typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; - static const int dim = Grid::dimension; - - // Primary variable indices - static const int momentumXIdx = PVOffset + 0; //!< Index of the x-component of the momentum equation - static const int momentumYIdx = PVOffset + 1; //!< Index of the y-component of the momentum equation - static const int momentumZIdx = PVOffset + 2; //!< Index of the z-component of the momentum equation - static const int lastMomentumIdx = momentumXIdx+dim-1; //!< Index of the last component of the momentum equation - - static const int dimXIdx = 0; //!< Index of the x-component of a vector of size dim - static const int dimYIdx = 1; //!< Index of the y-component of a vector of size dim - static const int dimZIdx = 2; //!< Index of the z-component of a vector of size dim - - static const int massBalanceIdx = dim; //!< Index of the mass balance equation - static const int conti0EqIdx = massBalanceIdx; //!< Index of first (for C-guys: 0th) mass conservation equation - - static const int pressureIdx = massBalanceIdx; //!< Index of the pressure in a solution vector - static const int velocityXIdx = momentumXIdx; //!< Index of the x-component of the velocity - static const int velocityYIdx = momentumYIdx; //!< Index of the y-component of the velocity - static const int velocityZIdx = momentumZIdx; //!< Index of the z-component of the velocity - - static const int phaseIdx = 0; //!< Index of the fluid phase (required to use the same fluid system in coupled models) -}; -} // end namespace +#include <dumux/freeflow/stokes/indices.hh> #endif diff --git a/dumux/freeflow/stokes/stokeslocaljacobian.hh b/dumux/freeflow/stokes/stokeslocaljacobian.hh index b15762a2d911e6432214c165327129aff6b8564a..29fd616933605a8b7bd4b44519f2dac5bfdd2414 100644 --- a/dumux/freeflow/stokes/stokeslocaljacobian.hh +++ b/dumux/freeflow/stokes/stokeslocaljacobian.hh @@ -1,60 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Element-wise calculation of the Jacobian matrix for the Stokes models. - */ -#ifndef DUMUX_STOKES_LOCAL_JACOBIAN_HH -#define DUMUX_STOKES_LOCAL_JACOBIAN_HH +#ifndef DUMUX_STOKES_LOCAL_JACOBIAN_HH_OLD +#define DUMUX_STOKES_LOCAL_JACOBIAN_HH_OLD -#include <dune/istl/matrix.hh> -#include "stokesproperties.hh" -#include <dumux/implicit/localjacobian.hh> +#warning this header is deprecated, use dumux/freeflow/stokes/localjacobian.hh instead -namespace Dumux -{ -/*! - * \ingroup BoxStokesModel - * \ingroup ImplicitLocalJacobian - * \brief Element-wise calculation of the Jacobian matrix for the Stokes models. - * - * This overloads the numericEpsilon method of the ImplicitLocalJacobian. - * The momentum balance equation uses larger epsilons than the rest. - */ -template<class TypeTag> -class StokesLocalJacobian : public ImplicitLocalJacobian<TypeTag> -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - -public: - //! \copydoc ImplicitLocalJacobian::numericEpsilon() - Scalar numericEpsilon(const int scvIdx, - const int pvIdx) const - { - Scalar pv = this->curVolVars_[scvIdx].priVars()[pvIdx]; - if (pvIdx < GridView::dimension){ - return 1e-7*(std::abs(pv) + 1); - } - return 1e-9*(std::abs(pv) + 1); - } -}; -} +#include <dumux/freeflow/stokes/localjacobian.hh> #endif diff --git a/dumux/freeflow/stokes/stokeslocalresidual.hh b/dumux/freeflow/stokes/stokeslocalresidual.hh index 247da3961abd033a795be88a46e24529e48a639b..83241d68e33c5fc56017193facd0ef7efddd9214 100644 --- a/dumux/freeflow/stokes/stokeslocalresidual.hh +++ b/dumux/freeflow/stokes/stokeslocalresidual.hh @@ -1,707 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Element-wise calculation of the Jacobian matrix for problems - * using the Stokes box model. - */ +#ifndef DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH_OLD +#define DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH_OLD -#ifndef DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH -#define DUMUX_STOKES_LOCAL_RESIDUAL_BASE_HH +#warning this header is deprecated, use dumux/freeflow/stokes/localresidual.hh instead -#include <dune/common/float_cmp.hh> -#include <dune/grid/common/grid.hh> - -#include <dumux/implicit/model.hh> -#include "stokesproperties.hh" -#include "stokesvolumevariables.hh" -#include "stokesfluxvariables.hh" - -namespace Dumux -{ -/*! - * \ingroup BoxStokesModel - * \ingroup ImplicitLocalResidual - * \brief Element-wise calculation of the local Jacobian matrix for problems - * using the Stokes box model. - * - * This class is also used for the non-isothermal and the two-component Stokes - * model (static polymorphism). - */ -template<class TypeTag> -class StokesLocalResidual : public GET_PROP_TYPE(TypeTag, BaseLocalResidual) -{ -protected: - typedef typename GET_PROP_TYPE(TypeTag, BaseLocalResidual) ParentType; - typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation; - - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - enum { - dim = GridView::dimension, - numEq = GET_PROP_VALUE(TypeTag, NumEq) - }; - enum { - massBalanceIdx = Indices::massBalanceIdx, //!< Index of the mass balance - momentumXIdx = Indices::momentumXIdx, //!< Index of the x-component of the momentum balance - lastMomentumIdx = Indices::lastMomentumIdx //!< Index of the last component of the momentum balance - }; - enum { pressureIdx = Indices::pressureIdx }; //!< Index of the pressure in a solution vector - - typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements; - typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement; - - typedef Dune::FieldVector<Scalar, dim> DimVector; - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; - - static const bool enableUnsymmetrizedVelocityGradient = GET_PROP_VALUE(TypeTag, EnableUnsymmetrizedVelocityGradient); - static const bool calculateNavierStokes = GET_PROP_VALUE(TypeTag, EnableNavierStokes); - static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); - - public: - /*! - * \brief Constructor. Sets the upwind weight and the stabilization parameters. - */ - StokesLocalResidual() - { - // retrieve the upwind weight for the mass conservation equations. Use the value - // specified via the property system as default, and overwrite - // it by the run-time parameter from the Dune::ParameterTree - massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight); - stabilizationAlpha_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Stokes, StabilizationAlpha); - stabilizationBeta_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Stokes, StabilizationBeta); - } - - /*! - * \brief Evaluates the amount of all conservation quantities - * (mass and momentum) within a sub-control volume. - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param scvIdx The SCV (sub-control-volume) index - * \param usePrevSol Evaluate function with solution of current or previous time step - */ - void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const - { - // if flag usePrevSol is set, the solution from the previous - // time step is used, otherwise the current solution is - // used. The secondary variables are used accordingly. This - // is required to compute the derivative of the storage term - // using the implicit Euler method. - const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() - : this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - storage = 0.0; - - if(useMoles) - // mass balance mole fraction based - storage[massBalanceIdx] = volVars.molarDensity(); - else - // mass balance mass fraction based - storage[massBalanceIdx] = volVars.density(); - - // momentum balance - for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; ++momentumIdx) - storage[momentumIdx] = volVars.density() - * volVars.velocity()[momentumIdx-momentumXIdx]; - } - - /*! - * \brief Evaluates the total flux of all conservation quantities - * over a face of a sub-control volume. The face may be within - * an element (SCV face) or on the boundary. The advective and - * the diffusive fluxes are computed. - * - * \param flux The flux over the SCV (sub-control-volume) face - * \param fIdx The index of the SCV face (may also be a boundary face) - * \param onBoundary Indicates, if the flux is evaluated on a boundary face. If it is true, - * the created fluxVars object contains boundary variables evaluated at the IP of the - * boundary face - */ - void computeFlux(PrimaryVariables &flux, const int fIdx, const bool onBoundary=false) const - { - const FluxVariables fluxVars(this->problem_(), - this->element_(), - this->fvGeometry_(), - fIdx, - this->curVolVars_(), - onBoundary); - flux = 0.0; - - asImp_()->computeAdvectiveFlux(flux, fluxVars); - Valgrind::CheckDefined(flux); - asImp_()->computeDiffusiveFlux(flux, fluxVars); - Valgrind::CheckDefined(flux); - } - - /*! - * \brief Evaluates the advective fluxes over - * a face of a sub-control volume. - * - * \param flux The advective flux over the sub-control-volume face for each component - * \param fluxVars The flux variables at the current SCV/boundary face - */ - void computeAdvectiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // if the momentum balance has a dirichlet b.c., the mass balance - // is replaced, thus we do not need to calculate outflow fluxes here - if (fluxVars.onBoundary() && - momentumBalanceDirichlet_(this->bcTypes_(fluxVars.upstreamIdx()))) - { - return; - } - - // data attached to upstream and the downstream vertices - const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); - const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); - - DimVector massBalanceResidual = fluxVars.velocity(); - - if(useMoles) - { - massBalanceResidual *= (massUpwindWeight_ * up.molarDensity() - + (1.-massUpwindWeight_) * dn.molarDensity()); - } - else - { - massBalanceResidual *= (massUpwindWeight_ * up.density() - + (1.-massUpwindWeight_) * dn.density()); - } - - if (!fluxVars.onBoundary()) - { - // stabilization of the mass balance - // with 0.5*alpha*(V_i + V_j)*grad P - DimVector stabilizationTerm = fluxVars.pressureGrad(); - stabilizationTerm *= stabilizationAlpha_* - fluxVars.averageSCVVolume(); - massBalanceResidual += stabilizationTerm; - } - - flux[massBalanceIdx] += - massBalanceResidual*fluxVars.face().normal; - - // momentum balance - pressure is evaluated as volume term - // at the center of the SCV in computeSource - // dynamic viscosity is upwinded - - Dune::FieldMatrix<Scalar, dim, dim> velGrad = fluxVars.velocityGrad(); - if (enableUnsymmetrizedVelocityGradient) - { - // nothing has to be done in this case: - // grad v - } - else - { - // compute symmetrized gradient for the momentum flux: - // grad v + (grad v)^T - for (int i=0; i<dim; ++i) - for (int j=0; j<dim; ++j) - velGrad[i][j] += fluxVars.velocityGrad()[j][i]; - } - - DimVector velGradComp(0.); - for (int velIdx = 0; velIdx < dim; ++velIdx) - { - velGradComp = velGrad[velIdx]; - - // TODO: dilatation term has to be accounted for in outflow, coupling, neumann - // velGradComp[velIdx] += 2./3*fluxVars.velocityDiv; - - velGradComp *= fluxVars.dynamicViscosity() + fluxVars.dynamicEddyViscosity(); - - flux[momentumXIdx + velIdx] -= - velGradComp*fluxVars.face().normal; - - // gravity is accounted for in computeSource; alternatively: - // Scalar gravityTerm = fluxVars.density * - // this->problem_().gravity()[dim-1] * - // fluxVars.face().ipGlobal[dim-1]* - // fluxVars.face().normal[velIdx]; - // flux[momentumXIdx + velIdx] -= - // gravityTerm; - - } - - // this term changes the Stokes equation to the Navier-Stokes equation - // rho v (v*n) - // rho and first v are upwinded, second v is evaluated at the face - if (calculateNavierStokes) - { - for (int dimIndex = 0; dimIndex < dim; ++dimIndex) - flux[momentumXIdx + dimIndex] += - up.density() * up.velocity()[dimIndex] * fluxVars.normalVelocity(); - } - } - - /*! - * \brief Adds the diffusive flux to the flux vector over - * a SCV face or a boundary face. - * - * It doesn't do anything in the Stokes model but is used by the - * transport and non-isothermal models to calculate diffusive and - * conductive fluxes. - * - * \param flux The diffusive flux over the SCV face or boundary face for each component - * \param fluxVars The flux variables at the current SCV/boundary face - */ - void computeDiffusiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { } - - /*! - * \brief Calculate the source term of all equations. - * The pressure gradient at the center of a SCV is computed - * and the gravity term evaluated. - * - * \param source The source/sink in the sub control volume for each component - * \param scvIdx The local index of the sub-control volume - */ - void computeSource(PrimaryVariables &source, const int scvIdx) - { - const ElementVolumeVariables &elemVolVars = this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - // retrieve the source term intrinsic to the problem - this->problem_().solDependentSource(source, - this->element_(), - this->fvGeometry_(), - scvIdx, - this->curVolVars_()); - - // ATTENTION: The source term of the mass balance has to be chosen as - // div (q_momentum) in the problem file - const Scalar alphaH2 = stabilizationAlpha_* - this->fvGeometry_().subContVol[scvIdx].volume; - source[massBalanceIdx] *= alphaH2; // stabilization of the source term - - // pressure gradient at the center of the SCV, - // the pressure is discretized as volume term, - // while -mu grad v is calculated in computeFlux - DimVector pressureGradAtSCVCenter(0.0); - DimVector grad(0.0); - - for (int scvIdx2 = 0; scvIdx2 < this->fvGeometry_().numScv; scvIdx2++) - { - grad = this->fvGeometry_().subContVol[scvIdx].gradCenter[scvIdx2]; - Valgrind::CheckDefined(grad); - grad *= elemVolVars[scvIdx2].pressure(); - - pressureGradAtSCVCenter += grad; - } - - // add the component of the pressure gradient to the respective part - // of the momentum equation and take the gravity term into account - // signs are inverted, since q is subtracted - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - { - source[momentumXIdx + dimIdx] -= pressureGradAtSCVCenter[dimIdx]; - source[momentumXIdx + dimIdx] += volVars.density()*this->problem_().gravity()[dimIdx]; - } - } - - /*! - * \brief The Stokes model needs a modified treatment of the boundary conditions as - * the common box models - */ - void evalBoundary_() - { - assert(this->residual_.size() == this->fvGeometry_().numScv); - const ReferenceElement &refElement = ReferenceElements::general(this->element_().geometry().type()); - - // loop over sub-control volums of the element - for (int scvIdx = 0; scvIdx < this->fvGeometry_().numScv; scvIdx++) - { - // consider only SCVs on the boundary - if (this->fvGeometry_().subContVol[scvIdx].inner) - continue; - - // important at corners of the grid - DimVector momentumResidual(0.0); - DimVector averagedNormal(0.0); - int numberOfOuterFaces = 0; - // evaluate boundary conditions for the intersections of - // the current element - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); - for (const auto& intersection : Dune::intersections(this->gridView_(), this->element_())) - { - // handle only intersections on the boundary - if (!intersection.boundary()) - continue; - - // assemble the boundary for all vertices of the current face - const int fIdx = intersection.indexInInside(); - const int numFaceVertices = refElement.size(fIdx, 1, dim); - - // loop over the single vertices on the current face - for (int faceVertexIdx = 0; faceVertexIdx < numFaceVertices; ++faceVertexIdx) - { - // only evaluate, if we consider the same face vertex as in the outer - // loop over the element vertices - if (refElement.subEntity(fIdx, 1, faceVertexIdx, dim) - != scvIdx) - continue; - - const int boundaryFaceIdx = this->fvGeometry_().boundaryFaceIndex(fIdx, faceVertexIdx); - const FluxVariables boundaryVars(this->problem_(), - this->element_(), - this->fvGeometry_(), - boundaryFaceIdx, - this->curVolVars_(), - true); - - // the computed residual of the momentum equations is stored - // into momentumResidual for the replacement of the mass balance - // in case of Dirichlet conditions for the momentum balance; - // the fluxes at the boundary are added in the second step - if (momentumBalanceDirichlet_(bcTypes)) - { - const DimVector &boundaryFaceNormal = - boundaryVars.face().normal; - - Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); - - DimVector muGradVelNormal(0.0); - velGrad.umv(boundaryFaceNormal, muGradVelNormal); - muGradVelNormal *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); - - for (unsigned int i=0; i < this->residual_.size(); i++) - Valgrind::CheckDefined(this->residual_[i]); - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - momentumResidual[dimIdx] = this->residual_[scvIdx][momentumXIdx+dimIdx]; - - //Sign is right!!!: boundary flux: -mu grad v n - //but to compensate outernormal -> residual - (-mu grad v n) - momentumResidual += muGradVelNormal; - averagedNormal += boundaryFaceNormal; - } - - // evaluate fluxes at a single boundary segment - asImp_()->evalNeumannSegment_(&intersection, scvIdx, boundaryFaceIdx, boundaryVars); - asImp_()->evalOutflowSegment_(&intersection, scvIdx, boundaryFaceIdx, boundaryVars); - - // count the number of outer faces to determine, if we are on - // a corner point and if an interpolation should be done - numberOfOuterFaces++; - } // end loop over face vertices - } // end loop over intersections - - if(!bcTypes.isDirichlet(massBalanceIdx)) - { - // replace the mass balance by the sum of the residua of the momentum balance - if (momentumBalanceDirichlet_(bcTypes)) - replaceMassbalanceResidual_(momentumResidual, averagedNormal, scvIdx); - else // de-stabilize (remove alpha*grad p - alpha div f - // from computeFlux on the boundary) - removeStabilizationAtBoundary_(scvIdx); - } - if (numberOfOuterFaces == 2) - interpolateCornerPoints_(bcTypes, scvIdx); - } // end loop over element vertices - - // evaluate the dirichlet conditions of the element - if (this->bcTypes_().hasDirichlet()) - asImp_()->evalDirichlet_(); - } - -protected: - /*! - * \brief Evaluate and add Neumann boundary conditions for a single sub-control - * volume face to the local residual. - */ - template <class IntersectionIterator> - void evalNeumannSegment_(const IntersectionIterator &isIt, - const int scvIdx, - const int boundaryFaceIdx, - const FluxVariables &boundaryVars) - { - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); - - if (bcTypes.hasNeumann()) - { - // call evalNeumannSegment_() of the base class first - ParentType::evalNeumannSegment_(isIt, scvIdx, boundaryFaceIdx); - - // temporary vector to store the Neumann boundary fluxes - PrimaryVariables values(0.0); - if (momentumBalanceHasNeumann_(bcTypes)) - { - // Neumann BC of momentum equation needs special treatment - // mathematically Neumann BC: p n - mu grad v n = q - // boundary terms: -mu grad v n - // implement q * A (from evalBoundarySegment) - p n(unity) A - DimVector pressureCorrection(boundaryVars.face().normal); - pressureCorrection *= this->curVolVars_(scvIdx).pressure(); - for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; momentumIdx++) - if(bcTypes.isNeumann(momentumIdx)) - this->residual_[scvIdx][momentumIdx] += pressureCorrection[momentumIdx]; - - // beta-stabilization at the boundary - // in case of neumann conditions for the momentum equation; - // calculate mu grad v t t - // center in the face of the reference element - DimVector tangent; - if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationBeta_, 0.0, 1.0e-30)) - { - if (dim == 3) - DUNE_THROW(Dune::NotImplemented, "The beta-stabilization is only implemented for 2D."); - - const DimVector& elementUnitNormal = isIt->centerUnitOuterNormal(); - - tangent[0] = elementUnitNormal[1]; //TODO: 3D - tangent[1] = -elementUnitNormal[0]; - - Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); - - DimVector muGradVelTangential(0.0); - velGrad.mv(tangent, muGradVelTangential); - muGradVelTangential *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); - - this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5* - this->curVolVars_(scvIdx).pressure(); - this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5* - (muGradVelTangential*tangent); - - for (int momentumIdx = momentumXIdx; momentumIdx <= lastMomentumIdx; momentumIdx++) - this->residual_[scvIdx][massBalanceIdx] -= stabilizationBeta_*0.5 - * values[momentumIdx]*elementUnitNormal[momentumIdx-momentumXIdx]; - } - Valgrind::CheckDefined(this->residual_); - } - } - } - - /*! - * \brief Evaluate outflow boundary conditions for a single SCV face on the boundary. - */ - template <class IntersectionIterator> - void evalOutflowSegment_(const IntersectionIterator &isIt, - const int scvIdx, - const int boundaryFaceIdx, - const FluxVariables &boundaryVars) - { - const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx); - - if (bcTypes.hasOutflow()) - { - PrimaryVariables values(0.0); - - asImp_()->computeFlux(values, boundaryFaceIdx, /*onBoundary=*/true); - Valgrind::CheckDefined(values); - - for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) - { - if (!bcTypes.isOutflow(eqIdx) ) - continue; - // do not calculate outflow for the mass balance - // if the momentum balance is dirichlet - - // it is replaced in that case - if (eqIdx==massBalanceIdx && momentumBalanceDirichlet_(bcTypes)) - continue; - // deduce outflow - this->residual_[scvIdx][eqIdx] += values[eqIdx]; - } - - // beta-stabilization at the boundary in case of outflow condition - // for the momentum balance - if(momentumBalanceOutflow_(bcTypes) && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationBeta_, 0.0, 1.0e-30)) - { - // calculate mu grad v t t for beta-stabilization - // center in the face of the reference element - DimVector tangent; - const DimVector& elementUnitNormal = isIt->centerUnitOuterNormal(); - tangent[0] = elementUnitNormal[1]; - tangent[1] = -elementUnitNormal[0]; - - Dune::FieldMatrix<Scalar, dim, dim> velGrad = boundaryVars.velocityGrad(); - if (enableUnsymmetrizedVelocityGradient) - { - // nothing has to be done in this case: - // grad v - } - else - { - // compute symmetrized gradient for the momentum flux: - // mu (grad v + (grad v)^t) - for (int i=0; i<dim; ++i) - for (int j=0; j<dim; ++j) - velGrad[i][j] += boundaryVars.velocityGrad()[j][i]; - } - - DimVector muGradVelTangential(0.0); - velGrad.umv(tangent, muGradVelTangential); - muGradVelTangential *= boundaryVars.dynamicViscosity() + boundaryVars.dynamicEddyViscosity(); - - this->residual_[scvIdx][massBalanceIdx] -= 0.5*stabilizationBeta_ - * (muGradVelTangential*tangent); - } - } - } - - /*! - * \brief Remove the alpha stabilization at boundaries. - */ - void removeStabilizationAtBoundary_(const int scvIdx) - { - if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(stabilizationAlpha_, 0.0, 1.0e-30)) - { - // loop over the edges of the element - for (int fIdx = 0; fIdx < this->fvGeometry_().numScvf; fIdx++) - { - const FluxVariables fluxVars(this->problem_(), - this->element_(), - this->fvGeometry_(), - fIdx, - this->curVolVars_()); - - const int i = this->fvGeometry_().subContVolFace[fIdx].i; - const int j = this->fvGeometry_().subContVolFace[fIdx].j; - - if (i != scvIdx && j != scvIdx) - continue; - - const Scalar alphaH2 = stabilizationAlpha_* - fluxVars.averageSCVVolume(); - Scalar stabilizationTerm = fluxVars.pressureGrad() * - this->fvGeometry_().subContVolFace[fIdx].normal; - - stabilizationTerm *= alphaH2; - - if (scvIdx == i) - this->residual_[i][massBalanceIdx] += stabilizationTerm; - if (scvIdx == j) - this->residual_[j][massBalanceIdx] -= stabilizationTerm; - } - - //destabilize source term - PrimaryVariables source(0.0); - this->problem_().solDependentSource(source, - this->element_(), - this->fvGeometry_(), - scvIdx, - this->curVolVars_()); - const Scalar alphaH2 = stabilizationAlpha_ * this->fvGeometry_().subContVol[scvIdx].volume; - this->residual_[scvIdx][massBalanceIdx] += alphaH2 * source[massBalanceIdx] * - this->fvGeometry_().subContVol[scvIdx].volume; - } - } - - /*! - * \brief Interpolate the pressure at corner points of the grid, thus taking the degree of freedom there. - * This is required due to stability reasons. - */ - void interpolateCornerPoints_(const BoundaryTypes &bcTypes, const int scvIdx) - { - if (dim == 3) - DUNE_THROW(Dune::NotImplemented, "The function interpolateCornerPoints_() is only implemented for 2D."); - - if (bcTypes.isCoupling(massBalanceIdx)) - { - if (scvIdx == 0 || scvIdx == 3) - this->residual_[scvIdx][massBalanceIdx] = - this->curPriVars_(0)[pressureIdx] - this->curPriVars_(3)[pressureIdx]; - if (scvIdx == 1 || scvIdx == 2) - this->residual_[scvIdx][massBalanceIdx] = - this->curPriVars_(1)[pressureIdx] - this->curPriVars_(2)[pressureIdx]; - } - else - { - if (!bcTypes.isDirichlet(massBalanceIdx)) // do nothing in case of dirichlet - this->residual_[scvIdx][massBalanceIdx] = - this->curPriVars_(0)[pressureIdx] + this->curPriVars_(3)[pressureIdx]- - this->curPriVars_(1)[pressureIdx] - this->curPriVars_(2)[pressureIdx]; - } - } - - /*! - * \brief Replace the local residual of the mass balance equation by - * the sum of the residuals of the momentum balance equation. - */ - void replaceMassbalanceResidual_(const DimVector& momentumResidual, - DimVector& averagedNormal, - const int scvIdx) - { - assert( (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(averagedNormal.two_norm(), 0.0, 1.0e-30)) ); - - // divide averagedNormal by its length - averagedNormal /= averagedNormal.two_norm(); - // replace the mass balance by the sum of the residuals of the momentum balances - this->residual_[scvIdx][massBalanceIdx] = momentumResidual*averagedNormal; - } - - /*! - * \brief Returns true, if all boundary conditions for the momentum balance - * at the considered vertex are Dirichlet. - */ - bool momentumBalanceDirichlet_(const BoundaryTypes& bcTypes) const - { - for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) - if (!bcTypes.isDirichlet(momentumIdx)) - return false; - return true; - } - - /*! - * \brief Returns true, if at least one boundary condition of the momentum balance is Neumann. - */ - bool momentumBalanceHasNeumann_(const BoundaryTypes& bcTypes) const - { - for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) - if (bcTypes.isNeumann(momentumIdx)) - return true; - return false; - } - - /*! - * \brief Returns true, if all boundary conditions for the momentum balance are outflow. - */ - bool momentumBalanceOutflow_(const BoundaryTypes& bcTypes) const - { - for (int momentumIdx=momentumXIdx; momentumIdx<=lastMomentumIdx; ++momentumIdx) - if (!bcTypes.isOutflow(momentumIdx)) - return false; - return true; - } - - Scalar massUpwindWeight_; - Scalar stabilizationAlpha_; - Scalar stabilizationBeta_; - - Implementation *asImp_() - { return static_cast<Implementation *>(this); } - const Implementation *asImp_() const - { return static_cast<const Implementation *>(this); } -}; - -} +#include <dumux/freeflow/stokes/localresidual.hh> #endif diff --git a/dumux/freeflow/stokes/stokesmodel.hh b/dumux/freeflow/stokes/stokesmodel.hh index d916d24a4b5ae33c963c43984fc51c2efaa6082a..cea3289d1892726bfb287f228454b886c1da4831 100644 --- a/dumux/freeflow/stokes/stokesmodel.hh +++ b/dumux/freeflow/stokes/stokesmodel.hh @@ -1,201 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -#ifndef DUMUX_STOKES_MODEL_HH -#define DUMUX_STOKES_MODEL_HH +#ifndef DUMUX_STOKES_MODEL_HH_OLD +#define DUMUX_STOKES_MODEL_HH_OLD -/*! - * \file - * \brief Base class for all models which use the Stokes box model. - */ +#warning this header is deprecated, use dumux/freeflow/stokes/model.hh instead -#include <dumux/implicit/model.hh> - -#include "stokeslocalresidual.hh" -#include "stokesnewtoncontroller.hh" -#include "stokeslocaljacobian.hh" -#include "stokesproblem.hh" -#include "stokesproperties.hh" - -namespace Dumux -{ -/*! - * \ingroup BoxStokesModel - * \brief Adaption of the box scheme to the Stokes model. - * - * This model implements laminar Stokes flow of a single fluid, solving the momentum balance equation - * \f[ - * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} - * + \text{div} \left( p_g {\bf {I}} - * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g - * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) - * - \varrho_g {\bf g} = 0 - * \f] - * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes - * equation can be solved. In this case an additional term - * \f[ - * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) - * \f] - * is added to the momentum balance equation. - * - * The mass balance equation: - * \f[ - * \frac{\partial \varrho_g}{\partial t} - * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 - * \f] - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class StokesModel : public GET_PROP_TYPE(TypeTag, BaseModel) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - enum { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld - }; - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - -public: - /*! - * \brief Calculate the fluxes across a certain layer in the domain. - * The layer is situated perpendicular to the coordinate axis "coord" and cuts - * the axis at the value "coordVal". - * - * \param globalSol The global solution vector - * \param flux A vector to store the flux - * \param axis The dimension, perpendicular to which the layer is situated - * \param coordVal The (Scalar) coordinate on the axis, at which the layer is situated - */ - void calculateFluxAcrossLayer(const SolutionVector &globalSol, Dune::FieldVector<Scalar, numEq> &flux, int axis, Scalar coordVal) - { - GlobalPosition globalI, globalJ; - PrimaryVariables tmpFlux(0.0); - - FVElementGeometry fvGeometry; - ElementVolumeVariables elemVolVars; - - // Loop over elements - for (const auto& element : Dune::elements(this->problem_.gridView())) - { - if (element.partitionType() != Dune::InteriorEntity) - continue; - - fvGeometry.update(this->gridView_(), element); - elemVolVars.update(this->problem_(), element, fvGeometry); - this->localResidual().evalFluxes(element, elemVolVars); - - bool hasLeft = false; - bool hasRight = false; - for (int i = 0; i < fvGeometry.numScv; i++) { - const GlobalPosition &globalPos = fvGeometry.subContVol[i].global; - if (globalI[axis] < coordVal) - hasLeft = true; - else if (globalI[axis] >= coordVal) - hasRight = true; - } - if (!hasLeft || !hasRight) - continue; - - for (int i = 0; i < fvGeometry.numScv; i++) { - const GlobalPosition &globalPos = fvGeometry.subContVol[i].global; - if (globalI[axis] < coordVal) - flux += this->localResidual().residual(i); - } - } - - flux = this->problem_.gridView().comm().sum(flux); - } - - //! \copydoc ImplicitModel::addOutputVtkFields - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - ScalarField &pn = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - - unsigned numElements = this->gridView_().size(0); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - - FVElementGeometry fvGeometry; - VolumeVariables volVars; - ElementBoundaryTypes elemBcTypes; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int eIdx = this->elementMapper().index(element); - - rank[eIdx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element); - - int numLocalVerts = element.subEntities(dim); - - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pn[vIdxGlobal] = volVars.pressure(); - delP[vIdxGlobal] = volVars.pressure() - 1e5; - rho[vIdxGlobal] = volVars.density(); - mu[vIdxGlobal] = volVars.dynamicViscosity(); - velocity[vIdxGlobal] = volVars.velocity(); - } - } - writer.attachVertexData(pn, "P"); - writer.attachVertexData(delP, "delP"); - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(velocity, "v", dim); - } -}; -} - -#include "stokespropertydefaults.hh" +#include <dumux/freeflow/stokes/model.hh> #endif diff --git a/dumux/freeflow/stokes/stokesnewtoncontroller.hh b/dumux/freeflow/stokes/stokesnewtoncontroller.hh index 8e98c6181e0762866ee306e8ff8dba9d15113357..dfd34f474fa1f8af65256fd8ecf37c78e6ab392d 100644 --- a/dumux/freeflow/stokes/stokesnewtoncontroller.hh +++ b/dumux/freeflow/stokes/stokesnewtoncontroller.hh @@ -1,50 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief A Stokes specific controller for the newton solver. - */ -#ifndef DUMUX_STOKES_NEWTON_CONTROLLER_HH -#define DUMUX_STOKES_NEWTON_CONTROLLER_HH +#ifndef DUMUX_STOKES_NEWTON_CONTROLLER_HH_OLD +#define DUMUX_STOKES_NEWTON_CONTROLLER_HH_OLD -#include <dumux/nonlinear/newtoncontroller.hh> +#warning this header is deprecated, use dumux/freeflow/stokes/newtoncontroller.hh instead -namespace Dumux { -/*! - * \ingroup BoxStokesModel - * \ingroup Newton - * \brief A Stokes-specific controller for the nonlinear Newton solver, which sets - * different parameters for the relative tolerance, target steps and maximum steps. - */ -template <class TypeTag> -class StokesNewtonController : public NewtonController<TypeTag> -{ - typedef NewtonController<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - -public: - StokesNewtonController(const Problem &problem) - : ParentType(problem) - { - Dune::FMatrixPrecision<>::set_singular_limit(1e-35); - } -}; -} // end namespace Dumux +#include <dumux/freeflow/stokes/newtoncontroller.hh> #endif diff --git a/dumux/freeflow/stokes/stokesproblem.hh b/dumux/freeflow/stokes/stokesproblem.hh index 143a47dd0c73bb583f33fba767bef05330097031..a0aab07e5a212312219a1bfd9c062602658e4fd4 100644 --- a/dumux/freeflow/stokes/stokesproblem.hh +++ b/dumux/freeflow/stokes/stokesproblem.hh @@ -1,135 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Base class for all stokes problems which use the box scheme. - */ -#ifndef DUMUX_STOKES_PROBLEM_HH -#define DUMUX_STOKES_PROBLEM_HH +#ifndef DUMUX_STOKES_PROBLEM_HH_OLD +#define DUMUX_STOKES_PROBLEM_HH_OLD -#include <dumux/implicit/problem.hh> +#warning this header is deprecated, use dumux/freeflow/stokes/problem.hh instead -#include "stokesproperties.hh" - -namespace Dumux -{ -/*! - * \ingroup ImplicitBaseProblems - * \ingroup BoxStokesModel - * \brief Base class for all problems which use the Stokes box model. - * - * This implements gravity (if desired) and a function returning the temperature. - */ -template<class TypeTag> -class StokesProblem : public ImplicitProblem<TypeTag> -{ - typedef ImplicitProblem<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation; - - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; - typedef typename GridView::Grid Grid; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GridView::Intersection Intersection; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - - enum { - dim = Grid::dimension, - dimWorld = Grid::dimensionworld - }; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - -public: - StokesProblem(TimeManager &timeManager, const GridView &gridView) - : ParentType(timeManager, gridView), - gravity_(0) - { - if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) - gravity_[dim-1] = -9.81; - } - - /*! - * \name Problem parameters - */ - // \{ - - - /*! - * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position. - * - * This is not specific to the discretization. By default it just - * calls temperature(). - * - * \param globalPos The position in global coordinates where the temperature should be specified. - */ - Scalar temperatureAtPos(const GlobalPosition &globalPos) const - { return asImp_().temperature(); } - - /*! - * \brief Returns the temperature within the domain. - * - * This method MUST be overwritten by the actual problem. - */ - Scalar temperature() const - { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); } - - /*! - * \brief Returns the acceleration due to gravity. - * - * If the <tt>EnableGravity</tt> property is true, this means - * \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$, else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$ - */ - const GlobalPosition &gravity() const - { return gravity_; } - - /*! - * \brief Evaluate the intrinsic permeability - * at the corner of a given element - * - * \return (Scalar) permeability - */ - DUNE_DEPRECATED_MSG("permeability() is deprecated.") - Scalar permeability(const Element &element, - const FVElementGeometry &fvGeometry, - const Intersection &intersection, - const int scvIdx, - const int boundaryFaceIdx) const - { DUNE_THROW(Dune::NotImplemented, "permeability()"); } - - // \} - -private: - //! Returns the implementation of the problem (i.e. static polymorphism) - Implementation &asImp_() - { return *static_cast<Implementation *>(this); } - - //! \copydoc asImp_() - const Implementation &asImp_() const - { return *static_cast<const Implementation *>(this); } - - GlobalPosition gravity_; -}; - -} +#include <dumux/freeflow/stokes/problem.hh> #endif diff --git a/dumux/freeflow/stokes/stokesproperties.hh b/dumux/freeflow/stokes/stokesproperties.hh index 14471f6608abcc25d30d55e521bf2f4ac9a67788..b72c13fdc7f5a80899d01575eae633757474ff82 100644 --- a/dumux/freeflow/stokes/stokesproperties.hh +++ b/dumux/freeflow/stokes/stokesproperties.hh @@ -1,68 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesModel - * - * \file - * - * \brief Defines the properties required for the Stokes box model. - */ +#ifndef DUMUX_STOKESPROPERTIES_HH_OLD +#define DUMUX_STOKESPROPERTIES_HH_OLD -#ifndef DUMUX_STOKESPROPERTIES_HH -#define DUMUX_STOKESPROPERTIES_HH +#warning this header is deprecated, use dumux/freeflow/stokes/properties.hh instead -#include <dumux/implicit/box/properties.hh> - -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tag for the stokes problems -NEW_TYPE_TAG(BoxStokes, INHERITS_FROM(BoxModel)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// - -NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem -NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the upwind parameter for the mobility -NEW_PROP_TAG(Indices); //!< Enumerations for the model -NEW_PROP_TAG(Fluid); -NEW_PROP_TAG(FluidSystem); //!< The employed fluid system -NEW_PROP_TAG(FluidState); -NEW_PROP_TAG(StokesStabilizationAlpha); //!< The parameter for the stabilization -NEW_PROP_TAG(StokesStabilizationBeta); //!< The parameter for the stabilization at boundaries -NEW_PROP_TAG(EnableUnsymmetrizedVelocityGradient); //!< Returns whether unsymmetrized velocity gradient for viscous term is used -NEW_PROP_TAG(EnableNavierStokes); //!< Returns whether Navier-Stokes should be solved instead of plain Stokes -NEW_PROP_TAG(UseMoles); //!< Defines whether molar (true) or mass (false) density is used - -NEW_PROP_TAG(PhaseIdx); //!< A phase index in case that a two-phase fluidsystem is used -NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters -NEW_PROP_TAG(Scaling); //!<Defines Scaling of the model -} -} +#include <dumux/freeflow/stokes/properties.hh> #endif diff --git a/dumux/freeflow/stokes/stokespropertydefaults.hh b/dumux/freeflow/stokes/stokespropertydefaults.hh index bbd7e996bacf9748f2c48b1c981131544981fa5e..0ec5813ac959b732704d852154f87091e7a23fd7 100644 --- a/dumux/freeflow/stokes/stokespropertydefaults.hh +++ b/dumux/freeflow/stokes/stokespropertydefaults.hh @@ -1,165 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesModel - * - * \file - * - * \brief Defines default properties for the Stokes box model. - * - * These can be overwritten at a different place or - * may be replaced by values of the input file. - */ +#ifndef DUMUX_STOKES_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_STOKES_PROPERTY_DEFAULTS_HH_OLD -#ifndef DUMUX_STOKES_PROPERTY_DEFAULTS_HH -#define DUMUX_STOKES_PROPERTY_DEFAULTS_HH +#warning this header is deprecated, use dumux/freeflow/stokes/propertydefaults.hh instead -#include "stokesproperties.hh" -#include "stokesindices.hh" -#include "stokeslocaljacobian.hh" -#include "stokeslocalresidual.hh" -#include "stokesmodel.hh" -#include "stokesvolumevariables.hh" -#include "stokesfluxvariables.hh" -#include "stokesnewtoncontroller.hh" - -#include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/material/fluidsystems/liquidphase.hh> -#include <dumux/material/components/nullcomponent.hh> - -#include <dumux/material/fluidsystems/1pfluidsystem.hh> -#include <dumux/material/fluidstates/immisciblefluidstate.hh> - -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -//! The local jacobian operator for the stokes box scheme -SET_TYPE_PROP(BoxStokes, LocalJacobian, Dumux::StokesLocalJacobian<TypeTag>); - -SET_PROP(BoxStokes, NumEq) //!< set the number of equations -{ - typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; - static const int dim = Grid::dimension; - public: - static constexpr int value = 1 + dim; -}; - -SET_SCALAR_PROP(BoxStokes, Scaling, 1); //!< set scaling to 1 by default - -//! Use the Stokes local residual function for the Stokes model -SET_TYPE_PROP(BoxStokes, LocalResidual, StokesLocalResidual<TypeTag>); - -//! Use the Stokes specific newton controller for the Stokes model -SET_TYPE_PROP(BoxStokes, NewtonController, StokesNewtonController<TypeTag>); - -#if HAVE_SUPERLU -SET_TYPE_PROP(BoxStokes, LinearSolver, SuperLUBackend<TypeTag>); -#elif HAVE_UMFPACK -SET_TYPE_PROP(BoxStokes, LinearSolver, UMFPackBackend<TypeTag>); -#endif - -//! the Model property -SET_TYPE_PROP(BoxStokes, Model, StokesModel<TypeTag>); - -//! the VolumeVariables property -SET_TYPE_PROP(BoxStokes, VolumeVariables, StokesVolumeVariables<TypeTag>); - -//! the FluxVariables property -SET_TYPE_PROP(BoxStokes, FluxVariables, StokesFluxVariables<TypeTag>); - -//! the upwind factor. -SET_SCALAR_PROP(BoxStokes, ImplicitMassUpwindWeight, 1.0); - -//! The fluid system to use by default -SET_PROP(BoxStokes, FluidSystem) -{ private: - typedef typename GET_PROP_TYPE(TypeTag, Fluid) Fluid; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; -public: - typedef FluidSystems::OneP<Scalar, Fluid> type; -}; - -//! The fluid that is used in the single-phase fluidsystem -SET_PROP(BoxStokes, Fluid) -{ private: - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; -public: - typedef Dumux::LiquidPhase<Scalar, Dumux::NullComponent<Scalar> > type; -}; - -//! Set the indices used by the Stokes model -SET_TYPE_PROP(BoxStokes, Indices, StokesCommonIndices<TypeTag>); - -//! Choose the type of the employed fluid state. -SET_PROP(BoxStokes, FluidState) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; -public: - typedef Dumux::ImmiscibleFluidState<Scalar, FluidSystem> type; - -}; - -//! Enable evaluation of shape function gradients at the sub-control volume center by default -// Used for the computation of the pressure gradients -SET_BOOL_PROP(BoxStokes, EvalGradientsAtSCVCenter, true); - -//! Set the phaseIndex per default to zero (for two-phase or two-component system imported -// from fluid systems, see property defaults in stokesnc model). -SET_INT_PROP(BoxStokes, PhaseIdx, 0); - -//! Use symmetrizedVelocityGradient by default -SET_BOOL_PROP(BoxStokes, EnableUnsymmetrizedVelocityGradient, false); - -//! Set calculation to Stokes, not Navier-Stokes -SET_BOOL_PROP(BoxStokes, EnableNavierStokes, false); - -//! The mass density is used in the continuity equation -SET_BOOL_PROP(BoxStokes, UseMoles, false); - -//! A stabilization factor. Set negative for stabilization and to zero for no stabilization -SET_SCALAR_PROP(BoxStokes, StokesStabilizationAlpha, 0.0); - -//! Stabilization factor for the boundaries -SET_SCALAR_PROP(BoxStokes, StokesStabilizationBeta, 0.0); - -//! Set gravity by default -SET_BOOL_PROP(BoxStokes, ProblemEnableGravity, true); - -//! Set the value for the maximum relative shift -SET_SCALAR_PROP(BoxStokes, NewtonMaxRelativeShift, 1e-6); - -//! Set the number of iterations at which the Newton method should aim at. -SET_INT_PROP(BoxStokes, NewtonTargetSteps, 10); - -//! Set the number of maximum iterations for the Newton method. -SET_INT_PROP(BoxStokes, NewtonMaxSteps, 18); -} - -} +#include <dumux/freeflow/stokes/propertydefaults.hh> #endif diff --git a/dumux/freeflow/stokes/stokesvolumevariables.hh b/dumux/freeflow/stokes/stokesvolumevariables.hh index 4c1caef58ef4f4da70a6da4f6e3c8a90d37921cd..8e03da9dbceca260f0107bce81190cfd9be337e6 100644 --- a/dumux/freeflow/stokes/stokesvolumevariables.hh +++ b/dumux/freeflow/stokes/stokesvolumevariables.hh @@ -1,224 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Contains the quantities which are constant within a - * finite volume in the Stokes box model. - */ -#ifndef DUMUX_STOKES_VOLUME_VARIABLES_HH -#define DUMUX_STOKES_VOLUME_VARIABLES_HH +#ifndef DUMUX_STOKES_VOLUME_VARIABLES_HH_OLD +#define DUMUX_STOKES_VOLUME_VARIABLES_HH_OLD -#include "stokesproperties.hh" +#warning this header is deprecated, use dumux/freeflow/stokes/volumevariables.hh instead -#include <dumux/implicit/volumevariables.hh> -#include <dumux/material/fluidstates/immisciblefluidstate.hh> - -namespace Dumux -{ - -/*! - * \ingroup BoxStokesModel - * \ingroup ImplicitVolumeVariables - * \brief Contains the quantities which are constant within a - * finite volume in the Stokes box model. - */ -template <class TypeTag> -class StokesVolumeVariables : public ImplicitVolumeVariables<TypeTag> -{ - typedef ImplicitVolumeVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - momentumXIdx = Indices::momentumXIdx, - lastMomentumIdx = Indices::lastMomentumIdx, - pressureIdx = Indices::pressureIdx - }; - - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - -public: - /*! - * \copydoc ImplicitVolumeVariables::update() - */ - void update(const PrimaryVariables &priVars, - const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx, - const bool isOldSol) - { - ParentType::update(priVars, - problem, - element, - fvGeometry, - scvIdx, - isOldSol); - - completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_, isOldSol); - - globalPos_ = fvGeometry.subContVol[scvIdx].global; - for (int dimIdx=momentumXIdx; dimIdx<=lastMomentumIdx; ++dimIdx) - velocity_[dimIdx] = priVars[dimIdx]; - } - - /*! - * \copydoc ImplicitModel::completeFluidState() - * \param isOldSol Specifies whether this is the previous solution or the current one - */ - static void completeFluidState(const PrimaryVariables& priVars, - const Problem& problem, - const Element& element, - const FVElementGeometry& fvGeometry, - const int scvIdx, - FluidState& fluidState, - const bool isOldSol = false) - { - Scalar temperature = Implementation::temperature_(priVars, problem, - element, fvGeometry, scvIdx); - fluidState.setTemperature(temperature); - fluidState.setPressure(phaseIdx, priVars[pressureIdx]); - - // create NullParameterCache and do dummy update - typename FluidSystem::ParameterCache paramCache; - paramCache.updateAll(fluidState); - - fluidState.setDensity(phaseIdx, - FluidSystem::density(fluidState, - paramCache, - phaseIdx)); - fluidState.setViscosity(phaseIdx, - FluidSystem::viscosity(fluidState, - paramCache, - phaseIdx)); - - // compute and set the enthalpy - Scalar h = Implementation::enthalpy_(fluidState, paramCache, phaseIdx); - fluidState.setEnthalpy(phaseIdx, h); - } - - /*! - * \brief Returns the phase state for the control-volume. - */ - const FluidState &fluidState() const - { return fluidState_; } - FluidState &fluidState() - { return fluidState_; } - - /*! - * \brief Returns the global position for the control-volume. - */ - const GlobalPosition globalPos() const - { return globalPos_; } - - /*! - * \brief Returns the mass density \f$\mathrm{[kg/m^3]}\f$ of the fluid within the - * sub-control volume. - */ - Scalar density() const - { return fluidState_.density(phaseIdx); } - - /*! - * \brief Returns the molar density \f$\mathrm{[mol/m^3]}\f$ of the fluid within the - * sub-control volume. - */ - Scalar molarDensity() const - { return this->fluidState_.density(phaseIdx) / this->fluidState_.averageMolarMass(phaseIdx); } - - /*! - * \brief Returns the fluid pressure \f$\mathrm{[Pa]}\f$ within - * the sub-control volume. - */ - Scalar pressure() const - { return fluidState_.pressure(phaseIdx); } - - /*! - * \brief Returns temperature\f$\mathrm{[T]}\f$ inside the sub-control volume. - */ - Scalar temperature() const - { return fluidState_.temperature(phaseIdx); } - - /*! - * \brief Returns the dynamic viscosity \f$ \mathrm{[Pa s]} \f$ of the fluid in - * the sub-control volume. - */ - Scalar dynamicViscosity() const - { return fluidState_.viscosity(phaseIdx); } - - /*! - * \brief Returns the kinematic viscosity \f$ \frac{m^2}{s} \f$ of the fluid in - * the sub-control volume. - */ - Scalar kinematicViscosity() const - { return fluidState_.viscosity(phaseIdx) / fluidState_.density(phaseIdx); } - - /*! - * \brief Returns the velocity vector in the sub-control volume. - */ - const DimVector &velocity() const - { return velocity_; } - -protected: - template<class ParameterCache> - static Scalar enthalpy_(const FluidState& fluidState, - const ParameterCache& paramCache, - int phaseIdx) - { - return 0; - } - - static Scalar temperature_(const PrimaryVariables &priVars, - const Problem& problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx) - { - return problem.temperatureAtPos(fvGeometry.subContVol[scvIdx].global); - } - - DimVector velocity_; - GlobalPosition globalPos_; - FluidState fluidState_; - -private: - Implementation &asImp() - { return *static_cast<Implementation*>(this); } - const Implementation &asImp() const - { return *static_cast<const Implementation*>(this); } -}; - -} +#include <dumux/freeflow/stokes/volumevariables.hh> #endif diff --git a/dumux/freeflow/stokes/volumevariables.hh b/dumux/freeflow/stokes/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..cfd9290caaedbd5b19eb3035bd21bc36dc8a09c2 --- /dev/null +++ b/dumux/freeflow/stokes/volumevariables.hh @@ -0,0 +1,224 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Contains the quantities which are constant within a + * finite volume in the Stokes box model. + */ +#ifndef DUMUX_STOKES_VOLUME_VARIABLES_HH +#define DUMUX_STOKES_VOLUME_VARIABLES_HH + +#include "properties.hh" + +#include <dumux/implicit/volumevariables.hh> +#include <dumux/material/fluidstates/immisciblefluidstate.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesModel + * \ingroup ImplicitVolumeVariables + * \brief Contains the quantities which are constant within a + * finite volume in the Stokes box model. + */ +template <class TypeTag> +class StokesVolumeVariables : public ImplicitVolumeVariables<TypeTag> +{ + typedef ImplicitVolumeVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + momentumXIdx = Indices::momentumXIdx, + lastMomentumIdx = Indices::lastMomentumIdx, + pressureIdx = Indices::pressureIdx + }; + + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + +public: + /*! + * \copydoc ImplicitVolumeVariables::update() + */ + void update(const PrimaryVariables &priVars, + const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int scvIdx, + const bool isOldSol) + { + ParentType::update(priVars, + problem, + element, + fvGeometry, + scvIdx, + isOldSol); + + completeFluidState(priVars, problem, element, fvGeometry, scvIdx, fluidState_, isOldSol); + + globalPos_ = fvGeometry.subContVol[scvIdx].global; + for (int dimIdx=momentumXIdx; dimIdx<=lastMomentumIdx; ++dimIdx) + velocity_[dimIdx] = priVars[dimIdx]; + } + + /*! + * \copydoc ImplicitModel::completeFluidState() + * \param isOldSol Specifies whether this is the previous solution or the current one + */ + static void completeFluidState(const PrimaryVariables& priVars, + const Problem& problem, + const Element& element, + const FVElementGeometry& fvGeometry, + const int scvIdx, + FluidState& fluidState, + const bool isOldSol = false) + { + Scalar temperature = Implementation::temperature_(priVars, problem, + element, fvGeometry, scvIdx); + fluidState.setTemperature(temperature); + fluidState.setPressure(phaseIdx, priVars[pressureIdx]); + + // create NullParameterCache and do dummy update + typename FluidSystem::ParameterCache paramCache; + paramCache.updateAll(fluidState); + + fluidState.setDensity(phaseIdx, + FluidSystem::density(fluidState, + paramCache, + phaseIdx)); + fluidState.setViscosity(phaseIdx, + FluidSystem::viscosity(fluidState, + paramCache, + phaseIdx)); + + // compute and set the enthalpy + Scalar h = Implementation::enthalpy_(fluidState, paramCache, phaseIdx); + fluidState.setEnthalpy(phaseIdx, h); + } + + /*! + * \brief Returns the phase state for the control-volume. + */ + const FluidState &fluidState() const + { return fluidState_; } + FluidState &fluidState() + { return fluidState_; } + + /*! + * \brief Returns the global position for the control-volume. + */ + const GlobalPosition globalPos() const + { return globalPos_; } + + /*! + * \brief Returns the mass density \f$\mathrm{[kg/m^3]}\f$ of the fluid within the + * sub-control volume. + */ + Scalar density() const + { return fluidState_.density(phaseIdx); } + + /*! + * \brief Returns the molar density \f$\mathrm{[mol/m^3]}\f$ of the fluid within the + * sub-control volume. + */ + Scalar molarDensity() const + { return this->fluidState_.density(phaseIdx) / this->fluidState_.averageMolarMass(phaseIdx); } + + /*! + * \brief Returns the fluid pressure \f$\mathrm{[Pa]}\f$ within + * the sub-control volume. + */ + Scalar pressure() const + { return fluidState_.pressure(phaseIdx); } + + /*! + * \brief Returns temperature\f$\mathrm{[T]}\f$ inside the sub-control volume. + */ + Scalar temperature() const + { return fluidState_.temperature(phaseIdx); } + + /*! + * \brief Returns the dynamic viscosity \f$ \mathrm{[Pa s]} \f$ of the fluid in + * the sub-control volume. + */ + Scalar dynamicViscosity() const + { return fluidState_.viscosity(phaseIdx); } + + /*! + * \brief Returns the kinematic viscosity \f$ \frac{m^2}{s} \f$ of the fluid in + * the sub-control volume. + */ + Scalar kinematicViscosity() const + { return fluidState_.viscosity(phaseIdx) / fluidState_.density(phaseIdx); } + + /*! + * \brief Returns the velocity vector in the sub-control volume. + */ + const DimVector &velocity() const + { return velocity_; } + +protected: + template<class ParameterCache> + static Scalar enthalpy_(const FluidState& fluidState, + const ParameterCache& paramCache, + int phaseIdx) + { + return 0; + } + + static Scalar temperature_(const PrimaryVariables &priVars, + const Problem& problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int scvIdx) + { + return problem.temperatureAtPos(fvGeometry.subContVol[scvIdx].global); + } + + DimVector velocity_; + GlobalPosition globalPos_; + FluidState fluidState_; + +private: + Implementation &asImp() + { return *static_cast<Implementation*>(this); } + const Implementation &asImp() const + { return *static_cast<const Implementation*>(this); } +}; + +} + +#endif diff --git a/dumux/freeflow/stokesnc/fluxvariables.hh b/dumux/freeflow/stokesnc/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..1086386313eed04cc4ac34159d10c19bb736efb1 --- /dev/null +++ b/dumux/freeflow/stokesnc/fluxvariables.hh @@ -0,0 +1,178 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief This file contains the data which is required to calculate the + * component fluxes over a face of a finite volume. + * + * This means concentration gradients, diffusion coefficients, mass fractions, etc. + * at the integration point. + */ +#ifndef DUMUX_STOKESNC_FLUX_VARIABLES_HH +#define DUMUX_STOKESNC_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/freeflow/stokes/fluxvariables.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesncModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains data which is required to + * calculate the component fluxes over a face of a finite + * volume for the compositional n component Stokes model. + * + * This means concentration gradients, diffusion coefficient, mass fractions, etc. + * at the integration point of a SCV or boundary face. + */ +template <class TypeTag> +class StokesncFluxVariables : public StokesFluxVariables<TypeTag> +{ + typedef StokesFluxVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + //dimensions + enum { dim = GridView::dimension }; + //phase indices + enum { phaseIdx = Indices::phaseIdx }; + //component indices + enum { phaseCompIdx = Indices::phaseCompIdx, + transportCompIdx = Indices::transportCompIdx }; + //number of components + enum { numComponents = Indices::numComponents }; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix; + +public: + //Constructor calls ParentType function + StokesncFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) + { + calculateValues_(problem, element, elemVolVars); + } + + /*! + * \brief Return the molar density \f$ \mathrm{[mol/m^3]} \f$ at the integration point. + */ + const Scalar molarDensity() const + { return molarDensity_; } + + /*! + * \brief Return the mass fraction of a transported component at the integration point. + */ + const Scalar massFraction(int compIdx) const + { return massFraction_[compIdx]; } + + /*! + * \brief Return the mole fraction of a transported component at the integration point. + */ + const Scalar moleFraction(int compIdx) const + { return moleFraction_[compIdx]; } + + /*! + * \brief Return the molar diffusion coefficient of a transported component at the integration point. + */ + const Scalar diffusionCoeff(int compIdx) const + { return diffusionCoeff_[compIdx]; } + + /*! + * \brief Return the gradient of the mole fraction at the integration point. + */ + const DimVector &moleFractionGrad(int compIdx) const + { return moleFractionGrad_[compIdx]; } + + /*! + * \brief Return the eddy diffusivity (if implemented). + */ + const Scalar eddyDiffusivity() const + { return 0; } + +protected: + void calculateValues_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + + // loop over all components + for (int compIdx=0; compIdx<numComponents; compIdx++){ + massFraction_[compIdx] = Scalar(0.0); + moleFraction_[compIdx] = Scalar(0.0); + diffusionCoeff_[compIdx] = Scalar(0.0); + moleFractionGrad_[compIdx] = Scalar(0.0); + + if (phaseCompIdx!=compIdx) //no transport equation parameters needed for the mass balance + { + molarDensity_ = Scalar(0.0); + + // calculate gradients and secondary variables at IPs + for (int scvIdx = 0; + scvIdx < this->fvGeometry_.numScv; + scvIdx++) // loop over vertices of the element + { + + molarDensity_ += elemVolVars[scvIdx].molarDensity()* + this->face().shapeValue[scvIdx]; + massFraction_[compIdx] += elemVolVars[scvIdx].massFraction(compIdx) * + this->face().shapeValue[scvIdx]; + moleFraction_[compIdx] += elemVolVars[scvIdx].moleFraction(compIdx) * + this->face().shapeValue[scvIdx]; + diffusionCoeff_[compIdx] += elemVolVars[scvIdx].diffusionCoeff(compIdx) * + this->face().shapeValue[scvIdx]; + + // the gradient of the mole fraction at the IP + DimVector grad = this->face().grad[scvIdx]; + grad *= elemVolVars[scvIdx].moleFraction(compIdx); + moleFractionGrad_[compIdx] += grad; + } + + Valgrind::CheckDefined(molarDensity_); + Valgrind::CheckDefined(massFraction_[compIdx]); + Valgrind::CheckDefined(moleFraction_[compIdx]); + Valgrind::CheckDefined(diffusionCoeff_[compIdx]); + Valgrind::CheckDefined(moleFractionGrad_[compIdx]); + } + } + } + + Scalar molarDensity_; + Scalar massFraction_[numComponents]; + Scalar moleFraction_[numComponents]; + Scalar diffusionCoeff_[numComponents]; + DimVector moleFractionGrad_[numComponents]; +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/stokesnc/indices.hh b/dumux/freeflow/stokesnc/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..455179d99db425293ae422227a6ada23b7a99269 --- /dev/null +++ b/dumux/freeflow/stokesnc/indices.hh @@ -0,0 +1,84 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * + * \brief Defines the indices required for the compositional n component Stokes box model. + */ +#ifndef DUMUX_STOKESNC_INDICES_HH +#define DUMUX_STOKESNC_INDICES_HH + +#include "properties.hh" +#include <dumux/freeflow/stokes/indices.hh> + +namespace Dumux +{ +// \{ + +/*! + * \ingroup BoxStokesncModel + * \ingroup ImplicitIndices + * \brief The common indices for the compositional n component Stokes box model. + * + * \tparam PVOffset The first index in a primary variable vector. + */ +template <class TypeTag, int PVOffset = 0> +struct StokesncCommonIndices : public StokesCommonIndices<TypeTag> +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + + // Dimension (copied for convenience) + static const int dim = StokesCommonIndices<TypeTag>::dim; //!< Number of dimensions + + // Phase Index + //! Index of the employed phase in case of a two-phase fluidsystem (set by default to nPhase) + static const int phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx); + + // Number of Components + //! Number of components in employed fluidsystem + static const int numComponents = FluidSystem::numComponents; + + // Component indices + //! The index of the main component of the considered phase + static const int phaseCompIdx = phaseIdx; + //! The index of the first transported component; ASSUMES phase indices of 0 and 1 + static const int transportCompIdx = (unsigned int)(1-phaseIdx); + + // Transport equation indices + //! The index of the mass conservation equation of the first component. In analogy to porous media models "conti" + //! is used here to describe mass conservation equations, i.e total mass balance and transport equations. + static const int conti0EqIdx = PVOffset + dim; + //! The index of the mass balance equation sits on the slot of the employed phase + static const int massBalanceIdx = conti0EqIdx + phaseCompIdx; + //! The index of the transport equation for a two component model. + //! For n>2 please don't use this index, because it looses its actual meaning. + static const int transportEqIdx = conti0EqIdx + transportCompIdx; + + // Primary variables + //! The index of the first mass or mole fraction of the transported component in primary variable vectors + static const int massOrMoleFracIdx = transportEqIdx; + //! The index of the pressure in primary variable vectors + static const int pressureIdx = massBalanceIdx; +}; +} // end namespace + +#endif diff --git a/dumux/freeflow/stokesnc/localresidual.hh b/dumux/freeflow/stokesnc/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..b23474c4a3446aaa03c5ecf6d1082dcb2b86aabe --- /dev/null +++ b/dumux/freeflow/stokesnc/localresidual.hh @@ -0,0 +1,232 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Element-wise calculation of the Jacobian matrix for problems + * using the compositional Stokes box model. + * + */ +#ifndef DUMUX_STOKESNC_LOCAL_RESIDUAL_HH +#define DUMUX_STOKESNC_LOCAL_RESIDUAL_HH + +#include <dumux/freeflow/stokes/localresidual.hh> + +#include "volumevariables.hh" +#include "fluxvariables.hh" + +namespace Dumux +{ +/*! + * \ingroup BoxStokesncModel + * \ingroup ImplicitLocalResidual + * \brief Element-wise calculation of the Jacobian matrix for problems + * using the compositional Stokes box model. This is derived + * from the Stokes box model. + */ +template<class TypeTag> +class StokesncLocalResidual : public StokesLocalResidual<TypeTag> +{ + typedef StokesLocalResidual<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + //dimensions + enum { dim = GridView::dimension }; + //number of equations + enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; + //number of components + enum { numComponents = Indices::numComponents }; + //equation indices + enum { massBalanceIdx = Indices::massBalanceIdx, + momentumXIdx = Indices::momentumXIdx, + lastMomentumIdx = Indices::lastMomentumIdx, + transportEqIdx = Indices::transportEqIdx, + conti0EqIdx = Indices::conti0EqIdx }; + //primary variable indices + enum { pressureIdx = Indices::pressureIdx }; + //phase employed + enum { phaseIdx = Indices::phaseIdx }; + //component indices + enum { phaseCompIdx = Indices::phaseCompIdx, + transportCompIdx = Indices::transportCompIdx }; + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + + typedef Dune::FieldVector<Scalar, dim> DimVector; + + typedef typename GridView::Intersection Intersection; + typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; + + static const bool calculateNavierStokes = GET_PROP_VALUE(TypeTag, EnableNavierStokes); + + //! property that defines whether mole or mass fractions are used + static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + +public: + /*! + * \brief Evaluate the stored amount of quantities additional to the Stokes model + * (transport equations). For using mole fraction also momentum balances and mass balance + * have to be calculated using molar quantities + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub control volume divided by the volume) + * + * \param storage The mass of the component within the sub-control volume + * \param scvIdx The SCV (sub-control-volume) index + * \param usePrevSol Evaluate function with solution of current or previous time step + */ + void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const + { + // compute the storage term for the transport equation + ParentType::computeStorage(storage, scvIdx, usePrevSol); + + // if flag usePrevSol is set, the solution from the previous + // time step is used, otherwise the current solution is + // used. The secondary variables are used accordingly. This + // is required to compute the derivative of the storage term + // using the implicit Euler method. + const ElementVolumeVariables &elemVolVars = usePrevSol ? + this->prevVolVars_() : this->curVolVars_(); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + if (useMoles) + { + // mass balance and transport equations + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (conti0EqIdx+compIdx != massBalanceIdx) + //else // transport equations + { + storage[conti0EqIdx+compIdx] = volVars.molarDensity() + * volVars.moleFraction(compIdx); + + Valgrind::CheckDefined(volVars.molarDensity()); + Valgrind::CheckDefined(volVars.moleFraction(compIdx)); + } + } + } + else + { + /* works for a maximum of two components, for more components + mole fractions must be used (set property UseMoles to true) */ + + //storage of transported component + storage[transportEqIdx] = volVars.density() + * volVars.massFraction(transportCompIdx); + + Valgrind::CheckDefined(volVars.density()); + Valgrind::CheckDefined(volVars.massFraction(transportCompIdx)); + + } + } + + /*! + * \brief Evaluates the advective component (mass) flux + * over a face of a sub-control volume and writes the result in + * the flux vector. + * + * This method is called by compute flux (base class). + * + * \param flux The advective flux over the sub-control-volume face for each component + * \param fluxVars The flux variables at the current SCV/boundary face + */ + void computeAdvectiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // call ParentType function + ParentType::computeAdvectiveFlux(flux,fluxVars); + + // data attached to upstream and the downstream vertices + const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); + const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); + + Scalar tmp = fluxVars.normalVelocity(); + + if(useMoles) + { + //transport equations + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (conti0EqIdx+compIdx != massBalanceIdx) // mass balance is calculated above + { + tmp *= (this->massUpwindWeight_ * up.molarDensity() * up.moleFraction(compIdx) + + (1.-this->massUpwindWeight_) * dn.molarDensity() * dn.moleFraction(compIdx)); + + flux[conti0EqIdx+compIdx] += tmp; + Valgrind::CheckDefined(flux[conti0EqIdx+compIdx]); + } + } + } + else + { + tmp *= (this->massUpwindWeight_ * up.density() * up.massFraction(transportCompIdx) + + (1.-this->massUpwindWeight_) * dn.density() * dn.massFraction(transportCompIdx)); + + flux[transportEqIdx] += tmp; + Valgrind::CheckDefined(flux[transportEqIdx]); + } + } + + /*! + * \brief Adds the diffusive component flux to the flux vector over + * the face of a sub-control volume. + * + * \param flux The diffusive flux over the SCV face or boundary face + * \param fluxVars The flux variables at the current SCV/boundary face + */ + void computeDiffusiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // diffusive component flux + if(useMoles) + { + //loop over secondary components + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (conti0EqIdx+compIdx != massBalanceIdx) + { + flux[conti0EqIdx+compIdx] -= fluxVars.moleFractionGrad(compIdx) + * fluxVars.face().normal + * (fluxVars.diffusionCoeff(compIdx) + fluxVars.eddyDiffusivity()) + * fluxVars.molarDensity(); + Valgrind::CheckDefined(flux[conti0EqIdx+compIdx]); + } + } + } + else + { + flux[transportEqIdx] -= fluxVars.moleFractionGrad(transportCompIdx) + * fluxVars.face().normal + * (fluxVars.diffusionCoeff(transportCompIdx) + fluxVars.eddyDiffusivity()) + * fluxVars.molarDensity() + * FluidSystem::molarMass(transportCompIdx);// Multiplied by molarMass [kg/mol] to convert form [mol/m^3 s] to [kg/m^3 s] + Valgrind::CheckDefined(flux[transportEqIdx]); + } + } +}; + +} + +#endif diff --git a/dumux/freeflow/stokesnc/model.hh b/dumux/freeflow/stokesnc/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..58c6752c184af6f9196d4c23c96fd03b3298abdf --- /dev/null +++ b/dumux/freeflow/stokesnc/model.hh @@ -0,0 +1,201 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Adaption of the box scheme to the n-component Stokes model. + */ +#ifndef DUMUX_STOKESNC_MODEL_HH +#define DUMUX_STOKESNC_MODEL_HH + +#include <dumux/freeflow/stokes/model.hh> + +#include "localresidual.hh" +#include "properties.hh" + +namespace Dumux { +/*! + * \ingroup BoxStokesncModel + * \brief Adaption of the box scheme to the compositional Stokes model. + * + * This model implements an isothermal n-component Stokes flow of a fluid + * solving a momentum balance, a mass balance and conservation equations for \f$n-1\f$ + * components. When using mole fractions naturally the densities represent molar + * densities + * + * The momentum balance: + * \f[ + * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} + * + \text{div} \left( p_g {\bf {I}} + * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g + * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) + * - \varrho_g {\bf g} = 0 + * \f] + * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes + * equation can be solved. In this case an additional term + * \f[ + * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) + * \f] + * is added to the momentum balance equation. + * + * The mass balance equation: + * \f[ + * \frac{\partial \varrho_g}{\partial t} + * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 + * \f] + * + * The component mass balance equations: + * \f[ + * \frac{\partial \left(\varrho_g X_g^\kappa\right)}{\partial t} + * + \text{div} \left( \varrho_g {\boldsymbol{v}}_g X_g^\kappa + * - D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \textbf{grad}\, x_g^\kappa \right) + * - q_g^\kappa = 0 + * \f] + * Please note that, even though it is n-component model, the diffusive + * fluxes are still calculated with binary diffusion. + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class StokesncModel : public StokesModel<TypeTag> +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { dim = GridView::dimension, + transportCompIdx = Indices::transportCompIdx, + phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx), + useMoles = GET_PROP_VALUE(TypeTag, UseMoles), + numComponents = Indices::numComponents + }; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + + +public: + //! \copydoc ImplicitModel::addOutputVtkFields + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; + + const Scalar scale_ = GET_PROP_VALUE(TypeTag, Scaling); + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + ScalarField &pN = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField &T = *writer.allocateManagedBuffer(numVertices); + + ScalarField *moleFraction[numComponents]; + for (int i = 0; i < numComponents; ++i) + moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + ScalarField *massFraction[numComponents]; + for (int i = 0; i < numComponents; ++i) + massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + + unsigned numElements = this->gridView_().size(0); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + + FVElementGeometry fvGeometry; + VolumeVariables volVars; + ElementBoundaryTypes elemBcTypes; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int idx = this->elementMapper().index(element); + + rank[idx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + elemBcTypes.update(this->problem_(), element, fvGeometry); + + int numLocalVerts = element.subEntities(dim); + + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pN[vIdxGlobal] = volVars.pressure()*scale_; + delP[vIdxGlobal] = volVars.pressure()*scale_ - 1e5; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + { + (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); + (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); + Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); + Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); + } + + T [vIdxGlobal] = volVars.temperature(); + + rho[vIdxGlobal] = volVars.density()*scale_*scale_*scale_; + mu[vIdxGlobal] = volVars.dynamicViscosity()*scale_; + velocity[vIdxGlobal] = volVars.velocity(); + velocity[vIdxGlobal] *= 1/scale_; + } + } + writer.attachVertexData(T, "temperature"); + writer.attachVertexData(pN, "P"); + writer.attachVertexData(delP, "delP"); + + for (int j = 0; j < numComponents; ++j) + { + std::ostringstream moleFrac, massFrac; + moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); + + massFrac << "X_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); + } + + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(velocity, "v", dim); + } +}; + +} + +#include "propertydefaults.hh" + +#endif diff --git a/dumux/freeflow/stokesnc/properties.hh b/dumux/freeflow/stokesnc/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..e3be9b6e91408e1837c07b0969860e941f6622cb --- /dev/null +++ b/dumux/freeflow/stokesnc/properties.hh @@ -0,0 +1,49 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesncModel + * + * \file + * + * \brief Defines the supplementary properties required for the compositional + * Stokes box model. + */ +#ifndef DUMUX_STOKESNC_PROPERTIES_HH +#define DUMUX_STOKESNC_PROPERTIES_HH + +#include <dumux/freeflow/stokes/properties.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the compositional Stokes problems +NEW_TYPE_TAG(BoxStokesnc, INHERITS_FROM(BoxStokes)); +} + +} + +#endif diff --git a/dumux/freeflow/stokesnc/propertydefaults.hh b/dumux/freeflow/stokesnc/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..7c8ba0f7facf049cc9a073d26e604569005b1981 --- /dev/null +++ b/dumux/freeflow/stokesnc/propertydefaults.hh @@ -0,0 +1,100 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesncModel + * + * \file + * + * \brief Defines the properties required for the compositional + * Stokes box model. + */ +#ifndef DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH +#define DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH + +#include <dumux/freeflow/stokes/propertydefaults.hh> + +#include "properties.hh" +#include "fluxvariables.hh" +#include "indices.hh" +#include "localresidual.hh" +#include "model.hh" +#include "volumevariables.hh" + +#include <dumux/material/fluidstates/compositionalfluidstate.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +//! Define that mole fractions are used in the balance equations +SET_BOOL_PROP(BoxStokesnc, UseMoles, true); + +//! set the number of equations +SET_PROP(BoxStokesnc, NumEq) +{ + typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + + static const int dim = Grid::dimension; +public: + static constexpr int value = FluidSystem::numComponents + dim; +}; + +//! Use the Stokes nc local residual function for the Stokes model +SET_TYPE_PROP(BoxStokesnc, LocalResidual, StokesncLocalResidual<TypeTag>); + +//! the Model property +SET_TYPE_PROP(BoxStokesnc, Model, StokesncModel<TypeTag>); + +//! the VolumeVariables property +SET_TYPE_PROP(BoxStokesnc, VolumeVariables, StokesncVolumeVariables<TypeTag>); + +//! the FluxVariables property +SET_TYPE_PROP(BoxStokesnc, FluxVariables, StokesncFluxVariables<TypeTag>); + +//! Set the Indices for the Stokes nc model. +SET_TYPE_PROP(BoxStokesnc, Indices, StokesncCommonIndices<TypeTag>); + +//! Choose the type of the employed fluid state +SET_PROP(BoxStokesnc, FluidState) +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; +public: + typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> type; +}; + +//! Choose the considered phase (single-phase system); the gas phase is used +SET_PROP(BoxStokesnc, PhaseIdx) +{ + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; +public: + static constexpr int value = FluidSystem::nPhaseIdx; +}; + +} // namespace Properties +} // namespace Dumux +#endif // DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH diff --git a/dumux/freeflow/stokesnc/stokesncfluxvariables.hh b/dumux/freeflow/stokesnc/stokesncfluxvariables.hh index def0d9efe38afdd8a98e4717822636a3df047995..c524f0da6dfd1db8b23d1e42168feac63571eb0a 100644 --- a/dumux/freeflow/stokesnc/stokesncfluxvariables.hh +++ b/dumux/freeflow/stokesnc/stokesncfluxvariables.hh @@ -1,178 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief This file contains the data which is required to calculate the - * component fluxes over a face of a finite volume. - * - * This means concentration gradients, diffusion coefficients, mass fractions, etc. - * at the integration point. - */ -#ifndef DUMUX_STOKESNC_FLUX_VARIABLES_HH -#define DUMUX_STOKESNC_FLUX_VARIABLES_HH +#ifndef DUMUX_STOKESNC_FLUX_VARIABLES_HH_OLD +#define DUMUX_STOKESNC_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/freeflow/stokes/stokesfluxvariables.hh> +#warning this header is deprecated, use dumux/freeflow/stokesnc/fluxvariables.hh instead -namespace Dumux -{ - -/*! - * \ingroup BoxStokesncModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains data which is required to - * calculate the component fluxes over a face of a finite - * volume for the compositional n component Stokes model. - * - * This means concentration gradients, diffusion coefficient, mass fractions, etc. - * at the integration point of a SCV or boundary face. - */ -template <class TypeTag> -class StokesncFluxVariables : public StokesFluxVariables<TypeTag> -{ - typedef StokesFluxVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - //dimensions - enum { dim = GridView::dimension }; - //phase indices - enum { phaseIdx = Indices::phaseIdx }; - //component indices - enum { phaseCompIdx = Indices::phaseCompIdx, - transportCompIdx = Indices::transportCompIdx }; - //number of components - enum { numComponents = Indices::numComponents }; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix; - -public: - //Constructor calls ParentType function - StokesncFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) - { - calculateValues_(problem, element, elemVolVars); - } - - /*! - * \brief Return the molar density \f$ \mathrm{[mol/m^3]} \f$ at the integration point. - */ - const Scalar molarDensity() const - { return molarDensity_; } - - /*! - * \brief Return the mass fraction of a transported component at the integration point. - */ - const Scalar massFraction(int compIdx) const - { return massFraction_[compIdx]; } - - /*! - * \brief Return the mole fraction of a transported component at the integration point. - */ - const Scalar moleFraction(int compIdx) const - { return moleFraction_[compIdx]; } - - /*! - * \brief Return the molar diffusion coefficient of a transported component at the integration point. - */ - const Scalar diffusionCoeff(int compIdx) const - { return diffusionCoeff_[compIdx]; } - - /*! - * \brief Return the gradient of the mole fraction at the integration point. - */ - const DimVector &moleFractionGrad(int compIdx) const - { return moleFractionGrad_[compIdx]; } - - /*! - * \brief Return the eddy diffusivity (if implemented). - */ - const Scalar eddyDiffusivity() const - { return 0; } - -protected: - void calculateValues_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - - // loop over all components - for (int compIdx=0; compIdx<numComponents; compIdx++){ - massFraction_[compIdx] = Scalar(0.0); - moleFraction_[compIdx] = Scalar(0.0); - diffusionCoeff_[compIdx] = Scalar(0.0); - moleFractionGrad_[compIdx] = Scalar(0.0); - - if (phaseCompIdx!=compIdx) //no transport equation parameters needed for the mass balance - { - molarDensity_ = Scalar(0.0); - - // calculate gradients and secondary variables at IPs - for (int scvIdx = 0; - scvIdx < this->fvGeometry_.numScv; - scvIdx++) // loop over vertices of the element - { - - molarDensity_ += elemVolVars[scvIdx].molarDensity()* - this->face().shapeValue[scvIdx]; - massFraction_[compIdx] += elemVolVars[scvIdx].massFraction(compIdx) * - this->face().shapeValue[scvIdx]; - moleFraction_[compIdx] += elemVolVars[scvIdx].moleFraction(compIdx) * - this->face().shapeValue[scvIdx]; - diffusionCoeff_[compIdx] += elemVolVars[scvIdx].diffusionCoeff(compIdx) * - this->face().shapeValue[scvIdx]; - - // the gradient of the mole fraction at the IP - DimVector grad = this->face().grad[scvIdx]; - grad *= elemVolVars[scvIdx].moleFraction(compIdx); - moleFractionGrad_[compIdx] += grad; - } - - Valgrind::CheckDefined(molarDensity_); - Valgrind::CheckDefined(massFraction_[compIdx]); - Valgrind::CheckDefined(moleFraction_[compIdx]); - Valgrind::CheckDefined(diffusionCoeff_[compIdx]); - Valgrind::CheckDefined(moleFractionGrad_[compIdx]); - } - } - } - - Scalar molarDensity_; - Scalar massFraction_[numComponents]; - Scalar moleFraction_[numComponents]; - Scalar diffusionCoeff_[numComponents]; - DimVector moleFractionGrad_[numComponents]; -}; - -} // end namespace +#include <dumux/freeflow/stokesnc/fluxvariables.hh> #endif diff --git a/dumux/freeflow/stokesnc/stokesncindices.hh b/dumux/freeflow/stokesnc/stokesncindices.hh index cf21bfb2acf760dbf4a4c5b8a2fa95b425df35c9..0c24b32069fff9664e81a88f8a799efac3e375db 100644 --- a/dumux/freeflow/stokesnc/stokesncindices.hh +++ b/dumux/freeflow/stokesnc/stokesncindices.hh @@ -1,84 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_STOKESNC_INDICES_HH_OLD +#define DUMUX_STOKESNC_INDICES_HH_OLD -/*! - * \file - * - * \brief Defines the indices required for the compositional n component Stokes box model. - */ -#ifndef DUMUX_STOKESNC_INDICES_HH -#define DUMUX_STOKESNC_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/stokesnc/indices.hh instead -#include "stokesncproperties.hh" -#include <dumux/freeflow/stokes/stokesindices.hh> - -namespace Dumux -{ -// \{ - -/*! - * \ingroup BoxStokesncModel - * \ingroup ImplicitIndices - * \brief The common indices for the compositional n component Stokes box model. - * - * \tparam PVOffset The first index in a primary variable vector. - */ -template <class TypeTag, int PVOffset = 0> -struct StokesncCommonIndices : public StokesCommonIndices<TypeTag> -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - - // Dimension (copied for convenience) - static const int dim = StokesCommonIndices<TypeTag>::dim; //!< Number of dimensions - - // Phase Index - //! Index of the employed phase in case of a two-phase fluidsystem (set by default to nPhase) - static const int phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx); - - // Number of Components - //! Number of components in employed fluidsystem - static const int numComponents = FluidSystem::numComponents; - - // Component indices - //! The index of the main component of the considered phase - static const int phaseCompIdx = phaseIdx; - //! The index of the first transported component; ASSUMES phase indices of 0 and 1 - static const int transportCompIdx = (unsigned int)(1-phaseIdx); - - // Transport equation indices - //! The index of the mass conservation equation of the first component. In analogy to porous media models "conti" - //! is used here to describe mass conservation equations, i.e total mass balance and transport equations. - static const int conti0EqIdx = PVOffset + dim; - //! The index of the mass balance equation sits on the slot of the employed phase - static const int massBalanceIdx = conti0EqIdx + phaseCompIdx; - //! The index of the transport equation for a two component model. - //! For n>2 please don't use this index, because it looses its actual meaning. - static const int transportEqIdx = conti0EqIdx + transportCompIdx; - - // Primary variables - //! The index of the first mass or mole fraction of the transported component in primary variable vectors - static const int massOrMoleFracIdx = transportEqIdx; - //! The index of the pressure in primary variable vectors - static const int pressureIdx = massBalanceIdx; -}; -} // end namespace +#include <dumux/freeflow/stokesnc/indices.hh> #endif diff --git a/dumux/freeflow/stokesnc/stokesnclocalresidual.hh b/dumux/freeflow/stokesnc/stokesnclocalresidual.hh index 0c1255b81d496d9a4717673a2792b15bbc748210..96af18b49d4134409d8154bf856cab496161aecf 100644 --- a/dumux/freeflow/stokesnc/stokesnclocalresidual.hh +++ b/dumux/freeflow/stokesnc/stokesnclocalresidual.hh @@ -1,232 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Element-wise calculation of the Jacobian matrix for problems - * using the compositional Stokes box model. - * - */ -#ifndef DUMUX_STOKESNC_LOCAL_RESIDUAL_HH -#define DUMUX_STOKESNC_LOCAL_RESIDUAL_HH +#ifndef DUMUX_STOKESNC_LOCAL_RESIDUAL_HH_OLD +#define DUMUX_STOKESNC_LOCAL_RESIDUAL_HH_OLD -#include <dumux/freeflow/stokes/stokeslocalresidual.hh> +#warning this header is deprecated, use dumux/freeflow/stokesnc/localresidual.hh instead -#include "stokesncvolumevariables.hh" -#include "stokesncfluxvariables.hh" - -namespace Dumux -{ -/*! - * \ingroup BoxStokesncModel - * \ingroup ImplicitLocalResidual - * \brief Element-wise calculation of the Jacobian matrix for problems - * using the compositional Stokes box model. This is derived - * from the Stokes box model. - */ -template<class TypeTag> -class StokesncLocalResidual : public StokesLocalResidual<TypeTag> -{ - typedef StokesLocalResidual<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - //dimensions - enum { dim = GridView::dimension }; - //number of equations - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; - //number of components - enum { numComponents = Indices::numComponents }; - //equation indices - enum { massBalanceIdx = Indices::massBalanceIdx, - momentumXIdx = Indices::momentumXIdx, - lastMomentumIdx = Indices::lastMomentumIdx, - transportEqIdx = Indices::transportEqIdx, - conti0EqIdx = Indices::conti0EqIdx }; - //primary variable indices - enum { pressureIdx = Indices::pressureIdx }; - //phase employed - enum { phaseIdx = Indices::phaseIdx }; - //component indices - enum { phaseCompIdx = Indices::phaseCompIdx, - transportCompIdx = Indices::transportCompIdx }; - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - - typedef Dune::FieldVector<Scalar, dim> DimVector; - - typedef typename GridView::Intersection Intersection; - typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; - - static const bool calculateNavierStokes = GET_PROP_VALUE(TypeTag, EnableNavierStokes); - - //! property that defines whether mole or mass fractions are used - static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); - -public: - /*! - * \brief Evaluate the stored amount of quantities additional to the Stokes model - * (transport equations). For using mole fraction also momentum balances and mass balance - * have to be calculated using molar quantities - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub control volume divided by the volume) - * - * \param storage The mass of the component within the sub-control volume - * \param scvIdx The SCV (sub-control-volume) index - * \param usePrevSol Evaluate function with solution of current or previous time step - */ - void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const - { - // compute the storage term for the transport equation - ParentType::computeStorage(storage, scvIdx, usePrevSol); - - // if flag usePrevSol is set, the solution from the previous - // time step is used, otherwise the current solution is - // used. The secondary variables are used accordingly. This - // is required to compute the derivative of the storage term - // using the implicit Euler method. - const ElementVolumeVariables &elemVolVars = usePrevSol ? - this->prevVolVars_() : this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - if (useMoles) - { - // mass balance and transport equations - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (conti0EqIdx+compIdx != massBalanceIdx) - //else // transport equations - { - storage[conti0EqIdx+compIdx] = volVars.molarDensity() - * volVars.moleFraction(compIdx); - - Valgrind::CheckDefined(volVars.molarDensity()); - Valgrind::CheckDefined(volVars.moleFraction(compIdx)); - } - } - } - else - { - /* works for a maximum of two components, for more components - mole fractions must be used (set property UseMoles to true) */ - - //storage of transported component - storage[transportEqIdx] = volVars.density() - * volVars.massFraction(transportCompIdx); - - Valgrind::CheckDefined(volVars.density()); - Valgrind::CheckDefined(volVars.massFraction(transportCompIdx)); - - } - } - - /*! - * \brief Evaluates the advective component (mass) flux - * over a face of a sub-control volume and writes the result in - * the flux vector. - * - * This method is called by compute flux (base class). - * - * \param flux The advective flux over the sub-control-volume face for each component - * \param fluxVars The flux variables at the current SCV/boundary face - */ - void computeAdvectiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // call ParentType function - ParentType::computeAdvectiveFlux(flux,fluxVars); - - // data attached to upstream and the downstream vertices - const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); - const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); - - Scalar tmp = fluxVars.normalVelocity(); - - if(useMoles) - { - //transport equations - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (conti0EqIdx+compIdx != massBalanceIdx) // mass balance is calculated above - { - tmp *= (this->massUpwindWeight_ * up.molarDensity() * up.moleFraction(compIdx) - + (1.-this->massUpwindWeight_) * dn.molarDensity() * dn.moleFraction(compIdx)); - - flux[conti0EqIdx+compIdx] += tmp; - Valgrind::CheckDefined(flux[conti0EqIdx+compIdx]); - } - } - } - else - { - tmp *= (this->massUpwindWeight_ * up.density() * up.massFraction(transportCompIdx) - + (1.-this->massUpwindWeight_) * dn.density() * dn.massFraction(transportCompIdx)); - - flux[transportEqIdx] += tmp; - Valgrind::CheckDefined(flux[transportEqIdx]); - } - } - - /*! - * \brief Adds the diffusive component flux to the flux vector over - * the face of a sub-control volume. - * - * \param flux The diffusive flux over the SCV face or boundary face - * \param fluxVars The flux variables at the current SCV/boundary face - */ - void computeDiffusiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // diffusive component flux - if(useMoles) - { - //loop over secondary components - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (conti0EqIdx+compIdx != massBalanceIdx) - { - flux[conti0EqIdx+compIdx] -= fluxVars.moleFractionGrad(compIdx) - * fluxVars.face().normal - * (fluxVars.diffusionCoeff(compIdx) + fluxVars.eddyDiffusivity()) - * fluxVars.molarDensity(); - Valgrind::CheckDefined(flux[conti0EqIdx+compIdx]); - } - } - } - else - { - flux[transportEqIdx] -= fluxVars.moleFractionGrad(transportCompIdx) - * fluxVars.face().normal - * (fluxVars.diffusionCoeff(transportCompIdx) + fluxVars.eddyDiffusivity()) - * fluxVars.molarDensity() - * FluidSystem::molarMass(transportCompIdx);// Multiplied by molarMass [kg/mol] to convert form [mol/m^3 s] to [kg/m^3 s] - Valgrind::CheckDefined(flux[transportEqIdx]); - } - } -}; - -} +#include <dumux/freeflow/stokesnc/localresidual.hh> #endif diff --git a/dumux/freeflow/stokesnc/stokesncmodel.hh b/dumux/freeflow/stokesnc/stokesncmodel.hh index 876b19603d1f060bcfeab5310b23083716451f45..bf191d5bfbd4a2e00dbf58d0b7c44795b51d3f55 100644 --- a/dumux/freeflow/stokesnc/stokesncmodel.hh +++ b/dumux/freeflow/stokesnc/stokesncmodel.hh @@ -1,201 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Adaption of the box scheme to the n-component Stokes model. - */ -#ifndef DUMUX_STOKESNC_MODEL_HH -#define DUMUX_STOKESNC_MODEL_HH +#ifndef DUMUX_STOKESNC_MODEL_HH_OLD +#define DUMUX_STOKESNC_MODEL_HH_OLD -#include <dumux/freeflow/stokes/stokesmodel.hh> +#warning this header is deprecated, use dumux/freeflow/stokesnc/model.hh instead -#include "stokesnclocalresidual.hh" -#include "stokesncproperties.hh" - -namespace Dumux { -/*! - * \ingroup BoxStokesncModel - * \brief Adaption of the box scheme to the compositional Stokes model. - * - * This model implements an isothermal n-component Stokes flow of a fluid - * solving a momentum balance, a mass balance and conservation equations for \f$n-1\f$ - * components. When using mole fractions naturally the densities represent molar - * densities - * - * The momentum balance: - * \f[ - * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} - * + \text{div} \left( p_g {\bf {I}} - * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g - * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) - * - \varrho_g {\bf g} = 0 - * \f] - * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes - * equation can be solved. In this case an additional term - * \f[ - * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) - * \f] - * is added to the momentum balance equation. - * - * The mass balance equation: - * \f[ - * \frac{\partial \varrho_g}{\partial t} - * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 - * \f] - * - * The component mass balance equations: - * \f[ - * \frac{\partial \left(\varrho_g X_g^\kappa\right)}{\partial t} - * + \text{div} \left( \varrho_g {\boldsymbol{v}}_g X_g^\kappa - * - D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \textbf{grad}\, x_g^\kappa \right) - * - q_g^\kappa = 0 - * \f] - * Please note that, even though it is n-component model, the diffusive - * fluxes are still calculated with binary diffusion. - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class StokesncModel : public StokesModel<TypeTag> -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { dim = GridView::dimension, - transportCompIdx = Indices::transportCompIdx, - phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx), - useMoles = GET_PROP_VALUE(TypeTag, UseMoles), - numComponents = Indices::numComponents - }; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - - -public: - //! \copydoc ImplicitModel::addOutputVtkFields - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; - - const Scalar scale_ = GET_PROP_VALUE(TypeTag, Scaling); - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - ScalarField &pN = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField &T = *writer.allocateManagedBuffer(numVertices); - - ScalarField *moleFraction[numComponents]; - for (int i = 0; i < numComponents; ++i) - moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - ScalarField *massFraction[numComponents]; - for (int i = 0; i < numComponents; ++i) - massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - - unsigned numElements = this->gridView_().size(0); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - - FVElementGeometry fvGeometry; - VolumeVariables volVars; - ElementBoundaryTypes elemBcTypes; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int idx = this->elementMapper().index(element); - - rank[idx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element, fvGeometry); - - int numLocalVerts = element.subEntities(dim); - - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pN[vIdxGlobal] = volVars.pressure()*scale_; - delP[vIdxGlobal] = volVars.pressure()*scale_ - 1e5; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - { - (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); - (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); - Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); - Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); - } - - T [vIdxGlobal] = volVars.temperature(); - - rho[vIdxGlobal] = volVars.density()*scale_*scale_*scale_; - mu[vIdxGlobal] = volVars.dynamicViscosity()*scale_; - velocity[vIdxGlobal] = volVars.velocity(); - velocity[vIdxGlobal] *= 1/scale_; - } - } - writer.attachVertexData(T, "temperature"); - writer.attachVertexData(pN, "P"); - writer.attachVertexData(delP, "delP"); - - for (int j = 0; j < numComponents; ++j) - { - std::ostringstream moleFrac, massFrac; - moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); - - massFrac << "X_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); - } - - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(velocity, "v", dim); - } -}; - -} - -#include "stokesncpropertydefaults.hh" +#include <dumux/freeflow/stokesnc/model.hh> #endif diff --git a/dumux/freeflow/stokesnc/stokesncproperties.hh b/dumux/freeflow/stokesnc/stokesncproperties.hh index 9f24e6022e88cab0180daf58711d3d3ccea5f05d..8f3ed1e93cac20bb970271b73ed9df0432e32daa 100644 --- a/dumux/freeflow/stokesnc/stokesncproperties.hh +++ b/dumux/freeflow/stokesnc/stokesncproperties.hh @@ -1,49 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesncModel - * - * \file - * - * \brief Defines the supplementary properties required for the compositional - * Stokes box model. - */ -#ifndef DUMUX_STOKESNC_PROPERTIES_HH -#define DUMUX_STOKESNC_PROPERTIES_HH +#ifndef DUMUX_STOKESNC_PROPERTIES_HH_OLD +#define DUMUX_STOKESNC_PROPERTIES_HH_OLD -#include <dumux/freeflow/stokes/stokesproperties.hh> +#warning this header is deprecated, use dumux/freeflow/stokesnc/properties.hh instead -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tag for the compositional Stokes problems -NEW_TYPE_TAG(BoxStokesnc, INHERITS_FROM(BoxStokes)); -} - -} +#include <dumux/freeflow/stokesnc/properties.hh> #endif diff --git a/dumux/freeflow/stokesnc/stokesncpropertydefaults.hh b/dumux/freeflow/stokesnc/stokesncpropertydefaults.hh index fab3f4065aa571464609b00ef6bb72249df53f35..5523de887bf4e466a9777b9b9e4c6b98726b330c 100644 --- a/dumux/freeflow/stokesnc/stokesncpropertydefaults.hh +++ b/dumux/freeflow/stokesnc/stokesncpropertydefaults.hh @@ -1,100 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesncModel - * - * \file - * - * \brief Defines the properties required for the compositional - * Stokes box model. - */ -#ifndef DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH -#define DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH +#ifndef DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH_OLD -#include <dumux/freeflow/stokes/stokespropertydefaults.hh> +#warning this header is deprecated, use dumux/freeflow/stokesnc/propertydefaults.hh instead -#include "stokesncproperties.hh" -#include "stokesncfluxvariables.hh" -#include "stokesncindices.hh" -#include "stokesnclocalresidual.hh" -#include "stokesncmodel.hh" -#include "stokesncvolumevariables.hh" +#include <dumux/freeflow/stokesnc/propertydefaults.hh> -#include <dumux/material/fluidstates/compositionalfluidstate.hh> - -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -//! Define that mole fractions are used in the balance equations -SET_BOOL_PROP(BoxStokesnc, UseMoles, true); - -//! set the number of equations -SET_PROP(BoxStokesnc, NumEq) -{ - typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - - static const int dim = Grid::dimension; -public: - static constexpr int value = FluidSystem::numComponents + dim; -}; - -//! Use the Stokes nc local residual function for the Stokes model -SET_TYPE_PROP(BoxStokesnc, LocalResidual, StokesncLocalResidual<TypeTag>); - -//! the Model property -SET_TYPE_PROP(BoxStokesnc, Model, StokesncModel<TypeTag>); - -//! the VolumeVariables property -SET_TYPE_PROP(BoxStokesnc, VolumeVariables, StokesncVolumeVariables<TypeTag>); - -//! the FluxVariables property -SET_TYPE_PROP(BoxStokesnc, FluxVariables, StokesncFluxVariables<TypeTag>); - -//! Set the Indices for the Stokes nc model. -SET_TYPE_PROP(BoxStokesnc, Indices, StokesncCommonIndices<TypeTag>); - -//! Choose the type of the employed fluid state -SET_PROP(BoxStokesnc, FluidState) -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; -public: - typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> type; -}; - -//! Choose the considered phase (single-phase system); the gas phase is used -SET_PROP(BoxStokesnc, PhaseIdx) -{ - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; -public: - static constexpr int value = FluidSystem::nPhaseIdx; -}; - -} // namespace Properties -} // namespace Dumux -#endif // DUMUX_STOKESNC_PROPERTY_DEFAULTS_HH +#endif diff --git a/dumux/freeflow/stokesnc/stokesncvolumevariables.hh b/dumux/freeflow/stokesnc/stokesncvolumevariables.hh index e4238bc6a5086b7e5c1811138539c231b3939ca8..8b6b578b8678ba1be26930a6488ef6d00f3780cf 100644 --- a/dumux/freeflow/stokesnc/stokesncvolumevariables.hh +++ b/dumux/freeflow/stokesnc/stokesncvolumevariables.hh @@ -1,196 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Contains the quantities which are constant within a - * finite volume in the compositional n-component Stokes model. - */ -#ifndef DUMUX_STOKESNC_VOLUME_VARIABLES_HH -#define DUMUX_STOKESNC_VOLUME_VARIABLES_HH +#ifndef DUMUX_STOKESNC_VOLUME_VARIABLES_HH_OLD +#define DUMUX_STOKESNC_VOLUME_VARIABLES_HH_OLD -#include <dumux/freeflow/stokes/stokesvolumevariables.hh> -#include "stokesncproperties.hh" +#warning this header is deprecated, use dumux/freeflow/stokesnc/volumevariables.hh instead -namespace Dumux -{ - -/*! - * \ingroup BoxStokesncModel - * \ingroup ImplicitVolumeVariables - * \brief Contains the quantities which are are constant within a - * finite volume in the n-component Stokes box model. - */ -template <class TypeTag> -class StokesncVolumeVariables : public StokesVolumeVariables<TypeTag> -{ - typedef StokesVolumeVariables<TypeTag> ParentType; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - //component indices - enum { transportCompIdx = Indices::transportCompIdx, - phaseCompIdx = Indices::phaseCompIdx }; - //number of components - enum { numComponents = Indices::numComponents }; - //employed phase index - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - //primary variable indices - enum { massOrMoleFracIdx = Indices::massOrMoleFracIdx }; - //equation indices - enum { conti0EqIdx = Indices::conti0EqIdx, - massBalanceIdx = Indices::massBalanceIdx, - transportEqIdx = Indices::transportEqIdx }; - - //! property that defines whether mole or mass fractions are used - static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); - -public: - /*! - * \copydoc ImplicitVolumeVariables::update() - */ - void update(const PrimaryVariables &priVars, - const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx, - const bool isOldSol) - { - - // Model is restricted to 2 components when using mass fractions - if (!useMoles && numComponents>2) - { - DUNE_THROW(Dune::NotImplemented, "This model is restricted to 2 components when using mass fractions!\ - To use mole fractions set property UseMoles true ..."); - } - - // set the mole fractions first - completeFluidState(priVars, problem, element, fvGeometry, scvIdx, this->fluidState(), isOldSol); - - // update vertex data for the mass and momentum balance - ParentType::update(priVars, - problem, - element, - fvGeometry, - scvIdx, - isOldSol); - - // Second instance of a parameter cache. - // Could be avoided if diffusion coefficients also - // became part of the fluid state. - typename FluidSystem::ParameterCache paramCache; - paramCache.updateAll(this->fluidState()); - - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (phaseCompIdx!=compIdx) - { - diffCoeff_[compIdx] = FluidSystem::binaryDiffusionCoefficient(this->fluidState(), - paramCache, - phaseIdx, - compIdx, - phaseCompIdx); - } - else - diffCoeff_[compIdx] = 0.0; - - Valgrind::CheckDefined(diffCoeff_[compIdx]); - } - }; - - /*! - * \copydoc ImplicitModel::completeFluidState() - * \param isOldSol Specifies whether this is the previous solution or the current one - */ - static void completeFluidState(const PrimaryVariables& priVars, - const Problem& problem, - const Element& element, - const FVElementGeometry& fvGeometry, - const int scvIdx, - FluidState& fluidState, - const bool isOldSol = false) - { - - if(useMoles) // mole-fraction formulation - { - Scalar moleFracPhase, sumMoleFrac(0.0); - - // loop over components - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (conti0EqIdx+compIdx != massBalanceIdx) - { - sumMoleFrac += priVars[conti0EqIdx+compIdx]; - fluidState.setMoleFraction(phaseIdx, compIdx, priVars[conti0EqIdx+compIdx]); - } - } - - // mole fraction for the main component (no primary variable) - moleFracPhase = 1 - sumMoleFrac; - fluidState.setMoleFraction(phaseIdx, phaseCompIdx, moleFracPhase); - } - else // mass-fraction formulation - { - // setMassFraction() has only to be called 1-numComponents times - fluidState.setMassFraction(phaseIdx, transportCompIdx, priVars[massOrMoleFracIdx]); - } - } - - /*! - * \brief Returns the mass fraction of a given component in the - * given fluid phase within the control volume. - * - * \param compIdx The component index - */ - Scalar massFraction(const int compIdx) const - { return this->fluidState_.massFraction(phaseIdx, compIdx); } - - /*! - * \brief Returns the mole fraction of a given component in the - * given fluid phase within the control volume. - * - * \param compIdx The component index - */ - Scalar moleFraction(const int compIdx) const - { return this->fluidState_.moleFraction(phaseIdx, compIdx); } - - /*! - * \brief Returns the binary (mass) diffusion coefficient - * - * \param compIdx The component index - */ - Scalar diffusionCoeff(int compIdx) const - { return diffCoeff_[compIdx]; } - -protected: - Scalar diffCoeff_[numComponents]; //!< Diffusion coefficient -}; - -} // end namespace +#include <dumux/freeflow/stokesnc/volumevariables.hh> #endif diff --git a/dumux/freeflow/stokesnc/volumevariables.hh b/dumux/freeflow/stokesnc/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..13819e5c29a09146d09647bfa1c694371d9a5d66 --- /dev/null +++ b/dumux/freeflow/stokesnc/volumevariables.hh @@ -0,0 +1,196 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Contains the quantities which are constant within a + * finite volume in the compositional n-component Stokes model. + */ +#ifndef DUMUX_STOKESNC_VOLUME_VARIABLES_HH +#define DUMUX_STOKESNC_VOLUME_VARIABLES_HH + +#include <dumux/freeflow/stokes/volumevariables.hh> +#include "properties.hh" + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesncModel + * \ingroup ImplicitVolumeVariables + * \brief Contains the quantities which are are constant within a + * finite volume in the n-component Stokes box model. + */ +template <class TypeTag> +class StokesncVolumeVariables : public StokesVolumeVariables<TypeTag> +{ + typedef StokesVolumeVariables<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + //component indices + enum { transportCompIdx = Indices::transportCompIdx, + phaseCompIdx = Indices::phaseCompIdx }; + //number of components + enum { numComponents = Indices::numComponents }; + //employed phase index + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + //primary variable indices + enum { massOrMoleFracIdx = Indices::massOrMoleFracIdx }; + //equation indices + enum { conti0EqIdx = Indices::conti0EqIdx, + massBalanceIdx = Indices::massBalanceIdx, + transportEqIdx = Indices::transportEqIdx }; + + //! property that defines whether mole or mass fractions are used + static const bool useMoles = GET_PROP_VALUE(TypeTag, UseMoles); + +public: + /*! + * \copydoc ImplicitVolumeVariables::update() + */ + void update(const PrimaryVariables &priVars, + const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int scvIdx, + const bool isOldSol) + { + + // Model is restricted to 2 components when using mass fractions + if (!useMoles && numComponents>2) + { + DUNE_THROW(Dune::NotImplemented, "This model is restricted to 2 components when using mass fractions!\ + To use mole fractions set property UseMoles true ..."); + } + + // set the mole fractions first + completeFluidState(priVars, problem, element, fvGeometry, scvIdx, this->fluidState(), isOldSol); + + // update vertex data for the mass and momentum balance + ParentType::update(priVars, + problem, + element, + fvGeometry, + scvIdx, + isOldSol); + + // Second instance of a parameter cache. + // Could be avoided if diffusion coefficients also + // became part of the fluid state. + typename FluidSystem::ParameterCache paramCache; + paramCache.updateAll(this->fluidState()); + + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (phaseCompIdx!=compIdx) + { + diffCoeff_[compIdx] = FluidSystem::binaryDiffusionCoefficient(this->fluidState(), + paramCache, + phaseIdx, + compIdx, + phaseCompIdx); + } + else + diffCoeff_[compIdx] = 0.0; + + Valgrind::CheckDefined(diffCoeff_[compIdx]); + } + }; + + /*! + * \copydoc ImplicitModel::completeFluidState() + * \param isOldSol Specifies whether this is the previous solution or the current one + */ + static void completeFluidState(const PrimaryVariables& priVars, + const Problem& problem, + const Element& element, + const FVElementGeometry& fvGeometry, + const int scvIdx, + FluidState& fluidState, + const bool isOldSol = false) + { + + if(useMoles) // mole-fraction formulation + { + Scalar moleFracPhase, sumMoleFrac(0.0); + + // loop over components + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (conti0EqIdx+compIdx != massBalanceIdx) + { + sumMoleFrac += priVars[conti0EqIdx+compIdx]; + fluidState.setMoleFraction(phaseIdx, compIdx, priVars[conti0EqIdx+compIdx]); + } + } + + // mole fraction for the main component (no primary variable) + moleFracPhase = 1 - sumMoleFrac; + fluidState.setMoleFraction(phaseIdx, phaseCompIdx, moleFracPhase); + } + else // mass-fraction formulation + { + // setMassFraction() has only to be called 1-numComponents times + fluidState.setMassFraction(phaseIdx, transportCompIdx, priVars[massOrMoleFracIdx]); + } + } + + /*! + * \brief Returns the mass fraction of a given component in the + * given fluid phase within the control volume. + * + * \param compIdx The component index + */ + Scalar massFraction(const int compIdx) const + { return this->fluidState_.massFraction(phaseIdx, compIdx); } + + /*! + * \brief Returns the mole fraction of a given component in the + * given fluid phase within the control volume. + * + * \param compIdx The component index + */ + Scalar moleFraction(const int compIdx) const + { return this->fluidState_.moleFraction(phaseIdx, compIdx); } + + /*! + * \brief Returns the binary (mass) diffusion coefficient + * + * \param compIdx The component index + */ + Scalar diffusionCoeff(int compIdx) const + { return diffCoeff_[compIdx]; } + +protected: + Scalar diffCoeff_[numComponents]; //!< Diffusion coefficient +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/stokesncni/fluxvariables.hh b/dumux/freeflow/stokesncni/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..173e276bd9e755e3bc8f8fda3d3ff01230876725 --- /dev/null +++ b/dumux/freeflow/stokesncni/fluxvariables.hh @@ -0,0 +1,173 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate the + * energy fluxes over a face of a finite volume. + * + * This means concentration temperature gradients and heat conductivity at + * the integration point. + */ +#ifndef DUMUX_STOKESNCNI_FLUX_VARIABLES_HH +#define DUMUX_STOKESNCNI_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/freeflow/stokesnc/fluxvariables.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesncniModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains data which is required to + * calculate the energy fluxes over a face of a finite + * volume for the non-isothermal compositional n-component Stokes box model. + * + * This means temperature gradients and heat conductivity + * at the integration point of a SCV face or boundary face. + */ +template <class TypeTag> +class StokesncniFluxVariables : public StokesncFluxVariables<TypeTag> +{ + typedef StokesncFluxVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + + enum { dim = GridView::dimension }; + + //number of components + enum { numComponents = Indices::numComponents }; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + +public: + StokesncniFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) + { + calculateValues_(problem, element, elemVolVars); + } + + /*! + * \brief Returns the temperature \f$\mathrm{[K]}\f$ at the integration point. + */ + const Scalar temperature() const + { return temperature_; } + + /*! + * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ at the integration point. + */ + const Scalar thermalConductivity() const + { return thermalConductivity_; } + + /*! + * \brief Returns the specific isobaric heat capacity \f$\mathrm{[J/(kg*K)]}\f$ + * at the integration point. + */ + Scalar heatCapacity() const + { return heatCapacity_; } + + /*! + * \brief Return the enthalpy of a component \f$\mathrm{[J/kg]}\f$ at the integration point. + */ + const Scalar componentEnthalpy(int componentIdx) const + { return componentEnthalpy_[componentIdx]; } + + /*! + * \brief Returns the temperature gradient \f$\mathrm{[K/m]}\f$ at the integration point. + */ + const DimVector &temperatureGrad() const + { return temperatureGrad_; } + + /*! + * \brief Return the thermal eddy conductivity \f$\mathrm{[W/(m*K)]}\f$ (if implemented). + */ + const Scalar thermalEddyConductivity() const + { return 0; } + + +protected: + void calculateValues_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + temperature_ = Scalar(0); + thermalConductivity_ = Scalar(0); + heatCapacity_ = Scalar(0); + temperatureGrad_ = Scalar(0); + + // calculate gradients and secondary variables at IPs + for (int scvIdx = 0; + scvIdx < this->fvGeometry_.numScv; + scvIdx++) // loop over vertices of the element + { + temperature_ += elemVolVars[scvIdx].temperature() * + this->face().shapeValue[scvIdx]; + + thermalConductivity_ += elemVolVars[scvIdx].thermalConductivity() * + this->face().shapeValue[scvIdx]; + + heatCapacity_ += elemVolVars[scvIdx].heatCapacity() * + this->face().shapeValue[scvIdx]; + + // the gradient of the temperature at the IP + DimVector grad = this->face().grad[scvIdx]; + grad *= elemVolVars[scvIdx].temperature(); + temperatureGrad_ += grad; + } + Valgrind::CheckDefined(temperature_); + Valgrind::CheckDefined(thermalConductivity_); + Valgrind::CheckDefined(heatCapacity_); + Valgrind::CheckDefined(temperatureGrad_); + + for (unsigned int i = 0; i < numComponents; ++i) + { + componentEnthalpy_[i] = Scalar(0.0); + for (int scvIdx = 0; scvIdx < this->fvGeometry_.numScv; scvIdx++) // loop over vertices of the element + { + componentEnthalpy_[i] += elemVolVars[scvIdx].componentEnthalpy(i) + * this->face().shapeValue[scvIdx]; + } + Valgrind::CheckDefined(componentEnthalpy_[i]); + } + } + + Scalar temperature_; + Scalar thermalConductivity_; + Scalar heatCapacity_; + Scalar componentEnthalpy_[numComponents]; + DimVector temperatureGrad_; +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/stokesncni/indices.hh b/dumux/freeflow/stokesncni/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..193891f2d4d414532d220bc94b1d919e1d6cd07e --- /dev/null +++ b/dumux/freeflow/stokesncni/indices.hh @@ -0,0 +1,53 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * \brief Defines the indices required for the non-isothermal compositional n-component Stokes box model. + */ +#ifndef DUMUX_STOKESNCNI_INDICES_HH +#define DUMUX_STOKESNCNI_INDICES_HH + +#include <dumux/freeflow/stokesnc/indices.hh> + +namespace Dumux +{ +// \{ + +/*! + * \ingroup BoxStokesncniModel + * \ingroup ImplicitIndices + * \brief Enumerations for the non-isothermal compositional n-component Stokes model + */ +template <class TypeTag, int PVOffset=0> +struct StokesncniCommonIndices : public StokesncCommonIndices<TypeTag, PVOffset> +{ + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + // number of dimensions + static const int dim = StokesCommonIndices<TypeTag>::dim; + static const int energyEqIdx = PVOffset + dim + FluidSystem::numComponents; //!< The index for the energy balance equation + static const int temperatureIdx = energyEqIdx; //!< The index for temperature in primary variable vectors +}; +// \} +} // end namespace Dumux + +#endif diff --git a/dumux/freeflow/stokesncni/localresidual.hh b/dumux/freeflow/stokesncni/localresidual.hh new file mode 100644 index 0000000000000000000000000000000000000000..0cefe773a170257b4c07ea666dca30c8ec39ba43 --- /dev/null +++ b/dumux/freeflow/stokesncni/localresidual.hh @@ -0,0 +1,185 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Element-wise calculation of the Jacobian matrix for problems + * using the non-isothermal compositional n-compontent Stokes box model. + * + */ +#ifndef DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH +#define DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH + +#include <dumux/freeflow/stokesnc/localresidual.hh> + +#include "volumevariables.hh" +#include "fluxvariables.hh" + +namespace Dumux +{ +/*! + * \ingroup BoxStokesncniModel + * \ingroup ImplicitLocalResidual + * \brief Element-wise calculation of the Jacobian matrix for problems + * using the non-isothermal compositional n-component Stokes box model. This class is derived + * from the stokesnc box local residual and adds the energy balance equation. + */ +template<class TypeTag> +class StokesncniLocalResidual : public StokesncLocalResidual<TypeTag> +{ + typedef StokesncLocalResidual<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { dim = GridView::dimension }; // dimensions + enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; // number of equations + enum { numComponents = Indices::numComponents }; // number of components + enum { energyEqIdx = Indices::energyEqIdx}; // equation indices + enum { phaseCompIdx = Indices::phaseCompIdx}; + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + +public: + /*! + * \brief Evaluate the amount the additional quantities to the stokesnc model + * (energy equation). + * + * The result should be averaged over the volume (e.g. phase mass + * inside a sub control volume divided by the volume) + */ + void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const + { + // compute the storage term for the transport equation + ParentType::computeStorage(storage, scvIdx, usePrevSol); + + // if flag usePrevSol is set, the solution from the previous + // time step is used, otherwise the current solution is + // used. The secondary variables are used accordingly. This + // is required to compute the derivative of the storage term + // using the implicit euler method. + const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_(); + const VolumeVariables &volVars = elemVolVars[scvIdx]; + + // compute the storage of energy + storage[energyEqIdx] = + volVars.density() * + volVars.internalEnergy(); + } + + /*! + * \brief Evaluates the convective energy flux + * over a face of a sub-control volume and writes the result in + * the flux vector. This method is called by computeFlux in the base class. + * + * \param flux The vector for the fluxes over the SCV/boundary face + * \param fluxVars The flux variables at the current SCV/boundary face + */ + void computeAdvectiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // call computation of the advective fluxes of the stokes model + // (momentum and mass fluxes) + ParentType::computeAdvectiveFlux(flux, fluxVars); + + // vertex data of the upstream and the downstream vertices + const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); + const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); + + Scalar tmp = fluxVars.normalVelocity(); + tmp *= (this->massUpwindWeight_ * up.density() * up.enthalpy() + + (1.0 - this->massUpwindWeight_) * dn.density() * dn.enthalpy()); + + flux[energyEqIdx] += tmp; + Valgrind::CheckDefined(flux[energyEqIdx]); + } + + /*! + * \brief Evaluates the diffusive component energy flux + * over the face of a sub-control volume. + * + * \param flux The vector for the fluxes over the SCV face + * \param fluxVars The flux variables at the current SCV face + */ + void computeDiffusiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // diffusive mass flux + ParentType::computeDiffusiveFlux(flux, fluxVars); + + // conductive energy flux + computeConductiveFlux(flux, fluxVars); + + // diffusive component energy flux + Scalar sumDiffusiveFluxes = 0; + for (int compIdx=0; compIdx<numComponents; compIdx++) + { + if (compIdx != phaseCompIdx) + { + Valgrind::CheckDefined(fluxVars.moleFractionGrad(compIdx)); + Valgrind::CheckDefined(fluxVars.face().normal); + Valgrind::CheckDefined(fluxVars.diffusionCoeff(compIdx)); + Valgrind::CheckDefined(fluxVars.eddyDiffusivity()); + Valgrind::CheckDefined(fluxVars.molarDensity()); + Valgrind::CheckDefined(FluidSystem::molarMass(compIdx)); + Valgrind::CheckDefined(fluxVars.componentEnthalpy(compIdx)); + Scalar diffusiveFlux = fluxVars.moleFractionGrad(compIdx) + * fluxVars.face().normal + * (fluxVars.diffusionCoeff(compIdx) + fluxVars.eddyDiffusivity()) + * fluxVars.molarDensity(); + sumDiffusiveFluxes += diffusiveFlux; + flux[energyEqIdx] -= diffusiveFlux * fluxVars.componentEnthalpy(compIdx) + * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]; + } + } + + // the diffusive flux of the phase component is the negative of the sum of the component fluxes + flux[energyEqIdx] += sumDiffusiveFluxes * fluxVars.componentEnthalpy(phaseCompIdx) + * FluidSystem::molarMass(phaseCompIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]; + + Valgrind::CheckDefined(flux[energyEqIdx]); + } + + /*! + * \brief Evaluates the conductive energy flux + * over the face of a sub-control volume. + * + * \param flux The vector for the fluxes over the SCV face + * \param fluxVars The flux variables at the current SCV face + */ + void computeConductiveFlux(PrimaryVariables &flux, + const FluxVariables &fluxVars) const + { + // diffusive heat flux + flux[energyEqIdx] -= + fluxVars.temperatureGrad() * fluxVars.face().normal + * (fluxVars.thermalConductivity() + fluxVars.thermalEddyConductivity()); + Valgrind::CheckDefined(flux[energyEqIdx]); + } +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/stokesncni/model.hh b/dumux/freeflow/stokesncni/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..44ec850d24ed176193c148f708d34be42c03e003 --- /dev/null +++ b/dumux/freeflow/stokesncni/model.hh @@ -0,0 +1,211 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Adaption of the box scheme to the non-isothermal + * n-component Stokes model. + */ +#ifndef DUMUX_STOKESNCNI_MODEL_HH +#define DUMUX_STOKESNCNI_MODEL_HH + +#include <dumux/freeflow/stokesnc/model.hh> + +#include "localresidual.hh" +#include "properties.hh" + +namespace Dumux { +/*! + * \ingroup BoxStokesncniModel + * \brief Adaption of the box scheme to the non-isothermal + * n-component Stokes model. + * + * This model implements a non-isothermal n-component Stokes flow of a fluid + * solving a momentum balance, a mass balance, conservation equations for \f$n-1\f$ components, + * and one balance equation for the energy. + * + * The momentum balance: + * \f[ + * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} + * + \text{div} \left( p_g {\bf {I}} + * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g + * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) + * - \varrho_g {\bf g} = 0 + * \f] + * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes + * equation can be solved. In this case an additional term + * \f[ + * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) + * \f] + * is added to the momentum balance equation. + * + * The mass balance equation: + * \f[ + * \frac{\partial \varrho_g}{\partial t} + * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 + * \f] + * + * The component mass balance equations: + * \f[ + * \frac{\partial \left(\varrho_g X_g^\kappa\right)}{\partial t} + * + \text{div} \left( \varrho_g {\boldsymbol{v}}_g X_g^\kappa + * - D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \textbf{grad}\, x_g^\kappa \right) + * - q_g^\kappa = 0 + * \f] + * Please note that, even though it is n-component model, the diffusive + * fluxes are still calculated with binary diffusion. + * + * The energy balance equation: + * \f[ + * \frac{\partial (\varrho_g u_g)}{\partial t} + * + \text{div} \left( \varrho_g h_g {\boldsymbol{v}}_g + * - \sum_\kappa \left[ h^\kappa_g D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} + * \textbf{grad}\, x^\kappa_g \right] + * - \lambda_g \textbf{grad}\, T \right) - q_T = 0 + * \f] + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class StokesncniModel : public StokesncModel<TypeTag> +{ + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { dim = GridView::dimension }; + enum { transportCompIdx = Indices::transportCompIdx }; + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + enum { useMoles = GET_PROP_VALUE(TypeTag, UseMoles) }; + enum { numComponents = Indices::numComponents }; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + +public: + //! \copydoc ImplicitModel::addOutputVtkFields + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; + + const Scalar scale_ = GET_PROP_VALUE(TypeTag, Scaling); + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + ScalarField &pn = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField &T = *writer.allocateManagedBuffer(numVertices); + ScalarField &h = *writer.allocateManagedBuffer(numVertices); + ScalarField *moleFraction[numComponents]; + for (int i = 0; i < numComponents; ++i) + moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + ScalarField *massFraction[numComponents]; + for (int i = 0; i < numComponents; ++i) + massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + + unsigned numElements = this->gridView_().size(0); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + + FVElementGeometry fvGeometry; + VolumeVariables volVars; + ElementBoundaryTypes elemBcTypes; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int idx = this->elementMapper().index(element); + + rank[idx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + elemBcTypes.update(this->problem_(), element, fvGeometry); + + int numLocalVerts = element.subEntities(dim); + + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pn[vIdxGlobal] = volVars.pressure()*scale_; + delP[vIdxGlobal] = volVars.pressure()*scale_ - 1e5; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + { + (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); + (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); + Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); + Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); + } + + T [vIdxGlobal] = volVars.temperature(); + + rho[vIdxGlobal] = volVars.density()*scale_*scale_*scale_; + mu[vIdxGlobal] = volVars.dynamicViscosity()*scale_; + h[vIdxGlobal] = volVars.enthalpy(); + velocity[vIdxGlobal] = volVars.velocity(); + velocity[vIdxGlobal] *= 1/scale_; + } + } + writer.attachVertexData(T, "temperature"); + writer.attachVertexData(pn, "pg"); + writer.attachVertexData(delP, "delP"); + + for (int j = 0; j < numComponents; ++j) + { + std::ostringstream moleFrac, massFrac; + moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); + + massFrac << "X_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); + } + + writer.attachVertexData(h, "h"); + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(velocity, "v", dim); + + } +}; + +} + +#include "propertydefaults.hh" + +#endif diff --git a/dumux/freeflow/stokesncni/properties.hh b/dumux/freeflow/stokesncni/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..749c7dc5b97b79783bd649fbded4f67ddec8537b --- /dev/null +++ b/dumux/freeflow/stokesncni/properties.hh @@ -0,0 +1,48 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesncniModel + * + * \file + * + * \brief Defines the additional properties required for the non-isothermal compositional n-compontent + * Stokes box model. + */ +#ifndef DUMUX_STOKESNCNI_PROPERTIES_HH +#define DUMUX_STOKESNCNI_PROPERTIES_HH + +#include <dumux/freeflow/stokesnc/properties.hh> + +namespace Dumux +{ +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the non-isothermal compositional n-component Stokes problems +NEW_TYPE_TAG(BoxStokesncni, INHERITS_FROM(BoxStokesnc)); + +} + +} +#endif diff --git a/dumux/freeflow/stokesncni/propertydefaults.hh b/dumux/freeflow/stokesncni/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..48e431a4af0233a00b6a921df056a64094d51104 --- /dev/null +++ b/dumux/freeflow/stokesncni/propertydefaults.hh @@ -0,0 +1,73 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxStokesncniModel + * + * \file + * + * \brief Sets default properties for the non-isothermal compositional + * n-component Stokes box model. + */ +#ifndef DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH +#define DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH + + +#include "fluxvariables.hh" +#include "indices.hh" +#include "localresidual.hh" +#include "model.hh" +#include "volumevariables.hh" + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +SET_PROP(BoxStokesncni, NumEq) //!< set the number of equations +{ + typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + static const int dim = Grid::dimension; + public: + static constexpr int value = dim + FluidSystem::numComponents +/*energyequation*/1; +}; + +//! Use the stokesncni local jacobian operator for the compositional stokes model +SET_TYPE_PROP(BoxStokesncni, LocalResidual, StokesncniLocalResidual<TypeTag>); + +//! the Model property +SET_TYPE_PROP(BoxStokesncni, Model, StokesncniModel<TypeTag>); + +//! the VolumeVariables property +SET_TYPE_PROP(BoxStokesncni, VolumeVariables, StokesncniVolumeVariables<TypeTag>); + +//! the FluxVariables property +SET_TYPE_PROP(BoxStokesncni, FluxVariables, StokesncniFluxVariables<TypeTag>); + +//! Set the indices for the Stokesncni model +SET_TYPE_PROP(BoxStokesncni, Indices, StokesncniCommonIndices<TypeTag>); +} +} +#endif diff --git a/dumux/freeflow/stokesncni/stokesncnifluxvariables.hh b/dumux/freeflow/stokesncni/stokesncnifluxvariables.hh index 75ee28d252aaaf7b503b5f68fa11aa7588136157..bd9945020614d380284f02f6b80b9eebaf56c6ea 100644 --- a/dumux/freeflow/stokesncni/stokesncnifluxvariables.hh +++ b/dumux/freeflow/stokesncni/stokesncnifluxvariables.hh @@ -1,173 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate the - * energy fluxes over a face of a finite volume. - * - * This means concentration temperature gradients and heat conductivity at - * the integration point. - */ -#ifndef DUMUX_STOKESNCNI_FLUX_VARIABLES_HH -#define DUMUX_STOKESNCNI_FLUX_VARIABLES_HH +#ifndef DUMUX_STOKESNCNI_FLUX_VARIABLES_HH_OLD +#define DUMUX_STOKESNCNI_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/freeflow/stokesnc/stokesncfluxvariables.hh> +#warning this header is deprecated, use dumux/freeflow/stokesncni/fluxvariables.hh instead -namespace Dumux -{ - -/*! - * \ingroup BoxStokesncniModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains data which is required to - * calculate the energy fluxes over a face of a finite - * volume for the non-isothermal compositional n-component Stokes box model. - * - * This means temperature gradients and heat conductivity - * at the integration point of a SCV face or boundary face. - */ -template <class TypeTag> -class StokesncniFluxVariables : public StokesncFluxVariables<TypeTag> -{ - typedef StokesncFluxVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - - enum { dim = GridView::dimension }; - - //number of components - enum { numComponents = Indices::numComponents }; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - -public: - StokesncniFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) - { - calculateValues_(problem, element, elemVolVars); - } - - /*! - * \brief Returns the temperature \f$\mathrm{[K]}\f$ at the integration point. - */ - const Scalar temperature() const - { return temperature_; } - - /*! - * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ at the integration point. - */ - const Scalar thermalConductivity() const - { return thermalConductivity_; } - - /*! - * \brief Returns the specific isobaric heat capacity \f$\mathrm{[J/(kg*K)]}\f$ - * at the integration point. - */ - Scalar heatCapacity() const - { return heatCapacity_; } - - /*! - * \brief Return the enthalpy of a component \f$\mathrm{[J/kg]}\f$ at the integration point. - */ - const Scalar componentEnthalpy(int componentIdx) const - { return componentEnthalpy_[componentIdx]; } - - /*! - * \brief Returns the temperature gradient \f$\mathrm{[K/m]}\f$ at the integration point. - */ - const DimVector &temperatureGrad() const - { return temperatureGrad_; } - - /*! - * \brief Return the thermal eddy conductivity \f$\mathrm{[W/(m*K)]}\f$ (if implemented). - */ - const Scalar thermalEddyConductivity() const - { return 0; } - - -protected: - void calculateValues_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - temperature_ = Scalar(0); - thermalConductivity_ = Scalar(0); - heatCapacity_ = Scalar(0); - temperatureGrad_ = Scalar(0); - - // calculate gradients and secondary variables at IPs - for (int scvIdx = 0; - scvIdx < this->fvGeometry_.numScv; - scvIdx++) // loop over vertices of the element - { - temperature_ += elemVolVars[scvIdx].temperature() * - this->face().shapeValue[scvIdx]; - - thermalConductivity_ += elemVolVars[scvIdx].thermalConductivity() * - this->face().shapeValue[scvIdx]; - - heatCapacity_ += elemVolVars[scvIdx].heatCapacity() * - this->face().shapeValue[scvIdx]; - - // the gradient of the temperature at the IP - DimVector grad = this->face().grad[scvIdx]; - grad *= elemVolVars[scvIdx].temperature(); - temperatureGrad_ += grad; - } - Valgrind::CheckDefined(temperature_); - Valgrind::CheckDefined(thermalConductivity_); - Valgrind::CheckDefined(heatCapacity_); - Valgrind::CheckDefined(temperatureGrad_); - - for (unsigned int i = 0; i < numComponents; ++i) - { - componentEnthalpy_[i] = Scalar(0.0); - for (int scvIdx = 0; scvIdx < this->fvGeometry_.numScv; scvIdx++) // loop over vertices of the element - { - componentEnthalpy_[i] += elemVolVars[scvIdx].componentEnthalpy(i) - * this->face().shapeValue[scvIdx]; - } - Valgrind::CheckDefined(componentEnthalpy_[i]); - } - } - - Scalar temperature_; - Scalar thermalConductivity_; - Scalar heatCapacity_; - Scalar componentEnthalpy_[numComponents]; - DimVector temperatureGrad_; -}; - -} // end namespace +#include <dumux/freeflow/stokesncni/fluxvariables.hh> #endif diff --git a/dumux/freeflow/stokesncni/stokesncniindices.hh b/dumux/freeflow/stokesncni/stokesncniindices.hh index fc96fdb6fb3cb51380e340f33c3198cb43ed9915..e527eb235e0848c9fcffd243b77e8e65d5beba42 100644 --- a/dumux/freeflow/stokesncni/stokesncniindices.hh +++ b/dumux/freeflow/stokesncni/stokesncniindices.hh @@ -1,53 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_STOKESNCNI_INDICES_HH_OLD +#define DUMUX_STOKESNCNI_INDICES_HH_OLD -/*! - * \file - * \brief Defines the indices required for the non-isothermal compositional n-component Stokes box model. - */ -#ifndef DUMUX_STOKESNCNI_INDICES_HH -#define DUMUX_STOKESNCNI_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/stokesncni/indices.hh instead -#include <dumux/freeflow/stokesnc/stokesncindices.hh> - -namespace Dumux -{ -// \{ - -/*! - * \ingroup BoxStokesncniModel - * \ingroup ImplicitIndices - * \brief Enumerations for the non-isothermal compositional n-component Stokes model - */ -template <class TypeTag, int PVOffset=0> -struct StokesncniCommonIndices : public StokesncCommonIndices<TypeTag, PVOffset> -{ - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - // number of dimensions - static const int dim = StokesCommonIndices<TypeTag>::dim; - static const int energyEqIdx = PVOffset + dim + FluidSystem::numComponents; //!< The index for the energy balance equation - static const int temperatureIdx = energyEqIdx; //!< The index for temperature in primary variable vectors -}; -// \} -} // end namespace Dumux +#include <dumux/freeflow/stokesncni/indices.hh> #endif diff --git a/dumux/freeflow/stokesncni/stokesncnilocalresidual.hh b/dumux/freeflow/stokesncni/stokesncnilocalresidual.hh index 9a8d49d49e20891c202abe6a980d34e86afd5bed..e91d0e376e9af562473f60fdf32bbc6a2941ce77 100644 --- a/dumux/freeflow/stokesncni/stokesncnilocalresidual.hh +++ b/dumux/freeflow/stokesncni/stokesncnilocalresidual.hh @@ -1,185 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Element-wise calculation of the Jacobian matrix for problems - * using the non-isothermal compositional n-compontent Stokes box model. - * - */ -#ifndef DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH -#define DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH +#ifndef DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH_OLD +#define DUMUX_STOKESNCNI_LOCAL_RESIDUAL_HH_OLD -#include <dumux/freeflow/stokesnc/stokesnclocalresidual.hh> +#warning this header is deprecated, use dumux/freeflow/stokesncni/localresidual.hh instead -#include "stokesncnivolumevariables.hh" -#include "stokesncnifluxvariables.hh" - -namespace Dumux -{ -/*! - * \ingroup BoxStokesncniModel - * \ingroup ImplicitLocalResidual - * \brief Element-wise calculation of the Jacobian matrix for problems - * using the non-isothermal compositional n-component Stokes box model. This class is derived - * from the stokesnc box local residual and adds the energy balance equation. - */ -template<class TypeTag> -class StokesncniLocalResidual : public StokesncLocalResidual<TypeTag> -{ - typedef StokesncLocalResidual<TypeTag> ParentType; - - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { dim = GridView::dimension }; // dimensions - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; // number of equations - enum { numComponents = Indices::numComponents }; // number of components - enum { energyEqIdx = Indices::energyEqIdx}; // equation indices - enum { phaseCompIdx = Indices::phaseCompIdx}; - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - -public: - /*! - * \brief Evaluate the amount the additional quantities to the stokesnc model - * (energy equation). - * - * The result should be averaged over the volume (e.g. phase mass - * inside a sub control volume divided by the volume) - */ - void computeStorage(PrimaryVariables &storage, const int scvIdx, const bool usePrevSol) const - { - // compute the storage term for the transport equation - ParentType::computeStorage(storage, scvIdx, usePrevSol); - - // if flag usePrevSol is set, the solution from the previous - // time step is used, otherwise the current solution is - // used. The secondary variables are used accordingly. This - // is required to compute the derivative of the storage term - // using the implicit euler method. - const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_(); - const VolumeVariables &volVars = elemVolVars[scvIdx]; - - // compute the storage of energy - storage[energyEqIdx] = - volVars.density() * - volVars.internalEnergy(); - } - - /*! - * \brief Evaluates the convective energy flux - * over a face of a sub-control volume and writes the result in - * the flux vector. This method is called by computeFlux in the base class. - * - * \param flux The vector for the fluxes over the SCV/boundary face - * \param fluxVars The flux variables at the current SCV/boundary face - */ - void computeAdvectiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // call computation of the advective fluxes of the stokes model - // (momentum and mass fluxes) - ParentType::computeAdvectiveFlux(flux, fluxVars); - - // vertex data of the upstream and the downstream vertices - const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx()); - const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx()); - - Scalar tmp = fluxVars.normalVelocity(); - tmp *= (this->massUpwindWeight_ * up.density() * up.enthalpy() - + (1.0 - this->massUpwindWeight_) * dn.density() * dn.enthalpy()); - - flux[energyEqIdx] += tmp; - Valgrind::CheckDefined(flux[energyEqIdx]); - } - - /*! - * \brief Evaluates the diffusive component energy flux - * over the face of a sub-control volume. - * - * \param flux The vector for the fluxes over the SCV face - * \param fluxVars The flux variables at the current SCV face - */ - void computeDiffusiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // diffusive mass flux - ParentType::computeDiffusiveFlux(flux, fluxVars); - - // conductive energy flux - computeConductiveFlux(flux, fluxVars); - - // diffusive component energy flux - Scalar sumDiffusiveFluxes = 0; - for (int compIdx=0; compIdx<numComponents; compIdx++) - { - if (compIdx != phaseCompIdx) - { - Valgrind::CheckDefined(fluxVars.moleFractionGrad(compIdx)); - Valgrind::CheckDefined(fluxVars.face().normal); - Valgrind::CheckDefined(fluxVars.diffusionCoeff(compIdx)); - Valgrind::CheckDefined(fluxVars.eddyDiffusivity()); - Valgrind::CheckDefined(fluxVars.molarDensity()); - Valgrind::CheckDefined(FluidSystem::molarMass(compIdx)); - Valgrind::CheckDefined(fluxVars.componentEnthalpy(compIdx)); - Scalar diffusiveFlux = fluxVars.moleFractionGrad(compIdx) - * fluxVars.face().normal - * (fluxVars.diffusionCoeff(compIdx) + fluxVars.eddyDiffusivity()) - * fluxVars.molarDensity(); - sumDiffusiveFluxes += diffusiveFlux; - flux[energyEqIdx] -= diffusiveFlux * fluxVars.componentEnthalpy(compIdx) - * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]; - } - } - - // the diffusive flux of the phase component is the negative of the sum of the component fluxes - flux[energyEqIdx] += sumDiffusiveFluxes * fluxVars.componentEnthalpy(phaseCompIdx) - * FluidSystem::molarMass(phaseCompIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]; - - Valgrind::CheckDefined(flux[energyEqIdx]); - } - - /*! - * \brief Evaluates the conductive energy flux - * over the face of a sub-control volume. - * - * \param flux The vector for the fluxes over the SCV face - * \param fluxVars The flux variables at the current SCV face - */ - void computeConductiveFlux(PrimaryVariables &flux, - const FluxVariables &fluxVars) const - { - // diffusive heat flux - flux[energyEqIdx] -= - fluxVars.temperatureGrad() * fluxVars.face().normal - * (fluxVars.thermalConductivity() + fluxVars.thermalEddyConductivity()); - Valgrind::CheckDefined(flux[energyEqIdx]); - } -}; - -} // end namespace +#include <dumux/freeflow/stokesncni/localresidual.hh> #endif diff --git a/dumux/freeflow/stokesncni/stokesncnimodel.hh b/dumux/freeflow/stokesncni/stokesncnimodel.hh index ab319cab9b03a3c2aade2bbc6257c8269986bc44..0f2d54e4e8c2d54ac4e0974033259d0db31dcf75 100644 --- a/dumux/freeflow/stokesncni/stokesncnimodel.hh +++ b/dumux/freeflow/stokesncni/stokesncnimodel.hh @@ -1,211 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Adaption of the box scheme to the non-isothermal - * n-component Stokes model. - */ -#ifndef DUMUX_STOKESNCNI_MODEL_HH -#define DUMUX_STOKESNCNI_MODEL_HH +#ifndef DUMUX_STOKESNCNI_MODEL_HH_OLD +#define DUMUX_STOKESNCNI_MODEL_HH_OLD -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> +#warning this header is deprecated, use dumux/freeflow/stokesncni/model.hh instead -#include "stokesncnilocalresidual.hh" -#include "stokesncniproperties.hh" - -namespace Dumux { -/*! - * \ingroup BoxStokesncniModel - * \brief Adaption of the box scheme to the non-isothermal - * n-component Stokes model. - * - * This model implements a non-isothermal n-component Stokes flow of a fluid - * solving a momentum balance, a mass balance, conservation equations for \f$n-1\f$ components, - * and one balance equation for the energy. - * - * The momentum balance: - * \f[ - * \frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t} - * + \text{div} \left( p_g {\bf {I}} - * - \mu_g \left( \textbf{grad}\, \boldsymbol{v}_g - * + \textbf{grad}\, \boldsymbol{v}_g^T \right) \right) - * - \varrho_g {\bf g} = 0 - * \f] - * By setting the property <code>EnableNavierStokes</code> to <code>true</code> the Navier-Stokes - * equation can be solved. In this case an additional term - * \f[ - * + \text{div} \left( \varrho_g \boldsymbol{v}_g \boldsymbol{v}_g \right) - * \f] - * is added to the momentum balance equation. - * - * The mass balance equation: - * \f[ - * \frac{\partial \varrho_g}{\partial t} - * + \text{div} \left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0 - * \f] - * - * The component mass balance equations: - * \f[ - * \frac{\partial \left(\varrho_g X_g^\kappa\right)}{\partial t} - * + \text{div} \left( \varrho_g {\boldsymbol{v}}_g X_g^\kappa - * - D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \textbf{grad}\, x_g^\kappa \right) - * - q_g^\kappa = 0 - * \f] - * Please note that, even though it is n-component model, the diffusive - * fluxes are still calculated with binary diffusion. - * - * The energy balance equation: - * \f[ - * \frac{\partial (\varrho_g u_g)}{\partial t} - * + \text{div} \left( \varrho_g h_g {\boldsymbol{v}}_g - * - \sum_\kappa \left[ h^\kappa_g D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} - * \textbf{grad}\, x^\kappa_g \right] - * - \lambda_g \textbf{grad}\, T \right) - q_T = 0 - * \f] - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class StokesncniModel : public StokesncModel<TypeTag> -{ - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { dim = GridView::dimension }; - enum { transportCompIdx = Indices::transportCompIdx }; - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - enum { useMoles = GET_PROP_VALUE(TypeTag, UseMoles) }; - enum { numComponents = Indices::numComponents }; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - -public: - //! \copydoc ImplicitModel::addOutputVtkFields - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VelocityField; - - const Scalar scale_ = GET_PROP_VALUE(TypeTag, Scaling); - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - ScalarField &pn = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField &T = *writer.allocateManagedBuffer(numVertices); - ScalarField &h = *writer.allocateManagedBuffer(numVertices); - ScalarField *moleFraction[numComponents]; - for (int i = 0; i < numComponents; ++i) - moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - ScalarField *massFraction[numComponents]; - for (int i = 0; i < numComponents; ++i) - massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - VelocityField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - - unsigned numElements = this->gridView_().size(0); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - - FVElementGeometry fvGeometry; - VolumeVariables volVars; - ElementBoundaryTypes elemBcTypes; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int idx = this->elementMapper().index(element); - - rank[idx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element, fvGeometry); - - int numLocalVerts = element.subEntities(dim); - - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pn[vIdxGlobal] = volVars.pressure()*scale_; - delP[vIdxGlobal] = volVars.pressure()*scale_ - 1e5; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - { - (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); - (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); - Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); - Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); - } - - T [vIdxGlobal] = volVars.temperature(); - - rho[vIdxGlobal] = volVars.density()*scale_*scale_*scale_; - mu[vIdxGlobal] = volVars.dynamicViscosity()*scale_; - h[vIdxGlobal] = volVars.enthalpy(); - velocity[vIdxGlobal] = volVars.velocity(); - velocity[vIdxGlobal] *= 1/scale_; - } - } - writer.attachVertexData(T, "temperature"); - writer.attachVertexData(pn, "pg"); - writer.attachVertexData(delP, "delP"); - - for (int j = 0; j < numComponents; ++j) - { - std::ostringstream moleFrac, massFrac; - moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); - - massFrac << "X_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); - } - - writer.attachVertexData(h, "h"); - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(velocity, "v", dim); - - } -}; - -} - -#include "stokesncnipropertydefaults.hh" +#include <dumux/freeflow/stokesncni/model.hh> #endif diff --git a/dumux/freeflow/stokesncni/stokesncniproperties.hh b/dumux/freeflow/stokesncni/stokesncniproperties.hh index 9758fd7eac83a1b3395966f9dcd8a217c7d23a72..6a20ea4c0a3696e8140e109823823ecddfa3b168 100644 --- a/dumux/freeflow/stokesncni/stokesncniproperties.hh +++ b/dumux/freeflow/stokesncni/stokesncniproperties.hh @@ -1,48 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesncniModel - * - * \file - * - * \brief Defines the additional properties required for the non-isothermal compositional n-compontent - * Stokes box model. - */ -#ifndef DUMUX_STOKESNCNI_PROPERTIES_HH -#define DUMUX_STOKESNCNI_PROPERTIES_HH +#ifndef DUMUX_STOKESNCNI_PROPERTIES_HH_OLD +#define DUMUX_STOKESNCNI_PROPERTIES_HH_OLD -#include <dumux/freeflow/stokesnc/stokesncproperties.hh> +#warning this header is deprecated, use dumux/freeflow/stokesncni/properties.hh instead -namespace Dumux -{ -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// +#include <dumux/freeflow/stokesncni/properties.hh> -//! The type tag for the non-isothermal compositional n-component Stokes problems -NEW_TYPE_TAG(BoxStokesncni, INHERITS_FROM(BoxStokesnc)); - -} - -} #endif diff --git a/dumux/freeflow/stokesncni/stokesncnipropertydefaults.hh b/dumux/freeflow/stokesncni/stokesncnipropertydefaults.hh index 772181c14693ba7251a1fcf93c35f8064b4ab047..d2add957992b16adfe6acbf13f889e72cd84be93 100644 --- a/dumux/freeflow/stokesncni/stokesncnipropertydefaults.hh +++ b/dumux/freeflow/stokesncni/stokesncnipropertydefaults.hh @@ -1,73 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxStokesncniModel - * - * \file - * - * \brief Sets default properties for the non-isothermal compositional - * n-component Stokes box model. - */ -#ifndef DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH -#define DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH +#ifndef DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_STOKESNCNI_PROPERTY_DEFAULTS_HH_OLD +#warning this header is deprecated, use dumux/freeflow/stokesncni/propertydefaults.hh instead -#include "stokesncnifluxvariables.hh" -#include "stokesncniindices.hh" -#include "stokesncnilocalresidual.hh" -#include "stokesncnimodel.hh" -#include "stokesncnivolumevariables.hh" +#include <dumux/freeflow/stokesncni/propertydefaults.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -SET_PROP(BoxStokesncni, NumEq) //!< set the number of equations -{ - typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - static const int dim = Grid::dimension; - public: - static constexpr int value = dim + FluidSystem::numComponents +/*energyequation*/1; -}; - -//! Use the stokesncni local jacobian operator for the compositional stokes model -SET_TYPE_PROP(BoxStokesncni, LocalResidual, StokesncniLocalResidual<TypeTag>); - -//! the Model property -SET_TYPE_PROP(BoxStokesncni, Model, StokesncniModel<TypeTag>); - -//! the VolumeVariables property -SET_TYPE_PROP(BoxStokesncni, VolumeVariables, StokesncniVolumeVariables<TypeTag>); - -//! the FluxVariables property -SET_TYPE_PROP(BoxStokesncni, FluxVariables, StokesncniFluxVariables<TypeTag>); - -//! Set the indices for the Stokesncni model -SET_TYPE_PROP(BoxStokesncni, Indices, StokesncniCommonIndices<TypeTag>); -} -} #endif diff --git a/dumux/freeflow/stokesncni/stokesncnivolumevariables.hh b/dumux/freeflow/stokesncni/stokesncnivolumevariables.hh index f53303532f75eb6effbed116049ce56f0ec68e70..fbe018811602ef9340e02022ea01310d67d8778e 100644 --- a/dumux/freeflow/stokesncni/stokesncnivolumevariables.hh +++ b/dumux/freeflow/stokesncni/stokesncnivolumevariables.hh @@ -1,141 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief Contains the supplemental quantities, which are constant within a - * finite volume in the non-isothermal compositional n-component Stokes box model. - */ -#ifndef DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH -#define DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH +#ifndef DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH_OLD +#define DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH_OLD -#include <dumux/freeflow/stokesnc/stokesncvolumevariables.hh> -#include "stokesncniproperties.hh" +#warning this header is deprecated, use dumux/freeflow/stokesncni/volumevariables.hh instead -namespace Dumux -{ - -/*! - * \ingroup BoxStokesncniModel - * \ingroup ImplicitVolumeVariables - * \brief Contains the quantities which are are constant within a - * finite volume in the non-isothermal two-component n-component Stokes - * box model. - */ -template <class TypeTag> -class StokesncniVolumeVariables : public StokesncVolumeVariables<TypeTag> -{ - typedef StokesncVolumeVariables<TypeTag> ParentType; - - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - enum { temperatureIdx = Indices::temperatureIdx }; - - typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; - -public: - /*! - * \copydoc ImplicitVolumeVariables::update() - */ - void update(const PrimaryVariables &priVars, - const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx, - bool isOldSol) - { - // vertex update data for the mass balance - ParentType::update(priVars, - problem, - element, - fvGeometry, - scvIdx, - isOldSol); - } - - /*! - * \brief Returns the total internal energy of the fluid phase in the - * sub-control volume. - */ - Scalar internalEnergy() const - { return this->fluidState_.internalEnergy(phaseIdx); } - - /*! - * \brief Returns the total enthalpy of the fluid phase in the sub-control - * volume. - */ - Scalar enthalpy() const - { return this->fluidState_.enthalpy(phaseIdx); } - - /*! - * \brief Return the specific isobaric heat capacity \f$\mathrm{[J/(kg*K)]}\f$ - * in the sub-control volume. - */ - Scalar heatCapacity() const - { return FluidSystem::heatCapacity(this->fluidState_, phaseIdx); } - - /*! - * \brief Returns the component enthalpy \f$\mathrm{[J/(kg*K)]}\f$ in the sub-control volume. - */ - Scalar componentEnthalpy(unsigned int componentIdx) const - { return FluidSystem::componentEnthalpy(this->fluidState_, phaseIdx, componentIdx); } - - /*! - * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ - * of the fluid phase in the sub-control volume. - */ - Scalar thermalConductivity() const - { return FluidSystem::thermalConductivity(this->fluidState_, phaseIdx); } - - -protected: - // this method gets called by the parent class. since this method - // is protected, we are friends with our parent... - friend class StokesVolumeVariables<TypeTag>; - - static Scalar temperature_(const PrimaryVariables &priVars, - const Problem& problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int scvIdx) - { - return priVars[temperatureIdx]; - } - - template<class ParameterCache> - static Scalar enthalpy_(const FluidState& fluidState, - const ParameterCache& paramCache, - const int phaseIdx) - { - return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); - } -}; - -} // end namespace +#include <dumux/freeflow/stokesncni/volumevariables.hh> #endif diff --git a/dumux/freeflow/stokesncni/volumevariables.hh b/dumux/freeflow/stokesncni/volumevariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..eb748668110d437fbfa1c38a2c52bb453b7368cc --- /dev/null +++ b/dumux/freeflow/stokesncni/volumevariables.hh @@ -0,0 +1,141 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * + * \brief Contains the supplemental quantities, which are constant within a + * finite volume in the non-isothermal compositional n-component Stokes box model. + */ +#ifndef DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH +#define DUMUX_STOKESNCNI_VOLUME_VARIABLES_HH + +#include <dumux/freeflow/stokesnc/volumevariables.hh> +#include "properties.hh" + +namespace Dumux +{ + +/*! + * \ingroup BoxStokesncniModel + * \ingroup ImplicitVolumeVariables + * \brief Contains the quantities which are are constant within a + * finite volume in the non-isothermal two-component n-component Stokes + * box model. + */ +template <class TypeTag> +class StokesncniVolumeVariables : public StokesncVolumeVariables<TypeTag> +{ + typedef StokesncVolumeVariables<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + enum { temperatureIdx = Indices::temperatureIdx }; + + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + +public: + /*! + * \copydoc ImplicitVolumeVariables::update() + */ + void update(const PrimaryVariables &priVars, + const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int scvIdx, + bool isOldSol) + { + // vertex update data for the mass balance + ParentType::update(priVars, + problem, + element, + fvGeometry, + scvIdx, + isOldSol); + } + + /*! + * \brief Returns the total internal energy of the fluid phase in the + * sub-control volume. + */ + Scalar internalEnergy() const + { return this->fluidState_.internalEnergy(phaseIdx); } + + /*! + * \brief Returns the total enthalpy of the fluid phase in the sub-control + * volume. + */ + Scalar enthalpy() const + { return this->fluidState_.enthalpy(phaseIdx); } + + /*! + * \brief Return the specific isobaric heat capacity \f$\mathrm{[J/(kg*K)]}\f$ + * in the sub-control volume. + */ + Scalar heatCapacity() const + { return FluidSystem::heatCapacity(this->fluidState_, phaseIdx); } + + /*! + * \brief Returns the component enthalpy \f$\mathrm{[J/(kg*K)]}\f$ in the sub-control volume. + */ + Scalar componentEnthalpy(unsigned int componentIdx) const + { return FluidSystem::componentEnthalpy(this->fluidState_, phaseIdx, componentIdx); } + + /*! + * \brief Returns the thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ + * of the fluid phase in the sub-control volume. + */ + Scalar thermalConductivity() const + { return FluidSystem::thermalConductivity(this->fluidState_, phaseIdx); } + + +protected: + // this method gets called by the parent class. since this method + // is protected, we are friends with our parent... + friend class StokesVolumeVariables<TypeTag>; + + static Scalar temperature_(const PrimaryVariables &priVars, + const Problem& problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int scvIdx) + { + return priVars[temperatureIdx]; + } + + template<class ParameterCache> + static Scalar enthalpy_(const FluidState& fluidState, + const ParameterCache& paramCache, + const int phaseIdx) + { + return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); + } +}; + +} // end namespace + +#endif diff --git a/dumux/freeflow/zeroeq/fluxvariables.hh b/dumux/freeflow/zeroeq/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..ed4b51959e10fcfca7699d172641b23f832ea196 --- /dev/null +++ b/dumux/freeflow/zeroeq/fluxvariables.hh @@ -0,0 +1,319 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * the fluxes of the ZeroEq model over a face of a finite volume. + * + * This means the methods to calculate the eddy viscosity. + */ +#ifndef DUMUX_ZEROEQ_FLUX_VARIABLES_HH +#define DUMUX_ZEROEQ_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/common/valgrind.hh> + +#include <dumux/freeflow/stokes/fluxvariables.hh> +#include <dumux/freeflow/zeroeq/indices.hh> +#include <dumux/freeflow/zeroeq/properties.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains data which is required to + * calculate the component fluxes over a face of a finite + * volume for a ZeroEq model. + * + * This means the methods to calculate the eddy viscosity. + */ +template <class TypeTag> +class ZeroEqFluxVariables : public GET_PROP_TYPE(TypeTag, BaseStokesFluxVariables) +{ + typedef typename GET_PROP_TYPE(TypeTag, BaseStokesFluxVariables) ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + + enum { dim = GridView::dimension }; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + +public: + ZeroEqFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) + , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + , eddyViscosityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) + , karmanConstant_(GET_PROP_VALUE(TypeTag, KarmanConstant)) + { + dynamicEddyViscosity_ = 0.0; + mixingLength_ = 0.0; + dynamicEddyViscosityInner_ = 0.0; + dynamicEddyViscosityOuter_ = 0.0; + fz_ = 0.0; + posIdx_ = problem.model().getPosIdx(globalPos()); + wallIdx_ = problem.model().getWallIdx(globalPos(), posIdx_); + distanceToWallRough_ = std::abs(problem.model().distanceToWallRough(globalPos(), wallIdx_, posIdx_)); + distanceToWallReal_ = std::abs(problem.model().distanceToWallReal(globalPos(), wallIdx_, posIdx_)); + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + maxVelocity_[dimIdx] = problem.model().wall[wallIdx_].maxVelocity[posIdx_][dimIdx]; + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + minVelocity_[dimIdx] = problem.model().wall[wallIdx_].minVelocity[posIdx_][dimIdx]; + velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; + frictionVelocityWall_ = sqrt(problem.model().wall[wallIdx_].wallShearStress[posIdx_] + / problem.model().wall[wallIdx_].wallDensity[posIdx_]); + yPlusRough_ = distanceToWallRough_ * frictionVelocityWall_ / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; + + // calculation of an eddy viscosity only makes sense with Navier-Stokes equation + if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) + calculateEddyViscosity_(problem, element, elemVolVars); + } + +protected: + /*! + * \brief This function calculates the dynamic viscosity. + * + * The eddy viscosity is added to the viscosity in stokeslocalresidual.hh at each scv + * face. + */ + void calculateEddyViscosity_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + // no turbulence model + if (eddyViscosityModel_ == EddyViscosityIndices::noEddyViscosityModel) + return; + + // Prandtl mixing length + // e.g. Wilcox, D. C., Turbulence Modeling for CFD, 2006 + else if (eddyViscosityModel_ == EddyViscosityIndices::prandtl) + { + mixingLength_ = distanceToWallRough_ * karmanConstant_; + dynamicEddyViscosity_ = this->density() * mixingLength() * mixingLength() * std::abs(velGrad_); + } + + // modified Van-Driest + // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 + else if (eddyViscosityModel_ == EddyViscosityIndices::modifiedVanDriest) + { + Scalar aPlus = 26.0; + Scalar bPlus = 0.26; + // eddy viscosity can only be calculated correctly for non-zero distance to walls + mixingLength_ = 0.0; + if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) + mixingLength_= karmanConstant_ * distanceToWallRough_ + * (1.0 - std::exp(-yPlusRough_ / aPlus )) + / std::sqrt(1.0 - std::exp(-bPlus * yPlusRough_)); + + dynamicEddyViscosity_ = this->density() * mixingLength() * mixingLength() * std::abs(velGrad_); + } + + // Baldwin and Lomax + // Baldwin, B. S. & Lomax, H. "Thin Layer Approximation and Algebraic Model for Seperated Turbulent Flows" + // AIAA Journal, 1978, 78--257, 1-9 + else if (eddyViscosityModel_ == EddyViscosityIndices::baldwinLomax) + { + // LAW CONSTANTS + const Scalar aPlus = 26.0; + const Scalar cCP = 1.6; + const Scalar cKleb = 0.30; + const Scalar cWK = 0.25; + const Scalar kUpper = 0.0168; + + // Calculate muInner + mixingLength_ = 0.0; + if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) + mixingLength_ = karmanConstant_ * distanceToWallRough_ + * (1.0 - std::exp(-yPlusRough_ / aPlus )); + Scalar omega1 = this->velocityGrad_[0][1] - this->velocityGrad_[1][0]; + Scalar omega2 = 0.0; + Scalar omega3 = 0.0; + if (dim == 3) + { + omega2 = this->velocityGrad_[1][2] - this->velocityGrad_[2][1]; + omega3 = this->velocityGrad_[2][0] - this->velocityGrad_[0][2]; + } + Scalar omega = sqrt(omega1 * omega1 + omega2 * omega2 + omega3 * omega3); + dynamicEddyViscosityInner_ = this->density() * mixingLength() * mixingLength() * omega; + + // Calculate muOuter + fz_ = 0.0; + if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) + fz_ = distanceToWallRough_ * omega * (1.0 - std::exp(-yPlusRough_ / aPlus )); + Scalar fMax = problem.model().wall[wallIdx_].fMax[posIdx_]; + Scalar yMax = std::abs(problem.model().wall[wallIdx_].yMax[posIdx_]); + Scalar uDiff = maxVelocity_.two_norm() - minVelocity_.two_norm(); + + Scalar f1 = yMax * fMax; + Scalar f2 = cWK * yMax * uDiff * uDiff / fMax; + Scalar fWake = fmin(f1, f2); + Scalar fKleb = 1 / (1 + 5.5 * std::pow(cKleb * distanceToWallRough_ / yMax, 6.0)); + dynamicEddyViscosityOuter_ = this->density() * kUpper * cCP * fWake * fKleb; + + bool inner = problem.model().useViscosityInner(this->face().ipGlobal, posIdx_); + + // muOuter can only be calculated correctly for non-zero fmax + if (fMax == 0) + inner = true; + + if (inner) + dynamicEddyViscosity_ = dynamicEddyViscosityInner_; + else + dynamicEddyViscosity_ = dynamicEddyViscosityOuter_; + } + + else + { + DUNE_THROW(Dune::NotImplemented, "This eddy viscosity model is not implemented."); + } + + Valgrind::CheckDefined(dynamicEddyViscosity_); + Valgrind::CheckDefined(dynamicEddyViscosityInner_); + Valgrind::CheckDefined(dynamicEddyViscosityOuter_); + } + +public: + /*! + * \brief Returns the global coordinates of the integration point. + */ + DimVector globalPos() const + { return this->face().ipGlobal; } + + /*! + * \brief Returns the mixing length \f$\mathrm{[m]}\f$. + */ + Scalar mixingLength() const + { return mixingLength_; } + + /*! + * \brief Returns the dynamic eddy viscosity + * \f$\mathrm{[Pa \cdot s]} = \mathrm{[N \cdot s/m^2]}\f$. + */ + const Scalar dynamicEddyViscosity() const + { return dynamicEddyViscosity_; } + + /*! + * \brief Returns the kinematic eddy viscosity + * \f$\mathrm{[m^2/s]}\f$ (if implemented). + */ + const Scalar kinematicEddyViscosity() const + { return dynamicEddyViscosity() / this->density(); } + + /*! + * \brief Returns the inner dynamic eddy Viscosity (only Baldwin-Lomax model) + * \f$\mu_\textrm{inner}\f$ in \f$\mathrm{[N\cdot s/m^2]}\f$. + */ + Scalar dynamicEddyViscosityInner() const + { return dynamicEddyViscosityInner_; } + + /*! + * \brief Returns the outer dynamic eddy Viscosity (only Baldwin-Lomax model). + * \f$\mu_\textrm{outer}\f$ in \f$\mathrm{[N\cdot s/m^2]}\f$. + */ + Scalar dynamicEddyViscosityOuter() const + { return dynamicEddyViscosityOuter_; } + + /*! + * \brief Returns the value of the f-function. + * + * \f$\mathrm{f = y \omega \left( 1 - exp \left[ -y^+ / A^+ \right] \right)}\f$.<br> + * y = distanceToWall + */ + Scalar fz() const + { return fz_; } + + /*! + * \brief Returns the friction velocity at the wall \f$\mathrm{[kg/(m*s^2)]}\f$. + */ + Scalar frictionVelocityWall() const + { return frictionVelocityWall_; } + + /*! + * \brief Returns the distance to the corresponding Wall, including surface roughness \f$\mathrm{[m]}\f$. + */ + Scalar distanceToWallRough() const + { return distanceToWallRough_; } + + /*! + * \brief Returns the real distance to the corresponding Wall \f$\mathrm{[m]}\f$. + */ + Scalar distanceToWallReal() const + { return distanceToWallReal_; } + + /*! + * \brief Returns dimensionless wall distance, including surface roughness \f$\mathrm{[-]}\f$. + */ + Scalar yPlusRough() const + { return yPlusRough_; } + + /*! + * \brief Returns a dimensionless velocity \f$\mathrm{[-]}\f$. + */ + Scalar uPlus() const + { return this->velocity()[flowNormal_] / frictionVelocityWall(); } + + /*! + * \brief Returns the Karman constant \f$\mathrm{[-]}\f$. + */ + Scalar karmanConstant() const + { return karmanConstant_; } + +private: + const int flowNormal_; + const int wallNormal_; + const int eddyViscosityModel_; + const Scalar karmanConstant_; + + int wallIdx_; + int posIdx_; + Scalar yPlusRough_; + Scalar distanceToWallReal_; + Scalar distanceToWallRough_; + Scalar sandGrainRoughness_; + Scalar sandGrainRoughnessDimensionless_; + + Scalar velGrad_; + Scalar frictionVelocityWall_; + DimVector maxVelocity_; + DimVector minVelocity_; + + Scalar mixingLength_; + Scalar dynamicEddyViscosity_; + Scalar dynamicEddyViscosityInner_; + Scalar dynamicEddyViscosityOuter_; + Scalar fz_; + + Scalar eps_; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQ_FLUX_VARIABLES_HH diff --git a/dumux/freeflow/zeroeq/indices.hh b/dumux/freeflow/zeroeq/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..30b7bccb9641123b694282c2bac45b5231bb65ff --- /dev/null +++ b/dumux/freeflow/zeroeq/indices.hh @@ -0,0 +1,61 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * \brief Defines the indices required for the ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQ_INDICES_HH +#define DUMUX_ZEROEQ_INDICES_HH + +#include <dumux/freeflow/stokes/indices.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqModel + * \brief The indices for the eddy viscosity model. + */ +struct EddyViscosityIndices +{ + // Eddy Viscosity Model Indices + static const int noEddyViscosityModel = 0; + static const int prandtl = 1; + static const int modifiedVanDriest = 2; + static const int baldwinLomax = 3; +}; + +/*! + * \ingroup BoxZeroEqModel + * \ingroup ImplicitIndices + * \brief The common indices for the isothermal ZeroEq model. + * + * \tparam PVOffset The first index in a primary variable vector. + */ +template <class TypeTag, int PVOffset = 0> +struct ZeroEqCommonIndices : public StokesCommonIndices<TypeTag, PVOffset> +{ + static const int scvDataPrecision = 5; + static const int scvDataWidth = scvDataPrecision + 10; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQ_INDICES_HH diff --git a/dumux/freeflow/zeroeq/model.hh b/dumux/freeflow/zeroeq/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..0ebd34a56591f7f209f751638e0316cd41ed720d --- /dev/null +++ b/dumux/freeflow/zeroeq/model.hh @@ -0,0 +1,1006 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for all models which use the ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQ_MODEL_HH +#define DUMUX_ZEROEQ_MODEL_HH + +#include "indices.hh" +#include "fluxvariables.hh" +#include "problem.hh" +#include "properties.hh" +#include <dumux/freeflow/stokes/model.hh> + +namespace Dumux +{ +/*! + * \ingroup BoxZeroEqModel + * \brief Adaption of the box scheme to the ZeroEq model. + * + * This model implements an single-phase isothermal free flow + * solving the mass and the momentum balance. For the momentum balance + * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation + * (algebraic) turbulence model is used. + * + * Mass balance: + * \f[ + * \frac{\partial \varrho_\textrm{g}}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) + * - q_\textrm{g} = 0 + * \f] + * + * Momentum Balance: + * \f[ + * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} + * + \text{div} \left( + * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} + * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] + * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} + * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) + * \right) + * + \left(p_\textrm{g} {\bf {I}} \right) + * - \varrho_\textrm{g} {\bf g} = 0 + * \f] + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class ZeroEqModel : public GET_PROP_TYPE(TypeTag, BaseStokesModel) +{ + typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), + bboxMinIsWall = GET_PROP_VALUE(TypeTag, BBoxMinIsWall), + bboxMaxIsWall = GET_PROP_VALUE(TypeTag, BBoxMaxIsWall), + walls = (bboxMinIsWall ? 1 : 0) + (bboxMaxIsWall ? 1 : 0) + }; + + typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements; + typedef Dune::ReferenceElement<Scalar, dim> ReferenceElement; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + + +public: + ZeroEqModel() + : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + { + eps_ = 1e-6; + + // check whether sand grain roughness may be used + if ((GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 + || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) + && surfaceRoughnessNotImplemented()) + { + Dune::dwarn << "warning: surface roughness is not implemented for eddy viscosity model " + << GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel) + << "." << std::endl; + } + } + + /*! + * \brief Write vtk and additional plain text scv-data. + * + * The routine for the vtk data should be the same as in dumux-stable. + * + * The scv-data files contain mainly information for the turbulence model. + * + * \param sol The solution vector. + * \param writer The writer for multi-file VTK datasets. + */ + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + unsigned numElements = this->gridView_().size(0); + ScalarField &pN = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + ScalarField &mut = *writer.allocateManagedBuffer(numElements); + ScalarField &nut = *writer.allocateManagedBuffer(numElements); + ScalarField &lmix = *writer.allocateManagedBuffer(numElements); + ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + + // write volume values to .vtu and .csv + char fileName[30]; + sprintf(fileName, "%s%05d%s", "volVarsData-", this->problem_().timeManager().timeStepIndex(), ".csv"); + std::ofstream volVarsFile(fileName, std::ios_base::out); + asImp_().writeVolVarsHeader(volVarsFile); + volVarsFile << std::endl; + + FVElementGeometry fvGeometry; + VolumeVariables volVars; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int idx = this->elementMapper().index(element); + rank[idx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + + int numLocalVerts = element.template subEntities(dim); + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pN[vIdxGlobal] = volVars.pressure(); + delP[vIdxGlobal] = volVars.pressure() - 1e5; + rho[vIdxGlobal] = volVars.density(); + mu[vIdxGlobal] = volVars.dynamicViscosity(); + velocity[vIdxGlobal] = volVars.velocity(); + + asImp_().writeVolVarsData(volVarsFile, volVars); + volVarsFile << std::endl; + } + } + volVarsFile.close(); + + writer.attachVertexData(pN, "P"); + writer.attachVertexData(delP, "delP"); + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(velocity, "v", dim); + + // ensure that the actual values are given out + asImp_().updateWallProperties(); + + // write flux values to .vtu and .csv + sprintf(fileName, "%s%05d%s", "fluxVarsData-", this->problem_().timeManager().timeStepIndex(), ".csv"); + std::ofstream fluxVarsFile(fileName, std::ios_base::out); + asImp_().writeFluxVarsHeader(fluxVarsFile); + fluxVarsFile << std::endl; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + unsigned int numFluxVars = 0; + Scalar sumDynamicEddyViscosity = 0.0; + Scalar sumKinematicEddyViscosity = 0.0; + Scalar sumMixingLength = 0.0; + Scalar sumUPlus = 0.0; + Scalar sumYPlus = 0.0; + + for (const auto& intersection : Dune::intersections(this->gridView_(), element)) + { + int fIdx = intersection.indexInInside(); + + FluxVariables fluxVars(this->problem_(), element, fvGeometry, + fIdx, elemVolVars, false); + + asImp_().writeFluxVarsData(fluxVarsFile, fluxVars); + fluxVarsFile << std::endl; + + sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); + sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); + sumMixingLength += fluxVars.mixingLength(); + sumUPlus += fluxVars.uPlus(); + sumYPlus += fluxVars.yPlusRough(); + numFluxVars += 1; + } + + int eIdxGlobal = this->elementMapper().index(element); + mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; + nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; + lmix[eIdxGlobal] = sumMixingLength / numFluxVars; + uPlus[eIdxGlobal] = sumUPlus / numFluxVars; + yPlus[eIdxGlobal] = sumYPlus / numFluxVars; + } + fluxVarsFile.close(); + + writer.attachCellData(mut, "mu_t"); + writer.attachCellData(nut, "nu_t"); + writer.attachCellData(lmix, "l_mix"); + writer.attachCellData(uPlus, "u^+"); + writer.attachCellData(yPlus, "y^+"); + } + + + /*! + * \brief Writes the header for the volVarsData.csv file + * + * \param stream The output file stream + */ + void writeVolVarsHeader(std::ofstream &stream) + { + std::cout << "Writing volVars file" << std::endl; + stream << "#globalPos[0]" + << "," << "globalPos[1]" + << "," << "velocity[0]" + << "," << "velocity[1]" + << "," << "pressure" + << "," << "density" + << "," << "temperature"; + } + + /*! + * \brief Writes the data into the volVarsData.csv file + * + * \param stream The output file stream + * \param volVars The volume variables + */ + void writeVolVarsData(std::ofstream &stream, const VolumeVariables &volVars) + { + stream << volVars.globalPos()[0] + << "," << volVars.globalPos()[1] + << "," << volVars.velocity()[0] + << "," << volVars.velocity()[1] + << "," << volVars.pressure() + << "," << volVars.density() + << "," << volVars.temperature(); + } + + /*! + * \brief Writes the header for the fluxVarsData.csv file + * + * \param stream The output file stream + */ + void writeFluxVarsHeader(std::ofstream &stream) + { + std::cout << "Writing fluxVars file" << std::endl; + stream << "#globalPos[0]" + << "," << "globalPos[1]" + << "," << "uPlus" + << "," << "yPlus" + << "," << "uStar" + << "," << "dynamicEddyViscosity" + << "," << "kinematicEddyViscosity" + << "," << "mixingLength"; + } + + /*! + * \brief Writes the data into the fluxVarsData.csv file + * + * \param stream The output file stream + * \param fluxVars The flux variables + */ + void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) + { + stream << fluxVars.globalPos()[0] + << "," << fluxVars.globalPos()[1] + << "," << fluxVars.uPlus() + << "," << fluxVars.yPlusRough() + << "," << fluxVars.frictionVelocityWall() + << "," << fluxVars.dynamicEddyViscosity() + << "," << fluxVars.kinematicEddyViscosity() + << "," << fluxVars.mixingLength(); + } + + /*! + * \name Wall properties + */ + // \{ + + /*! + * \brief Container for all necessary information, needed to calculate the + * eddy viscosity at a certain point in relation to the wall distance + * and fluid/flow properties at the wall. + */ + struct WallProperties + { + public: + bool isBBoxMinWall; //!< Actual wall properties are located on bboxmin or bboxmax. + Scalar wallPos[intervals]; //!< Position of the wall interval in global coordinates. + Scalar sandGrainRoughness[intervals]; //!< Sand grain roughness. + Scalar boundaryLayerThickness[intervals]; //!< Domain influenced by this wall. + Scalar boundaryLayerThicknessCalculated[intervals]; //!< Boundary layer thickness based on v = v_99. + Scalar viscousSublayerThicknessCalculated[intervals]; //!< Viscous sublayer thickness based on y^+ <= 5. + Scalar crossLength[intervals]; //!< Switching point for the Baldwin-Lomax model. + Scalar maxVelocity[intervals][dim]; //!< Max velocity related to this wall. + Scalar maxVelocityAbs[intervals][dim]; //!< Max velocity at this interval position. + Scalar minVelocity[intervals][dim]; //!< Min velocity related to this wall. + Scalar wallDensity[intervals]; //!< Fluid density at the wall. + Scalar wallKinematicViscosity[intervals]; //!< Kinematic viscosity at the wall. + Scalar wallVelGrad[intervals]; //!< Velocity gradient at the wall, in wall normal direction. + Scalar wallShearStress[intervals]; //!< Shear stress at the wall. + Scalar fMax[intervals]; //!< Max value of the f function for Baldwin-Lomax model. + Scalar yMax[intervals]; //!< Distance of position where fMax occurs. + Scalar maxMassFraction[intervals]; //!< Max mass fraction related to this wall. + Scalar maxMoleFraction[intervals]; //!< Max mole fraction related to this wall. + Scalar maxTemperature[intervals]; //!< Max temperature related to this wall. + int isInterpolated[intervals]; //!< Value is only interpolated between neighboring wall intervals. + int fluxValuesCount[intervals]; //!< Number of flux values contributing to the interval. + int wallValuesCount[intervals]; //!< Number of values contributing properties directly at the wall. + bool headerWritten[intervals]; //!< Header of scv-data file was already written. + WallProperties() {} //!< Constructor for wall properties. + }; + WallProperties wall[walls]; + + /*! + * \brief Initializes the wall structure with values. + * + * This should only be done before updating (preTimeStepFunction and + * only once per time Step), because the crossLength + * for the Baldwin Lomax model is reset. + */ + void resetWallProperties() + { + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + { + for (int posIdx = 0; posIdx < intervals; ++posIdx) + { + if (walls == 1) + { + if (bboxMinIsWall) + { + wall[wallIdx].wallPos[posIdx] = this->problem_().bBoxMin()[wallNormal_]; + wall[wallIdx].boundaryLayerThickness[posIdx] = this->problem_().bBoxMax()[wallNormal_] - this->problem_().bBoxMin()[wallNormal_] + eps_; + wall[wallIdx].isBBoxMinWall = true; + wall[wallIdx].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness); + } + if (bboxMaxIsWall) + { + wall[wallIdx].wallPos[posIdx] = this->problem_().bBoxMax()[wallNormal_]; + wall[wallIdx].boundaryLayerThickness[posIdx] = this->problem_().bBoxMin()[wallNormal_] - this->problem_().bBoxMax()[wallNormal_] - eps_; + wall[wallIdx].isBBoxMinWall = false; + wall[wallIdx].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness); + } + } + if (walls == 2 && wallIdx == 0) + { + wall[0].wallPos[posIdx] = this->problem_().bBoxMin()[wallNormal_]; + wall[1].wallPos[posIdx] = this->problem_().bBoxMax()[wallNormal_]; + wall[0].boundaryLayerThickness[posIdx] = (wall[1].wallPos[posIdx] - wall[0].wallPos[posIdx]) / 2 + eps_; + wall[1].boundaryLayerThickness[posIdx] = - wall[0].boundaryLayerThickness[posIdx]; + wall[0].isBBoxMinWall = true; + wall[1].isBBoxMinWall = false; + wall[0].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness); + wall[1].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness); + } + wall[wallIdx].crossLength[posIdx] = wall[wallIdx].boundaryLayerThickness[posIdx]; + wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThickness[posIdx]; // != 0, da kleinster wert gwünscht + wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = 0; // == 0, da größter wert gewünscht + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + { + wall[wallIdx].maxVelocity[posIdx][dimIdx] = 0.0; + wall[wallIdx].maxVelocityAbs[posIdx][dimIdx] = 0.0; + wall[wallIdx].minVelocity[posIdx][dimIdx] = 0.0; + } + wall[wallIdx].fMax[posIdx] = 0.0; + wall[wallIdx].yMax[posIdx] = 0.0; + wall[wallIdx].isInterpolated[posIdx] = 0.0; + wall[wallIdx].fluxValuesCount[posIdx] = 0.0; + wall[wallIdx].wallValuesCount[posIdx] = 0.0; + wall[wallIdx].headerWritten[posIdx] = false; + } + } + } + + /*! + * \brief Initializes the wall fluid properties with 0. + */ + void resetWallFluidProperties() + { + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + for (int posIdx = 0; posIdx < intervals; ++posIdx) + { + wall[wallIdx].wallDensity[posIdx] = 0.0; + wall[wallIdx].wallKinematicViscosity[posIdx] = 0.0; + wall[wallIdx].wallVelGrad[posIdx] = 0.0; + wall[wallIdx].wallShearStress[posIdx] = 0.0; + } + } + + /*! + * \brief Complete calculation for all relevant wall values. + * + * If the order is changed, errors may occur because of unknown or zero values + */ + void updateWallProperties() + { + asImp_().resetWallProperties(); + asImp_().updateMaxFluxVars(); + asImp_().updateCrossLength(); + asImp_().resetWallFluidProperties(); + asImp_().updateWallFluidProperties(); + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + { + for (int posIdx = 0; posIdx < intervals; ++posIdx) + if (wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] > wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]) + wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]; + asImp_().interpolateWallProperties(wallIdx); + } + } + + /*! + * \brief Get position index (interval section) a point belongs to. + * + * \param globalPos Global Position. + */ + const int getPosIdx(const GlobalPosition &globalPos) const + { + int posIdx = int (intervals * (globalPos[flowNormal_] - this->problem_().bBoxMin()[flowNormal_])) + / (this->problem_().bBoxMax()[flowNormal_] - this->problem_().bBoxMin()[flowNormal_]); + if (posIdx >= intervals) + posIdx = intervals -1; + return posIdx; + } + + /*! + * \brief Return wall a point belongs to. + * + * \param posIdx Position Index of current Global Position. + * \param globalPos Global Position. + */ + const int getWallIdx(const GlobalPosition &globalPos, const int posIdx) const + { + if (walls == 0) + DUNE_THROW(Dune::NotImplemented, "Eddy viscosity models are not implemented for use without walls."); + + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + if ((wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + wall[wallIdx].boundaryLayerThickness[posIdx]) + || (!wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] + wall[wallIdx].boundaryLayerThickness[posIdx])) + { + return wallIdx; + } + + static bool alreadyPrintedError = false; + static Scalar timePrintedError = 0.0; + if (this->problem_().timeManager().time() > timePrintedError) + { + alreadyPrintedError = false; + } + + if (!alreadyPrintedError) + { + Dune::dinfo << "info: point " << globalPos << " in interval " << posIdx + << " does not belong to wall -> now belongs to wall 0" << std::endl; + alreadyPrintedError = true; + timePrintedError = this->problem_().timeManager().time(); + } + return 0; + } + + + /*! + * \brief Return the distance to corresponding wall including roughness effects + * + * For ksPlus = 0, this is the normal wall distance. + * For ksPlus > 0, an additional length is added to the real wall distance. + * \param globalPos Global Position. + * \param wallIdx Wall Index of current Global Position. + * \param posIdx Position Index of current Global Position. + */ + const Scalar distanceToWallRough(const GlobalPosition &globalPos, const int wallIdx, const int posIdx) const + { + if (surfaceRoughnessNotImplemented()) + { return distanceToWallReal (globalPos, wallIdx, posIdx); } + if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) < eps_&& wall[wallIdx].isBBoxMinWall) + { return distanceToWallReal (globalPos, wallIdx, posIdx); } + if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) < eps_&& !wall[wallIdx].isBBoxMinWall) + { return distanceToWallReal (globalPos, wallIdx, posIdx); } + + Scalar ksPlus = wall[wallIdx].sandGrainRoughness[posIdx] * sqrt(wall[wallIdx].wallShearStress[posIdx] / wall[wallIdx].wallDensity[posIdx]) + / wall[wallIdx].wallKinematicViscosity[posIdx]; + + if (ksPlus > 2000) + { + std::cout << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << globalPos + << " is not in the valid range (ksPlus < 2000)," + << " for high ksPlus values the roughness function reaches a turning point."<< std::endl; + DUNE_THROW(Dune::NotImplemented, "Unphysical roughness behavior."); + ksPlus = 2000; + } + else if (ksPlus < 4.535) + { + Dune::dinfo << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << globalPos + << " is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl; + ksPlus = 0.0; + } + + Scalar delta = 0.0; // delta is only changed for ksPlus, which are in valid range, otherwise smooth wall is assumed + if (ksPlus >= 4.535) + { + delta = 0.9 * wall[wallIdx].wallKinematicViscosity[posIdx] / sqrt(wall[wallIdx].wallShearStress[posIdx] / wall[wallIdx].wallDensity[posIdx]) * (sqrt(ksPlus) - ksPlus * exp(- 1.0 * ksPlus / 6.0)); + } + + int sign = std::abs(globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]) / (globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]); + return globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx] + sign * delta; + } + + /*! + * \brief Return the distance to corresponding wall. + * + * \param globalPos Global Position. + * \param wallIdx Wall Index of current Global Position. + * \param posIdx Position Index of current Global Position. + */ + const Scalar distanceToWallReal(const GlobalPosition &globalPos, const int wallIdx, const int posIdx) const + { return globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]; } + + /*! + * \brief Return true if function for muInner should be used. + * + * \param globalPos Global Position. + * \param posIdx Position Index of current Global Position. + */ + const bool useViscosityInner(const GlobalPosition &globalPos, const int posIdx) const + { + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + if ((wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + wall[wallIdx].crossLength[posIdx]) + || (!wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] + wall[wallIdx].crossLength[posIdx])) + return true; + return false; + } + + /*! + * \brief Loop over all elements, used to calculate maximum flux values + * in the whole domain. + */ + void updateMaxFluxVars() + { + FVElementGeometry fvGeometry; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + for (int fIdx = 0; fIdx < fvGeometry.numScvf; ++fIdx) + { + + FluxVariables fluxVars(this->problem_(), + element, + fvGeometry, + fIdx, + elemVolVars, + false); + + GlobalPosition globalPos = fvGeometry.subContVolFace[fIdx].ipGlobal; + + asImp_().calculateMaxFluxVars(fluxVars, globalPos); + } + } + } + + /*! + * \brief Update maximum values in the domain and + * set them to the corresponding wall. + * + * \param fluxVars Flux Variables of current element. + * \param globalPos Global Position. + */ + void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition globalPos) + { + int posIdx = getPosIdx(globalPos); + int wallIdx = getWallIdx(globalPos, posIdx); + for (int dimIdx = 0; dimIdx < dim; ++dimIdx) + { + if (std::abs(wall[wallIdx].maxVelocity[posIdx][dimIdx]) < std::abs(fluxVars.velocity()[dimIdx])) + { + wall[wallIdx].maxVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; +// // if the values in the middle should be set on both wall +// for (int wIdx = 0; wIdx < walls; ++wIdx) +// if (std::abs(distanceToWallReal(globalPos, wallIdx, posIdx)) < std::abs(wall[wIdx].boundaryLayerThickness[posIdx] + 1e-5)) +// wall[wIdx].maxVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; + // set it as maxVelocityAbs + if (std::abs(wall[wallIdx].maxVelocityAbs[posIdx][dimIdx]) < std::abs(fluxVars.velocity()[dimIdx])) + for (int wIdx = 0; wIdx < walls; ++wIdx) + wall[wIdx].maxVelocityAbs[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; + wall[wallIdx].fluxValuesCount[posIdx]++; + } + if (std::abs(wall[wallIdx].minVelocity[posIdx][dimIdx]) > std::abs(fluxVars.velocity()[dimIdx])) + wall[wallIdx].minVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; + } + + // fMax and yMax + if (wall[wallIdx].fMax[posIdx] < fluxVars.fz()) + { + wall[wallIdx].fMax[posIdx] = fluxVars.fz(); + wall[wallIdx].yMax[posIdx] = distanceToWallRough(globalPos, wallIdx, posIdx); +// // if the values in the middle should be set on both wall +// for (int wIdx = 0; wIdx < walls; ++wIdx) +// if (std::abs(distanceToWall(globalPos, wIdx, posIdx)) < std::abs(wall[wIdx].boundaryLayerThickness[posIdx] + 1e-4)) +// { +// wall[wIdx].fMax[posIdx] = fluxVars.fz(); +// wall[wIdx].yMax[posIdx] = distanceToWall(globalPos, wallIdx, posIdx); +// } + } + } + + /*! + * \brief Get maximum values of the f(z) function in the Baldwin-Lomax model. + */ + void updateCrossLength() + { + FVElementGeometry fvGeometry; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + for (const auto& intersection : Dune::intersections(this->gridView_(), element)) + { + int fIdx = intersection.indexInInside(); + FluxVariables fluxVars(this->problem_(), + element, + fvGeometry, + fIdx, + elemVolVars, + false); + + GlobalPosition globalPos = fvGeometry.subContVolFace[fIdx].ipGlobal; + int posIdx = getPosIdx(globalPos); + int wallIdx = getWallIdx(globalPos, posIdx); + + // muCross + if (fluxVars.dynamicEddyViscosityOuter() < fluxVars.dynamicEddyViscosityInner() + && useViscosityInner(globalPos, posIdx)) + { + wall[wallIdx].crossLength[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); + } + + if (std::abs(fluxVars.velocity()[flowNormal_]) >= 0.99 * std::abs(wall[wallIdx].maxVelocity[posIdx][flowNormal_]) + && std::abs(wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]) > std::abs(distanceToWallReal(globalPos, wallIdx, posIdx))) + { + wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); + } + + if (wall[wallIdx].maxVelocity[posIdx][flowNormal_] * globalPos[flowNormal_] / fluxVars.kinematicViscosity() < 2300) + { + wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]; + } + else if ((fluxVars.velocity()[flowNormal_] / fluxVars.frictionVelocityWall() <= 5.0) + && (std::abs(wall[wallIdx].viscousSublayerThicknessCalculated[posIdx]) + < std::abs(distanceToWallReal(globalPos, wallIdx, posIdx)))) + { + wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); + } + } + } + } + + /*! + * \brief Loop over all elements to update the values at the wall. + */ + void updateWallFluidProperties() + { + FVElementGeometry fvGeometry; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + const ReferenceElement &refElement = ReferenceElements::general(element.geometry().type()); + for (const auto& intersection : Dune::intersections(this->gridView_(), element)) + { + // handle only faces on the boundary + if (!intersection.boundary()) + continue; + + // Assemble the boundary for all vertices of the current + // face + int fIdx = intersection.indexInInside(); + int numFaceVerts = refElement.size(fIdx, 1, dim); + for (int faceVertIdx = 0; + faceVertIdx < numFaceVerts; + ++faceVertIdx) + { + int boundaryFaceIdx = fvGeometry.boundaryFaceIndex(fIdx, faceVertIdx); + + + + + const FluxVariables boundaryVars(this->problem_(), + element, + fvGeometry, + boundaryFaceIdx, + elemVolVars, + true); + + GlobalPosition globalPos = fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal; + if ( + globalPos[wallNormal_] > this->problem_().bBoxMin()[wallNormal_] + 1e-15 + && globalPos[wallNormal_] < this->problem_().bBoxMax()[wallNormal_] - 1e-15 + ) + continue; + + asImp_().calculateWallFluidProperties(boundaryVars, globalPos); + } // end loop over intersections + } // end loop over element vertices + } + } + + /*! + * \brief Calculate / average the values at the wall. + * + * \param boundaryVars Flux Variables at boundary segment. + * \param globalPos Global Position. + */ + void calculateWallFluidProperties(const FluxVariables &boundaryVars, const GlobalPosition &globalPos) + { + int posIdx = getPosIdx(globalPos); + int wallIdx = getWallIdx(globalPos, posIdx); + if (globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] - 1e-8 + && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + 1e-8) + { + wall[wallIdx].wallValuesCount[posIdx] += 1; + wall[wallIdx].wallDensity[posIdx] = + (wall[wallIdx].wallDensity[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.density()) + / wall[wallIdx].wallValuesCount[posIdx]; + wall[wallIdx].wallKinematicViscosity[posIdx] = + (wall[wallIdx].wallKinematicViscosity[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.kinematicViscosity()) + / wall[wallIdx].wallValuesCount[posIdx]; + wall[wallIdx].wallVelGrad[posIdx] = + (boundaryVars.velocityGrad()[flowNormal_][wallNormal_] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.velocityGrad()[flowNormal_][wallNormal_]) + / wall[wallIdx].wallValuesCount[posIdx]; + wall[wallIdx].wallShearStress[posIdx] = + (wall[wallIdx].wallShearStress[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + + std::abs(boundaryVars.velocityGrad()[flowNormal_][wallNormal_]) * boundaryVars.dynamicViscosity()) + / wall[wallIdx].wallValuesCount[posIdx]; + } + } + + + /*! + * \brief Find points with given values and start interpolation. + * + * \param wallIdx Wall Index of current Global Position. + */ + const void interpolateWallProperties(const int wallIdx) + { + const int startInterpolation = 0; + const int endInterpolation = intervals; + + for (int posIdx = startInterpolation; posIdx < endInterpolation; ++posIdx) + { + if (wall[wallIdx].fluxValuesCount[posIdx] == 0) + { + int prevIdx = posIdx; + int nextIdx = posIdx; + // Getting previous value, if 0 is reached (and tau is still < eps_), get next value + for (prevIdx = posIdx-1; prevIdx >= startInterpolation; --prevIdx) + if (wall[wallIdx].fluxValuesCount[prevIdx] != 0) + break; + if (prevIdx < startInterpolation) // interpolation at x=0, prevIdx is -1 + for (prevIdx = posIdx+1; prevIdx < endInterpolation; ++prevIdx) + if (wall[wallIdx].fluxValuesCount[prevIdx] != 0) + break; + if (prevIdx == endInterpolation && this->problem_().timeManager().time() > this->problem_().timeManager().timeStepSize()) + { + Dune::dinfo << "info: for posIdx " << posIdx << "on wall " << wallIdx + << "there are no fluxValues for interpolation." << std::endl; + break; + } + + // Getting next value, if intervals is reached get prev value + for (nextIdx = posIdx+1; nextIdx < endInterpolation; ++nextIdx) + if (wall[wallIdx].fluxValuesCount[nextIdx] != 0 && nextIdx != prevIdx) + break; + if (nextIdx == endInterpolation) + for (nextIdx = posIdx-1; nextIdx >= startInterpolation; --nextIdx) + if (wall[wallIdx].fluxValuesCount[nextIdx] != 0 && nextIdx != prevIdx) + break; + + asImp_().doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); + } + + + if (wall[wallIdx].wallValuesCount[posIdx] == 0) // || wall[wallIdx].wallValuesCount[posIdx] > 50) + { + int prevIdx = posIdx; + int nextIdx = posIdx; + // Getting previous value, if 0 is reached (and tau is still < eps_), get next value + for (prevIdx = posIdx-1; prevIdx >= startInterpolation; --prevIdx) + if (wall[wallIdx].wallValuesCount[prevIdx] != 0) + break; + if (prevIdx < startInterpolation) // interpolation at x=0, prevIdx is -1 + for (prevIdx = posIdx+1; prevIdx < endInterpolation; ++prevIdx) + if (wall[wallIdx].wallValuesCount[prevIdx] != 0) + break; + if (prevIdx == endInterpolation && this->problem_().timeManager().time() > this->problem_().timeManager().timeStepSize()) + { + Dune::dinfo << "info: for posIdx " << posIdx << "on wall " << wallIdx + << "there are no wallValues for interpolation." << std::endl; + break; + } + + // Getting next value, if intervals is reached get prev value + for (nextIdx = posIdx+1; nextIdx < endInterpolation; ++nextIdx) + if (wall[wallIdx].wallValuesCount[nextIdx] != 0 && nextIdx != prevIdx) + break; + if (nextIdx == endInterpolation) + for (nextIdx = posIdx-1; nextIdx >= startInterpolation; --nextIdx) + if (wall[wallIdx].wallValuesCount[nextIdx] != 0 && nextIdx != prevIdx) + break; + + asImp_().doInterpolationWallValues(wallIdx, posIdx, prevIdx, nextIdx); + } + } + } + + /*! + * \brief Interpolate flux Values, so that flux related Properties + * are given in every Interval. + * + * \param wallIdx Wall Index for interpolation. + * \param posIdx Position Index for interpolation (no given value). + * \param prevIdx Position Index with value. + * \param nextIdx Position Index with value. + */ + const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) + { + wall[wallIdx].boundaryLayerThickness[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].boundaryLayerThickness[prevIdx], nextIdx, wall[wallIdx].boundaryLayerThickness[nextIdx]); + wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].boundaryLayerThicknessCalculated[prevIdx], nextIdx, wall[wallIdx].boundaryLayerThicknessCalculated[nextIdx]); + wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].viscousSublayerThicknessCalculated[prevIdx], nextIdx, wall[wallIdx].viscousSublayerThicknessCalculated[nextIdx]); + wall[wallIdx].crossLength[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].crossLength[prevIdx], nextIdx, wall[wallIdx].crossLength[nextIdx]); + wall[wallIdx].maxVelocity[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocity[prevIdx][0], nextIdx, wall[wallIdx].maxVelocity[nextIdx][0]); + wall[wallIdx].maxVelocity[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocity[prevIdx][1], nextIdx, wall[wallIdx].maxVelocity[nextIdx][1]); + wall[wallIdx].minVelocity[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].minVelocity[prevIdx][0], nextIdx, wall[wallIdx].minVelocity[nextIdx][0]); + wall[wallIdx].minVelocity[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].minVelocity[prevIdx][1], nextIdx, wall[wallIdx].minVelocity[nextIdx][1]); + wall[wallIdx].maxVelocityAbs[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocityAbs[prevIdx][0], nextIdx, wall[wallIdx].maxVelocityAbs[nextIdx][0]); + wall[wallIdx].maxVelocityAbs[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocityAbs[prevIdx][1], nextIdx, wall[wallIdx].maxVelocityAbs[nextIdx][1]); + wall[wallIdx].fMax[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].fMax[prevIdx], nextIdx, wall[wallIdx].fMax[nextIdx]); + wall[wallIdx].yMax[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].yMax[prevIdx], nextIdx, wall[wallIdx].yMax[nextIdx]); + wall[wallIdx].isInterpolated[posIdx] += 1; + } + + /*! + * \brief Interpolate wall Values, so that wall related Properties + * are given in every Interval. + * + * \param wallIdx Wall Index for interpolation. + * \param posIdx Position Index for interpolation (no given value). + * \param prevIdx Position Index with value. + * \param nextIdx Position Index with value. + */ + const void doInterpolationWallValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) + { + wall[wallIdx].wallDensity[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallDensity[prevIdx], nextIdx, wall[wallIdx].wallDensity[nextIdx]); + wall[wallIdx].wallKinematicViscosity[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallKinematicViscosity[prevIdx], nextIdx, wall[wallIdx].wallKinematicViscosity[nextIdx]); + wall[wallIdx].wallVelGrad[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallVelGrad[prevIdx], nextIdx, wall[wallIdx].wallVelGrad[nextIdx]); + wall[wallIdx].wallShearStress[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallShearStress[prevIdx], nextIdx, wall[wallIdx].wallShearStress[nextIdx]); + wall[wallIdx].isInterpolated[posIdx] += 2; + } + + /*! + * \brief Mathematical linear interpolation routine. + * + * Return the linear interpolated value at any point between to values. + * + * \param position Position for which interpolation is made. + * \param prev First Position for which the value is known. + * \param prevValue Known value at prev position. + * \param next Second Position for which the value is known. + * \param nextValue Known value at next position. + */ + const Scalar interpolation(const Scalar position, const Scalar prev, const Scalar prevValue, const Scalar next, const Scalar nextValue) + { + return (prevValue + (nextValue - prevValue) / (next - prev) * (position - prev)); + } + + // \} // wall properties + + /*! + * \brief Returns whether the actual eddy viscosity model includes surface roughness approach. + * + * Surface roughness is not included in the Baldwin Lomax model + */ + const bool surfaceRoughnessNotImplemented() const + { + switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) + { + case EddyViscosityIndices::noEddyViscosityModel: // 0 + return true; + break; + default: + return false; + } + } + + /*! + * \brief Returns the name of the used eddy viscosity model. + */ + const char *eddyViscosityModelName() const + { + switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) + { + case EddyViscosityIndices::noEddyViscosityModel: // 0 + return "noEddyViscosityModel"; + break; + case EddyViscosityIndices::prandtl: // 1 + return "prandtl"; + break; + case EddyViscosityIndices::modifiedVanDriest: // 2 + return "modifiedVanDriest"; + break; + case EddyViscosityIndices::baldwinLomax: // 3 + return "baldwinLomax"; + break; + default: + DUNE_THROW(Dune::NotImplemented, "This eddy viscosity model is not implemented."); + } + } + + +protected: + //! Current implementation. + Implementation &asImp_() + { return *static_cast<Implementation*>(this); } + //! Current implementation. + const Implementation &asImp_() const + { return *static_cast<const Implementation*>(this); } + +private: + const int flowNormal_; + const int wallNormal_; + Scalar eps_; +}; + +} + +#include "propertydefaults.hh" + +#endif // DUMUX_ZEROEQ_MODEL_HH diff --git a/dumux/freeflow/zeroeq/problem.hh b/dumux/freeflow/zeroeq/problem.hh new file mode 100644 index 0000000000000000000000000000000000000000..2692e6367835b2e7e4d30a38fd8efaea4219a4e9 --- /dev/null +++ b/dumux/freeflow/zeroeq/problem.hh @@ -0,0 +1,82 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for all ZeroEq problems which use the box scheme. + */ +#ifndef DUMUX_ZEROEQ_PROBLEM_HH +#define DUMUX_ZEROEQ_PROBLEM_HH + +#include <dumux/freeflow/stokes/model.hh> +#include <dumux/freeflow/zeroeq/properties.hh> + +namespace Dumux +{ +/*! + * \ingroup ImplicitBaseProblems + * \ingroup BoxZeroEqModel + * \brief Base class for all problems which use the ZeroEq box model. + * + * This implements the call of update functions used for the wall properties of + * the ZeroEq box model. + */ +template<class TypeTag> +class ZeroEqProblem : public StokesProblem<TypeTag> +{ + typedef StokesProblem<TypeTag> ParentType; + + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + +public: + ZeroEqProblem(TimeManager &timeManager, const GridView &gridView) + : ParentType(timeManager, gridView) + { } + + /*! + * \brief Called by the Dumux::TimeManager in order to initialize the problem. + * + * If you overload this method don't forget to call ParentType::init().<br> + * This initializes all wall-related properties, which are necessary for the + * ZeroEq box model. + */ + void init() + { + // set the initial condition of the model + ParentType::init(); + this->model().resetWallProperties(); + this->model().resetWallFluidProperties(); + } + + /*! + * \brief Called by the time manager before the time integration. + * + * This updates all wall-related properties, which are necessary for the + * ZeroEq box model + */ + void preTimeStep() + { + this->model().updateWallProperties(); + } +}; + +} + +#endif // DUMUX_ZEROEQ_PROBLEM_HH diff --git a/dumux/freeflow/zeroeq/properties.hh b/dumux/freeflow/zeroeq/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..e46ddd85085a6a780fa1bf9b0af3434898d58ed0 --- /dev/null +++ b/dumux/freeflow/zeroeq/properties.hh @@ -0,0 +1,68 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqModel + * + * \file + * + * \brief Defines the supplementary properties required for the + * ZeroEq model. + * + */ + +#ifndef DUMUX_ZEROEQ_PROPERTIES_HH +#define DUMUX_ZEROEQ_PROPERTIES_HH + +#include <dumux/freeflow/stokes/properties.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the ZeroEq Problem +NEW_TYPE_TAG(BoxZeroEq, INHERITS_FROM(BoxStokes)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// + +NEW_PROP_TAG(KarmanConstant); //!< The Karman constant +NEW_PROP_TAG(BBoxMinIsWall); //!< Sets BBoxMin as a wall +NEW_PROP_TAG(BBoxMaxIsWall); //!< Sets BBoxMax as a wall +NEW_PROP_TAG(ZeroEqFlowNormal); //!< Indicates the main flow direction +NEW_PROP_TAG(ZeroEqWallNormal); //!< Indicates the wall normal direction +NEW_PROP_TAG(ZeroEqBBoxMinSandGrainRoughness); //!< Sets a sand grain roughness at BBoxMin +NEW_PROP_TAG(ZeroEqBBoxMaxSandGrainRoughness); //!< Sets a sand grain roughness at BBoxMax +NEW_PROP_TAG(ZeroEqEddyViscosityModel); //!< Returns used eddy viscosity model +NEW_PROP_TAG(NumberOfIntervals); //!< Returns number of wall intervals +NEW_PROP_TAG(BaseStokesModel); //!< Returns the base implementation of the Stokes model +NEW_PROP_TAG(BaseStokesVolumeVariables); //!< Returns the base implementation of the Stokes volume variables +NEW_PROP_TAG(BaseStokesFluxVariables); //!< Returns the base implementation of the Stokes flux variables +} + +} + +#endif // DUMUX_ZEROEQ_PROPERTIES_HH diff --git a/dumux/freeflow/zeroeq/propertydefaults.hh b/dumux/freeflow/zeroeq/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..46bcb756ba727bb9756a12721f7090a5d0f5eb13 --- /dev/null +++ b/dumux/freeflow/zeroeq/propertydefaults.hh @@ -0,0 +1,92 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqModel + * + * \file + * + * \brief Defines the properties required for the ZeroEq model. + */ + +#ifndef DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH +#define DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH + +#include "fluxvariables.hh" +#include "model.hh" + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +// INHERITED +//! Set the Model property +SET_TYPE_PROP(BoxZeroEq, Model, ZeroEqModel<TypeTag>); + +//! Set the Flux Variables property +SET_TYPE_PROP(BoxZeroEq, FluxVariables, ZeroEqFluxVariables<TypeTag>); + +//! Set the indices used by the ZeroEq model +SET_TYPE_PROP(BoxZeroEq, Indices, ZeroEqCommonIndices<TypeTag>); + +//! Set calculation to Navier Stokes +SET_BOOL_PROP(BoxZeroEq, EnableNavierStokes, true); + +// NEW PROPERTIES +//! Set the Karman constant \f$[-]\f$ +SET_SCALAR_PROP(BoxZeroEq, KarmanConstant, 0.41); + +//! Set BBoxMin of wall normal direction as a wall +SET_BOOL_PROP(BoxZeroEq, BBoxMinIsWall, true); + +//! Set BBoxMax of wall normal direction as a wall +SET_BOOL_PROP(BoxZeroEq, BBoxMaxIsWall, true); + +//! Set main flow direction +SET_INT_PROP(BoxZeroEq, ZeroEqFlowNormal, 0); + +//! Set wall normal direction +SET_INT_PROP(BoxZeroEq, ZeroEqWallNormal, 1); + +//! Set a zero sand grain roughness \f$[m]\f$ at BBoxMin +SET_SCALAR_PROP(BoxZeroEq, ZeroEqBBoxMinSandGrainRoughness, 0.0); + +//! Set a zero sand grain roughness \f$[m]\f$ at BBoxMax +SET_SCALAR_PROP(BoxZeroEq, ZeroEqBBoxMaxSandGrainRoughness, 0.0); + +//! Set the eddy viscosity model +SET_INT_PROP(BoxZeroEq, ZeroEqEddyViscosityModel, 1); + +//! Set the number of wall intervals in which more complex turbulence models are evaluated +SET_INT_PROP(BoxZeroEq, NumberOfIntervals, 1000); + +//! Set the BaseStokesFluxVariables to StokesFluxVariables +SET_TYPE_PROP(BoxZeroEq, BaseStokesFluxVariables, StokesFluxVariables<TypeTag>); + +//! Set the BaseStokesModel to StokesModel +SET_TYPE_PROP(BoxZeroEq, BaseStokesModel, StokesModel<TypeTag>); +} +} // namespace Dumux +#endif // DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH diff --git a/dumux/freeflow/zeroeq/zeroeqfluxvariables.hh b/dumux/freeflow/zeroeq/zeroeqfluxvariables.hh index 0e93c587db184d29a4cf0c963a913e87f8cb4a09..dac3755571582a2197450d939a2222a92f40d944 100644 --- a/dumux/freeflow/zeroeq/zeroeqfluxvariables.hh +++ b/dumux/freeflow/zeroeq/zeroeqfluxvariables.hh @@ -1,319 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * the fluxes of the ZeroEq model over a face of a finite volume. - * - * This means the methods to calculate the eddy viscosity. - */ -#ifndef DUMUX_ZEROEQ_FLUX_VARIABLES_HH -#define DUMUX_ZEROEQ_FLUX_VARIABLES_HH +#ifndef DUMUX_ZEROEQ_FLUX_VARIABLES_HH_OLD +#define DUMUX_ZEROEQ_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/common/valgrind.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeq/fluxvariables.hh instead -#include <dumux/freeflow/stokes/stokesfluxvariables.hh> -#include <dumux/freeflow/zeroeq/zeroeqindices.hh> -#include <dumux/freeflow/zeroeq/zeroeqproperties.hh> +#include <dumux/freeflow/zeroeq/fluxvariables.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains data which is required to - * calculate the component fluxes over a face of a finite - * volume for a ZeroEq model. - * - * This means the methods to calculate the eddy viscosity. - */ -template <class TypeTag> -class ZeroEqFluxVariables : public GET_PROP_TYPE(TypeTag, BaseStokesFluxVariables) -{ - typedef typename GET_PROP_TYPE(TypeTag, BaseStokesFluxVariables) ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - - enum { dim = GridView::dimension }; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - -public: - ZeroEqFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) - , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - , eddyViscosityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) - , karmanConstant_(GET_PROP_VALUE(TypeTag, KarmanConstant)) - { - dynamicEddyViscosity_ = 0.0; - mixingLength_ = 0.0; - dynamicEddyViscosityInner_ = 0.0; - dynamicEddyViscosityOuter_ = 0.0; - fz_ = 0.0; - posIdx_ = problem.model().getPosIdx(globalPos()); - wallIdx_ = problem.model().getWallIdx(globalPos(), posIdx_); - distanceToWallRough_ = std::abs(problem.model().distanceToWallRough(globalPos(), wallIdx_, posIdx_)); - distanceToWallReal_ = std::abs(problem.model().distanceToWallReal(globalPos(), wallIdx_, posIdx_)); - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - maxVelocity_[dimIdx] = problem.model().wall[wallIdx_].maxVelocity[posIdx_][dimIdx]; - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - minVelocity_[dimIdx] = problem.model().wall[wallIdx_].minVelocity[posIdx_][dimIdx]; - velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; - frictionVelocityWall_ = sqrt(problem.model().wall[wallIdx_].wallShearStress[posIdx_] - / problem.model().wall[wallIdx_].wallDensity[posIdx_]); - yPlusRough_ = distanceToWallRough_ * frictionVelocityWall_ / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; - - // calculation of an eddy viscosity only makes sense with Navier-Stokes equation - if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) - calculateEddyViscosity_(problem, element, elemVolVars); - } - -protected: - /*! - * \brief This function calculates the dynamic viscosity. - * - * The eddy viscosity is added to the viscosity in stokeslocalresidual.hh at each scv - * face. - */ - void calculateEddyViscosity_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - // no turbulence model - if (eddyViscosityModel_ == EddyViscosityIndices::noEddyViscosityModel) - return; - - // Prandtl mixing length - // e.g. Wilcox, D. C., Turbulence Modeling for CFD, 2006 - else if (eddyViscosityModel_ == EddyViscosityIndices::prandtl) - { - mixingLength_ = distanceToWallRough_ * karmanConstant_; - dynamicEddyViscosity_ = this->density() * mixingLength() * mixingLength() * std::abs(velGrad_); - } - - // modified Van-Driest - // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 - else if (eddyViscosityModel_ == EddyViscosityIndices::modifiedVanDriest) - { - Scalar aPlus = 26.0; - Scalar bPlus = 0.26; - // eddy viscosity can only be calculated correctly for non-zero distance to walls - mixingLength_ = 0.0; - if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) - mixingLength_= karmanConstant_ * distanceToWallRough_ - * (1.0 - std::exp(-yPlusRough_ / aPlus )) - / std::sqrt(1.0 - std::exp(-bPlus * yPlusRough_)); - - dynamicEddyViscosity_ = this->density() * mixingLength() * mixingLength() * std::abs(velGrad_); - } - - // Baldwin and Lomax - // Baldwin, B. S. & Lomax, H. "Thin Layer Approximation and Algebraic Model for Seperated Turbulent Flows" - // AIAA Journal, 1978, 78--257, 1-9 - else if (eddyViscosityModel_ == EddyViscosityIndices::baldwinLomax) - { - // LAW CONSTANTS - const Scalar aPlus = 26.0; - const Scalar cCP = 1.6; - const Scalar cKleb = 0.30; - const Scalar cWK = 0.25; - const Scalar kUpper = 0.0168; - - // Calculate muInner - mixingLength_ = 0.0; - if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) - mixingLength_ = karmanConstant_ * distanceToWallRough_ - * (1.0 - std::exp(-yPlusRough_ / aPlus )); - Scalar omega1 = this->velocityGrad_[0][1] - this->velocityGrad_[1][0]; - Scalar omega2 = 0.0; - Scalar omega3 = 0.0; - if (dim == 3) - { - omega2 = this->velocityGrad_[1][2] - this->velocityGrad_[2][1]; - omega3 = this->velocityGrad_[2][0] - this->velocityGrad_[0][2]; - } - Scalar omega = sqrt(omega1 * omega1 + omega2 * omega2 + omega3 * omega3); - dynamicEddyViscosityInner_ = this->density() * mixingLength() * mixingLength() * omega; - - // Calculate muOuter - fz_ = 0.0; - if (distanceToWallRough_ > 0.0 && yPlusRough_ > 0.0) - fz_ = distanceToWallRough_ * omega * (1.0 - std::exp(-yPlusRough_ / aPlus )); - Scalar fMax = problem.model().wall[wallIdx_].fMax[posIdx_]; - Scalar yMax = std::abs(problem.model().wall[wallIdx_].yMax[posIdx_]); - Scalar uDiff = maxVelocity_.two_norm() - minVelocity_.two_norm(); - - Scalar f1 = yMax * fMax; - Scalar f2 = cWK * yMax * uDiff * uDiff / fMax; - Scalar fWake = fmin(f1, f2); - Scalar fKleb = 1 / (1 + 5.5 * std::pow(cKleb * distanceToWallRough_ / yMax, 6.0)); - dynamicEddyViscosityOuter_ = this->density() * kUpper * cCP * fWake * fKleb; - - bool inner = problem.model().useViscosityInner(this->face().ipGlobal, posIdx_); - - // muOuter can only be calculated correctly for non-zero fmax - if (fMax == 0) - inner = true; - - if (inner) - dynamicEddyViscosity_ = dynamicEddyViscosityInner_; - else - dynamicEddyViscosity_ = dynamicEddyViscosityOuter_; - } - - else - { - DUNE_THROW(Dune::NotImplemented, "This eddy viscosity model is not implemented."); - } - - Valgrind::CheckDefined(dynamicEddyViscosity_); - Valgrind::CheckDefined(dynamicEddyViscosityInner_); - Valgrind::CheckDefined(dynamicEddyViscosityOuter_); - } - -public: - /*! - * \brief Returns the global coordinates of the integration point. - */ - DimVector globalPos() const - { return this->face().ipGlobal; } - - /*! - * \brief Returns the mixing length \f$\mathrm{[m]}\f$. - */ - Scalar mixingLength() const - { return mixingLength_; } - - /*! - * \brief Returns the dynamic eddy viscosity - * \f$\mathrm{[Pa \cdot s]} = \mathrm{[N \cdot s/m^2]}\f$. - */ - const Scalar dynamicEddyViscosity() const - { return dynamicEddyViscosity_; } - - /*! - * \brief Returns the kinematic eddy viscosity - * \f$\mathrm{[m^2/s]}\f$ (if implemented). - */ - const Scalar kinematicEddyViscosity() const - { return dynamicEddyViscosity() / this->density(); } - - /*! - * \brief Returns the inner dynamic eddy Viscosity (only Baldwin-Lomax model) - * \f$\mu_\textrm{inner}\f$ in \f$\mathrm{[N\cdot s/m^2]}\f$. - */ - Scalar dynamicEddyViscosityInner() const - { return dynamicEddyViscosityInner_; } - - /*! - * \brief Returns the outer dynamic eddy Viscosity (only Baldwin-Lomax model). - * \f$\mu_\textrm{outer}\f$ in \f$\mathrm{[N\cdot s/m^2]}\f$. - */ - Scalar dynamicEddyViscosityOuter() const - { return dynamicEddyViscosityOuter_; } - - /*! - * \brief Returns the value of the f-function. - * - * \f$\mathrm{f = y \omega \left( 1 - exp \left[ -y^+ / A^+ \right] \right)}\f$.<br> - * y = distanceToWall - */ - Scalar fz() const - { return fz_; } - - /*! - * \brief Returns the friction velocity at the wall \f$\mathrm{[kg/(m*s^2)]}\f$. - */ - Scalar frictionVelocityWall() const - { return frictionVelocityWall_; } - - /*! - * \brief Returns the distance to the corresponding Wall, including surface roughness \f$\mathrm{[m]}\f$. - */ - Scalar distanceToWallRough() const - { return distanceToWallRough_; } - - /*! - * \brief Returns the real distance to the corresponding Wall \f$\mathrm{[m]}\f$. - */ - Scalar distanceToWallReal() const - { return distanceToWallReal_; } - - /*! - * \brief Returns dimensionless wall distance, including surface roughness \f$\mathrm{[-]}\f$. - */ - Scalar yPlusRough() const - { return yPlusRough_; } - - /*! - * \brief Returns a dimensionless velocity \f$\mathrm{[-]}\f$. - */ - Scalar uPlus() const - { return this->velocity()[flowNormal_] / frictionVelocityWall(); } - - /*! - * \brief Returns the Karman constant \f$\mathrm{[-]}\f$. - */ - Scalar karmanConstant() const - { return karmanConstant_; } - -private: - const int flowNormal_; - const int wallNormal_; - const int eddyViscosityModel_; - const Scalar karmanConstant_; - - int wallIdx_; - int posIdx_; - Scalar yPlusRough_; - Scalar distanceToWallReal_; - Scalar distanceToWallRough_; - Scalar sandGrainRoughness_; - Scalar sandGrainRoughnessDimensionless_; - - Scalar velGrad_; - Scalar frictionVelocityWall_; - DimVector maxVelocity_; - DimVector minVelocity_; - - Scalar mixingLength_; - Scalar dynamicEddyViscosity_; - Scalar dynamicEddyViscosityInner_; - Scalar dynamicEddyViscosityOuter_; - Scalar fz_; - - Scalar eps_; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQ_FLUX_VARIABLES_HH +#endif diff --git a/dumux/freeflow/zeroeq/zeroeqindices.hh b/dumux/freeflow/zeroeq/zeroeqindices.hh index 838f97752da8af179bdf320b5bdb06dfb6201743..f69375869dc4de463bc32c1c98b7221fae5e5331 100644 --- a/dumux/freeflow/zeroeq/zeroeqindices.hh +++ b/dumux/freeflow/zeroeq/zeroeqindices.hh @@ -1,61 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_ZEROEQ_INDICES_HH_OLD +#define DUMUX_ZEROEQ_INDICES_HH_OLD -/*! - * \file - * \brief Defines the indices required for the ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQ_INDICES_HH -#define DUMUX_ZEROEQ_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeq/indices.hh instead -#include <dumux/freeflow/stokes/stokesindices.hh> +#include <dumux/freeflow/zeroeq/indices.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqModel - * \brief The indices for the eddy viscosity model. - */ -struct EddyViscosityIndices -{ - // Eddy Viscosity Model Indices - static const int noEddyViscosityModel = 0; - static const int prandtl = 1; - static const int modifiedVanDriest = 2; - static const int baldwinLomax = 3; -}; - -/*! - * \ingroup BoxZeroEqModel - * \ingroup ImplicitIndices - * \brief The common indices for the isothermal ZeroEq model. - * - * \tparam PVOffset The first index in a primary variable vector. - */ -template <class TypeTag, int PVOffset = 0> -struct ZeroEqCommonIndices : public StokesCommonIndices<TypeTag, PVOffset> -{ - static const int scvDataPrecision = 5; - static const int scvDataWidth = scvDataPrecision + 10; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQ_INDICES_HH +#endif diff --git a/dumux/freeflow/zeroeq/zeroeqmodel.hh b/dumux/freeflow/zeroeq/zeroeqmodel.hh index dcc4c3f5743d8a157772d01db9d25efd27d2bad0..d3fe0da958e4550f788ec2c4232dd936338d34ae 100644 --- a/dumux/freeflow/zeroeq/zeroeqmodel.hh +++ b/dumux/freeflow/zeroeq/zeroeqmodel.hh @@ -1,1006 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Base class for all models which use the ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQ_MODEL_HH -#define DUMUX_ZEROEQ_MODEL_HH +#ifndef DUMUX_ZEROEQ_MODEL_HH_OLD +#define DUMUX_ZEROEQ_MODEL_HH_OLD -#include "zeroeqindices.hh" -#include "zeroeqfluxvariables.hh" -#include "zeroeqproblem.hh" -#include "zeroeqproperties.hh" -#include <dumux/freeflow/stokes/stokesmodel.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeq/model.hh instead -namespace Dumux -{ -/*! - * \ingroup BoxZeroEqModel - * \brief Adaption of the box scheme to the ZeroEq model. - * - * This model implements an single-phase isothermal free flow - * solving the mass and the momentum balance. For the momentum balance - * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation - * (algebraic) turbulence model is used. - * - * Mass balance: - * \f[ - * \frac{\partial \varrho_\textrm{g}}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) - * - q_\textrm{g} = 0 - * \f] - * - * Momentum Balance: - * \f[ - * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} - * + \text{div} \left( - * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} - * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] - * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} - * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) - * \right) - * + \left(p_\textrm{g} {\bf {I}} \right) - * - \varrho_\textrm{g} {\bf g} = 0 - * \f] - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class ZeroEqModel : public GET_PROP_TYPE(TypeTag, BaseStokesModel) -{ - typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; +#include <dumux/freeflow/zeroeq/model.hh> - enum { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), - bboxMinIsWall = GET_PROP_VALUE(TypeTag, BBoxMinIsWall), - bboxMaxIsWall = GET_PROP_VALUE(TypeTag, BBoxMaxIsWall), - walls = (bboxMinIsWall ? 1 : 0) + (bboxMaxIsWall ? 1 : 0) - }; - - typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements; - typedef Dune::ReferenceElement<Scalar, dim> ReferenceElement; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - - -public: - ZeroEqModel() - : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - { - eps_ = 1e-6; - - // check whether sand grain roughness may be used - if ((GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 - || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) - && surfaceRoughnessNotImplemented()) - { - Dune::dwarn << "warning: surface roughness is not implemented for eddy viscosity model " - << GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel) - << "." << std::endl; - } - } - - /*! - * \brief Write vtk and additional plain text scv-data. - * - * The routine for the vtk data should be the same as in dumux-stable. - * - * The scv-data files contain mainly information for the turbulence model. - * - * \param sol The solution vector. - * \param writer The writer for multi-file VTK datasets. - */ - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - unsigned numElements = this->gridView_().size(0); - ScalarField &pN = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - ScalarField &mut = *writer.allocateManagedBuffer(numElements); - ScalarField &nut = *writer.allocateManagedBuffer(numElements); - ScalarField &lmix = *writer.allocateManagedBuffer(numElements); - ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - - // write volume values to .vtu and .csv - char fileName[30]; - sprintf(fileName, "%s%05d%s", "volVarsData-", this->problem_().timeManager().timeStepIndex(), ".csv"); - std::ofstream volVarsFile(fileName, std::ios_base::out); - asImp_().writeVolVarsHeader(volVarsFile); - volVarsFile << std::endl; - - FVElementGeometry fvGeometry; - VolumeVariables volVars; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int idx = this->elementMapper().index(element); - rank[idx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - - int numLocalVerts = element.template subEntities(dim); - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pN[vIdxGlobal] = volVars.pressure(); - delP[vIdxGlobal] = volVars.pressure() - 1e5; - rho[vIdxGlobal] = volVars.density(); - mu[vIdxGlobal] = volVars.dynamicViscosity(); - velocity[vIdxGlobal] = volVars.velocity(); - - asImp_().writeVolVarsData(volVarsFile, volVars); - volVarsFile << std::endl; - } - } - volVarsFile.close(); - - writer.attachVertexData(pN, "P"); - writer.attachVertexData(delP, "delP"); - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(velocity, "v", dim); - - // ensure that the actual values are given out - asImp_().updateWallProperties(); - - // write flux values to .vtu and .csv - sprintf(fileName, "%s%05d%s", "fluxVarsData-", this->problem_().timeManager().timeStepIndex(), ".csv"); - std::ofstream fluxVarsFile(fileName, std::ios_base::out); - asImp_().writeFluxVarsHeader(fluxVarsFile); - fluxVarsFile << std::endl; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - unsigned int numFluxVars = 0; - Scalar sumDynamicEddyViscosity = 0.0; - Scalar sumKinematicEddyViscosity = 0.0; - Scalar sumMixingLength = 0.0; - Scalar sumUPlus = 0.0; - Scalar sumYPlus = 0.0; - - for (const auto& intersection : Dune::intersections(this->gridView_(), element)) - { - int fIdx = intersection.indexInInside(); - - FluxVariables fluxVars(this->problem_(), element, fvGeometry, - fIdx, elemVolVars, false); - - asImp_().writeFluxVarsData(fluxVarsFile, fluxVars); - fluxVarsFile << std::endl; - - sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); - sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); - sumMixingLength += fluxVars.mixingLength(); - sumUPlus += fluxVars.uPlus(); - sumYPlus += fluxVars.yPlusRough(); - numFluxVars += 1; - } - - int eIdxGlobal = this->elementMapper().index(element); - mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; - nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; - lmix[eIdxGlobal] = sumMixingLength / numFluxVars; - uPlus[eIdxGlobal] = sumUPlus / numFluxVars; - yPlus[eIdxGlobal] = sumYPlus / numFluxVars; - } - fluxVarsFile.close(); - - writer.attachCellData(mut, "mu_t"); - writer.attachCellData(nut, "nu_t"); - writer.attachCellData(lmix, "l_mix"); - writer.attachCellData(uPlus, "u^+"); - writer.attachCellData(yPlus, "y^+"); - } - - - /*! - * \brief Writes the header for the volVarsData.csv file - * - * \param stream The output file stream - */ - void writeVolVarsHeader(std::ofstream &stream) - { - std::cout << "Writing volVars file" << std::endl; - stream << "#globalPos[0]" - << "," << "globalPos[1]" - << "," << "velocity[0]" - << "," << "velocity[1]" - << "," << "pressure" - << "," << "density" - << "," << "temperature"; - } - - /*! - * \brief Writes the data into the volVarsData.csv file - * - * \param stream The output file stream - * \param volVars The volume variables - */ - void writeVolVarsData(std::ofstream &stream, const VolumeVariables &volVars) - { - stream << volVars.globalPos()[0] - << "," << volVars.globalPos()[1] - << "," << volVars.velocity()[0] - << "," << volVars.velocity()[1] - << "," << volVars.pressure() - << "," << volVars.density() - << "," << volVars.temperature(); - } - - /*! - * \brief Writes the header for the fluxVarsData.csv file - * - * \param stream The output file stream - */ - void writeFluxVarsHeader(std::ofstream &stream) - { - std::cout << "Writing fluxVars file" << std::endl; - stream << "#globalPos[0]" - << "," << "globalPos[1]" - << "," << "uPlus" - << "," << "yPlus" - << "," << "uStar" - << "," << "dynamicEddyViscosity" - << "," << "kinematicEddyViscosity" - << "," << "mixingLength"; - } - - /*! - * \brief Writes the data into the fluxVarsData.csv file - * - * \param stream The output file stream - * \param fluxVars The flux variables - */ - void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) - { - stream << fluxVars.globalPos()[0] - << "," << fluxVars.globalPos()[1] - << "," << fluxVars.uPlus() - << "," << fluxVars.yPlusRough() - << "," << fluxVars.frictionVelocityWall() - << "," << fluxVars.dynamicEddyViscosity() - << "," << fluxVars.kinematicEddyViscosity() - << "," << fluxVars.mixingLength(); - } - - /*! - * \name Wall properties - */ - // \{ - - /*! - * \brief Container for all necessary information, needed to calculate the - * eddy viscosity at a certain point in relation to the wall distance - * and fluid/flow properties at the wall. - */ - struct WallProperties - { - public: - bool isBBoxMinWall; //!< Actual wall properties are located on bboxmin or bboxmax. - Scalar wallPos[intervals]; //!< Position of the wall interval in global coordinates. - Scalar sandGrainRoughness[intervals]; //!< Sand grain roughness. - Scalar boundaryLayerThickness[intervals]; //!< Domain influenced by this wall. - Scalar boundaryLayerThicknessCalculated[intervals]; //!< Boundary layer thickness based on v = v_99. - Scalar viscousSublayerThicknessCalculated[intervals]; //!< Viscous sublayer thickness based on y^+ <= 5. - Scalar crossLength[intervals]; //!< Switching point for the Baldwin-Lomax model. - Scalar maxVelocity[intervals][dim]; //!< Max velocity related to this wall. - Scalar maxVelocityAbs[intervals][dim]; //!< Max velocity at this interval position. - Scalar minVelocity[intervals][dim]; //!< Min velocity related to this wall. - Scalar wallDensity[intervals]; //!< Fluid density at the wall. - Scalar wallKinematicViscosity[intervals]; //!< Kinematic viscosity at the wall. - Scalar wallVelGrad[intervals]; //!< Velocity gradient at the wall, in wall normal direction. - Scalar wallShearStress[intervals]; //!< Shear stress at the wall. - Scalar fMax[intervals]; //!< Max value of the f function for Baldwin-Lomax model. - Scalar yMax[intervals]; //!< Distance of position where fMax occurs. - Scalar maxMassFraction[intervals]; //!< Max mass fraction related to this wall. - Scalar maxMoleFraction[intervals]; //!< Max mole fraction related to this wall. - Scalar maxTemperature[intervals]; //!< Max temperature related to this wall. - int isInterpolated[intervals]; //!< Value is only interpolated between neighboring wall intervals. - int fluxValuesCount[intervals]; //!< Number of flux values contributing to the interval. - int wallValuesCount[intervals]; //!< Number of values contributing properties directly at the wall. - bool headerWritten[intervals]; //!< Header of scv-data file was already written. - WallProperties() {} //!< Constructor for wall properties. - }; - WallProperties wall[walls]; - - /*! - * \brief Initializes the wall structure with values. - * - * This should only be done before updating (preTimeStepFunction and - * only once per time Step), because the crossLength - * for the Baldwin Lomax model is reset. - */ - void resetWallProperties() - { - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - { - for (int posIdx = 0; posIdx < intervals; ++posIdx) - { - if (walls == 1) - { - if (bboxMinIsWall) - { - wall[wallIdx].wallPos[posIdx] = this->problem_().bBoxMin()[wallNormal_]; - wall[wallIdx].boundaryLayerThickness[posIdx] = this->problem_().bBoxMax()[wallNormal_] - this->problem_().bBoxMin()[wallNormal_] + eps_; - wall[wallIdx].isBBoxMinWall = true; - wall[wallIdx].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness); - } - if (bboxMaxIsWall) - { - wall[wallIdx].wallPos[posIdx] = this->problem_().bBoxMax()[wallNormal_]; - wall[wallIdx].boundaryLayerThickness[posIdx] = this->problem_().bBoxMin()[wallNormal_] - this->problem_().bBoxMax()[wallNormal_] - eps_; - wall[wallIdx].isBBoxMinWall = false; - wall[wallIdx].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness); - } - } - if (walls == 2 && wallIdx == 0) - { - wall[0].wallPos[posIdx] = this->problem_().bBoxMin()[wallNormal_]; - wall[1].wallPos[posIdx] = this->problem_().bBoxMax()[wallNormal_]; - wall[0].boundaryLayerThickness[posIdx] = (wall[1].wallPos[posIdx] - wall[0].wallPos[posIdx]) / 2 + eps_; - wall[1].boundaryLayerThickness[posIdx] = - wall[0].boundaryLayerThickness[posIdx]; - wall[0].isBBoxMinWall = true; - wall[1].isBBoxMinWall = false; - wall[0].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness); - wall[1].sandGrainRoughness[posIdx] = GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness); - } - wall[wallIdx].crossLength[posIdx] = wall[wallIdx].boundaryLayerThickness[posIdx]; - wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThickness[posIdx]; // != 0, da kleinster wert gwünscht - wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = 0; // == 0, da größter wert gewünscht - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - { - wall[wallIdx].maxVelocity[posIdx][dimIdx] = 0.0; - wall[wallIdx].maxVelocityAbs[posIdx][dimIdx] = 0.0; - wall[wallIdx].minVelocity[posIdx][dimIdx] = 0.0; - } - wall[wallIdx].fMax[posIdx] = 0.0; - wall[wallIdx].yMax[posIdx] = 0.0; - wall[wallIdx].isInterpolated[posIdx] = 0.0; - wall[wallIdx].fluxValuesCount[posIdx] = 0.0; - wall[wallIdx].wallValuesCount[posIdx] = 0.0; - wall[wallIdx].headerWritten[posIdx] = false; - } - } - } - - /*! - * \brief Initializes the wall fluid properties with 0. - */ - void resetWallFluidProperties() - { - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - for (int posIdx = 0; posIdx < intervals; ++posIdx) - { - wall[wallIdx].wallDensity[posIdx] = 0.0; - wall[wallIdx].wallKinematicViscosity[posIdx] = 0.0; - wall[wallIdx].wallVelGrad[posIdx] = 0.0; - wall[wallIdx].wallShearStress[posIdx] = 0.0; - } - } - - /*! - * \brief Complete calculation for all relevant wall values. - * - * If the order is changed, errors may occur because of unknown or zero values - */ - void updateWallProperties() - { - asImp_().resetWallProperties(); - asImp_().updateMaxFluxVars(); - asImp_().updateCrossLength(); - asImp_().resetWallFluidProperties(); - asImp_().updateWallFluidProperties(); - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - { - for (int posIdx = 0; posIdx < intervals; ++posIdx) - if (wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] > wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]) - wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]; - asImp_().interpolateWallProperties(wallIdx); - } - } - - /*! - * \brief Get position index (interval section) a point belongs to. - * - * \param globalPos Global Position. - */ - const int getPosIdx(const GlobalPosition &globalPos) const - { - int posIdx = int (intervals * (globalPos[flowNormal_] - this->problem_().bBoxMin()[flowNormal_])) - / (this->problem_().bBoxMax()[flowNormal_] - this->problem_().bBoxMin()[flowNormal_]); - if (posIdx >= intervals) - posIdx = intervals -1; - return posIdx; - } - - /*! - * \brief Return wall a point belongs to. - * - * \param posIdx Position Index of current Global Position. - * \param globalPos Global Position. - */ - const int getWallIdx(const GlobalPosition &globalPos, const int posIdx) const - { - if (walls == 0) - DUNE_THROW(Dune::NotImplemented, "Eddy viscosity models are not implemented for use without walls."); - - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - if ((wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + wall[wallIdx].boundaryLayerThickness[posIdx]) - || (!wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] + wall[wallIdx].boundaryLayerThickness[posIdx])) - { - return wallIdx; - } - - static bool alreadyPrintedError = false; - static Scalar timePrintedError = 0.0; - if (this->problem_().timeManager().time() > timePrintedError) - { - alreadyPrintedError = false; - } - - if (!alreadyPrintedError) - { - Dune::dinfo << "info: point " << globalPos << " in interval " << posIdx - << " does not belong to wall -> now belongs to wall 0" << std::endl; - alreadyPrintedError = true; - timePrintedError = this->problem_().timeManager().time(); - } - return 0; - } - - - /*! - * \brief Return the distance to corresponding wall including roughness effects - * - * For ksPlus = 0, this is the normal wall distance. - * For ksPlus > 0, an additional length is added to the real wall distance. - * \param globalPos Global Position. - * \param wallIdx Wall Index of current Global Position. - * \param posIdx Position Index of current Global Position. - */ - const Scalar distanceToWallRough(const GlobalPosition &globalPos, const int wallIdx, const int posIdx) const - { - if (surfaceRoughnessNotImplemented()) - { return distanceToWallReal (globalPos, wallIdx, posIdx); } - if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) < eps_&& wall[wallIdx].isBBoxMinWall) - { return distanceToWallReal (globalPos, wallIdx, posIdx); } - if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) < eps_&& !wall[wallIdx].isBBoxMinWall) - { return distanceToWallReal (globalPos, wallIdx, posIdx); } - - Scalar ksPlus = wall[wallIdx].sandGrainRoughness[posIdx] * sqrt(wall[wallIdx].wallShearStress[posIdx] / wall[wallIdx].wallDensity[posIdx]) - / wall[wallIdx].wallKinematicViscosity[posIdx]; - - if (ksPlus > 2000) - { - std::cout << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << globalPos - << " is not in the valid range (ksPlus < 2000)," - << " for high ksPlus values the roughness function reaches a turning point."<< std::endl; - DUNE_THROW(Dune::NotImplemented, "Unphysical roughness behavior."); - ksPlus = 2000; - } - else if (ksPlus < 4.535) - { - Dune::dinfo << "info: equivalent sand grain roughness ks+=" << ksPlus << " at " << globalPos - << " is not in the valid range (ksPlus > 4.535) and now set to 0.0"<< std::endl; - ksPlus = 0.0; - } - - Scalar delta = 0.0; // delta is only changed for ksPlus, which are in valid range, otherwise smooth wall is assumed - if (ksPlus >= 4.535) - { - delta = 0.9 * wall[wallIdx].wallKinematicViscosity[posIdx] / sqrt(wall[wallIdx].wallShearStress[posIdx] / wall[wallIdx].wallDensity[posIdx]) * (sqrt(ksPlus) - ksPlus * exp(- 1.0 * ksPlus / 6.0)); - } - - int sign = std::abs(globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]) / (globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]); - return globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx] + sign * delta; - } - - /*! - * \brief Return the distance to corresponding wall. - * - * \param globalPos Global Position. - * \param wallIdx Wall Index of current Global Position. - * \param posIdx Position Index of current Global Position. - */ - const Scalar distanceToWallReal(const GlobalPosition &globalPos, const int wallIdx, const int posIdx) const - { return globalPos[wallNormal_] - wall[wallIdx].wallPos[posIdx]; } - - /*! - * \brief Return true if function for muInner should be used. - * - * \param globalPos Global Position. - * \param posIdx Position Index of current Global Position. - */ - const bool useViscosityInner(const GlobalPosition &globalPos, const int posIdx) const - { - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - if ((wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + wall[wallIdx].crossLength[posIdx]) - || (!wall[wallIdx].isBBoxMinWall && globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] + wall[wallIdx].crossLength[posIdx])) - return true; - return false; - } - - /*! - * \brief Loop over all elements, used to calculate maximum flux values - * in the whole domain. - */ - void updateMaxFluxVars() - { - FVElementGeometry fvGeometry; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - for (int fIdx = 0; fIdx < fvGeometry.numScvf; ++fIdx) - { - - FluxVariables fluxVars(this->problem_(), - element, - fvGeometry, - fIdx, - elemVolVars, - false); - - GlobalPosition globalPos = fvGeometry.subContVolFace[fIdx].ipGlobal; - - asImp_().calculateMaxFluxVars(fluxVars, globalPos); - } - } - } - - /*! - * \brief Update maximum values in the domain and - * set them to the corresponding wall. - * - * \param fluxVars Flux Variables of current element. - * \param globalPos Global Position. - */ - void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition globalPos) - { - int posIdx = getPosIdx(globalPos); - int wallIdx = getWallIdx(globalPos, posIdx); - for (int dimIdx = 0; dimIdx < dim; ++dimIdx) - { - if (std::abs(wall[wallIdx].maxVelocity[posIdx][dimIdx]) < std::abs(fluxVars.velocity()[dimIdx])) - { - wall[wallIdx].maxVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; -// // if the values in the middle should be set on both wall -// for (int wIdx = 0; wIdx < walls; ++wIdx) -// if (std::abs(distanceToWallReal(globalPos, wallIdx, posIdx)) < std::abs(wall[wIdx].boundaryLayerThickness[posIdx] + 1e-5)) -// wall[wIdx].maxVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; - // set it as maxVelocityAbs - if (std::abs(wall[wallIdx].maxVelocityAbs[posIdx][dimIdx]) < std::abs(fluxVars.velocity()[dimIdx])) - for (int wIdx = 0; wIdx < walls; ++wIdx) - wall[wIdx].maxVelocityAbs[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; - wall[wallIdx].fluxValuesCount[posIdx]++; - } - if (std::abs(wall[wallIdx].minVelocity[posIdx][dimIdx]) > std::abs(fluxVars.velocity()[dimIdx])) - wall[wallIdx].minVelocity[posIdx][dimIdx] = fluxVars.velocity()[dimIdx]; - } - - // fMax and yMax - if (wall[wallIdx].fMax[posIdx] < fluxVars.fz()) - { - wall[wallIdx].fMax[posIdx] = fluxVars.fz(); - wall[wallIdx].yMax[posIdx] = distanceToWallRough(globalPos, wallIdx, posIdx); -// // if the values in the middle should be set on both wall -// for (int wIdx = 0; wIdx < walls; ++wIdx) -// if (std::abs(distanceToWall(globalPos, wIdx, posIdx)) < std::abs(wall[wIdx].boundaryLayerThickness[posIdx] + 1e-4)) -// { -// wall[wIdx].fMax[posIdx] = fluxVars.fz(); -// wall[wIdx].yMax[posIdx] = distanceToWall(globalPos, wallIdx, posIdx); -// } - } - } - - /*! - * \brief Get maximum values of the f(z) function in the Baldwin-Lomax model. - */ - void updateCrossLength() - { - FVElementGeometry fvGeometry; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - for (const auto& intersection : Dune::intersections(this->gridView_(), element)) - { - int fIdx = intersection.indexInInside(); - FluxVariables fluxVars(this->problem_(), - element, - fvGeometry, - fIdx, - elemVolVars, - false); - - GlobalPosition globalPos = fvGeometry.subContVolFace[fIdx].ipGlobal; - int posIdx = getPosIdx(globalPos); - int wallIdx = getWallIdx(globalPos, posIdx); - - // muCross - if (fluxVars.dynamicEddyViscosityOuter() < fluxVars.dynamicEddyViscosityInner() - && useViscosityInner(globalPos, posIdx)) - { - wall[wallIdx].crossLength[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); - } - - if (std::abs(fluxVars.velocity()[flowNormal_]) >= 0.99 * std::abs(wall[wallIdx].maxVelocity[posIdx][flowNormal_]) - && std::abs(wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]) > std::abs(distanceToWallReal(globalPos, wallIdx, posIdx))) - { - wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); - } - - if (wall[wallIdx].maxVelocity[posIdx][flowNormal_] * globalPos[flowNormal_] / fluxVars.kinematicViscosity() < 2300) - { - wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = wall[wallIdx].boundaryLayerThicknessCalculated[posIdx]; - } - else if ((fluxVars.velocity()[flowNormal_] / fluxVars.frictionVelocityWall() <= 5.0) - && (std::abs(wall[wallIdx].viscousSublayerThicknessCalculated[posIdx]) - < std::abs(distanceToWallReal(globalPos, wallIdx, posIdx)))) - { - wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = distanceToWallReal(globalPos, wallIdx, posIdx); - } - } - } - } - - /*! - * \brief Loop over all elements to update the values at the wall. - */ - void updateWallFluidProperties() - { - FVElementGeometry fvGeometry; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - const ReferenceElement &refElement = ReferenceElements::general(element.geometry().type()); - for (const auto& intersection : Dune::intersections(this->gridView_(), element)) - { - // handle only faces on the boundary - if (!intersection.boundary()) - continue; - - // Assemble the boundary for all vertices of the current - // face - int fIdx = intersection.indexInInside(); - int numFaceVerts = refElement.size(fIdx, 1, dim); - for (int faceVertIdx = 0; - faceVertIdx < numFaceVerts; - ++faceVertIdx) - { - int boundaryFaceIdx = fvGeometry.boundaryFaceIndex(fIdx, faceVertIdx); - - - - - const FluxVariables boundaryVars(this->problem_(), - element, - fvGeometry, - boundaryFaceIdx, - elemVolVars, - true); - - GlobalPosition globalPos = fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal; - if ( - globalPos[wallNormal_] > this->problem_().bBoxMin()[wallNormal_] + 1e-15 - && globalPos[wallNormal_] < this->problem_().bBoxMax()[wallNormal_] - 1e-15 - ) - continue; - - asImp_().calculateWallFluidProperties(boundaryVars, globalPos); - } // end loop over intersections - } // end loop over element vertices - } - } - - /*! - * \brief Calculate / average the values at the wall. - * - * \param boundaryVars Flux Variables at boundary segment. - * \param globalPos Global Position. - */ - void calculateWallFluidProperties(const FluxVariables &boundaryVars, const GlobalPosition &globalPos) - { - int posIdx = getPosIdx(globalPos); - int wallIdx = getWallIdx(globalPos, posIdx); - if (globalPos[wallNormal_] > wall[wallIdx].wallPos[posIdx] - 1e-8 - && globalPos[wallNormal_] < wall[wallIdx].wallPos[posIdx] + 1e-8) - { - wall[wallIdx].wallValuesCount[posIdx] += 1; - wall[wallIdx].wallDensity[posIdx] = - (wall[wallIdx].wallDensity[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.density()) - / wall[wallIdx].wallValuesCount[posIdx]; - wall[wallIdx].wallKinematicViscosity[posIdx] = - (wall[wallIdx].wallKinematicViscosity[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.kinematicViscosity()) - / wall[wallIdx].wallValuesCount[posIdx]; - wall[wallIdx].wallVelGrad[posIdx] = - (boundaryVars.velocityGrad()[flowNormal_][wallNormal_] * (wall[wallIdx].wallValuesCount[posIdx] - 1) + boundaryVars.velocityGrad()[flowNormal_][wallNormal_]) - / wall[wallIdx].wallValuesCount[posIdx]; - wall[wallIdx].wallShearStress[posIdx] = - (wall[wallIdx].wallShearStress[posIdx] * (wall[wallIdx].wallValuesCount[posIdx] - 1) - + std::abs(boundaryVars.velocityGrad()[flowNormal_][wallNormal_]) * boundaryVars.dynamicViscosity()) - / wall[wallIdx].wallValuesCount[posIdx]; - } - } - - - /*! - * \brief Find points with given values and start interpolation. - * - * \param wallIdx Wall Index of current Global Position. - */ - const void interpolateWallProperties(const int wallIdx) - { - const int startInterpolation = 0; - const int endInterpolation = intervals; - - for (int posIdx = startInterpolation; posIdx < endInterpolation; ++posIdx) - { - if (wall[wallIdx].fluxValuesCount[posIdx] == 0) - { - int prevIdx = posIdx; - int nextIdx = posIdx; - // Getting previous value, if 0 is reached (and tau is still < eps_), get next value - for (prevIdx = posIdx-1; prevIdx >= startInterpolation; --prevIdx) - if (wall[wallIdx].fluxValuesCount[prevIdx] != 0) - break; - if (prevIdx < startInterpolation) // interpolation at x=0, prevIdx is -1 - for (prevIdx = posIdx+1; prevIdx < endInterpolation; ++prevIdx) - if (wall[wallIdx].fluxValuesCount[prevIdx] != 0) - break; - if (prevIdx == endInterpolation && this->problem_().timeManager().time() > this->problem_().timeManager().timeStepSize()) - { - Dune::dinfo << "info: for posIdx " << posIdx << "on wall " << wallIdx - << "there are no fluxValues for interpolation." << std::endl; - break; - } - - // Getting next value, if intervals is reached get prev value - for (nextIdx = posIdx+1; nextIdx < endInterpolation; ++nextIdx) - if (wall[wallIdx].fluxValuesCount[nextIdx] != 0 && nextIdx != prevIdx) - break; - if (nextIdx == endInterpolation) - for (nextIdx = posIdx-1; nextIdx >= startInterpolation; --nextIdx) - if (wall[wallIdx].fluxValuesCount[nextIdx] != 0 && nextIdx != prevIdx) - break; - - asImp_().doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); - } - - - if (wall[wallIdx].wallValuesCount[posIdx] == 0) // || wall[wallIdx].wallValuesCount[posIdx] > 50) - { - int prevIdx = posIdx; - int nextIdx = posIdx; - // Getting previous value, if 0 is reached (and tau is still < eps_), get next value - for (prevIdx = posIdx-1; prevIdx >= startInterpolation; --prevIdx) - if (wall[wallIdx].wallValuesCount[prevIdx] != 0) - break; - if (prevIdx < startInterpolation) // interpolation at x=0, prevIdx is -1 - for (prevIdx = posIdx+1; prevIdx < endInterpolation; ++prevIdx) - if (wall[wallIdx].wallValuesCount[prevIdx] != 0) - break; - if (prevIdx == endInterpolation && this->problem_().timeManager().time() > this->problem_().timeManager().timeStepSize()) - { - Dune::dinfo << "info: for posIdx " << posIdx << "on wall " << wallIdx - << "there are no wallValues for interpolation." << std::endl; - break; - } - - // Getting next value, if intervals is reached get prev value - for (nextIdx = posIdx+1; nextIdx < endInterpolation; ++nextIdx) - if (wall[wallIdx].wallValuesCount[nextIdx] != 0 && nextIdx != prevIdx) - break; - if (nextIdx == endInterpolation) - for (nextIdx = posIdx-1; nextIdx >= startInterpolation; --nextIdx) - if (wall[wallIdx].wallValuesCount[nextIdx] != 0 && nextIdx != prevIdx) - break; - - asImp_().doInterpolationWallValues(wallIdx, posIdx, prevIdx, nextIdx); - } - } - } - - /*! - * \brief Interpolate flux Values, so that flux related Properties - * are given in every Interval. - * - * \param wallIdx Wall Index for interpolation. - * \param posIdx Position Index for interpolation (no given value). - * \param prevIdx Position Index with value. - * \param nextIdx Position Index with value. - */ - const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) - { - wall[wallIdx].boundaryLayerThickness[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].boundaryLayerThickness[prevIdx], nextIdx, wall[wallIdx].boundaryLayerThickness[nextIdx]); - wall[wallIdx].boundaryLayerThicknessCalculated[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].boundaryLayerThicknessCalculated[prevIdx], nextIdx, wall[wallIdx].boundaryLayerThicknessCalculated[nextIdx]); - wall[wallIdx].viscousSublayerThicknessCalculated[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].viscousSublayerThicknessCalculated[prevIdx], nextIdx, wall[wallIdx].viscousSublayerThicknessCalculated[nextIdx]); - wall[wallIdx].crossLength[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].crossLength[prevIdx], nextIdx, wall[wallIdx].crossLength[nextIdx]); - wall[wallIdx].maxVelocity[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocity[prevIdx][0], nextIdx, wall[wallIdx].maxVelocity[nextIdx][0]); - wall[wallIdx].maxVelocity[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocity[prevIdx][1], nextIdx, wall[wallIdx].maxVelocity[nextIdx][1]); - wall[wallIdx].minVelocity[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].minVelocity[prevIdx][0], nextIdx, wall[wallIdx].minVelocity[nextIdx][0]); - wall[wallIdx].minVelocity[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].minVelocity[prevIdx][1], nextIdx, wall[wallIdx].minVelocity[nextIdx][1]); - wall[wallIdx].maxVelocityAbs[posIdx][0] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocityAbs[prevIdx][0], nextIdx, wall[wallIdx].maxVelocityAbs[nextIdx][0]); - wall[wallIdx].maxVelocityAbs[posIdx][1] = interpolation(posIdx, prevIdx, wall[wallIdx].maxVelocityAbs[prevIdx][1], nextIdx, wall[wallIdx].maxVelocityAbs[nextIdx][1]); - wall[wallIdx].fMax[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].fMax[prevIdx], nextIdx, wall[wallIdx].fMax[nextIdx]); - wall[wallIdx].yMax[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].yMax[prevIdx], nextIdx, wall[wallIdx].yMax[nextIdx]); - wall[wallIdx].isInterpolated[posIdx] += 1; - } - - /*! - * \brief Interpolate wall Values, so that wall related Properties - * are given in every Interval. - * - * \param wallIdx Wall Index for interpolation. - * \param posIdx Position Index for interpolation (no given value). - * \param prevIdx Position Index with value. - * \param nextIdx Position Index with value. - */ - const void doInterpolationWallValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) - { - wall[wallIdx].wallDensity[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallDensity[prevIdx], nextIdx, wall[wallIdx].wallDensity[nextIdx]); - wall[wallIdx].wallKinematicViscosity[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallKinematicViscosity[prevIdx], nextIdx, wall[wallIdx].wallKinematicViscosity[nextIdx]); - wall[wallIdx].wallVelGrad[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallVelGrad[prevIdx], nextIdx, wall[wallIdx].wallVelGrad[nextIdx]); - wall[wallIdx].wallShearStress[posIdx] = interpolation(posIdx, prevIdx, wall[wallIdx].wallShearStress[prevIdx], nextIdx, wall[wallIdx].wallShearStress[nextIdx]); - wall[wallIdx].isInterpolated[posIdx] += 2; - } - - /*! - * \brief Mathematical linear interpolation routine. - * - * Return the linear interpolated value at any point between to values. - * - * \param position Position for which interpolation is made. - * \param prev First Position for which the value is known. - * \param prevValue Known value at prev position. - * \param next Second Position for which the value is known. - * \param nextValue Known value at next position. - */ - const Scalar interpolation(const Scalar position, const Scalar prev, const Scalar prevValue, const Scalar next, const Scalar nextValue) - { - return (prevValue + (nextValue - prevValue) / (next - prev) * (position - prev)); - } - - // \} // wall properties - - /*! - * \brief Returns whether the actual eddy viscosity model includes surface roughness approach. - * - * Surface roughness is not included in the Baldwin Lomax model - */ - const bool surfaceRoughnessNotImplemented() const - { - switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) - { - case EddyViscosityIndices::noEddyViscosityModel: // 0 - return true; - break; - default: - return false; - } - } - - /*! - * \brief Returns the name of the used eddy viscosity model. - */ - const char *eddyViscosityModelName() const - { - switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyViscosityModel)) - { - case EddyViscosityIndices::noEddyViscosityModel: // 0 - return "noEddyViscosityModel"; - break; - case EddyViscosityIndices::prandtl: // 1 - return "prandtl"; - break; - case EddyViscosityIndices::modifiedVanDriest: // 2 - return "modifiedVanDriest"; - break; - case EddyViscosityIndices::baldwinLomax: // 3 - return "baldwinLomax"; - break; - default: - DUNE_THROW(Dune::NotImplemented, "This eddy viscosity model is not implemented."); - } - } - - -protected: - //! Current implementation. - Implementation &asImp_() - { return *static_cast<Implementation*>(this); } - //! Current implementation. - const Implementation &asImp_() const - { return *static_cast<const Implementation*>(this); } - -private: - const int flowNormal_; - const int wallNormal_; - Scalar eps_; -}; - -} - -#include "zeroeqpropertydefaults.hh" - -#endif // DUMUX_ZEROEQ_MODEL_HH +#endif diff --git a/dumux/freeflow/zeroeq/zeroeqproblem.hh b/dumux/freeflow/zeroeq/zeroeqproblem.hh index 04fa62da9947f1524c5b7da9b930cc06824e5221..2807e5984baee721f63a4fe17805294edfae234c 100644 --- a/dumux/freeflow/zeroeq/zeroeqproblem.hh +++ b/dumux/freeflow/zeroeq/zeroeqproblem.hh @@ -1,82 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Base class for all ZeroEq problems which use the box scheme. - */ -#ifndef DUMUX_ZEROEQ_PROBLEM_HH -#define DUMUX_ZEROEQ_PROBLEM_HH +#ifndef DUMUX_ZEROEQ_PROBLEM_HH_OLD +#define DUMUX_ZEROEQ_PROBLEM_HH_OLD -#include <dumux/freeflow/stokes/stokesmodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqproperties.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeq/problem.hh instead -namespace Dumux -{ -/*! - * \ingroup ImplicitBaseProblems - * \ingroup BoxZeroEqModel - * \brief Base class for all problems which use the ZeroEq box model. - * - * This implements the call of update functions used for the wall properties of - * the ZeroEq box model. - */ -template<class TypeTag> -class ZeroEqProblem : public StokesProblem<TypeTag> -{ - typedef StokesProblem<TypeTag> ParentType; +#include <dumux/freeflow/zeroeq/problem.hh> - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - -public: - ZeroEqProblem(TimeManager &timeManager, const GridView &gridView) - : ParentType(timeManager, gridView) - { } - - /*! - * \brief Called by the Dumux::TimeManager in order to initialize the problem. - * - * If you overload this method don't forget to call ParentType::init().<br> - * This initializes all wall-related properties, which are necessary for the - * ZeroEq box model. - */ - void init() - { - // set the initial condition of the model - ParentType::init(); - this->model().resetWallProperties(); - this->model().resetWallFluidProperties(); - } - - /*! - * \brief Called by the time manager before the time integration. - * - * This updates all wall-related properties, which are necessary for the - * ZeroEq box model - */ - void preTimeStep() - { - this->model().updateWallProperties(); - } -}; - -} - -#endif // DUMUX_ZEROEQ_PROBLEM_HH +#endif diff --git a/dumux/freeflow/zeroeq/zeroeqproperties.hh b/dumux/freeflow/zeroeq/zeroeqproperties.hh index 532406163cddf2e4fc998eb1512259b6a90a77de..d3d2d8df69a74c83cd864a5a528c7d2a2081fa40 100644 --- a/dumux/freeflow/zeroeq/zeroeqproperties.hh +++ b/dumux/freeflow/zeroeq/zeroeqproperties.hh @@ -1,68 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqModel - * - * \file - * - * \brief Defines the supplementary properties required for the - * ZeroEq model. - * - */ +#ifndef DUMUX_ZEROEQ_PROPERTIES_HH_OLD +#define DUMUX_ZEROEQ_PROPERTIES_HH_OLD -#ifndef DUMUX_ZEROEQ_PROPERTIES_HH -#define DUMUX_ZEROEQ_PROPERTIES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeq/properties.hh instead -#include <dumux/freeflow/stokes/stokesproperties.hh> +#include <dumux/freeflow/zeroeq/properties.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tag for the ZeroEq Problem -NEW_TYPE_TAG(BoxZeroEq, INHERITS_FROM(BoxStokes)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// - -NEW_PROP_TAG(KarmanConstant); //!< The Karman constant -NEW_PROP_TAG(BBoxMinIsWall); //!< Sets BBoxMin as a wall -NEW_PROP_TAG(BBoxMaxIsWall); //!< Sets BBoxMax as a wall -NEW_PROP_TAG(ZeroEqFlowNormal); //!< Indicates the main flow direction -NEW_PROP_TAG(ZeroEqWallNormal); //!< Indicates the wall normal direction -NEW_PROP_TAG(ZeroEqBBoxMinSandGrainRoughness); //!< Sets a sand grain roughness at BBoxMin -NEW_PROP_TAG(ZeroEqBBoxMaxSandGrainRoughness); //!< Sets a sand grain roughness at BBoxMax -NEW_PROP_TAG(ZeroEqEddyViscosityModel); //!< Returns used eddy viscosity model -NEW_PROP_TAG(NumberOfIntervals); //!< Returns number of wall intervals -NEW_PROP_TAG(BaseStokesModel); //!< Returns the base implementation of the Stokes model -NEW_PROP_TAG(BaseStokesVolumeVariables); //!< Returns the base implementation of the Stokes volume variables -NEW_PROP_TAG(BaseStokesFluxVariables); //!< Returns the base implementation of the Stokes flux variables -} - -} - -#endif // DUMUX_ZEROEQ_PROPERTIES_HH +#endif diff --git a/dumux/freeflow/zeroeq/zeroeqpropertydefaults.hh b/dumux/freeflow/zeroeq/zeroeqpropertydefaults.hh index 088e7c34d791eadd1859c13238629b3b910f6f0c..3d4daaf6224dbdd40706a40eee55cf274c69651b 100644 --- a/dumux/freeflow/zeroeq/zeroeqpropertydefaults.hh +++ b/dumux/freeflow/zeroeq/zeroeqpropertydefaults.hh @@ -1,92 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqModel - * - * \file - * - * \brief Defines the properties required for the ZeroEq model. - */ +#ifndef DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH_OLD -#ifndef DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH -#define DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH +#warning this header is deprecated, use dumux/freeflow/zeroeq/propertydefaults.hh instead -#include "zeroeqfluxvariables.hh" -#include "zeroeqmodel.hh" +#include <dumux/freeflow/zeroeq/propertydefaults.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -// INHERITED -//! Set the Model property -SET_TYPE_PROP(BoxZeroEq, Model, ZeroEqModel<TypeTag>); - -//! Set the Flux Variables property -SET_TYPE_PROP(BoxZeroEq, FluxVariables, ZeroEqFluxVariables<TypeTag>); - -//! Set the indices used by the ZeroEq model -SET_TYPE_PROP(BoxZeroEq, Indices, ZeroEqCommonIndices<TypeTag>); - -//! Set calculation to Navier Stokes -SET_BOOL_PROP(BoxZeroEq, EnableNavierStokes, true); - -// NEW PROPERTIES -//! Set the Karman constant \f$[-]\f$ -SET_SCALAR_PROP(BoxZeroEq, KarmanConstant, 0.41); - -//! Set BBoxMin of wall normal direction as a wall -SET_BOOL_PROP(BoxZeroEq, BBoxMinIsWall, true); - -//! Set BBoxMax of wall normal direction as a wall -SET_BOOL_PROP(BoxZeroEq, BBoxMaxIsWall, true); - -//! Set main flow direction -SET_INT_PROP(BoxZeroEq, ZeroEqFlowNormal, 0); - -//! Set wall normal direction -SET_INT_PROP(BoxZeroEq, ZeroEqWallNormal, 1); - -//! Set a zero sand grain roughness \f$[m]\f$ at BBoxMin -SET_SCALAR_PROP(BoxZeroEq, ZeroEqBBoxMinSandGrainRoughness, 0.0); - -//! Set a zero sand grain roughness \f$[m]\f$ at BBoxMax -SET_SCALAR_PROP(BoxZeroEq, ZeroEqBBoxMaxSandGrainRoughness, 0.0); - -//! Set the eddy viscosity model -SET_INT_PROP(BoxZeroEq, ZeroEqEddyViscosityModel, 1); - -//! Set the number of wall intervals in which more complex turbulence models are evaluated -SET_INT_PROP(BoxZeroEq, NumberOfIntervals, 1000); - -//! Set the BaseStokesFluxVariables to StokesFluxVariables -SET_TYPE_PROP(BoxZeroEq, BaseStokesFluxVariables, StokesFluxVariables<TypeTag>); - -//! Set the BaseStokesModel to StokesModel -SET_TYPE_PROP(BoxZeroEq, BaseStokesModel, StokesModel<TypeTag>); -} -} // namespace Dumux -#endif // DUMUX_ZEROEQ_PROPERTY_DEFAULTS_HH +#endif diff --git a/dumux/freeflow/zeroeqnc/fluxvariables.hh b/dumux/freeflow/zeroeqnc/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..5cf4770a33231f692892bdd22641c9cf730f12d9 --- /dev/null +++ b/dumux/freeflow/zeroeqnc/fluxvariables.hh @@ -0,0 +1,258 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * the fluxes of the compositional ZeroEq model over a face of a finite volume. + * + * This means the methods to calculate the eddy diffusivity. + */ +#ifndef DUMUX_ZEROEQNC_FLUX_VARIABLES_HH +#define DUMUX_ZEROEQNC_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/common/valgrind.hh> + +#include <dumux/freeflow/zeroeq/fluxvariables.hh> +#include <dumux/freeflow/zeroeqnc/indices.hh> +#include <dumux/freeflow/zeroeqnc/properties.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqncModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains data which is required to + * calculate the component fluxes over a face of a finite + * volume for a compositional ZeroEq model. + * + * This means the methods to calculate the eddy diffusivity. + */ +template <class TypeTag> +class ZeroEqncFluxVariables : public ZeroEqFluxVariables<TypeTag> +{ + typedef ZeroEqFluxVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { dim = GridView::dimension, + phaseIdx = Indices::phaseIdx, + transportCompIdx = Indices::transportCompIdx}; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + +public: + ZeroEqncFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) + , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + , eddyDiffusivityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyDiffusivityModel)) + { + globalPos_ = this->face().ipGlobal; + posIdx_ = problem.model().getPosIdx(globalPos_); + wallIdx_ = problem.model().getWallIdx(globalPos_, posIdx_); + velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; + velGradWall_ = problem.model().wall[wallIdx_].wallVelGrad[posIdx_]; + yPlusReal_ = this->distanceToWallReal() * this->frictionVelocityWall() + / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; + + eddyDiffusivity_ = 0.0; + mixingLengthDiffusivity_ = 0.0; + + DimVector tmp(0.0); + densityGrad_ = 0.0; + + // calculate gradients and secondary variables at IPs + for (int idx = 0; idx < this->fvGeometry_.numScv; idx++) + { + tmp = this->face().grad[idx]; + tmp *= elemVolVars[idx].density(); + densityGrad_ += tmp; + } + + // Richardson number + // Schlichting, Boundary Layer Theory, 1997, p472 + Scalar gravity = 0.0; + if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) + gravity = problem.gravity()[wallNormal_]; + else + gravity = 9.81; + richardsonNumber_ = -gravity / this->density() + * densityGrad()[wallNormal_] / (velGradWall_ * velGradWall_); + + // calculation of an eddy diffusivity only makes sense with Navier-Stokes equation + if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) + calculateEddyDiffusivity_(problem, element, elemVolVars); + }; + +protected: + /*! + * \brief This functions calculates the eddy diffusivity. + * + * The eddy diffusivity is added to the diffusivity in stokesnclocalresidual.hh + * at each scv face. + */ + void calculateEddyDiffusivity_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + // no eddy diffusivity model + if (eddyDiffusivityModel_ == EddyDiffusivityIndices::noEddyDiffusivityModel) + return; + + // Reynolds analogy + // Bird, Stewart and Lightfoot, Transport Phenomena, 2007, p 657 + else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::reynoldsAnalogy) + { + eddyDiffusivity_ = this->kinematicEddyViscosity() + / GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, TurbulentSchmidtNumber); + } + + // modified Van-Driest + // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 + else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::modifiedVanDriest) + { + Scalar aPlus = 26.0; + Scalar bPlus = 0.26; + // eddy diffusivity can only be calculated correctly for non-zero distance to walls + mixingLengthDiffusivity_ = 0.0; + if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) + mixingLengthDiffusivity_ = this->karmanConstant() * this->distanceToWallReal() + * (1.0 - std::exp(-yPlusReal_ / aPlus)) + / std::sqrt(1.0 - std::exp(-bPlus * yPlusReal_)); + + eddyDiffusivity_ = mixingLengthDiffusivity_ * mixingLengthDiffusivity_ * std::abs(velGrad_); + } + + // Deissler near wall law + // Deissler, R. G. "Analysis of Turbulent Heat Transfer, Mass Transfer, and Friction in Smooth Tubes at High Prandtl and Schmidt Numbers" + // NACA Report, 1954, 1210, 69-82 + else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::deissler) + { + const Scalar deisslerConstant = 0.124; + const Scalar beta = this->density() * deisslerConstant * deisslerConstant + * std::abs(this->velocity()[flowNormal_]) + * this->distanceToWallReal(); + eddyDiffusivity_ = beta * (1.0 - std::exp(-beta / this->dynamicViscosity())); + eddyDiffusivity_ /= this->density(); + } + + // Meier and Rotta + // Cebeci, Analysis of turbulent boundary layer, 1974, p 251f + else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::meier) + { + // Sc_t at flow = 0.86 + // Sc_t in wall = 1.34 + Scalar kappaMeier = this->karmanConstant() / std::sqrt(0.86); + Scalar aPlusMeier = std::sqrt(1.34) / std::sqrt(0.86) * 26.0; + mixingLengthDiffusivity_ = 0.0; + if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) + mixingLengthDiffusivity_ = kappaMeier * this->distanceToWallReal() + * (1.0 - std::exp(- yPlusReal_ / aPlusMeier)); + eddyDiffusivity_ = mixingLengthDiffusivity_ * mixingLengthDiffusivity_ * std::abs(velGrad_); + } + + // exponential (after Mamayev) + // Lehfeldt, Ein algebraisches Turbulenzmodell für Ästuare, 1991, p 65 + else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::exponential) + { + Scalar m = 0.8; // 18.0=Perrels, 0.8=Mamayev + if (velGradWall_ == 0) // means incredible high Ri + eddyDiffusivity_ = 0.0; + else + eddyDiffusivity_ = std::exp(-m * richardsonNumber()) + * this->kinematicEddyViscosity(); + } + + else + { + DUNE_THROW(Dune::NotImplemented, "This eddy diffusivity model is not implemented."); + } + + Valgrind::CheckDefined(eddyDiffusivity_); + } + + +public: + /*! + * \brief Returns the eddy diffusivity \f$\mathrm{[m^2/s]}\f$. + * + * The eddy diffusivity does not depend on the component + */ + const Scalar eddyDiffusivity() const + { return eddyDiffusivity_; } + + /*! + * \brief Returns the density gradient \f$\mathrm{[kg/m^4]}\f$. + */ + const DimVector densityGrad() const + { return densityGrad_; } + + /*! + * \brief Returns the richardson number \f$\mathrm{[-]}\f$. + */ + const Scalar richardsonNumber() const + { return richardsonNumber_; } + + /*! + * \brief Returns the Schmidt number (molecular) \f$\mathrm{[-]}\f$. + */ + const Scalar schmidtNumber() const + { return this->kinematicViscosity() / this->diffusionCoeff(transportCompIdx); } + + /*! + * \brief Returns the turbulent Schmidt number \f$\mathrm{[-]}\f$. + */ + const Scalar turbulentSchmidtNumber() const + { return this->kinematicEddyViscosity() / eddyDiffusivity(); } + +private: + const int flowNormal_; + const int wallNormal_; + const int eddyDiffusivityModel_; + int posIdx_; + int wallIdx_; + + Scalar velGrad_; + Scalar velGradWall_; + Scalar yPlusReal_; + DimVector globalPos_; + + Scalar eddyDiffusivity_; + Scalar mixingLengthDiffusivity_; + Scalar richardsonNumber_; + DimVector densityGrad_; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQNC_FLUX_VARIABLES_HH diff --git a/dumux/freeflow/zeroeqnc/indices.hh b/dumux/freeflow/zeroeqnc/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..236a5b54295c3a92382445a35ed6f14ea7ee838e --- /dev/null +++ b/dumux/freeflow/zeroeqnc/indices.hh @@ -0,0 +1,64 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * \brief Defines the indices required for the compositional ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQNC_INDICES_HH +#define DUMUX_ZEROEQNC_INDICES_HH + +#include <dumux/freeflow/stokesnc/indices.hh> +#include <dumux/freeflow/zeroeq/indices.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqncModel + * \brief The indices for the eddy diffusivity model. + */ +struct EddyDiffusivityIndices +{ + // Eddy Diffusivity Model Indices + static const int noEddyDiffusivityModel = 0; + static const int reynoldsAnalogy = 1; + static const int modifiedVanDriest = 2; + static const int deissler = 3; + static const int meier = 4; + static const int exponential = 5; +}; + +/*! + * \ingroup BoxZeroEqncModel + * \ingroup ImplicitIndices + * \brief The common indices for the isothermal compositional ZeroEq box model. + * + * \tparam PVOffset The first index in a primary variable vector. + */ +template <class TypeTag, int PVOffset = 0> +struct ZeroEqncCommonIndices : public StokesncCommonIndices<TypeTag, PVOffset> +{ + static const int scvDataPrecision = 5; + static const int scvDataWidth = scvDataPrecision + 10; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQNC_INDICES_HH diff --git a/dumux/freeflow/zeroeqnc/model.hh b/dumux/freeflow/zeroeqnc/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..41b790ef3a010950f194c9281027f5b855892712 --- /dev/null +++ b/dumux/freeflow/zeroeqnc/model.hh @@ -0,0 +1,390 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for all models which use the compositional ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQNC_MODEL_HH +#define DUMUX_ZEROEQNC_MODEL_HH + +#include "indices.hh" +#include "properties.hh" +#include <dumux/freeflow/stokesnc/model.hh> +#include <dumux/freeflow/zeroeq/model.hh> + +namespace Dumux +{ +/*! + * \ingroup BoxZeroEqncModel + * \brief Adaption of the box scheme to the compositional ZeroEq model. + * + * This model implements an single-phase isothermal compositional free flow + * solving the mass and the momentum balance. For the momentum balance + * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation + * (algebraic) turbulence model is used. + * + * Mass balance: + * \f[ + * \frac{\partial \varrho_\textrm{g}}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) + * - q_\textrm{g} = 0 + * \f] + * + * Momentum Balance: + * \f[ + * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} + * + \text{div} \left( + * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} + * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] + * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} + * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) + * \right) + * + \left(p_\textrm{g} {\bf {I}} \right) + * - \varrho_\textrm{g} {\bf g} = 0 + * \f] + * + * Component mass balance equations: + * \f[ + * \frac{\partial \left(\varrho_\textrm{g} X_\textrm{g}^\kappa\right)}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} X_\textrm{g}^\kappa + * - \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] + * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x_\textrm{g}^\kappa \right) + * - q_\textrm{g}^\kappa = 0 + * \f] + * Please note that, even though it is n-component model, the diffusive + * fluxes are still calculated with binary diffusion. + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class ZeroEqncModel : public ZeroEqModel<TypeTag> +{ + typedef ZeroEqModel<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), + walls = (GET_PROP_VALUE(TypeTag, BBoxMinIsWall) ? 1 : 0) + + (GET_PROP_VALUE(TypeTag, BBoxMaxIsWall) ? 1 : 0) + }; + enum { transportCompIdx = Indices::transportCompIdx, + numComponents = Indices::numComponents }; + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + + +public: + ZeroEqncModel() + : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + { + eps_ = 1e-6; + + // check whether sand grain roughness may be used + if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 + || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) + { + Dune::dwarn << "warning: surface roughness will not be used for eddy diffusivity models." << std::endl; + } + } + + //! \copydoc ImplicitModel::addOutputVtkFields + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + unsigned numElements = this->gridView_().size(0); + ScalarField &pN = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField *moleFraction[numComponents]; + ScalarField *massFraction[numComponents]; + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + ScalarField &D = *writer.allocateManagedBuffer(numVertices); + ScalarField &mut = *writer.allocateManagedBuffer(numElements); + ScalarField &nut = *writer.allocateManagedBuffer(numElements); + ScalarField &lmix = *writer.allocateManagedBuffer(numElements); + ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &Dt = *writer.allocateManagedBuffer(numElements); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + for (int i = 0; i < numComponents; ++i) + moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + for (int i = 0; i < numComponents; ++i) + massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + // write volume values to .vtu and .csv + std::ofstream volVarsFile("volVarsData.csv", std::ios_base::out); + asImp_().writeVolVarsHeader(volVarsFile); + volVarsFile << std::endl; + + FVElementGeometry fvGeometry; + ElementBoundaryTypes elemBcTypes; + VolumeVariables volVars; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int idx = this->elementMapper().index(element); + rank[idx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + elemBcTypes.update(this->problem_(), element, fvGeometry); + + int numLocalVerts = element.template subEntities(dim); + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pN[vIdxGlobal] = volVars.pressure(); + delP[vIdxGlobal] = volVars.pressure() - 1e5; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + { + (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); + (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); + Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); + Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); + } + rho[vIdxGlobal] = volVars.density(); + mu[vIdxGlobal] = volVars.dynamicViscosity(); + D[vIdxGlobal] = volVars.diffusionCoeff(transportCompIdx); + velocity[vIdxGlobal] = volVars.velocity(); + + asImp_().writeVolVarsData(volVarsFile, volVars); + volVarsFile << std::endl; + } + } + writer.attachVertexData(pN, "P"); + writer.attachVertexData(delP, "delP"); + + for (int j = 0; j < numComponents; ++j) + { + std::ostringstream moleFrac, massFrac; + moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); + + massFrac << "X_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); + } + volVarsFile.close(); + + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(D, "D"); + writer.attachVertexData(velocity, "v", dim); + + // ensure that the actual values are given out + asImp_().updateWallProperties(); + + // write flux values to .vtu and .csv + std::ofstream fluxFile("fluxVarsData.csv", std::ios_base::out); + asImp_().writeFluxVarsHeader(fluxFile); + fluxFile << std::endl; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + unsigned int numFluxVars = 0; + Scalar sumDynamicEddyViscosity = 0.0; + Scalar sumKinematicEddyViscosity = 0.0; + Scalar sumMixingLength = 0.0; + Scalar sumUPlus = 0.0; + Scalar sumYPlus = 0.0; + Scalar sumEddyDiffusivity = 0.0; + + for (const auto& intersection : Dune::intersections(this->gridView_(), element)) + { + int fIdx = intersection.indexInInside(); + + FluxVariables fluxVars(this->problem_(), element, fvGeometry, + fIdx, elemVolVars, false); + + asImp_().writeFluxVarsData(fluxFile, fluxVars); + fluxFile << std::endl; + + sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); + sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); + sumMixingLength += fluxVars.mixingLength(); + sumUPlus += fluxVars.uPlus(); + sumYPlus += fluxVars.yPlusRough(); + sumEddyDiffusivity += fluxVars.eddyDiffusivity(); + numFluxVars += 1; + } + + int eIdxGlobal = this->elementMapper().index(element); + mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; + nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; + lmix[eIdxGlobal] = sumMixingLength / numFluxVars; + uPlus[eIdxGlobal] = sumUPlus / numFluxVars; + yPlus[eIdxGlobal] = sumYPlus / numFluxVars; + Dt[eIdxGlobal] = sumEddyDiffusivity / numFluxVars; + } + fluxFile.close(); + + writer.attachCellData(mut, "mu_t"); + writer.attachCellData(nut, "nu_t"); + writer.attachCellData(lmix, "l_mix"); + writer.attachCellData(uPlus, "u^+"); + writer.attachCellData(yPlus, "y^+"); + writer.attachCellData(Dt, "D_t"); + } + + //! \copydoc ZeroEqModel::writeFluxVarsHeader + void writeFluxVarsHeader(std::ofstream &stream) + { + ParentType::writeFluxVarsHeader(stream); + stream << "," << "eddyDiffusivity"; + } + + //! \copydoc ZeroEqModel::writeFluxVarsData + void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) + { + ParentType::writeFluxVarsData(stream, fluxVars); + stream << "," << fluxVars.eddyDiffusivity(); + } + + /*! + * \name Wall properties + */ + // \{ + + //! \copydoc ZeroEqModel::resetWallProperties + void resetWallProperties() + { + ParentType::resetWallProperties(); + + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + for (int posIdx = 0; posIdx < intervals; ++posIdx) + { + this->wall[wallIdx].maxMassFraction[posIdx] = 0.0; + this->wall[wallIdx].maxMoleFraction[posIdx] = 0.0; + } + } + + //! \copydoc ZeroEqModel::calculateMaxFluxVars + void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition &globalPos) + { + ParentType::calculateMaxFluxVars(fluxVars, globalPos); + + int posIdx = this->getPosIdx(globalPos); + int wallIdx = this->getWallIdx(globalPos, posIdx); + // mass fraction + if (this->wall[wallIdx].maxMassFraction[posIdx] < fluxVars.massFraction(transportCompIdx)) + for (int wIdx = 0; wIdx < walls; ++wIdx) + this->wall[wIdx].maxMassFraction[posIdx] = fluxVars.massFraction(transportCompIdx); + // mole fraction + if (this->wall[wallIdx].maxMoleFraction[posIdx] < fluxVars.moleFraction(transportCompIdx)) + for (int wIdx = 0; wIdx < walls; ++wIdx) + this->wall[wIdx].maxMoleFraction[posIdx] = fluxVars.moleFraction(transportCompIdx); + } + + //! \copydoc ZeroEqModel::doInterpolationFluxValues + const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) + { + ParentType::doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); + + this->wall[wallIdx].maxMassFraction[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxMassFraction[prevIdx], nextIdx, this->wall[wallIdx].maxMassFraction[nextIdx]); + this->wall[wallIdx].maxMoleFraction[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxMoleFraction[prevIdx], nextIdx, this->wall[wallIdx].maxMoleFraction[nextIdx]); + } + + // \} // wall properties + + /*! + * \brief Returns the name of used the eddy diffusivity model. + */ + const char *eddyDiffusivityModelName() const + { + switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyDiffusivityModel)) + { + case EddyDiffusivityIndices::noEddyDiffusivityModel: // 0 + return "noEddyDiffusivityModel"; + break; + case EddyDiffusivityIndices::reynoldsAnalogy: // 1 + return "reynoldsAnalogy"; + break; + case EddyDiffusivityIndices::modifiedVanDriest: // 2 + return "modifiedVanDriest"; + break; + case EddyDiffusivityIndices::deissler: // 3 + return "deissler"; + break; + case EddyDiffusivityIndices::meier: // 4 + return "meier"; + break; + case EddyDiffusivityIndices::exponential: // 5 + return "exponential"; + break; + default: + DUNE_THROW(Dune::NotImplemented, "This eddy diffusivity model is not implemented."); + } + } + +private: + Scalar eps_; + const int flowNormal_; + const int wallNormal_; + + Implementation &asImp_() + { return *static_cast<Implementation*>(this); } + const Implementation &asImp_() const + { return *static_cast<const Implementation*>(this); } +}; + +} + +#include "propertydefaults.hh" + +#endif // DUMUX_ZEROEQNC_MODEL_HH diff --git a/dumux/freeflow/zeroeqnc/properties.hh b/dumux/freeflow/zeroeqnc/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..7ff3ddefa6a0a65bb8358d85a0a05ea52f4ea314 --- /dev/null +++ b/dumux/freeflow/zeroeqnc/properties.hh @@ -0,0 +1,56 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqncModel + * + * \file + * + * \brief Defines the properties required for the compositional ZeroEq box model. + */ + +#ifndef DUMUX_ZEROEQNC_PROPERTIES_HH +#define DUMUX_ZEROEQNC_PROPERTIES_HH + +#include <dumux/freeflow/stokesnc/properties.hh> +#include <dumux/freeflow/zeroeq/properties.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the ZeroEqnc Problem +NEW_TYPE_TAG(BoxZeroEqnc, INHERITS_FROM(BoxZeroEq, BoxStokesnc)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// + +NEW_PROP_TAG(ZeroEqEddyDiffusivityModel); //!< Returns which Eddy Diffusivity Model is used +NEW_PROP_TAG(ZeroEqTurbulentSchmidtNumber); //!< Returns the used turbulent Schmidt number (Reynolds analogy) +} +} + +#endif // DUMUX_ZEROEQNC_PROPERTIES_HH diff --git a/dumux/freeflow/zeroeqnc/propertydefaults.hh b/dumux/freeflow/zeroeqnc/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..5e2fc6f91b2746edbb3501dd57ffbd8a1c472e2a --- /dev/null +++ b/dumux/freeflow/zeroeqnc/propertydefaults.hh @@ -0,0 +1,79 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqncModel + * + * \file + * + * \brief Defines default properties for the compositional ZeroEq box model. + */ + +#ifndef DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH +#define DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH + +#include <dumux/freeflow/stokesnc/fluxvariables.hh> +#include <dumux/freeflow/stokesnc/model.hh> +#include <dumux/freeflow/stokesnc/volumevariables.hh> +#include "fluxvariables.hh" +#include "model.hh" + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +// INHERITED +//! Set the Model property +SET_TYPE_PROP(BoxZeroEqnc, Model, ZeroEqncModel<TypeTag>); + +//! Set the FluxVariables property +SET_TYPE_PROP(BoxZeroEqnc, FluxVariables, ZeroEqncFluxVariables<TypeTag>); + +//! Set the indices used by the ZeroEqnc model +SET_TYPE_PROP(BoxZeroEqnc, Indices, ZeroEqncCommonIndices<TypeTag>); + +//! Set calculation to Navier-Stokes +SET_BOOL_PROP(BoxZeroEqnc, EnableNavierStokes, true); + +//! Don't use mole fractions +SET_BOOL_PROP(BoxZeroEqnc, UseMoles, false); + +// NEW PROPERTIES +//! Set the Eddy Diffusivity Model +SET_INT_PROP(BoxZeroEqnc, ZeroEqEddyDiffusivityModel, 1); + +//! Set the turbulent Schmidt number \f$[-]\f$ (Reynolds analogy) +SET_SCALAR_PROP(BoxZeroEqnc, ZeroEqTurbulentSchmidtNumber, 1.0); + +//! Set the BaseStokesModel to StokesncModel +SET_TYPE_PROP(BoxZeroEqnc, BaseStokesModel, StokesncModel<TypeTag>); + +//! Set the BaseStokesFluxVariables to StokesncniFluxVariables +SET_TYPE_PROP(BoxZeroEqnc, BaseStokesFluxVariables, StokesncFluxVariables<TypeTag>); + +} +} + +#endif // DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH diff --git a/dumux/freeflow/zeroeqnc/zeroeqncfluxvariables.hh b/dumux/freeflow/zeroeqnc/zeroeqncfluxvariables.hh index c62f99a1b7b6b8bbd8f95b00602ac4e87db35b4c..1ddd1dd62eed7ed723dfd06fb22790f32967af29 100644 --- a/dumux/freeflow/zeroeqnc/zeroeqncfluxvariables.hh +++ b/dumux/freeflow/zeroeqnc/zeroeqncfluxvariables.hh @@ -1,258 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * the fluxes of the compositional ZeroEq model over a face of a finite volume. - * - * This means the methods to calculate the eddy diffusivity. - */ -#ifndef DUMUX_ZEROEQNC_FLUX_VARIABLES_HH -#define DUMUX_ZEROEQNC_FLUX_VARIABLES_HH +#ifndef DUMUX_ZEROEQNC_FLUX_VARIABLES_HH_OLD +#define DUMUX_ZEROEQNC_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/common/valgrind.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeqnc/fluxvariables.hh instead -#include <dumux/freeflow/zeroeq/zeroeqfluxvariables.hh> -#include <dumux/freeflow/zeroeqnc/zeroeqncindices.hh> -#include <dumux/freeflow/zeroeqnc/zeroeqncproperties.hh> +#include <dumux/freeflow/zeroeqnc/fluxvariables.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqncModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains data which is required to - * calculate the component fluxes over a face of a finite - * volume for a compositional ZeroEq model. - * - * This means the methods to calculate the eddy diffusivity. - */ -template <class TypeTag> -class ZeroEqncFluxVariables : public ZeroEqFluxVariables<TypeTag> -{ - typedef ZeroEqFluxVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { dim = GridView::dimension, - phaseIdx = Indices::phaseIdx, - transportCompIdx = Indices::transportCompIdx}; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - -public: - ZeroEqncFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) - , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - , eddyDiffusivityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyDiffusivityModel)) - { - globalPos_ = this->face().ipGlobal; - posIdx_ = problem.model().getPosIdx(globalPos_); - wallIdx_ = problem.model().getWallIdx(globalPos_, posIdx_); - velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; - velGradWall_ = problem.model().wall[wallIdx_].wallVelGrad[posIdx_]; - yPlusReal_ = this->distanceToWallReal() * this->frictionVelocityWall() - / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; - - eddyDiffusivity_ = 0.0; - mixingLengthDiffusivity_ = 0.0; - - DimVector tmp(0.0); - densityGrad_ = 0.0; - - // calculate gradients and secondary variables at IPs - for (int idx = 0; idx < this->fvGeometry_.numScv; idx++) - { - tmp = this->face().grad[idx]; - tmp *= elemVolVars[idx].density(); - densityGrad_ += tmp; - } - - // Richardson number - // Schlichting, Boundary Layer Theory, 1997, p472 - Scalar gravity = 0.0; - if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity)) - gravity = problem.gravity()[wallNormal_]; - else - gravity = 9.81; - richardsonNumber_ = -gravity / this->density() - * densityGrad()[wallNormal_] / (velGradWall_ * velGradWall_); - - // calculation of an eddy diffusivity only makes sense with Navier-Stokes equation - if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) - calculateEddyDiffusivity_(problem, element, elemVolVars); - }; - -protected: - /*! - * \brief This functions calculates the eddy diffusivity. - * - * The eddy diffusivity is added to the diffusivity in stokesnclocalresidual.hh - * at each scv face. - */ - void calculateEddyDiffusivity_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - // no eddy diffusivity model - if (eddyDiffusivityModel_ == EddyDiffusivityIndices::noEddyDiffusivityModel) - return; - - // Reynolds analogy - // Bird, Stewart and Lightfoot, Transport Phenomena, 2007, p 657 - else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::reynoldsAnalogy) - { - eddyDiffusivity_ = this->kinematicEddyViscosity() - / GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, TurbulentSchmidtNumber); - } - - // modified Van-Driest - // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 - else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::modifiedVanDriest) - { - Scalar aPlus = 26.0; - Scalar bPlus = 0.26; - // eddy diffusivity can only be calculated correctly for non-zero distance to walls - mixingLengthDiffusivity_ = 0.0; - if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) - mixingLengthDiffusivity_ = this->karmanConstant() * this->distanceToWallReal() - * (1.0 - std::exp(-yPlusReal_ / aPlus)) - / std::sqrt(1.0 - std::exp(-bPlus * yPlusReal_)); - - eddyDiffusivity_ = mixingLengthDiffusivity_ * mixingLengthDiffusivity_ * std::abs(velGrad_); - } - - // Deissler near wall law - // Deissler, R. G. "Analysis of Turbulent Heat Transfer, Mass Transfer, and Friction in Smooth Tubes at High Prandtl and Schmidt Numbers" - // NACA Report, 1954, 1210, 69-82 - else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::deissler) - { - const Scalar deisslerConstant = 0.124; - const Scalar beta = this->density() * deisslerConstant * deisslerConstant - * std::abs(this->velocity()[flowNormal_]) - * this->distanceToWallReal(); - eddyDiffusivity_ = beta * (1.0 - std::exp(-beta / this->dynamicViscosity())); - eddyDiffusivity_ /= this->density(); - } - - // Meier and Rotta - // Cebeci, Analysis of turbulent boundary layer, 1974, p 251f - else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::meier) - { - // Sc_t at flow = 0.86 - // Sc_t in wall = 1.34 - Scalar kappaMeier = this->karmanConstant() / std::sqrt(0.86); - Scalar aPlusMeier = std::sqrt(1.34) / std::sqrt(0.86) * 26.0; - mixingLengthDiffusivity_ = 0.0; - if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) - mixingLengthDiffusivity_ = kappaMeier * this->distanceToWallReal() - * (1.0 - std::exp(- yPlusReal_ / aPlusMeier)); - eddyDiffusivity_ = mixingLengthDiffusivity_ * mixingLengthDiffusivity_ * std::abs(velGrad_); - } - - // exponential (after Mamayev) - // Lehfeldt, Ein algebraisches Turbulenzmodell für Ästuare, 1991, p 65 - else if (eddyDiffusivityModel_ == EddyDiffusivityIndices::exponential) - { - Scalar m = 0.8; // 18.0=Perrels, 0.8=Mamayev - if (velGradWall_ == 0) // means incredible high Ri - eddyDiffusivity_ = 0.0; - else - eddyDiffusivity_ = std::exp(-m * richardsonNumber()) - * this->kinematicEddyViscosity(); - } - - else - { - DUNE_THROW(Dune::NotImplemented, "This eddy diffusivity model is not implemented."); - } - - Valgrind::CheckDefined(eddyDiffusivity_); - } - - -public: - /*! - * \brief Returns the eddy diffusivity \f$\mathrm{[m^2/s]}\f$. - * - * The eddy diffusivity does not depend on the component - */ - const Scalar eddyDiffusivity() const - { return eddyDiffusivity_; } - - /*! - * \brief Returns the density gradient \f$\mathrm{[kg/m^4]}\f$. - */ - const DimVector densityGrad() const - { return densityGrad_; } - - /*! - * \brief Returns the richardson number \f$\mathrm{[-]}\f$. - */ - const Scalar richardsonNumber() const - { return richardsonNumber_; } - - /*! - * \brief Returns the Schmidt number (molecular) \f$\mathrm{[-]}\f$. - */ - const Scalar schmidtNumber() const - { return this->kinematicViscosity() / this->diffusionCoeff(transportCompIdx); } - - /*! - * \brief Returns the turbulent Schmidt number \f$\mathrm{[-]}\f$. - */ - const Scalar turbulentSchmidtNumber() const - { return this->kinematicEddyViscosity() / eddyDiffusivity(); } - -private: - const int flowNormal_; - const int wallNormal_; - const int eddyDiffusivityModel_; - int posIdx_; - int wallIdx_; - - Scalar velGrad_; - Scalar velGradWall_; - Scalar yPlusReal_; - DimVector globalPos_; - - Scalar eddyDiffusivity_; - Scalar mixingLengthDiffusivity_; - Scalar richardsonNumber_; - DimVector densityGrad_; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQNC_FLUX_VARIABLES_HH +#endif diff --git a/dumux/freeflow/zeroeqnc/zeroeqncindices.hh b/dumux/freeflow/zeroeqnc/zeroeqncindices.hh index 164fec7f4cfa816e84596f0ff084659bb6bbeadc..455330b93fd3040e4b4abc238bec282629b0d461 100644 --- a/dumux/freeflow/zeroeqnc/zeroeqncindices.hh +++ b/dumux/freeflow/zeroeqnc/zeroeqncindices.hh @@ -1,64 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_ZEROEQNC_INDICES_HH_OLD +#define DUMUX_ZEROEQNC_INDICES_HH_OLD -/*! - * \file - * \brief Defines the indices required for the compositional ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQNC_INDICES_HH -#define DUMUX_ZEROEQNC_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqnc/indices.hh instead -#include <dumux/freeflow/stokesnc/stokesncindices.hh> -#include <dumux/freeflow/zeroeq/zeroeqindices.hh> +#include <dumux/freeflow/zeroeqnc/indices.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqncModel - * \brief The indices for the eddy diffusivity model. - */ -struct EddyDiffusivityIndices -{ - // Eddy Diffusivity Model Indices - static const int noEddyDiffusivityModel = 0; - static const int reynoldsAnalogy = 1; - static const int modifiedVanDriest = 2; - static const int deissler = 3; - static const int meier = 4; - static const int exponential = 5; -}; - -/*! - * \ingroup BoxZeroEqncModel - * \ingroup ImplicitIndices - * \brief The common indices for the isothermal compositional ZeroEq box model. - * - * \tparam PVOffset The first index in a primary variable vector. - */ -template <class TypeTag, int PVOffset = 0> -struct ZeroEqncCommonIndices : public StokesncCommonIndices<TypeTag, PVOffset> -{ - static const int scvDataPrecision = 5; - static const int scvDataWidth = scvDataPrecision + 10; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQNC_INDICES_HH +#endif diff --git a/dumux/freeflow/zeroeqnc/zeroeqncmodel.hh b/dumux/freeflow/zeroeqnc/zeroeqncmodel.hh index 5b3daf00db0fd49f7b7c9d9ab4120239552fef9b..ad6949811722a776fed5187915f0d26d05cdc302 100644 --- a/dumux/freeflow/zeroeqnc/zeroeqncmodel.hh +++ b/dumux/freeflow/zeroeqnc/zeroeqncmodel.hh @@ -1,390 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Base class for all models which use the compositional ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQNC_MODEL_HH -#define DUMUX_ZEROEQNC_MODEL_HH +#ifndef DUMUX_ZEROEQNC_MODEL_HH_OLD +#define DUMUX_ZEROEQNC_MODEL_HH_OLD -#include "zeroeqncindices.hh" -#include "zeroeqncproperties.hh" -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqmodel.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeqnc/model.hh instead -namespace Dumux -{ -/*! - * \ingroup BoxZeroEqncModel - * \brief Adaption of the box scheme to the compositional ZeroEq model. - * - * This model implements an single-phase isothermal compositional free flow - * solving the mass and the momentum balance. For the momentum balance - * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation - * (algebraic) turbulence model is used. - * - * Mass balance: - * \f[ - * \frac{\partial \varrho_\textrm{g}}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) - * - q_\textrm{g} = 0 - * \f] - * - * Momentum Balance: - * \f[ - * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} - * + \text{div} \left( - * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} - * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] - * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} - * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) - * \right) - * + \left(p_\textrm{g} {\bf {I}} \right) - * - \varrho_\textrm{g} {\bf g} = 0 - * \f] - * - * Component mass balance equations: - * \f[ - * \frac{\partial \left(\varrho_\textrm{g} X_\textrm{g}^\kappa\right)}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} X_\textrm{g}^\kappa - * - \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] - * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x_\textrm{g}^\kappa \right) - * - q_\textrm{g}^\kappa = 0 - * \f] - * Please note that, even though it is n-component model, the diffusive - * fluxes are still calculated with binary diffusion. - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class ZeroEqncModel : public ZeroEqModel<TypeTag> -{ - typedef ZeroEqModel<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; +#include <dumux/freeflow/zeroeqnc/model.hh> - enum { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), - walls = (GET_PROP_VALUE(TypeTag, BBoxMinIsWall) ? 1 : 0) - + (GET_PROP_VALUE(TypeTag, BBoxMaxIsWall) ? 1 : 0) - }; - enum { transportCompIdx = Indices::transportCompIdx, - numComponents = Indices::numComponents }; - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - - -public: - ZeroEqncModel() - : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - { - eps_ = 1e-6; - - // check whether sand grain roughness may be used - if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 - || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) - { - Dune::dwarn << "warning: surface roughness will not be used for eddy diffusivity models." << std::endl; - } - } - - //! \copydoc ImplicitModel::addOutputVtkFields - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - unsigned numElements = this->gridView_().size(0); - ScalarField &pN = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField *moleFraction[numComponents]; - ScalarField *massFraction[numComponents]; - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - ScalarField &D = *writer.allocateManagedBuffer(numVertices); - ScalarField &mut = *writer.allocateManagedBuffer(numElements); - ScalarField &nut = *writer.allocateManagedBuffer(numElements); - ScalarField &lmix = *writer.allocateManagedBuffer(numElements); - ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &Dt = *writer.allocateManagedBuffer(numElements); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - for (int i = 0; i < numComponents; ++i) - moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - for (int i = 0; i < numComponents; ++i) - massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - // write volume values to .vtu and .csv - std::ofstream volVarsFile("volVarsData.csv", std::ios_base::out); - asImp_().writeVolVarsHeader(volVarsFile); - volVarsFile << std::endl; - - FVElementGeometry fvGeometry; - ElementBoundaryTypes elemBcTypes; - VolumeVariables volVars; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int idx = this->elementMapper().index(element); - rank[idx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - elemBcTypes.update(this->problem_(), element, fvGeometry); - - int numLocalVerts = element.template subEntities(dim); - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pN[vIdxGlobal] = volVars.pressure(); - delP[vIdxGlobal] = volVars.pressure() - 1e5; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - { - (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); - (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); - Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); - Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); - } - rho[vIdxGlobal] = volVars.density(); - mu[vIdxGlobal] = volVars.dynamicViscosity(); - D[vIdxGlobal] = volVars.diffusionCoeff(transportCompIdx); - velocity[vIdxGlobal] = volVars.velocity(); - - asImp_().writeVolVarsData(volVarsFile, volVars); - volVarsFile << std::endl; - } - } - writer.attachVertexData(pN, "P"); - writer.attachVertexData(delP, "delP"); - - for (int j = 0; j < numComponents; ++j) - { - std::ostringstream moleFrac, massFrac; - moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); - - massFrac << "X_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); - } - volVarsFile.close(); - - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(D, "D"); - writer.attachVertexData(velocity, "v", dim); - - // ensure that the actual values are given out - asImp_().updateWallProperties(); - - // write flux values to .vtu and .csv - std::ofstream fluxFile("fluxVarsData.csv", std::ios_base::out); - asImp_().writeFluxVarsHeader(fluxFile); - fluxFile << std::endl; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - unsigned int numFluxVars = 0; - Scalar sumDynamicEddyViscosity = 0.0; - Scalar sumKinematicEddyViscosity = 0.0; - Scalar sumMixingLength = 0.0; - Scalar sumUPlus = 0.0; - Scalar sumYPlus = 0.0; - Scalar sumEddyDiffusivity = 0.0; - - for (const auto& intersection : Dune::intersections(this->gridView_(), element)) - { - int fIdx = intersection.indexInInside(); - - FluxVariables fluxVars(this->problem_(), element, fvGeometry, - fIdx, elemVolVars, false); - - asImp_().writeFluxVarsData(fluxFile, fluxVars); - fluxFile << std::endl; - - sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); - sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); - sumMixingLength += fluxVars.mixingLength(); - sumUPlus += fluxVars.uPlus(); - sumYPlus += fluxVars.yPlusRough(); - sumEddyDiffusivity += fluxVars.eddyDiffusivity(); - numFluxVars += 1; - } - - int eIdxGlobal = this->elementMapper().index(element); - mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; - nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; - lmix[eIdxGlobal] = sumMixingLength / numFluxVars; - uPlus[eIdxGlobal] = sumUPlus / numFluxVars; - yPlus[eIdxGlobal] = sumYPlus / numFluxVars; - Dt[eIdxGlobal] = sumEddyDiffusivity / numFluxVars; - } - fluxFile.close(); - - writer.attachCellData(mut, "mu_t"); - writer.attachCellData(nut, "nu_t"); - writer.attachCellData(lmix, "l_mix"); - writer.attachCellData(uPlus, "u^+"); - writer.attachCellData(yPlus, "y^+"); - writer.attachCellData(Dt, "D_t"); - } - - //! \copydoc ZeroEqModel::writeFluxVarsHeader - void writeFluxVarsHeader(std::ofstream &stream) - { - ParentType::writeFluxVarsHeader(stream); - stream << "," << "eddyDiffusivity"; - } - - //! \copydoc ZeroEqModel::writeFluxVarsData - void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) - { - ParentType::writeFluxVarsData(stream, fluxVars); - stream << "," << fluxVars.eddyDiffusivity(); - } - - /*! - * \name Wall properties - */ - // \{ - - //! \copydoc ZeroEqModel::resetWallProperties - void resetWallProperties() - { - ParentType::resetWallProperties(); - - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - for (int posIdx = 0; posIdx < intervals; ++posIdx) - { - this->wall[wallIdx].maxMassFraction[posIdx] = 0.0; - this->wall[wallIdx].maxMoleFraction[posIdx] = 0.0; - } - } - - //! \copydoc ZeroEqModel::calculateMaxFluxVars - void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition &globalPos) - { - ParentType::calculateMaxFluxVars(fluxVars, globalPos); - - int posIdx = this->getPosIdx(globalPos); - int wallIdx = this->getWallIdx(globalPos, posIdx); - // mass fraction - if (this->wall[wallIdx].maxMassFraction[posIdx] < fluxVars.massFraction(transportCompIdx)) - for (int wIdx = 0; wIdx < walls; ++wIdx) - this->wall[wIdx].maxMassFraction[posIdx] = fluxVars.massFraction(transportCompIdx); - // mole fraction - if (this->wall[wallIdx].maxMoleFraction[posIdx] < fluxVars.moleFraction(transportCompIdx)) - for (int wIdx = 0; wIdx < walls; ++wIdx) - this->wall[wIdx].maxMoleFraction[posIdx] = fluxVars.moleFraction(transportCompIdx); - } - - //! \copydoc ZeroEqModel::doInterpolationFluxValues - const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) - { - ParentType::doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); - - this->wall[wallIdx].maxMassFraction[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxMassFraction[prevIdx], nextIdx, this->wall[wallIdx].maxMassFraction[nextIdx]); - this->wall[wallIdx].maxMoleFraction[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxMoleFraction[prevIdx], nextIdx, this->wall[wallIdx].maxMoleFraction[nextIdx]); - } - - // \} // wall properties - - /*! - * \brief Returns the name of used the eddy diffusivity model. - */ - const char *eddyDiffusivityModelName() const - { - switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyDiffusivityModel)) - { - case EddyDiffusivityIndices::noEddyDiffusivityModel: // 0 - return "noEddyDiffusivityModel"; - break; - case EddyDiffusivityIndices::reynoldsAnalogy: // 1 - return "reynoldsAnalogy"; - break; - case EddyDiffusivityIndices::modifiedVanDriest: // 2 - return "modifiedVanDriest"; - break; - case EddyDiffusivityIndices::deissler: // 3 - return "deissler"; - break; - case EddyDiffusivityIndices::meier: // 4 - return "meier"; - break; - case EddyDiffusivityIndices::exponential: // 5 - return "exponential"; - break; - default: - DUNE_THROW(Dune::NotImplemented, "This eddy diffusivity model is not implemented."); - } - } - -private: - Scalar eps_; - const int flowNormal_; - const int wallNormal_; - - Implementation &asImp_() - { return *static_cast<Implementation*>(this); } - const Implementation &asImp_() const - { return *static_cast<const Implementation*>(this); } -}; - -} - -#include "zeroeqncpropertydefaults.hh" - -#endif // DUMUX_ZEROEQNC_MODEL_HH +#endif diff --git a/dumux/freeflow/zeroeqnc/zeroeqncproperties.hh b/dumux/freeflow/zeroeqnc/zeroeqncproperties.hh index b31e3a3bcb94238392c446763e268ce70ab5af99..8a9c3aeee2a991b157d4f3f295caf848c9810d2c 100644 --- a/dumux/freeflow/zeroeqnc/zeroeqncproperties.hh +++ b/dumux/freeflow/zeroeqnc/zeroeqncproperties.hh @@ -1,56 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqncModel - * - * \file - * - * \brief Defines the properties required for the compositional ZeroEq box model. - */ +#ifndef DUMUX_ZEROEQNC_PROPERTIES_HH_OLD +#define DUMUX_ZEROEQNC_PROPERTIES_HH_OLD -#ifndef DUMUX_ZEROEQNC_PROPERTIES_HH -#define DUMUX_ZEROEQNC_PROPERTIES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqnc/properties.hh instead -#include <dumux/freeflow/stokesnc/stokesncproperties.hh> -#include <dumux/freeflow/zeroeq/zeroeqproperties.hh> +#include <dumux/freeflow/zeroeqnc/properties.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tag for the ZeroEqnc Problem -NEW_TYPE_TAG(BoxZeroEqnc, INHERITS_FROM(BoxZeroEq, BoxStokesnc)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// - -NEW_PROP_TAG(ZeroEqEddyDiffusivityModel); //!< Returns which Eddy Diffusivity Model is used -NEW_PROP_TAG(ZeroEqTurbulentSchmidtNumber); //!< Returns the used turbulent Schmidt number (Reynolds analogy) -} -} - -#endif // DUMUX_ZEROEQNC_PROPERTIES_HH +#endif diff --git a/dumux/freeflow/zeroeqnc/zeroeqncpropertydefaults.hh b/dumux/freeflow/zeroeqnc/zeroeqncpropertydefaults.hh index b7a520f0a61be89742b29d608bba63e63a54ab6e..84843cb0aaff314b523e59473c6ea64170882b38 100644 --- a/dumux/freeflow/zeroeqnc/zeroeqncpropertydefaults.hh +++ b/dumux/freeflow/zeroeqnc/zeroeqncpropertydefaults.hh @@ -1,79 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqncModel - * - * \file - * - * \brief Defines default properties for the compositional ZeroEq box model. - */ +#ifndef DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH_OLD -#ifndef DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH -#define DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqnc/propertydefaults.hh instead -#include <dumux/freeflow/stokesnc/stokesncfluxvariables.hh> -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> -#include <dumux/freeflow/stokesnc/stokesncvolumevariables.hh> -#include "zeroeqncfluxvariables.hh" -#include "zeroeqncmodel.hh" +#include <dumux/freeflow/zeroeqnc/propertydefaults.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -// INHERITED -//! Set the Model property -SET_TYPE_PROP(BoxZeroEqnc, Model, ZeroEqncModel<TypeTag>); - -//! Set the FluxVariables property -SET_TYPE_PROP(BoxZeroEqnc, FluxVariables, ZeroEqncFluxVariables<TypeTag>); - -//! Set the indices used by the ZeroEqnc model -SET_TYPE_PROP(BoxZeroEqnc, Indices, ZeroEqncCommonIndices<TypeTag>); - -//! Set calculation to Navier-Stokes -SET_BOOL_PROP(BoxZeroEqnc, EnableNavierStokes, true); - -//! Don't use mole fractions -SET_BOOL_PROP(BoxZeroEqnc, UseMoles, false); - -// NEW PROPERTIES -//! Set the Eddy Diffusivity Model -SET_INT_PROP(BoxZeroEqnc, ZeroEqEddyDiffusivityModel, 1); - -//! Set the turbulent Schmidt number \f$[-]\f$ (Reynolds analogy) -SET_SCALAR_PROP(BoxZeroEqnc, ZeroEqTurbulentSchmidtNumber, 1.0); - -//! Set the BaseStokesModel to StokesncModel -SET_TYPE_PROP(BoxZeroEqnc, BaseStokesModel, StokesncModel<TypeTag>); - -//! Set the BaseStokesFluxVariables to StokesncniFluxVariables -SET_TYPE_PROP(BoxZeroEqnc, BaseStokesFluxVariables, StokesncFluxVariables<TypeTag>); - -} -} - -#endif // DUMUX_ZEROEQNC_PROPERTY_DEFAULTS_HH +#endif diff --git a/dumux/freeflow/zeroeqncni/fluxvariables.hh b/dumux/freeflow/zeroeqncni/fluxvariables.hh new file mode 100644 index 0000000000000000000000000000000000000000..1fbacd02b173cd90e962adfb995a350f9250b0ff --- /dev/null +++ b/dumux/freeflow/zeroeqncni/fluxvariables.hh @@ -0,0 +1,222 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief This file contains the data which is required to calculate + * the fluxes of the non-isothermal compositional ZeroEq model over + * a face of a finite volume. + * + * This means the methods to calculate the eddy conductivity. + */ +#ifndef DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH +#define DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH + +#include <dumux/common/math.hh> +#include <dumux/common/valgrind.hh> + +#include <dumux/freeflow/zeroeqnc/fluxvariables.hh> +#include <dumux/freeflow/zeroeqncni/indices.hh> +#include <dumux/freeflow/zeroeqncni/properties.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqncniModel + * \ingroup ImplicitFluxVariables + * \brief This template class contains data which is required to + * calculate the component fluxes over a face of a finite + * volume for a non-isothermal compositional ZeroEq model. + * + * This means the methods to calculate the eddy conductivity. + */ +template <class TypeTag> +class ZeroEqncniFluxVariables : public ZeroEqncFluxVariables<TypeTag> +{ + typedef ZeroEqncFluxVariables<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { dim = GridView::dimension, + phaseIdx = Indices::phaseIdx, + transportCompIdx = Indices::transportCompIdx}; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef Dune::FieldVector<Scalar, dim> DimVector; + + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + +public: + ZeroEqncniFluxVariables(const Problem &problem, + const Element &element, + const FVElementGeometry &fvGeometry, + const int fIdx, + const ElementVolumeVariables &elemVolVars, + const bool onBoundary = false) + : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) + , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + , eddyConductivityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyConductivityModel)) + { + globalPos_ = this->face().ipGlobal; + posIdx_ = problem.model().getPosIdx(globalPos_); + wallIdx_ = problem.model().getWallIdx(globalPos_, posIdx_); + velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; + velGradWall_ = problem.model().wall[wallIdx_].wallVelGrad[posIdx_]; + yPlusReal_ = this->distanceToWallReal() * this->frictionVelocityWall() + / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; + + temperatureEddyConductivity_ = 0.0; + mixingLengthConductivity_ = 0.0; + + // calculation of an eddy conductivity only makes sense with Navier-Stokes equation + if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) + calculateEddyConductivity_(problem, element, elemVolVars); + }; + +protected: + /*! + * \brief This functions calculates the eddy conductivity. + * + * The eddy conductivity is added to the conductivity in stokesncnilocalresidual.hh + * at each scv face. + */ + void calculateEddyConductivity_(const Problem &problem, + const Element &element, + const ElementVolumeVariables &elemVolVars) + { + // IMPORTANT: + // the temperatureEddyConductivity_ a_t [m^2/s] is converted to + // thermalEddyConductivity \lambda_t [W/(m K)] by the convenience function + + // no eddy conductivity model + if (eddyConductivityModel_ == EddyConductivityIndices::noEddyConductivityModel) + return; + + // Reynolds analogy + // Bird, Stewart and Lightfoot, Transport Phenomena, 2007, p 657 + else if (eddyConductivityModel_ == EddyConductivityIndices::reynoldsAnalogy) + { + temperatureEddyConductivity_ = this->kinematicEddyViscosity() + / GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, TurbulentPrandtlNumber); + } + + // modified Van-Driest + // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 + else if (eddyConductivityModel_ == EddyConductivityIndices::modifiedVanDriest) + { + Scalar aPlus = 26.0; + Scalar bPlus = 0.26; + // eddy conductivity can only be calculated correctly for non-zero distance to walls + mixingLengthConductivity_ = 0.0; + if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) + mixingLengthConductivity_ = this->karmanConstant() * this->distanceToWallReal() + * (1.0 - std::exp(-yPlusReal_ / aPlus)) + / std::sqrt(1.0 - std::exp(-bPlus * yPlusReal_)); + + temperatureEddyConductivity_ = mixingLengthConductivity_ * mixingLengthConductivity_ + * std::abs(velGrad_); + } + + // Deissler near wall law + // Deissler, R. G. "Analysis of Turbulent Heat Transfer, Mass Transfer, and Friction in Smooth Tubes at High Prandtl and Schmidt Numbers" + // NACA Report, 1954, 1210, 69-82 + else if (eddyConductivityModel_ == EddyConductivityIndices::deissler) + { + const Scalar deisslerConstant = 0.124; + const Scalar beta = this->density() * deisslerConstant * deisslerConstant + * std::abs(this->velocity()[flowNormal_]) + * this->distanceToWallReal(); + temperatureEddyConductivity_ = beta * (1.0 - std::exp(-beta / this->dynamicViscosity())); + temperatureEddyConductivity_ /= this->density(); + } + + // Meier and Rotta + // Cebeci, Analysis of turbulent boundary layer, 1974, p 251f + else if (eddyConductivityModel_ == EddyConductivityIndices::meier) + { + // Pr_t at flow = 0.86 + // Pr_t in wall = 1.34 + Scalar kappaMeier = this->karmanConstant() / std::sqrt(0.86); + Scalar aPlusMeier = std::sqrt(1.34) / std::sqrt(0.86) * 26.0; + mixingLengthConductivity_ = 0.0; + if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) + mixingLengthConductivity_ = kappaMeier * this->distanceToWallReal() + * (1.0 - std::exp(- yPlusReal_ / aPlusMeier)); + temperatureEddyConductivity_ = mixingLengthConductivity_ * mixingLengthConductivity_ * std::abs(velGrad_); + } + + else + { + DUNE_THROW(Dune::NotImplemented, "This eddy conductivity model is not implemented."); + } + + Valgrind::CheckDefined(temperatureEddyConductivity_); + } + + +public: + /*! + * \brief Returns the thermal eddy conductivity \f$\mathrm{[W/(m*K)]}\f$. + */ + const Scalar thermalEddyConductivity() const + { return temperatureEddyConductivity() * this->density() * this->heatCapacity(); } + + /*! + * \brief Returns the temperature eddy conductivity \f$\mathrm{[m^2/s]}\f$. + */ + const Scalar temperatureEddyConductivity() const + { return temperatureEddyConductivity_; } + + /*! + * \brief Returns Prandtl number (molecular) \f$\mathrm{[-]}\f$. + */ + const Scalar prandtlNumber() const + { return this->dynamicViscosity() * this->heatCapacity() / this->thermalConductivity(); } + + /*! + * \brief Returns the turbulent Prandtl number \f$\mathrm{[-]}\f$. + */ + const Scalar turbulentPrandtlNumber() const + { return this->dynamicEddyViscosity() * this->heatCapacity() / thermalEddyConductivity(); } + + +private: + const int flowNormal_; + const int wallNormal_; + const int eddyConductivityModel_; + int posIdx_; + int wallIdx_; + + Scalar velGrad_; + Scalar velGradWall_; + DimVector globalPos_; + Scalar yPlusReal_; + + Scalar temperatureEddyConductivity_; + Scalar mixingLengthConductivity_; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH diff --git a/dumux/freeflow/zeroeqncni/indices.hh b/dumux/freeflow/zeroeqncni/indices.hh new file mode 100644 index 0000000000000000000000000000000000000000..9e86e428dbb15b45a979fab22ce85172bcc82b61 --- /dev/null +++ b/dumux/freeflow/zeroeqncni/indices.hh @@ -0,0 +1,65 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file + * \brief Defines the indices required for the non-isothermal + * compositional ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQNCNI_INDICES_HH +#define DUMUX_ZEROEQNCNI_INDICES_HH + +#include <dumux/freeflow/stokesncni/indices.hh> +#include <dumux/freeflow/zeroeq/indices.hh> +#include <dumux/freeflow/zeroeqnc/indices.hh> + +namespace Dumux +{ + +/*! + * \ingroup BoxZeroEqncniModel + * \brief The indices for the eddy conductivity model. + */ +struct EddyConductivityIndices +{ + // Eddy Conductivity Model Indices + static const int noEddyConductivityModel = 0; + static const int reynoldsAnalogy = 1; + static const int modifiedVanDriest = 2; + static const int deissler = 3; + static const int meier = 4; +}; + +/*! + * \ingroup BoxZeroEqncniModel + * \ingroup ImplicitIndices + * \brief The common indices for the non-isothermal compositional ZeroEq box model. + * + * \tparam PVOffset The first index in a primary variable vector. + */ +template <class TypeTag, int PVOffset = 0> +struct ZeroEqncniCommonIndices : public StokesncniCommonIndices<TypeTag, PVOffset> +{ + static const int scvDataPrecision = 5; + static const int scvDataWidth = scvDataPrecision + 10; +}; + +} // end namespace + +#endif // DUMUX_ZEROEQNCNI_INDICES_HH diff --git a/dumux/freeflow/zeroeqncni/model.hh b/dumux/freeflow/zeroeqncni/model.hh new file mode 100644 index 0000000000000000000000000000000000000000..7cb238c38518328a88cf83c481e017155f9d7003 --- /dev/null +++ b/dumux/freeflow/zeroeqncni/model.hh @@ -0,0 +1,403 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Base class for all models which use the non-isothermal + * compositional ZeroEq box model. + */ +#ifndef DUMUX_ZEROEQNCNI_MODEL_HH +#define DUMUX_ZEROEQNCNI_MODEL_HH + +#include "indices.hh" +#include "properties.hh" +#include <dumux/freeflow/zeroeqnc/model.hh> + + +namespace Dumux +{ +/*! + * \ingroup BoxZeroEqncniModel + * \brief Adaption of the box scheme to the non-isothermal compositional ZeroEq model. + * + * This model implements an single-phase non-isothermal compositional free flow + * solving the mass and the momentum balance. For the momentum balance + * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation + * (algebraic) turbulence model is used. + * + * Mass balance: + * \f[ + * \frac{\partial \varrho_\textrm{g}}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) + * - q_\textrm{g} = 0 + * \f] + * + * Momentum Balance: + * \f[ + * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} + * + \text{div} \left( + * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} + * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] + * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} + * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) + * \right) + * + \left(p_\textrm{g} {\bf {I}} \right) + * - \varrho_\textrm{g} {\bf g} = 0 + * \f] + * + * Component mass balance equations: + * \f[ + * \frac{\partial \left(\varrho_\textrm{g} X_\textrm{g}^\kappa\right)}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} X_\textrm{g}^\kappa + * - \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] + * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x_\textrm{g}^\kappa \right) + * - q_\textrm{g}^\kappa = 0 + * \f] + * + * Energy balance equation: + * \f[ + * \frac{\partial (\varrho_\textrm{g} u_\textrm{g})}{\partial t} + * + \text{div} \left( \varrho_\textrm{g} h_\textrm{g} {\boldsymbol{v}}_\textrm{g} + * - \sum_\kappa \left( h^\kappa_\textrm{g} \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] + * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x^\kappa_\textrm{g} \right) + * - \left[ \lambda_\textrm{g} + \lambda_\textrm{g,t} \right] \textbf{grad}\, T \right) + * - q_\textrm{T} = 0 + * \f] + * Please note that, even though it is n-component model, the diffusive + * fluxes are still calculated with binary diffusion. + * + * This is discretized by a fully-coupled vertex-centered finite volume + * (box) scheme in space and by the implicit Euler method in time. + */ +template<class TypeTag> +class ZeroEqncniModel : public ZeroEqncModel<TypeTag> +{ + typedef ZeroEqncModel<TypeTag> ParentType; + typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), + walls = (GET_PROP_VALUE(TypeTag, BBoxMinIsWall) ? 1 : 0) + + (GET_PROP_VALUE(TypeTag, BBoxMaxIsWall) ? 1 : 0) + }; + enum { transportCompIdx = Indices::transportCompIdx, + numComponents = Indices::numComponents }; + enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; + + typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + + typedef typename GridView::template Codim<0>::Entity Element; + typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; + typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; + typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; + typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; + + +public: + ZeroEqncniModel() + : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) + , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) + { + eps_ = 1e-6; + + // check whether sand grain roughness may be used + if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 + || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) + { + Dune::dwarn << "warning: surface roughness will not be used for eddy conductivity models." << std::endl; + } + } + + //! \copydoc ImplicitModel::addOutputVtkFields + template <class MultiWriter> + void addOutputVtkFields(const SolutionVector &sol, + MultiWriter &writer) + { + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; + typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; + + // create the required scalar fields + unsigned numVertices = this->gridView_().size(dim); + unsigned numElements = this->gridView_().size(0); + ScalarField &pN = *writer.allocateManagedBuffer(numVertices); + ScalarField &delP = *writer.allocateManagedBuffer(numVertices); + ScalarField *moleFraction[numComponents]; + ScalarField *massFraction[numComponents]; + ScalarField &rho = *writer.allocateManagedBuffer(numVertices); + VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); + ScalarField &mu = *writer.allocateManagedBuffer(numVertices); + ScalarField &D = *writer.allocateManagedBuffer(numVertices); + ScalarField &T = *writer.allocateManagedBuffer(numVertices); + ScalarField &lambda = *writer.allocateManagedBuffer(numVertices); + ScalarField &mut = *writer.allocateManagedBuffer(numElements); + ScalarField &nut = *writer.allocateManagedBuffer(numElements); + ScalarField &lmix = *writer.allocateManagedBuffer(numElements); + ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); + ScalarField &Dt = *writer.allocateManagedBuffer(numElements); + ScalarField &lambdat = *writer.allocateManagedBuffer(numElements); + ScalarField &rank = *writer.allocateManagedBuffer(numElements); + for (int i = 0; i < numComponents; ++i) + moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + for (int i = 0; i < numComponents; ++i) + massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); + + // write volume values to .vtu and .csv + std::ofstream volVarsFile("volVarsData.csv", std::ios_base::out); + asImp_().writeVolVarsHeader(volVarsFile); + volVarsFile << std::endl; + + FVElementGeometry fvGeometry; + VolumeVariables volVars; + + for (const auto& element : Dune::elements(this->gridView_())) + { + int idx = this->elementMapper().index(element); + rank[idx] = this->gridView_().comm().rank(); + + fvGeometry.update(this->gridView_(), element); + + int numLocalVerts = element.template subEntities(dim); + for (int i = 0; i < numLocalVerts; ++i) + { + int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); + volVars.update(sol[vIdxGlobal], + this->problem_(), + element, + fvGeometry, + i, + false); + + pN[vIdxGlobal] = volVars.pressure(); + delP[vIdxGlobal] = volVars.pressure() - 1e5; + for (int compIdx = 0; compIdx < numComponents; ++compIdx) + { + (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); + (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); + Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); + Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); + } + rho[vIdxGlobal] = volVars.density(); + mu[vIdxGlobal] = volVars.dynamicViscosity(); + D[vIdxGlobal] = volVars.diffusionCoeff(transportCompIdx); + T[vIdxGlobal] = volVars.temperature(); + velocity[vIdxGlobal] = volVars.velocity(); + + asImp_().writeVolVarsData(volVarsFile, volVars); + volVarsFile << std::endl; + } + } + volVarsFile.close(); + + writer.attachVertexData(pN, "P"); + writer.attachVertexData(delP, "delP"); + + for (int j = 0; j < numComponents; ++j) + { + std::ostringstream moleFrac, massFrac; + moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); + + massFrac << "X_" << FluidSystem::phaseName(phaseIdx) + << "^" << FluidSystem::componentName(j); + writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); + } + + writer.attachVertexData(rho, "rho"); + writer.attachVertexData(mu, "mu"); + writer.attachVertexData(D, "D"); + writer.attachVertexData(lambda, "lambda"); + writer.attachVertexData(T, "temperature"); + writer.attachVertexData(velocity, "v", dim); + + // ensure that the actual values are given out + asImp_().updateWallProperties(); + + // write flux values to .vtu and .csv + std::ofstream fluxFile("fluxVarsData.csv", std::ios_base::out); + asImp_().writeFluxVarsHeader(fluxFile); + fluxFile << std::endl; + + for (const auto& element : Dune::elements(this->gridView_())) + { + fvGeometry.update(this->gridView_(), element); + + ElementVolumeVariables elemVolVars; + elemVolVars.update(this->problem_(), + element, + fvGeometry, + false); + + unsigned int numFluxVars = 0; + Scalar sumDynamicEddyViscosity = 0.0; + Scalar sumKinematicEddyViscosity = 0.0; + Scalar sumMixingLength = 0.0; + Scalar sumUPlus = 0.0; + Scalar sumYPlus = 0.0; + Scalar sumEddyDiffusivity = 0.0; + Scalar sumEddyConducitivity = 0.0; + + for (const auto& intersection : Dune::intersections(this->gridView_(), element)) + { + int fIdx = intersection.indexInInside(); + + FluxVariables fluxVars(this->problem_(), + element, + fvGeometry, + fIdx, + elemVolVars, + false); + + asImp_().writeFluxVarsData(fluxFile, fluxVars); + fluxFile << std::endl; + + sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); + sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); + sumMixingLength += fluxVars.mixingLength(); + sumUPlus += fluxVars.uPlus(); + sumYPlus += fluxVars.yPlusRough(); + sumEddyDiffusivity += fluxVars.eddyDiffusivity(); + sumEddyConducitivity += fluxVars.thermalEddyConductivity(); + numFluxVars += 1; + } + + int eIdxGlobal = this->elementMapper().index(element); + mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; + nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; + lmix[eIdxGlobal] = sumMixingLength / numFluxVars; + uPlus[eIdxGlobal] = sumUPlus / numFluxVars; + yPlus[eIdxGlobal] = sumYPlus / numFluxVars; + Dt[eIdxGlobal] = sumEddyDiffusivity / numFluxVars; + lambdat[eIdxGlobal] = sumEddyConducitivity / numFluxVars; + } + fluxFile.close(); + + writer.attachCellData(mut, "mu_t"); + writer.attachCellData(nut, "nu_t"); + writer.attachCellData(lmix, "l_mix"); + writer.attachCellData(uPlus, "u^+"); + writer.attachCellData(yPlus, "y^+"); + writer.attachCellData(Dt, "D_t"); + writer.attachCellData(lambdat, "lambda_t"); + } + + //! \copydoc ZeroEqModel::writeFluxVarsHeader + void writeFluxVarsHeader(std::ofstream &stream) + { + ParentType::writeFluxVarsHeader(stream); + stream << "," << "EddyConductivity"; + } + + //! \copydoc ZeroEqModel::writeFluxVarsData + void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) + { + ParentType::writeFluxVarsData(stream, fluxVars); + stream << "," << fluxVars.thermalEddyConductivity(); + } + + /*! + * \name Wall properties + */ + // \{ + + + //! \copydoc ZeroEqModel::resetWallProperties + void resetWallProperties() + { + ParentType::resetWallProperties(); + + for (int wallIdx = 0; wallIdx < walls; ++wallIdx) + for (int posIdx = 0; posIdx < intervals; ++posIdx) + { + this->wall[wallIdx].maxTemperature[posIdx] = 0.0; + } + } + + //! \copydoc ZeroEqModel::calculateMaxFluxVars + void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition &globalPos) + { + ParentType::calculateMaxFluxVars(fluxVars, globalPos); + + int posIdx = this->getPosIdx(globalPos); + int wallIdx = this->getWallIdx(globalPos, posIdx); + if (this->wall[wallIdx].maxTemperature[posIdx] < fluxVars.temperature()) + for (int wIdx = 0; wIdx < walls; ++wIdx) + this->wall[wIdx].maxTemperature[posIdx] = fluxVars.temperature(); + } + + //! \copydoc ZeroEqModel::doInterpolationFluxValues + const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) + { + ParentType::doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); + this->wall[wallIdx].maxTemperature[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxTemperature[prevIdx], nextIdx, this->wall[wallIdx].maxTemperature[nextIdx]); + } + + // \} // wall properties + + /*! + * \brief Returns the name of used the eddy conductivity model. + */ + const char *eddyConductivityModelName() const + { + switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyConductivityModel)) + { + case EddyConductivityIndices::noEddyConductivityModel: // 0 + return "noEddyConductivityModel"; + break; + case EddyConductivityIndices::reynoldsAnalogy: // 1 + return "reynoldsAnalogy"; + break; + case EddyConductivityIndices::modifiedVanDriest: // 2 + return "modifiedVanDriest"; + break; + case EddyConductivityIndices::deissler: // 3 + return "deissler"; + break; + case EddyConductivityIndices::meier: // 4 + return "meier"; + break; + default: + DUNE_THROW(Dune::NotImplemented, "This eddy conductivity model is not implemented."); + } + } + +private: + Scalar eps_; + const int flowNormal_; + const int wallNormal_; + + Implementation &asImp_() + { return *static_cast<Implementation*>(this); } + const Implementation &asImp_() const + { return *static_cast<const Implementation*>(this); } +}; + +} + +#include "propertydefaults.hh" + +#endif // DUMUX_ZEROEQNCNI_MODEL_HH diff --git a/dumux/freeflow/zeroeqncni/properties.hh b/dumux/freeflow/zeroeqncni/properties.hh new file mode 100644 index 0000000000000000000000000000000000000000..30dd276fd110ca2d3732e0239a8126ecaade8ac3 --- /dev/null +++ b/dumux/freeflow/zeroeqncni/properties.hh @@ -0,0 +1,57 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqncniModel + * + * \file + * + * \brief Defines the properties required for the + * non-isothermal compositional ZeroEq box model. + */ + +#ifndef DUMUX_ZEROEQNCNI_PROPERTIES_HH +#define DUMUX_ZEROEQNCNI_PROPERTIES_HH + +#include <dumux/freeflow/stokesncni/properties.hh> +#include <dumux/freeflow/zeroeqnc/properties.hh> + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Type tags +////////////////////////////////////////////////////////////////// + +//! The type tag for the ZeroEqncni Problem +NEW_TYPE_TAG(BoxZeroEqncni, INHERITS_FROM(BoxZeroEqnc, BoxStokesncni)); + +////////////////////////////////////////////////////////////////// +// Property tags +////////////////////////////////////////////////////////////////// + +NEW_PROP_TAG(ZeroEqEddyConductivityModel); //!< Returns which Eddy Conductivity Model is used +NEW_PROP_TAG(ZeroEqTurbulentPrandtlNumber); //!< Returns the used turbulent Prandtl number (Reynolds analogy) +} +} + +#endif // DUMUX_ZEROEQNCNI_PROPERTIES_HH diff --git a/dumux/freeflow/zeroeqncni/propertydefaults.hh b/dumux/freeflow/zeroeqncni/propertydefaults.hh new file mode 100644 index 0000000000000000000000000000000000000000..ede282c640374ac7d967e590ccc6349f6748d9c4 --- /dev/null +++ b/dumux/freeflow/zeroeqncni/propertydefaults.hh @@ -0,0 +1,77 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \ingroup Properties + * \ingroup ImplicitProperties + * \ingroup BoxZeroEqcniModel + * \file + * + * \brief Defines default properties for the non-isothermal compositional ZeroEq box model. + */ + +#ifndef DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH +#define DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH + +#include <dumux/freeflow/stokesncni/fluxvariables.hh> +#include <dumux/freeflow/stokesncni/model.hh> +#include <dumux/freeflow/stokesncni/volumevariables.hh> +#include "fluxvariables.hh" +#include "model.hh" + +namespace Dumux +{ + +namespace Properties +{ +////////////////////////////////////////////////////////////////// +// Properties +////////////////////////////////////////////////////////////////// + +// INHERITED +//! Set the Model property +SET_TYPE_PROP(BoxZeroEqncni, Model, ZeroEqncniModel<TypeTag>); + +//! Set the FluxVariables property +SET_TYPE_PROP(BoxZeroEqncni, FluxVariables, ZeroEqncniFluxVariables<TypeTag>); + +//! Set the indices used by the ZeroEqncni model +SET_TYPE_PROP(BoxZeroEqncni, Indices, ZeroEqncniCommonIndices<TypeTag>); + +//! Set calculation to Navier-Stokes +SET_BOOL_PROP(BoxZeroEqncni, EnableNavierStokes, true); + +//! Don't use mole fractions +SET_BOOL_PROP(BoxZeroEqncni, UseMoles, false); + +// NEW PROPERTIES +//! Set the Eddy Conductivity Model +SET_INT_PROP(BoxZeroEqncni, ZeroEqEddyConductivityModel, 1); + +//! Set the turbulent Prandtl number \f$[-]\f$ (Reynolds analogy) +SET_SCALAR_PROP(BoxZeroEqncni, ZeroEqTurbulentPrandtlNumber, 1.0); + +//! Set the BaseStokesModel to StokesncniModel +SET_TYPE_PROP(BoxZeroEqncni, BaseStokesModel, StokesncniModel<TypeTag>); + +//! Set the BaseStokesFluxVariables to StokesncniFluxVariables +SET_TYPE_PROP(BoxZeroEqncni, BaseStokesFluxVariables, StokesncniFluxVariables<TypeTag>); +} +} + +#endif // DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH diff --git a/dumux/freeflow/zeroeqncni/zeroeqncnifluxvariables.hh b/dumux/freeflow/zeroeqncni/zeroeqncnifluxvariables.hh index ec6e583363cbccd4cccbf1bfb81571aa5afb7083..4c80a8c685608d99ca9d3df17665bb741f8400ef 100644 --- a/dumux/freeflow/zeroeqncni/zeroeqncnifluxvariables.hh +++ b/dumux/freeflow/zeroeqncni/zeroeqncnifluxvariables.hh @@ -1,222 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief This file contains the data which is required to calculate - * the fluxes of the non-isothermal compositional ZeroEq model over - * a face of a finite volume. - * - * This means the methods to calculate the eddy conductivity. - */ -#ifndef DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH -#define DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH +#ifndef DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH_OLD +#define DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH_OLD -#include <dumux/common/math.hh> -#include <dumux/common/valgrind.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeqncni/fluxvariables.hh instead -#include <dumux/freeflow/zeroeqnc/zeroeqncfluxvariables.hh> -#include <dumux/freeflow/zeroeqncni/zeroeqncniindices.hh> -#include <dumux/freeflow/zeroeqncni/zeroeqncniproperties.hh> +#include <dumux/freeflow/zeroeqncni/fluxvariables.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqncniModel - * \ingroup ImplicitFluxVariables - * \brief This template class contains data which is required to - * calculate the component fluxes over a face of a finite - * volume for a non-isothermal compositional ZeroEq model. - * - * This means the methods to calculate the eddy conductivity. - */ -template <class TypeTag> -class ZeroEqncniFluxVariables : public ZeroEqncFluxVariables<TypeTag> -{ - typedef ZeroEqncFluxVariables<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { dim = GridView::dimension, - phaseIdx = Indices::phaseIdx, - transportCompIdx = Indices::transportCompIdx}; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef Dune::FieldVector<Scalar, dim> DimVector; - - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - -public: - ZeroEqncniFluxVariables(const Problem &problem, - const Element &element, - const FVElementGeometry &fvGeometry, - const int fIdx, - const ElementVolumeVariables &elemVolVars, - const bool onBoundary = false) - : ParentType(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary) - , flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - , eddyConductivityModel_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyConductivityModel)) - { - globalPos_ = this->face().ipGlobal; - posIdx_ = problem.model().getPosIdx(globalPos_); - wallIdx_ = problem.model().getWallIdx(globalPos_, posIdx_); - velGrad_ = this->velocityGrad_[flowNormal_][wallNormal_]; - velGradWall_ = problem.model().wall[wallIdx_].wallVelGrad[posIdx_]; - yPlusReal_ = this->distanceToWallReal() * this->frictionVelocityWall() - / problem.model().wall[wallIdx_].wallKinematicViscosity[posIdx_]; - - temperatureEddyConductivity_ = 0.0; - mixingLengthConductivity_ = 0.0; - - // calculation of an eddy conductivity only makes sense with Navier-Stokes equation - if (GET_PROP_VALUE(TypeTag, EnableNavierStokes)) - calculateEddyConductivity_(problem, element, elemVolVars); - }; - -protected: - /*! - * \brief This functions calculates the eddy conductivity. - * - * The eddy conductivity is added to the conductivity in stokesncnilocalresidual.hh - * at each scv face. - */ - void calculateEddyConductivity_(const Problem &problem, - const Element &element, - const ElementVolumeVariables &elemVolVars) - { - // IMPORTANT: - // the temperatureEddyConductivity_ a_t [m^2/s] is converted to - // thermalEddyConductivity \lambda_t [W/(m K)] by the convenience function - - // no eddy conductivity model - if (eddyConductivityModel_ == EddyConductivityIndices::noEddyConductivityModel) - return; - - // Reynolds analogy - // Bird, Stewart and Lightfoot, Transport Phenomena, 2007, p 657 - else if (eddyConductivityModel_ == EddyConductivityIndices::reynoldsAnalogy) - { - temperatureEddyConductivity_ = this->kinematicEddyViscosity() - / GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, TurbulentPrandtlNumber); - } - - // modified Van-Driest - // e.g. Bird, Stewart, and Lightfoot, E. N. Transport phenomena, 2007 - else if (eddyConductivityModel_ == EddyConductivityIndices::modifiedVanDriest) - { - Scalar aPlus = 26.0; - Scalar bPlus = 0.26; - // eddy conductivity can only be calculated correctly for non-zero distance to walls - mixingLengthConductivity_ = 0.0; - if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) - mixingLengthConductivity_ = this->karmanConstant() * this->distanceToWallReal() - * (1.0 - std::exp(-yPlusReal_ / aPlus)) - / std::sqrt(1.0 - std::exp(-bPlus * yPlusReal_)); - - temperatureEddyConductivity_ = mixingLengthConductivity_ * mixingLengthConductivity_ - * std::abs(velGrad_); - } - - // Deissler near wall law - // Deissler, R. G. "Analysis of Turbulent Heat Transfer, Mass Transfer, and Friction in Smooth Tubes at High Prandtl and Schmidt Numbers" - // NACA Report, 1954, 1210, 69-82 - else if (eddyConductivityModel_ == EddyConductivityIndices::deissler) - { - const Scalar deisslerConstant = 0.124; - const Scalar beta = this->density() * deisslerConstant * deisslerConstant - * std::abs(this->velocity()[flowNormal_]) - * this->distanceToWallReal(); - temperatureEddyConductivity_ = beta * (1.0 - std::exp(-beta / this->dynamicViscosity())); - temperatureEddyConductivity_ /= this->density(); - } - - // Meier and Rotta - // Cebeci, Analysis of turbulent boundary layer, 1974, p 251f - else if (eddyConductivityModel_ == EddyConductivityIndices::meier) - { - // Pr_t at flow = 0.86 - // Pr_t in wall = 1.34 - Scalar kappaMeier = this->karmanConstant() / std::sqrt(0.86); - Scalar aPlusMeier = std::sqrt(1.34) / std::sqrt(0.86) * 26.0; - mixingLengthConductivity_ = 0.0; - if (this->distanceToWallReal() > 0.0 && yPlusReal_ > 0.0) - mixingLengthConductivity_ = kappaMeier * this->distanceToWallReal() - * (1.0 - std::exp(- yPlusReal_ / aPlusMeier)); - temperatureEddyConductivity_ = mixingLengthConductivity_ * mixingLengthConductivity_ * std::abs(velGrad_); - } - - else - { - DUNE_THROW(Dune::NotImplemented, "This eddy conductivity model is not implemented."); - } - - Valgrind::CheckDefined(temperatureEddyConductivity_); - } - - -public: - /*! - * \brief Returns the thermal eddy conductivity \f$\mathrm{[W/(m*K)]}\f$. - */ - const Scalar thermalEddyConductivity() const - { return temperatureEddyConductivity() * this->density() * this->heatCapacity(); } - - /*! - * \brief Returns the temperature eddy conductivity \f$\mathrm{[m^2/s]}\f$. - */ - const Scalar temperatureEddyConductivity() const - { return temperatureEddyConductivity_; } - - /*! - * \brief Returns Prandtl number (molecular) \f$\mathrm{[-]}\f$. - */ - const Scalar prandtlNumber() const - { return this->dynamicViscosity() * this->heatCapacity() / this->thermalConductivity(); } - - /*! - * \brief Returns the turbulent Prandtl number \f$\mathrm{[-]}\f$. - */ - const Scalar turbulentPrandtlNumber() const - { return this->dynamicEddyViscosity() * this->heatCapacity() / thermalEddyConductivity(); } - - -private: - const int flowNormal_; - const int wallNormal_; - const int eddyConductivityModel_; - int posIdx_; - int wallIdx_; - - Scalar velGrad_; - Scalar velGradWall_; - DimVector globalPos_; - Scalar yPlusReal_; - - Scalar temperatureEddyConductivity_; - Scalar mixingLengthConductivity_; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQNCNI_FLUX_VARIABLES_HH +#endif diff --git a/dumux/freeflow/zeroeqncni/zeroeqncniindices.hh b/dumux/freeflow/zeroeqncni/zeroeqncniindices.hh index eb8e9efab6856e43a10333bd726a524a5a60e0a2..af1150d979489f6c43cf5c889ac84a9a5b93e8d7 100644 --- a/dumux/freeflow/zeroeqncni/zeroeqncniindices.hh +++ b/dumux/freeflow/zeroeqncni/zeroeqncniindices.hh @@ -1,65 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ +#ifndef DUMUX_ZEROEQNCNI_INDICES_HH_OLD +#define DUMUX_ZEROEQNCNI_INDICES_HH_OLD -/*! - * \file - * \brief Defines the indices required for the non-isothermal - * compositional ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQNCNI_INDICES_HH -#define DUMUX_ZEROEQNCNI_INDICES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqncni/indices.hh instead -#include <dumux/freeflow/stokesncni/stokesncniindices.hh> -#include <dumux/freeflow/zeroeq/zeroeqindices.hh> -#include <dumux/freeflow/zeroeqnc/zeroeqncindices.hh> +#include <dumux/freeflow/zeroeqncni/indices.hh> -namespace Dumux -{ - -/*! - * \ingroup BoxZeroEqncniModel - * \brief The indices for the eddy conductivity model. - */ -struct EddyConductivityIndices -{ - // Eddy Conductivity Model Indices - static const int noEddyConductivityModel = 0; - static const int reynoldsAnalogy = 1; - static const int modifiedVanDriest = 2; - static const int deissler = 3; - static const int meier = 4; -}; - -/*! - * \ingroup BoxZeroEqncniModel - * \ingroup ImplicitIndices - * \brief The common indices for the non-isothermal compositional ZeroEq box model. - * - * \tparam PVOffset The first index in a primary variable vector. - */ -template <class TypeTag, int PVOffset = 0> -struct ZeroEqncniCommonIndices : public StokesncniCommonIndices<TypeTag, PVOffset> -{ - static const int scvDataPrecision = 5; - static const int scvDataWidth = scvDataPrecision + 10; -}; - -} // end namespace - -#endif // DUMUX_ZEROEQNCNI_INDICES_HH +#endif diff --git a/dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh b/dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh index b9069258a5c5495621c3cac32aa67da75c3f0519..fd0f40f365046b64fdb6d84c6ef669d220788f17 100644 --- a/dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh +++ b/dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh @@ -1,403 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief Base class for all models which use the non-isothermal - * compositional ZeroEq box model. - */ -#ifndef DUMUX_ZEROEQNCNI_MODEL_HH -#define DUMUX_ZEROEQNCNI_MODEL_HH +#ifndef DUMUX_ZEROEQNCNI_MODEL_HH_OLD +#define DUMUX_ZEROEQNCNI_MODEL_HH_OLD -#include "zeroeqncniindices.hh" -#include "zeroeqncniproperties.hh" -#include <dumux/freeflow/zeroeqnc/zeroeqncmodel.hh> +#warning this header is deprecated, use dumux/freeflow/zeroeqncni/model.hh instead +#include <dumux/freeflow/zeroeqncni/model.hh> -namespace Dumux -{ -/*! - * \ingroup BoxZeroEqncniModel - * \brief Adaption of the box scheme to the non-isothermal compositional ZeroEq model. - * - * This model implements an single-phase non-isothermal compositional free flow - * solving the mass and the momentum balance. For the momentum balance - * the Reynolds-averaged Navier-Stokes (RANS) equation with zero equation - * (algebraic) turbulence model is used. - * - * Mass balance: - * \f[ - * \frac{\partial \varrho_\textrm{g}}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) - * - q_\textrm{g} = 0 - * \f] - * - * Momentum Balance: - * \f[ - * \frac{\partial \left(\varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g}\right)}{\partial t} - * + \text{div} \left( - * \varrho_\textrm{g} {\boldsymbol{v}_\textrm{g} {\boldsymbol{v}}_\textrm{g}} - * - \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right] - * \left( \textbf{grad}\, \boldsymbol{v}_\textrm{g} - * + \textbf{grad}\, \boldsymbol{v}_\textrm{g}^T \right) - * \right) - * + \left(p_\textrm{g} {\bf {I}} \right) - * - \varrho_\textrm{g} {\bf g} = 0 - * \f] - * - * Component mass balance equations: - * \f[ - * \frac{\partial \left(\varrho_\textrm{g} X_\textrm{g}^\kappa\right)}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} X_\textrm{g}^\kappa - * - \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] - * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x_\textrm{g}^\kappa \right) - * - q_\textrm{g}^\kappa = 0 - * \f] - * - * Energy balance equation: - * \f[ - * \frac{\partial (\varrho_\textrm{g} u_\textrm{g})}{\partial t} - * + \text{div} \left( \varrho_\textrm{g} h_\textrm{g} {\boldsymbol{v}}_\textrm{g} - * - \sum_\kappa \left( h^\kappa_\textrm{g} \left[ D^\kappa_\textrm{g} + D^\kappa_\textrm{g,t} \right] - * \varrho_\textrm{g} \frac{M^\kappa}{M_\textrm{g}} \textbf{grad}\, x^\kappa_\textrm{g} \right) - * - \left[ \lambda_\textrm{g} + \lambda_\textrm{g,t} \right] \textbf{grad}\, T \right) - * - q_\textrm{T} = 0 - * \f] - * Please note that, even though it is n-component model, the diffusive - * fluxes are still calculated with binary diffusion. - * - * This is discretized by a fully-coupled vertex-centered finite volume - * (box) scheme in space and by the implicit Euler method in time. - */ -template<class TypeTag> -class ZeroEqncniModel : public ZeroEqncModel<TypeTag> -{ - typedef ZeroEqncModel<TypeTag> ParentType; - typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation; - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; - typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; - - enum { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - intervals = GET_PROP_VALUE(TypeTag, NumberOfIntervals), - walls = (GET_PROP_VALUE(TypeTag, BBoxMinIsWall) ? 1 : 0) - + (GET_PROP_VALUE(TypeTag, BBoxMaxIsWall) ? 1 : 0) - }; - enum { transportCompIdx = Indices::transportCompIdx, - numComponents = Indices::numComponents }; - enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) }; - - typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; - - typedef typename GridView::template Codim<0>::Entity Element; - typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry; - typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector; - - typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; - typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; - typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables; - typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables; - - -public: - ZeroEqncniModel() - : flowNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, FlowNormal)) - , wallNormal_(GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, WallNormal)) - { - eps_ = 1e-6; - - // check whether sand grain roughness may be used - if (GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMinSandGrainRoughness) > 0 - || GET_PARAM_FROM_GROUP(TypeTag, Scalar, ZeroEq, BBoxMaxSandGrainRoughness) > 0) - { - Dune::dwarn << "warning: surface roughness will not be used for eddy conductivity models." << std::endl; - } - } - - //! \copydoc ImplicitModel::addOutputVtkFields - template <class MultiWriter> - void addOutputVtkFields(const SolutionVector &sol, - MultiWriter &writer) - { - typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField; - typedef Dune::BlockVector<Dune::FieldVector<Scalar, dim> > VectorField; - - // create the required scalar fields - unsigned numVertices = this->gridView_().size(dim); - unsigned numElements = this->gridView_().size(0); - ScalarField &pN = *writer.allocateManagedBuffer(numVertices); - ScalarField &delP = *writer.allocateManagedBuffer(numVertices); - ScalarField *moleFraction[numComponents]; - ScalarField *massFraction[numComponents]; - ScalarField &rho = *writer.allocateManagedBuffer(numVertices); - VectorField &velocity = *writer.template allocateManagedBuffer<Scalar, dim> (numVertices); - ScalarField &mu = *writer.allocateManagedBuffer(numVertices); - ScalarField &D = *writer.allocateManagedBuffer(numVertices); - ScalarField &T = *writer.allocateManagedBuffer(numVertices); - ScalarField &lambda = *writer.allocateManagedBuffer(numVertices); - ScalarField &mut = *writer.allocateManagedBuffer(numElements); - ScalarField &nut = *writer.allocateManagedBuffer(numElements); - ScalarField &lmix = *writer.allocateManagedBuffer(numElements); - ScalarField &uPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &yPlus = *writer.allocateManagedBuffer(numElements); - ScalarField &Dt = *writer.allocateManagedBuffer(numElements); - ScalarField &lambdat = *writer.allocateManagedBuffer(numElements); - ScalarField &rank = *writer.allocateManagedBuffer(numElements); - for (int i = 0; i < numComponents; ++i) - moleFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - for (int i = 0; i < numComponents; ++i) - massFraction[i] = writer.template allocateManagedBuffer<Scalar, 1>(numVertices); - - // write volume values to .vtu and .csv - std::ofstream volVarsFile("volVarsData.csv", std::ios_base::out); - asImp_().writeVolVarsHeader(volVarsFile); - volVarsFile << std::endl; - - FVElementGeometry fvGeometry; - VolumeVariables volVars; - - for (const auto& element : Dune::elements(this->gridView_())) - { - int idx = this->elementMapper().index(element); - rank[idx] = this->gridView_().comm().rank(); - - fvGeometry.update(this->gridView_(), element); - - int numLocalVerts = element.template subEntities(dim); - for (int i = 0; i < numLocalVerts; ++i) - { - int vIdxGlobal = this->vertexMapper().subIndex(element, i, dim); - volVars.update(sol[vIdxGlobal], - this->problem_(), - element, - fvGeometry, - i, - false); - - pN[vIdxGlobal] = volVars.pressure(); - delP[vIdxGlobal] = volVars.pressure() - 1e5; - for (int compIdx = 0; compIdx < numComponents; ++compIdx) - { - (*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx); - (*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx); - Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]); - Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]); - } - rho[vIdxGlobal] = volVars.density(); - mu[vIdxGlobal] = volVars.dynamicViscosity(); - D[vIdxGlobal] = volVars.diffusionCoeff(transportCompIdx); - T[vIdxGlobal] = volVars.temperature(); - velocity[vIdxGlobal] = volVars.velocity(); - - asImp_().writeVolVarsData(volVarsFile, volVars); - volVarsFile << std::endl; - } - } - volVarsFile.close(); - - writer.attachVertexData(pN, "P"); - writer.attachVertexData(delP, "delP"); - - for (int j = 0; j < numComponents; ++j) - { - std::ostringstream moleFrac, massFrac; - moleFrac << "x_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str()); - - massFrac << "X_" << FluidSystem::phaseName(phaseIdx) - << "^" << FluidSystem::componentName(j); - writer.attachVertexData(*massFraction[j], massFrac.str().c_str()); - } - - writer.attachVertexData(rho, "rho"); - writer.attachVertexData(mu, "mu"); - writer.attachVertexData(D, "D"); - writer.attachVertexData(lambda, "lambda"); - writer.attachVertexData(T, "temperature"); - writer.attachVertexData(velocity, "v", dim); - - // ensure that the actual values are given out - asImp_().updateWallProperties(); - - // write flux values to .vtu and .csv - std::ofstream fluxFile("fluxVarsData.csv", std::ios_base::out); - asImp_().writeFluxVarsHeader(fluxFile); - fluxFile << std::endl; - - for (const auto& element : Dune::elements(this->gridView_())) - { - fvGeometry.update(this->gridView_(), element); - - ElementVolumeVariables elemVolVars; - elemVolVars.update(this->problem_(), - element, - fvGeometry, - false); - - unsigned int numFluxVars = 0; - Scalar sumDynamicEddyViscosity = 0.0; - Scalar sumKinematicEddyViscosity = 0.0; - Scalar sumMixingLength = 0.0; - Scalar sumUPlus = 0.0; - Scalar sumYPlus = 0.0; - Scalar sumEddyDiffusivity = 0.0; - Scalar sumEddyConducitivity = 0.0; - - for (const auto& intersection : Dune::intersections(this->gridView_(), element)) - { - int fIdx = intersection.indexInInside(); - - FluxVariables fluxVars(this->problem_(), - element, - fvGeometry, - fIdx, - elemVolVars, - false); - - asImp_().writeFluxVarsData(fluxFile, fluxVars); - fluxFile << std::endl; - - sumDynamicEddyViscosity += fluxVars.dynamicEddyViscosity(); - sumKinematicEddyViscosity += fluxVars.kinematicEddyViscosity(); - sumMixingLength += fluxVars.mixingLength(); - sumUPlus += fluxVars.uPlus(); - sumYPlus += fluxVars.yPlusRough(); - sumEddyDiffusivity += fluxVars.eddyDiffusivity(); - sumEddyConducitivity += fluxVars.thermalEddyConductivity(); - numFluxVars += 1; - } - - int eIdxGlobal = this->elementMapper().index(element); - mut[eIdxGlobal] = sumDynamicEddyViscosity / numFluxVars; - nut[eIdxGlobal] = sumKinematicEddyViscosity / numFluxVars; - lmix[eIdxGlobal] = sumMixingLength / numFluxVars; - uPlus[eIdxGlobal] = sumUPlus / numFluxVars; - yPlus[eIdxGlobal] = sumYPlus / numFluxVars; - Dt[eIdxGlobal] = sumEddyDiffusivity / numFluxVars; - lambdat[eIdxGlobal] = sumEddyConducitivity / numFluxVars; - } - fluxFile.close(); - - writer.attachCellData(mut, "mu_t"); - writer.attachCellData(nut, "nu_t"); - writer.attachCellData(lmix, "l_mix"); - writer.attachCellData(uPlus, "u^+"); - writer.attachCellData(yPlus, "y^+"); - writer.attachCellData(Dt, "D_t"); - writer.attachCellData(lambdat, "lambda_t"); - } - - //! \copydoc ZeroEqModel::writeFluxVarsHeader - void writeFluxVarsHeader(std::ofstream &stream) - { - ParentType::writeFluxVarsHeader(stream); - stream << "," << "EddyConductivity"; - } - - //! \copydoc ZeroEqModel::writeFluxVarsData - void writeFluxVarsData(std::ofstream &stream, const FluxVariables &fluxVars) - { - ParentType::writeFluxVarsData(stream, fluxVars); - stream << "," << fluxVars.thermalEddyConductivity(); - } - - /*! - * \name Wall properties - */ - // \{ - - - //! \copydoc ZeroEqModel::resetWallProperties - void resetWallProperties() - { - ParentType::resetWallProperties(); - - for (int wallIdx = 0; wallIdx < walls; ++wallIdx) - for (int posIdx = 0; posIdx < intervals; ++posIdx) - { - this->wall[wallIdx].maxTemperature[posIdx] = 0.0; - } - } - - //! \copydoc ZeroEqModel::calculateMaxFluxVars - void calculateMaxFluxVars(const FluxVariables &fluxVars, const GlobalPosition &globalPos) - { - ParentType::calculateMaxFluxVars(fluxVars, globalPos); - - int posIdx = this->getPosIdx(globalPos); - int wallIdx = this->getWallIdx(globalPos, posIdx); - if (this->wall[wallIdx].maxTemperature[posIdx] < fluxVars.temperature()) - for (int wIdx = 0; wIdx < walls; ++wIdx) - this->wall[wIdx].maxTemperature[posIdx] = fluxVars.temperature(); - } - - //! \copydoc ZeroEqModel::doInterpolationFluxValues - const void doInterpolationFluxValues(const int wallIdx, const int posIdx, const int prevIdx, const int nextIdx) - { - ParentType::doInterpolationFluxValues(wallIdx, posIdx, prevIdx, nextIdx); - this->wall[wallIdx].maxTemperature[posIdx] = this->interpolation(posIdx, prevIdx, this->wall[wallIdx].maxTemperature[prevIdx], nextIdx, this->wall[wallIdx].maxTemperature[nextIdx]); - } - - // \} // wall properties - - /*! - * \brief Returns the name of used the eddy conductivity model. - */ - const char *eddyConductivityModelName() const - { - switch (GET_PARAM_FROM_GROUP(TypeTag, int, ZeroEq, EddyConductivityModel)) - { - case EddyConductivityIndices::noEddyConductivityModel: // 0 - return "noEddyConductivityModel"; - break; - case EddyConductivityIndices::reynoldsAnalogy: // 1 - return "reynoldsAnalogy"; - break; - case EddyConductivityIndices::modifiedVanDriest: // 2 - return "modifiedVanDriest"; - break; - case EddyConductivityIndices::deissler: // 3 - return "deissler"; - break; - case EddyConductivityIndices::meier: // 4 - return "meier"; - break; - default: - DUNE_THROW(Dune::NotImplemented, "This eddy conductivity model is not implemented."); - } - } - -private: - Scalar eps_; - const int flowNormal_; - const int wallNormal_; - - Implementation &asImp_() - { return *static_cast<Implementation*>(this); } - const Implementation &asImp_() const - { return *static_cast<const Implementation*>(this); } -}; - -} - -#include "zeroeqncnipropertydefaults.hh" - -#endif // DUMUX_ZEROEQNCNI_MODEL_HH +#endif diff --git a/dumux/freeflow/zeroeqncni/zeroeqncniproperties.hh b/dumux/freeflow/zeroeqncni/zeroeqncniproperties.hh index cbdf6c40f8a17ecc6dc365692b9644e134e41598..f2bbf3ea4a8d3ca86e40689119bbbe54d75064b2 100644 --- a/dumux/freeflow/zeroeqncni/zeroeqncniproperties.hh +++ b/dumux/freeflow/zeroeqncni/zeroeqncniproperties.hh @@ -1,57 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqncniModel - * - * \file - * - * \brief Defines the properties required for the - * non-isothermal compositional ZeroEq box model. - */ +#ifndef DUMUX_ZEROEQNCNI_PROPERTIES_HH_OLD +#define DUMUX_ZEROEQNCNI_PROPERTIES_HH_OLD -#ifndef DUMUX_ZEROEQNCNI_PROPERTIES_HH -#define DUMUX_ZEROEQNCNI_PROPERTIES_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqncni/properties.hh instead -#include <dumux/freeflow/stokesncni/stokesncniproperties.hh> -#include <dumux/freeflow/zeroeqnc/zeroeqncproperties.hh> +#include <dumux/freeflow/zeroeqncni/properties.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Type tags -////////////////////////////////////////////////////////////////// - -//! The type tag for the ZeroEqncni Problem -NEW_TYPE_TAG(BoxZeroEqncni, INHERITS_FROM(BoxZeroEqnc, BoxStokesncni)); - -////////////////////////////////////////////////////////////////// -// Property tags -////////////////////////////////////////////////////////////////// - -NEW_PROP_TAG(ZeroEqEddyConductivityModel); //!< Returns which Eddy Conductivity Model is used -NEW_PROP_TAG(ZeroEqTurbulentPrandtlNumber); //!< Returns the used turbulent Prandtl number (Reynolds analogy) -} -} - -#endif // DUMUX_ZEROEQNCNI_PROPERTIES_HH +#endif diff --git a/dumux/freeflow/zeroeqncni/zeroeqncnipropertydefaults.hh b/dumux/freeflow/zeroeqncni/zeroeqncnipropertydefaults.hh index 710d2380d7cd573be8d45462267983446e70fdd5..4545ca6ed174b3015a21a0c672218830d67055dd 100644 --- a/dumux/freeflow/zeroeqncni/zeroeqncnipropertydefaults.hh +++ b/dumux/freeflow/zeroeqncni/zeroeqncnipropertydefaults.hh @@ -1,77 +1,8 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \ingroup Properties - * \ingroup ImplicitProperties - * \ingroup BoxZeroEqcniModel - * \file - * - * \brief Defines default properties for the non-isothermal compositional ZeroEq box model. - */ +#ifndef DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH_OLD +#define DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH_OLD -#ifndef DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH -#define DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH +#warning this header is deprecated, use dumux/freeflow/zeroeqncni/propertydefaults.hh instead -#include <dumux/freeflow/stokesncni/stokesncnifluxvariables.hh> -#include <dumux/freeflow/stokesncni/stokesncnimodel.hh> -#include <dumux/freeflow/stokesncni/stokesncnivolumevariables.hh> -#include "zeroeqncnifluxvariables.hh" -#include "zeroeqncnimodel.hh" +#include <dumux/freeflow/zeroeqncni/propertydefaults.hh> -namespace Dumux -{ - -namespace Properties -{ -////////////////////////////////////////////////////////////////// -// Properties -////////////////////////////////////////////////////////////////// - -// INHERITED -//! Set the Model property -SET_TYPE_PROP(BoxZeroEqncni, Model, ZeroEqncniModel<TypeTag>); - -//! Set the FluxVariables property -SET_TYPE_PROP(BoxZeroEqncni, FluxVariables, ZeroEqncniFluxVariables<TypeTag>); - -//! Set the indices used by the ZeroEqncni model -SET_TYPE_PROP(BoxZeroEqncni, Indices, ZeroEqncniCommonIndices<TypeTag>); - -//! Set calculation to Navier-Stokes -SET_BOOL_PROP(BoxZeroEqncni, EnableNavierStokes, true); - -//! Don't use mole fractions -SET_BOOL_PROP(BoxZeroEqncni, UseMoles, false); - -// NEW PROPERTIES -//! Set the Eddy Conductivity Model -SET_INT_PROP(BoxZeroEqncni, ZeroEqEddyConductivityModel, 1); - -//! Set the turbulent Prandtl number \f$[-]\f$ (Reynolds analogy) -SET_SCALAR_PROP(BoxZeroEqncni, ZeroEqTurbulentPrandtlNumber, 1.0); - -//! Set the BaseStokesModel to StokesncniModel -SET_TYPE_PROP(BoxZeroEqncni, BaseStokesModel, StokesncniModel<TypeTag>); - -//! Set the BaseStokesFluxVariables to StokesncniFluxVariables -SET_TYPE_PROP(BoxZeroEqncni, BaseStokesFluxVariables, StokesncniFluxVariables<TypeTag>); -} -} - -#endif // DUMUX_ZEROEQNCNI_PROPERTY_DEFAULTS_HH +#endif diff --git a/dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh b/dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh index b359f4cc3d8997aef54ec88ebf20cfe63e5c785d..52bb8793a6e223e3a3ab4f8e854c4fb8528166fd 100644 --- a/dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh +++ b/dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh @@ -28,8 +28,8 @@ #include <dune/common/deprecated.hh> -#include <dumux/freeflow/stokesncni/stokesncnilocalresidual.hh> -#include <dumux/freeflow/stokesncni/stokesncnimodel.hh> +#include <dumux/freeflow/stokesncni/localresidual.hh> +#include <dumux/freeflow/stokesncni/model.hh> namespace Dumux { diff --git a/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh b/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh index e07fc319502776b2108ce046aa3fd1beb5bb49ec..6743259f8acac4cbaf1602208b9c5260b131ee59 100644 --- a/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh +++ b/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh @@ -36,7 +36,7 @@ #include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh> #include <dumux/freeflow/boundarylayermodel.hh> #include <dumux/freeflow/masstransfermodel.hh> -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> +#include <dumux/freeflow/stokesnc/model.hh> #include <dumux/porousmediumflow/2p2c/implicit/model.hh> diff --git a/dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh b/dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh index cfd97aed23bdad391a224d0a65e8fb065f77635c..b4a9154875946af7b346439f990dcc6488a86ebc 100644 --- a/dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh +++ b/dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh @@ -28,8 +28,8 @@ #include <dune/common/deprecated.hh> -#include <dumux/freeflow/stokesnc/stokesnclocalresidual.hh> -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> +#include <dumux/freeflow/stokesnc/localresidual.hh> +#include <dumux/freeflow/stokesnc/model.hh> namespace Dumux { diff --git a/test/freeflow/navierstokes/navierstokestestproblem.hh b/test/freeflow/navierstokes/navierstokestestproblem.hh index 175db8b581b7992cd23df4d2c41f33c1ea953e5c..fc4505dbfb05e643e3a60d8e70b6ae69f91056b2 100644 --- a/test/freeflow/navierstokes/navierstokestestproblem.hh +++ b/test/freeflow/navierstokes/navierstokestestproblem.hh @@ -37,7 +37,7 @@ #include <dumux/material/components/constant.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/stokes/stokesmodel.hh> +#include <dumux/freeflow/stokes/model.hh> namespace Dumux { diff --git a/test/freeflow/stokes/stokestestproblem.hh b/test/freeflow/stokes/stokestestproblem.hh index f2b69f7d299c4be4cb660a6d1c30d7e45b9654d0..3cbb52c8e58448c3ee4ff2429c1717423ccc8447 100644 --- a/test/freeflow/stokes/stokestestproblem.hh +++ b/test/freeflow/stokes/stokestestproblem.hh @@ -28,7 +28,7 @@ #include <dumux/material/fluidsystems/h2on2fluidsystem.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/stokes/stokesmodel.hh> +#include <dumux/freeflow/stokes/model.hh> namespace Dumux { diff --git a/test/freeflow/stokes2c/stokes2ctestproblem.hh b/test/freeflow/stokes2c/stokes2ctestproblem.hh index 215bb626f8dbd007f073c7d01c53a5c68cd15028..ce8e8adaa0148f3541ec4020748ad9adca51c20d 100644 --- a/test/freeflow/stokes2c/stokes2ctestproblem.hh +++ b/test/freeflow/stokes2c/stokes2ctestproblem.hh @@ -27,7 +27,7 @@ #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> +#include <dumux/freeflow/stokesnc/model.hh> namespace Dumux { diff --git a/test/freeflow/stokes2cni/stokes2cnitestproblem.hh b/test/freeflow/stokes2cni/stokes2cnitestproblem.hh index 2a99b16ceee1d2461dc674bec21a28840323c6e4..7bc4aa5d5af9a4c077b3b95bc054571a1ce26ff6 100644 --- a/test/freeflow/stokes2cni/stokes2cnitestproblem.hh +++ b/test/freeflow/stokes2cni/stokes2cnitestproblem.hh @@ -31,7 +31,7 @@ #include <dumux/linear/seqsolverbackend.hh> #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> -#include <dumux/freeflow/stokesncni/stokesncnimodel.hh> +#include <dumux/freeflow/stokesncni/model.hh> namespace Dumux { diff --git a/test/freeflow/zeroeq/zeroeqchanneltestproblem.hh b/test/freeflow/zeroeq/zeroeqchanneltestproblem.hh index 1287ea3546dce24178d05698c07e9cb98802f218..cf42457d4a15b27a0add83f2afcb431b09da7880 100644 --- a/test/freeflow/zeroeq/zeroeqchanneltestproblem.hh +++ b/test/freeflow/zeroeq/zeroeqchanneltestproblem.hh @@ -32,8 +32,8 @@ #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/zeroeq/zeroeqmodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqproblem.hh> +#include <dumux/freeflow/zeroeq/model.hh> +#include <dumux/freeflow/zeroeq/problem.hh> namespace Dumux { diff --git a/test/freeflow/zeroeq/zeroeqtestproblem.hh b/test/freeflow/zeroeq/zeroeqtestproblem.hh index f1c706cf806a810d9061b26e24eefed6883648bc..914ec6f097f08248ba33d7e5e16289b769888593 100644 --- a/test/freeflow/zeroeq/zeroeqtestproblem.hh +++ b/test/freeflow/zeroeq/zeroeqtestproblem.hh @@ -35,8 +35,8 @@ #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/zeroeq/zeroeqmodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqproblem.hh> +#include <dumux/freeflow/zeroeq/model.hh> +#include <dumux/freeflow/zeroeq/problem.hh> namespace Dumux { diff --git a/test/freeflow/zeroeq2c/zeroeq2ctestproblem.hh b/test/freeflow/zeroeq2c/zeroeq2ctestproblem.hh index 703e0fdab51c5296663c7650d5ab53b16fca9759..77e4cca525670ff72392469c4ad6ed0b2d5387bd 100644 --- a/test/freeflow/zeroeq2c/zeroeq2ctestproblem.hh +++ b/test/freeflow/zeroeq2c/zeroeq2ctestproblem.hh @@ -32,8 +32,8 @@ #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/zeroeqnc/zeroeqncmodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqproblem.hh> +#include <dumux/freeflow/zeroeqnc/model.hh> +#include <dumux/freeflow/zeroeq/problem.hh> namespace Dumux { diff --git a/test/freeflow/zeroeq2cni/zeroeq2cnitestproblem.hh b/test/freeflow/zeroeq2cni/zeroeq2cnitestproblem.hh index bca301d8c7f4421c7dd4eb512811600eee65faea..6086ba9e8e61bc6c6ae80e54ca48f2c532049f6d 100644 --- a/test/freeflow/zeroeq2cni/zeroeq2cnitestproblem.hh +++ b/test/freeflow/zeroeq2cni/zeroeq2cnitestproblem.hh @@ -32,8 +32,8 @@ #include <dumux/material/fluidsystems/h2oairfluidsystem.hh> #include <dumux/material/fluidsystems/gasphase.hh> -#include <dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh> -#include <dumux/freeflow/zeroeq/zeroeqproblem.hh> +#include <dumux/freeflow/zeroeqncni/model.hh> +#include <dumux/freeflow/zeroeq/problem.hh> namespace Dumux { diff --git a/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh b/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh index 6726d33db45924dc261db60fed407f1665f96e6e..87f20d8cbfaa02c23b8e1a6cfa3038c25f4b63ab 100644 --- a/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh +++ b/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_STOKES2CNI_SUBPROBLEM_HH #define DUMUX_STOKES2CNI_SUBPROBLEM_HH -#include <dumux/freeflow/stokesncni/stokesncnimodel.hh> +#include <dumux/freeflow/stokesncni/model.hh> #include <dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh> #include <dumux/multidomain/common/subdomainpropertydefaults.hh> diff --git a/test/multidomain/2cnizeroeq2p2cni/zeroeq2cnisubproblem.hh b/test/multidomain/2cnizeroeq2p2cni/zeroeq2cnisubproblem.hh index bf0914cefbcff51b73de061a48e8dde31fab4ed1..55f39c590c75dd94195c552d1d046ad414ea6b01 100644 --- a/test/multidomain/2cnizeroeq2p2cni/zeroeq2cnisubproblem.hh +++ b/test/multidomain/2cnizeroeq2p2cni/zeroeq2cnisubproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_ZEROEQTWOCNI_SUBPROBLEM_HH #define DUMUX_ZEROEQTWOCNI_SUBPROBLEM_HH -#include <dumux/freeflow/zeroeqncni/zeroeqncnimodel.hh> +#include <dumux/freeflow/zeroeqncni/model.hh> #include <dumux/multidomain/common/subdomainpropertydefaults.hh> #include <dumux/multidomain/2cnistokes2p2cni/stokesncnicouplinglocalresidual.hh> diff --git a/test/multidomain/2cstokes2p2c/stokes2csubproblem.hh b/test/multidomain/2cstokes2p2c/stokes2csubproblem.hh index d5af4f91ab9bce8764778e6d072500e9e5a59f67..6cf0ae00e95e7608941345eca36a410ad0a23d4d 100644 --- a/test/multidomain/2cstokes2p2c/stokes2csubproblem.hh +++ b/test/multidomain/2cstokes2p2c/stokes2csubproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_STOKES2C_SUBPROBLEM_HH #define DUMUX_STOKES2C_SUBPROBLEM_HH -#include <dumux/freeflow/stokesnc/stokesncmodel.hh> +#include <dumux/freeflow/stokesnc/model.hh> #include <dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh> #include <dumux/multidomain/common/subdomainpropertydefaults.hh> diff --git a/test/multidomain/2czeroeq2p2c/zeroeq2csubproblem.hh b/test/multidomain/2czeroeq2p2c/zeroeq2csubproblem.hh index 8d8f1029bb031d1272139386c6b78b6b40238292..b97caf150c9a61282f1589e21098378d7c340a59 100644 --- a/test/multidomain/2czeroeq2p2c/zeroeq2csubproblem.hh +++ b/test/multidomain/2czeroeq2p2c/zeroeq2csubproblem.hh @@ -24,7 +24,7 @@ #ifndef DUMUX_ZEROEQTWOCSUBPROBLEM_HH #define DUMUX_ZEROEQTWOCSUBPROBLEM_HH -#include <dumux/freeflow/zeroeqnc/zeroeqncmodel.hh> +#include <dumux/freeflow/zeroeqnc/model.hh> #include <dumux/multidomain/common/subdomainpropertydefaults.hh> #include <dumux/multidomain/2cstokes2p2c/stokesnccouplinglocalresidual.hh>