Merge pull request #562 from trinemykk/addtracer

Added missing support for tracers in the parser
This commit is contained in:
Joakim Hove
2018-11-26 13:02:19 +01:00
committed by GitHub
12 changed files with 304 additions and 54 deletions

View File

@@ -98,6 +98,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellInjectionProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellTestConfig.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp
@@ -237,6 +238,7 @@ if(ENABLE_ECL_INPUT)
tests/parser/UnitTests.cpp
tests/parser/ValueTests.cpp
tests/parser/WellSolventTests.cpp
tests/parser/WellTracerTests.cpp
tests/parser/WellTests.cpp
tests/parser/WTEST.cpp)
endif()
@@ -460,6 +462,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp
opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.hpp
opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp
opm/parser/eclipse/EclipseState/Schedule/Group.hpp
opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp

View File

@@ -176,6 +176,7 @@ namespace Opm
void handleWCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
void handleWPOLYMER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
void handleWSOLVENT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
void handleWTRACER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
void handleWTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
void handleWPMITAB( const DeckKeyword& keyword, const size_t currentStep, const ParseContext& parseContext);
void handleWSKPTAB( const DeckKeyword& keyword, const size_t currentStep, const ParseContext& parseContext);

View File

@@ -32,6 +32,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellInjectionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
@@ -150,6 +151,9 @@ namespace Opm {
WellPolymerProperties getPolymerPropertiesCopy(size_t timeStep) const;
const WellPolymerProperties& getPolymerProperties(size_t timeStep) const;
bool setTracerProperties(size_t timeStep , const WellTracerProperties& properties);
const WellTracerProperties& getTracerProperties(size_t timeStep) const;
bool setSolventFraction(size_t timeStep , const double fraction);
const double& getSolventFraction(size_t timeStep) const;
@@ -222,6 +226,7 @@ namespace Opm {
DynamicState< WellPolymerProperties > m_polymerProperties;
DynamicState< WellEconProductionLimits > m_econproductionlimits;
DynamicState< double > m_solventFraction;
DynamicState< WellTracerProperties > m_tracerProperties;
DynamicState< std::string > m_groupName;
DynamicState< int > m_rft;
DynamicState< int > m_plt;

View File

@@ -0,0 +1,45 @@
/*
Copyright 2018 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 WELLTRACERPROPERTIES_HPP_HEADER_INCLUDED
#define WELLTRACERPROPERTIES_HPP_HEADER_INCLUDED
#include <vector>
#include <string>
#include <map>
namespace Opm {
class WellTracerProperties {
public:
WellTracerProperties();
void setConcentration(const std::string& name, const double& concentration);
double getConcentration(const std::string& name) const;
bool operator==(const WellTracerProperties& other) const;
bool operator!=(const WellTracerProperties& other) const;
private:
std::map< std::string, double > m_tracerConcentrations;
};
}
#endif

View File

@@ -192,6 +192,9 @@ namespace Opm {
else if (keyword.name() == "WSOLVENT")
handleWSOLVENT(keyword, currentStep, parseContext);
else if (keyword.name() == "WTRACER")
handleWTRACER(keyword, currentStep, parseContext);
else if (keyword.name() == "WTEST")
handleWTEST(keyword, currentStep, parseContext);
@@ -890,6 +893,26 @@ namespace Opm {
}
}
}
void Schedule::handleWTRACER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext) {
for( const auto& record : keyword ) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
const auto wells = getWells( wellNamePattern );
if (wells.empty())
invalidNamePattern(wellNamePattern, parseContext, keyword);
for( auto* well : wells) {
WellTracerProperties wellTracerProperties = well->getTracerProperties( currentStep );
double tracerConcentration = record.getItem("CONCENTRATION").get< double >(0);
const std::string& tracerName = record.getItem("TRACER").getTrimmedString(0);
wellTracerProperties.setConcentration(tracerName, tracerConcentration);
well->setTracerProperties(currentStep, wellTracerProperties);
}
}
}
void Schedule::handleWTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext) {
for( const auto& record : keyword ) {

View File

@@ -54,6 +54,7 @@ namespace Opm {
m_polymerProperties( timeMap, WellPolymerProperties() ),
m_econproductionlimits( timeMap, WellEconProductionLimits() ),
m_solventFraction( timeMap, 0.0 ),
m_tracerProperties( timeMap, WellTracerProperties() ),
m_groupName( timeMap, "" ),
m_rft( timeMap, false ),
m_plt( timeMap, false ),
@@ -208,6 +209,13 @@ namespace Opm {
return m_solventFraction.update(timeStep, fraction);
}
bool Well::setTracerProperties(size_t timeStep , const WellTracerProperties& newProperties) {
if (isProducer(timeStep))
throw std::invalid_argument("WTRACER keyword can only be applied to injectors");
return m_tracerProperties.update(timeStep, newProperties);
}
bool Well::setEconProductionLimits(const size_t timeStep, const WellEconProductionLimits& productionlimits) {
// not sure if this keyword turning a well to be producer.
// not sure what will happen if we use this keyword to a injector.
@@ -222,6 +230,10 @@ namespace Opm {
return m_solventFraction.at(timeStep);
}
const WellTracerProperties& Well::getTracerProperties(size_t timeStep) const {
return m_tracerProperties.at(timeStep);
}
bool Well::hasBeenDefined(size_t timeStep) const {

View File

@@ -0,0 +1,52 @@
/*
Copyright 2018 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/WellTracerProperties.hpp>
#include <string>
#include <vector>
#include <map>
namespace Opm {
WellTracerProperties::WellTracerProperties() {
}
bool WellTracerProperties::operator==(const WellTracerProperties& other) const {
if (m_tracerConcentrations == other.m_tracerConcentrations)
return true;
else
return false;
}
void WellTracerProperties::setConcentration(const std::string& name, const double& concentration) {
m_tracerConcentrations[name] = concentration;
}
double WellTracerProperties::getConcentration(const std::string& name) const {
auto it = m_tracerConcentrations.find(name);
if (it == m_tracerConcentrations.end())
return 0.0;
return it->second;
}
bool WellTracerProperties::operator!=(const WellTracerProperties& other) const {
return !(*this == other);
}
}

View File

@@ -0,0 +1,6 @@
{
"name" : "TBLK",
"deck_name_regex":"TBLK(F|S).{1,3}",
"sections" : ["SOLUTION"],
"data" : {"value_type" : "DOUBLE", "dimension" : "1"}
}

View File

@@ -9,6 +9,6 @@
"name" : "table",
"value_type" : "DOUBLE",
"size_type" : "ALL",
"dimension" : ["Length" , "ContextDependent"]
"dimension" : ["Length" , "1"]
}]
}

View File

@@ -328,6 +328,7 @@ set( keywords
000_Eclipse100/S/SWOF
000_Eclipse100/S/SWU
000_Eclipse100/T/TABDIMS
000_Eclipse100/T/TBLK
000_Eclipse100/T/TEMP
000_Eclipse100/T/THCONR
000_Eclipse100/T/THERMAL

View File

@@ -0,0 +1,155 @@
/*
Copyright 2018 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 WellTracerTests
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#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/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
using namespace Opm;
static Deck createDeckWithOutTracer() {
Opm::Parser parser;
std::string input =
"SCHEDULE\n"
"WELSPECS\n"
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
"/\n"
"COMPDAT\n"
" 'W_1' 2* 1 1 'OPEN' / \n"
"/\n"
"WCONINJE\n"
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n";
return parser.parseString(input, ParseContext());
}
static Deck createDeckWithDynamicWTRACER() {
Opm::Parser parser;
std::string input =
"START -- 0 \n"
"1 JAN 2000 / \n"
"SCHEDULE\n"
"WELSPECS\n"
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
"/\n"
"COMPDAT\n"
" 'W_1' 2* 1 1 'OPEN' / \n"
"/\n"
"WCONINJE\n"
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
"DATES -- 1\n"
" 1 MAY 2000 / \n"
"/\n"
"WTRACER\n"
" 'W_1' 'I1' 1 / \n "
" 'W_1' 'I2' 1 / \n "
"/\n"
"DATES -- 2, 3\n"
" 1 JUL 2000 / \n"
" 1 AUG 2000 / \n"
"/\n"
"WTRACER\n"
" 'W_1' 'I1' 0 / \n "
"/\n"
"DATES -- 4\n"
" 1 SEP 2000 / \n"
"/\n";
return parser.parseString(input, ParseContext());
}
static Deck createDeckWithTracerInProducer() {
Opm::Parser parser;
std::string input =
"START -- 0 \n"
"1 JAN 2000 / \n"
"SCHEDULE\n"
"WELSPECS\n"
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
"/\n"
"COMPDAT\n"
" 'W_1' 2* 1 1 'OPEN' / \n"
"/\n"
"WCONPROD\n"
"'W_1' 'OPEN' 'ORAT' 20000 4* 1000 /\n"
"WTRACER\n"
" 'W_1' 'I1' 1 / \n "
" 'W_1' 'I2' 1 / \n "
"/\n";
return parser.parseString(input, ParseContext());
}
BOOST_AUTO_TEST_CASE(TestNoTracer) {
auto deck = createDeckWithOutTracer();
EclipseGrid grid(10,10,10);
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec ( deck );
Schedule schedule(deck, grid , eclipseProperties, runspec , ParseContext());
BOOST_CHECK(!deck.hasKeyword("WTRACER"));
}
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
auto deck = createDeckWithDynamicWTRACER();
EclipseGrid grid(10,10,10);
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec ( deck );
Schedule schedule(deck, grid , eclipseProperties, runspec , ParseContext());
BOOST_CHECK(deck.hasKeyword("WTRACER"));
const auto& keyword = deck.getKeyword("WTRACER");
BOOST_CHECK_EQUAL(keyword.size(),1);
const auto& record = keyword.getRecord(0);
const std::string& wellNamesPattern = record.getItem("WELL").getTrimmedString(0);
auto wells_Tracer = schedule.getWellsMatching(wellNamesPattern);
BOOST_CHECK_EQUAL(wellNamesPattern, "W_1");
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(0).getConcentration("I1"),0); //default 0
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(0).getConcentration("I2"),0); //default 0
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(1).getConcentration("I1"),1);
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(2).getConcentration("I1"),1);
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(4).getConcentration("I1"),0);
BOOST_CHECK_EQUAL(wells_Tracer[0]->getTracerProperties(4).getConcentration("I2"),1);
}
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW) {
auto deck = createDeckWithTracerInProducer();
EclipseGrid grid(10,10,10);
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec ( deck );
BOOST_CHECK_THROW(Schedule(deck, grid, eclipseProperties, runspec , ParseContext()), std::invalid_argument);
}

View File

@@ -91,9 +91,6 @@ RPTSCHED
DATES
16 'JUL' 1998 /
/
WTRACER
'C-1H' 'SEA' 1.000 1* /
/
RPTSCHED
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
@@ -158,18 +155,12 @@ DATES
DATES
21 'JAN' 1999 /
/
WTRACER
'C-2H' 'SEA' 1.000 1* /
/
DATES
1 'FEB' 1999 /
/
DATES
24 'FEB' 1999 /
/
WTRACER
'C-4H' 'SEA' 1.000 1* /
/
DATES
1 'MAR' 1999 /
/
@@ -209,9 +200,6 @@ DATES
DATES
20 'MAY' 1999 /
/
WTRACER
'C-3H' 'SEA' 1.000 1* /
/
DATES
21 'MAY' 1999 /
/
@@ -245,28 +233,15 @@ DATES
DATES
1 'SEP' 1999 /
/
WTRACER
'F-1H' 'SEA' 1.000 1* /
/
DATES
3 'SEP' 1999 /
/
DATES
21 'SEP' 1999 /
/
WTRACER
'C-1H' 'HTO' 1000.000 1* /
'C-3H' '4FB' 1000.000 1* /
'F-1H' 'S36' 98.000 1* /
/
DATES
22 'SEP' 1999 /
/
WTRACER
'C-1H' 'HTO' 0.000 1* /
'C-3H' '4FB' 0.000 1* /
'F-1H' 'S36' 0.000 1* /
/
DATES
1 'OCT' 1999 /
/
@@ -285,9 +260,6 @@ DATES
DATES
13 'OCT' 1999 /
/
WTRACER
'F-2H' 'SEA' 1.000 1* /
/
DATES
16 'OCT' 1999 /
/
@@ -375,19 +347,9 @@ DATES
DATES
26 'AUG' 2000 /
/
WTRACER
'C-2H' 'S36' 78.000 1* /
'C-4H' '2FB' 1000.000 1* /
'F-2H' 'DFB' 1000.000 1* /
/
DATES
27 'AUG' 2000 /
/
WTRACER
'C-2H' 'S36' 0.000 1* /
'C-4H' '2FB' 0.000 1* /
'F-2H' 'DFB' 0.000 1* /
/
DATES
1 'SEP' 2000 /
/
@@ -403,9 +365,6 @@ DATES
DATES
22 'SEP' 2000 /
/
WTRACER
'F-3H' 'SEA' 1.000 1* /
/
DATES
1 'OCT' 2000 /
/
@@ -509,9 +468,6 @@ DATES
DATES
10 'SEP' 2001 /
/
WTRACER
'F-4H' 'SEA' 1.000 1* /
/
DATES
1 'OCT' 2001 /
/
@@ -545,15 +501,9 @@ RPTSCHED
DATES
12 'FEB' 2002 /
/
WTRACER
'F-3H' 'TFB' 1000.000 1* /
/
DATES
13 'FEB' 2002 /
/
WTRACER
'F-3H' 'TFB' 0.000 1* /
/
DATES
1 'MAR' 2002 /
/
@@ -771,9 +721,6 @@ RPTSCHED
DATES
20 'JAN' 2004 /
/
WTRACER
'C-4AH' 'SEA' 1.000 1* /
/
DATES
1 'FEB' 2004 /
/