![]() |
Gowdy solver
|
00001 /** 00002 * @file cubicSpline.h 00003 * @brief The natural cubic spline of degree 3 with continuity C2. 00004 * @author Mikica Kocic 00005 * @copyright GNU General Public License (GPLv3). 00006 */ 00007 00008 ///////////////////////////////////////////////////////////////////////////////////////// 00009 /** @defgroup g11 Numerical Methods */ 00010 ///////////////////////////////////////////////////////////////////////////////////////// 00011 /*@{*/ 00012 /** CubicSpline encapsulates the natural cubic spline of degree 3 with continuity C2. 00013 * (Natural means that the second derivatives of the spline polynomials are set 00014 * equal to zero at the endpoints of the interval of interpolation.) 00015 * 00016 * Input: a set of N = k+1 coordinates. 00017 * Output: a spline as a set of polynomial pieces. 00018 * 00019 * @see <a href="https://en.wikipedia.org/wiki/Spline_(mathematics)"> 00020 * Algorithm for computing natural cubic splines </a> 00021 * @see <a href="http://mathfaculty.fullerton.edu/mathews/n2003/CubicSplinesMod.html"> 00022 * Cubic splines module </a> 00023 * @see Mathmatica notebook `Natural cubic spline.nb` used for tests 00024 */ 00025 class CubicSpline 00026 { 00027 Int k; //!< Dimension: k+1 points 00028 VecReal x; //!< The intervals: x[0]..x[1], x[1]..x[2], ... 00029 VecReal a, b, c, d; //!< The polynomial coefficients, i = 0,...,k-1 00030 00031 VecReal h, alp, l, z, mu; // Temporary 00032 00033 public: 00034 00035 /** Constructor. Only allocates memory for the arrays. 00036 */ 00037 CubicSpline( Int N ) 00038 : k( N - 1 ) 00039 , x(N), a(N), b(N), c(N), d(N) 00040 , h(N), alp(N), l(N), z(N), mu(N) 00041 {} 00042 00043 /** Calculates the spline based on the endpoints of the interval of interpolation. 00044 */ 00045 void initialize( Real pts[][2] ) 00046 { 00047 for( Int i = 0; i < k + 1; ++i ) { 00048 x[i] = pts[i][0]; 00049 a[i] = pts[i][1]; 00050 } 00051 00052 // Calculate the differences 00053 00054 for( Int i = 0; i < k; ++i ) { 00055 h[i] = x[i+1] - x[i]; 00056 } 00057 00058 for( Int i = 1; i < k; ++i ) { 00059 alp[i] = 3 * ( a[i+1] - a[i] ) / h[i] - 3 * ( a[i] - a[i-1] ) / h[i-1]; 00060 } 00061 00062 // Solve the tridiagonal linear equation (Crout's factorization) 00063 00064 l[0] = 1; mu[0] = z[0] = 0; 00065 00066 for( Int i = 1; i < k; ++i ) { 00067 l[i] = 2 * ( x[i+1] - x[i-1] ) - h[i-1] * mu[i-1]; 00068 mu[i] = h[i] / l[i]; 00069 z[i] = ( alp[i] - h[i-1] * z[i-1] ) / l[i]; 00070 } 00071 00072 // Compute the polynomial coefficients 00073 00074 l[k] = 1; z[k] = c[k] = 0; 00075 00076 for( Int j = k - 1; j >= 0; --j ) { 00077 c[j] = z[j] - mu[j] * c[j+1]; 00078 b[j] = ( a[j+1] - a[j] ) / h[j] - h[j] * ( c[j+1] + 2 * c[j] ) / 3; 00079 d[j] = ( c[j+1] - c[j] ) / ( 3 * h[j] ); 00080 } 00081 } 00082 00083 /** Dumps the polynomial coefficients 00084 */ 00085 void dump () 00086 { 00087 std::cout << "Polynomial coefficients:" << std::endl << std::endl; 00088 00089 for( Int i = 0; i < k; ++i ) { 00090 std::cout << a[i] << "\t" << b[i] << "\t" << c[i] << "\t" << d[i] 00091 << " x-range " << x[i] << " .. " << x[i+1] << std::endl; 00092 } 00093 } 00094 /** Returns a value approximated by the cubic splice. 00095 */ 00096 Real operator()( Real v ) 00097 { 00098 // Find the polynomial. The polynomial index i goes from 0 to k-1. 00099 // The interval where the polynomial is valid is x[i-1]..x[i] 00100 // 00101 Int i = 0; 00102 while( i < k - 1 && v >= x[i+1] ) { 00103 ++i; 00104 } 00105 00106 // The interval has not been found. Use the last polynomial for approximation. 00107 if ( i >= k - 1 ) { 00108 i = k - 1; 00109 } 00110 00111 v -= x[i]; // Subtract the x-value from the reference value 00112 00113 return a[i] + v * ( b[i] + v * ( c[i] + v * d[i] ) ); 00114 } 00115 }; 00116 00117 void CubicSpline_sanityCheck () 00118 { 00119 Real pts[5][2] = 00120 { 00121 {0.005, 4.892186615295462}, {0.045, 44.02967953765916}, 00122 {0.105, 102.7359189212047 }, {0.145, 40.74442799816186}, 00123 {0.195, 10.719645882407347} 00124 }; 00125 00126 CubicSpline ncs( 5 ); 00127 ncs.initialize( pts ); 00128 ncs.dump (); 00129 00130 for( Real x = 0; x < 0.2001; x += 0.01 ) { 00131 std::cout << x << "\t" << ncs( x ) << std::endl; 00132 } 00133 } 00134 /*@}*/ 00135 /////////////////////////////////////////////////////////////////////////////////////////