Merge pull request #460 from joakim-hove/ACTIONX

Actionx
This commit is contained in:
Joakim Hove
2018-08-10 20:26:03 +02:00
committed by GitHub
11 changed files with 374 additions and 221 deletions

View File

@@ -73,6 +73,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/IOConfig/IOConfig.cpp
src/opm/parser/eclipse/EclipseState/IOConfig/RestartConfig.cpp
src/opm/parser/eclipse/EclipseState/Runspec.cpp
src/opm/parser/eclipse/EclipseState/Schedule/ActionX.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Connection.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellConnections.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Events.cpp
@@ -173,6 +174,7 @@ list (APPEND TEST_SOURCE_FILES
)
if(ENABLE_ECL_INPUT)
list(APPEND TEST_SOURCE_FILES
tests/parser/ACTIONX.cpp
tests/parser/ADDREGTests.cpp
tests/parser/AquiferCTTests.cpp
tests/parser/AqudimsTests.cpp
@@ -443,6 +445,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/EclipseConfig.hpp
opm/parser/eclipse/EclipseState/Aquancon.hpp
opm/parser/eclipse/EclipseState/AquiferCT.hpp
opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp
opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp
opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp
opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp

View File

@@ -0,0 +1,70 @@
/*
Copyright 2013 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 ActionX_HPP_
#define ActionX_HPP_
#include <string>
namespace Opm {
/*
The ActionX class internalizes the ACTIONX keyword. This keyword represents a
small in-deck programming language for the SCHEDULE section. In the deck the
ACTIONX keyword comes together with a 'ENDACTIO' kewyord and then a list of
regular keywords in the between. The principle is then that ACTIONX represents
a condition, and when that condition is satisfied the keywords are applied. In
the example below the ACTIONX keyword defines a condition whether well OPX has
watercut above 0.75, when the condition is met the WELOPEN keyword is applied
- and the well is shut.
ACTIONX
'NAME' /
WWCT OPX > 0.50 /
/
WELOPEN
'OPX' OPEN /
/
ENDACTION
*/
class DeckKeyword;
class ActionX {
public:
ActionX(const std::string& name, size_t max_run, double max_wait);
explicit ActionX(const DeckKeyword& kw);
void addKeyword(const DeckKeyword& kw);
const std::string& name() const;
private:
std::string m_name;
size_t max_run;
double max_wait;
std::vector<DeckKeyword> keywords;
};
}
#endif /* WELL_HPP_ */

View File

@@ -189,6 +189,15 @@ namespace Opm
void handleVFPINJ(const DeckKeyword& vfpprodKeyword, const UnitSystem& unit_system, size_t currentStep);
void checkUnhandledKeywords( const SCHEDULESection& ) const;
void checkIfAllConnectionsIsShut(size_t currentStep);
void handleKeyword(size_t& currentStep,
const SCHEDULESection& section,
size_t keywordIdx,
const DeckKeyword& keyword,
const ParseContext& parseContext,
const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties,
const UnitSystem& unit_system,
std::vector<std::pair<const DeckKeyword*, size_t > >& rftProperties);
static double convertInjectionRateToSI(double rawRate, WellInjector::TypeEnum wellType, const Opm::UnitSystem &unitSystem);
static double convertInjectionRateToSI(double rawRate, Phase wellPhase, const Opm::UnitSystem &unitSystem);

View File

@@ -40,14 +40,9 @@ namespace Opm {
bool hasKeyword(const std::string& keyword) const;
std::shared_ptr<const ParserKeyword> getKeyword(const std::string& keyword) const;
std::string getJsonFile(const std::string& keyword) const;
size_t loadKeywordDirectory(const std::string& pathname);
size_t loadKeywordDirectory(boost::filesystem::path& path);
void loadKeyword(const std::string& filename);
void loadKeyword(boost::filesystem::path& path);
static std::vector<std::string> sortSubdirectories( const std::string& directory );
size_t loadMultipleKeywordDirectories(const std::string& directory);
std::map<std::string , std::shared_ptr<ParserKeyword> >::const_iterator keyword_begin( ) const;
std::map<std::string , std::shared_ptr<ParserKeyword> >::const_iterator keyword_end( ) const;
private:

View File

@@ -0,0 +1,49 @@
/*
Copyright 2018 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/>.
*/
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp>
namespace Opm {
ActionX::ActionX(const std::string& name, size_t max_run, double max_wait) :
m_name(name),
max_run(max_run),
max_wait(max_wait)
{}
ActionX::ActionX(const DeckKeyword& kw) {
const auto& record = kw.getRecord(0);
this->m_name = record.getItem("NAME").getTrimmedString(0);
this->max_run = record.getItem("NUM").get<int>(0);
this->max_wait = record.getItem("MAX_WAIT").getSIDouble(0);
}
void ActionX::addKeyword(const DeckKeyword& kw) {
this->keywords.push_back(kw);
}
const std::string& ActionX::name() const {
return this->m_name;
}
}

View File

@@ -36,6 +36,7 @@
#include <opm/parser/eclipse/Parser/ParserKeywords/W.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellConnections.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/DynamicState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/DynamicVector.hpp>
@@ -117,15 +118,23 @@ namespace Opm {
return this->m_timeMap.getEndTime();
}
void Schedule::iterateScheduleSection(const ParseContext& parseContext , const SCHEDULESection& section , const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties) {
/*
geoModifiers is a list of geo modifiers which can be found in the schedule
section. This is only partly supported, support is indicated by the bool
value. The keywords which are supported will be assembled in a per-timestep
'minideck', whereas ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER will be
consulted for the others.
*/
void Schedule::handleKeyword(size_t& currentStep,
const SCHEDULESection& section,
size_t keywordIdx,
const DeckKeyword& keyword,
const ParseContext& parseContext,
const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties,
const UnitSystem& unit_system,
std::vector<std::pair<const DeckKeyword*, size_t > >& rftProperties) {
/*
geoModifiers is a list of geo modifiers which can be found in the schedule
section. This is only partly supported, support is indicated by the bool
value. The keywords which are supported will be assembled in a per-timestep
'minideck', whereas ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER will be
consulted for the others.
*/
const std::map<std::string,bool> geoModifiers = {{"MULTFLT" , true},
{"MULTPV" , false},
@@ -143,145 +152,169 @@ namespace Opm {
{"MULTTHT" , false},
{"MULTTHT-" , false}};
size_t currentStep = 0;
std::vector<std::pair< const DeckKeyword* , size_t> > rftProperties;
const auto& unit_system = section.unitSystem();
if (keyword.name() == "DATES") {
checkIfAllConnectionsIsShut(currentStep);
currentStep += keyword.size();
}
for (size_t keywordIdx = 0; keywordIdx < section.size(); ++keywordIdx) {
const auto& keyword = section.getKeyword(keywordIdx);
else if (keyword.name() == "TSTEP") {
checkIfAllConnectionsIsShut(currentStep);
currentStep += keyword.getRecord(0).getItem(0).size(); // This is a bit weird API.
}
if (keyword.name() == "DATES") {
checkIfAllConnectionsIsShut(currentStep);
currentStep += keyword.size();
}
else if (keyword.name() == "WELSPECS")
handleWELSPECS( section, keywordIdx, currentStep );
else if (keyword.name() == "TSTEP") {
checkIfAllConnectionsIsShut(currentStep);
currentStep += keyword.getRecord(0).getItem(0).size(); // This is a bit weird API.
}
else if (keyword.name() == "WHISTCTL")
handleWHISTCTL(parseContext, keyword);
else if (keyword.name() == "WELSPECS")
handleWELSPECS( section, keywordIdx, currentStep );
else if (keyword.name() == "WCONHIST")
handleWCONHIST(keyword, currentStep, parseContext);
else if (keyword.name() == "WHISTCTL")
handleWHISTCTL(parseContext, keyword);
else if (keyword.name() == "WCONPROD")
handleWCONPROD(keyword, currentStep, parseContext);
else if (keyword.name() == "WCONHIST")
handleWCONHIST(keyword, currentStep, parseContext);
else if (keyword.name() == "WCONINJE")
handleWCONINJE(section, keyword, currentStep, parseContext);
else if (keyword.name() == "WCONPROD")
handleWCONPROD(keyword, currentStep, parseContext);
else if (keyword.name() == "WPOLYMER")
handleWPOLYMER(keyword, currentStep, parseContext);
else if (keyword.name() == "WCONINJE")
handleWCONINJE(section, keyword, currentStep, parseContext);
else if (keyword.name() == "WSOLVENT")
handleWSOLVENT(keyword, currentStep, parseContext);
else if (keyword.name() == "WPOLYMER")
handleWPOLYMER(keyword, currentStep, parseContext);
else if (keyword.name() == "WTEST")
handleWTEST(keyword, currentStep, parseContext);
else if (keyword.name() == "WSOLVENT")
handleWSOLVENT(keyword, currentStep, parseContext);
else if (keyword.name() == "WTEMP")
handleWTEMP(keyword, currentStep, parseContext);
else if (keyword.name() == "WTEST")
handleWTEST(keyword, currentStep, parseContext);
else if (keyword.name() == "WINJTEMP")
handleWINJTEMP(keyword, currentStep, parseContext);
else if (keyword.name() == "WTEMP")
handleWTEMP(keyword, currentStep, parseContext);
else if (keyword.name() == "WCONINJH")
handleWCONINJH(section, keyword, currentStep, parseContext);
else if (keyword.name() == "WINJTEMP")
handleWINJTEMP(keyword, currentStep, parseContext);
else if (keyword.name() == "WGRUPCON")
handleWGRUPCON(keyword, currentStep);
else if (keyword.name() == "WCONINJH")
handleWCONINJH(section, keyword, currentStep, parseContext);
else if (keyword.name() == "COMPDAT")
handleCOMPDAT(keyword, currentStep, grid, eclipseProperties, parseContext);
else if (keyword.name() == "WGRUPCON")
handleWGRUPCON(keyword, currentStep);
else if (keyword.name() == "WELSEGS")
handleWELSEGS(keyword, currentStep);
else if (keyword.name() == "COMPDAT")
handleCOMPDAT(keyword, currentStep, grid, eclipseProperties, parseContext);
else if (keyword.name() == "COMPSEGS")
handleCOMPSEGS(keyword, currentStep);
else if (keyword.name() == "WELSEGS")
handleWELSEGS(keyword, currentStep);
else if (keyword.name() == "WELOPEN")
handleWELOPEN(keyword, currentStep, parseContext);
else if (keyword.name() == "COMPSEGS")
handleCOMPSEGS(keyword, currentStep);
else if (keyword.name() == "WELTARG")
handleWELTARG(section, keyword, currentStep, parseContext);
else if (keyword.name() == "WELOPEN")
handleWELOPEN(keyword, currentStep, parseContext);
else if (keyword.name() == "GRUPTREE")
handleGRUPTREE(keyword, currentStep);
else if (keyword.name() == "WELTARG")
handleWELTARG(section, keyword, currentStep, parseContext);
else if (keyword.name() == "GRUPNET")
handleGRUPNET(keyword, currentStep);
else if (keyword.name() == "GRUPTREE")
handleGRUPTREE(keyword, currentStep);
else if (keyword.name() == "GCONINJE")
handleGCONINJE(section, keyword, currentStep, parseContext);
else if (keyword.name() == "GRUPNET")
handleGRUPNET(keyword, currentStep);
else if (keyword.name() == "GCONPROD")
handleGCONPROD(keyword, currentStep, parseContext);
else if (keyword.name() == "GCONINJE")
handleGCONINJE(section, keyword, currentStep, parseContext);
else if (keyword.name() == "GEFAC")
handleGEFAC(keyword, currentStep, parseContext);
else if (keyword.name() == "GCONPROD")
handleGCONPROD(keyword, currentStep, parseContext);
else if (keyword.name() == "TUNING")
handleTUNING(keyword, currentStep);
else if (keyword.name() == "GEFAC")
handleGEFAC(keyword, currentStep, parseContext);
else if (keyword.name() == "WRFT")
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
else if (keyword.name() == "TUNING")
handleTUNING(keyword, currentStep);
else if (keyword.name() == "WRFTPLT")
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
else if (keyword.name() == "WRFT")
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
else if (keyword.name() == "WPIMULT")
handleWPIMULT(keyword, currentStep);
else if (keyword.name() == "WRFTPLT")
rftProperties.push_back( std::make_pair( &keyword , currentStep ));
else if (keyword.name() == "COMPORD")
handleCOMPORD(parseContext , keyword, currentStep);
else if (keyword.name() == "WPIMULT")
handleWPIMULT(keyword, currentStep);
else if (keyword.name() == "COMPLUMP")
handleCOMPLUMP(keyword, currentStep);
else if (keyword.name() == "COMPORD")
handleCOMPORD(parseContext , keyword, currentStep);
else if (keyword.name() == "DRSDT")
handleDRSDT(keyword, currentStep);
else if (keyword.name() == "COMPLUMP")
handleCOMPLUMP(keyword, currentStep);
else if (keyword.name() == "DRVDT")
handleDRVDT(keyword, currentStep);
else if (keyword.name() == "DRSDT")
handleDRSDT(keyword, currentStep);
else if (keyword.name() == "VAPPARS")
handleVAPPARS(keyword, currentStep);
else if (keyword.name() == "DRVDT")
handleDRVDT(keyword, currentStep);
else if (keyword.name() == "WECON")
handleWECON(keyword, currentStep, parseContext);
else if (keyword.name() == "VAPPARS")
handleVAPPARS(keyword, currentStep);
else if (keyword.name() == "MESSAGES")
handleMESSAGES(keyword, currentStep);
else if (keyword.name() == "WECON")
handleWECON(keyword, currentStep, parseContext);
else if (keyword.name() == "WEFAC")
handleWEFAC(keyword, currentStep, parseContext);
else if (keyword.name() == "MESSAGES")
handleMESSAGES(keyword, currentStep);
else if (keyword.name() == "VFPINJ")
handleVFPINJ(keyword, unit_system, currentStep);
else if (keyword.name() == "WEFAC")
handleWEFAC(keyword, currentStep, parseContext);
else if (keyword.name() == "VFPPROD")
handleVFPPROD(keyword, unit_system, currentStep);
else if (keyword.name() == "VFPINJ")
handleVFPINJ(keyword, unit_system, currentStep);
else if (keyword.name() == "VFPPROD")
handleVFPPROD(keyword, unit_system, currentStep);
else if (geoModifiers.find( keyword.name() ) != geoModifiers.end()) {
bool supported = geoModifiers.at( keyword.name() );
if (supported) {
this->m_modifierDeck[ currentStep ].addKeyword( keyword );
m_events.addEvent( ScheduleEvents::GEO_MODIFIER , currentStep);
} else {
std::string msg = "OPM does not support grid property modifier " + keyword.name() + " in the Schedule section. Error at report: " + std::to_string( currentStep );
parseContext.handleError( ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , msg );
}
else if (geoModifiers.find( keyword.name() ) != geoModifiers.end()) {
bool supported = geoModifiers.at( keyword.name() );
if (supported) {
this->m_modifierDeck[ currentStep ].addKeyword( keyword );
m_events.addEvent( ScheduleEvents::GEO_MODIFIER , currentStep);
} else {
std::string msg = "OPM does not support grid property modifier " + keyword.name() + " in the Schedule section. Error at report: " + std::to_string( currentStep );
parseContext.handleError( ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , msg );
}
}
checkIfAllConnectionsIsShut(currentStep);
}
void Schedule::iterateScheduleSection(const ParseContext& parseContext , const SCHEDULESection& section , const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties) {
size_t currentStep = 0;
const auto& unit_system = section.unitSystem();
std::vector<std::pair< const DeckKeyword* , size_t> > rftProperties;
size_t keywordIdx = 0;
while (true) {
const auto& keyword = section.getKeyword(keywordIdx);
if (keyword.name() == "ACTIONX") {
ActionX action(keyword);
while (true) {
keywordIdx++;
if (keywordIdx == section.size())
throw std::invalid_argument("Invalid ACTIONX section - missing ENDACTIO");
const auto& action_keyword = section.getKeyword(keywordIdx);
if (action_keyword.name() == "ENDACTIO")
break;
action.addKeyword(action_keyword);
}
} else
this->handleKeyword(currentStep, section, keywordIdx, keyword, parseContext, grid, eclipseProperties, unit_system, rftProperties);
keywordIdx++;
if (keywordIdx == section.size())
break;
}
checkIfAllConnectionsIsShut(currentStep);
for (auto rftPair = rftProperties.begin(); rftPair != rftProperties.end(); ++rftPair) {
const DeckKeyword& keyword = *rftPair->first;
size_t timeStep = rftPair->second;
@@ -297,6 +330,7 @@ namespace Opm {
checkUnhandledKeywords(section);
}
void Schedule::checkUnhandledKeywords(const SCHEDULESection& /*section*/) const
{
}

View File

@@ -30,8 +30,6 @@
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
#include <ert/ecl/ecl_grid.h>
namespace Opm {

View File

@@ -67,43 +67,6 @@ namespace Opm {
}
size_t KeywordLoader::loadKeywordDirectory(boost::filesystem::path& path) {
size_t loadCount = 0;
if (boost::filesystem::is_directory( path )) {
boost::filesystem::directory_iterator end_iterator;
for (boost::filesystem::directory_iterator iter(path); iter != end_iterator; ++iter) {
boost::filesystem::path iter_path = iter->path();
if (boost::filesystem::is_directory( iter_path )) {
loadCount += loadKeywordDirectory( iter_path );
} else {
std::string internalName = iter_path.filename().string();
if (ParserKeyword::validInternalName(internalName)) {
if (m_verbose)
std::cout << "Loading keyword " << internalName << " from file: " << iter_path << "....";
loadKeyword( iter_path );
if (m_verbose)
std::cout << std::endl;
loadCount += 1;
} else {
if (m_verbose)
std::cout << "Ignoring file " << iter_path << " - incorrectly formatted name." << std::endl;
}
}
}
} else
throw std::invalid_argument("Input does not correspond to existing directory\n");
return loadCount;
}
size_t KeywordLoader::loadKeywordDirectory(const std::string& directory) {
boost::filesystem::path path( directory );
return loadKeywordDirectory( path );
}
void KeywordLoader::loadKeyword(boost::filesystem::path& path) {
std::shared_ptr<Json::JsonObject> jsonConfig = std::make_shared<Json::JsonObject>( path );
std::shared_ptr<ParserKeyword> parserKeyword = std::make_shared<ParserKeyword>(*jsonConfig);
@@ -114,19 +77,10 @@ namespace Opm {
}
size_t KeywordLoader::loadMultipleKeywordDirectories(const std::string& directory) {
std::vector<std::string> directories = sortSubdirectories( directory );
size_t load_count = 0;
for (auto iter = directories.begin(); iter != directories.end(); ++iter)
load_count += loadKeywordDirectory(*iter);
return load_count;
}
void KeywordLoader::loadKeyword(const std::string& filename) {
boost::filesystem::path path( filename );
if (m_verbose)
std::cout << "Loading keyword from file: " << filename << std::endl;
return loadKeyword( path );
}
@@ -144,22 +98,6 @@ namespace Opm {
}
std::vector<std::string> KeywordLoader::sortSubdirectories( const std::string& root_path) {
boost::filesystem::path root(root_path);
if (boost::filesystem::is_directory( root )) {
std::vector<std::string> paths_in_root;
boost::filesystem::directory_iterator end_iterator;
for (boost::filesystem::directory_iterator iter(root); iter != end_iterator; ++iter) {
if (boost::filesystem::is_directory( iter->path() ))
paths_in_root.push_back(iter->path().string());
}
std::sort(paths_in_root.begin(), paths_in_root.end());
return paths_in_root;
} else
throw std::invalid_argument("Input argument is not a directory");
}
std::map<std::string , std::shared_ptr<ParserKeyword> >::const_iterator KeywordLoader::keyword_begin( ) const {
return m_keywords.begin( );

View File

@@ -1,5 +1,5 @@
{
"name" : "ACTION", "sections" : ["SCHEDULE"], "records" : [
"name" : "ACTIONX", "sections" : ["SCHEDULE"], "records" : [
[{"name" : "NAME", "value_type" : "STRING"},
{"name" : "NUM" , "value_type" : "INT", "default" : 1},
{"name" : "MAX_WAIT" , "value_type" : "DOUBLE", "default" : 0, "dimension" : "Time"}],

100
tests/parser/ACTIONX.cpp Normal file
View File

@@ -0,0 +1,100 @@
/*
Copyright 2018 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/>.
*/
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#define BOOST_TEST_MODULE ACTIONX
#include <boost/test/unit_test.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
using namespace Opm;
BOOST_AUTO_TEST_CASE(Create) {
const auto action_kw = std::string{ R"(
ACTIONX
'ACTION' /
WWCT OPX > 0.75 /
/
)"};
ActionX action1("NAME", 10, 100);
BOOST_CHECK_EQUAL(action1.name(), "NAME");
const auto deck = Parser{}.parseString( action_kw );
const auto& kw = deck.getKeyword("ACTIONX");
ActionX action2(kw);
BOOST_CHECK_EQUAL(action2.name(), "ACTION");
}
BOOST_AUTO_TEST_CASE(SCAN) {
const auto MISSING_END= std::string{ R"(
SCHEDULE
ACTIONX
'ACTION' /
WWCT OPX > 0.75 /
/
)"};
const auto WITH_WELSPECS = std::string{ R"(
SCHEDULE
WELSPECS
'W2' 'OP' 1 1 3.33 'OIL' 7*/
/
ACTIONX
'ACTION' /
WWCT OPX > 0.75 /
/
WELSPECS
'W1' 'OP' 1 1 3.33 'OIL' 7*/
/
ENDACTIO
)"};
Opm::Parser parser;
auto deck1 = parser.parseString(MISSING_END, Opm::ParseContext());
auto deck2 = parser.parseString(WITH_WELSPECS, Opm::ParseContext());
EclipseGrid grid1(10,10,10);
TableManager table ( deck1 );
Eclipse3DProperties eclipseProperties ( deck1 , table, grid1);
// The ACTIONX keyword has no matching 'ENDACTIO' -> exception
BOOST_CHECK_THROW(Schedule(deck1, grid1, eclipseProperties, Phases(true,true,true), ParseContext()), std::invalid_argument);
Schedule sched(deck2, grid1, eclipseProperties, Phases(true,true,true), ParseContext());
BOOST_CHECK( !sched.hasWell("W1") );
BOOST_CHECK( sched.hasWell("W2"));
}

View File

@@ -64,46 +64,3 @@ BOOST_AUTO_TEST_CASE(LoadKeyword) {
BOOST_AUTO_TEST_CASE(LoadKeywordDirectory) {
Opm::KeywordLoader loader(false);
BOOST_CHECK_THROW( loader.loadKeywordDirectory("does/not/exists") , std::invalid_argument );
BOOST_CHECK_THROW( loader.loadKeywordDirectory(prefix() + "invalid.json") , std::invalid_argument);
BOOST_CHECK_EQUAL( 4 , loader.loadKeywordDirectory( prefix() + "loader/001_ECLIPSE100"));
BOOST_CHECK( loader.hasKeyword("ADDREG") );
BOOST_CHECK( loader.hasKeyword("ACTNUM") );
BOOST_CHECK( loader.hasKeyword("BOX") );
BOOST_CHECK( loader.hasKeyword("BLOCK_PROBE") );
{
auto kw = loader.getKeyword("ADDREG");
auto record = kw->getRecord(0);
BOOST_CHECK( !record.hasItem("REGION_NUMBER") );
}
}
BOOST_AUTO_TEST_CASE(DirectorySort) {
BOOST_CHECK_THROW( Opm::KeywordLoader::sortSubdirectories( prefix() + "loader/ZCORN") , std::invalid_argument );
std::vector<std::string> dir_list = Opm::KeywordLoader::sortSubdirectories( prefix() + "loader");
namespace fs = boost::filesystem;
BOOST_CHECK_EQUAL( 2U , dir_list.size());
BOOST_CHECK_EQUAL( fs::path( dir_list[0] ), fs::path( prefix() + "loader/001_ECLIPSE100" ) );
BOOST_CHECK_EQUAL( fs::path( dir_list[1] ), fs::path( prefix() + "loader/002_ECLIPSE300" ) );
}
BOOST_AUTO_TEST_CASE(BigLoad) {
Opm::KeywordLoader loader(false);
BOOST_CHECK_THROW( loader.loadMultipleKeywordDirectories("does/not/exists") , std::invalid_argument );
BOOST_CHECK_THROW( loader.loadMultipleKeywordDirectories(prefix() + "invalid.json") , std::invalid_argument);
loader.loadMultipleKeywordDirectories(prefix() + "loader");
BOOST_CHECK( loader.hasKeyword("EQUIL"));
{
auto kw = loader.getKeyword("ADDREG");
auto record = kw->getRecord(0);
BOOST_CHECK( record.hasItem("REGION_NUMBER"));
}
}