Added keywords PVTWSALT and modified SALTVD, WSALT and BDENSITY for a simple salt/brine implementation

This commit is contained in:
Trine S. Mykkeltvedt
2019-08-28 11:20:25 +02:00
committed by Tor Harald Sandve
parent 5fd756699e
commit aa19f38a54
24 changed files with 747 additions and 18 deletions

View File

@@ -128,6 +128,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellFoamProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellSaltwaterProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTracerProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp
@@ -148,6 +149,8 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Tables/Tables.cpp
src/opm/parser/eclipse/EclipseState/Tables/Rock2dTable.cpp
src/opm/parser/eclipse/EclipseState/Tables/Rock2dtrTable.cpp
src/opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.cpp
src/opm/parser/eclipse/EclipseState/Tables/BrineDensityTable.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQASTNode.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParser.cpp
@@ -321,6 +324,7 @@ if(ENABLE_ECL_INPUT)
tests/parser/RestartConfigTests.cpp
tests/parser/RockTableTests.cpp
tests/parser/RunspecTests.cpp
tests/parser/SaltTableTests.cpp
tests/parser/SatfuncPropertyInitializersTests.cpp
tests/parser/ScheduleTests.cpp
tests/parser/SectionTests.cpp
@@ -537,6 +541,8 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Tables/Regdims.hpp
opm/parser/eclipse/EclipseState/Tables/Eqldims.hpp
opm/parser/eclipse/EclipseState/Tables/SpecrockTable.hpp
opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.hpp
opm/parser/eclipse/EclipseState/Tables/BrineDensityTable.hpp
opm/parser/eclipse/EclipseState/Tables/PlydhflfTable.hpp
opm/parser/eclipse/EclipseState/Tables/PlymwinjTable.hpp
opm/parser/eclipse/EclipseState/Tables/PlyshlogTable.hpp
@@ -621,6 +627,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellEconProductionLimits.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellFoamProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellSaltwaterProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp

View File

@@ -39,11 +39,12 @@ enum class Phase {
POLYMER = 4,
ENERGY = 5,
POLYMW = 6,
FOAM = 7
FOAM = 7,
SALTWATER = 8
// If you add more entries to this enum, remember to update NUM_PHASES_IN_ENUM below.
};
constexpr int NUM_PHASES_IN_ENUM = static_cast<int>(Phase::FOAM) + 1; // Used to get correct size of the bitset in class Phases.
constexpr int NUM_PHASES_IN_ENUM = static_cast<int>(Phase::SALTWATER) + 1; // Used to get correct size of the bitset in class Phases.
Phase get_phase( const std::string& );
std::ostream& operator<<( std::ostream&, const Phase& );
@@ -52,7 +53,7 @@ class Phases {
public:
Phases() noexcept = default;
Phases( bool oil, bool gas, bool wat, bool solvent = false, bool polymer = false, bool energy = false,
bool polymw = false, bool foam = false ) noexcept;
bool polymw = false, bool foam = false, bool saltwater = false ) noexcept;
Phases(const std::bitset<NUM_PHASES_IN_ENUM>& bbits);
unsigned long getBits() const;

View File

@@ -338,6 +338,7 @@ namespace Opm
void handleWCONINJE( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWFOAM( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWPOLYMER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWSALT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWSOLVENT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWTRACER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
void handleWTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);

View File

@@ -30,6 +30,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Well/ProductionControls.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/InjectionControls.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellFoamProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellSaltwaterProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTracerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellEconProductionLimits.hpp>
@@ -453,6 +454,7 @@ public:
const WellEconProductionLimits& getEconLimits() const;
const WellFoamProperties& getFoamProperties() const;
const WellPolymerProperties& getPolymerProperties() const;
const WellSaltwaterProperties& getSaltwaterProperties() const;
const WellTracerProperties& getTracerProperties() const;
const WellConnections& getConnections() const;
const WellSegments& getSegments() const;
@@ -504,6 +506,7 @@ public:
bool updateTracer(std::shared_ptr<WellTracerProperties> tracer_properties);
bool updateFoamProperties(std::shared_ptr<WellFoamProperties> foam_properties);
bool updatePolymerProperties(std::shared_ptr<WellPolymerProperties> polymer_properties);
bool updateSaltwaterProperties(std::shared_ptr<WellSaltwaterProperties> saltwater_properties);
bool updateEconLimits(std::shared_ptr<WellEconProductionLimits> econ_limits);
bool updateProduction(std::shared_ptr<WellProductionProperties> production);
bool updateInjection(std::shared_ptr<WellInjectionProperties> injection);
@@ -557,6 +560,7 @@ private:
std::shared_ptr<const WellEconProductionLimits> econ_limits;
std::shared_ptr<const WellFoamProperties> foam_properties;
std::shared_ptr<const WellPolymerProperties> polymer_properties;
std::shared_ptr<const WellSaltwaterProperties> saltwater_properties;
std::shared_ptr<const WellTracerProperties> tracer_properties;
std::shared_ptr<WellConnections> connections; // The WellConnections object can not be const because of the filterConnections method - would be beneficial to rewrite to enable const
std::shared_ptr<const WellProductionProperties> production;

View File

@@ -0,0 +1,37 @@
/*
Copyright 2019 by Norce.
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 OPM_WELLSALTWATERPROPERTIES_HEADER_INCLUDED
#define OPM_WELLSALTWATERPROPERTIES_HEADER_INCLUDED
namespace Opm
{
class DeckRecord;
struct WellSaltwaterProperties
{
double m_saltwaterConcentration = 0.0;
void handleWSALT(const DeckRecord& rec);
bool operator!=(const WellSaltwaterProperties& other) const;
};
} // namespace Opm
#endif // OPM_WELLSALTWATERPROPERTIES_HEADER_INCLUDED

View File

@@ -0,0 +1,38 @@
/*
Copyright (C) 2015 Statoil ASA.
2015 IRIS AS
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 OPM_PARSER_BRINEDENSITY_TABLE_HPP
#define OPM_PARSER_BRINEDENSITY_TABLE_HPP
namespace Opm {
class DeckItem;
class BrineDensityTable {
public:
BrineDensityTable();
void init(const Opm::DeckRecord& record);
const std::vector<double>& getBrineDensityColumn() const;
private:
std::vector<double> m_tableValues;
};
}
#endif

View File

@@ -0,0 +1,53 @@
/*
Copyright (C) 2019 by Norce
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 OPM_PARSER_PVTWSALT_TABLE_HPP
#define OPM_PARSER_PVTWSALT_TABLE_HPP
#include <vector>
namespace Opm {
class DeckKeyword;
class PvtwsaltTable {
public:
PvtwsaltTable();
void init(const Opm::DeckRecord& record0, const Opm::DeckRecord& record1);
size_t size() const;
std::vector<double> getSaltConcentrationColumn() const;
std::vector<double> getFormationVolumeFactorColumn() const;
std::vector<double> getCompressibilityColumn() const;
std::vector<double> getViscosityColumn() const;
std::vector<double> getViscosibilityColumn() const;
double getReferencePressureValue() const;
double getReferenceSaltConcentrationValue() const;
protected:
double m_pRefValues;
double m_saltConsRefValues;
std::vector <double> m_tableValues;
};
}
#endif

View File

@@ -0,0 +1,37 @@
/*
Copyright (C) 2019 by Norce.
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 OPM_PARSER_SALTVD_TABLE_HPP
#define OPM_PARSER_SALTVD_TABLE_HPP
#include "SimpleTable.hpp"
namespace Opm {
class DeckItem;
class SaltvdTable : public SimpleTable {
public:
SaltvdTable( const DeckItem& item );
const TableColumn& getDepthColumn() const;
const TableColumn& getSaltColumn() const;
};
}
#endif

View File

@@ -34,6 +34,9 @@
#include <opm/parser/eclipse/EclipseState/Tables/PvtoTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/Rock2dTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/Rock2dtrTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/BrineDensityTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/FlatTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SorwmisTable.hpp>
@@ -111,6 +114,7 @@ namespace Opm {
const TableContainer& getRvvdTables() const;
const TableContainer& getPbvdTables() const;
const TableContainer& getPdvdTables() const;
const TableContainer& getSaltvdTables() const;
const TableContainer& getEnkrvdTables() const;
const TableContainer& getEnptvdTables() const;
const TableContainer& getImkrvdTables() const;
@@ -152,6 +156,9 @@ namespace Opm {
const TableContainer& getOverburdTables() const;
const PvtwTable& getPvtwTable() const;
const std::vector<PvtwsaltTable>& getPvtwSaltTables() const;
const std::vector<BrineDensityTable>& getBrineDensityTables() const;
const PvcdoTable& getPvcdoTable() const;
const DensityTable& getDensityTable() const;
const RockTable& getRockTable() const;
@@ -235,6 +242,38 @@ namespace Opm {
}
template <class TableType>
void initPvtwsaltTables(const Deck& deck, std::vector<TableType>& pvtwtables ) {
size_t numTables = m_tabdims.getNumPVTTables();
pvtwtables.resize(numTables);
const auto& keyword = deck.getKeyword("PVTWSALT");
size_t numEntries = keyword.size();
size_t regionIdx = 0;
for (unsigned lineIdx = 0; lineIdx < numEntries; ++lineIdx) {
pvtwtables[regionIdx].init(keyword.getRecord(lineIdx), keyword.getRecord(lineIdx+1));
++regionIdx;
++lineIdx;
}
assert(regionIdx == numTables);
}
template <class TableType>
void initBrineTables(const Deck& deck, std::vector<TableType>& brinetables ) {
size_t numTables = m_tabdims.getNumPVTTables();
brinetables.resize(numTables);
const auto& keyword = deck.getKeyword("BDENSITY");
size_t numEntries = keyword.size();
assert(numEntries == numTables);
for (unsigned lineIdx = 0; lineIdx < numEntries; ++lineIdx) {
brinetables[lineIdx].init(keyword.getRecord(lineIdx));
}
}
/**
* JFUNC
*/
@@ -371,6 +410,8 @@ namespace Opm {
RockTable m_rockTable;
ViscrefTable m_viscrefTable;
WatdentTable m_watdentTable;
std::vector<PvtwsaltTable> m_pvtwsaltTables;
std::vector<BrineDensityTable> m_bdensityTables;
std::map<int, PlymwinjTable> m_plymwinjTables;
std::map<int, SkprwatTable> m_skprwatTables;
std::map<int, SkprpolyTable> m_skprpolyTables;

View File

@@ -35,6 +35,7 @@ Phase get_phase( const std::string& str ) {
if( str == "ENERGY" ) return Phase::ENERGY;
if( str == "POLYMW" ) return Phase::POLYMW;
if( str == "FOAM" ) return Phase::FOAM;
if( str == "SALTWATER" ) return Phase::SALTWATER;
throw std::invalid_argument( "Unknown phase '" + str + "'" );
}
@@ -49,6 +50,7 @@ std::ostream& operator<<( std::ostream& stream, const Phase& p ) {
case Phase::ENERGY: return stream << "ENERGY";
case Phase::POLYMW: return stream << "POLYMW";
case Phase::FOAM: return stream << "FOAM";
case Phase::SALTWATER: return stream << "SALTWATER";
}
@@ -57,7 +59,7 @@ std::ostream& operator<<( std::ostream& stream, const Phase& p ) {
using un = std::underlying_type< Phase >::type;
Phases::Phases( bool oil, bool gas, bool wat, bool sol, bool pol, bool energy, bool polymw, bool foam ) noexcept :
Phases::Phases( bool oil, bool gas, bool wat, bool sol, bool pol, bool energy, bool polymw, bool foam, bool saltwater) noexcept :
bits( (oil ? (1 << static_cast< un >( Phase::OIL ) ) : 0) |
(gas ? (1 << static_cast< un >( Phase::GAS ) ) : 0) |
(wat ? (1 << static_cast< un >( Phase::WATER ) ) : 0) |
@@ -65,7 +67,8 @@ Phases::Phases( bool oil, bool gas, bool wat, bool sol, bool pol, bool energy, b
(pol ? (1 << static_cast< un >( Phase::POLYMER ) ) : 0) |
(energy ? (1 << static_cast< un >( Phase::ENERGY ) ) : 0) |
(polymw ? (1 << static_cast< un >( Phase::POLYMW ) ) : 0) |
(foam ? (1 << static_cast< un >( Phase::FOAM ) ) : 0) )
(foam ? (1 << static_cast< un >( Phase::FOAM ) ) : 0) |
(saltwater ? (1 << static_cast< un >( Phase::SALTWATER ) ) : 0) )
{}
@@ -239,7 +242,8 @@ Runspec::Runspec( const Deck& deck ) :
deck.hasKeyword( "POLYMER" ),
deck.hasKeyword( "THERMAL" ),
deck.hasKeyword( "POLYMW" ),
deck.hasKeyword( "FOAM" ) ) ),
deck.hasKeyword( "FOAM" ),
deck.hasKeyword( "BRINE" ) ) ),
m_tabdims( deck ),
endscale( deck ),
welldims( deck ),

View File

@@ -63,6 +63,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellSaltwaterProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/Units/Dimension.hpp>
@@ -341,6 +342,9 @@ namespace {
else if (keyword.name() == "WPOLYMER")
handleWPOLYMER(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "WSALT")
handleWSALT(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "WSOLVENT")
handleWSOLVENT(keyword, currentStep, parseContext, errors);
@@ -1105,6 +1109,25 @@ namespace {
}
}
void Schedule::handleWSALT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors) {
for (const auto& record : keyword) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
const auto well_names = wellNames(wellNamePattern, currentStep );
if (well_names.empty())
invalidNamePattern(wellNamePattern, parseContext, errors, keyword);
for (const auto& well_name : well_names) {
const auto& dynamic_state = this->wells_static.at(well_name);
auto well2 = std::make_shared<Well>(*dynamic_state[currentStep]);
auto saltwater_properties = std::make_shared<WellSaltwaterProperties>(well2->getSaltwaterProperties());
saltwater_properties->handleWSALT(record);
if (well2->updateSaltwaterProperties(saltwater_properties))
this->updateWell(well2, currentStep);
}
}
}
void Schedule::handleWPMITAB( const DeckKeyword& keyword, const size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors) {

View File

@@ -126,6 +126,7 @@ Well::Well(const std::string& wname_arg,
econ_limits(std::make_shared<WellEconProductionLimits>()),
foam_properties(std::make_shared<WellFoamProperties>()),
polymer_properties(std::make_shared<WellPolymerProperties>()),
saltwater_properties(std::make_shared<WellSaltwaterProperties>()),
tracer_properties(std::make_shared<WellTracerProperties>()),
connections(std::make_shared<WellConnections>(headI, headJ)),
production(std::make_shared<WellProductionProperties>(wname)),
@@ -241,6 +242,19 @@ bool Well::updatePolymerProperties(std::shared_ptr<WellPolymerProperties> polyme
return false;
}
bool Well::updateSaltwaterProperties(std::shared_ptr<WellSaltwaterProperties> saltwater_properties_arg) {
if (this->producer) {
throw std::runtime_error("Not allowed to set saltwater injection properties for well " + name() +
" since it is a production well");
}
if (*this->saltwater_properties != *saltwater_properties_arg) {
this->saltwater_properties = saltwater_properties_arg;
return true;
}
return false;
}
bool Well::updateEconLimits(std::shared_ptr<WellEconProductionLimits> econ_limits_arg) {
if (*this->econ_limits != *econ_limits_arg) {
@@ -556,6 +570,9 @@ const WellPolymerProperties& Well::getPolymerProperties() const {
return *this->polymer_properties;
}
const WellSaltwaterProperties& Well::getSaltwaterProperties() const {
return *this->saltwater_properties;
}
const WellTracerProperties& Well::getTracerProperties() const {
return *this->tracer_properties;
@@ -833,6 +850,8 @@ double Well::production_rate(const SummaryState& st, Phase prod_phase) const {
throw std::invalid_argument( "Production of 'POLYMW' requested.");
case Phase::FOAM:
throw std::invalid_argument( "Production of 'FOAM' requested.");
case Phase::SALTWATER:
throw std::invalid_argument( "Production of 'SALTWATER' requested.");
}
throw std::logic_error( "Unreachable state. Invalid Phase value. "

View File

@@ -0,0 +1,33 @@
/*
Copyright 2019 by Norce.
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/>.
*/
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellSaltwaterProperties.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
void Opm::WellSaltwaterProperties::handleWSALT(const DeckRecord& rec)
{
this->m_saltwaterConcentration = rec.getItem("CONCENTRATION").get<UDAValue>(0).get<double>();
}
bool Opm::WellSaltwaterProperties::operator!=(const WellSaltwaterProperties& other) const
{
return this->m_saltwaterConcentration != other.m_saltwaterConcentration;
}

View File

@@ -0,0 +1,117 @@
/*
Copyright (C) 2019 by Norce
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/>.
*/
#include <vector>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.hpp>
namespace Opm {
static const size_t numEntries = 5;
PvtwsaltTable::PvtwsaltTable()
{
}
void PvtwsaltTable::init(const Opm::DeckRecord& record0, const Opm::DeckRecord& record1)
{
m_pRefValues = record0.getItem("P_REF").getSIDoubleData()[0];
m_saltConsRefValues = record0.getItem("SALT_CONCENTRATION_REF").getSIDoubleData()[0];
m_tableValues = record1.getItem("DATA").getSIDoubleData();
}
size_t PvtwsaltTable::size() const
{
return m_tableValues.size()/numEntries;
}
double PvtwsaltTable::getReferencePressureValue() const
{
return m_pRefValues;
}
double PvtwsaltTable::getReferenceSaltConcentrationValue() const
{
return m_saltConsRefValues;
}
std::vector<double> PvtwsaltTable::getSaltConcentrationColumn() const
{
size_t tableindex = 0;
std::vector<double> saltCons(this->size());
for(size_t i=0; i<this->size(); ++i){
saltCons[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return saltCons;
}
std::vector<double> PvtwsaltTable::getFormationVolumeFactorColumn() const
{
size_t tableindex = 1;
std::vector<double> formationvolumefactor(this->size());
for(size_t i=0; i<this->size(); ++i){
formationvolumefactor[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return formationvolumefactor;
}
std::vector<double> PvtwsaltTable::getCompressibilityColumn() const
{
size_t tableindex = 2;
std::vector<double> compresibility(this->size());
for(size_t i=0; i<this->size(); ++i){
compresibility[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return compresibility;
}
std::vector<double> PvtwsaltTable::getViscosityColumn() const
{
size_t tableindex = 3;
std::vector<double> viscosity(this->size());
for(size_t i=0; i<this->size(); ++i){
viscosity[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return viscosity;
}
std::vector<double> PvtwsaltTable::getViscosibilityColumn() const
{
size_t tableindex = 4;
std::vector<double> viscosibility(this->size());
for(size_t i=0; i<this->size(); ++i){
viscosibility[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return viscosibility;
}
}

View File

@@ -0,0 +1,44 @@
/*
Copyright (C) 2019 by Norce
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/>.
*/
#include <vector>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/BrineDensityTable.hpp>
namespace Opm {
BrineDensityTable::BrineDensityTable()
{
}
void BrineDensityTable::init(const Opm::DeckRecord& record )
{
m_tableValues = record.getItem("BRINE_DENSITY").getSIDoubleData();
}
const std::vector<double>& BrineDensityTable::getBrineDensityColumn() const
{
return m_tableValues;
}
}

View File

@@ -0,0 +1,117 @@
/*
Copyright (C) 2019 by Norce
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/>.
*/
#include <vector>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.hpp>
namespace Opm {
static const size_t numEntries = 5;
PvtwsaltTable::PvtwsaltTable()
{
}
void PvtwsaltTable::init(const Opm::DeckRecord& record0, const Opm::DeckRecord& record1)
{
m_pRefValues = record0.getItem("P_REF").getSIDoubleData()[0];
m_saltConsRefValues = record0.getItem("SALT_CONCENTRATION_REF").getSIDoubleData()[0];
m_tableValues = record1.getItem("DATA").getSIDoubleData();
}
size_t PvtwsaltTable::size() const
{
return m_tableValues.size()/numEntries;
}
double PvtwsaltTable::getReferencePressureValue() const
{
return m_pRefValues;
}
double PvtwsaltTable::getReferenceSaltConcentrationValue() const
{
return m_saltConsRefValues;
}
std::vector<double> PvtwsaltTable::getSaltConcentrationColumn() const
{
size_t tableindex = 0;
std::vector<double> saltCons(this->size());
for(size_t i=0; i<this->size(); ++i){
saltCons[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return saltCons;
}
std::vector<double> PvtwsaltTable::getFormationVolumeFactorColumn() const
{
size_t tableindex = 1;
std::vector<double> formationvolumefactor(this->size());
for(size_t i=0; i<this->size(); ++i){
formationvolumefactor[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return formationvolumefactor;
}
std::vector<double> PvtwsaltTable::getCompressibilityColumn() const
{
size_t tableindex = 2;
std::vector<double> compresibility(this->size());
for(size_t i=0; i<this->size(); ++i){
compresibility[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return compresibility;
}
std::vector<double> PvtwsaltTable::getViscosityColumn() const
{
size_t tableindex = 3;
std::vector<double> viscosity(this->size());
for(size_t i=0; i<this->size(); ++i){
viscosity[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return viscosity;
}
std::vector<double> PvtwsaltTable::getViscosibilityColumn() const
{
size_t tableindex = 4;
std::vector<double> viscosibility(this->size());
for(size_t i=0; i<this->size(); ++i){
viscosibility[i] = m_tableValues[tableindex];
tableindex = tableindex+numEntries;
}
return viscosibility;
}
}

View File

@@ -36,6 +36,7 @@
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/S.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/BrineDensityTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/EnkrvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/EnptvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/GasvisctTable.hpp>
@@ -65,6 +66,7 @@
#include <opm/parser/eclipse/EclipseState/Tables/PdvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/RtempvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/RvvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SaltvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgcwmisTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp>
@@ -162,6 +164,7 @@ namespace Opm {
initSimpleTables( deck );
initFullTables(deck, "PVTG", m_pvtgTables);
initFullTables(deck, "PVTO", m_pvtoTables);
if( deck.hasKeyword( "PVTW" ) )
this->m_pvtwTable = PvtwTable( deck.getKeyword( "PVTW" ) );
@@ -191,6 +194,14 @@ namespace Opm {
if ( deck.hasKeyword( "ROCK2DTR") )
initRockTables(deck, "ROCK2DTR", m_rock2dtrTables );
if ( deck.hasKeyword( "PVTWSALT") )
initPvtwsaltTables(deck, m_pvtwsaltTables );
if ( deck.hasKeyword( "BDENSITY") )
initBrineTables(deck, m_bdensityTables );
}
TableManager& TableManager::operator=(const TableManager& data) {
@@ -290,6 +301,7 @@ namespace Opm {
}
void TableManager::initSimpleTables(const Deck& deck) {
addTables( "SWOF" , m_tabdims.getNumSatTables() );
addTables( "SGWFN", m_tabdims.getNumSatTables() );
addTables( "SGOF", m_tabdims.getNumSatTables() );
@@ -325,6 +337,7 @@ namespace Opm {
addTables( "RVVD", m_eqldims->getNumEquilRegions());
addTables( "PBVD", m_eqldims->getNumEquilRegions());
addTables( "PDVD", m_eqldims->getNumEquilRegions());
addTables( "SALTVD", m_eqldims->getNumEquilRegions());
addTables( "AQUTAB", m_aqudims.getNumInfluenceTablesCT());
{
@@ -387,6 +400,7 @@ namespace Opm {
initSimpleTableContainer<RvvdTable>(deck, "RVVD" , m_eqldims->getNumEquilRegions());
initSimpleTableContainer<PbvdTable>(deck, "PBVD" , m_eqldims->getNumEquilRegions());
initSimpleTableContainer<PdvdTable>(deck, "PDVD" , m_eqldims->getNumEquilRegions());
initSimpleTableContainer<SaltvdTable>(deck, "SALTVD" , m_eqldims->getNumEquilRegions());
initSimpleTableContainer<AqutabTable>(deck, "AQUTAB" , m_aqudims.getNumInfluenceTablesCT());
{
size_t numEndScaleTables = ParserKeywords::ENDSCALE::NUM_TABLES::defaultValue;
@@ -767,6 +781,10 @@ namespace Opm {
return getTables("PDVD");
}
const TableContainer& TableManager::getSaltvdTables() const {
return getTables("SALTVD");
}
const TableContainer& TableManager::getEnkrvdTables() const {
return getTables("ENKRVD");
}
@@ -889,6 +907,14 @@ namespace Opm {
return this->m_pvtwTable;
}
const std::vector<PvtwsaltTable>& TableManager::getPvtwSaltTables() const {
return this->m_pvtwsaltTables;
}
const std::vector<BrineDensityTable>& TableManager::getBrineDensityTables() const {
return this->m_bdensityTables;
}
const PvcdoTable& TableManager::getPvcdoTable() const {
return this->m_pvcdoTable;
}

View File

@@ -61,6 +61,7 @@
#include <opm/parser/eclipse/EclipseState/Tables/RvvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PbvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PdvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SaltvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgcwmisTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp>
@@ -900,6 +901,21 @@ const TableColumn& PdvdTable::getPdewColumn() const {
return SimpleTable::getColumn(1);
}
SaltvdTable::SaltvdTable( const DeckItem& item ) {
m_schema.addColumn( ColumnSchema( "DEPTH" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE ));
m_schema.addColumn( ColumnSchema( "SALT" , Table::RANDOM , Table::DEFAULT_NONE ));
SimpleTable::init(item);
}
const TableColumn& SaltvdTable::getDepthColumn() const {
return SimpleTable::getColumn(0);
}
const TableColumn& SaltvdTable::getSaltColumn() const {
return SimpleTable::getColumn(1);
}
AqutabTable::AqutabTable( const DeckItem& item ) {
m_schema.addColumn( ColumnSchema( "TD" , Table::STRICTLY_INCREASING , Table::DEFAULT_NONE ) );
m_schema.addColumn( ColumnSchema( "PD" , Table::RANDOM , Table::DEFAULT_LINEAR ) );

View File

@@ -1,5 +1,3 @@
{"name" : "BDENSITY" , "sections" : ["PROPS"] , "size" : {"keyword" : "TABDIMS" , "item" : "NTPVT"} , "items" :
[
{"name" : "DATA" , "value_type":"DOUBLE" , "size_type":"ALL", "dimension" : "Mass/LiquidSurfaceVolume"}
]
}
{"name" : "BDENSITY", "sections" : ["PROPS"], "size" : {"keyword":"TABDIMS", "item":"NTPVT" }, "records" :
[[{"name": "BRINE_DENSITY" , "value_type" : "DOUBLE" ,"size_type" : "ALL" , "dimension" : "Density"}]
]}

View File

@@ -1 +1 @@
{"name" : "BRINE" , "sections" : ["RUNSPEC"], "data" : {"value_type" : "STRING" }}
{"name" : "BRINE" , "sections" : ["RUNSPEC"]}

View File

@@ -1,4 +1,5 @@
{"name" : "SALTVD" ,
"sections" : ["SOLUTION"],
"size" : {"keyword" : "EQLDIMS", "item" : "NTEQUL"},
"items" : [{"name" : "DATA", "value_type" : "DOUBLE", "size_type" : "ALL"}]}
{"name" : "SALTVD" , "sections" : ["SOLUTION"], "size" : {"keyword" : "EQLDIMS" , "item" : "NTEQUL"},
"items" : [{"name" : "DATA" ,
"value_type" : "DOUBLE" ,
"size_type" : "ALL",
"dimension" : ["Length" , "Density"]}]}

View File

@@ -1,5 +1,5 @@
{"name" : "WSALT", "sections" : ["SCHEDULE"],
"comment" : "The CONCENTRATION item should be UDA - but UDA & size_type:ALL is not supported",
"comment" : "UDA & size_type:ALL is not supported i.e Multi-Component Brine Model not supported",
"items" :
[{"name" : "WELL" , "value_type" : "STRING"},
{"name" : "CONCENTRATION" , "value_type" : "DOUBLE" , "size_type" : "ALL"}]}
{"name" : "CONCENTRATION" , "value_type" : "UDA"}]}

View File

@@ -0,0 +1,111 @@
/*
Copyright (C) 2019 by Norce
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/>.
*/
#define BOOST_TEST_MODULE SaltTableTests
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/P.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
// generic table classes
#include <opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/PvtwsaltTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/SaltvdTable.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
// keyword specific table classes
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <stdexcept>
#include <iostream>
using namespace Opm;
inline std::string prefix() {
return boost::unit_test::framework::master_test_suite().argv[1];
}
BOOST_AUTO_TEST_CASE( Brine ) {
const char *deckData =
"TABDIMS\n"
"1 1/\n"
"\n"
"BDENSITY\n"
" 1000 1050 /\n"
"\n"
"PVTWSALT\n"
" 1000/\n"
" 0 1 2 3 4 \n"
" 10 11 12 13 14/\n"
"\n"
"EQLDIMS\n"
"1 /\n"
"\n"
"SALTVD\n"
"500 0\n"
"550 50/\n";
Opm::Parser parser;
auto deck = parser.parseString(deckData);
Opm::TableManager tables(deck);
const auto& PvtwsaltTables = tables.getPvtwSaltTables( );
BOOST_CHECK_EQUAL( 1 , PvtwsaltTables.size() );
BOOST_CHECK_EQUAL(2, PvtwsaltTables[0].size());
const auto& PvtwsaltTable1 = PvtwsaltTables[0];
BOOST_CHECK_EQUAL (PvtwsaltTable1.getSaltConcentrationColumn().size(), 2);
BOOST_CHECK_CLOSE (PvtwsaltTable1.getSaltConcentrationColumn()[1], 10, 1e-5);
BOOST_CHECK_EQUAL (PvtwsaltTable1.getFormationVolumeFactorColumn().size(), 2);
BOOST_CHECK_CLOSE (PvtwsaltTable1.getFormationVolumeFactorColumn()[0], 1, 1e-5);
BOOST_CHECK_EQUAL (PvtwsaltTable1.getCompressibilityColumn().size(), 2);
BOOST_CHECK_CLOSE (PvtwsaltTable1.getCompressibilityColumn()[1], 12/1e5, 1e-5);
BOOST_CHECK_EQUAL (PvtwsaltTable1.getViscosityColumn().size(), 2);
BOOST_CHECK_CLOSE (PvtwsaltTable1.getViscosityColumn()[1], 13*0.001, 1e-5);
BOOST_CHECK_CLOSE (PvtwsaltTable1.getReferencePressureValue(), 1000*1e5, 1e-5);
const auto& BdensityTables = tables.getBrineDensityTables( );
const auto& BdensityTable1 = BdensityTables[0];
BOOST_CHECK_EQUAL( 1 , BdensityTables.size() );
BOOST_CHECK_EQUAL (BdensityTable1.getBrineDensityColumn().size(), 2);
BOOST_CHECK_CLOSE (BdensityTable1.getBrineDensityColumn()[1], 1050, 1e-5);
const Opm::TableContainer& saltvdTables = tables.getSaltvdTables();
const auto& saltvdTable = saltvdTables.getTable<Opm::SaltvdTable>(0);
BOOST_CHECK_EQUAL(saltvdTable.getDepthColumn() .size(), 2);
BOOST_CHECK_CLOSE (saltvdTable.getSaltColumn() [1],50, 1e-5);
}

View File

@@ -329,6 +329,7 @@ BOOST_AUTO_TEST_CASE(PdvdTable_Tests) {
BOOST_CHECK_THROW(Opm::PdvdTable pdvdTable2(deck.getKeyword("PDVD").getRecord(1).getItem(0)), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(SgwfnTable_Tests) {
const char *deckData =
"TABDIMS\n"