From 488d7655f71a0577c7ef640ac2b09caea70a092a Mon Sep 17 00:00:00 2001 From: Kristian Flikka Date: Wed, 20 Mar 2013 16:29:51 +0100 Subject: [PATCH] Moved files into structure similar to opm-core. Added KeywordRawData class to store 0th pass objects --- {eclipse/docs => docs}/keywordtypes.txt | 0 eclipse/CMakeLists.txt | 2 - eclipse/src/Parser.cpp | 81 --------- eclipse/testdata/gurbat_trimmed.DATA | 160 ------------------ eclipse/testdata/single.data | 2 - .../src => opm/parser/eclipse}/CMakeLists.txt | 4 +- .../parser/eclipse}/EclipseDeck.cpp | 0 .../parser/eclipse}/EclipseDeck.hpp | 0 opm/parser/eclipse/KeywordRawData.cpp | 38 +++++ opm/parser/eclipse/KeywordRawData.hpp | 28 +++ .../src => opm/parser/eclipse}/Logger.cpp | 0 .../src => opm/parser/eclipse}/Logger.hpp | 0 opm/parser/eclipse/Parser.cpp | 131 ++++++++++++++ .../src => opm/parser/eclipse}/Parser.hpp | 18 +- testdata/small.data | 18 ++ {eclipse/src/tests => tests}/CMakeLists.txt | 1 - {eclipse/src/tests => tests}/ParserTests.cpp | 21 +-- 17 files changed, 236 insertions(+), 268 deletions(-) rename {eclipse/docs => docs}/keywordtypes.txt (100%) delete mode 100644 eclipse/CMakeLists.txt delete mode 100644 eclipse/src/Parser.cpp delete mode 100644 eclipse/testdata/gurbat_trimmed.DATA delete mode 100644 eclipse/testdata/single.data rename {eclipse/src => opm/parser/eclipse}/CMakeLists.txt (53%) rename {eclipse/src => opm/parser/eclipse}/EclipseDeck.cpp (100%) rename {eclipse/src => opm/parser/eclipse}/EclipseDeck.hpp (100%) create mode 100644 opm/parser/eclipse/KeywordRawData.cpp create mode 100644 opm/parser/eclipse/KeywordRawData.hpp rename {eclipse/src => opm/parser/eclipse}/Logger.cpp (100%) rename {eclipse/src => opm/parser/eclipse}/Logger.hpp (100%) create mode 100644 opm/parser/eclipse/Parser.cpp rename {eclipse/src => opm/parser/eclipse}/Parser.hpp (67%) create mode 100644 testdata/small.data rename {eclipse/src/tests => tests}/CMakeLists.txt (99%) rename {eclipse/src/tests => tests}/ParserTests.cpp (79%) diff --git a/eclipse/docs/keywordtypes.txt b/docs/keywordtypes.txt similarity index 100% rename from eclipse/docs/keywordtypes.txt rename to docs/keywordtypes.txt diff --git a/eclipse/CMakeLists.txt b/eclipse/CMakeLists.txt deleted file mode 100644 index 814b7bb27..000000000 --- a/eclipse/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory (src) -file(COPY testdata DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/eclipse/src/Parser.cpp b/eclipse/src/Parser.cpp deleted file mode 100644 index 2c253b24d..000000000 --- a/eclipse/src/Parser.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - 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 . - */ - -#include -#include -namespace fs = boost::filesystem; - -#include - -#include "Parser.hpp" - -namespace Opm { - - Parser::Parser() { - } - - Parser::Parser(const std::string &path) { - m_dataFilePath = path; - } - - EclipseDeck Parser::parse(const std::string &path) { - m_logger.setLogLevel(Opm::Logger::INFO); - fs::path pathToCheck(path); - if (!fs::is_regular_file(pathToCheck)) { - m_logger.error("Unable to open file with path: " + path); - throw std::invalid_argument("Given path is not a valid file-path, path: " + path); - } - - ifstream file; - initInputStream(path, file); - EclipseDeck deck = doFileParsing(file); - file.close(); - return deck; - } - - EclipseDeck Parser::parse() { - return parse(m_dataFilePath); - } - - EclipseDeck Parser::doFileParsing(ifstream& inputstream) { - EclipseDeck deck; - std::string line; - while (std::getline(inputstream, line)) { - if (line.substr(0, 2) == "--") { - m_logger.debug("COMMENT LINE < " + line + ">"); - } else if (boost::algorithm::trim_copy(line).length() == 0) { - m_logger.debug("EMPTY LINE <" + line + ">"); - } else if (line.substr(0, 1) != " " && boost::algorithm::to_upper_copy(line) == line) { - deck.addKeyword(line); - m_logger.debug("KEYWORD LINE <" + line + ">"); - } else { - m_logger.debug("SOMETHING ELSE <" + line + ">"); - } - } - return deck; - } - - void Parser::initInputStream(const std::string &path, ifstream& file) { - m_logger.info("Initializing from file: " + path); - file.open(path.c_str()); - } - - Parser::~Parser() { - } -} // namespace Opm diff --git a/eclipse/testdata/gurbat_trimmed.DATA b/eclipse/testdata/gurbat_trimmed.DATA deleted file mode 100644 index 63d8adcc1..000000000 --- a/eclipse/testdata/gurbat_trimmed.DATA +++ /dev/null @@ -1,160 +0,0 @@ --- AUTO-SMOOTHER - ------------------------------------------------------------------ ------------------------------------------------------------------ --- This is the DATA file used by EnKF to run ECLIPSE. It is nearly a 100% --- normal ECLIPSE DATA file, but there have been som modifications to use --- it with EnkF. There are essentially three types of modifications: --- --- * The parameters we want to update/estimate with EnKF are separated --- out in separate files, which are included into this file. --- --- * There are som 'magic strings' looking like this: . These are --- replaced withother content by EnKF before the simulations starts - --- observe that the 'magic strings' never represent parameters to --- update. --- --- * There are some special ECLIPSE keywords which must/must not be --- present in the DATA file. --- --- All the places[1] where the DATA file has been update for EnKF are marked --- with EnKF. --- --- [1]: There are many places with the string /private/joaho/ERT/git/ert/Gurbat - that is --- not essential EnKF - just convenience to get EnKF to insert the --- include path. The value of INCLUDE_PATH must be set with DATA_KW in --- the main configuration file. ------------------------------------------------------------------ ------------------------------------------------------------------ - - ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ --- Reservoir Simulation Model Building Basic Principles: Generic Reservoir --- by Gurbat S. Agaev, 26.06.2006 --- --- Objective: Explain simulation modelling steps --- 3-phase model --- Geological Grid - 120 x 200 x 42 ------------------------------------------------------------------------------------------ --- --- --- ************************************************************************************** --- In this section simulation run specification is given --- ************************************************************************************** --- ------------------------------------------------------------------------------------------ --- ************************************************************************************** -RUNSPEC --- ************************************************************************************** --- Simulation run title -TITLE -Reservoir Simulation Model Building Basic Principles --- --- -------------------------------------------------------------------------------------- --- Simulation grid dimension (Imax, Jmax, Kmax) -DIMENS - 40 64 14 / --- --- -------------------------------------------------------------------------------------- --- Big Model ---BIGMODEL --- --- -------------------------------------------------------------------------------------- --- Simulation run start -START ----- - 1 JAN 2000 / --- --- -------------------------------------------------------------------------------------- --- Fluid phases present -OIL -GAS -WATER -DISGAS -VAPOIL --- --- -------------------------------------------------------------------------------------- --- Measurement unit used -METRIC --- --- -------------------------------------------------------------------------------------- ---Options to process grid data ---If MULTX-, MULTY- and MULTZ- are used, set first parameter= 'YES' -GRIDOPTS --- MULTNUM? NRMULT - 'YES' 1* / -INCLUDE - 'include/example_summary.txt' / - --- Tracer data to be written to SUMMARY file ---FTPRSK1 ---FTPRSK2 ---FTPRSK3 - ---FTPTSK1 ---FTPTSK2 ---FTPTSK3 - ---WTPRSK1 ---/ ---WTPRSK2 ---/ ---WTPRSK3 ---/ - ---WTPTSK1 ---/ ---WTPTSK2 ---/ ---WTPTSK3 ---/ --- --- --- ************************************************************************************** --- In this section data required to describe history and prediction is given --- - well completions, well production/injection, well constraints --- - platform/production unit constraints, etc. --- ************************************************************************************** --- ------------------------------------------------------------------------------------------ --- ************************************************************************************** -SCHEDULE --- ************************************************************************************** ------------------------------------------------------------------------------------------ --- EnKF: RPTSCHED must have RESTART=2 for EnKF to work. -RPTSCHED - RESTART=2 / - --- EnKF: The keyword 'SKIPREST' in the SCHEDULE section is essential --- EnKF: for EnKF to work. -SKIPREST -NOECHO --- --- -------------------------------------------------------------------------------------- --- Schedule file (well comptetions, well constraints, well groups, rates, etc.) --- Generated by SCHEDULE software --- Input data required and input data formats are given in directory --- -INCLUDE - 'target.SCH' / - ---INCLUDE --- 'include/target.SCH' / - --- --- -------------------------------------------------------------------------------------- --- Production well VFP table (used for predictions) ---INCLUDE --- 'include/example_vfp.vfp' / - --- --- -------------------------------------------------------------------------------------- --- If injection well VFP tables are required, include them in this section --- - ---INCLUDE --- 'prediction.sch' / - -END diff --git a/eclipse/testdata/single.data b/eclipse/testdata/single.data deleted file mode 100644 index 921a11873..000000000 --- a/eclipse/testdata/single.data +++ /dev/null @@ -1,2 +0,0 @@ --- Dette er en supertest -HALLOEN \ No newline at end of file diff --git a/eclipse/src/CMakeLists.txt b/opm/parser/eclipse/CMakeLists.txt similarity index 53% rename from eclipse/src/CMakeLists.txt rename to opm/parser/eclipse/CMakeLists.txt index c26e06020..7d25f6ff2 100644 --- a/eclipse/src/CMakeLists.txt +++ b/opm/parser/eclipse/CMakeLists.txt @@ -1,7 +1,5 @@ -add_library(Parser Parser.cpp EclipseDeck.cpp) +add_library(Parser Parser.cpp EclipseDeck.cpp KeywordRawData.cpp) add_library(Logger Logger.cpp) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_subdirectory(tests) - diff --git a/eclipse/src/EclipseDeck.cpp b/opm/parser/eclipse/EclipseDeck.cpp similarity index 100% rename from eclipse/src/EclipseDeck.cpp rename to opm/parser/eclipse/EclipseDeck.cpp diff --git a/eclipse/src/EclipseDeck.hpp b/opm/parser/eclipse/EclipseDeck.hpp similarity index 100% rename from eclipse/src/EclipseDeck.hpp rename to opm/parser/eclipse/EclipseDeck.hpp diff --git a/opm/parser/eclipse/KeywordRawData.cpp b/opm/parser/eclipse/KeywordRawData.cpp new file mode 100644 index 000000000..a2ec0e2b2 --- /dev/null +++ b/opm/parser/eclipse/KeywordRawData.cpp @@ -0,0 +1,38 @@ +/* + 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 . + */ + +#include +#include "KeywordRawData.hpp" +namespace Opm { + + KeywordRawData::KeywordRawData() { + } + + void KeywordRawData::addKeywordDataBlob(const std::string& keyword, const std::list& blob) { + m_keywordRawData.push_back(std::make_pair(keyword, blob)); + } + + int KeywordRawData::numberOfKeywords() { + return m_keywordRawData.size(); + } + + KeywordRawData::~KeywordRawData() { + } +} + diff --git a/opm/parser/eclipse/KeywordRawData.hpp b/opm/parser/eclipse/KeywordRawData.hpp new file mode 100644 index 000000000..224868f98 --- /dev/null +++ b/opm/parser/eclipse/KeywordRawData.hpp @@ -0,0 +1,28 @@ +/* + * File: KeywordRawData.hpp + * Author: kflik + * + * Created on March 20, 2013, 3:59 PM + */ + +#ifndef KEYWORDRAWDATA_HPP +#define KEYWORDRAWDATA_HPP + +#include +#include +#include + +namespace Opm { + + class KeywordRawData { + public: + KeywordRawData(); + void addKeywordDataBlob(const std::string& keyword, const std::list& blob); + int numberOfKeywords(); + virtual ~KeywordRawData(); + private: + std::list< std::pair< std::string, std::list > > m_keywordRawData; + }; +} +#endif /* KEYWORDRAWDATA_HPP */ + diff --git a/eclipse/src/Logger.cpp b/opm/parser/eclipse/Logger.cpp similarity index 100% rename from eclipse/src/Logger.cpp rename to opm/parser/eclipse/Logger.cpp diff --git a/eclipse/src/Logger.hpp b/opm/parser/eclipse/Logger.hpp similarity index 100% rename from eclipse/src/Logger.hpp rename to opm/parser/eclipse/Logger.hpp diff --git a/opm/parser/eclipse/Parser.cpp b/opm/parser/eclipse/Parser.cpp new file mode 100644 index 000000000..f2b920359 --- /dev/null +++ b/opm/parser/eclipse/Parser.cpp @@ -0,0 +1,131 @@ +/* + 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 . + */ +#include +#include +#include + +#include +namespace fs = boost::filesystem; +#include + +#include "Parser.hpp" + +namespace Opm { + + Parser::Parser() { + m_keywordRawData = new KeywordRawData(); + } + + Parser::Parser(const std::string &path) { + m_keywordRawData = new KeywordRawData(); + m_dataFilePath = path; + } + + void Parser::parse(const std::string &path) { + m_logger.setLogLevel(Opm::Logger::DEBUG); + + fs::path pathToCheck(path); + if (!fs::is_regular_file(pathToCheck)) { + m_logger.error("Unable to open file with path: " + path); + throw std::invalid_argument("Given path is not a valid file-path, path: " + path); + } + + std::ifstream file; + initInputStream(path, file); + createKeywordAndRawData(file); + file.close(); + } + + void Parser::parse() { + parse(m_dataFilePath); + } + + int Parser::getNumberOfKeywords() { + return m_keywordRawData -> numberOfKeywords(); + } + + void Parser::createKeywordAndRawData(std::ifstream& inputstream) { + EclipseDeck deck; + std::string line; + std::string currentKeyword = ""; + std::list currentDataBlob; + while (std::getline(inputstream, line)) { + if (isKeyword(line)) { + if (currentKeyword != "") { + m_keywordRawData->addKeywordDataBlob(line, currentDataBlob); + } + currentDataBlob = std::list(); + currentKeyword = line; + } else { + addDataToBlob(line, currentDataBlob); + } + } + if (currentKeyword != "") { + m_keywordRawData->addKeywordDataBlob(line, currentDataBlob); + } + } + + void Parser::addDataToBlob(const std::string& line, std::list& currentDataBlob) { + if (looksLikeData(line)) { + currentDataBlob.push_back(line); + } + } + + bool Parser::looksLikeData(const std::string& line) { + if (line.substr(0, 2) == "--") { + m_logger.debug("COMMENT LINE <" + line + ">"); + return false; + } else if (boost::algorithm::trim_copy(line).length() == 0) { + m_logger.debug("EMPTY LINE <" + line + ">"); + return false; + } else { + m_logger.debug("LOOKS LIKE DATA<" + line + ">"); + return true; + } + } + + bool Parser::isKeyword(const std::string& line) { + std::string keywordRegex = "^[A-Z]{1,8}$"; + int status; + regex_t re; + regmatch_t rm; + if (regcomp(&re, keywordRegex.c_str(), REG_EXTENDED) != 0) { + m_logger.error("Unable to compile regular expression for keyword! Expression: " + keywordRegex); + throw std::runtime_error("Unable to compile regular expression for keyword! Expression: " + keywordRegex); + } + + status = regexec(&re, line.c_str(), 1, &rm, 0); + regfree(&re); + + if (status == 0) { + m_logger.debug("KEYWORD LINE <" + line + ">"); + return true; + } + return false; + } + + void Parser::initInputStream(const std::string &path, std::ifstream& file) { + m_logger.info("Initializing from file: " + path); + file.open(path.c_str()); + } + + Parser::~Parser() { + delete m_keywordRawData; + } +} // namespace Opm diff --git a/eclipse/src/Parser.hpp b/opm/parser/eclipse/Parser.hpp similarity index 67% rename from eclipse/src/Parser.hpp rename to opm/parser/eclipse/Parser.hpp index 94376386a..6db2277c2 100644 --- a/eclipse/src/Parser.hpp +++ b/opm/parser/eclipse/Parser.hpp @@ -19,13 +19,12 @@ #ifndef PARSER_H #define PARSER_H - #include #include -using std::ifstream; #include "EclipseDeck.hpp" #include "Logger.hpp" +#include "KeywordRawData.hpp" namespace Opm { @@ -33,15 +32,20 @@ namespace Opm { public: Parser(); Parser(const std::string &path); - EclipseDeck parse(); - EclipseDeck parse(const std::string &path); - std::string getLog(); + void parse(); + void parse(const std::string &path); + int getNumberOfKeywords(); virtual ~Parser(); private: std::string m_dataFilePath; Logger m_logger; - void initInputStream(const std::string &path, ifstream& file); - EclipseDeck doFileParsing(ifstream& inputstream); + KeywordRawData* m_keywordRawData; + void initInputStream(const std::string &path, std::ifstream& file); + void createKeywordAndRawData(std::ifstream& inputstream); + bool isKeyword(const std::string& line); + void addDataToBlob(const std::string& line, std::list& dataBlob); + bool looksLikeData(const std::string& line); + }; } // namespace Opm #endif /* PARSER_H */ diff --git a/testdata/small.data b/testdata/small.data new file mode 100644 index 000000000..2b83f42aa --- /dev/null +++ b/testdata/small.data @@ -0,0 +1,18 @@ +-- Dette er en supertest, 8 tegn kommer +HALLOENZ + +-- Saa bare en +A + +-- Saa kommer en for lang en + +ABCXYZFFD + +-- Og en med tall + +ABC5ADFC + + +-- Og en med mellomrom etter + +ABC5AD diff --git a/eclipse/src/tests/CMakeLists.txt b/tests/CMakeLists.txt similarity index 99% rename from eclipse/src/tests/CMakeLists.txt rename to tests/CMakeLists.txt index 8525e58e1..7c3065d88 100644 --- a/eclipse/src/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,5 @@ # Add test executable add_executable(runUnitTests ParserTests.cpp) - target_link_libraries(runUnitTests Parser Logger ${Boost_LIBRARIES}) add_test(NAME runUnitTests WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} COMMAND ${EXECUTABLE_OUTPUT_PATH}/runUnitTests ) diff --git a/eclipse/src/tests/ParserTests.cpp b/tests/ParserTests.cpp similarity index 79% rename from eclipse/src/tests/ParserTests.cpp rename to tests/ParserTests.cpp index 063982ec8..93d939f22 100644 --- a/eclipse/src/tests/ParserTests.cpp +++ b/tests/ParserTests.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -25,8 +26,8 @@ #define BOOST_TEST_MODULE ParserTests #include -#include "Parser.hpp" -#include "EclipseDeck.hpp" +#include "opm/parser/eclipse/Parser.hpp" +#include "opm/parser/eclipse/EclipseDeck.hpp" using namespace Opm; @@ -46,7 +47,7 @@ BOOST_AUTO_TEST_CASE(ParseWithInvalidInputFileThrows) { } BOOST_AUTO_TEST_CASE(ParseWithValidFileSetOnParseCallNoThrow) { - boost::filesystem::path singleKeywordFile("testdata/single.data"); + boost::filesystem::path singleKeywordFile("testdata/small.data"); Parser parser; BOOST_REQUIRE_NO_THROW(parser.parse(singleKeywordFile.string())); } @@ -58,21 +59,17 @@ BOOST_AUTO_TEST_CASE(ParseWithInValidFileSetOnParseCallThrows) { } BOOST_AUTO_TEST_CASE(ParseFileWithOneKeyword) { - boost::filesystem::path singleKeywordFile("testdata/single.data"); + boost::filesystem::path singleKeywordFile("testdata/small.data"); Parser parser(singleKeywordFile.string()); - EclipseDeck deck = parser.parse(); - - BOOST_REQUIRE_EQUAL(1, deck.getNumberOfKeywords()); - BOOST_REQUIRE_EQUAL((unsigned int)1, deck.getKeywords().size()); + parser.parse(); + BOOST_REQUIRE_EQUAL(2, parser.getNumberOfKeywords()); } BOOST_AUTO_TEST_CASE(ParseFileWithManyKeywords) { boost::filesystem::path multipleKeywordFile("testdata/gurbat_trimmed.DATA"); Parser parser(multipleKeywordFile.string()); - EclipseDeck deck = parser.parse(); - - BOOST_REQUIRE_EQUAL(18, deck.getNumberOfKeywords()); - BOOST_REQUIRE_EQUAL((unsigned int)18, deck.getKeywords().size()); + parser.parse(); + BOOST_REQUIRE_EQUAL(18, parser.getNumberOfKeywords()); }