Gowdy solver
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
grid/gridOutput.h
Go to the documentation of this file.
00001 /**
00002  *  @file      gridOutput.h
00003  *  @brief     Writes checkpoints from the grid to the output data file.
00004  *  @author    Mikica Kocic
00005  *  @copyright GNU General Public License (GPLv3).
00006  */
00007 
00008 #include <deque>
00009 
00010 /** Writes checkpoints from the grid to the output data file.
00011  */
00012 class GridOutputWriter
00013 {
00014     UniformGrid* gridDriver;     //! The grid-driver
00015     bool  binaryFormat;          //!< Write binary data to output file.
00016     FILE* outf;                  //!< Output stream for the results.
00017     std::string fileName;        //!< Output filename
00018     std::string prefixFileName;  //!< Filename that is copied out (reversed) before start
00019     std::vector<Int> output;     //!< List of grid functions to write out
00020 
00021     struct skipInfo { Real t; Int mSkip; Real delta_t; };
00022     std::deque<skipInfo> skipSetter;  //!< Apply new "skips" at the given time point
00023 
00024     Int mSkip;     //!< Output every `mSkip` rows
00025     Int nOut;      //!< Number of grid points to get in the output
00026     Int nSkip;     //!< Output every `nSkip` points
00027     Int chunkSize; //!< Size (in bytes) of the output chunk
00028 
00029     /** Writes the results for a particular grid row to output.
00030      */
00031     void write( Int m, Int nFrom, Int nTo, Int nSkip = 1 )
00032     {
00033         GridPoint* row = gridDriver->get_grid() [m];
00034         for( Int n = nFrom; n < nTo; n += nSkip ) {
00035             IORecord( row[n] ).write( outf, binaryFormat, output );
00036         }
00037     }
00038 
00039 public:
00040 
00041     Int get_mSkip () const { return mSkip; }
00042     Int get_nOut  () const { return nOut;  }
00043     Int get_nSkip () const { return nSkip; }
00044 
00045     /** Retrieve the size (in bytes) of the output record.
00046      */
00047     Int recordSizeInBytes () const { return chunkSize; }
00048 
00049     /** Constructs the output writer as specified in the parameter file.
00050      */
00051     GridOutputWriter( Parameters& params, UniformGrid& ug )
00052         : gridDriver( &ug ), binaryFormat(false), outf(NULL)
00053     {
00054         output.reserve( 100 );
00055         output.push_back( fld::t );
00056         output.push_back( fld::r );
00057 
00058         params.get( "output.file",   fileName, "stdout" );
00059         params.get( "output.binary", binaryFormat, true );
00060         params.get( "output.prefix", prefixFileName, "" );
00061 
00062         slog << "Output Writer:" << std::endl << std::endl
00063              << "    file = " << fileName << ",  binary = " << binaryFormat
00064              << std::endl << std::endl;
00065 
00066         params.get( "output.nOut",  nOut,  10 );
00067         params.get( "output.nSkip", nSkip,  1 );
00068         params.get( "output.mSkip", mSkip,  1 );
00069 
00070         chunkSize = 0; // still not defined
00071 
00072         slog << "Output Filter:" << std::endl << std::endl
00073              << "    nOut = " << nOut << ",  nSkip = " << nSkip << ",  mSkip = " << mSkip
00074              << std::endl << std::endl;
00075 
00076         // Get skip setters
00077         //
00078         for( int i = 1; i < 10; ++i )
00079         {
00080             std::string tag = "at" + std::to_string( i );
00081             skipInfo info;
00082             params.get( tag + ".t",       info.t,       NAN );
00083             params.get( tag + ".mSkip",   info.mSkip,   1   );
00084             params.get( tag + ".delta_t", info.delta_t, NAN );
00085             if ( ! std::isnan( info.t ) ) {
00086                 skipSetter.push_back( info );
00087             }
00088         }
00089 
00090         if( skipSetter.size() > 0 )
00091         {
00092             slog << "Skip Setter:" << std::endl << std::endl;
00093             for( auto i: skipSetter ) {
00094                 slog << "    t = " << i.t << ", mSkip = " << i.mSkip
00095                     << ", delta_t = " << i.delta_t << std::endl;
00096             }
00097             slog << std::endl;
00098         }
00099     }
00100 
00101     ~GridOutputWriter ()
00102     {
00103         close ();
00104     }
00105 
00106     /** The given grid functions will be written to the output.
00107      */
00108     void gridFunctions( const std::vector<Int>& gfs )
00109     {
00110         output.insert( output.end(), gfs.begin(), gfs.end() );
00111     }
00112 
00113     /** Opens output data file for storing the results.
00114      */
00115     bool open ()
00116     {
00117         GridPoint** grid = gridDriver->get_grid ();
00118         Int nGhost = gridDriver->get_nGhost();
00119 
00120         chunkSize = ( 2 * nGhost + nOut / nSkip ) * output.size() * sizeof(Real);
00121 
00122         if( fileName == "stdout" ) {
00123             binaryFormat = false;
00124             outf = stdout;
00125             return false;
00126         }
00127 
00128         if ( gridDriver->mpiSize() > 1 ) {
00129             outf = fopen( ( std::to_string( gridDriver->mpiRank() + 100 )
00130                            + "-" + fileName ).c_str(), binaryFormat ? "wb+" : "w+" );
00131         }
00132         else {
00133             outf = fopen( fileName.c_str(), binaryFormat ? "wb+" : "w+" );
00134         }
00135 
00136         if( binaryFormat && prefixFileName != "" )
00137         {
00138             std::ifstream pref( prefixFileName, std::ios::in | std::ios::binary );
00139             if( pref )
00140             {
00141                 slog << "*** Appending the reversed-t: " << prefixFileName << std::endl;
00142 
00143                 pref.seekg( 0, std::ios::end );  // Go to end of file
00144                 auto len = pref.tellg ();   // Get the length of file (in bytes)
00145 
00146                 if ( ( len % chunkSize ) != 0 ) {
00147                     std::cerr << "Error: Invalid grid alignment." << std::endl;
00148                     return false;
00149                 }
00150 
00151                 // While len > 0 means skip the last record (at t_0)
00152                 for( len -= chunkSize; len > 0; len -= chunkSize )
00153                 {
00154                     pref.seekg( len, std::ios::beg );
00155                     pref.read( (char*)&grid[0][0], chunkSize );
00156                     fwrite( &grid[0][0], chunkSize, 1, outf );
00157                 }
00158                 pref.close ();
00159             }
00160         }
00161 
00162         return true;
00163     }
00164 
00165     /** Closes the output file.
00166      */
00167     void close ()
00168     {
00169         if( outf != NULL ) {
00170             fclose( outf );
00171             outf = NULL;
00172         }
00173     }
00174 
00175     void write( Int m, Real cur_t, Real& delta_t )
00176     {
00177         Int nLen   = gridDriver->get_nLen ();
00178         Int nGhost = gridDriver->get_nGhost ();
00179         write( m, 0, nGhost );
00180         write( m, nGhost, nGhost + (nLen < nOut ? nLen : nOut), nSkip );
00181         write( m, nGhost + nLen, nGhost + nLen + nGhost );
00182 
00183         if( skipSetter.size() > 0 && cur_t >= skipSetter.front().t )
00184         {
00185             mSkip = skipSetter.front().mSkip;
00186             Real new_dt = skipSetter.front().delta_t;
00187             if( ! std::isnan( new_dt ) )
00188             {
00189                 delta_t = new_dt;
00190                 slog << std::endl << std::endl << "*** at t = " << cur_t
00191                      << " new mSkip = " << mSkip << ", delta_t = " << delta_t
00192                      << std::endl << std::endl;
00193             }
00194             else
00195             {
00196                 slog << std::endl << std::endl << "*** at t = " << cur_t
00197                      << " new mSkip = " << mSkip << std::endl << std::endl;
00198             }
00199             skipSetter.pop_front ();
00200         }
00201     }
00202 };