/* Copyright 2017 Statoil ASA. 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 3 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 . */ #ifndef OPM_ECLSATURATIONFUNC_HEADER_INCLUDED #define OPM_ECLSATURATIONFUNC_HEADER_INCLUDED #include #include #include #include #include #include /// \file /// /// Public interface to relative permeability evaluation machinery. The /// back-end is aware of ECLIPSE's standard three-phase model for relative /// permeability of oil and the two- and three-point saturation end-point /// scaling options. Vertical scaling of relative permeability is not /// supported at present. namespace Opm { class ECLGraph; class ECLRestartData; class ECLInitFileData; /// Extract phase saturation of single phase for all active cells in all /// grids. /// /// Handles the case of oil saturation being explicitly stored in a /// result set or implicitly defined from the gas and/or water /// saturations. /// /// \param[in] G Connected topology of current model's active cells. /// Needed to linearise phase saturations (e.g., SOIL) that are /// distributed on local grids to all of the model's active cells /// (\code member function G.rawLinearisedCellData() \endcode). /// /// \param[in] rstrt ECLIPSE restart vectors. Result set view /// assumed to be positioned at a particular report step of /// interest. /// /// \param[in] phase Phase for which to extract the phase saturation /// values. /// /// \return Phase saturation values of active phase \p phase for all /// active cells in model \p G. Empty if phase \p phase is not /// actually active in the current result set or if the saturation /// values are not stored on the current report/restart step. std::vector phaseSaturation(const ECLGraph& G, const ECLRestartData& rstrt, const ECLPhaseIndex phase); /// Gateway to engine for computing relative permeability values based /// on tabulated saturation functions in ECL output. class ECLSaturationFunc { public: /// Protocol for describing a particular saturation function /// request. struct RawCurve { /// Which saturation function does this request reference. enum class Function { /// Relative permeability functions RelPerm, /// Capillary pressure CapPress, }; /// Which one-dimensional sub-system does this request reference. enum class SubSystem { /// Oil-Gas subsystem OilGas, /// Oil-Water subsystem OilWater, }; /// Particular saturation function of this request. Function curve; /// Particular sub-system of this request. SubSystem subsys; /// Phase/component for which to form the effective saturation /// function curve. ECLPhaseIndex thisPh; }; struct SatFuncScaling { enum Type : unsigned char { Horizontal = 1 << 0u, Vertical = 1 << 1u, }; SatFuncScaling() : enable(Type::Horizontal | Type::Vertical) {} // Default: Use both Horizontal and Vertical if specified. unsigned char enable; }; /// Constructor /// /// \param[in] G Connected topology of current model's active cells. /// Needed to linearise region mapping (e.g., SATNUM) that is /// distributed on local grids to all of the model's active cells /// (\code member function G.rawLinearisedCellData() \endcode). /// /// \param[in] init Container of tabulated saturation functions and /// saturation table end points, if applicable, for all active /// cells in the model \p G. ECLSaturationFunc(const ECLGraph& G, const ECLInitFileData& init); /// Destructor. ~ECLSaturationFunc(); /// Move constructor. /// /// Subsumes the implementation of an existing object. /// /// \param[in] rhs Existing engine for saturation function /// evaluation. Does not have a valid implementation when the /// constructor completes. ECLSaturationFunc(ECLSaturationFunc&& rhs); /// Copy constructor. /// /// \param[in] rhs Existing engine for saturation function /// evaluation. ECLSaturationFunc(const ECLSaturationFunc& rhs); /// Move assignment operator. /// /// Subsumes the implementation of an existing object. /// /// \param[in] rhs Existing engine for saturation function /// evaluation. Does not have a valid implementation when the /// constructor completes. /// /// \return \code *this \endcode. ECLSaturationFunc& operator=(ECLSaturationFunc&& rhs); /// Assignment operator. /// /// \param[in] rhs Existing engine for saturation function /// evaluation. /// /// \return \code *this \endcode. ECLSaturationFunc& operator=(const ECLSaturationFunc& rhs); /// Define a collection of units of measure for output purposes. /// /// Capillary pressure curves produced by getSatFuncCurve() will be /// reported in the pressure units of this system. If this function /// is never called (or called with null pointer), then the output /// units are implicitly set to the flow-diagnostics module's /// internal units of measurement (meaning all properties and curves /// will be reported in strict SI units). /// /// \param[in] usys Collection of units of measure for output /// purposes. Typically the return value from one of the \code /// *UnitConvention() \endcode functions of the \code ECLUnits /// \endcode namespace. void setOutputUnits(std::unique_ptr usys); /// Compute relative permeability values in all active cells for a /// single phase. /// /// \param[in] G Connected topology of current model's active cells. /// Needed to linearise phase saturations (e.g., SOIL) that are /// distributed on local grids to all of the model's active cells /// (\code member function G.rawLinearisedCellData() \endcode). /// /// \param[in] rstrt ECLIPSE restart vectors. Result set view /// assumed to be positioned at a particular report step of /// interest. /// /// \param[in] p Phase for which to compute relative permeability /// values. /// /// \return Derived relative permeability values of active phase \p /// p for all active cells in model \p G. Empty if phase \p p is /// not actually active in the current result set. std::vector relperm(const ECLGraph& G, const ECLRestartData& rstrt, const ECLPhaseIndex p) const; /// Retrieve 2D graph representations of sequence of effective /// saturation functions in a single cell. /// /// \param[in] func Sequence of saturation function descriptions. /// /// \param[in] activeCell Index of active cell from which to derive /// the effective saturation function. Use member function \code /// ECLGraph::activeCell() \endcode to translate a global cell /// (I,J,K) tuple--relative to a model grid--to a linear active /// cell ID. /// /// \param[in] useEPS Whether or not to include effects of /// saturation end-point scaling. No effect if the INIT result /// set from which the object was constructed does not actually /// include saturation end-point scaling data. Otherwise, /// enables turning EPS off even if associate data is present in /// the INIT result set. /// /// Default value (\c true) means that effects of EPS are /// included if requisite data is present in the INIT result. /// /// \return Sequence of 2D graphs for all saturation function /// requests represented by \p func. In particular, the \c i-th /// element of the result corresponds to input request \code /// func[i] \endcode. Abscissas are stored in \code /// graph[i].first \endcode and ordinates are stored in \code /// graph[i].second \endcode. If a particular request is /// semantically invalid, such as when requesting the water /// relative permeability in the oil-gas system, then the /// corresponding graph in the result is empty. /// /// Example: Retrieve relative permeability curves for oil in active /// cell 2718 in both the oil-gas and oil-water sub-systems while /// excluding effects of end-point scaling. This effectively /// retrieves the "raw" tabulated saturation functions in the /// INIT result set. /// /// \code /// using RC = ECLSaturationFunc::RawCurve; /// auto func = std::vector{}; /// func.reserve(2); /// /// // Request krog (oil rel-perm in oil-gas system) /// func.push_back(RC{ /// RC::Function::RelPerm, /// RC::SubSystem::OilGas, /// ECLPhaseIndex::Liquid /// }); /// /// // Request krow (oil rel-perm in oil-water system) /// func.push_back(RC{ /// RC::Function::RelPerm, /// RC::SubSystem::OilWater, /// ECLPhaseIndex::Liquid /// }); /// /// const auto graph = /// sfunc.getSatFuncCurve(func, 2718, false); /// \endcode std::vector getSatFuncCurve(const std::vector& func, const int activeCell, const bool useEPS = true) const; /// Retrieve 2D graph representations of sequence of effective /// saturation functions in a single cell. /// /// \param[in] func Sequence of saturation function descriptions. /// /// \param[in] activeCell Index of active cell from which to derive /// the effective saturation function. Use member function \code /// ECLGraph::activeCell() \endcode to translate a global cell /// (I,J,K) tuple--relative to a model grid--to a linear active /// cell ID. /// /// \param[in] scaling Which type of saturation function scaling to /// apply. No effect if the INIT result set from which the /// object was constructed does not actually include saturation /// end-point scaling or function value scaling data. Otherwise, /// enables turning various scaling effects on or off even if /// associate data is present in the INIT result set. /// /// \return Sequence of 2D graphs for all saturation function /// requests represented by \p func. In particular, the \c i-th /// element of the result corresponds to input request \code /// func[i] \endcode. Abscissas are stored in \code /// graph[i].first \endcode and ordinates are stored in \code /// graph[i].second \endcode. If a particular request is /// semantically invalid, such as when requesting the water /// relative permeability in the oil-gas system, then the /// corresponding graph in the result is empty. /// /// Example: Retrieve relative permeability curves for oil in active /// cell 2718 in both the oil-gas and oil-water sub-systems /// including effects of vertical scaling only. /// /// \code /// using RC = ECLSaturationFunc::RawCurve; /// auto func = std::vector{}; /// func.reserve(2); /// /// // Request krog (oil rel-perm in oil-gas system) /// func.push_back(RC{ /// RC::Function::RelPerm, /// RC::SubSystem::OilGas, /// ECLPhaseIndex::Liquid /// }); /// /// // Request krow (oil rel-perm in oil-water system) /// func.push_back(RC{ /// RC::Function::RelPerm, /// RC::SubSystem::OilWater, /// ECLPhaseIndex::Liquid /// }); /// /// auto scaling = SatFuncScaling{}; /// scaling.enable = static_cast(0); /// scaling.enable |= SatFuncScaling::Type::Vertical; /// /// const auto graph = /// sfunc.getSatFuncCurve(func, 2718, scaling); /// \endcode std::vector getSatFuncCurve(const std::vector& func, const int activeCell, const SatFuncScaling& scaling) const; private: /// Implementation backend. class Impl; /// Pointer to actual backend/engine object. std::unique_ptr pImpl_; }; } // namespace Opm #endif // OPM_ECLSATURATIONFUNC_HEADER_INCLUDED