Gowdy solver
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
gowdy-solver.cpp
Go to the documentation of this file.
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 }