From 94974f045452651e0bf58d392db61b94ca2895c6 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Thu, 20 Nov 2014 16:20:54 +0800 Subject: [PATCH 1/3] add WPOLYMER to schedule section. --- opm/parser/eclipse/CMakeLists.txt | 2 ++ .../EclipseState/Schedule/Schedule.cpp | 28 +++++++++++++++ .../EclipseState/Schedule/Schedule.hpp | 1 + .../eclipse/EclipseState/Schedule/Well.cpp | 15 ++++++++ .../eclipse/EclipseState/Schedule/Well.hpp | 6 ++++ .../Schedule/WellPolymerProperties.cpp | 12 +++++++ .../Schedule/WellPolymerProperties.hpp | 34 +++++++++++++++++++ 7 files changed, 98 insertions(+) create mode 100644 opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp create mode 100644 opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp diff --git a/opm/parser/eclipse/CMakeLists.txt b/opm/parser/eclipse/CMakeLists.txt index f2a300605..476015fe7 100644 --- a/opm/parser/eclipse/CMakeLists.txt +++ b/opm/parser/eclipse/CMakeLists.txt @@ -70,6 +70,7 @@ EclipseState/Schedule/Schedule.cpp EclipseState/Schedule/Well.cpp EclipseState/Schedule/WellProductionProperties.cpp EclipseState/Schedule/WellInjectionProperties.cpp +EclipseState/Schedule/WellPolymerProperties.cpp EclipseState/Schedule/WellSet.cpp EclipseState/Schedule/Group.cpp EclipseState/Schedule/Completion.cpp @@ -134,6 +135,7 @@ EclipseState/Schedule/Schedule.hpp EclipseState/Schedule/Well.hpp EclipseState/Schedule/WellProductionProperties.hpp EclipseState/Schedule/WellInjectionProperties.hpp +EclipseState/Schedule/WellPolymerProperties.hpp EclipseState/Schedule/WellSet.hpp EclipseState/Schedule/Group.hpp EclipseState/Schedule/DynamicState.hpp diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 32ade4b51..0856f9cf2 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,9 @@ namespace Opm { if (keyword->name() == "WCONINJE") handleWCONINJE(deck, keyword, parserLog, currentStep); + if (keyword->name() == "WPOLYMER") + handleWPOLYMER(deck, keyword, parserLog, currentStep); + if (keyword->name() == "WCONINJH") handleWCONINJH(deck, keyword, parserLog, currentStep); @@ -321,6 +325,29 @@ namespace Opm { } + void Schedule::handleWPOLYMER(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr /*parserLog*/, size_t currentStep) { + for (size_t recordNr = 0; recordNr < keyword->size(); recordNr++) { + DeckRecordConstPtr record = keyword->getRecord(recordNr); + const std::string& wellNamePattern = record->getItem("WELL")->getTrimmedString(0); + std::vector wells = getWells(wellNamePattern); + + for (auto wellIter=wells.begin(); wellIter != wells.end(); ++wellIter) { + WellPtr well = *wellIter; + + WellPolymerProperties properties(well->getPolymerPropertiesCopy(currentStep)); + + if (!record->getItem("POLYMER_CONCENTRATION")->defaultApplied(0)) { + properties.m_polymerConcentration = record->getItem("POLYMER_CONCENTRATION")->getSIDouble(0); + } + if (!record->getItem("SALT_CONCENTRATION")->defaultApplied(0)) { + properties.m_saltConcentration = record->getItem("SALT_CONCENTRATION")->getSIDouble(0); + } + + well->setPolymerProperties(currentStep, properties); + } + } + } + void Schedule::handleWCONINJH(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr /*parserLog*/, size_t currentStep) { for (size_t recordNr = 0; recordNr < keyword->size(); recordNr++) { DeckRecordConstPtr record = keyword->getRecord(recordNr); @@ -617,6 +644,7 @@ namespace Opm { } } + bool Schedule::convertEclipseStringToBool(const std::string& eclipseString) { std::string lowerTrimmed = boost::algorithm::to_lower_copy(eclipseString); boost::algorithm::trim(lowerTrimmed); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 124857418..a7fc3c7ca 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -79,6 +79,7 @@ namespace Opm void handleWGRUPCON(DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); void handleCOMPDAT(DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); void handleWCONINJE(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); + void handleWPOLYMER(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); void handleWCONINJH(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); void handleWELOPEN(DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); void handleGCONINJE(DeckConstPtr deck, DeckKeywordConstPtr keyword, ParserLogPtr parserLog, size_t currentStep); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well.cpp b/opm/parser/eclipse/EclipseState/Schedule/Well.cpp index a16b974cf..26afc7941 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well.cpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well.cpp @@ -38,6 +38,7 @@ namespace Opm { m_completions( new DynamicState( timeMap , CompletionSetConstPtr( new CompletionSet()) )), m_productionProperties( new DynamicState(timeMap, WellProductionProperties() )), m_injectionProperties( new DynamicState(timeMap, WellInjectionProperties() )), + m_polymerProperties( new DynamicState(timeMap, WellPolymerProperties() )), m_groupName( new DynamicState( timeMap , "" )), m_headI(headI), m_headJ(headJ), @@ -60,6 +61,7 @@ namespace Opm { m_completions( new DynamicState( timeMap , CompletionSetConstPtr( new CompletionSet()) )), m_productionProperties( new DynamicState(timeMap, WellProductionProperties() )), m_injectionProperties( new DynamicState(timeMap, WellInjectionProperties() )), + m_polymerProperties( new DynamicState(timeMap, WellPolymerProperties() )), m_groupName( new DynamicState( timeMap , "" )), m_headI(headI), m_headJ(headJ), @@ -102,6 +104,19 @@ namespace Opm { return m_injectionProperties->at(timeStep); } + void Well::setPolymerProperties(size_t timeStep , const WellPolymerProperties newProperties) { + m_isProducer->add(timeStep , false); + m_polymerProperties->add(timeStep, newProperties); + } + + WellPolymerProperties Well::getPolymerPropertiesCopy(size_t timeStep) const { + return m_polymerProperties->get(timeStep); + } + + const WellPolymerProperties& Well::getPolymerProperties(size_t timeStep) const { + return m_polymerProperties->at(timeStep); + } + bool Well::hasBeenDefined(size_t timeStep) const { if (timeStep < m_creationTimeStep) return false; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well.hpp index f10a51e62..a7068dfec 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -83,6 +84,10 @@ namespace Opm { WellInjectionProperties getInjectionPropertiesCopy(size_t timeStep) const; const WellInjectionProperties& getInjectionProperties(size_t timeStep) const; + void setPolymerProperties(size_t timeStep , const WellPolymerProperties properties); + WellPolymerProperties getPolymerPropertiesCopy(size_t timeStep) const; + const WellPolymerProperties& getPolymerProperties(size_t timeStep) const; + private: size_t m_creationTimeStep; std::string m_name; @@ -98,6 +103,7 @@ namespace Opm { std::shared_ptr > m_completions; std::shared_ptr > m_productionProperties; std::shared_ptr > m_injectionProperties; + std::shared_ptr > m_polymerProperties; std::shared_ptr > m_groupName; // WELSPECS data - assumes this is not dynamic diff --git a/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp b/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp new file mode 100644 index 000000000..8a04c496c --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp @@ -0,0 +1,12 @@ +#include + +#include +#include + +namespace Opm { + + WellPolymerProperties::WellPolymerProperties() { + m_polymerConcentration = 0.0; + m_saltConcentration = 0.0; + } +} diff --git a/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp b/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp new file mode 100644 index 000000000..236d96a11 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp @@ -0,0 +1,34 @@ +/* + Copyright 2014 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 WELLPOLYMERPROPERTIES_HPP_HEADER_INCLUDED +#define WELLPOLYMERPROPERTIES_HPP_HEADER_INCLUDED + + +namespace Opm { + + struct WellPolymerProperties { + double m_polymerConcentration; + double m_saltConcentration; + + WellPolymerProperties(); + }; +} + +#endif From 81be71cac82ffdfc8f6a66793f7ba7f9fe48359f Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Thu, 20 Nov 2014 17:23:12 +0800 Subject: [PATCH 2/3] throw if group polymer/salt concentration is set. --- .../eclipse/EclipseState/Schedule/Schedule.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 0856f9cf2..8312864f1 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -336,13 +336,19 @@ namespace Opm { WellPolymerProperties properties(well->getPolymerPropertiesCopy(currentStep)); - if (!record->getItem("POLYMER_CONCENTRATION")->defaultApplied(0)) { - properties.m_polymerConcentration = record->getItem("POLYMER_CONCENTRATION")->getSIDouble(0); - } - if (!record->getItem("SALT_CONCENTRATION")->defaultApplied(0)) { - properties.m_saltConcentration = record->getItem("SALT_CONCENTRATION")->getSIDouble(0); + properties.m_polymerConcentration = record->getItem("POLYMER_CONCENTRATION")->getSIDouble(0); + properties.m_saltConcentration = record->getItem("SALT_CONCENTRATION")->getSIDouble(0); + + auto group_polymer_item = record->getItem("GROUP_POLYMER_CONCENTRATION"); + auto group_salt_item = record->getItem("GROUP_SALT_CONCENTRATION"); + + if (!group_polymer_item->defaultApplied(0)) { + throw std::logic_error("Sorry explicit setting of \`GROUP_POLYMER_CONCENTRATION\` is not supported!"); } + if (!group_salt_item->defaultApplied(0)) { + throw std::logic_error("Sorry explicit setting of \`GROUP_SALT_CONCENTRATION\` is not supported!"); + } well->setPolymerProperties(currentStep, properties); } } From 5b3a92159a6b8543f28aec497409939bf33934d5 Mon Sep 17 00:00:00 2001 From: Liu Ming Date: Fri, 21 Nov 2014 13:21:24 +0800 Subject: [PATCH 3/3] add unit test for WPOLYMER. --- .../ScheduleCreateFromDeck.cpp | 43 ++++++++++++++ .../SCHEDULE/SCHEDULE_POLYMER | 56 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 testdata/integration_tests/SCHEDULE/SCHEDULE_POLYMER diff --git a/opm/parser/eclipse/IntegrationTests/ScheduleCreateFromDeck.cpp b/opm/parser/eclipse/IntegrationTests/ScheduleCreateFromDeck.cpp index ac06e2fa5..1e27e11c0 100644 --- a/opm/parser/eclipse/IntegrationTests/ScheduleCreateFromDeck.cpp +++ b/opm/parser/eclipse/IntegrationTests/ScheduleCreateFromDeck.cpp @@ -592,3 +592,46 @@ BOOST_AUTO_TEST_CASE(WELLS_SHUT) { BOOST_CHECK_EQUAL( WellCommon::StatusEnum::SHUT , well3->getStatus(2)); } +BOOST_AUTO_TEST_CASE(WellTestWPOLYMER) { + ParserPtr parser(new Parser()); + boost::filesystem::path scheduleFile("testdata/integration_tests/SCHEDULE/SCHEDULE_POLYMER"); + DeckPtr deck = parser->parseFile(scheduleFile.string()); + ScheduleConstPtr sched(new Schedule(deck)); + + BOOST_CHECK_EQUAL(4U, sched->numWells()); + BOOST_CHECK(sched->hasWell("INJE01")); + BOOST_CHECK(sched->hasWell("PROD01")); + + WellConstPtr well1 = sched->getWell("INJE01"); + BOOST_CHECK( well1->isInjector(0)); + { + const WellPolymerProperties& props_well10 = well1->getPolymerProperties(0); + BOOST_CHECK_CLOSE(1.5*Metric::PolymerDensity, props_well10.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well11 = well1->getPolymerProperties(1); + BOOST_CHECK_CLOSE(1.0*Metric::PolymerDensity, props_well11.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well12 = well1->getPolymerProperties(2); + BOOST_CHECK_CLOSE(0.1*Metric::PolymerDensity, props_well12.m_polymerConcentration, 0.0001); + } + + WellConstPtr well2 = sched->getWell("INJE02"); + BOOST_CHECK( well2->isInjector(0)); + { + const WellPolymerProperties& props_well20 = well2->getPolymerProperties(0); + BOOST_CHECK_CLOSE(2.0*Metric::PolymerDensity, props_well20.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well21 = well2->getPolymerProperties(1); + BOOST_CHECK_CLOSE(1.5*Metric::PolymerDensity, props_well21.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well22 = well2->getPolymerProperties(2); + BOOST_CHECK_CLOSE(0.2*Metric::PolymerDensity, props_well22.m_polymerConcentration, 0.0001); + } + + WellConstPtr well3 = sched->getWell("INJE03"); + BOOST_CHECK( well3->isInjector(0)); + { + const WellPolymerProperties& props_well30 = well3->getPolymerProperties(0); + BOOST_CHECK_CLOSE(2.5*Metric::PolymerDensity, props_well30.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well31 = well3->getPolymerProperties(1); + BOOST_CHECK_CLOSE(2.0*Metric::PolymerDensity, props_well31.m_polymerConcentration, 0.0001); + const WellPolymerProperties& props_well32 = well3->getPolymerProperties(2); + BOOST_CHECK_CLOSE(0.3*Metric::PolymerDensity, props_well32.m_polymerConcentration, 0.0001); + } +} diff --git a/testdata/integration_tests/SCHEDULE/SCHEDULE_POLYMER b/testdata/integration_tests/SCHEDULE/SCHEDULE_POLYMER new file mode 100644 index 000000000..86d47aa6d --- /dev/null +++ b/testdata/integration_tests/SCHEDULE/SCHEDULE_POLYMER @@ -0,0 +1,56 @@ +START + 10 MAI 2007 / + + +SCHEDULE + + +WELSPECS + 'INJE01' 'I' 1 1 1* 'WATER' / + 'INJE02' 'I' 5 1 1* 'WATER' / + 'INJE03' 'I' 10 1 1* 'WATER' / + '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' 'WATER' 'OPEN' 'RATE' 800.00 1* 1000 / + 'INJE02' 'WATER' 'OPEN' 'RATE' 800.00 1* 1000 / + 'INJE03' 'WATER' 'OPEN' 'RATE' 800.00 1* 1000 / +/ +WCONPROD + 'PROD01' 'OPEN' 'BHP' 5* 200 / +/ + +WPOLYMER + 'INJE01' 1.5 0.0 / + 'INJE02' 2.0 0.0 / + 'INJE03' 2.5 0.0 / +/ +TSTEP +10 +/ +WPOLYMER + 'INJE01' 1.0 0.0 / + 'INJE02' 1.5 0.0 / + 'INJE03' 2.0 0.0 / +/ +TSTEP +10 +/ + +WPOLYMER + 'INJE01' 0.1 0.0 / + 'INJE02' 0.2 0.0 / + 'INJE03' 0.3 0.0 / +/ + +TSTEP +10 +/