can parse keywords of type double-record.
... ParserKeyword: bool double_records set. added keywords CECONT. ParserKeywords: double_records set by keyword generator. Parsertests: added test for parsing double_records. ParserKeywords.parse: if double_records returns empty. double_records keywords set to SLASH_TERMINATED. ... ParserKeyword: for double records size_type = DOUBLE_SLASH_TERMINATED. double_records: RawKeyword is Raw::DOUBLE_SLASH_TERMINATED. RawKeyword uses m_isTempFinished. Parser: can parse files with double-record keywords. Parser.cpp/RawRecord.cpp: removed comments. DeckKeyword has param m_isDoubleRecordKeyword. test ParseDoubleRecords: double records to have linear structure. DeckKeyword: Can create records of type double_record. double-records parser test transferred to ParserTests.cpp. ... ...
This commit is contained in:
@@ -58,7 +58,9 @@ namespace Opm {
|
||||
DeckRecord& getRecord(size_t index);
|
||||
const DeckRecord& getDataRecord() const;
|
||||
void setDataKeyword(bool isDataKeyword = true);
|
||||
void setDoubleRecordKeyword(bool isDoubleRecordKeyword = true);
|
||||
bool isDataKeyword() const;
|
||||
bool isDoubleRecordKeyword() const;
|
||||
|
||||
const std::vector<int>& getIntData() const;
|
||||
const std::vector<double>& getRawDoubleData() const;
|
||||
@@ -93,6 +95,7 @@ namespace Opm {
|
||||
std::vector< DeckRecord > m_recordList;
|
||||
bool m_isDataKeyword;
|
||||
bool m_slashTerminated;
|
||||
bool m_isDoubleRecordKeyword = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace Opm {
|
||||
FIXED = 1,
|
||||
OTHER_KEYWORD_IN_DECK = 2,
|
||||
UNKNOWN = 3,
|
||||
FIXED_CODE = 4
|
||||
FIXED_CODE = 4,
|
||||
DOUBLE_SLASH_TERMINATED = 5
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -131,7 +131,9 @@ namespace Opm {
|
||||
bool rawStringKeyword() const;
|
||||
bool isCodeKeyword() const;
|
||||
bool isAlternatingKeyword() const;
|
||||
bool isDoubleRecordKeyword() const;
|
||||
void setAlternatingKeyword(bool alternating);
|
||||
void setDoubleRecordsKeyword(bool double_rec);
|
||||
|
||||
std::string createDeclaration(const std::string& indent) const;
|
||||
std::string createDecl() const;
|
||||
@@ -154,6 +156,7 @@ namespace Opm {
|
||||
std::string m_Description;
|
||||
bool raw_string_keyword = false;
|
||||
bool alternating_keyword = false;
|
||||
bool double_records = false;
|
||||
std::string code_end;
|
||||
|
||||
static bool validNameStart(const string_view& name);
|
||||
|
||||
@@ -189,10 +189,18 @@ namespace Opm {
|
||||
m_isDataKeyword = isDataKeyword_;
|
||||
}
|
||||
|
||||
void DeckKeyword::setDoubleRecordKeyword(bool isDoubleRecordKeyword) {
|
||||
m_isDoubleRecordKeyword = isDoubleRecordKeyword;
|
||||
}
|
||||
|
||||
bool DeckKeyword::isDataKeyword() const {
|
||||
return m_isDataKeyword;
|
||||
}
|
||||
|
||||
bool DeckKeyword::isDoubleRecordKeyword() const {
|
||||
return m_isDoubleRecordKeyword;
|
||||
}
|
||||
|
||||
const std::string& DeckKeyword::name() const {
|
||||
return m_keywordName;
|
||||
}
|
||||
|
||||
@@ -560,11 +560,16 @@ void ParserState::addPathAlias( const std::string& alias, const std::string& pat
|
||||
RawKeyword * newRawKeyword(const ParserKeyword& parserKeyword, const std::string& keywordString, ParserState& parserState, const Parser& parser) {
|
||||
bool raw_string_keyword = parserKeyword.rawStringKeyword();
|
||||
|
||||
if( parserKeyword.getSizeType() == SLASH_TERMINATED || parserKeyword.getSizeType() == UNKNOWN) {
|
||||
if( parserKeyword.getSizeType() == SLASH_TERMINATED || parserKeyword.getSizeType() == UNKNOWN || parserKeyword.getSizeType() == DOUBLE_SLASH_TERMINATED) {
|
||||
|
||||
const auto rawSizeType = parserKeyword.getSizeType() == SLASH_TERMINATED
|
||||
? Raw::SLASH_TERMINATED
|
||||
: Raw::UNKNOWN;
|
||||
const auto size_type = parserKeyword.getSizeType();
|
||||
Raw::KeywordSizeEnum rawSizeType;
|
||||
|
||||
switch(size_type) {
|
||||
case SLASH_TERMINATED: rawSizeType = Raw::SLASH_TERMINATED; break;
|
||||
case UNKNOWN: rawSizeType = Raw::UNKNOWN; break;
|
||||
case DOUBLE_SLASH_TERMINATED: rawSizeType = Raw::DOUBLE_SLASH_TERMINATED; break;
|
||||
}
|
||||
|
||||
return new RawKeyword( keywordString,
|
||||
parserState.current_path().string(),
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace Opm {
|
||||
case FIXED_CODE:
|
||||
return "FIXED_CODE";
|
||||
break;
|
||||
case DOUBLE_SLASH_TERMINATED:
|
||||
return "DOUBLE_SLASH_TERMINATED";
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Implementation error - should NOT be here");
|
||||
}
|
||||
|
||||
@@ -140,6 +140,11 @@ namespace Opm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jsonConfig.has_item("records_set")) {
|
||||
m_keywordSizeType = DOUBLE_SLASH_TERMINATED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (jsonConfig.has_item("items") || jsonConfig.has_item("records")) {
|
||||
// The number of records is undetermined - the keyword will be '/'
|
||||
// terminated.
|
||||
@@ -184,7 +189,9 @@ namespace Opm {
|
||||
initSectionNames(jsonConfig);
|
||||
initMatchRegex(jsonConfig);
|
||||
|
||||
if (jsonConfig.has_item("items") && (jsonConfig.has_item("records") || jsonConfig.has_item("alternating_records")))
|
||||
if (jsonConfig.has_item("items") && (jsonConfig.has_item("records") ||
|
||||
jsonConfig.has_item("alternating_records") ||
|
||||
jsonConfig.has_item("records_set") ))
|
||||
throw std::invalid_argument("Fatal error in " + getName() + " configuration. Can NOT have both records: and items:");
|
||||
|
||||
if (jsonConfig.has_item("items")) {
|
||||
@@ -205,6 +212,12 @@ namespace Opm {
|
||||
parseRecords( recordsConfig );
|
||||
}
|
||||
|
||||
if (jsonConfig.has_item("records_set")) {
|
||||
double_records = true;
|
||||
const Json::JsonObject recordsConfig = jsonConfig.get_item("records_set");
|
||||
parseRecords( recordsConfig );
|
||||
}
|
||||
|
||||
if (jsonConfig.has_item("data"))
|
||||
initData(jsonConfig);
|
||||
|
||||
@@ -523,19 +536,40 @@ void set_dimensions( ParserItem& item,
|
||||
UnitSystem& active_unitsystem,
|
||||
UnitSystem& default_unitsystem,
|
||||
const std::string& filename) const {
|
||||
|
||||
if( !rawKeyword.isFinished() )
|
||||
throw std::invalid_argument("Tried to create a deck keyword from an incomplete raw keyword " + rawKeyword.getKeywordName());
|
||||
|
||||
DeckKeyword keyword( rawKeyword.location(), rawKeyword.getKeywordName() );
|
||||
keyword.setDataKeyword( isDataKeyword() );
|
||||
|
||||
size_t record_nr = 0;
|
||||
for( auto& rawRecord : rawKeyword ) {
|
||||
if( m_records.size() == 0 && rawRecord.size() > 0 )
|
||||
throw std::invalid_argument("Missing item information " + rawKeyword.getKeywordName());
|
||||
if (double_records)
|
||||
keyword.setDoubleRecordKeyword();
|
||||
|
||||
keyword.addRecord( this->getRecord( record_nr ).parse( parseContext, errors, rawRecord, active_unitsystem, default_unitsystem, rawKeyword.getKeywordName(), filename ) );
|
||||
record_nr++;
|
||||
if (double_records) {
|
||||
/* Note: this merely dumps all records sequentially into m_recordList.
|
||||
In order to actually use double-record keywords, DeckKeyword needs to have a
|
||||
2-dimensional DeckRecord structure, e.g.
|
||||
std::vector< std::vector<DeckRecord >> m_recordList; */
|
||||
size_t record_nr = 0;
|
||||
for (auto& rawRecord : rawKeyword) {
|
||||
if (rawRecord.size() == 0)
|
||||
record_nr = 0;
|
||||
else {
|
||||
keyword.addRecord( this->getRecord( record_nr ).parse( parseContext, errors, rawRecord, active_unitsystem, default_unitsystem, rawKeyword.getKeywordName(), filename ) );
|
||||
record_nr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t record_nr = 0;
|
||||
for( auto& rawRecord : rawKeyword ) {
|
||||
if( m_records.size() == 0 && rawRecord.size() > 0 )
|
||||
throw std::invalid_argument("Missing item information " + rawKeyword.getKeywordName());
|
||||
|
||||
keyword.addRecord( this->getRecord( record_nr ).parse( parseContext, errors, rawRecord, active_unitsystem, default_unitsystem, rawKeyword.getKeywordName(), filename ) );
|
||||
record_nr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hasFixedSize( ))
|
||||
@@ -588,10 +622,18 @@ void set_dimensions( ParserItem& item,
|
||||
return alternating_keyword;
|
||||
}
|
||||
|
||||
bool ParserKeyword::isDoubleRecordKeyword() const {
|
||||
return double_records;
|
||||
}
|
||||
|
||||
void ParserKeyword::setAlternatingKeyword(bool alternating) {
|
||||
alternating_keyword = alternating;
|
||||
}
|
||||
|
||||
void ParserKeyword::setDoubleRecordsKeyword(bool double_rec) {
|
||||
double_records = double_rec;
|
||||
}
|
||||
|
||||
bool ParserKeyword::hasMatchRegex() const {
|
||||
return !m_matchRegexString.empty();
|
||||
}
|
||||
@@ -662,6 +704,7 @@ void set_dimensions( ParserItem& item,
|
||||
switch (m_keywordSizeType) {
|
||||
case SLASH_TERMINATED:
|
||||
case FIXED_CODE:
|
||||
case DOUBLE_SLASH_TERMINATED:
|
||||
case UNKNOWN:
|
||||
ss << "setSizeType(" << sizeString << ");" << '\n';
|
||||
break;
|
||||
@@ -698,6 +741,10 @@ void set_dimensions( ParserItem& item,
|
||||
if (alternating_keyword)
|
||||
ss << indent << "setAlternatingKeyword(true);" << '\n';
|
||||
|
||||
// set DoubleRecords
|
||||
if (double_records)
|
||||
ss << indent << "setDoubleRecordsKeyword(true);" << '\n';
|
||||
|
||||
// set the deck name match regex
|
||||
if (hasMatchRegex())
|
||||
ss << indent << "setMatchRegex(\"" << m_matchRegexString << "\");" << '\n';
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Opm {
|
||||
UNKNOWN = 3,
|
||||
TABLE_COLLECTION = 4,
|
||||
CODE = 5,
|
||||
DOUBLE_SLASH_TERMINATED = 6
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,13 @@ namespace {
|
||||
if (this->m_sizeType == Raw::SLASH_TERMINATED)
|
||||
this->m_isFinished = true;
|
||||
|
||||
if (this->m_sizeType == Raw::DOUBLE_SLASH_TERMINATED) {
|
||||
if (m_isTempFinished)
|
||||
this->m_isFinished = true;
|
||||
else
|
||||
this->m_isTempFinished = true;
|
||||
}
|
||||
|
||||
if (m_sizeType == Raw::TABLE_COLLECTION) {
|
||||
m_currentNumTables += 1;
|
||||
if (m_currentNumTables == m_numTables)
|
||||
@@ -110,12 +117,15 @@ namespace {
|
||||
|
||||
|
||||
bool RawKeyword::addRecord(RawRecord record) {
|
||||
|
||||
if (record.size() > 0)
|
||||
m_isTempFinished = false;
|
||||
|
||||
this->m_records.push_back(std::move(record));
|
||||
if (m_records.size() == this->m_fixedSize) {
|
||||
if( this->m_sizeType == Raw::FIXED || this->m_sizeType == Raw::CODE)
|
||||
this->m_isFinished = true;
|
||||
}
|
||||
|
||||
return this->m_isFinished;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Opm {
|
||||
size_t m_fixedSize = 0;
|
||||
size_t m_numTables = 0;
|
||||
size_t m_currentNumTables = 0;
|
||||
bool m_isTempFinished = false;
|
||||
bool m_isFinished = false;
|
||||
|
||||
std::vector< RawRecord > m_records;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name" : "CECONT", "sections" : ["SCHEDULE"], "records_set" : [
|
||||
[
|
||||
{"name" : "WELL", "value_type" : "STRING"},
|
||||
{"name" : "I", "value_type" : "INT", "default" : 0},
|
||||
{"name" : "J", "value_type" : "INT", "default" : 0},
|
||||
{"name" : "K_UPPER", "value_type" : "INT", "default" : 0},
|
||||
{"name" : "K_LOWER", "value_type" : "INT", "default" : 0},
|
||||
{"name" : "PROCEDURE", "value_type" : "STRING", "default" : "CON"},
|
||||
{"name" : "CHECK_STOPPED_WELLS", "value_type" : "STRING", "default" : "NO"}
|
||||
],
|
||||
[
|
||||
{"name" : "TRACER", "value_type" : "STRING"},
|
||||
{"name" : "MAX_TOTAL_TRACER_RATE", "value_type" : "DOUBLE", "default" : 1e200},
|
||||
{"name" : "MAX_TOTAL_TRACER_CONC", "value_type" : "DOUBLE", "default" : 1e200},
|
||||
{"name" : "MAX_FREE_TRACER_RATE", "value_type" : "DOUBLE", "default" : 1e200},
|
||||
{"name" : "MAX_FREE_TRACER_CONC", "value_type" : "DOUBLE", "default" : 1e200},
|
||||
{"name" : "MAX_SOL_TRACER_RATE", "value_type" : "DOUBLE", "default" : 1e200},
|
||||
{"name" : "MAX_SOL_TRACER_CONC", "value_type" : "DOUBLE", "default" : 1e200}
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -79,6 +79,7 @@ set( keywords
|
||||
000_Eclipse100/C/CART
|
||||
000_Eclipse100/C/CBMOPTS
|
||||
000_Eclipse100/C/CECON
|
||||
000_Eclipse100/C/CECONT
|
||||
000_Eclipse100/C/COAL
|
||||
000_Eclipse100/C/COALADS
|
||||
000_Eclipse100/C/COALNUM
|
||||
|
||||
@@ -1774,6 +1774,38 @@ BOOST_AUTO_TEST_CASE(GetAlternatingKeywordFromParser) {
|
||||
BOOST_CHECK(kw.getRecord(13) == record1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ConstructFromJson_withDoubleRecords) {
|
||||
const std::string json_string = R"(
|
||||
{"name" : "CECONT", "sections" : ["PROPS"] , "records_set" : [[
|
||||
{"name" : "WELL", "value_type" : "STRING"},
|
||||
{"name" : "I", "value_type" : "INT"},
|
||||
{"name" : "J", "value_type" : "INT"},
|
||||
{"name" : "K", "value_type" : "INT"}], [
|
||||
{"name" : "TRACER" , "value_type" : "STRING"},
|
||||
{"name" : "rate", "value_type" : "DOUBLE"}]]}
|
||||
)";
|
||||
Json::JsonObject jsonObject( json_string );
|
||||
ParserKeyword kw( jsonObject );
|
||||
BOOST_CHECK( kw.isDoubleRecordKeyword() );
|
||||
BOOST_CHECK_EQUAL(kw.getRecord(0).size(), 4);
|
||||
BOOST_CHECK_EQUAL(kw.getRecord(1).size(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GetDoubleRecordKeywordFromParser) {
|
||||
Parser parser;
|
||||
BOOST_CHECK(parser.hasKeyword("CECONT"));
|
||||
ParserKeyword kw = parser.getKeyword("CECONT");
|
||||
BOOST_CHECK(kw.isDoubleRecordKeyword());
|
||||
BOOST_CHECK(kw.getSizeType() == DOUBLE_SLASH_TERMINATED);
|
||||
auto record0 = kw.getRecord(0);
|
||||
auto record1 = kw.getRecord(1);
|
||||
BOOST_CHECK_EQUAL(record0.get(0).name(), "WELL");
|
||||
BOOST_CHECK_EQUAL(record1.get(0).name(), "TRACER");
|
||||
BOOST_CHECK(kw.getRecord(11) == record1);
|
||||
BOOST_CHECK(kw.getRecord(13) == record1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Create1Arg) {
|
||||
ParserKeyword kw("GRID");
|
||||
@@ -2136,4 +2168,78 @@ DENSITY
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ParseDoubleRecords) {
|
||||
const auto deck_string = std::string { R"(
|
||||
RUNSPEC
|
||||
FIELD
|
||||
TABDIMS
|
||||
1* 2
|
||||
/
|
||||
|
||||
PROPS
|
||||
|
||||
DENSITY
|
||||
50.91 62.4 /
|
||||
51.90 64.2 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
CECONT
|
||||
PROD1 4* CON NO /
|
||||
TR1 1000.0 0.5 /
|
||||
TR2 2* 1* 0.8 2* /
|
||||
TR3 1500.0 0.1 /
|
||||
/
|
||||
PROD2 5 6 3 3 CON+ NO /
|
||||
TR3 100.0 0.05 /
|
||||
/
|
||||
PROD3 6* /
|
||||
TR4 200 5* /
|
||||
PLY 1* 0.7 /
|
||||
/
|
||||
/
|
||||
|
||||
GCONSUMP
|
||||
PLAT-A 20 50 /
|
||||
PLAT-B 15 /
|
||||
/
|
||||
|
||||
)" };
|
||||
Parser parser;
|
||||
auto deck = parser.parseString(deck_string);
|
||||
BOOST_CHECK( deck.hasKeyword("CECONT") );
|
||||
BOOST_CHECK( deck.hasKeyword("GCONSUMP") );
|
||||
|
||||
auto kw_density = deck.getKeyword("DENSITY");
|
||||
|
||||
auto kw = deck.getKeyword("CECONT");
|
||||
BOOST_CHECK( kw.isDoubleRecordKeyword() );
|
||||
|
||||
auto record00 = kw.getRecord(0);
|
||||
BOOST_CHECK_EQUAL(record00.getItem(0).name(), "WELL");
|
||||
BOOST_CHECK_EQUAL(record00.getItem(0).get<std::string>(0), "PROD1");
|
||||
BOOST_CHECK(record00.getItem(1).getType() == type_tag::integer);
|
||||
BOOST_CHECK_EQUAL(record00.getItem(1).get<int>(0), 0);
|
||||
|
||||
auto record01 = kw.getRecord(1);
|
||||
BOOST_CHECK_EQUAL(record01.getItem(0).name(), "TRACER");
|
||||
BOOST_CHECK_EQUAL(record01.getItem(0).get<std::string>(0), "TR1");
|
||||
BOOST_CHECK(record01.getItem(1).getType() == type_tag::fdouble);
|
||||
BOOST_CHECK_EQUAL(record01.getItem(1).get<double>(0), 1000);
|
||||
|
||||
auto record04 = kw.getRecord(4);
|
||||
BOOST_CHECK_EQUAL(record04.getItem(0).name(), "WELL");
|
||||
BOOST_CHECK_EQUAL(record04.getItem(0).get<std::string>(0), "PROD2");
|
||||
BOOST_CHECK(record04.getItem(1).getType() == type_tag::integer);
|
||||
BOOST_CHECK_EQUAL(record04.getItem(1).get<int>(0), 5);
|
||||
|
||||
auto record08 = kw.getRecord(8);
|
||||
BOOST_CHECK_EQUAL(record08.getItem(0).name(), "TRACER");
|
||||
BOOST_CHECK_EQUAL(record08.getItem(0).get<std::string>(0), "PLY");
|
||||
BOOST_CHECK(record08.getItem(2).getType() == type_tag::fdouble);
|
||||
BOOST_CHECK_EQUAL(record08.getItem(2).get<double>(0), 0.7);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user