Merge pull request #882 from atgeirr/add-wfoam-support

Add WFOAM support
This commit is contained in:
Atgeirr Flø Rasmussen
2019-07-04 11:16:46 +02:00
committed by GitHub
12 changed files with 334 additions and 6 deletions

View File

@@ -108,6 +108,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/Well/WList.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/WellEconProductionLimits.cpp
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/WellTracerProperties.cpp
@@ -528,6 +529,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/Well/WList.hpp
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/WellPolymerProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellTracerProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp

View File

@@ -209,6 +209,7 @@ namespace Opm
void handleWELSEGS( const DeckKeyword& keyword, size_t currentStep);
void handleCOMPSEGS( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
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 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);

View File

@@ -30,6 +30,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
#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/WellTracerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellEconProductionLimits.hpp>
@@ -93,6 +94,7 @@ public:
const WellProductionProperties& getProductionProperties() const;
const WellInjectionProperties& getInjectionProperties() const;
const WellEconProductionLimits& getEconLimits() const;
const WellFoamProperties& getFoamProperties() const;
const WellPolymerProperties& getPolymerProperties() const;
const WellTracerProperties& getTracerProperties() const;
const WellConnections& getConnections() const;
@@ -143,6 +145,7 @@ public:
bool updateEfficiencyFactor(double efficiency_factor);
bool updateSolventFraction(double solvent_fraction);
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 updateEconLimits(std::shared_ptr<WellEconProductionLimits> econ_limits);
bool updateProduction(std::shared_ptr<WellProductionProperties> production);
@@ -187,6 +190,7 @@ private:
bool prediction_mode = true;
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 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

View File

@@ -0,0 +1,37 @@
/*
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
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_WELLFOAMPROPERTIES_HEADER_INCLUDED
#define OPM_WELLFOAMPROPERTIES_HEADER_INCLUDED
namespace Opm
{
class DeckRecord;
struct WellFoamProperties
{
double m_foamConcentration = 0.0;
void handleWFOAM(const DeckRecord& rec);
bool operator!=(const WellFoamProperties& other) const;
};
} // namespace Opm
#endif // OPM_WELLFOAMPROPERTIES_HEADER_INCLUDED

View File

@@ -55,6 +55,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WList.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellFoamProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellPolymerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
@@ -238,6 +239,9 @@ namespace Opm {
else if (keyword.name() == "WCONINJE")
handleWCONINJE(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "WFOAM")
handleWFOAM(keyword, currentStep, parseContext, errors);
else if (keyword.name() == "WPOLYMER")
handleWPOLYMER(keyword, currentStep, parseContext, errors);
@@ -941,6 +945,25 @@ namespace Opm {
}
}
void Schedule::handleWFOAM( 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<Well2>(*dynamic_state[currentStep]);
auto foam_properties = std::make_shared<WellFoamProperties>(well2->getFoamProperties());
foam_properties->handleWFOAM(record);
if (well2->updateFoamProperties(foam_properties))
this->updateWell(well2, currentStep);
}
}
}
void Schedule::handleWPOLYMER( 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);
@@ -951,7 +974,7 @@ namespace Opm {
for( const auto& well_name : well_names) {
{
auto& dynamic_state = this->wells_static.at(well_name);
const auto& dynamic_state = this->wells_static.at(well_name);
auto well2 = std::make_shared<Well2>(*dynamic_state[currentStep]);
auto polymer_properties = std::make_shared<WellPolymerProperties>( well2->getPolymerProperties() );
polymer_properties->handleWPOLYMER(record);

View File

@@ -104,6 +104,7 @@ Well2::Well2(const std::string& wname_arg,
efficiency_factor(1.0),
solvent_fraction(0.0),
econ_limits(std::make_shared<WellEconProductionLimits>()),
foam_properties(std::make_shared<WellFoamProperties>()),
polymer_properties(std::make_shared<WellPolymerProperties>()),
tracer_properties(std::make_shared<WellTracerProperties>()),
connections(std::make_shared<WellConnections>(headI, headJ)),
@@ -134,10 +135,27 @@ bool Well2::updateWellGuideRate(double guide_rate_arg) {
}
bool Well2::updateFoamProperties(std::shared_ptr<WellFoamProperties> foam_properties_arg) {
if (this->producer) {
throw std::runtime_error("Not allowed to set foam injection properties for well " + name()
+ " since it is a production well");
}
if (*this->foam_properties != *foam_properties_arg) {
this->foam_properties = foam_properties_arg;
return true;
}
return false;
}
bool Well2::updatePolymerProperties(std::shared_ptr<WellPolymerProperties> polymer_properties_arg) {
if (this->producer) {
throw std::runtime_error("Not allowed to set polymer injection properties for well " + name() +
" since it is a production well");
}
if (*this->polymer_properties != *polymer_properties_arg) {
this->polymer_properties = polymer_properties_arg;
this->producer = false;
return true;
}
@@ -452,6 +470,10 @@ const WellConnections& Well2::getConnections() const {
return *this->connections;
}
const WellFoamProperties& Well2::getFoamProperties() const {
return *this->foam_properties;
}
const WellPolymerProperties& Well2::getPolymerProperties() const {
return *this->polymer_properties;
}

View File

@@ -0,0 +1,33 @@
/*
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
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/WellFoamProperties.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
void Opm::WellFoamProperties::handleWFOAM(const DeckRecord& rec)
{
this->m_foamConcentration = rec.getItem("FOAM_CONCENTRATION").get<UDAValue>(0).get<double>();
}
bool Opm::WellFoamProperties::operator!=(const WellFoamProperties& other) const
{
return this->m_foamConcentration != other.m_foamConcentration;
}

View File

@@ -649,6 +649,23 @@ BOOST_AUTO_TEST_CASE( test_invalid_wtemplate_config ) {
)";
testSamples.push_back(testSample);
// Invalid well name in WFOAM
testSample = R"(
COMPDAT
'INJ' 10 10 3 3 'OPEN' 1* 1* 0.5 /
/
WCONINJE
'INJ' 'WATER' 'OPEN' 'RATE' 20000 4* /
/
DATES
15 OKT 2008 /
/
WFOAM
'SOMETHINGELSE' 0.02 /
/
)";
testSamples.push_back(testSample);
// Invalid well name in WELOPEN
testSample = R"(
COMPDAT

View File

@@ -3002,6 +3002,9 @@ BOOST_AUTO_TEST_CASE(POLYINJ_TEST) {
"WELSPECS\n"
"'INJE01' 'I' 1 1 1 'WATER' /\n"
"/\n"
"WCONINJE\n"
"'INJE01' 'WATER' 'OPEN' 'RATE' 800.00 1* 1000 /\n"
"/\n"
"TSTEP\n"
" 1/\n"
"WPOLYMER\n"
@@ -3049,6 +3052,56 @@ BOOST_AUTO_TEST_CASE(POLYINJ_TEST) {
BOOST_CHECK_EQUAL(poly3.m_skprpolytable, 2);
}
// Test for WFOAM
BOOST_AUTO_TEST_CASE(WFOAM_TEST) {
const char *deckData =
"START\n"
" 8 MAR 2018/\n"
"GRID\n"
"PERMX\n"
" 1000*0.25 /\n"
"COPY\n"
" PERMX PERMY /\n"
" PERMX PERMZ /\n"
"/\n"
"PROPS\n \n"
"SCHEDULE\n"
"WELSPECS\n"
"'INJE01' 'I' 1 1 1 'WATER' /\n"
"/\n"
"WCONINJE\n"
"'INJE01' 'GAS' 'OPEN' 'RATE' 80000.00 1* 1000 /\n"
"/\n"
"TSTEP\n"
" 1/\n"
"WFOAM\n"
" 'INJE01' 0.2 /\n"
"/\n"
"TSTEP\n"
" 2*1/\n"
"WFOAM\n"
" 'INJE01' 0.3 /\n"
"/\n"
"TSTEP\n"
" 1 /\n";
Opm::Parser parser;
auto deck = parser.parseString(deckData);
EclipseGrid grid1(10,10,10);
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid1);
Runspec runspec (deck);
Schedule schedule(deck, grid1 , eclipseProperties, runspec);
const auto& f0 = schedule.getWell2("INJE01", 0).getFoamProperties();
const auto& f1 = schedule.getWell2("INJE01", 1).getFoamProperties();
const auto& f3 = schedule.getWell2("INJE01", 3).getFoamProperties();
BOOST_CHECK_EQUAL(f0.m_foamConcentration, 0.0);
BOOST_CHECK_EQUAL(f1.m_foamConcentration, 0.2);
BOOST_CHECK_EQUAL(f3.m_foamConcentration, 0.3);
}
BOOST_AUTO_TEST_CASE(WTEST_CONFIG) {
auto deck = createDeckWTEST();

View File

@@ -0,0 +1,70 @@
-- Based on the SCHEDULE_POLYMER test
START
10 MAI 2007 /
RUNSPEC
DIMENS
30 30 30 /
GRID
PERMX
27000*0.25 /
COPY
PERMX PERMY /
PERMX PERMZ /
/
SCHEDULE
WELSPECS
'INJE01' 'I' 1 1 1* 'GAS' /
'INJE02' 'I' 5 1 1* 'GAS' /
'INJE03' 'I' 10 1 1* 'GAS' /
'PROD01' 'P' 20 1 1* 'OIL' 7* /
/
COMPDAT
'INJE01' 1 1 2 2 'OPEN' 1* 200. 0.5 /
'INJE02' 5 1 2 2 'OPEN' 1* 200. 0.5 /
'INJE03' 10 1 2 2 'OPEN' 1* 200. 0.5 /
'PROD01' 20 1 1 1 'OPEN' 1* 200. 0.5 /
/
WCONINJE
'INJE01' 'GAS' 'OPEN' 'RATE' 80000.00 1* 1000 /
'INJE02' 'GAS' 'OPEN' 'RATE' 80000.00 1* 1000 /
'INJE03' 'GAS' 'OPEN' 'RATE' 80000.00 1* 1000 /
/
WCONPROD
'PROD01' 'OPEN' 'BHP' 5* 200 /
/
WFOAM
'INJE01' 0.11 /
'INJE03' 0.31 /
/
TSTEP
10
/
WFOAM
'INJE01' 0.12 /
'INJE02' 0.22 /
'INJE03' 0.0 /
/
TSTEP
10
/
WFOAM
'INJE01' 0.13 /
'INJE02' 0.0 /
'INJE03' 0.33 /
/
TSTEP
10
/

View File

@@ -680,6 +680,73 @@ BOOST_AUTO_TEST_CASE(WellTestWPOLYMER) {
}
BOOST_AUTO_TEST_CASE(WellTestWFOAM) {
Parser parser;
std::string scheduleFile(pathprefix() + "SCHEDULE/SCHEDULE_FOAM");
auto deck = parser.parseFile(scheduleFile);
EclipseGrid grid(30,30,30);
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec (deck);
Schedule sched(deck, grid , eclipseProperties, runspec);
BOOST_CHECK_EQUAL(4U, sched.numWells());
BOOST_CHECK(sched.hasWell("INJE01"));
BOOST_CHECK(sched.hasWell("PROD01"));
{
const auto& well1 = sched.getWell2("INJE01", 0);
BOOST_CHECK( well1.isInjector());
const WellFoamProperties& props_well10 = well1.getFoamProperties();
BOOST_CHECK_EQUAL(0.11, props_well10.m_foamConcentration);
}
{
const auto& well1 = sched.getWell2("INJE01", 1);
const WellFoamProperties& props_well11 = well1.getFoamProperties();
BOOST_CHECK_EQUAL(0.12, props_well11.m_foamConcentration);
}
{
const auto& well1 = sched.getWell2("INJE01", 2);
const WellFoamProperties& props_well12 = well1.getFoamProperties();
BOOST_CHECK_EQUAL(0.13, props_well12.m_foamConcentration);
}
{
const auto& well2 = sched.getWell2("INJE02", 0);
BOOST_CHECK( well2.isInjector());
const WellFoamProperties& props_well20 = well2.getFoamProperties();
BOOST_CHECK_EQUAL(0.0, props_well20.m_foamConcentration);
}
{
const auto& well2 = sched.getWell2("INJE02", 1);
const WellFoamProperties& props_well21 = well2.getFoamProperties();
BOOST_CHECK_EQUAL(0.22, props_well21.m_foamConcentration);
}
{
const auto& well2 = sched.getWell2("INJE02", 2);
const WellFoamProperties& props_well22 = well2.getFoamProperties();
BOOST_CHECK_EQUAL(0.0, props_well22.m_foamConcentration);
}
{
const auto& well3 = sched.getWell2("INJE03", 0);
BOOST_CHECK( well3.isInjector());
const WellFoamProperties& props_well30 = well3.getFoamProperties();
BOOST_CHECK_EQUAL(0.31, props_well30.m_foamConcentration);
}
{
const auto& well3 = sched.getWell2("INJE03", 1);
const WellFoamProperties& props_well31 = well3.getFoamProperties();
BOOST_CHECK_EQUAL(0.0, props_well31.m_foamConcentration);
}
{
const auto& well3 = sched.getWell2("INJE03", 2);
const WellFoamProperties& props_well32 = well3.getFoamProperties();
BOOST_CHECK_EQUAL(0.33, props_well32.m_foamConcentration);
}
}
BOOST_AUTO_TEST_CASE(WellTestWECON) {
Parser parser;
std::string scheduleFile(pathprefix() + "SCHEDULE/SCHEDULE_WECON");

View File

@@ -721,10 +721,6 @@ COMPDAT
W_6 0 0 2 2 2* 1* 2* 0.7 / -- Active index: 2
/
WPOLYMER
'W_3' 1.5 1.0 /
/
WCONHIST
-- history rates are set so that W_1 produces 1, W_2 produces 2 etc.
-- index.offset.
@@ -738,6 +734,9 @@ WCONINJH
W_3 WATER STOP 30.0 2.1 2.2 /
/
WPOLYMER
'W_3' 1.5 1.0 /
/
WCONINJH
-- Injection historical rates (water only, as we only support pure injectors)
W_6 GAS STOP 30000.0 /