![]() |
Gowdy solver
|
00001 /** 00002 * @file gowdy-solver.cpp 00003 * @brief IVP solver for Gowdy spacetimes that uses bimetric-solver framework. 00004 * @author Mikica Kocic 00005 * @copyright GNU General Public License (GPLv3). 00006 * 00007 * @mainpage IVP solver for Gowdy spacetimes 00008 * 00009 * The code implements a pedagogical IVP solver for Gowdy spacetimes that uses 00010 * <a href="http://qft.nu/_private_bim-ss">bimetric-solver framework</a> 00011 * @cite BimSolver:2018. <p> 00012 * The equations of motion come from @cite Garfinkle:2004tu. 00013 * 00014 * @par Main file: 00015 * gowdy-solver.cpp 00016 * 00017 * @version 0.3, inception 2018-04-19, last modified **2018-08-16 22:54** 00018 * @author Mikica Kocic 00019 * 00020 * @par References 00021 * @copydoc citelist 00022 */ 00023 00024 #include <iostream> 00025 #include <iomanip> 00026 #include <fstream> 00027 #include <string> 00028 #include <cmath> 00029 #include <cstdio> 00030 #include <chrono> 00031 00032 #include "numMethods.h" // The implemented numerical modules 00033 #include "sys/paramsHolder.h" // Holds 'key=value' pairs got from the parameter file 00034 #include "sys/slog.h" // For writing both to cerr and cout simultaneously 00035 #include "sys/trackUsedTime.h" // Keep track of the elapsed time of the application 00036 #include "sys/hpc.h" // High-Performance Computing (HPC) support 00037 00038 ///////////////////////////////////////////////////////////////////////////////////////// 00039 // Declare our grid functions (their number must be known to the grid-driver beforehand) 00040 00041 #include "grid/gridFunctions.h" 00042 00043 /** Definitions of grid functions are here. 00044 */ 00045 namespace fld 00046 { 00047 /** Identifiers of all known grid functions (the variables or fields on a grid). 00048 */ 00049 enum Index 00050 { 00051 P = GFCNT, Q, R, S, L, //!< Evolved variables 00052 P_t, Q_t, R_t, S_t, L_t, //!< Time derivatives of the evolved variables 00053 C, //!< Constraint violation 00054 gowdyLast //!< The total number of grid functions 00055 }; 00056 #undef GFCNT // Clear the old number of grid functions then 00057 #define GFCNT fld::gowdyLast //!< Set the number of grid functions on a grid point 00058 00059 /** The fields that will be read from the initial data. 00060 */ 00061 static const std::vector<Int> gowdyInput = { 00062 P, Q, R, L, S 00063 }; 00064 00065 /** The fields which will be written to the output. 00066 */ 00067 static const std::vector<Int> gowdyOutput = { 00068 P, Q, R, L, S, 00069 C 00070 }; 00071 00072 /** The grid functions that are evolved in time. 00073 */ 00074 static const std::vector<EvolvedBy> gowdyEvolved = { 00075 { P, P_t }, { Q, Q_t }, { R, R_t }, 00076 { S, S_t }, { L, L_t } 00077 }; 00078 } 00079 00080 ///////////////////////////////////////////////////////////////////////////////////////// 00081 // The grid-driver and other modules 00082 00083 #include "grid/gridPoint.h" 00084 #include "grid/gridDriver.h" 00085 #include "grid/gridInitialData.h" 00086 #include "grid/gridOutput.h" 00087 #include "grid/integrator.h" 00088 00089 ///////////////////////////////////////////////////////////////////////////////////////// 00090 00091 /** GowdyEvolve encapsulates the IVP solver for Gowdy spacetime. 00092 */ 00093 class GowdyEvolve 00094 : GridUser, public IntegFace 00095 { 00096 ///////////////////////////////////////////////////////////////////////////////////// 00097 // Fields (grid functions) 00098 ///////////////////////////////////////////////////////////////////////////////////// 00099 00100 /** `emitField` is a macro that emits a method encapsulating 00101 * a grid function that access data in a grid at a point given by 00102 * `m` (discretized t-coordinate) and `n` (discretized r-coordinate). 00103 * For example, `emitField(r)` defines `r(m,n)`. 00104 */ 00105 #define emitField(gf) \ 00106 inline Real& gf( Int m, Int n ) { return grid[m][n][fld::gf]; } 00107 00108 emitField(t) 00109 emitField(r) 00110 emitField(P) emitField(P_t) emitDerivative_r( P ) emitDerivative_rr( P ) 00111 emitField(Q) emitField(Q_t) emitDerivative_r( Q ) emitDerivative_rr( Q ) 00112 emitField(R) emitField(R_t) emitDerivative_r( R ) emitDerivative_rr( R ) 00113 emitField(S) emitField(S_t) emitDerivative_r( S ) emitDerivative_rr( S ) 00114 emitField(L) emitField(L_t) emitDerivative_r( L ) emitDerivative_rr( L ) 00115 emitField(C) 00116 00117 ///////////////////////////////////////////////////////////////////////////////////// 00118 // RHS of the time derivatives (equations of motion) 00119 ///////////////////////////////////////////////////////////////////////////////////// 00120 00121 Real eq_P_t( Int m, Int n ) { 00122 return R(m, n); 00123 } 00124 00125 Real eq_Q_t( Int m, Int n ) { 00126 return S(m, n); 00127 } 00128 00129 Real eq_R_t( Int m, Int n ) { 00130 return P_rr(m, n) / exp(2 * t(m,n)) 00131 - exp(2 * (P(m, n) - t(m,n))) * pow2(Q_r(m, n)) 00132 + exp(2 * P(m, n)) * pow2(S(m, n)); 00133 } 00134 00135 Real eq_S_t( Int m, Int n ) { 00136 return Q_rr(m, n) / exp(2 * t(m,n)) 00137 + 2 * P_r(m, n) * Q_r(m, n) / exp(2 * t(m,n)) 00138 - 2 * R(m, n) * S(m, n); 00139 } 00140 00141 Real eq_L_t( Int m, Int n ) { 00142 return -pow2(P_r(m, n)) / exp(2 * t(m,n)) 00143 - exp(2 * (P(m, n) - t(m,n))) * pow2(Q_r(m, n)) 00144 - exp(2 * P(m, n)) * pow2(S(m, n)) 00145 - pow2(R(m, n)); 00146 } 00147 00148 // Constraints violation 00149 00150 Real eq_C_violation( Int m, Int n ) { 00151 return L_r(m, n) + 2 * P_r(m, n) * R(m, n) 00152 + 2 * exp(2 * P(m, n)) * Q_r(m, n) * S(m, n); 00153 } 00154 00155 ///////////////////////////////////////////////////////////////////////////////////// 00156 // MoLInterface implementation 00157 ///////////////////////////////////////////////////////////////////////////////////// 00158 00159 /** Calculates the dependent variables from the prime state variables 00160 * which are needed for the integration. 00161 */ 00162 virtual void integStep_Prepare( Int m ) 00163 {} // Unimplemented 00164 00165 /** Calculate the right-hand side for time evolution. 00166 */ 00167 virtual void integStep_CalcEvolutionRHS( Int m ) 00168 { 00169 OMP_parallel_for( Int n = nGhost; n < nGhost + nLen; ++n ) 00170 { 00171 P_t (m,n) = eq_P_t (m,n); 00172 Q_t (m,n) = eq_Q_t (m,n); 00173 R_t (m,n) = eq_R_t (m,n); 00174 S_t (m,n) = eq_S_t (m,n); 00175 L_t (m,n) = eq_L_t (m,n); 00176 00177 // Calculate the constraint violation 00178 C(m,n) = eq_C_violation(m,n); 00179 } 00180 } 00181 00182 /** At each checkpoint, outputs the grid row every mSkip steps, also 00183 * reporting the integration time and checking for eventual NaNs. 00184 */ 00185 virtual bool integStep_CheckForNaNs( Int m, Int nFrom, Int nTo ) 00186 { 00187 for( Int n = nFrom; n < nTo; ++n ) { 00188 if ( std::isnan( GF( fld::P, m, nGhost + n ) ) ) { 00189 return true; 00190 } 00191 } 00192 return false; 00193 } 00194 00195 virtual void integStep_Finalize( Int mNext, Int mPrev ) 00196 {} // Unimplemented IntegFace methods 00197 00198 /** Apply the periodic boundary conditions on left. 00199 */ 00200 virtual void applyLeftBoundaryCondition( Int m ) 00201 { 00202 for( Int i = 0; i < nGhost; ++i ) 00203 { 00204 t(m,i) = t(m,nLen+i); 00205 r(m,i) = r(m,nLen+i); 00206 P(m,i) = P(m,nLen+i); 00207 Q(m,i) = Q(m,nLen+i); 00208 R(m,i) = R(m,nLen+i); 00209 S(m,i) = S(m,nLen+i); 00210 L(m,i) = L(m,nLen+i); 00211 } 00212 } 00213 00214 /** Apply the periodic boundary conditions on right. 00215 */ 00216 virtual void applyRightBoundaryCondition( Int m ) 00217 { 00218 for( Int i = 0; i < nGhost; ++i ) 00219 { 00220 t(m,nGhost+nLen+i) = t(m,nGhost+i); 00221 r(m,nGhost+nLen+i) = r(m,nGhost+i); 00222 P(m,nGhost+nLen+i) = P(m,nGhost+i); 00223 Q(m,nGhost+nLen+i) = Q(m,nGhost+i); 00224 R(m,nGhost+nLen+i) = R(m,nGhost+i); 00225 S(m,nGhost+nLen+i) = S(m,nGhost+i); 00226 L(m,nGhost+nLen+i) = L(m,nGhost+i); 00227 } 00228 } 00229 00230 public: 00231 00232 /** The initial data is prepared by hand (thus not loaded from any file). 00233 */ 00234 bool setupInitialData () 00235 { 00236 static const double PI = acos(-1.0); 00237 00238 for( Int n = 0; n < nLen; ++n ) 00239 { 00240 double x = 2.0 * PI * n / nLen; 00241 r(0,nGhost+n) = x; 00242 P(0,nGhost+n) = 0; 00243 Q(0,nGhost+n) = cosl(x); 00244 R(0,nGhost+n) = 5 * cosl(x); 00245 S(0,nGhost+n) = 0; 00246 L(0,nGhost+n) = 0; 00247 } 00248 00249 return true; 00250 } 00251 00252 /** Creates and configures the Gowdy solver from the given parameters. 00253 */ 00254 GowdyEvolve( Parameters& params, UniformGrid& ug, MoLIntegrator& integ ) 00255 : GridUser( ug ) 00256 { 00257 slog << "Gowdy Solver:" << std::endl << std::endl; 00258 00259 // Sign up for the integration 00260 // 00261 integ.addToEvolution( this ); 00262 00263 // Add our grid functions to the evolution 00264 // 00265 integ.keepEvolved( fld::gowdyEvolved ); // Evolved 00266 } 00267 }; 00268 00269 ///////////////////////////////////////////////////////////////////////////////////////// 00270 // The main entry point of `gowdy-solver`. 00271 // 00272 int main( int argc, char* argv[] ) 00273 { 00274 TrackUsedTime timer; 00275 00276 // Read the configuration 00277 // 00278 Parameters params( argc >= 2 ? argv[1] : "config.ini" ); 00279 00280 // Create the grid driver 00281 // 00282 UniformGrid ugrid( params ); 00283 00284 // Create the output sync 00285 // 00286 GridOutputWriter output ( params, ugrid ); 00287 output.gridFunctions( fld::gowdyOutput ); 00288 if ( ! output.open () ) return -1; 00289 00290 // Evolve the equations from the manually setup ID 00291 // 00292 MoLIntegrator integ( params, ugrid, output ); 00293 GowdyEvolve gowdy( params, ugrid, integ ); 00294 gowdy.setupInitialData (); 00295 00296 return integ.evolveEquations () ? 0 : -1; 00297 }