Gowdy solver
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
numMethods/finiteDifferences.h
Go to the documentation of this file.
00001 /**
00002  *  @file      finiteDifferences.h
00003  *  @brief     Macros to emit various finite differences (e.g., for approximating
00004                derivatives, or for the Keisser-Oliger term).
00005  *  @author    Mikica Kocic
00006  *  @copyright GNU General Public License (GPLv3).
00007  */
00008 
00009 /////////////////////////////////////////////////////////////////////////////////////////
00010 /** @defgroup g11 Numerical Methods                                                    */
00011 /////////////////////////////////////////////////////////////////////////////////////////
00012                                                                                    /*@{*/
00013 #ifndef CFDS_ORDER
00014     /** The order of the centered final difference scheme.
00015      */
00016     #define CFDS_ORDER 4
00017 #endif
00018 
00019 /// @todo A run-time CFDS_ORDER?
00020 
00021 /////////////////////////////////////////////////////////////////////////////////////////
00022 // Macros to emit the spatial derivatives (centered in space)
00023 //
00024 // Convention: if f() denotes a function, then f_r() denotes a spatial derivative,
00025 // f_t() denotes a time derivative, f_rr() denotes a Real spatial derivative.
00026 //
00027 // @note The execution of the code where the spatial derivatives are
00028 // converted to differences in Mathematica (and then simplified) is around two times
00029 // faster than the code where the derivatives use the f_r and f_rr inline functions.
00030 
00031 #if CFDS_ORDER == 2 // Second order central finite difference scheme
00032 
00033     /** `emitDerivative_r` is a macro that emits a method for the first derivative
00034      *  in `r` using the 2nd order central finite difference scheme.
00035      */
00036     #define emitDerivative_r( f ) inline Real f##_r( Int m, Int n ) \
00037         { return 0.5 * ( f(m,n+1) - f(m,n-1) ) * inv_delta_r; }
00038 
00039     /** `emitDerivative_rr` is a macro that emits a method for the second derivative
00040      *  in `r` using the 2nd order central finite difference scheme.
00041      */
00042     #define emitDerivative_rr( f ) inline Real f##_rr( Int m, Int n ) \
00043         { return ( f(m,n+1) - 2 * f(m,n) + f(m,n-1) ) * inv_delta_rr; }
00044 
00045 #elif CFDS_ORDER == 4 // Fourth order central finite difference scheme
00046 
00047     /** `emitDerivative_r` is a macro that emits a method for the first derivative
00048      *  in `r` using the 4th order central finite difference scheme.
00049      */
00050     #define emitDerivative_r( f ) inline Real f##_r( Int m, Int n ) \
00051         { return ( - 1./12. * f(m,n+2) + 2./3.  * f(m,n+1) \
00052                    - 2./3.  * f(m,n-1) + 1./12. * f(m,n-2) ) * inv_delta_r; }
00053 
00054     /** `emitDerivative_rr` is a macro that emits a method for the second derivative
00055      *  in `r` using the 4th order central finite difference scheme.
00056      */
00057     #define emitDerivative_rr( f ) inline Real f##_rr( Int m, Int n ) \
00058         { return ( - 1./12.* f(m,n+2) + 4./3.  * f(m,n+1) - 5./2. * f(m,n) \
00059                    + 4./3. * f(m,n-1) - 1./12. * f(m,n-2) ) * inv_delta_rr; }
00060 
00061 #elif CFDS_ORDER == 6 // Sixth order central finite difference scheme
00062 
00063     /** `emitDerivative_r` is a macro that emits a method for the first derivative
00064      *  in `r` using the 6th order central finite difference scheme.
00065      */
00066     #define emitDerivative_r( f ) inline Real f##_r( Int m, Int n ) \
00067         { return ( 1./60. * f(m,n+3) - 9./60. * f(m,n+2) + 45./60. * f(m,n+1) \
00068            - 45./60. * f(m,n-1) + 9./60. * f(m,n-2) - 1./60. * f(m,n-3) ) * inv_delta_r; }
00069 
00070     /** `emitDerivative_rr` is a macro that emits a method for the second derivative
00071      *  in `r` using the 6th order central finite difference scheme.
00072      */
00073     #define emitDerivative_rr( f ) inline Real f##_rr( Int m, Int n ) \
00074         { return ( 2./180. * f(m,n+3) - 27./180. * f(m,n+2) + 270./180. * f(m,n+1) \
00075                   - 490./180. * f(m,n) + 270./180. * f(m,n-1) - 27./180. * f(m,n-2) \
00076                   + 2./180. * f(m,n-3) ) * inv_delta_rr; }
00077 
00078 #else
00079 
00080     #error "CFDS_ORDER must be either 2, 4, or 6"
00081 
00082 #endif
00083 
00084 /////////////////////////////////////////////////////////////////////////////////////////
00085 
00086 /** extrapolate_R is an optimized version of 4th order in accuracy extrapolation
00087  *  using the 4th order Taylor expansion.
00088  */
00089 #define extrapolate_R(f,m,n)  f(m,n) = \
00090     -   7./48. * f(m,n-8) +  209./144. * f(m,n-7) - 103./16. * f(m,n-6) \
00091     + 793./48. * f(m,n-5) - 3835./144. * f(m,n-4) + 439./16. * f(m,n-3) \
00092     - 281./16. * f(m,n-2) +  917./144. * f(m,n-1)
00093 
00094 #define extrapolate_RGF(f,m,n)  GF(f,m,n) = \
00095     -   7./48. * GF(f,m,n-8) +  209./144. * GF(f,m,n-7) - 103./16. * GF(f,m,n-6) \
00096     + 793./48. * GF(f,m,n-5) - 3835./144. * GF(f,m,n-4) + 439./16. * GF(f,m,n-3) \
00097     - 281./16. * GF(f,m,n-2) +  917./144. * GF(f,m,n-1)
00098 
00099 /** extrapolate_D is a linear extrapolation of the 4th order in accuracy
00100  *  (used for derivatives).
00101  */
00102 #define extrapolate_D(f,m,n)  f(m,n) = \
00103     1./4. * f(m,n-5) - 4./3. * f(m,n-4) + 3 * f(m,n-3) - 4 * f(m,n-2) + 37./12. * f(m,n-1)
00104 
00105 #define extrapolate_DGF(f,m,n)  GF(f,m,n) = \
00106     1./4. * GF(f,m,n-5) - 4./3. * GF(f,m,n-4) + 3 * GF(f,m,n-3) - 4 * GF(f,m,n-2) + 37./12. * GF(f,m,n-1)
00107 
00108 /////////////////////////////////////////////////////////////////////////////////////////
00109     /** `KreissOligerTerm` is a macro that gives a Kreiss-Oliger dissipation term.
00110      *
00111      *  Coefficients d_k at gridpoints for the centred finite-difference discretisation
00112      *  of the derivative `partial_x^{2N}` (of the dissipative Kreiss-Oliger operator).
00113      *  <pre>
00114      *      ---------------------------------------------
00115      *       N  -4  -3   -2   -1    0   +1   +2  +3  +4
00116      *      ---------------------------------------------
00117      *       1                +1   -2   +1
00118      *       2           -1   +4   -6   +4   -1
00119      *       3      +1   -6  +15  -20  +15   -6  +1
00120      *       4  -1  +8  -28  +56  -70  +56  -28  +8  -1
00121      *      ---------------------------------------------  </pre>
00122      *
00123      *  Here, `N >= 1` is an integer and `D_h^{2N}` is a centered difference operator
00124      *  approximating a partial spatial derivative of order `2N`, e.g.,
00125      *  a second- (`N = 1`) or fourth-order (`N = 2`) spatial derivative.
00126      *
00127      *  To be subtracted from the evolution equation:
00128      *
00129      *      `epsilon (-1)^N  delta_t {delta_x}^{2N-1}  D_h^{2N}`
00130      *
00131      *  where:
00132      *
00133      *      `D_h^{2N} = (2 delta_x)^{-2N} * ( sum_k d_k f[n+k] )`
00134      *
00135      *  For `N = 2`, subtract from the evolution equation `u_t`:
00136      *
00137      *      `dissip(f,dt) = epsilon 2^{-2N} * dt/delta_x * ( sum_k d_k f[n+k] )`
00138      */
00139 #if CFDS_ORDER == 2
00140         #define KreissOligerTerm(f,dt) \
00141             ( - ( f(m,n-1) - 2* f(m,n) + f(m,n+1) ) * dissip_delta_r * (dt) )
00142         #define KreissOligerTermGF(f,dt) \
00143             ( - ( GF(f,m,n-1) - 2* GF(f,m,n) + GF(f,m,n+1) ) * dissip_delta_r * (dt) )
00144 #else
00145     #if CFDS_ORDER == 4
00146         #define KreissOligerTerm(f,dt) \
00147             ( ( f(m,n-2) - 4* f(m,n-1) + 6* f(m,n) - 4* f(m,n+1) + f(m,n+2) ) \
00148                * dissip_delta_r * (dt) )
00149         #define KreissOligerTermGF(f,dt) \
00150             ( ( GF(f,m,n-2) - 4* GF(f,m,n-1) + 6* GF(f,m,n) - 4* GF(f,m,n+1) + GF(f,m,n+2) ) \
00151                * dissip_delta_r * (dt) )
00152     #else
00153         #define KreissOligerTerm(f,dt) \
00154             ( - ( f(m,n-3) - 6* f(m,n-2) + 15* f(m,n-1) - 20* f(m,n) + 15* f(m,n+1) \
00155                - 6* f(m,n+2) + f(m,n+3) ) * dissip_delta_r * (dt) )
00156         #define KreissOligerTermGF(f,dt) \
00157             ( - ( GF(f,m,n-3) - 6* GF(f,m,n-2) + 15* GF(f,m,n-1) - 20* GF(f,m,n) + 15* GF(f,m,n+1) \
00158                - 6* GF(f,m,n+2) + GF(f,m,n+3) ) * dissip_delta_r * (dt) )
00159     #endif
00160 #endif
00161                                                                                    /*@}*/
00162 /////////////////////////////////////////////////////////////////////////////////////////