// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /* Copyright (C) 2012-2013 by Andreas Lauser Copyright (C) 2012 by Klaus Mosthaf This file is part of the Open Porous Media project (OPM). OPM 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. OPM 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 OPM. If not, see . */ /*! * \file * \copydoc Ewoms::NavierStokesTestProblem */ #ifndef EWOMS_NAVIER_STOKES_TEST_PROBLEM_HH #define EWOMS_NAVIER_STOKES_TEST_PROBLEM_HH #include #include #include #include #include #include #include namespace Ewoms { template class NavierStokesTestProblem; } namespace Opm { namespace Properties { NEW_TYPE_TAG(NavierStokesTestProblem, INHERITS_FROM(NavierStokesModel)); // Set the grid type SET_TYPE_PROP(NavierStokesTestProblem, Grid, Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming>); // Set the property which defines the type of the physical problem SET_TYPE_PROP(NavierStokesTestProblem, Problem, Ewoms::NavierStokesTestProblem); SET_PROP(NavierStokesTestProblem, Fluid) { private: typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; public: typedef Opm::GasPhase > type; }; // Disable gravity SET_BOOL_PROP(NavierStokesTestProblem, EnableGravity, false); // Enable constraints SET_BOOL_PROP(NavierStokesTestProblem, EnableConstraints, true); // Default simulation end time [s] SET_SCALAR_PROP(NavierStokesTestProblem, EndTime, 1e-3); // Default initial time step size [s] SET_SCALAR_PROP(NavierStokesTestProblem, InitialTimeStepSize, 1e-3); // Default grid file to load SET_STRING_PROP(NavierStokesTestProblem, GridFile, "grids/test_navierstokes.dgf"); } } namespace Ewoms { /*! * \ingroup StokesModel * \ingroup VcfvTestProblems * \brief Stokes flow problem with modified nitrogen (N2) circulating in * a cavity. (lid-driven cavity-flow) * * The example is taken from Ghia, Ghia, and Shin (1982), "High-Re solutions * for incompressible flow using the Navier-Stokes equations and a multigrid * method", Journal of Computational Physics, Vol. 48, pp. 387-411. * * The domain is two-dimensional and sized 1m times 1m. The boundary * conditions for the momentum balances are no-flow boundary * conditions except for the top, which is floating from left to right * with 1 m/s. The mass balance features outflow boundary * conditions. All vertices at the bottom, left and right boundaries * are constraint to a constant pressure level and zero velocity. */ template class NavierStokesTestProblem : public StokesProblem { typedef StokesProblem ParentType; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; typedef typename GET_PROP_TYPE(TypeTag, RateVector) RateVector; typedef typename GET_PROP_TYPE(TypeTag, BoundaryRateVector) BoundaryRateVector; typedef typename GET_PROP_TYPE(TypeTag, Constraints) Constraints; typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; enum { // Number of equations and grid dimension dimWorld = GridView::dimensionworld, // copy some indices for convenience pressureIdx = Indices::pressureIdx, velocity0Idx = Indices::velocity0Idx, conti0EqIdx = Indices::conti0EqIdx, momentum0EqIdx = Indices::momentum0EqIdx }; typedef typename GridView::ctype CoordScalar; typedef Dune::FieldVector GlobalPosition; public: /*! * \copydoc Doxygen::defaultProblemConstructor */ NavierStokesTestProblem(TimeManager &timeManager) #if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 3) : ParentType(timeManager, GET_PROP_TYPE(TypeTag, GridCreator)::grid().leafGridView()) #else : ParentType(timeManager, GET_PROP_TYPE(TypeTag, GridCreator)::grid().leafView()) #endif { eps_ = 1e-6; } /*! * \name Problem parameters */ //! \{ /*! * \copydoc VcfvProblem::name */ const char *name() const { return "navierstokes"; } /*! * \brief StokesProblem::temperature * * This problem assumes a constant temperature of 10 degrees Celsius. */ template Scalar temperature(const Context &context, int spaceIdx, int timeIdx) const { return 273.15 + 10; } //! \} /*! * \name Boundary conditions */ //! \{ /*! * \copydoc VcfvProblem::boundary */ template void boundary(BoundaryRateVector &values, const Context &context, int spaceIdx, int timeIdx) const { /* const GlobalPosition &pos = context.pos(spaceIdx, timeIdx); values.setOutflow(massBalanceIdx); values.setDirichlet(momentumXIdx); values.setDirichlet(momentumYIdx); // set pressure for all vertices at the bottom if (onLowerBoundary_(pos)) { values.setDirichlet(massBalanceIdx); } */ values.setNoFlow(context, spaceIdx, timeIdx); } //! \} /*! * \name Volume terms */ //! \{ /*! * \copydoc VcfvProblem::initial */ template void initial(PrimaryVariables &values, const Context &context, int spaceIdx, int timeIdx) const { initial_(values); } /*! * \copydoc VcfvProblem::constraints * * For this problem, we fix the velocity of upper boundary. */ template void constraints(Constraints &constraints, const Context &context, int spaceIdx, int timeIdx) const { const auto &pos = context.pos(spaceIdx, timeIdx); if (onUpperBoundary_(pos)) { // lid moves from left to right const Scalar lidVelocity = 1.0; constraints.setConstraint(momentum0EqIdx, velocity0Idx + 0, lidVelocity); constraints.setConstraint(momentum0EqIdx + 1, velocity0Idx + 1, 0); constraints.setConstraint(conti0EqIdx, pressureIdx, 1e5); } } /*! * \copydoc VcfvProblem::source */ template void source(RateVector &rate, const Context &context, int spaceIdx, int timeIdx) const { rate = Scalar(0.0); } //! \} private: // internal method for the initial condition void initial_(PrimaryVariables &priVars) const { priVars[pressureIdx] = 1e5; priVars[velocity0Idx + 0] = 0.0; priVars[velocity0Idx + 1] = 0.0; } bool onLeftBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] < this->boundingBoxMin()[0] + eps_; } bool onRightBoundary_(const GlobalPosition &globalPos) const { return globalPos[0] > this->boundingBoxMax()[0] - eps_; } bool onLowerBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] < this->boundingBoxMin()[1] + eps_; } bool onUpperBoundary_(const GlobalPosition &globalPos) const { return globalPos[1] > this->boundingBoxMax()[1] - eps_; } Scalar eps_; }; } // namespace Ewoms #endif