![]() |
Gowdy solver
|
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 };