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-15 10:27:50 +01:00
using EclEntry = std : : tuple < std : : string , eclArrType , long int > ;
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 ;
}