Moved files into structure similar to opm-core. Added KeywordRawData class to store 0th pass objects

This commit is contained in:
Kristian Flikka
2013-03-20 16:29:51 +01:00
parent 7d6bba588b
commit 488d7655f7
17 changed files with 236 additions and 268 deletions

View File

@@ -1,2 +0,0 @@
add_subdirectory (src)
file(COPY testdata DESTINATION ${CMAKE_BINARY_DIR})

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#include <boost/algorithm/string.hpp>
#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

View File

@@ -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: <xxxx>. 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

View File

@@ -1,2 +0,0 @@
-- Dette er en supertest
HALLOEN

View File

@@ -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)

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <utility>
#include "KeywordRawData.hpp"
namespace Opm {
KeywordRawData::KeywordRawData() {
}
void KeywordRawData::addKeywordDataBlob(const std::string& keyword, const std::list<std::string>& blob) {
m_keywordRawData.push_back(std::make_pair(keyword, blob));
}
int KeywordRawData::numberOfKeywords() {
return m_keywordRawData.size();
}
KeywordRawData::~KeywordRawData() {
}
}

View File

@@ -0,0 +1,28 @@
/*
* File: KeywordRawData.hpp
* Author: kflik
*
* Created on March 20, 2013, 3:59 PM
*/
#ifndef KEYWORDRAWDATA_HPP
#define KEYWORDRAWDATA_HPP
#include <string>
#include <utility>
#include <list>
namespace Opm {
class KeywordRawData {
public:
KeywordRawData();
void addKeywordDataBlob(const std::string& keyword, const std::list<std::string>& blob);
int numberOfKeywords();
virtual ~KeywordRawData();
private:
std::list< std::pair< std::string, std::list<std::string > > > m_keywordRawData;
};
}
#endif /* KEYWORDRAWDATA_HPP */

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <stdexcept>
#include <regex.h>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
#include <boost/algorithm/string.hpp>
#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<std::string> currentDataBlob;
while (std::getline(inputstream, line)) {
if (isKeyword(line)) {
if (currentKeyword != "") {
m_keywordRawData->addKeywordDataBlob(line, currentDataBlob);
}
currentDataBlob = std::list<std::string>();
currentKeyword = line;
} else {
addDataToBlob(line, currentDataBlob);
}
}
if (currentKeyword != "") {
m_keywordRawData->addKeywordDataBlob(line, currentDataBlob);
}
}
void Parser::addDataToBlob(const std::string& line, std::list<std::string>& 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

View File

@@ -19,13 +19,12 @@
#ifndef PARSER_H
#define PARSER_H
#include <string>
#include <fstream>
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<std::string>& dataBlob);
bool looksLikeData(const std::string& line);
};
} // namespace Opm
#endif /* PARSER_H */

18
testdata/small.data vendored Normal file
View File

@@ -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

View File

@@ -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 )

View File

@@ -18,6 +18,7 @@
*/
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
@@ -25,8 +26,8 @@
#define BOOST_TEST_MODULE ParserTests
#include <boost/test/unit_test.hpp>
#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());
}