Files
opm-common/opm/parser/eclipse/Deck/DeckItem.cpp
Jørgen Kvalsvik 1406630aa3 DeckItem constructor takes size hint
Enable preallocation by passing size hints to DeckItem constructor.
2016-03-14 08:29:54 +01:00

404 lines
13 KiB
C++

/*
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 <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Units/Dimension.hpp>
#include <boost/algorithm/string.hpp>
#include <stdexcept>
namespace Opm {
template< typename T >
class DeckTypeItem : public DeckItemBase {
public:
const std::string& name() const override;
bool defaultApplied( size_t ) const override;
bool hasValue( size_t ) const override;
size_t size() const override;
void push_back( T );
void push_back( T, size_t numValues );
void push_backDefault( T );
void push_backDummyDefault() override;
const T& get( size_t ) const;
const std::vector< T >& getData() const;
protected:
DeckTypeItem( const std::string&, size_t );
private:
std::string item_name;
std::vector< bool > dataPointDefaulted;
std::vector< T > data;
};
template< typename T >
class DeckItemT : public DeckTypeItem< T > {
private:
using DeckTypeItem< T >::DeckTypeItem;
std::unique_ptr< DeckItemBase > clone() const override;
friend class DeckItem;
};
template<>
class DeckItemT< double > : public DeckTypeItem< double > {
public:
using DeckTypeItem< double >::DeckTypeItem;
const double& getSI( size_t ) const;
const std::vector< double >& getSIData() const;
void push_backDimension(
std::shared_ptr< const Dimension > activeDimension,
std::shared_ptr< const Dimension > defaultDimension );
private:
const std::vector< double >& assertSIData() const;
std::unique_ptr< DeckItemBase > clone() const override;
std::vector< double > SIdata;
std::vector< std::shared_ptr< const Dimension > > dimensions;
friend class DeckItem;
};
template< typename T >
DeckTypeItem< T >::DeckTypeItem( const std::string& name, size_t size ) :
item_name( name )
{
this->dataPointDefaulted.reserve( size );
this->data.reserve( size );
}
template< typename T >
const std::string& DeckTypeItem< T >::name() const {
return this->item_name;
}
template< typename T >
bool DeckTypeItem< T >::defaultApplied( size_t index ) const {
return this->dataPointDefaulted.at( index );
}
template< typename T >
bool DeckTypeItem< T >::hasValue( size_t index ) const {
return index < this->size();
}
template< typename T >
size_t DeckTypeItem< T >::size() const {
return this->data.size();
}
template< typename T >
void DeckTypeItem< T >::push_back( T x ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.push_back( x );
this->dataPointDefaulted.push_back( false );
}
template< typename T >
void DeckTypeItem< T >::push_backDefault( T data_arg ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.push_back( data_arg );
this->dataPointDefaulted.push_back(true);
}
template< typename T >
void DeckTypeItem< T >::push_backDummyDefault() {
if( this->dataPointDefaulted.size() != 0 )
throw std::logic_error("Pseudo defaults can only be specified for empty items");
this->dataPointDefaulted.push_back( true );
}
template< typename T >
void DeckTypeItem< T >::push_back( T x, size_t numValues ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.insert( this->data.end(), numValues, x );
this->dataPointDefaulted.insert( this->dataPointDefaulted.end(), numValues, false );
}
template< typename T >
const T& DeckTypeItem< T >::get( size_t index ) const {
return this->data.at( index );
}
template< typename T >
const std::vector< T >& DeckTypeItem< T >::getData() const {
return this->data;
}
const double& DeckItemT< double >::getSI( size_t index ) const {
return this->assertSIData().at( index );
}
const std::vector< double >& DeckItemT< double >::getSIData() const {
return this->assertSIData();
}
void DeckItemT< double >::push_backDimension(
std::shared_ptr< const Dimension > activeDimension,
std::shared_ptr< const Dimension > defaultDimension ) {
if( this->size() == 0 || this->defaultApplied( this->size() - 1 ) )
this->dimensions.push_back( defaultDimension );
else
this->dimensions.push_back( activeDimension );
}
template< typename T >
std::unique_ptr< DeckItemBase > DeckItemT< T >::clone() const {
return std::unique_ptr< DeckItemBase > { new DeckItemT< T >( *this ) };
}
std::unique_ptr< DeckItemBase > DeckItemT< double >::clone() const {
return std::unique_ptr< DeckItemBase > { new DeckItemT< double >( *this ) };
}
const std::vector< double >& DeckItemT< double >::assertSIData() const {
if( this->dimensions.size() <= 0 )
throw std::invalid_argument("No dimension has been set for item:" + this->name() + " can not ask for SI data");
// we already converted this item to SI?
if( this->SIdata.size() > 0 ) return this->SIdata;
/*
* This is an unobservable state change - SIData is lazily converted to
* SI units, so externally the object still behaves as const
*/
auto& data = const_cast< DeckItemT< double >* >( this )->SIdata;
data.resize( this->size() );
for( size_t index = 0; index < this->size(); index++ ) {
const auto dimIndex = ( index % dimensions.size() );
data[ index ] = this->dimensions[ dimIndex ]
->convertRawToSi( this->get( index ) );
}
return data;
}
template< typename Ptr >
static inline DeckItem::type typeof_item( Ptr* item ) {
if( dynamic_cast< DeckItemT< int >* >( item ) )
return DeckItem::type::integer;
if( dynamic_cast< DeckItemT< std::string >* >( item ) )
return DeckItem::type::string;
if( dynamic_cast< DeckItemT< double >* >( item ) )
return DeckItem::type::fdouble;
return DeckItem::type::unknown;
}
static inline std::string typetag_to_string( DeckItem::type x ) {
switch( x ) {
case DeckItem::type::integer: return "int";
case DeckItem::type::string: return "std::string";
case DeckItem::type::fdouble: return "double";
case DeckItem::type::unknown: return "unknown";
}
return "unknown";
}
template< typename T > static std::string typename_string();
template<>
std::string typename_string< int >() {
return "int";
}
template<>
std::string typename_string< double >() {
return "double";
}
template<>
std::string typename_string< std::string >() {
return "std::string";
}
template< typename T >
static inline DeckItemT< T >* conv( std::unique_ptr< DeckItemBase >& ptr ) {
if( auto* d = dynamic_cast< DeckItemT< T >* >( ptr.get() ) )
return d;
throw std::logic_error(
"Treating item " + ptr->name()
+ " as " + typename_string< T >()
+ ", but is "
+ typetag_to_string( typeof_item( ptr.get() ) ) );
}
template< typename T >
static inline
const DeckItemT< T >* conv( const std::unique_ptr< DeckItemBase >& ptr ) {
if( auto* d = dynamic_cast< const DeckItemT< T >* >( ptr.get() ) )
return d;
throw std::logic_error(
"Treating item " + ptr->name()
+ " as " + typename_string< T >()
+ ", but is "
+ typetag_to_string( typeof_item( ptr.get() ) ) );
}
DeckItem::DeckItem( const DeckItem& rhs ) :
ptr( rhs.ptr->clone() )
{}
DeckItem::DeckItem( std::unique_ptr< DeckItemBase >&& x ) :
ptr( std::move( x ) )
{}
template< typename T >
DeckItem DeckItem::make( const std::string& name, size_t size ) {
return DeckItem( std::unique_ptr< DeckItemBase > { new DeckItemT< T >( name, size ) } );
}
const std::string& DeckItem::name() const {
return this->ptr->name();
}
bool DeckItem::defaultApplied( size_t index ) const {
return this->ptr->defaultApplied( index );
}
bool DeckItem::hasValue( size_t index ) const {
return this->ptr->hasValue( index );
}
size_t DeckItem::size() const {
return this->ptr->size();
}
template< typename T >
const T& DeckItem::get( size_t index ) const {
return conv< T >( this->ptr )->get( index );
}
template< typename T >
const std::vector< T >& DeckItem::getData() const {
return conv< T >( this->ptr )->getData();
}
template< typename T >
void DeckItem::push_back( T x ) {
return conv< T >( this->ptr )->push_back( x );
}
template< typename T >
void DeckItem::push_back( T x, size_t n ) {
return conv< T >( this->ptr )->push_back( x, n );
}
template< typename T >
void DeckItem::push_backDefault( T x ) {
return conv< T >( this->ptr )->push_backDefault( x );
}
template<>
void DeckItem::push_back( const char* x ) {
return conv< std::string >( this->ptr )->push_back( x );
}
template<>
void DeckItem::push_back( const char* x, size_t n ) {
return conv< std::string >( this->ptr )->push_back( x, n );
}
template<>
void DeckItem::push_backDefault( const char* x ) {
return conv< std::string >( this->ptr )->push_backDefault( x );
}
void DeckItem::push_backDummyDefault() {
return this->ptr->push_backDummyDefault();
}
std::string DeckItem::getTrimmedString( size_t index ) const {
return boost::algorithm::trim_copy(
conv< std::string >( this->ptr )->get( index )
);
}
double DeckItem::getSIDouble( size_t index ) const {
return conv< double >( this->ptr )->getSI( index );
}
const std::vector< double >& DeckItem::getSIDoubleData() const {
return conv< double >( this->ptr )->getSIData();
}
void DeckItem::push_backDimension( std::shared_ptr< const Dimension > active,
std::shared_ptr< const Dimension > def ) {
return conv< double >( this->ptr )->push_backDimension( active, def );
}
DeckItem::type DeckItem::typeof() const {
return typeof_item( this->ptr.get() );
}
/*
* Explicit template instantiations. These must be manually maintained and
* updated with changes in DeckItem so that code is emitted.
*/
template class DeckTypeItem< int >;
template class DeckTypeItem< double >;
template class DeckTypeItem< std::string >;
template class DeckItemT< int >;
template class DeckItemT< double >;
template class DeckItemT< std::string >;
template DeckItem DeckItem::make< int >( const std::string&, size_t );
template DeckItem DeckItem::make< double >( const std::string&, size_t );
template DeckItem DeckItem::make< std::string >( const std::string&, size_t );
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 std::vector< int >& DeckItem::getData< int >() const;
template const std::vector< double >& DeckItem::getData< double >() const;
template const std::vector< std::string >& DeckItem::getData< std::string >() const;
template void DeckItem::push_back< int >( int );
template void DeckItem::push_back< double >( double );
template void DeckItem::push_back< std::string >( std::string );
template void DeckItem::push_back< int >( int, size_t );
template void DeckItem::push_back< double >( double, size_t );
template void DeckItem::push_back< std::string >( std::string, size_t );
template void DeckItem::push_backDefault< int >( int );
template void DeckItem::push_backDefault< double >( double );
template void DeckItem::push_backDefault< std::string >( std::string );
}