Merge pull request #725 from joakim-hove/uda-value

UDA values in the deck
This commit is contained in:
Joakim Hove 2019-04-30 07:57:08 +02:00 committed by GitHub
commit 0466effc93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 415 additions and 48 deletions

View File

@ -45,6 +45,7 @@ if(ENABLE_ECL_INPUT)
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/EclipseState/AquiferCT.cpp
src/opm/parser/eclipse/EclipseState/Aquifetp.cpp
src/opm/parser/eclipse/EclipseState/Aquancon.cpp
@ -552,6 +553,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/Deck/DeckOutput.hpp
opm/parser/eclipse/Deck/DeckKeyword.hpp
opm/parser/eclipse/Deck/DeckRecord.hpp
opm/parser/eclipse/Deck/UDAValue.hpp
opm/parser/eclipse/RawDeck/StarToken.hpp
opm/parser/eclipse/RawDeck/RawEnums.hpp
opm/parser/eclipse/RawDeck/RawRecord.hpp

View File

@ -1,5 +1,6 @@
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/Deck.cpp
src/opm/parser/eclipse/Deck/DeckItem.cpp
src/opm/parser/eclipse/Deck/DeckKeyword.cpp

View File

@ -27,6 +27,7 @@
#include <opm/parser/eclipse/Units/Dimension.hpp>
#include <opm/parser/eclipse/Utility/Typetools.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
class DeckOutput;
@ -39,6 +40,7 @@ namespace Opm {
DeckItem( const std::string&, int, size_t size_hint = 8 );
DeckItem( const std::string&, double, size_t size_hint = 8 );
DeckItem( const std::string&, std::string, size_t size_hint = 8 );
DeckItem( const std::string&, UDAValue, size_t size_hint = 8 );
const std::string& name() const;
@ -58,6 +60,7 @@ namespace Opm {
size_t size() const;
size_t out_size() const;
//template< typename T > T& get( size_t ) ;
template< typename T > const T& get( size_t ) const;
double getSIDouble( size_t ) const;
std::string getTrimmedString( size_t ) const;
@ -65,12 +68,15 @@ namespace Opm {
template< typename T > const std::vector< T >& getData() const;
const std::vector< double >& getSIDoubleData() const;
void push_back( UDAValue );
void push_back( int );
void push_back( double );
void push_back( std::string );
void push_back( UDAValue, size_t );
void push_back( int, size_t );
void push_back( double, size_t );
void push_back( std::string, size_t );
void push_backDefault( UDAValue );
void push_backDefault( int );
void push_backDefault( double );
void push_backDefault( std::string );
@ -107,9 +113,10 @@ namespace Opm {
bool operator!=(const DeckItem& other) const;
static bool to_bool(std::string string_value);
private:
std::vector< double > dval;
mutable std::vector< double > dval;
std::vector< int > ival;
std::vector< std::string > sval;
std::vector< UDAValue > uval;
type_tag type = type_tag::unknown;

View File

@ -0,0 +1,61 @@
/*
Copyright 2019 Equinor 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/>.
*/
#ifndef UDA_VALUE_HPP
#define UDA_VALUE_HPP
#include <stdexcept>
#include <vector>
#include <string>
#include <opm/parser/eclipse/Units/Dimension.hpp>
namespace Opm {
class UDAValue {
public:
UDAValue();
UDAValue(double);
UDAValue(const std::string&);
template<typename T>
T get() const;
template<typename T>
bool is() const;
void set_dim(const Dimension& dim) const;
const Dimension& get_dim() const;
bool operator==(const UDAValue& other) const;
bool operator!=(const UDAValue& other) const;
private:
bool numeric_value;
double double_value;
std::string string_value;
/* This 'mutable' modifier is a hack to avoid tampering with the overall
const-ness of the data in a deck item. */
mutable Dimension dim;
};
}
#endif

View File

@ -80,6 +80,7 @@ namespace Opm {
size_t numDimensions() const;
const std::string& name() const;
item_size sizeType() const;
type_tag dataType() const;
void setSizeType(item_size size_type);
std::string getDescription() const;
bool scalar() const;
@ -108,6 +109,7 @@ namespace Opm {
double dval;
int ival;
std::string sval;
UDAValue uval;
std::vector< std::string > dimensions;
std::string m_name;

View File

@ -26,7 +26,7 @@ namespace Opm {
class Dimension {
public:
Dimension() = default;
Dimension();
Dimension(const std::string& name, double SIfactor, double SIoffset = 0.0);
double getSIScaling() const;

View File

@ -1,16 +1,15 @@
#ifndef OPM_TYPETOOLS_HPP
#define OPM_TYPETOOLS_HPP
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
enum class type_tag {
/* for python interop as well as queries, must be manually synchronised
* with cdeck_item.cc and opm/deck/item_type_enum.py
*/
unknown = 0,
integer = 1,
string = 2,
fdouble = 3,
uda = 4,
};
inline std::string tag_name( type_tag x ) {
@ -18,23 +17,30 @@ inline std::string tag_name( type_tag x ) {
case type_tag::integer: return "int";
case type_tag::string: return "std::string";
case type_tag::fdouble: return "double";
case type_tag::uda: return "UDAValue";
case type_tag::unknown: return "unknown";
}
return "unknown";
}
template< typename T > type_tag get_type();
template<> inline type_tag get_type< int >() {
return type_tag::integer;
}
template<> inline type_tag get_type< double >() {
return type_tag::fdouble;
}
template<> inline type_tag get_type< std::string >() {
return type_tag::string;
}
template<> inline type_tag get_type<UDAValue>() {
return type_tag::uda;
}
}
#endif //OPM_TYPETOOLS_HPP

View File

@ -41,27 +41,46 @@ std::vector< T >& DeckItem::value_ref() {
template<>
const std::vector< int >& DeckItem::value_ref< int >() const {
if( this->type != get_type< int >() )
throw std::invalid_argument( "Item of wrong type." );
throw std::invalid_argument( "DekcItem::velut_ref<int> Item of wrong type." );
return this->ival;
}
template<>
const std::vector< double >& DeckItem::value_ref< double >() const {
if( this->type != get_type< double >() )
throw std::invalid_argument( "Item of wrong type." );
if (this->type == get_type<double>())
return this->dval;
return this->dval;
/* Temporary return double values when user code asks for double on
something which is really a UDAValue.
*/
if( this->type == get_type< UDAValue >() ) {
this->dval.clear();
for (const auto& uv : this->uval)
this->dval.push_back(uv.get<double>());
return this->dval;
}
throw std::invalid_argument( "DeckItem::value_ref<double> Item of wrong type." );
}
template<>
const std::vector< std::string >& DeckItem::value_ref< std::string >() const {
if( this->type != get_type< std::string >() )
throw std::invalid_argument( "Item of wrong type." );
throw std::invalid_argument( "DeckItem::value_ref<std::string> Item of wrong type." );
return this->sval;
}
template<>
const std::vector< UDAValue >& DeckItem::value_ref< UDAValue >() const {
if( this->type != get_type< UDAValue >() )
throw std::invalid_argument( "DeckItem::value_ref<UDAValue> Item of wrong type." );
return this->uval;
}
DeckItem::DeckItem( const std::string& nm ) : item_name( nm ) {}
DeckItem::DeckItem( const std::string& nm, int, size_t hint ) :
@ -80,6 +99,14 @@ DeckItem::DeckItem( const std::string& nm, double, size_t hint ) :
this->defaulted.reserve( hint );
}
DeckItem::DeckItem( const std::string& nm, UDAValue , size_t hint ) :
type( get_type< UDAValue >() ),
item_name( nm )
{
this->uval.reserve( hint );
this->defaulted.reserve( hint );
}
DeckItem::DeckItem( const std::string& nm, std::string, size_t hint ) :
type( get_type< std::string >() ),
item_name( nm )
@ -101,7 +128,8 @@ bool DeckItem::hasValue( size_t index ) const {
case type_tag::integer: return this->ival.size() > index;
case type_tag::fdouble: return this->dval.size() > index;
case type_tag::string: return this->sval.size() > index;
default: throw std::logic_error( "Type not set." );
case type_tag::uda: return this->uval.size() > index;
default: throw std::logic_error( "DeckItem::hasValue: Type not set." );
}
}
@ -110,7 +138,8 @@ size_t DeckItem::size() const {
case type_tag::integer: return this->ival.size();
case type_tag::fdouble: return this->dval.size();
case type_tag::string: return this->sval.size();
default: throw std::logic_error( "Type not set." );
case type_tag::uda: return this->uval.size();
default: throw std::logic_error( "DeckItem::size: Type not set." );
}
}
@ -119,6 +148,16 @@ size_t DeckItem::out_size() const {
return std::max( data_size , this->defaulted.size() );
}
/*
The non const overload is only used for the UDAValue type because we need to
mutate the UDAValue object and add dimension to it retroactively.
*/
/*template<>
UDAValue& DeckItem::get( size_t index ) {
return this->uval[index];
}
*/
template< typename T >
const T& DeckItem::get( size_t index ) const {
return this->value_ref< T >().at( index );
@ -149,6 +188,10 @@ void DeckItem::push_back( std::string x ) {
this->push( std::move( x ) );
}
void DeckItem::push_back( UDAValue x ) {
this->push( std::move( x ) );
}
template< typename T >
void DeckItem::push( T x, size_t n ) {
auto& val = this->value_ref< T >();
@ -169,6 +212,10 @@ void DeckItem::push_back( std::string x, size_t n ) {
this->push( std::move( x ), n );
}
void DeckItem::push_back( UDAValue x, size_t n ) {
this->push( std::move( x ), n );
}
template< typename T >
void DeckItem::push_default( T x ) {
auto& val = this->value_ref< T >();
@ -192,6 +239,10 @@ void DeckItem::push_backDefault( std::string x ) {
this->push_default( std::move( x ) );
}
void DeckItem::push_backDefault( UDAValue x ) {
this->push_default( std::move( x ) );
}
void DeckItem::push_backDummyDefault() {
if( !this->defaulted.empty() )
@ -238,12 +289,26 @@ const std::vector< double >& DeckItem::getSIDoubleData() const {
}
void DeckItem::push_backDimension( const Dimension& active,
const Dimension& def ) {
const auto& ds = this->value_ref< double >();
const bool dim_inactive = ds.empty()
|| this->defaultApplied( ds.size() - 1 );
const Dimension& def ) {
if (this->type == type_tag::fdouble) {
const auto& ds = this->value_ref< double >();
const bool dim_inactive = ds.empty()
|| this->defaultApplied( ds.size() - 1 );
this->dimensions.push_back( dim_inactive ? def : active );
this->dimensions.push_back( dim_inactive ? def : active );
return;
}
if (this->type == type_tag::uda) {
auto& du = this->value_ref< UDAValue >();
const bool dim_inactive = du.empty()
|| this->defaultApplied( du.size() - 1 );
this->dimensions.push_back( dim_inactive ? def : active );
return;
}
throw std::logic_error("Tried to push dimensions to an item which can not hold dimension. ");
}
type_tag DeckItem::getType() const {
@ -274,8 +339,11 @@ void DeckItem::write(DeckOutput& stream) const {
case type_tag::string:
this->write_vector( stream, this->sval );
break;
case type_tag::uda:
this->write_vector( stream, this->uval );
break;
default:
throw std::logic_error( "Type not set." );
throw std::logic_error( "DeckItem::write: Type not set." );
}
}
@ -405,8 +473,10 @@ bool DeckItem::to_bool(std::string string_value) {
template const int& DeckItem::get< int >( size_t ) const;
template const double& DeckItem::get< double >( size_t ) const;
template const std::string& DeckItem::get< std::string >( size_t ) const;
template const UDAValue& DeckItem::get< UDAValue >( size_t ) const;
template const std::vector< int >& DeckItem::getData< int >() const;
template const std::vector< double >& DeckItem::getData< double >() const;
template const std::vector< UDAValue >& DeckItem::getData< UDAValue >() const;
template const std::vector< std::string >& DeckItem::getData< std::string >() const;
}

View File

@ -20,6 +20,7 @@
#include <ostream>
#include <opm/parser/eclipse/Deck/DeckOutput.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
@ -82,6 +83,14 @@ namespace Opm {
this->os << value;
}
template <>
void DeckOutput::write_value( const UDAValue& value ) {
if (value.is<double>())
this->write_value(value.get<double>());
else
this->write_value(value.get<std::string>());
}
void DeckOutput::stash_default( ) {
this->default_count++;
}
@ -132,4 +141,5 @@ namespace Opm {
template void DeckOutput::write( const int& value);
template void DeckOutput::write( const double& value);
template void DeckOutput::write( const std::string& value);
template void DeckOutput::write( const UDAValue& value);
}

View File

@ -0,0 +1,96 @@
/*
Copyright 2019 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 <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
UDAValue::UDAValue(double value):
numeric_value(true),
double_value(value)
{
}
UDAValue::UDAValue() :
UDAValue(0)
{}
UDAValue::UDAValue(const std::string& value):
numeric_value(false),
string_value(value)
{
}
template<>
bool UDAValue::is<double>() const {
return this->numeric_value;
}
template<>
bool UDAValue::is<std::string>() const {
return !this->numeric_value;
}
template<>
double UDAValue::get() const {
if (this->numeric_value)
return this->double_value;
throw std::invalid_argument("UDAValue does not hold a numerical value");
}
template<>
std::string UDAValue::get() const {
if (!this->numeric_value)
return this->string_value;
throw std::invalid_argument("UDAValue does not hold a string value");
}
void UDAValue::set_dim(const Dimension& dim) const {
this->dim = dim;
}
const Dimension& UDAValue::get_dim() const {
return this->dim;
}
bool UDAValue::operator==(const UDAValue& other) const {
if (this->numeric_value != other.numeric_value)
return false;
if (this->numeric_value)
return (this->double_value == other.double_value);
return this->string_value == other.string_value;
}
bool UDAValue::operator!=(const UDAValue& other) const {
return !(*this == other);
}
}

View File

@ -49,6 +49,7 @@ const std::string testHeader =
"auto unitSystem = UnitSystem::newMETRIC();\n";
const std::string sourceHeader =
"#include <opm/parser/eclipse/Deck/UDAValue.hpp>\n"
"#include <opm/parser/eclipse/Parser/ParserKeyword.hpp>\n"
"#include <opm/parser/eclipse/Parser/ParserItem.hpp>\n"
"#include <opm/parser/eclipse/Parser/ParserRecord.hpp>\n"

View File

@ -30,7 +30,7 @@
#include <opm/parser/eclipse/Parser/ParserEnums.hpp>
#include <opm/parser/eclipse/RawDeck/RawRecord.hpp>
#include <opm/parser/eclipse/RawDeck/StarToken.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
@ -47,6 +47,11 @@ template<> const double& default_value< double >() {
return value;
}
template<> const UDAValue& default_value< UDAValue >() {
static const UDAValue value = UDAValue(std::numeric_limits<double>::quiet_NaN());
return value;
}
template<> const std::string& default_value< std::string >() {
static const std::string value = "";
return value;
@ -57,7 +62,7 @@ type_tag get_data_type_json( const std::string& str ) {
if( str == "DOUBLE" ) return type_tag::fdouble;
if( str == "STRING" ) return type_tag::string;
if( str == "RAW_STRING") return type_tag::string;
if( str == "UDA") return type_tag::fdouble;
if( str == "UDA") return type_tag::uda;
throw std::invalid_argument( str + " cannot be converted to enum 'tag'" );
}
@ -88,7 +93,14 @@ std::string ParserItem::string_from_size( ParserItem::item_size sz ) {
case item_size::SINGLE: return "SINGLE";
}
throw std::logic_error( "Fatal error; should not be reachable" );
throw std::logic_error( "ParserItem::string_from_size: Fatal error; should not be reachable" );
}
template<> const UDAValue& ParserItem::value_ref< UDAValue >() const {
if( this->data_type != get_type< UDAValue >() )
throw std::invalid_argument("ValueRef<UDAValue> Wrong type." );
return this->uval;
}
template<> const int& ParserItem::value_ref< int >() const {
@ -164,17 +176,17 @@ ParserItem::ParserItem( const Json::JsonObject& json ) :
this->setDefault( json.get_double( "default" ) );
break;
case itype::UDA:
this->setDefault( UDAValue(json.get_double( "default" )) );
break;
case itype::STRING:
case itype::RAW_STRING:
this->setDefault( json.get_string( "default" ) );
break;
case itype::UDA:
this->setDefault( json.get_double( "default" ) );
break;
default:
throw std::logic_error( "Item of unknown type." );
throw std::logic_error( "Item of unknown type: <" + json.get_string("value_type") + ">" );
}
}
@ -205,7 +217,7 @@ void ParserItem::setInputType(ParserItem::itype input_type) {
this->setDataType( std::string() );
else if (input_type == itype::UDA)
this->setDataType( double() );
this->setDataType( UDAValue(0) );
else
throw std::invalid_argument("BUG: input type not recognized in setInputType()");
@ -238,22 +250,17 @@ const T& ParserItem::getDefault() const {
}
bool ParserItem::hasDimension() const {
if( this->data_type != type_tag::fdouble )
return false;
return !this->dimensions.empty();
}
size_t ParserItem::numDimensions() const {
if( this->data_type != type_tag::fdouble ) return 0;
return this->dimensions.size();
}
const std::string& ParserItem::getDimension( size_t index ) const {
if( this->data_type != type_tag::fdouble )
throw std::invalid_argument("Item is not double.");
return this->dimensions.at( index );
if( this->data_type == type_tag::fdouble || this->data_type == type_tag::uda)
return this->dimensions.at( index );
throw std::invalid_argument("Item is not double / UDA .");
}
void ParserItem::push_backDimension( const std::string& dim ) {
@ -278,6 +285,10 @@ void ParserItem::push_backDimension( const std::string& dim ) {
}
type_tag ParserItem::dataType() const {
return this->data_type;
}
ParserItem::item_size ParserItem::sizeType() const {
return m_sizeType;
@ -293,6 +304,18 @@ void ParserItem::push_backDimension( const std::string& dim ) {
void ParserItem::setSizeType(item_size size_type) {
/*
The restriction that data type UDA can only be combined with size_type
SINGLE is due to the way units are bolted on to the Deck
datastructures after the parsing has completed. UDA values are
currently only used as scalars in well/group control and the
restriction does not have any effect. If at some stage in the future
this should change the way units are applied to the deck must be
refactored.
*/
if (this->data_type == type_tag::uda && size_type != item_size::SINGLE)
throw std::invalid_argument("Sorry - the UDA datatype can only be used with size type SINGLE");
this->m_sizeType = size_type;
}
@ -329,8 +352,12 @@ bool ParserItem::operator==( const ParserItem& rhs ) const {
if( this->sval != rhs.sval ) return false;
break;
case type_tag::uda:
if( this->uval != rhs.uval ) return false;
break;
default:
throw std::logic_error( "Item of unknown type." );
throw std::logic_error( "Item of unknown type data_type:" + tag_name(this->data_type));
}
}
if( this->data_type != type_tag::fdouble ) return true;
@ -415,6 +442,13 @@ std::string ParserItem::createCode(const std::string& indent) const {
stream << "double(" << as_string(this->getDefault<double>()) << ")";
break;
case type_tag::uda:
{
double double_value =this->getDefault<UDAValue>().get<double>();
stream << "UDAValue(" << as_string(double_value) << ")";
}
break;
case type_tag::string:
stream << "std::string(\"" << this->getDefault< std::string >() << "\")";
break;
@ -425,6 +459,9 @@ std::string ParserItem::createCode(const std::string& indent) const {
stream << " );" << '\n';
}
for (size_t idim=0; idim < this->numDimensions(); idim++)
stream << indent <<"item.push_backDimension(\"" << this->getDimension( idim ) << "\");" << '\n';
if (this->m_description.size() > 0)
stream << indent << "item.setDescription(\"" << this->m_description << "\");" << '\n';
@ -540,8 +577,10 @@ DeckItem ParserItem::scan( RawRecord& record ) const {
return scan_item< double >( *this, record );
case type_tag::string:
return scan_item< std::string >( *this, record );
case type_tag::uda:
return scan_item<UDAValue>(*this, record);
default:
throw std::logic_error( "Fatal error; should not be reachable" );
throw std::logic_error( "ParserItem::scan: Fatal error; should not be reachable" );
}
}
@ -580,11 +619,16 @@ std::string ParserItem::inlineClassInit(const std::string& parentClass,
return std::to_string( this->getDefault< int >() );
case type_tag::fdouble:
return std::to_string( this->getDefault< double >() );
case type_tag::uda:
{
double value = this->getDefault<UDAValue>().get<double>();
return "UDAValue(" + std::to_string(value) + ")";
}
case type_tag::string:
return "\"" + this->getDefault< std::string >() + "\"";
default:
throw std::logic_error( "Fatal error; should not be reachable" );
throw std::logic_error( "ParserItem::inlineClassInit: Fatal error; should not be reachable" );
}
};
@ -649,13 +693,16 @@ bool ParserItem::parseRaw( ) const {
template void ParserItem::setDefault( int );
template void ParserItem::setDefault( double );
template void ParserItem::setDefault( std::string );
template void ParserItem::setDefault( UDAValue );
template void ParserItem::setDataType( int );
template void ParserItem::setDataType( double );
template void ParserItem::setDataType( std::string );
template void ParserItem::setDataType( UDAValue );
template const int& ParserItem::getDefault() const;
template const double& ParserItem::getDefault() const;
template const std::string& ParserItem::getDefault() const;
template const UDAValue& ParserItem::getDefault() const;
}

View File

@ -648,8 +648,6 @@ void set_dimensions( ParserItem& item,
{
std::string indent3 = local_indent + " ";
ss << item.createCode(indent3);
for (size_t idim=0; idim < item.numDimensions(); idim++)
ss << indent3 <<"item.push_backDimension(\"" << item.getDimension( idim ) << "\");" << '\n';
{
std::string addItemMethod = "addItem";
if (isDataKeyword())

View File

@ -95,16 +95,30 @@ namespace {
void ParserRecord::applyUnitsToDeck( Deck& deck, DeckRecord& deckRecord ) const {
for( const auto& item : *this ) {
if( !item.hasDimension() ) continue;
for( const auto& parser_item : *this ) {
if( !parser_item.hasDimension() ) continue;
auto& deckItem = deckRecord.getItem( item.name() );
for (size_t idim = 0; idim < item.numDimensions(); idim++) {
auto activeDimension = deck.getActiveUnitSystem().getNewDimension( item.getDimension(idim) );
auto defaultDimension = deck.getDefaultUnitSystem().getNewDimension( item.getDimension(idim) );
auto& deckItem = deckRecord.getItem( parser_item.name() );
for (size_t idim = 0; idim < parser_item.numDimensions(); idim++) {
auto activeDimension = deck.getActiveUnitSystem().getNewDimension( parser_item.getDimension(idim) );
auto defaultDimension = deck.getDefaultUnitSystem().getNewDimension( parser_item.getDimension(idim) );
deckItem.push_backDimension( activeDimension , defaultDimension );
}
/*
A little special casing ... the UDAValue elements in the deck must
carry their own dimension. Observe that the
ParserItem::setSizeType() method guarantees that UDA data is
scalar, i.e. this special case loop can be simpler than the
general code in the block above.
*/
if (parser_item.dataType() == type_tag::uda && deckItem.size() > 0) {
auto uda = deckItem.get<UDAValue>(0);
if (deckItem.defaultApplied(0))
uda.set_dim( deck.getDefaultUnitSystem().getNewDimension( parser_item.getDimension(0)));
else
uda.set_dim( deck.getActiveUnitSystem().getNewDimension( parser_item.getDimension(0)));
}
}
}

View File

@ -28,6 +28,7 @@
#include <opm/parser/eclipse/RawDeck/StarToken.hpp>
#include <opm/parser/eclipse/Utility/Stringview.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace qi = boost::spirit::qi;
@ -105,6 +106,7 @@ namespace Opm {
throw std::invalid_argument( "Malformed floating point number '" + view + "'" );
}
template <>
std::string readValueToken< std::string >( string_view view ) {
if( view.size() == 0 || view[ 0 ] != '\'' )
@ -116,6 +118,17 @@ namespace Opm {
return view.substr( 1, view.size() - 1 );
}
template<>
UDAValue readValueToken< UDAValue >( string_view view ) {
double n = 0;
qi::real_parser< double, fortran_double< double > > double_;
auto cursor = view.begin();
const auto ok = qi::parse( cursor, view.end(), double_, n );
if( ok && cursor == view.end() ) return UDAValue(n);
return UDAValue( readValueToken<std::string>(view) );
}
void StarToken::init_( const string_view& token ) {
// special-case the interpretation of a lone star as "1*" but do not
// allow constructs like "*123"...

View File

@ -25,6 +25,14 @@
namespace Opm {
Dimension::Dimension()
{
this->m_name = "Unit";
this->m_SIfactor = 1.0;
this->m_SIoffset = 0.0;
}
Dimension::Dimension(const std::string& name, double SIfactor, double SIoffset)
{
for (auto iter = name.begin(); iter != name.end(); ++iter) {

View File

@ -24,6 +24,7 @@
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.hpp>
@ -954,3 +955,27 @@ BOOST_AUTO_TEST_CASE(UDQPARSE_PARSECONTEXT) {
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::THROW_EXCEPTION);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", tokens, parseContext, errors), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(UDA_VALUE) {
UDAValue value0;
BOOST_CHECK(value0.is<double>());
BOOST_CHECK(!value0.is<std::string>());
BOOST_CHECK_EQUAL( value0.get<double>(), 0);
BOOST_CHECK_THROW( value0.get<std::string>(), std::invalid_argument);
UDAValue value1(10);
BOOST_CHECK(value1.is<double>());
BOOST_CHECK(!value1.is<std::string>());
BOOST_CHECK_EQUAL( value1.get<double>(), 10);
BOOST_CHECK_THROW( value1.get<std::string>(), std::invalid_argument);
UDAValue value2("FUBHP");
BOOST_CHECK(!value2.is<double>());
BOOST_CHECK(value2.is<std::string>());
BOOST_CHECK_EQUAL( value2.get<std::string>(), std::string("FUBHP"));
BOOST_CHECK_THROW( value2.get<double>(), std::invalid_argument);
}

View File

@ -30,6 +30,12 @@
using namespace Opm;
BOOST_AUTO_TEST_CASE(DefDim) {
Dimension dim;
BOOST_CHECK_EQUAL(1.0, dim.getSIScaling());
BOOST_CHECK( dim.isCompositable() );
}
BOOST_AUTO_TEST_CASE(CreateDimension) {
Dimension length("Length" , 1);
BOOST_CHECK_EQUAL("Length" , length.getName());