opm-common/opm/output/eclipse/Tables.hpp

144 lines
5.6 KiB
C++
Raw Permalink Normal View History

/*
Copyright 2019 Equinor.
Copyright 2017 Statoil ASA.
Copyright 2016 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 <http://www.gnu.org/licenses/>.
*/
#ifndef OUTPUT_TABLES_HPP
#define OUTPUT_TABLES_HPP
#include <vector>
#include <opm/input/eclipse/EclipseState/Tables/FlatTable.hpp>
namespace Opm {
class UnitSystem;
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
class EclipseState;
class Tables {
public:
explicit Tables( const UnitSystem& units);
void addDensity(const DensityTable& density);
/// Add normalised PVT function tables to INIT file's TAB vector.
///
/// \param[in] es Valid \c EclipseState object with accurate RUNSPEC
/// information on active phases and table dimensions ("TABDIMS").
///
/// \param[in] logihead Flag specifications identifying which tables
/// to output.
void addPVTTables(const EclipseState& es);
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
/// Add normalised saturation function tables to INIT file's TAB
/// vector.
///
/// \param[in] es Valid \c EclipseState object with accurate RUNSPEC
/// information on active phases and table dimensions ("TABDIMS").
void addSatFunc(const EclipseState& es);
/// Acquire read-only reference to internal TABDIMS vector.
const std::vector<int>& tabdims() const;
/// Acquire read-only reference to internal TAB vector.
const std::vector<double>& tab() const;
private:
/// Convention for units of measure of the result set.
const UnitSystem& units;
/// Offset and size information for the tabular data.
std::vector<int> m_tabdims;
/// Linearised tabular data of PVT and saturation functions.
std::vector<double> data;
void addData(const std::size_t offset_index,
const std::vector<double>& new_data);
INIT File: Add Support for Writing Saturation Function Tables This commit extends the INIT file Table writing to also output the saturation function tables in normalised form. We support generating the INIT file's SGFN, SOFN, and SWFN tables--including the derivative information--for both two and three phases from both families of saturation function keywords (S{G,W}OF and S{G,W}FN + SOF{2,3}). We do not yet support generating the appropriate tables from input keyword SLGOF. We leverage the LinearisedOutputTable to abstract away some of the details of indexing into the linear 'tab' array and create a helper function to loop across saturation function regions whence each table generator need only be concerned about the specific data pertaining to that region's saturation function (i.e., the values of independent and dependent variates and number of active rows). We allocate the output tables according to information in the TABDIMS keyword, notably the number of saturation nodes (item 3 of TABDIMS). Generating the three-phase SOFN table, which has the same columns as the input table SOF3, in the case of family One (SGOF and SWOF) is slightly involved. In particular we need to join the SGOF and SWOF tables on common oil saturation values and derive/insert missing KroX data through piecewise linear interpolation in the appropriate input table. We defer the details of merging on common (and uniqe) oil saturation values to the standard library routine 'set_union()' which outputs repeated saturation values exactly once rather than for each occurrence. That way we only need to wrap the input tables in a simple class to facilitate look-up of oil saturation values and the mechanics of piecewise linear interpolation of the relative permeability column for oil. Due to this merging process, the number of rows in SOFN is twice the number of saturation nodes in this case. Since this support depends on being able to determine which phases are active in a particular run, what table sizes to use for the output and which keywords are being used to represent the saturation function tables we introduce a single new public member function void Tables::addSatFunc(const EclipseState& es) This function determines the run's active phases and dispatches to the new helper functions void Tables::addSatFunc_FamilyOne() void Tables::addSatFunc_FamilyTwo() according to which keyword family exists in the input deck. These functions in turn call additional helper functions to handle each phase table separately. For instance addSatFunc_FamilyOne() uses the helper function SatFunc::Oil::ThreePhase::fromSGOFandSWOF() to generate a three-phase SOFN table based on the information in the SGOF and SWOF tables. Information about slopes/derivatives for the piecewise interpolants of the dependent variates is computed through the helper function DifferentiateOutputTable::calcSlopes() whence the first entry of each derivative column is undefined (i.e., assigned the sentinel value 1e+20). This should arguably be zero instead. Further testing and comparison with INIT result sets generated by ECL will inform the decision here. We add unit tests for all combinations of number of active phases (two or three) and which saturation function keyword family is present in the simulation case. The unit tests use the tables from SPE 9 for keyword family One and the tables from SPE 1 for keyword family Two. Comparison data is extracted directly from the ECL INIT file in the case of the SPE 9 tables and derived from independent calculation for the SPE 1 tables.
2017-11-16 09:34:05 -06:00
/// Add saturation function tables corresponding to family I (SGOF,
/// SWOF) to the tabular data (TABDIMS and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
///
/// \param[in] gas Whether or not gas is active the current run.
///
/// \param[in] oil Whether or not oil is active the current run.
///
/// \param[in] wat Whether or not water is active the current run.
void addSatFunc_FamilyOne(const EclipseState& es,
const bool gas,
const bool oil,
const bool wat);
/// Add saturation function tables corresponding to family II (SGFN,
/// SOF{2,3}, SWFN) to the tabular data (TABDIMS and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
///
/// \param[in] gas Whether or not gas is active the current run.
///
/// \param[in] oil Whether or not oil is active the current run.
///
/// \param[in] wat Whether or not water is active the current run.
void addSatFunc_FamilyTwo(const EclipseState& es,
const bool gas,
const bool oil,
const bool wat);
/// Add saturation function tables corresponding to family III (WSF,
/// GSF) to the tabular data (TABDIMS and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
///
void addSatFunc_FamilyThree(const EclipseState& es);
/// Add gas PVT tables (keywords PVDG and PVTG) to the tabular data
/// (TABDIMS and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
void addGasPVTTables(const EclipseState& es);
/// Add oil PVT tables (keywords PVCDO, PVDO and PVTO) to the
/// tabular data (TABDIMS and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
void addOilPVTTables(const EclipseState& es);
/// Add water PVT tables (keyword PVTW) to the tabular data (TABDIMS
/// and TAB vectors).
///
/// \param[in] es Valid \c EclipseState object with accurate table
/// dimensions ("TABDIMS" keyword) and an initialised \c
/// TableManager sub-object.
void addWaterPVTTables(const EclipseState& es);
};
}
#endif // OUTPUT_TABLES_HPP