// -*- 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::DiffusionProblem */ #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 namespace Opm { template class DiffusionProblem; } namespace Opm::Properties { namespace TTag { struct DiffusionBaseProblem {}; } // namespace TTag // 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::DiffusionProblem; }; // Set the fluid system template struct FluidSystem { private: using Scalar = GetPropType; public: using type = Opm::H2ON2FluidSystem; }; // Set the material Law template struct MaterialLaw { private: using Scalar = GetPropType; using FluidSystem = GetPropType; static_assert(FluidSystem::numPhases == 2, "A fluid system with two phases is required " "for this problem!"); using Traits = Opm::TwoPhaseMaterialTraits; public: using type = Opm::LinearMaterial; }; // Enable molecular diffusion for this problem template struct EnableDiffusion { static constexpr bool value = true; }; } // namespace Opm::Properties namespace Opm { /*! * \ingroup TestProblems * \brief 1D problem which is driven by molecular diffusion. * * The domain is one meter long and completely filled with gas and * closed on all boundaries. Its left half exhibits a slightly higher * water concentration than the right one. After a while, the * concentration of water will be equilibrate due to molecular * diffusion. */ template class DiffusionProblem : public GetPropType { using ParentType = GetPropType; using Scalar = GetPropType; using GridView = GetPropType; using FluidSystem = GetPropType; using PrimaryVariables = GetPropType; using Simulator = GetPropType; using Model = GetPropType; enum { // number of phases numPhases = FluidSystem::numPhases, // phase indices liquidPhaseIdx = FluidSystem::liquidPhaseIdx, gasPhaseIdx = FluidSystem::gasPhaseIdx, // component indices H2OIdx = FluidSystem::H2OIdx, N2Idx = FluidSystem::N2Idx, // Grid and world dimension dim = GridView::dimension, dimWorld = GridView::dimensionworld }; using EqVector = GetPropType; using RateVector = GetPropType; using BoundaryRateVector = GetPropType; using MaterialLaw = GetPropType; using MaterialLawParams = GetPropType; using CoordScalar = typename GridView::ctype; using GlobalPosition = Dune::FieldVector; using DimMatrix = Dune::FieldMatrix; public: /*! * \copydoc Doxygen::defaultProblemConstructor */ DiffusionProblem(Simulator& simulator) : ParentType(simulator) { } /*! * \copydoc FvBaseProblem::finishInit */ void finishInit() { ParentType::finishInit(); FluidSystem::init(); temperature_ = 273.15 + 20.0; materialParams_.finalize(); K_ = this->toDimMatrix_(1e-12); // [m^2] setupInitialFluidStates_(); } /*! * \copydoc FvBaseMultiPhaseProblem::registerParameters */ static void registerParameters() { ParentType::registerParameters(); Parameters::SetDefault(250); if constexpr (dim > 1) { Parameters::SetDefault(1); } if constexpr (dim == 3) { Parameters::SetDefault(1); } Parameters::SetDefault>(1e6); Parameters::SetDefault>(1000); } /*! * \name Auxiliary methods */ //! \{ /*! * \copydoc FvBaseProblem::name */ std::string name() const { return std::string("diffusion_") + Model::name(); } /*! * \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 FvBaseMultiPhaseProblem::porosity */ template Scalar porosity(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { return 0.35; } /*! * \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 no-flow boundaries everywhere. */ template void boundary(BoundaryRateVector& values, const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const { values.setNoFlow(); } //! \} /*! * \name Volumetric terms */ //! \{ /*! * \copydoc FvBaseProblem::initial */ template void initial(PrimaryVariables& values, const Context& context, unsigned spaceIdx, unsigned timeIdx) const { const auto& pos = context.pos(spaceIdx, timeIdx); if (onLeftSide_(pos)) values.assignNaive(leftInitialFluidState_); else values.assignNaive(rightInitialFluidState_); } /*! * \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 onLeftSide_(const GlobalPosition& pos) const { return pos[0] < (this->boundingBoxMin()[0] + this->boundingBoxMax()[0]) / 2; } void setupInitialFluidStates_() { // create the initial fluid state for the left half of the domain leftInitialFluidState_.setTemperature(temperature_); Scalar Sl = 0.0; leftInitialFluidState_.setSaturation(liquidPhaseIdx, Sl); leftInitialFluidState_.setSaturation(gasPhaseIdx, 1 - Sl); Scalar p = 1e5; leftInitialFluidState_.setPressure(liquidPhaseIdx, p); leftInitialFluidState_.setPressure(gasPhaseIdx, p); Scalar xH2O = 0.01; leftInitialFluidState_.setMoleFraction(gasPhaseIdx, H2OIdx, xH2O); leftInitialFluidState_.setMoleFraction(gasPhaseIdx, N2Idx, 1 - xH2O); using CFRP = Opm::ComputeFromReferencePhase; typename FluidSystem::template ParameterCache paramCache; CFRP::solve(leftInitialFluidState_, paramCache, gasPhaseIdx, /*setViscosity=*/false, /*setEnthalpy=*/false); // create the initial fluid state for the right half of the domain rightInitialFluidState_.assign(leftInitialFluidState_); xH2O = 0.0; rightInitialFluidState_.setMoleFraction(gasPhaseIdx, H2OIdx, xH2O); rightInitialFluidState_.setMoleFraction(gasPhaseIdx, N2Idx, 1 - xH2O); CFRP::solve(rightInitialFluidState_, paramCache, gasPhaseIdx, /*setViscosity=*/false, /*setEnthalpy=*/false); } DimMatrix K_; MaterialLawParams materialParams_; Opm::CompositionalFluidState leftInitialFluidState_; Opm::CompositionalFluidState rightInitialFluidState_; Scalar temperature_; }; } // namespace Opm #endif