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