2019-03-28 15:03:20 +01:00
#include <chrono>
#include <iomanip>
2019-05-02 15:01:20 +02:00
#include <iostream>
#include <tuple>
2019-07-18 17:55:34 +02:00
#include <getopt.h>
2019-03-28 15:03:20 +01:00
2019-05-02 15:01:20 +02:00
#include <opm/io/eclipse/EclFile.hpp>
2019-07-18 17:55:34 +02:00
#include <opm/io/eclipse/ERst.hpp>
2019-05-02 15:01:20 +02:00
#include <opm/io/eclipse/EclOutput.hpp>
2019-03-28 15:03:20 +01:00
2019-05-24 15:26:01 +02:00
using namespace Opm :: EclIO ;
2020-03-24 08:05:34 +01:00
using EclEntry = EclFile :: EclEntry ;
2019-03-28 15:03:20 +01:00
2019-07-18 17:55:34 +02:00
template < typename T >
2019-03-28 15:03:20 +01:00
void write ( EclOutput & outFile , EclFile & file1 ,
const std :: string & name , int index )
{
auto vect = file1 . get < T > ( index );
outFile . write ( name , vect );
}
2019-07-18 17:55:34 +02:00
template < typename T >
void write ( EclOutput & outFile , ERst & file1 ,
2019-11-03 19:34:25 +01:00
const std :: string & name , int index , int reportStepNumber )
2019-07-18 17:55:34 +02:00
{
2019-11-03 19:34:25 +01:00
auto vect = file1 . getRst < T > ( index , reportStepNumber );
outFile . write ( name , vect );
}
2019-07-18 17:55:34 +02:00
2019-11-03 19:34:25 +01:00
template < typename T >
void write ( EclOutput & outFile , ERst & file1 ,
const std :: string & name , int index )
{
auto vect = file1 . get < T > ( index );
2019-07-18 17:55:34 +02:00
outFile . write ( name , vect );
}
2019-11-03 19:34:25 +01:00
2019-07-18 17:55:34 +02:00
template < typename T >
void writeArray ( std :: string name , eclArrType arrType , T & file1 , int index , EclOutput & outFile ) {
if ( arrType == INTE ) {
write < int > ( outFile , file1 , name , index );
} else if ( arrType == REAL ) {
write < float > ( outFile , file1 , name , index );
} else if ( arrType == DOUB ) {
write < double > ( outFile , file1 , name , index );
} else if ( arrType == LOGI ) {
write < bool > ( outFile , file1 , name , index );
} else if ( arrType == CHAR ) {
write < std :: string > ( outFile , file1 , name , index );
} else if ( arrType == MESS ) {
outFile . message ( name );
} else {
std :: cout << "unknown array type " << std :: endl ;
exit ( 1 );
}
}
2019-11-03 19:34:25 +01:00
template < typename T >
void writeArray ( std :: string name , eclArrType arrType , T & file1 , int index , int reportStepNumber , EclOutput & outFile ) {
if ( arrType == INTE ) {
write < int > ( outFile , file1 , name , index , reportStepNumber );
} else if ( arrType == REAL ) {
write < float > ( outFile , file1 , name , index , reportStepNumber );
} else if ( arrType == DOUB ) {
write < double > ( outFile , file1 , name , index , reportStepNumber );
} else if ( arrType == LOGI ) {
write < bool > ( outFile , file1 , name , index , reportStepNumber );
} else if ( arrType == CHAR ) {
write < std :: string > ( outFile , file1 , name , index , reportStepNumber );
} else if ( arrType == MESS ) {
outFile . message ( name );
} else {
std :: cout << "unknown array type " << std :: endl ;
exit ( 1 );
}
}
2019-07-18 17:55:34 +02:00
void writeArrayList ( std :: vector < EclEntry >& arrayList , EclFile file1 , EclOutput & outFile ) {
for ( size_t index = 0 ; index < arrayList . size (); index ++ ) {
std :: string name = std :: get < 0 > ( arrayList [ index ]);
eclArrType arrType = std :: get < 1 > ( arrayList [ index ]);
writeArray ( name , arrType , file1 , index , outFile );
}
}
void writeArrayList ( std :: vector < EclEntry >& arrayList , ERst file1 , int reportStepNumber , EclOutput & outFile ) {
for ( size_t index = 0 ; index < arrayList . size (); index ++ ) {
std :: string name = std :: get < 0 > ( arrayList [ index ]);
eclArrType arrType = std :: get < 1 > ( arrayList [ index ]);
2019-11-03 19:34:25 +01:00
writeArray ( name , arrType , file1 , index , reportStepNumber , outFile );
2019-07-18 17:55:34 +02:00
}
}
static void printHelp () {
std :: cout << " \n convertECL needs one argument which is the input file to be converted. If this is a binary file the output file will be formatted. If the input file is formatted the output will be binary. \n "
<< " \n In addition, the program takes these options (which must be given before the arguments): \n\n "
<< "-h Print help and exit. \n "
<< "-l list report step numbers in the selected restart file. \n "
<< "-r extract and convert a spesific report time step number from a unified restart file. \n\n " ;
}
2019-03-28 15:03:20 +01:00
int main ( int argc , char ** argv ) {
2019-07-18 17:55:34 +02:00
int c = 0 ;
int reportStepNumber = - 1 ;
bool specificReportStepNumber = false ;
bool listProperties = false ;
while (( c = getopt ( argc , argv , "hr:l" )) != - 1 ) {
switch ( c ) {
case 'h' :
printHelp ();
return 0 ;
case 'l' :
listProperties = true ;
break ;
case 'r' :
specificReportStepNumber = true ;
reportStepNumber = atoi ( optarg );
break ;
default :
return EXIT_FAILURE ;
}
2019-03-28 15:03:20 +01:00
}
2019-07-18 17:55:34 +02:00
int argOffset = optind ;
2019-03-28 15:03:20 +01:00
// start reading
auto start = std :: chrono :: system_clock :: now ();
2019-07-18 17:55:34 +02:00
std :: string filename = argv [ argOffset ];
2019-03-28 15:03:20 +01:00
EclFile file1 ( filename );
bool formattedOutput = file1 . formattedInput () ? false : true ;
int p = filename . find_last_of ( "." );
int l = filename . length ();
std :: string rootN = filename . substr ( 0 , p );
std :: string extension = filename . substr ( p , l - p );
std :: string resFile ;
2019-07-18 17:55:34 +02:00
if ( listProperties ) {
if ( extension == ".UNRST" ) {
ERst rst1 ( filename );
rst1 . loadData ( "INTEHEAD" );
std :: vector < int > reportStepList = rst1 . listOfReportStepNumbers ();
for ( auto seqn : reportStepList ) {
2019-11-03 19:34:25 +01:00
std :: vector < int > inteh = rst1 . getRst < int > ( "INTEHEAD" , seqn , 0 );
2019-07-18 17:55:34 +02:00
std :: cout << "Report step number: "
<< std :: setfill ( ' ' ) << std :: setw ( 4 ) << seqn << " Date: " << inteh [ 66 ] << "/"
<< std :: setfill ( '0' ) << std :: setw ( 2 ) << inteh [ 65 ] << "/"
<< std :: setfill ( '0' ) << std :: setw ( 2 ) << inteh [ 64 ] << std :: endl ;
}
std :: cout << std :: endl ;
} else {
std :: cout << " \n !ERROR, option -l only only available for unified restart files (*.UNRST) " << std :: endl ;
exit ( 1 );
}
return 0 ;
}
2019-09-16 15:02:21 +02:00
std :: map < std :: string , std :: string > to_formatted = {{ ".EGRID" , ".FEGRID" }, { ".INIT" , ".FINIT" }, { ".SMSPEC" , ".FSMSPEC" },
{ ".UNSMRY" , ".FUNSMRY" }, { ".UNRST" , ".FUNRST" }, { ".RFT" , ".FRFT" }};
2019-07-18 17:55:34 +02:00
2019-09-16 15:02:21 +02:00
std :: map < std :: string , std :: string > to_binary = {{ ".FEGRID" , ".EGRID" }, { ".FINIT" , ".INIT" }, { ".FSMSPEC" , ".SMSPEC" },
{ ".FUNSMRY" , ".UNSMRY" }, { ".FUNRST" , ".UNRST" }, { ".FRFT" , ".RFT" }};
2019-03-28 15:03:20 +01:00
if ( formattedOutput ) {
2019-09-16 15:02:21 +02:00
auto search = to_formatted . find ( extension );
if ( search != to_formatted . end ()){
resFile = rootN + search -> second ;
} else if ( extension . substr ( 1 , 1 ) == "X" ){
2019-07-18 17:55:34 +02:00
resFile = rootN + ".F" + extension . substr ( 2 );
} else if ( extension . substr ( 1 , 1 ) == "S" ){
resFile = rootN + ".A" + extension . substr ( 2 );
} else {
2019-09-16 15:02:21 +02:00
std :: cout << " \n !ERROR, unknown file type for input file '" << rootN + extension << "' \n " << std :: endl ;
exit ( 1 );
2019-07-18 17:55:34 +02:00
}
2019-03-28 15:03:20 +01:00
} else {
2019-09-16 15:02:21 +02:00
auto search = to_binary . find ( extension );
if ( search != to_binary . end ()){
resFile = rootN + search -> second ;
} else if ( extension . substr ( 1 , 1 ) == "F" ){
2019-07-18 17:55:34 +02:00
resFile = rootN + ".X" + extension . substr ( 2 );
} else if ( extension . substr ( 1 , 1 ) == "A" ){
resFile = rootN + ".S" + extension . substr ( 2 );
} else {
2019-09-16 15:02:21 +02:00
std :: cout << " \n !ERROR, unknown file type for input file '" << rootN + extension << "' \n " << std :: endl ;
exit ( 1 );
2019-07-18 17:55:34 +02:00
}
2019-03-28 15:03:20 +01:00
}
2019-07-18 17:55:34 +02:00
std :: cout << " \033 [1;31m" << " \n converting " << argv [ argOffset ] << " -> " << resFile << " \033 [0m \n " << std :: endl ;
2019-03-28 15:03:20 +01:00
EclOutput outFile ( resFile , formattedOutput );
2019-07-18 17:55:34 +02:00
if ( specificReportStepNumber ) {
2019-03-28 15:03:20 +01:00
2019-07-18 17:55:34 +02:00
if ( extension != ".UNRST" ) {
std :: cout << " \n !ERROR, option -r only can only be used with unified restart files (*.UNRST) " << std :: endl ;
exit ( 1 );
}
2019-03-28 15:03:20 +01:00
2019-07-18 17:55:34 +02:00
ERst rst1 ( filename );
if ( ! rst1 . hasReportStepNumber ( reportStepNumber )) {
std :: cout << " \n !ERROR, selected unified restart file doesn't have report step number " << reportStepNumber << " \n " << std :: endl ;
2019-03-28 15:03:20 +01:00
exit ( 1 );
}
2019-07-18 17:55:34 +02:00
rst1 . loadReportStepNumber ( reportStepNumber );
auto arrayList = rst1 . listOfRstArrays ( reportStepNumber );
writeArrayList ( arrayList , rst1 , reportStepNumber , outFile );
} else {
file1 . loadData ();
auto arrayList = file1 . getList ();
writeArrayList ( arrayList , file1 , outFile );
2019-03-28 15:03:20 +01:00
}
2019-09-16 15:02:21 +02:00
auto end = std :: chrono :: system_clock :: now ();
std :: chrono :: duration < double > elapsed_seconds = end - start ;
2019-07-18 17:55:34 +02:00
2019-09-16 15:02:21 +02:00
std :: cout << "runtime : " << argv [ argOffset ] << ": " << elapsed_seconds . count () << " seconds \n " << std :: endl ;
2019-03-28 15:03:20 +01:00
return 0 ;
}