Merge pull request #1070 from stefoss23/deck_keyword_value_constructor

DeckKeyword constructor w/ DeckValue records
This commit is contained in:
Joakim Hove
2019-10-04 11:49:17 +02:00
committed by GitHub
7 changed files with 175 additions and 29 deletions

View File

@@ -41,12 +41,12 @@ if(ENABLE_ECL_INPUT)
src/opm/json/JsonObject.cpp
src/opm/parser/eclipse/Deck/Deck.cpp
src/opm/parser/eclipse/Deck/DeckItem.cpp
src/opm/parser/eclipse/Deck/DeckValue.cpp
src/opm/parser/eclipse/Deck/DeckKeyword.cpp
src/opm/parser/eclipse/Deck/DeckRecord.cpp
src/opm/parser/eclipse/Deck/DeckOutput.cpp
src/opm/parser/eclipse/Deck/Section.cpp
src/opm/parser/eclipse/Deck/UDAValue.cpp
src/opm/parser/eclipse/Deck/DeckValue.cpp
src/opm/parser/eclipse/Python/Python.cpp
src/opm/parser/eclipse/EclipseState/AquiferCT.cpp
src/opm/parser/eclipse/EclipseState/Aquifetp.cpp
@@ -625,10 +625,10 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/Deck/Deck.hpp
opm/parser/eclipse/Deck/Section.hpp
opm/parser/eclipse/Deck/DeckOutput.hpp
opm/parser/eclipse/Deck/DeckValue.hpp
opm/parser/eclipse/Deck/DeckKeyword.hpp
opm/parser/eclipse/Deck/DeckRecord.hpp
opm/parser/eclipse/Deck/UDAValue.hpp
opm/parser/eclipse/Deck/DeckValue.hpp
opm/parser/eclipse/Python/Python.hpp)
endif()
if(ENABLE_ECL_OUTPUT)

View File

@@ -1,6 +1,7 @@
set(genkw_SOURCES src/opm/json/JsonObject.cpp
src/opm/parser/eclipse/Parser/createDefaultKeywordList.cpp
src/opm/parser/eclipse/Deck/UDAValue.cpp
src/opm/parser/eclipse/Deck/DeckValue.cpp
src/opm/parser/eclipse/Deck/Deck.cpp
src/opm/parser/eclipse/Deck/DeckItem.cpp
src/opm/parser/eclipse/Deck/DeckKeyword.cpp

View File

@@ -26,6 +26,7 @@
#include <utility>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckValue.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
namespace Opm {
@@ -37,8 +38,11 @@ namespace Opm {
typedef std::vector< DeckRecord >::const_iterator const_iterator;
explicit DeckKeyword(const ParserKeyword& parserKeyword);
DeckKeyword(const ParserKeyword& parserKeyword, const std::string& keywordName);
DeckKeyword(const ParserKeyword& parserKeyword, const std::vector<std::vector<DeckValue>>& record_list);
const std::string& name() const;
void setFixedSize();
void setLocation(const std::pair<const std::string&, std::size_t>& location);

View File

@@ -22,6 +22,8 @@
#include <string>
#include <opm/parser/eclipse/Utility/Typetools.hpp>
namespace Opm {
class DeckValue {
@@ -31,18 +33,19 @@ class DeckValue {
explicit DeckValue(int);
explicit DeckValue(double);
explicit DeckValue(const std::string&);
bool is_default() const;
template<typename T>
T get() const;
template<typename T>
bool is() const;
bool is_compatible() const;
private:
enum class DeckValueEnum {INT, DOUBLE, STRING};
DeckValueEnum value_enum;
bool default_value;
type_tag value_enum;
int int_value;
double double_value;
std::string string_value;

View File

@@ -16,6 +16,9 @@
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 <opm/parser/eclipse/Utility/Typetools.hpp>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
@@ -45,6 +48,68 @@ namespace Opm {
{
}
namespace {
template< typename T >
void add_deckvalue( const std::string& kw_name, DeckRecord& currentDeckRecord, const ParserItem& parser_item, const std::vector<DeckValue>& current_record, size_t j) {
DeckItem item(parser_item.name(), T());
if (j >= current_record.size() || current_record[j].is_default()) {
if (parser_item.hasDefault())
item.push_back( parser_item.getDefault<T>() );
else
item.push_backDummyDefault();
}
else if (current_record[j].is_compatible<T>())
item.push_back( current_record[j].get<T>() );
else
throw std::invalid_argument("For input to DeckKeyword '" + kw_name +
", item '" + parser_item.name() +
"': wrong type.");
currentDeckRecord.addItem( std::move(item) );
}
}
DeckKeyword::DeckKeyword(const ParserKeyword& parserKeyword, const std::vector<std::vector<DeckValue>>& record_list) :
DeckKeyword(parserKeyword)
{
if (parserKeyword.hasFixedSize() && (record_list.size() != parserKeyword.getFixedSize()))
throw std::invalid_argument("Wrong number of records added to constructor for deckkeyword '" + name() + "'.");
for (size_t i = 0; i < record_list.size(); i++) {
ParserRecord parser_record = parserKeyword.getRecord(i);
const std::vector<DeckValue>& current_record = record_list[i];
DeckRecord currentDeckRecord;
for (size_t j = 0; j < parser_record.size(); j++) {
const ParserItem& parser_item = parser_record.get(j);
if (parser_item.sizeType() == ParserItem::item_size::ALL)
throw std::invalid_argument("constructor DeckKeyword::DeckKeyword(const ParserKeyword&, const std::vector<std::vector<DeckValue>>&) does not handle sizetype ALL.");
switch( parser_item.dataType() ) {
case type_tag::integer:
add_deckvalue<int>( name(), currentDeckRecord, parser_item, current_record, j);
break;
case type_tag::fdouble:
add_deckvalue<double>( name(), currentDeckRecord, parser_item, current_record, j);
break;
case type_tag::string:
add_deckvalue<std::string>( name(), currentDeckRecord, parser_item, current_record, j);
break;
default: throw std::invalid_argument("For input to DeckKeyword '" + name() + ": unsupported type. (only support for string, double and int.)");
}
}
addRecord( std::move(currentDeckRecord) );
}
}
void DeckKeyword::setFixedSize() {
m_slashTerminated = false;

View File

@@ -25,27 +25,35 @@
namespace Opm {
DeckValue::DeckValue():
DeckValue(0)
default_value(true),
value_enum(type_tag::unknown)
{}
DeckValue::DeckValue(int value):
value_enum(DeckValueEnum::INT),
default_value(false),
value_enum(type_tag::integer),
int_value(value)
{}
DeckValue::DeckValue(double value):
value_enum(DeckValueEnum::DOUBLE),
default_value(false),
value_enum(type_tag::fdouble),
double_value(value)
{}
DeckValue::DeckValue(const std::string& value):
value_enum(DeckValueEnum::STRING),
default_value(false),
value_enum(type_tag::string),
string_value(value)
{}
bool DeckValue::is_default() const {
return default_value;
}
template<>
int DeckValue::get() const {
if (value_enum == DeckValueEnum::INT)
if (value_enum == type_tag::integer)
return this->int_value;
throw std::invalid_argument("DeckValue does not hold an integer value");
@@ -53,34 +61,37 @@ int DeckValue::get() const {
template<>
double DeckValue::get() const {
if (value_enum == DeckValueEnum::DOUBLE)
if (value_enum == type_tag::fdouble)
return this->double_value;
if (value_enum == type_tag::integer)
return this->int_value;
throw std::invalid_argument("DeckValue does not hold a double value");
}
template<>
std::string DeckValue::get() const {
if (value_enum == DeckValueEnum::STRING)
if (value_enum == type_tag::string)
return this->string_value;
throw std::invalid_argument("DeckValue does not hold a string value");
}
template<>
bool DeckValue::is<int>() const {
return (value_enum == DeckValueEnum::INT);
bool DeckValue::is_compatible<int>() const {
return (value_enum == type_tag::integer);
}
template<>
bool DeckValue::is<double>() const {
return (value_enum == DeckValueEnum::DOUBLE);
bool DeckValue::is_compatible<double>() const {
return (value_enum == type_tag::fdouble || value_enum == type_tag::integer);
}
template<>
bool DeckValue::is<std::string>() const {
return (value_enum == DeckValueEnum::STRING);
bool DeckValue::is_compatible<std::string>() const {
return (value_enum == type_tag::string);
}

View File

@@ -2,11 +2,15 @@
#define BOOST_TEST_MODULE DeckValueTests
#include <vector>
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/B.hpp>
#include <opm/parser/eclipse/Deck/DeckValue.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
@@ -15,32 +19,90 @@ using namespace Opm;
BOOST_AUTO_TEST_CASE(DeckValueTest) {
DeckValue value0;
const DeckValue value0;
BOOST_CHECK(value0.is<int>());
BOOST_CHECK(!value0.is<std::string>());
BOOST_CHECK_EQUAL( value0.get<int>(), 0);
BOOST_CHECK(value0.is_default());
BOOST_CHECK(!value0.is_compatible<int>());
BOOST_CHECK(!value0.is_compatible<std::string>());
BOOST_CHECK(!value0.is_compatible<double>());
BOOST_CHECK_THROW( value0.get<int>(), std::invalid_argument);
BOOST_CHECK_THROW( value0.get<std::string>(), std::invalid_argument);
BOOST_CHECK_THROW( value0.get<double>(), std::invalid_argument);
DeckValue value1(10);
BOOST_CHECK(value1.is<int>());
BOOST_CHECK(!value1.is<std::string>());
BOOST_CHECK(!value1.is_default());
BOOST_CHECK(value1.is_compatible<int>());
BOOST_CHECK(value1.is_compatible<double>());
BOOST_CHECK(!value1.is_compatible<std::string>());
BOOST_CHECK_EQUAL( value1.get<int>(), 10);
BOOST_CHECK_EQUAL( value1.get<double>(), 10);
DeckValue value2(10.0);
BOOST_CHECK(value2.is<double>());
BOOST_CHECK(!value2.is<std::string>());
BOOST_CHECK(value2.is_compatible<double>());
BOOST_CHECK(!value2.is_compatible<int>());
BOOST_CHECK(!value2.is_compatible<std::string>());
BOOST_CHECK_EQUAL( value2.get<double>(), 10);
BOOST_CHECK_THROW( value2.get<std::string>(), std::invalid_argument);
BOOST_CHECK_THROW( value2.get<int>(), std::invalid_argument);
DeckValue value3("FUBHP");
BOOST_CHECK(!value3.is<double>());
BOOST_CHECK(value3.is<std::string>());
BOOST_CHECK(!value3.is_compatible<double>());
BOOST_CHECK(value3.is_compatible<std::string>());
BOOST_CHECK_EQUAL( value3.get<std::string>(), std::string("FUBHP"));
BOOST_CHECK_THROW( value3.get<double>(), std::invalid_argument);
BOOST_CHECK_THROW( value3.get<int>(), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(DeckKeywordConstructor) {
Parser parser;
const ParserKeyword& big_model = parser.getKeyword("BIGMODEL");
BOOST_CHECK_THROW( DeckKeyword( big_model, {{DeckValue("WORD_A")}} ), std::invalid_argument );
const ParserKeyword& box = parser.getKeyword("BOX");
std::vector< DeckValue > record1 = {DeckValue(1), DeckValue(2), DeckValue(3), DeckValue(4), DeckValue(5), DeckValue(6)};
BOOST_CHECK_NO_THROW( DeckKeyword( box, {record1} ) );
BOOST_CHECK_THROW( DeckKeyword( box, {record1, record1} ) , std::invalid_argument);
const ParserKeyword& addreg = parser.getKeyword("ADDREG");
BOOST_CHECK_NO_THROW( DeckKeyword( addreg, {{ DeckValue("WORD_A") }} ) );
BOOST_CHECK_THROW( DeckKeyword( addreg, {{DeckValue("WORD_A"), DeckValue(77), DeckValue(16.25), DeckValue("WORD_B")}} ) , std::invalid_argument);
std::vector< DeckValue > record = {DeckValue("WORD_A"), DeckValue(16.25), DeckValue(77), DeckValue("WORD_B")};
DeckKeyword deck_kw(addreg, {record});
BOOST_CHECK_EQUAL( deck_kw.size(), 1 );
const DeckRecord& deck_record = deck_kw.getRecord(0);
BOOST_CHECK_EQUAL( deck_record.size(), 4 );
const auto& array = deck_record.getItem( 0 );
const auto& shift = deck_record.getItem( 1 );
const auto& number = deck_record.getItem( 2 );
const auto& name = deck_record.getItem( 3 );
BOOST_CHECK_EQUAL( array.get<std::string>(0), "WORD_A" );
BOOST_CHECK_EQUAL( shift.get<double>(0), 16.25 );
BOOST_CHECK_EQUAL( number.get<int>(0), 77 );
BOOST_CHECK_EQUAL( name.get<std::string>(0), "WORD_B" );
//checking default values:
record = {DeckValue("WORD_A"), DeckValue(), DeckValue(77)};
DeckKeyword deck_kw1(addreg, {record});
const DeckRecord& deck_record1 = deck_kw1.getRecord(0);
const auto& shift1 = deck_record1.getItem( 1 );
const auto& name1 = deck_record1.getItem( 3 );
BOOST_CHECK_EQUAL( shift1.get<double>(0), 0 );
BOOST_CHECK_EQUAL( name1.get<std::string>(0), "M" );
//check that int can substitute double
BOOST_CHECK_NO_THROW( DeckKeyword(addreg, {{DeckValue("WORD_A"), DeckValue(5), DeckValue(77)}} ) );
}