@@ -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
|
||||
|
||||
70
opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp
Normal file
70
opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp
Normal 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_ */
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
49
src/opm/parser/eclipse/EclipseState/Schedule/ActionX.cpp
Normal file
49
src/opm/parser/eclipse/EclipseState/Schedule/ActionX.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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( );
|
||||
|
||||
@@ -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
100
tests/parser/ACTIONX.cpp
Normal 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"));
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user