// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /* 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 . Consult the COPYING file in the top-level source directory of this module for the precise wording of the license and the list of copyright holders. */ /*! * \file * * \copydoc Opm::PowerInjectionProblem */ #ifndef EWOMS_POWER_INJECTION_PROBLEM_HH #define EWOMS_POWER_INJECTION_PROBLEM_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Opm { template class PowerInjectionProblem; } namespace Opm::Properties { namespace TTag { struct PowerInjectionBaseProblem {}; } // Set the grid implementation to be used template struct Grid { using type = Dune::YaspGrid; }; // set the Vanguard property template struct Vanguard { using type = Opm::CubeGridVanguard; }; // Set the problem property template struct Problem { using type = Opm::PowerInjectionProblem; }; // Set the wetting phase template struct WettingPhase { private: using Scalar = GetPropType; public: using type = Opm::LiquidPhase >; }; // Set the non-wetting phase template struct NonwettingPhase { private: using Scalar = GetPropType; public: using type = Opm::GasPhase >; }; // Set the material Law template struct MaterialLaw { private: using FluidSystem = GetPropType; enum { wettingPhaseIdx = FluidSystem::wettingPhaseIdx }; enum { nonWettingPhaseIdx = FluidSystem::nonWettingPhaseIdx }; using Scalar = GetPropType; using Traits = Opm::TwoPhaseMaterialTraits; // define the material law which is parameterized by effective // saturations using EffectiveLaw = Opm::RegularizedVanGenuchten; public: // define the material law parameterized by absolute saturations using type = Opm::EffToAbsLaw; }; } // namespace Opm::Properties namespace Opm { /*! * \ingroup TestProblems * \brief 1D Problem with very fast injection of gas on the left. * * The velocity model is chosen in the .cc file in this problem. The * spatial parameters are inspired by the ones given by * * V. Jambhekar: "Forchheimer Porous-media Flow models -- Numerical * Investigation and Comparison with Experimental Data", Master's * Thesis at Institute for Modelling Hydraulic and Environmental * Systems, University of Stuttgart, 2011 */ template class PowerInjectionProblem : public GetPropType { using ParentType = GetPropType; using Scalar = GetPropType; using GridView = GetPropType; using Indices = GetPropType; using FluidSystem = GetPropType; using WettingPhase = GetPropType; using NonwettingPhase = GetPropType; using PrimaryVariables = GetPropType; using EqVector = GetPropType; using RateVector = GetPropType; using BoundaryRateVector = GetPropType; using Simulator = GetPropType; enum { // number of phases numPhases = FluidSystem::numPhases, // phase indices wettingPhaseIdx = FluidSystem::wettingPhaseIdx, nonWettingPhaseIdx = FluidSystem::nonWettingPhaseIdx, // equation indices contiNEqIdx = Indices::conti0EqIdx + nonWettingPhaseIdx, // Grid and world dimension dim = GridView::dimension, dimWorld = GridView::dimensionworld }; using MaterialLaw = GetPropType; using MaterialLawParams = GetPropType; using CoordScalar = typename GridView::ctype; using GlobalPosition = Dune::FieldVector; using DimMatrix = Dune::FieldMatrix; public: /*! * \copydoc Doxygen::defaultProblemConstructor */ PowerInjectionProblem(Simulator& simulator) : ParentType(simulator) { } /*! * \copydoc FvBaseProblem::finishInit */ void finishInit() { ParentType::finishInit(); eps_ = 3e-6; FluidSystem::init(); temperature_ = 273.15 + 26.6; // parameters for the Van Genuchten law // alpha and n materialParams_.setVgAlpha(0.00045); materialParams_.setVgN(7.3); materialParams_.finalize(); K_ = this->toDimMatrix_(5.73e-08); // [m^2] setupInitialFluidState_(); } /*! * \copydoc FvBaseMultiPhaseProblem::registerParameters */ static void registerParameters() { ParentType::registerParameters(); Parameters::SetDefault(250); Parameters::SetDefault>(100.0); if constexpr (dim > 1) { Parameters::SetDefault(1); Parameters::SetDefault>(1.0); } if constexpr (dim == 3) { Parameters::SetDefault(1); Parameters::SetDefault>(1.0); } Parameters::SetDefault>(100.0); Parameters::SetDefault>(1e-3); Parameters::SetDefault(true); } /*! * \name Auxiliary methods */ //! \{ /*! * \copydoc FvBaseProblem::name */ std::string name() const { std::ostringstream oss; oss << "powerinjection_"; if (std::is_same, Opm::DarcyFluxModule >::value) oss << "darcy"; else oss << "forchheimer"; if (std::is_same, Properties::TTag::AutoDiffLocalLinearizer>::value) oss << "_" << "ad"; else oss << "_" << "fd"; return oss.str(); } /*! * \copydoc FvBaseProblem::endTimeStep */ void endTimeStep() { #ifndef NDEBUG this->model().checkConservativeness(); // Calculate storage terms EqVector storage; this->model().globalStorage(storage); // Write mass balance information for rank 0 if (this->gridView().comm().rank() == 0) { std::cout << "Storage: " << storage << std::endl << std::flush; } #endif // NDEBUG } //! \} /*! * \name Soil parameters */ //! \{ /*! * \copydoc FvBaseMultiPhaseProblem::intrinsicPermeability */ template const DimMatrix& intrinsicPermeability(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return K_; } /*! * \copydoc ForchheimerBaseProblem::ergunCoefficient */ template Scalar ergunCoefficient(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return 0.3866; } /*! * \copydoc FvBaseMultiPhaseProblem::porosity */ template Scalar porosity(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return 0.558; } /*! * \copydoc FvBaseMultiPhaseProblem::materialLawParams */ template const MaterialLawParams& materialLawParams(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return materialParams_; } /*! * \copydoc FvBaseMultiPhaseProblem::temperature */ template Scalar temperature(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return temperature_; } //! \} /*! * \name Boundary conditions */ //! \{ /*! * \copydoc FvBaseProblem::boundary * * This problem sets a very high injection rate of nitrogen on the * left and a free-flow boundary on the right. */ template void boundary(BoundaryRateVector& values, const Context& context, unsigned spaceIdx, unsigned timeIdx) const { const GlobalPosition& pos = context.pos(spaceIdx, timeIdx); if (onLeftBoundary_(pos)) { RateVector massRate(0.0); massRate = 0.0; massRate[contiNEqIdx] = -1.00; // kg / (m^2 * s) // impose a forced flow boundary values.setMassRate(massRate); } else if (onRightBoundary_(pos)) // free flow boundary with initial condition on the right values.setFreeFlow(context, spaceIdx, timeIdx, initialFluidState_); else values.setNoFlow(); } //! \} /*! * \name Volumetric terms */ //! \{ /*! * \copydoc FvBaseProblem::initial */ template void initial(PrimaryVariables& values, const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { // assign the primary variables values.assignNaive(initialFluidState_); } /*! * \copydoc FvBaseProblem::source * * For this problem, the source term of all components is 0 * everywhere. */ template void source(RateVector& rate, const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { rate = Scalar(0.0); } //! \} private: bool onLeftBoundary_(const GlobalPosition& pos) const { return pos[0] < this->boundingBoxMin()[0] + eps_; } bool onRightBoundary_(const GlobalPosition& pos) const { return pos[0] > this->boundingBoxMax()[0] - eps_; } void setupInitialFluidState_() { initialFluidState_.setTemperature(temperature_); Scalar Sw = 1.0; initialFluidState_.setSaturation(wettingPhaseIdx, Sw); initialFluidState_.setSaturation(nonWettingPhaseIdx, 1 - Sw); Scalar p = 1e5; initialFluidState_.setPressure(wettingPhaseIdx, p); initialFluidState_.setPressure(nonWettingPhaseIdx, p); typename FluidSystem::template ParameterCache paramCache; paramCache.updateAll(initialFluidState_); for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) { initialFluidState_.setDensity(phaseIdx, FluidSystem::density(initialFluidState_, paramCache, phaseIdx)); initialFluidState_.setViscosity(phaseIdx, FluidSystem::viscosity(initialFluidState_, paramCache, phaseIdx)); } } DimMatrix K_; MaterialLawParams materialParams_; Opm::ImmiscibleFluidState initialFluidState_; Scalar temperature_; Scalar eps_; }; } // namespace Opm #endif