2019-02-01 08:57:05 +01:00
/*
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/>.
*/
2019-03-28 11:55:50 +01:00
#include "EclFile.hpp"
#include "EclUtil.hpp"
2019-04-30 11:39:21 +02:00
#include <array>
2019-03-28 11:55:50 +01:00
#include <functional>
2019-02-01 08:57:05 +01:00
#include <string>
#include <string.h>
#include <sstream>
#include <iterator>
#include <iomanip>
#include <algorithm>
2019-03-28 11:55:50 +01:00
#include <opm/common/ErrorMacros.hpp>
2019-02-01 08:57:05 +01:00
// anonymous namespace for EclFile
namespace {
2019-03-28 11:55:50 +01:00
bool isFormatted ( const std :: string & filename )
{
int p = filename . find_last_of ( "." );
int l = filename . length ();
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
std :: string rootN = filename . substr ( 0 , p );
std :: string extension = filename . substr ( p , l - p );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
return extension . substr ( 1 , 1 ) == "F" || extension . substr ( 1 , 1 ) == "A" ;
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
bool isEOF ( std :: fstream * fileH )
{
int num ;
long int pos = fileH -> tellg ();
fileH -> read ( reinterpret_cast < char *> ( & num ), sizeof ( num ));
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( fileH -> eof ()) {
return true ;
} else {
fileH -> seekg ( pos );
return false ;
2019-02-01 08:57:05 +01:00
}
}
2019-03-28 11:55:50 +01:00
void readBinaryHeader ( std :: fstream & fileH , std :: string & arrName ,
int & size , EIOD :: eclArrType & arrType )
{
2019-02-01 08:57:05 +01:00
int bhead ;
std :: string tmpStrName ( 8 , ' ' );
std :: string tmpStrType ( 4 , ' ' );
2019-03-28 11:55:50 +01:00
fileH . read ( reinterpret_cast < char *> ( & bhead ), sizeof ( bhead ));
bhead = EIOD :: flipEndianInt ( bhead );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( bhead != 16 ) {
2019-02-01 08:57:05 +01:00
std :: string message = "Error reading binary header. Expected 16 bytes of header data, found " + std :: to_string ( bhead );
2019-03-28 11:55:50 +01:00
OPM_THROW ( std :: runtime_error , message );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
2019-02-01 08:57:05 +01:00
fileH . read ( & tmpStrName [ 0 ], 8 );
2019-03-28 11:55:50 +01:00
fileH . read ( reinterpret_cast < char *> ( & size ), sizeof ( size ));
size = EIOD :: flipEndianInt ( size );
2019-02-01 08:57:05 +01:00
fileH . read ( & tmpStrType [ 0 ], 4 );
2019-03-28 11:55:50 +01:00
fileH . read ( reinterpret_cast < char *> ( & bhead ), sizeof ( bhead ));
bhead = EIOD :: flipEndianInt ( bhead );
if ( bhead != 16 ) {
2019-02-01 08:57:05 +01:00
std :: string message = "Error reading binary header. Expected 16 bytes of header data, found " + std :: to_string ( bhead );
2019-03-28 11:55:50 +01:00
OPM_THROW ( std :: runtime_error , message );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
arrName = tmpStrName ;
if ( tmpStrType == "INTE" )
arrType = EIOD :: INTE ;
else if ( tmpStrType == "REAL" )
arrType = EIOD :: REAL ;
else if ( tmpStrType == "DOUB" )
arrType = EIOD :: DOUB ;
else if ( tmpStrType == "CHAR" )
arrType = EIOD :: CHAR ;
else if ( tmpStrType == "LOGI" )
arrType = EIOD :: LOGI ;
else if ( tmpStrType == "MESS" )
arrType = EIOD :: MESS ;
2019-02-01 08:57:05 +01:00
else
2019-03-28 11:55:50 +01:00
OPM_THROW ( std :: runtime_error , "Error, unknown array type '" + tmpStrType + "'" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
unsigned long int sizeOnDiskBinary ( int num , EIOD :: eclArrType arrType )
{
unsigned long int size = 0 ;
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( arrType == EIOD :: MESS ) {
if ( num > 0 ) {
std :: string message = "In routine calcSizeOfArray, type MESS can not have size > 0" ;
OPM_THROW ( std :: invalid_argument , message );
2019-02-01 08:57:05 +01:00
}
} else {
2019-03-28 11:55:50 +01:00
auto sizeData = EIOD :: block_size_data_binary ( arrType );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
int sizeOfElement = std :: get < 0 > ( sizeData );
2019-02-01 08:57:05 +01:00
int maxBlockSize = std :: get < 1 > ( sizeData );
2019-03-28 11:55:50 +01:00
int maxNumberOfElements = maxBlockSize / sizeOfElement ;
size = num * sizeOfElement ;
size = size + (( num - 1 ) / maxNumberOfElements ) * 2 * EIOD :: sizeOfInte ; // 8 byte (two integers) every 1000 element
if ( num > 0 ) {
size = size + 2 * EIOD :: sizeOfInte ;
2019-02-01 08:57:05 +01:00
}
}
2019-03-28 11:55:50 +01:00
2019-02-01 08:57:05 +01:00
return size ;
}
2019-03-28 11:55:50 +01:00
unsigned long int sizeOnDiskFormatted ( const int num , EIOD :: eclArrType arrType )
{
unsigned long int size = 0 ;
if ( arrType == EIOD :: MESS ) {
if ( num > 0 ) {
OPM_THROW ( std :: invalid_argument , "In routine calcSizeOfArray, type MESS can not have size > 0" );
}
} else {
auto sizeData = block_size_data_formatted ( arrType );
int maxBlockSize = std :: get < 0 > ( sizeData );
int nColumns = std :: get < 1 > ( sizeData );
int columnWidth = std :: get < 2 > ( sizeData );
int nBlocks = num / maxBlockSize ;
int sizeOfLastBlock = num % maxBlockSize ;
size = 0 ;
if ( nBlocks > 0 ) {
int nLinesBlock = maxBlockSize / nColumns ;
int rest = maxBlockSize % nColumns ;
if ( rest > 0 ) {
nLinesBlock ++ ;
}
long int blockSize = maxBlockSize * columnWidth + nLinesBlock ;
size = nBlocks * blockSize ;
}
int nLines = sizeOfLastBlock / nColumns ;
int rest = sizeOfLastBlock % nColumns ;
size = size + sizeOfLastBlock * columnWidth + nLines ;
if ( rest > 0 ) {
size ++ ;
}
}
return size ;
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
template < typename T , typename T2 >
std :: vector < T > readBinaryArray ( std :: fstream & fileH , const int size , EIOD :: eclArrType type ,
std :: function < T ( T2 ) >& flip )
{
std :: vector < T > arr ;
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
auto sizeData = block_size_data_binary ( type );
2019-02-01 08:57:05 +01:00
int sizeOfElement = std :: get < 0 > ( sizeData );
int maxBlockSize = std :: get < 1 > ( sizeData );
2019-03-28 11:55:50 +01:00
int maxNumberOfElements = maxBlockSize / sizeOfElement ;
2019-02-01 08:57:05 +01:00
arr . reserve ( size );
2019-03-28 11:55:50 +01:00
int rest = size ;
while ( rest > 0 ) {
int dhead ;
fileH . read ( reinterpret_cast < char *> ( & dhead ), sizeof ( dhead ));
dhead = EIOD :: flipEndianInt ( dhead );
int num = dhead / sizeOfElement ;
if (( num > maxNumberOfElements ) || ( num < 0 )) {
OPM_THROW ( std :: runtime_error , "Error reading binary data, inconsistent header data or incorrect number of elements" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
for ( int i = 0 ; i < num ; i ++ ) {
T2 value ;
fileH . read ( reinterpret_cast < char *> ( & value ), sizeOfElement );
arr . push_back ( flip ( value ));
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
rest -= num ;
if (( num < maxNumberOfElements && rest != 0 ) ||
( num == maxNumberOfElements && rest < 0 )) {
std :: string message = "Error reading binary data, incorrect number of elements" ;
OPM_THROW ( std :: runtime_error , message );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
int dtail ;
fileH . read ( reinterpret_cast < char *> ( & dtail ), sizeof ( dtail ));
dtail = EIOD :: flipEndianInt ( dtail );
if ( dhead != dtail ) {
OPM_THROW ( std :: runtime_error , "Error reading binary data, tail not matching header." );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
}
2019-02-01 08:57:05 +01:00
return arr ;
}
2019-03-28 11:55:50 +01:00
std :: vector < int > readBinaryInteArray ( std :: fstream & fileH , const int size )
{
std :: function < int ( int ) > f = EIOD :: flipEndianInt ;
return readBinaryArray < int , int > ( fileH , size , EIOD :: INTE , f );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
std :: vector < float > readBinaryRealArray ( std :: fstream & fileH , const int size )
{
std :: function < float ( float ) > f = EIOD :: flipEndianFloat ;
return readBinaryArray < float , float > ( fileH , size , EIOD :: REAL , f );
}
std :: vector < double > readBinaryDoubArray ( std :: fstream & fileH , const int size )
{
std :: function < double ( double ) > f = EIOD :: flipEndianDouble ;
return readBinaryArray < double , double > ( fileH , size , EIOD :: DOUB , f );
}
std :: vector < bool > readBinaryLogiArray ( std :: fstream & fileH , const int size )
{
std :: function < bool ( unsigned int ) > f = []( unsigned int intVal )
{
bool value ;
if ( intVal == EIOD :: true_value ) {
value = true ;
} else if ( intVal == EIOD :: false_value ) {
value = false ;
} else {
OPM_THROW ( std :: runtime_error , "Error reading logi value" );
}
return value ;
};
return readBinaryArray < bool , unsigned int > ( fileH , size , EIOD :: LOGI , f );
}
std :: vector < std :: string > readBinaryCharArray ( std :: fstream & fileH , const int size )
{
using Char8 = std :: array < char , 8 > ;
std :: function < std :: string ( Char8 ) > f = []( const Char8 & val )
{
std :: string res ( val . begin (), val . end ());
return EIOD :: trimr ( res );
};
return readBinaryArray < std :: string , Char8 > ( fileH , size , EIOD :: CHAR , f );
}
std :: vector < std :: string > split_string ( const std :: string & inputStr )
{
std :: istringstream iss ( inputStr );
std :: vector < std :: string > tokens { std :: istream_iterator < std :: string > { iss },
std :: istream_iterator < std :: string > {}
};
return tokens ;
}
void readFormattedHeader ( std :: fstream & fileH , std :: string & arrName ,
int & num , EIOD :: eclArrType & arrType )
{
std :: string line ;
getline ( fileH , line );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
int p1 = line . find_first_of ( "'" );
int p2 = line . find_first_of ( "'" , p1 + 1 );
int p3 = line . find_first_of ( "'" , p2 + 1 );
int p4 = line . find_first_of ( "'" , p3 + 1 );
if ( p1 == - 1 || p2 == - 1 || p3 == - 1 || p4 == - 1 ) {
OPM_THROW ( std :: runtime_error , "Header name and type should be enclosed with '" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
arrName = line . substr ( p1 + 1 , p2 - p1 - 1 );
std :: string antStr = line . substr ( p2 + 1 , p3 - p2 - 1 );
std :: string arrTypeStr = line . substr ( p3 + 1 , p4 - p3 - 1 );
num = std :: stoi ( antStr );
if ( arrTypeStr == "INTE" )
arrType = EIOD :: INTE ;
else if ( arrTypeStr == "REAL" )
arrType = EIOD :: REAL ;
else if ( arrTypeStr == "DOUB" )
arrType = EIOD :: DOUB ;
else if ( arrTypeStr == "CHAR" )
arrType = EIOD :: CHAR ;
else if ( arrTypeStr == "LOGI" )
arrType = EIOD :: LOGI ;
else if ( arrTypeStr == "MESS" )
arrType = EIOD :: MESS ;
else
OPM_THROW ( std :: runtime_error , "Error, unknown array type '" + arrTypeStr + "'" );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( arrName . size () != 8 ) {
OPM_THROW ( std :: runtime_error , "Header name should be 8 characters" );
}
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
template < typename T >
std :: vector < T > readFormattedArray ( std :: fstream & fileH , const int size ,
std :: function < T ( const std :: string & ) >& process )
{
std :: vector < T > arr ;
std :: vector < std :: string > tokens ;
std :: string line ;
int num = 0 ;
while ( num < size ) {
if ( fileH . eof ()) {
OPM_THROW ( std :: runtime_error , "End of file reached when reading array" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
getline ( fileH , line );
tokens = split_string ( line );
for ( const std :: string & token : tokens ) {
arr . push_back ( process ( token ));
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
num = num + tokens . size ();
}
2019-02-01 08:57:05 +01:00
return arr ;
}
2019-03-28 11:55:50 +01:00
std :: vector < int > readFormattedInteArray ( std :: fstream & fileH , const int size )
{
std :: function < int ( const std :: string & ) > f = []( const std :: string & val )
{
return std :: stoi ( val );
};
return readFormattedArray ( fileH , size , f );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
std :: vector < std :: string > readFormattedCharArray ( std :: fstream & fileH , const int size )
{
if ( ! fileH . is_open ()) {
OPM_THROW ( std :: runtime_error , "fstream fileH not open for reading" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
std :: vector < std :: string > arr ;
int num = 0 ;
while ( num < size ) {
std :: string line ;
getline ( fileH , line );
if ( line . empty ()) {
std :: string message = "Reading formatted char array, end of file or blank line, read " + std :: to_string ( arr . size ()) + " of " + std :: to_string ( size ) + " elements" ;
OPM_THROW ( std :: runtime_error , message );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
int p1 = line . find_first_of ( "'" );
if ( p1 == - 1 ) {
std :: string message = "Reading formatted char array, all strings must be enclosed by apostrophe (')" ;
OPM_THROW ( std :: runtime_error , message );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
while ( p1 > - 1 ) {
int p2 = line . find_first_of ( "'" , p1 + 1 );
if ( p2 == - 1 ) {
std :: string message = "Reading formatted char array, all strings must be enclosed by apostrophe (')" ;
OPM_THROW ( std :: runtime_error , message );
}
std :: string value = line . substr ( p1 + 1 , p2 - p1 - 1 );
if ( value . size () != 8 ) {
std :: string message = "Reading formatted char array, all strings should have 8 characters" ;
OPM_THROW ( std :: runtime_error , message );
}
if ( value == " " ) {
arr . push_back ( "" );
} else {
arr . push_back ( EIOD :: trimr ( value ));
}
num ++ ;
p1 = line . find_first_of ( "'" , p2 + 1 );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
}
2019-02-01 08:57:05 +01:00
return arr ;
}
2019-03-28 11:55:50 +01:00
std :: vector < float > readFormattedRealArray ( std :: fstream & fileH , const int size )
{
std :: function < float ( const std :: string & ) > f = []( const std :: string & val )
{
// tskille: temporary fix, need to be discussed. OPM flow writes numbers
// that are outside valid range for float, and function stof will fail
double dtmpv = std :: stod ( val );
return dtmpv ;
};
return readFormattedArray < float > ( fileH , size , f );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
std :: vector < bool > readFormattedLogiArray ( std :: fstream & fileH , const int size )
{
std :: function < bool ( const std :: string & ) > f = []( const std :: string & val )
{
if ( val == "T" ) {
return true ;
} else if ( val == "F" ) {
return false ;
} else {
std :: string message = "Could not convert '" + val + "' to a bool value " ;
OPM_THROW ( std :: invalid_argument , message );
}
};
return readFormattedArray < bool > ( fileH , size , f );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
std :: vector < double > readFormattedDoubArray ( std :: fstream & fileH , const int size )
{
std :: function < double ( const std :: string & ) > f = []( const std :: string & value )
{
std :: string val ( value );
int p1 = val . find_first_of ( "D" );
if ( p1 == - 1 ) {
p1 = val . find_first_of ( "-" , 1 );
if ( p1 > - 1 ) {
val = val . insert ( p1 , "E" );
} else {
p1 = val . find_first_of ( "+" , 1 );
if ( p1 == - 1 ) {
std :: string message = "In Routine Read readFormattedDoubArray, could not convert '" + val + "' to double." ;
OPM_THROW ( std :: invalid_argument , message );
}
val = val . insert ( p1 , "E" );
}
} else {
val . replace ( p1 , 1 , "E" );
}
return std :: stod ( val );
};
return readFormattedArray < double > ( fileH , size , f );
}
} // anonymous namespace
EclFile :: EclFile ( const std :: string & filename ) : inputFilename ( filename )
{
std :: fstream fileH ;
formatted = isFormatted ( filename );
if ( formatted ) {
fileH . open ( filename , std :: ios :: in );
} else {
fileH . open ( filename , std :: ios :: in | std :: ios :: binary );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
if ( ! fileH ) {
std :: string message = "Could not open file: " + filename ;
OPM_THROW ( std :: runtime_error , message );
}
int n = 0 ;
while ( ! isEOF ( & fileH )) {
std :: string arrName ( 8 , ' ' );
EIOD :: eclArrType arrType ;
int num ;
if ( formatted ) {
readFormattedHeader ( fileH , arrName , num , arrType );
} else {
readBinaryHeader ( fileH , arrName , num , arrType );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
array_size . push_back ( num );
array_type . push_back ( arrType );
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
array_name . push_back ( EIOD :: trimr ( arrName ));
array_index [ array_name [ n ]] = n ;
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
unsigned long int pos = fileH . tellg ();
ifStreamPos . push_back ( pos );
arrayLoaded . push_back ( false );
if ( formatted ) {
unsigned long int sizeOfNextArray = sizeOnDiskFormatted ( num , arrType );
fileH . ignore ( sizeOfNextArray );
} else {
unsigned long int sizeOfNextArray = sizeOnDiskBinary ( num , arrType );
fileH . ignore ( sizeOfNextArray );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
n ++ ;
};
fileH . close ();
}
void EclFile :: loadArray ( std :: fstream & fileH , int arrIndex )
{
fileH . seekg ( ifStreamPos [ arrIndex ], fileH . beg );
if ( formatted ) {
switch ( array_type [ arrIndex ]) {
case EIOD :: INTE :
inte_array [ arrIndex ] = readFormattedInteArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: REAL :
real_array [ arrIndex ] = readFormattedRealArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: DOUB :
doub_array [ arrIndex ] = readFormattedDoubArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: LOGI :
logi_array [ arrIndex ] = readFormattedLogiArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: CHAR :
char_array [ arrIndex ] = readFormattedCharArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: MESS :
break ;
default :
OPM_THROW ( std :: runtime_error , "Asked to read unexpected array type" );
break ;
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
} else {
switch ( array_type [ arrIndex ]) {
case EIOD :: INTE :
inte_array [ arrIndex ] = readBinaryInteArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: REAL :
real_array [ arrIndex ] = readBinaryRealArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: DOUB :
doub_array [ arrIndex ] = readBinaryDoubArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: LOGI :
logi_array [ arrIndex ] = readBinaryLogiArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: CHAR :
char_array [ arrIndex ] = readBinaryCharArray ( fileH , array_size [ arrIndex ]);
break ;
case EIOD :: MESS :
break ;
default :
OPM_THROW ( std :: runtime_error , "Asked to read unexpected array type" );
break ;
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
}
arrayLoaded [ arrIndex ] = true ;
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
void EclFile :: loadData ()
{
std :: fstream fileH ;
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( formatted ) {
fileH . open ( inputFilename , std :: ios :: in );
} else {
fileH . open ( inputFilename , std :: ios :: in | std :: ios :: binary );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( ! fileH ) {
std :: string message = "Could not open file: '" + inputFilename + "'" ;
OPM_THROW ( std :: runtime_error , message );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
for ( size_t i = 0 ; i < array_name . size (); i ++ ) {
loadArray ( fileH , i );
}
fileH . close ();
}
void EclFile :: loadData ( const std :: string & name )
{
std :: fstream fileH ;
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
if ( formatted ) {
fileH . open ( inputFilename , std :: ios :: in );
} else {
fileH . open ( inputFilename , std :: ios :: in | std :: ios :: binary );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
if ( ! fileH ) {
std :: string message = "Could not open file: '" + inputFilename + "'" ;
OPM_THROW ( std :: runtime_error , message );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
for ( size_t i = 0 ; i < array_name . size (); i ++ ) {
if ( array_name [ i ] == name ) {
loadArray ( fileH , i );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
}
fileH . close ();
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
void EclFile :: loadData ( const std :: vector < int >& arrIndex )
{
std :: fstream fileH ;
if ( formatted ) {
fileH . open ( inputFilename , std :: ios :: in );
} else {
fileH . open ( inputFilename , std :: ios :: in | std :: ios :: binary );
}
if ( ! fileH ) {
std :: string message = "Could not open file: '" + inputFilename + "'" ;
OPM_THROW ( std :: runtime_error , message );
}
for ( int ind : arrIndex ) {
loadArray ( fileH , ind );
}
fileH . close ();
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
void EclFile :: loadData ( int arrIndex )
{
2019-02-01 08:57:05 +01:00
std :: fstream fileH ;
2019-03-28 11:55:50 +01:00
if ( formatted ) {
fileH . open ( inputFilename , std :: ios :: in );
} else {
fileH . open ( inputFilename , std :: ios :: in | std :: ios :: binary );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
if ( ! fileH ) {
std :: string message = "Could not open file: '" + inputFilename + "'" ;
OPM_THROW ( std :: runtime_error , message );
}
loadArray ( fileH , arrIndex );
2019-02-01 08:57:05 +01:00
fileH . close ();
2019-03-28 11:55:50 +01:00
}
std :: vector < EclFile :: EclEntry > EclFile :: getList () const
{
std :: vector < EclEntry > list ;
list . reserve ( this -> array_name . size ());
for ( size_t i = 0 ; i < array_name . size (); i ++ ) {
list . emplace_back ( array_name [ i ], array_type [ i ], array_size [ i ]);
}
return list ;
}
template <>
const std :: vector < int >& EclFile :: get < int > ( int arrIndex )
{
return getImpl ( arrIndex , EIOD :: INTE , inte_array , "integer" );
}
template <>
const std :: vector < float >&
EclFile :: get < float > ( int arrIndex )
{
return getImpl ( arrIndex , EIOD :: REAL , real_array , "float" );
}
template <>
const std :: vector < double > & EclFile :: get < double > ( int arrIndex )
{
return getImpl ( arrIndex , EIOD :: DOUB , doub_array , "double" );
}
template <>
const std :: vector < bool >& EclFile :: get < bool > ( int arrIndex )
{
return getImpl ( arrIndex , EIOD :: LOGI , logi_array , "bool" );
}
2019-02-01 08:57:05 +01:00
2019-03-28 11:55:50 +01:00
template <>
const std :: vector < std :: string >& EclFile :: get < std :: string > ( int arrIndex )
{
return getImpl ( arrIndex , EIOD :: CHAR , char_array , "string" );
2019-02-01 08:57:05 +01:00
}
2019-03-28 11:55:50 +01:00
bool EclFile :: hasKey ( const std :: string & name ) const
{
auto search = array_index . find ( name );
return search != array_index . end ();
}
template <>
const std :: vector < int >& EclFile :: get < int > ( const std :: string & name )
{
auto search = array_index . find ( name );
if ( search == array_index . end ()) {
std :: string message = "key '" + name + "' not found" ;
OPM_THROW ( std :: invalid_argument , message );
}
return getImpl ( search -> second , EIOD :: INTE , inte_array , "integer" );
}
template <>
const std :: vector < float >& EclFile :: get < float > ( const std :: string & name )
{
auto search = array_index . find ( name );
if ( search == array_index . end ()) {
std :: string message = "key '" + name + "' not found" ;
OPM_THROW ( std :: invalid_argument , message );
}
return getImpl ( search -> second , EIOD :: REAL , real_array , "float" );
}
template <>
const std :: vector < double >& EclFile :: get < double > ( const std :: string & name )
{
auto search = array_index . find ( name );
if ( search == array_index . end ()) {
std :: string message = "key '" + name + "' not found" ;
OPM_THROW ( std :: invalid_argument , message );
}
return getImpl ( search -> second , EIOD :: DOUB , doub_array , "double" );
}
template <>
const std :: vector < bool >& EclFile :: get < bool > ( const std :: string & name )
{
auto search = array_index . find ( name );
if ( search == array_index . end ()) {
std :: string message = "key '" + name + "' not found" ;
OPM_THROW ( std :: invalid_argument , message );
}
return getImpl ( search -> second , EIOD :: LOGI , logi_array , "bool" );
}
template <>
const std :: vector < std :: string >& EclFile :: get < std :: string > ( const std :: string & name )
{
auto search = array_index . find ( name );
if ( search == array_index . end ()) {
std :: string message = "key '" + name + "' not found" ;
OPM_THROW ( std :: invalid_argument , message );
}
return getImpl ( search -> second , EIOD :: CHAR , char_array , "string" );
}