$treeview $search $mathjax
|
Palabos
Version 1.1
$projectbrief
|
$projectbrief
|
$searchbox |
00001 /* This file is part of the Palabos library. 00002 * 00003 * Copyright (C) 2011 FlowKit Sarl 00004 * Avenue de Chailly 23 00005 * 1012 Lausanne, Switzerland 00006 * E-mail contact: contact@flowkit.com 00007 * 00008 * The most recent release of Palabos can be downloaded at 00009 * <http://www.palabos.org/> 00010 * 00011 * The library Palabos is free software: you can redistribute it and/or 00012 * modify it under the terms of the GNU Affero General Public License as 00013 * published by the Free Software Foundation, either version 3 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * The library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Affero General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Affero General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 #ifndef SPLINE_HH 00026 #define SPLINE_HH 00027 00028 #include "core/runTimeDiagnostics.h" 00029 #include "core/util.h" 00030 #include "spline.h" 00031 #include <cstdio> 00032 #include <limits> 00033 00034 namespace plb { 00035 00036 template<typename T> 00037 Spline<T>::Spline(std::string fname) 00038 { 00039 FILE *fp = fopen(fname.c_str(), "r"); 00040 PLB_ASSERT(fp != NULL); 00041 00042 long double tmp0, tmp1; 00043 while (!feof(fp)) 00044 if (fscanf(fp, "%Lf%Lf", &tmp0, &tmp1) != EOF) { 00045 x.push_back((T) tmp0); 00046 y.push_back((T) tmp1); 00047 } 00048 00049 fclose(fp); 00050 00051 PLB_ASSERT(x.size() == y.size()); 00052 #ifdef PLB_DEBUG 00053 T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00054 for (plint i = 1; i < (plint) x.size(); i++) 00055 if (x[i] < x[i - 1] || util::fpequal(x[i], x[i - 1], eps)) { 00056 plbLogicError("The abscissa of the interpolation points must be monotonically increasing."); 00057 } 00058 #endif // PLB_DEBUG 00059 } 00060 00061 template<typename T> 00062 Spline<T>::Spline(std::vector<T> const& x_, std::vector<T> const& y_) 00063 : x(x_), 00064 y(y_) 00065 { 00066 PLB_ASSERT(x.size() == y.size()); 00067 #ifdef PLB_DEBUG 00068 T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00069 for (plint i = 1; i < (plint) x.size(); i++) 00070 if (x[i] < x[i - 1] || util::fpequal(x[i], x[i - 1], eps)) { 00071 plbLogicError("The abscissa of the interpolation points must be monotonically increasing."); 00072 } 00073 #endif // PLB_DEBUG 00074 } 00075 00076 template<typename T> 00077 NaturalCubicSpline<T>::NaturalCubicSpline(std::string fname) 00078 : Spline<T>(fname) 00079 { 00080 icache = 0; 00081 constructSpline(); 00082 } 00083 00084 template<typename T> 00085 NaturalCubicSpline<T>::NaturalCubicSpline(std::vector<T> const& x_, std::vector<T> const& y_) 00086 : Spline<T>(x_, y_) 00087 { 00088 icache = 0; 00089 constructSpline(); 00090 } 00091 00092 template<typename T> 00093 NaturalCubicSpline<T>* NaturalCubicSpline<T>::clone() const { 00094 return new NaturalCubicSpline<T>(*this); 00095 } 00096 00097 template<typename T> 00098 void NaturalCubicSpline<T>::constructSpline() 00099 { 00100 std::vector<T> const& x = this->getAbscissae(); 00101 std::vector<T> const& y = this->getOrdinates(); 00102 plint n = (plint) x.size(); 00103 PLB_ASSERT( n>=2 ); 00104 std::vector<T> a1(n-1), a2(n-1), a3(n), a4(n), a5(n); 00105 00106 y1.resize(n-1); 00107 y2.resize(n); 00108 y3.resize(n-1); 00109 00110 // Calculate the spline coefficients for polynomials of the form: 00111 // S_j(x) = y_j + y1_j * (x - x_j) + y2_j * (x - x_j)^2 + y3_j * (x - x_j)^3 00112 00113 for (plint i = 0; i < n - 1; i++) 00114 a1[i] = x[i + 1] - x[i]; 00115 00116 for (plint i = 1; i < n - 1; i++) 00117 a2[i] = 3.0 * (y[i + 1] - y[i]) / a1[i] - 3.0 * (y[i] - y[i - 1]) / a1[i - 1]; 00118 00119 a3[0] = 1.0; 00120 a4[0] = 0.0; 00121 a5[0] = 0.0; 00122 00123 for (plint i = 1; i < n - 1; i++) { 00124 a3[i] = 2.0 * (x[i + 1] - x[i - 1]) - a1[i - 1] * a4[i - 1]; 00125 a4[i] = a1[i] / a3[i]; 00126 a5[i] = (a2[i] - a1[i - 1] * a5[i - 1]) / a3[i]; 00127 } 00128 00129 a3[n - 1] = 1.0; 00130 a5[n - 1] = 0.0; 00131 y2[n - 1] = 0.0; 00132 00133 for (plint i = n - 2; i > -1; i--) { 00134 y2[i] = a5[i] - a4[i] * y2[i + 1]; 00135 y1[i] = (y[i + 1] - y[i]) / a1[i] - a1[i] * (y2[i + 1] + 2.0 * y2[i]) / 3.0; 00136 y3[i] = (y2[i + 1] - y2[i]) / (3.0 * a1[i]); 00137 } 00138 00139 y2.resize(n-1); 00140 } 00141 00142 // return an index i in the range from il to ih for which x[i] <= t < x[i + 1] 00143 template<typename T> 00144 plint NaturalCubicSpline<T>::bsrch(T t, plint il, plint ih) const 00145 { 00146 std::vector<T> const& x = this->getAbscissae(); 00147 plint ilo = il; 00148 plint ihi = ih; 00149 00150 plint i; 00151 while (ihi > (ilo + 1)) { 00152 i = (ihi + ilo) / 2; 00153 00154 if (x[i] > t) 00155 ihi = i; 00156 else 00157 ilo = i; 00158 } 00159 00160 return ilo; 00161 } 00162 00163 template<typename T> 00164 T NaturalCubicSpline<T>::getFunctionValue(T t) const 00165 { 00166 std::vector<T> const& x = this->getAbscissae(); 00167 std::vector<T> const& y = this->getOrdinates(); 00168 plint n = (plint) x.size(); 00169 PLB_ASSERT( n>=1 ); 00170 00171 #ifdef PLB_DEBUG 00172 T x1 = x[0]; 00173 T x2 = x[n-1]; 00174 static T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00175 if ((t < x1 && !util::fpequal(t, x1, eps)) || 00176 (t > x2 && !util::fpequal(t, x2, eps))) 00177 plbLogicError("Argument out of bounds."); 00178 #endif // PLB_DEBUG 00179 00180 if (t < x[icache] || t >= x[icache + 1]) { 00181 if (t > x[icache]) { 00182 icache = bsrch(t, icache, n - 1); 00183 } else { 00184 icache = bsrch(t, 0, icache); 00185 } 00186 } 00187 00188 T xtmp = t - x[icache]; 00189 T ytmp = y[icache] + xtmp * (y1[icache] + xtmp * (y2[icache] + xtmp * (y3[icache]))); 00190 return ytmp; 00191 } 00192 00193 template<typename T> 00194 T NaturalCubicSpline<T>::getDerivativeValue(T t) const 00195 { 00196 std::vector<T> const& x = this->getAbscissae(); 00197 plint n = (plint) x.size(); 00198 PLB_ASSERT( n>=1 ); 00199 T x1 = x[0]; 00200 T x2 = x[n-1]; 00201 00202 #ifdef PLB_DEBUG 00203 static T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00204 if ((t < x1 && !util::fpequal(t, x1, eps)) || 00205 (t > x2 && !util::fpequal(t, x2, eps))) 00206 plbLogicError("Argument out of bounds."); 00207 #endif // PLB_DEBUG 00208 00209 if (t < x[icache] || t >= x[icache + 1]) { 00210 if (t > x[icache]) { 00211 icache = bsrch(t, icache, n - 1); 00212 } else { 00213 icache = bsrch(t, 0, icache); 00214 } 00215 } 00216 00217 T xtmp = t - x[icache]; 00218 T ydtmp = y1[icache] + xtmp * (2.0 * y2[icache] + xtmp * (3.0 * y3[icache])); 00219 return ydtmp; 00220 } 00221 00222 template<typename T> 00223 T NaturalCubicSpline<T>::getSecondDerivativeValue(T t) const 00224 { 00225 std::vector<T> const& x = this->getAbscissae(); 00226 plint n = (plint) x.size(); 00227 PLB_ASSERT( n>=1 ); 00228 T x1 = x[0]; 00229 T x2 = x[n-1]; 00230 00231 #ifdef PLB_DEBUG 00232 static T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00233 if ((t < x1 && !util::fpequal(t, x1, eps)) || 00234 (t > x2 && !util::fpequal(t, x2, eps))) 00235 plbLogicError("Argument out of bounds."); 00236 #endif // PLB_DEBUG 00237 00238 if (t < x[icache] || t >= x[icache + 1]) { 00239 if (t > x[icache]) { 00240 icache = bsrch(t, icache, n - 1); 00241 } else { 00242 icache = bsrch(t, 0, icache); 00243 } 00244 } 00245 00246 T xtmp = t - x[icache]; 00247 T yd2tmp = 2.0 * y2[icache] + 6.0 * y3[icache] * xtmp; 00248 return yd2tmp; 00249 } 00250 00251 template<typename T> 00252 T NaturalCubicSpline<T>::getThirdDerivativeValue(T t) const 00253 { 00254 std::vector<T> const& x = this->getAbscissae(); 00255 plint n = (plint) x.size(); 00256 PLB_ASSERT( n>=1 ); 00257 T x1 = x[0]; 00258 T x2 = x[n-1]; 00259 00260 #ifdef PLB_DEBUG 00261 static T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00262 if ((t < x1 && !util::fpequal(t, x1, eps)) || 00263 (t > x2 && !util::fpequal(t, x2, eps))) 00264 plbLogicError("Argument out of bounds."); 00265 #endif // PLB_DEBUG 00266 00267 if (t < x[icache] || t >= x[icache + 1]) { 00268 if (t > x[icache]) { 00269 icache = bsrch(t, icache, n - 1); 00270 } else { 00271 icache = bsrch(t, 0, icache); 00272 } 00273 } 00274 00275 T yd3tmp = 6.0 * y3[icache]; 00276 return yd3tmp; 00277 } 00278 00279 template<typename T> 00280 T NaturalCubicSpline<T>::getIntegralValue() const 00281 { 00282 std::vector<T> const& x = this->getAbscissae(); 00283 std::vector<T> const& y = this->getOrdinates(); 00284 plint n = (plint) x.size(); 00285 00286 T integral = (T) 0; 00287 for (plint i = 0; i < n-1; i++) { 00288 T dx = x[i + 1] - x[i]; 00289 integral += dx * (y[i] + dx * (y1[i] / 2.0 + dx * (y2[i] / 3.0 + dx * (y3[i] / 4.0)))); 00290 } 00291 00292 return integral; 00293 } 00294 00295 template<typename T> 00296 T NaturalCubicSpline<T>::getIntegralValue(T tmin, T tmax) const 00297 { 00298 static T eps = 100.0 * std::numeric_limits<T>::epsilon(); 00299 std::vector<T> const& x = this->getAbscissae(); 00300 std::vector<T> const& y = this->getOrdinates(); 00301 plint n = (plint) x.size(); 00302 T x1 = x[0]; 00303 T x2 = x[n-1]; 00304 00305 #ifdef PLB_DEBUG 00306 if (tmin > tmax) 00307 plbLogicError("Invalid arguments."); 00308 if ((tmin < x1 && !util::fpequal(tmin, x1, eps)) || 00309 (tmin > x2 && !util::fpequal(tmin, x2, eps))) 00310 plbLogicError("Argument out of bounds."); 00311 if ((tmax < x1 && !util::fpequal(tmax, x1, eps)) || 00312 (tmax > x2 && !util::fpequal(tmax, x2, eps))) 00313 plbLogicError("Argument out of bounds."); 00314 #endif // PLB_DEBUG 00315 00316 if (util::fpequal(tmin, tmax, eps)) 00317 return ((T) 0); 00318 00319 if (tmin < x[icache] || tmin >= x[icache + 1]) { 00320 if (tmin > x[icache]) { 00321 icache = bsrch(tmin, icache, n - 1); 00322 } else { 00323 icache = bsrch(tmin, 0, icache); 00324 } 00325 } 00326 plint imin = icache; 00327 00328 if (tmax < x[icache] || tmax >= x[icache + 1]) { 00329 if (tmax > x[icache]) { 00330 icache = bsrch(tmax, icache, n - 1); 00331 } else { 00332 icache = bsrch(tmax, 0, icache); 00333 } 00334 } 00335 plint imax = icache; 00336 00337 plint i; 00338 T dxmin, dxmax, integral; 00339 00340 if (imin == imax) { 00341 i = imin; 00342 dxmin = tmin - x[i]; 00343 dxmax = tmax - x[i]; 00344 integral = y[i] * (tmax - tmin) + 00345 (y1[i]/2.0) * (dxmax*dxmax - dxmin*dxmin) + 00346 (y2[i]/3.0) * (dxmax*dxmax*dxmax - dxmin*dxmin*dxmin) + 00347 (y3[i]/4.0) * (dxmax*dxmax*dxmax*dxmax - dxmin*dxmin*dxmin*dxmin); 00348 return integral; 00349 } 00350 00351 i = imin; 00352 dxmin = tmin - x[i]; 00353 dxmax = x[i + 1] - x[i]; 00354 integral = y[i] * (x[i + 1] - tmin) + 00355 (y1[i]/2.0) * (dxmax*dxmax - dxmin*dxmin) + 00356 (y2[i]/3.0) * (dxmax*dxmax*dxmax - dxmin*dxmin*dxmin) + 00357 (y3[i]/4.0) * (dxmax*dxmax*dxmax*dxmax - dxmin*dxmin*dxmin*dxmin); 00358 00359 T dx; 00360 for (i = imin + 1; i < imax; i++) { 00361 dx = x[i + 1] - x[i]; 00362 integral += dx * (y[i] + dx * (y1[i] / 2.0 + dx * (y2[i] / 3.0 + dx * (y3[i] / 4.0)))); 00363 } 00364 00365 i = imax; 00366 dx = tmax - x[i]; 00367 integral += dx * (y[i] + dx * (y1[i] / 2.0 + dx * (y2[i] / 3.0 + dx * (y3[i] / 4.0)))); 00368 00369 return integral; 00370 } 00371 00372 } // namespace plb 00373 00374 #endif // SPLINE_HH
1.6.3
1.6.3