From b72df6f4069b18e4068226576e44cc9e417de050 Mon Sep 17 00:00:00 2001 From: Andreas Lauser Date: Fri, 12 Sep 2014 12:23:37 +0200 Subject: [PATCH] make ParserItems always defaultable i.e. remove the defaultSet() method and its friends. this is required to be able to specify defaults in DATA items like grid properties or saturation tables. e.g. SGL 10*0.1 10* 10*0.2 / would not be possible without this. If no meaningful default for an item is defined, float and double items get NaN, int items get -1 and string ones get an empty string. The hope is that if these values get used in the simulation, they will make the result obviously incorrect. (Whether a data point of an item was defaulted can be queried using item->defaultApplied(index).) --- .../eclipse/EclipseState/EclipseState.cpp | 12 +++---- .../EclipseState/Schedule/Completion.cpp | 11 +++---- .../IntegrationTests/IntegrationTests.cpp | 6 ++-- .../eclipse/IntegrationTests/ParsePVTO.cpp | 1 + .../eclipse/Parser/ParserDoubleItem.cpp | 10 +++--- opm/parser/eclipse/Parser/ParserFloatItem.cpp | 10 +++--- opm/parser/eclipse/Parser/ParserIntItem.cpp | 11 ++++--- opm/parser/eclipse/Parser/ParserItem.hpp | 23 +++++--------- .../eclipse/Parser/ParserStringItem.cpp | 8 ++--- .../eclipse/Parser/tests/ParserItemTests.cpp | 31 +++++++++++++------ .../eclipse/Utility/MultiRecordTable.cpp | 2 +- 11 files changed, 69 insertions(+), 56 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/EclipseState.cpp b/opm/parser/eclipse/EclipseState/EclipseState.cpp index 9d9064630..ee116d0a4 100644 --- a/opm/parser/eclipse/EclipseState/EclipseState.cpp +++ b/opm/parser/eclipse/EclipseState/EclipseState.cpp @@ -671,22 +671,22 @@ namespace Opm { size_t setCount = 0; - if (I1Item->size() > 0 && !I1Item->defaultApplied(0)) + if (!I1Item->defaultApplied(0)) setCount++; - if (I2Item->size() > 0 && !I2Item->defaultApplied(0)) + if (!I2Item->defaultApplied(0)) setCount++; - if (J1Item->size() > 0 && !J1Item->defaultApplied(0)) + if (!J1Item->defaultApplied(0)) setCount++; - if (J2Item->size() > 0 && !J2Item->defaultApplied(0)) + if (!J2Item->defaultApplied(0)) setCount++; - if (K1Item->size() > 0 && !K1Item->defaultApplied(0)) + if (!K1Item->defaultApplied(0)) setCount++; - if (K2Item->size() > 0 && !K2Item->defaultApplied(0)) + if (!K2Item->defaultApplied(0)) setCount++; if (setCount == 6) { diff --git a/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp b/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp index 10fd5c4ed..08249155c 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp @@ -71,14 +71,11 @@ namespace Opm { DeckItemConstPtr diameterItem = compdatRecord->getItem("DIAMETER"); DeckItemConstPtr skinFactorItem = compdatRecord->getItem("SKIN"); - if (connectionTransmissibilityFactorItem->size() > 0 && !connectionTransmissibilityFactorItem->defaultApplied(0)) - connectionTransmissibilityFactor.setValue( connectionTransmissibilityFactorItem->getSIDouble(0)); - - if (diameterItem->size() > 0 && !diameterItem->defaultApplied(0)) - diameter.setValue( diameterItem->getSIDouble(0)); + if (!connectionTransmissibilityFactorItem->defaultApplied(0)) + connectionTransmissibilityFactor.setValue(connectionTransmissibilityFactorItem->getSIDouble(0)); - if (skinFactorItem->size() > 0 && !skinFactorItem->defaultApplied(0)) - skinFactor.setValue( skinFactorItem->getRawDouble(0)); + diameter.setValue( diameterItem->getSIDouble(0)); + skinFactor.setValue( skinFactorItem->getRawDouble(0)); } const CompletionDirection::DirectionEnum& direction = CompletionDirection::DirectionEnumFromString(compdatRecord->getItem("DIR")->getTrimmedString(0)); diff --git a/opm/parser/eclipse/IntegrationTests/IntegrationTests.cpp b/opm/parser/eclipse/IntegrationTests/IntegrationTests.cpp index ab225c7fb..f057b372f 100644 --- a/opm/parser/eclipse/IntegrationTests/IntegrationTests.cpp +++ b/opm/parser/eclipse/IntegrationTests/IntegrationTests.cpp @@ -235,14 +235,16 @@ BOOST_AUTO_TEST_CASE(parse_truncatedrecords_deckFilledWithDefaults) { BOOST_CHECK_EQUAL("NAME", radfin4_1_partial->getRecord(0)->getItem(0)->getString(0)); // Default string - BOOST_CHECK_THROW(radfin4_2_nodata->getRecord(0)->getItem(0)->getString(0), std::out_of_range); + BOOST_CHECK_NO_THROW(radfin4_2_nodata->getRecord(0)->getItem(0)->getString(0)); + BOOST_CHECK( radfin4_2_nodata->getRecord(0)->getItem(0)->defaultApplied(0)); // Specified in datafile BOOST_CHECK_EQUAL(213, radfin4_0_full->getRecord(0)->getItem(1)->getInt(0)); BOOST_CHECK_EQUAL(213, radfin4_1_partial->getRecord(0)->getItem(1)->getInt(0)); // Default int - BOOST_CHECK_THROW( radfin4_2_nodata->getRecord(0)->getItem(1)->getInt(0), std::out_of_range); + BOOST_CHECK_NO_THROW( radfin4_2_nodata->getRecord(0)->getItem(1)->getInt(0)); + BOOST_CHECK( radfin4_2_nodata->getRecord(0)->getItem(1)->defaultApplied(0)); ParserKeywordConstPtr parserKeyword = parser->getParserKeywordFromDeckName("RADFIN4"); diff --git a/opm/parser/eclipse/IntegrationTests/ParsePVTO.cpp b/opm/parser/eclipse/IntegrationTests/ParsePVTO.cpp index a86a9ecb5..2c977e849 100644 --- a/opm/parser/eclipse/IntegrationTests/ParsePVTO.cpp +++ b/opm/parser/eclipse/IntegrationTests/ParsePVTO.cpp @@ -86,6 +86,7 @@ static void check_parser(ParserPtr parser) { DeckItemConstPtr item2_0 = record2->getItem("RS"); DeckItemConstPtr item2_1 = record2->getItem("DATA"); + BOOST_CHECK(item2_0->defaultApplied(0)); BOOST_CHECK_EQUAL(0U , item2_1->size()); BOOST_CHECK_EQUAL(2U , record2->size()); diff --git a/opm/parser/eclipse/Parser/ParserDoubleItem.cpp b/opm/parser/eclipse/Parser/ParserDoubleItem.cpp index c4774389c..2719b4f2d 100644 --- a/opm/parser/eclipse/Parser/ParserDoubleItem.cpp +++ b/opm/parser/eclipse/Parser/ParserDoubleItem.cpp @@ -34,10 +34,14 @@ namespace Opm ParserItemSizeEnum sizeType_) : ParserItem(itemName, sizeType_) { + // use NaN as 'default default'. (Keep in mind that in the deck it can be queried + // using deckItem->defaultApplied(idx) if an item was defaulted or not... + m_default = std::numeric_limits::quiet_NaN(); } ParserDoubleItem::ParserDoubleItem(const std::string& itemName) : ParserItem(itemName) { + m_default = std::numeric_limits::quiet_NaN(); } @@ -54,10 +58,7 @@ namespace Opm double ParserDoubleItem::getDefault() const { - if (m_defaultSet) - return m_default; - else - throw std::invalid_argument("Tried get default from parser item " + name() + " No default has been configured"); + return m_default; } @@ -71,6 +72,7 @@ namespace Opm ParserDoubleItem::ParserDoubleItem(const Json::JsonObject& jsonConfig) : ParserItem(jsonConfig) { + m_default = std::numeric_limits::quiet_NaN(); if (jsonConfig.has_item("default")) setDefault( jsonConfig.get_double("default") ); } diff --git a/opm/parser/eclipse/Parser/ParserFloatItem.cpp b/opm/parser/eclipse/Parser/ParserFloatItem.cpp index 5ae8b1db2..b03d34585 100644 --- a/opm/parser/eclipse/Parser/ParserFloatItem.cpp +++ b/opm/parser/eclipse/Parser/ParserFloatItem.cpp @@ -34,10 +34,14 @@ namespace Opm ParserItemSizeEnum sizeType_) : ParserItem(itemName, sizeType_) { + // use NaN as 'default default'. (Keep in mind that in the deck it can be queried + // using deckItem->defaultApplied(idx) if an item was defaulted or not... + m_default = std::numeric_limits::quiet_NaN(); } ParserFloatItem::ParserFloatItem(const std::string& itemName) : ParserItem(itemName) { + m_default = std::numeric_limits::quiet_NaN(); } @@ -54,10 +58,7 @@ namespace Opm float ParserFloatItem::getDefault() const { - if (m_defaultSet) - return m_default; - else - throw std::invalid_argument("Tried get default from parser item " + name() + " No default has been configured"); + return m_default; } @@ -73,6 +74,7 @@ namespace Opm ParserFloatItem::ParserFloatItem(const Json::JsonObject& jsonConfig) : ParserItem(jsonConfig) { + m_default = std::numeric_limits::quiet_NaN(); if (jsonConfig.has_item("default")) setDefault( jsonConfig.get_double("default")); } diff --git a/opm/parser/eclipse/Parser/ParserIntItem.cpp b/opm/parser/eclipse/Parser/ParserIntItem.cpp index 7ff300214..dfebf1347 100644 --- a/opm/parser/eclipse/Parser/ParserIntItem.cpp +++ b/opm/parser/eclipse/Parser/ParserIntItem.cpp @@ -30,10 +30,15 @@ namespace Opm { ParserIntItem::ParserIntItem(const std::string& itemName) : ParserItem(itemName) { + // integers do not have a representation for NaN. Let's use a negative value as + // this is usually meaningless. (Keep in mind that in the deck it can be queried + // using deckItem->defaultApplied(idx) if an item was defaulted or not... + m_default = -1; } ParserIntItem::ParserIntItem(const std::string& itemName, ParserItemSizeEnum sizeType_) : ParserItem(itemName, sizeType_) { + m_default = -1; } ParserIntItem::ParserIntItem(const std::string& itemName, int defaultValue) : ParserItem(itemName) @@ -49,6 +54,7 @@ namespace Opm { ParserIntItem::ParserIntItem(const Json::JsonObject& jsonConfig) : ParserItem(jsonConfig) { + m_default = -1; if (jsonConfig.has_item("default")) setDefault( jsonConfig.get_int("default") ); } @@ -62,10 +68,7 @@ namespace Opm { } int ParserIntItem::getDefault() const { - if (m_defaultSet) - return m_default; - else - throw std::invalid_argument("Tried get default from parser item " + name() + " No default has been configured"); + return m_default; } DeckItemPtr ParserIntItem::scan(RawRecordPtr rawRecord) const { diff --git a/opm/parser/eclipse/Parser/ParserItem.hpp b/opm/parser/eclipse/Parser/ParserItem.hpp index 7d48c077d..e1f9358af 100644 --- a/opm/parser/eclipse/Parser/ParserItem.hpp +++ b/opm/parser/eclipse/Parser/ParserItem.hpp @@ -104,13 +104,9 @@ namespace Opm { value = st.value(); deckItem->push_backMultiple( value , st.multiplier()); } else { - if (self->defaultSet()) { - value = self->getDefault(); - for (size_t i=0; i < st.multiplier(); i++) - deckItem->push_backDefault( value ); - } - else - throw std::invalid_argument("No default specified for item of DATA kind"); + value = self->getDefault(); + for (size_t i=0; i < st.multiplier(); i++) + deckItem->push_backDefault( value ); } } else { ValueType value = readValueToken(token); @@ -118,22 +114,19 @@ namespace Opm { } } } else { - if (rawRecord->size() == 0) { + if (rawRecord->size() == 0) // if the record was ended prematurely, use the default value for the // item... - if (self->defaultSet()) - deckItem->push_backDefault( self->getDefault() ); - } else { + deckItem->push_backDefault( self->getDefault() ); + else { // The '*' should be interpreted as a repetition indicator, but it must // be preceeded by an integer... std::string token = rawRecord->pop_front(); if (tokenContainsStar( token )) { StarToken st(token); - if (!st.hasValue()) { - if (self->defaultSet()) - deckItem->push_backDefault( self->getDefault() ); - } + if (!st.hasValue()) + deckItem->push_backDefault( self->getDefault() ); else deckItem->push_back(st.value()); diff --git a/opm/parser/eclipse/Parser/ParserStringItem.cpp b/opm/parser/eclipse/Parser/ParserStringItem.cpp index e99831e8d..ac278965d 100644 --- a/opm/parser/eclipse/Parser/ParserStringItem.cpp +++ b/opm/parser/eclipse/Parser/ParserStringItem.cpp @@ -26,11 +26,13 @@ namespace Opm { ParserStringItem::ParserStringItem(const std::string& itemName) : ParserItem(itemName) { + m_default = ""; } ParserStringItem::ParserStringItem(const std::string& itemName, ParserItemSizeEnum sizeType_) : ParserItem(itemName, sizeType_) { + m_default = ""; } ParserStringItem::ParserStringItem(const std::string& itemName, ParserItemSizeEnum sizeType_, const std::string& defaultValue) : ParserItem(itemName, sizeType_) { @@ -44,6 +46,7 @@ namespace Opm { ParserStringItem::ParserStringItem(const Json::JsonObject& jsonConfig) : ParserItem(jsonConfig) { + m_default = ""; if (jsonConfig.has_item("default")) setDefault( jsonConfig.get_string("default") ); } @@ -59,10 +62,7 @@ namespace Opm { } std::string ParserStringItem::getDefault() const { - if (m_defaultSet) - return m_default; - else - throw std::invalid_argument("Tried get default from parser item " + name() + " No default has been configured"); + return m_default; } diff --git a/opm/parser/eclipse/Parser/tests/ParserItemTests.cpp b/opm/parser/eclipse/Parser/tests/ParserItemTests.cpp index 3cb35ae90..af1be54ba 100644 --- a/opm/parser/eclipse/Parser/tests/ParserItemTests.cpp +++ b/opm/parser/eclipse/Parser/tests/ParserItemTests.cpp @@ -34,6 +34,8 @@ #include +#include + using namespace Opm; BOOST_AUTO_TEST_CASE(Initialize) { @@ -69,7 +71,7 @@ BOOST_AUTO_TEST_CASE(Initialize_DefaultSizeType) { BOOST_AUTO_TEST_CASE(Initialize_Default) { ParserIntItem item1(std::string("ITEM1")); ParserIntItem item2(std::string("ITEM1"), 88); - BOOST_CHECK_THROW(item1.getDefault(), std::invalid_argument); + BOOST_CHECK(item1.getDefault() < 0); BOOST_CHECK_EQUAL(item2.getDefault(), 88); } @@ -77,21 +79,21 @@ BOOST_AUTO_TEST_CASE(Initialize_Default) { BOOST_AUTO_TEST_CASE(Initialize_Default_Double) { ParserDoubleItem item1(std::string("ITEM1")); ParserDoubleItem item2("ITEM1", 88.91); - BOOST_CHECK_THROW(item1.getDefault(), std::invalid_argument); + BOOST_CHECK(!std::isfinite(item1.getDefault())); BOOST_CHECK_EQUAL( 88.91 , item2.getDefault()); } BOOST_AUTO_TEST_CASE(Initialize_Default_Float) { ParserFloatItem item1(std::string("ITEM1")); ParserFloatItem item2("ITEM1", 88.91F); - BOOST_CHECK_THROW(item1.getDefault(), std::invalid_argument); + BOOST_CHECK(!std::isfinite(item1.getDefault())); BOOST_CHECK_EQUAL( 88.91F , item2.getDefault()); } BOOST_AUTO_TEST_CASE(Initialize_Default_String) { ParserStringItem item1(std::string("ITEM1")); - BOOST_CHECK_THROW( item1.getDefault(), std::invalid_argument); + BOOST_CHECK(item1.getDefault() == ""); ParserStringItem item2("ITEM1", "String"); BOOST_CHECK_EQUAL( "String" , item2.getDefault()); @@ -102,8 +104,12 @@ BOOST_AUTO_TEST_CASE(scan_PreMatureTerminator_defaultUsed) { RawRecordPtr rawRecord1(new RawRecord("/")); DeckItemConstPtr defaulted = itemInt.scan(rawRecord1); - BOOST_CHECK_THROW(defaulted->defaultApplied(0), std::out_of_range); - BOOST_CHECK_THROW(defaulted->getInt(0) , std::out_of_range); + // an item is always present even if the record was ended. If the deck specified no + // data and the item does not have a meaningful default, the item gets assigned a NaN + // (for float and double items), -1 (for integer items) and "" (for string items) + // whit the defaultApplied(0) method returning true... + BOOST_CHECK(defaulted->defaultApplied(0)); + BOOST_CHECK(defaulted->getInt(0) < 0); } BOOST_AUTO_TEST_CASE(InitializeIntItem_setDescription_canReadBack) { @@ -136,7 +142,7 @@ BOOST_AUTO_TEST_CASE(InitializeIntItem_FromJsonObject) { ParserIntItem item1( jsonConfig ); BOOST_CHECK_EQUAL( "ITEM1" , item1.name() ); BOOST_CHECK_EQUAL( ALL , item1.sizeType() ); - BOOST_CHECK_THROW( item1.getDefault(), std::invalid_argument); + BOOST_CHECK(item1.getDefault() < 0); } @@ -395,7 +401,14 @@ BOOST_AUTO_TEST_CASE(Scan_All_WithDefaults) { ParserIntItem itemInt("ITEM", sizeType); RawRecordPtr rawRecord(new RawRecord("100 10* 10*1 25/")); - BOOST_CHECK_THROW(itemInt.scan(rawRecord), std::invalid_argument); + DeckItemConstPtr deckIntItem = itemInt.scan(rawRecord); + BOOST_CHECK_EQUAL(22U, deckIntItem->size()); + BOOST_CHECK(!deckIntItem->defaultApplied(0)); + BOOST_CHECK(deckIntItem->defaultApplied(1)); + BOOST_CHECK(!deckIntItem->defaultApplied(11)); + BOOST_CHECK(!deckIntItem->defaultApplied(21)); + BOOST_CHECK_EQUAL(1, deckIntItem->getInt(20)); + BOOST_CHECK_EQUAL(25, deckIntItem->getInt(21)); } BOOST_AUTO_TEST_CASE(Scan_SINGLE_CorrectIntSetInDeckItem) { @@ -540,7 +553,7 @@ BOOST_AUTO_TEST_CASE(InitializeStringItem_FromJsonObject) { ParserStringItem item1( jsonConfig ); BOOST_CHECK_EQUAL( "ITEM1" , item1.name() ); BOOST_CHECK_EQUAL( ALL , item1.sizeType() ); - BOOST_CHECK_THROW( item1.getDefault() , std::invalid_argument ); + BOOST_CHECK(item1.getDefault() == ""); } diff --git a/opm/parser/eclipse/Utility/MultiRecordTable.cpp b/opm/parser/eclipse/Utility/MultiRecordTable.cpp index 9e0a0d9e2..18c0e2ad3 100644 --- a/opm/parser/eclipse/Utility/MultiRecordTable.cpp +++ b/opm/parser/eclipse/Utility/MultiRecordTable.cpp @@ -99,7 +99,7 @@ size_t MultiRecordTable::getNumFlatItems_(Opm::DeckRecordConstPtr deckRecord) int result = 0; for (unsigned i = 0; i < deckRecord->size(); ++ i) { Opm::DeckItemConstPtr item(deckRecord->getItem(i)); - if (i == 0 && !item->wasSetInDeck(0)) + if (item->size() == 0 || item->defaultApplied(0)) return result; result += item->size(); }