// -*- 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 3 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 * \ingroup BoundaryTests * \brief A simple Stokes test problem for the staggered grid (Navier-)Stokes model. */ #ifndef DUMUX_STOKES_BJS_SUBPROBLEM_HH #define DUMUX_STOKES_BJS_SUBPROBLEM_HH #include <dumux/common/properties.hh> #include <dumux/common/parameters.hh> #include <dumux/common/numeqvector.hh> #include <dumux/discretization/staggered/freeflow/properties.hh> #include <dumux/freeflow/navierstokes/boundarytypes.hh> #include <dumux/freeflow/navierstokes/model.hh> #include <dumux/freeflow/navierstokes/problem.hh> #include <dumux/multidomain/boundary/stokesdarcy/couplingdata.hh> namespace Dumux { /*! * \brief The rans subproblem */ template <class TypeTag> class StokesSubProblem : public NavierStokesProblem<TypeTag> { using ParentType = NavierStokesProblem<TypeTag>; using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; using FluidState = GetPropType<TypeTag, Properties::FluidState>; using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; using NumEqVector = Dumux::NumEqVector<PrimaryVariables>; using Scalar = GetPropType<TypeTag, Properties::Scalar>; using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>; using BoundaryTypes = Dumux::NavierStokesBoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>; using Element = typename GridGeometry::GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>; static constexpr auto dimWorld = GridGeometry::GridView::dimensionworld; public: StokesSubProblem(std::shared_ptr<const GridGeometry> gridGeometry, std::shared_ptr<CouplingManager> couplingManager) : ParentType(gridGeometry, "NavierStokes") , eps_(1e-8) , couplingManager_(couplingManager) { problemName_ = getParam<std::string>("Vtk.OutputName") + "_" + getParamFromGroup<std::string>(this->paramGroup(), "Problem.Name"); pressureDifference_ = getParam<Scalar>("Problem.PressureDifference"); porousMediaBoxMin_ = getParam<GlobalPosition>("Problem.PorousMediaBoxMin"); porousMediaBoxMax_ = getParam<GlobalPosition>("Problem.PorousMediaBoxMax"); } const std::string& name() const { return problemName_; } /*! * \brief Returns the temperature [K] within the domain for the isothermal model. */ Scalar temperature() const { return 298.15; } /*! * \brief Specifies which kind of boundary condition should be * used for which equation on a given boundary segment. * * \param element The finite element * \param scvf The sub control volume face */ BoundaryTypes boundaryTypes(const Element& element, const SubControlVolumeFace& scvf) const { BoundaryTypes values; const auto& globalPos = scvf.ipGlobal(); if (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos)) values.setDirichlet(Indices::pressureIdx); else if (isOnCouplingWall_(scvf)) { values.setCouplingNeumann(Indices::conti0EqIdx); values.setCouplingNeumann(scvf.directionIndex()); values.setBeaversJoseph(1 - scvf.directionIndex()); } else values.setAllSymmetry(); return values; } /*! * \brief Evaluate the boundary conditions for a dirichlet * control volume. * * \param globalPos The center of the finite volume which ought to be set. */ PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const { PrimaryVariables values(0.0); if(onLeftBoundary_(globalPos)) values[Indices::pressureIdx] = pressureDifference_; return values; } /*! * \brief Evaluates the boundary conditions for a Neumann control volume. * * \param element The element for which the Neumann boundary condition is set * \param fvGeometry The fvGeometry * \param elemVolVars The element volume variables * \param elemFaceVars The element face variables * \param scvf The boundary sub control volume face */ template<class ElementVolumeVariables, class ElementFaceVariables> NumEqVector neumann(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& elemVolVars, const ElementFaceVariables& elemFaceVars, const SubControlVolumeFace& scvf) const { NumEqVector values(0.0); if (couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf)) { values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf); } return values; } /*! * \brief Evaluate the initial value for a control volume. * * \param globalPos The global position */ PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const { return PrimaryVariables(0.0); } //! Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const { return couplingManager().couplingData().darcyPermeability(element, scvf); } //! Returns the alpha value required as input parameter for the Beavers-Joseph-Saffman boundary condition Scalar alphaBJ(const SubControlVolumeFace& scvf) const { return couplingManager().problem(CouplingManager::darcyIdx).spatialParams().beaversJosephCoeffAtPos(scvf.center()); } //! Set the coupling manager void setCouplingManager(std::shared_ptr<CouplingManager> cm) { couplingManager_ = cm; } //! Get the coupling manager const CouplingManager& couplingManager() const { return *couplingManager_; } private: bool onLeftBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_; } bool onRightBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_; } bool onLowerBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_; } bool onUpperBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; } bool isOnCouplingWall_(const SubControlVolumeFace& scvf) const { return couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf); } // the height of the free-flow domain const Scalar height_() const { return this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]; } Scalar pressureDifference_; GlobalPosition porousMediaBoxMin_; GlobalPosition porousMediaBoxMax_; Scalar eps_; std::string problemName_; std::shared_ptr<CouplingManager> couplingManager_; }; } // end namespace Dumux #endif