Main Lemma Repository
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

CubicSplineInterpolator.cpp 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* This file is part of Lemma, a geophysical modelling and inversion API.
  2. * More information is available at http://lemmasoftware.org
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file
  10. * @date 02/07/2014 12:50:52 PM
  11. * @version $Id$
  12. * @author Trevor Irons (ti)
  13. * @email Trevor.Irons@xri-geo.com
  14. * @copyright Copyright (c) 2014, XRI GeophysiSpline, LLC
  15. * @copyright Copyright (c) 2014, Trevor Irons
  16. */
  17. #include "CubicSplineInterpolator.h"
  18. #include<iostream>
  19. #include<fstream>
  20. #include<vector>
  21. #include<algorithm>
  22. #include<cmath>
  23. namespace Lemma {
  24. // ==================== FRIEND METHODS =====================
  25. std::ostream &operator<<(std::ostream &stream, const CubicSplineInterpolator &ob) {
  26. stream << *(LemmaObject*)(&ob);
  27. return stream;
  28. }
  29. // ==================== LIFECYCLE =======================
  30. //--------------------------------------------------------------------------------------
  31. // Class: CubicSplineInterpolator
  32. // Method: CubicSplineInterpolator
  33. // Description: constructor (protected)
  34. //--------------------------------------------------------------------------------------
  35. CubicSplineInterpolator::CubicSplineInterpolator (const std::string& name) : LemmaObject(name) {
  36. } // ----- end of method CubicSplineInterpolator::CubicSplineInterpolator (constructor) -----
  37. //--------------------------------------------------------------------------------------
  38. // Class: CubicSplineInterpolator
  39. // Method: NewSP()
  40. // Description: public constructor
  41. //--------------------------------------------------------------------------------------
  42. std::shared_ptr<CubicSplineInterpolator> CubicSplineInterpolator::NewSP() {
  43. std::shared_ptr<CubicSplineInterpolator> sp(new CubicSplineInterpolator("CubicSplineInterpolator"), LemmaObjectDeleter() );
  44. return sp;
  45. }
  46. //--------------------------------------------------------------------------------------
  47. // Class: CubicSplineInterpolator
  48. // Method: ~CubicSplineInterpolator
  49. // Description: destructor (protected)
  50. //--------------------------------------------------------------------------------------
  51. CubicSplineInterpolator::~CubicSplineInterpolator () {
  52. } // ----- end of method CubicSplineInterpolator::~CubicSplineInterpolator (destructor) -----
  53. //--------------------------------------------------------------------------------------
  54. // Class: CubicSplineInterpolator
  55. // Method: Release
  56. // Description: destructor (protected)
  57. //--------------------------------------------------------------------------------------
  58. void CubicSplineInterpolator::Release() {
  59. delete this;
  60. }
  61. // ==================== OPERATIONS =======================
  62. //--------------------------------------------------------------------------------------
  63. // Class: CubicSplineInterpolator
  64. // Method: SetKnots
  65. //--------------------------------------------------------------------------------------
  66. void CubicSplineInterpolator::SetKnots ( const VectorXr& x, const VectorXr& y ) {
  67. int n = x.size()-1;
  68. Spline = SplineSet(n);
  69. Spline.a = y;
  70. Spline.x = x;
  71. VectorXr h = VectorXr::Zero(n);
  72. for(int i=0; i<n; ++i)
  73. h(i) = Spline.x(i+1)-Spline.x(i);
  74. VectorXr alpha(n-1);
  75. for(int i=1; i<n-1; ++i)
  76. alpha(i) = 3.*(Spline.a[i+1]-Spline.a[i])/h[i] - 3.*(Spline.a[i]-Spline.a[i-1])/h[i-1] ;
  77. VectorXr l = VectorXr::Zero(n+1);
  78. VectorXr mu = VectorXr::Zero(n+1);
  79. VectorXr z = VectorXr::Zero(n+1);
  80. l[0] = 1;
  81. mu[0] = 0;
  82. z[0] = 0;
  83. for(int i = 1; i < n-1; ++i) {
  84. l[i] = 2 *(Spline.x[i+1]-Spline.x[i-1])-h[i-1]*mu[i-1];
  85. mu[i] = h[i]/l[i];
  86. z[i] = (alpha[i]-h[i-1]*z[i-1])/l[i];
  87. }
  88. l[n] = 1;
  89. z[n] = 0;
  90. for(int j = n-1; j >= 0; --j) {
  91. Spline.c[j] = z[j] - mu[j] * Spline.c[j+1];
  92. Spline.b[j] = (Spline.a[j+1]-Spline.a[j])/h[j]-h[j]*(Spline.c[j+1]+2*Spline.c[j])/3;
  93. Spline.d[j] = (Spline.c[j+1]-Spline.c[j])/3/h[j];
  94. }
  95. // On OSX, this causes a strange bug 'sometimes', alignment?
  96. //Spline.c = Spline.c.head(n);
  97. return;
  98. } // ----- end of method CubicSplineInterpolator::SetKnots -----
  99. //--------------------------------------------------------------------------------------
  100. // Class: CubicSplineInterplator
  101. // Method: ResetKnotOrdinate
  102. //--------------------------------------------------------------------------------------
  103. void CubicSplineInterpolator::ResetKnotOrdinate ( const VectorXr& y ) {
  104. VectorXr x = Spline.x;
  105. SetKnots(x, y);
  106. return ;
  107. } // ----- end of method CubicSplineInterplator::ResetKnotOrdinate -----
  108. //--------------------------------------------------------------------------------------
  109. // Class: CubicSplineInterpolator
  110. // Method: InterpolateOrderedSet
  111. //--------------------------------------------------------------------------------------
  112. VectorXr CubicSplineInterpolator::InterpolateOrderedSet ( const VectorXr& x ) {
  113. VectorXr y = VectorXr::Zero(x.size());
  114. int ii = 0;
  115. for (int iy=0; iy<y.size(); ++iy) {
  116. y[iy] = Interpolate(x[iy], ii);
  117. }
  118. return y;
  119. } // ----- end of method CubicSplineInterpolator::InterpolateOrderedSet -----
  120. //--------------------------------------------------------------------------------------
  121. // Class: CubicSplineInterpolator
  122. // Method: Interpolate
  123. //--------------------------------------------------------------------------------------
  124. Real CubicSplineInterpolator::Interpolate ( const Real& x, int& i) {
  125. // O(n) search, could do bisection, but if these are sorted, then this is quick
  126. while(Spline.x[i] < x && i<Spline.x.size()) {
  127. ++i;
  128. }
  129. --i;
  130. //if ( x > Spline.x[i] ) {
  131. // throw std::runtime_error("CubicSplineInterpolator::Interpolate ATTEMPT TO INTERPOLATE PAST LAST KNOT");
  132. //}
  133. return Spline.a[i] + Spline.b[i]*(x-Spline.x[i]) + Spline.c[i]*((x-Spline.x[i])*(x-Spline.x[i])) +
  134. Spline.d[i]*((x-Spline.x[i])*(x-Spline.x[i])*(x-Spline.x[i]) );
  135. } // ----- end of method CubicSplineInterpolator::Interpolate -----
  136. //--------------------------------------------------------------------------------------
  137. // Class: CubicSplineInterpolator
  138. // Method: Interpolate
  139. //--------------------------------------------------------------------------------------
  140. Real CubicSplineInterpolator::Interpolate ( const Real& x ) {
  141. int ii(0);
  142. return Interpolate(x, ii);
  143. }
  144. //--------------------------------------------------------------------------------------
  145. // Class: CubicSplineInterpolator
  146. // Method: Integrate
  147. //--------------------------------------------------------------------------------------
  148. Real CubicSplineInterpolator::Integrate ( const Real& x0, const Real& x1, const int& n ) {
  149. assert(n > 0);
  150. // force n to be even?
  151. //n += (n % 2);
  152. Real S = Interpolate(x0) + Interpolate(x1);
  153. Real h = (x1 - x0) / Real(n);
  154. int ik = 0;
  155. for (int i=1; i<n; i+=2) {
  156. S += 4. * Interpolate(x0 + (Real)(i)*h, ik);
  157. }
  158. ik = 0;
  159. for (int i=2; i<n-1; i+=2) {
  160. S += 2. * Interpolate(x0 + (Real)(i)*h, ik);
  161. }
  162. return S * h / 3.;
  163. }
  164. //--------------------------------------------------------------------------------------
  165. // Class: CubicSplineInterpolator
  166. // Method: Integrate
  167. //--------------------------------------------------------------------------------------
  168. Real CubicSplineInterpolator::Integrate ( const Real& x0, const Real& x1 ) {
  169. int i0 = Interval(x0);
  170. int i1 = Interval(x1);
  171. Real h0 = x0 - Spline.x(i0);
  172. if (mflag == -1) h0 = 0;
  173. Real h1 = x1 - Spline.x(i1);
  174. Real cubint = (((Spline.d(i1)*h1/4.0 + Spline.c(i1) )*h1/3.0 +
  175. Spline.b(i1) )*h1/2.0 + Spline.a(i1) )*h1
  176. - (((Spline.d(i0)*h0/4.0 + Spline.c(i0) )*h0/3.0 +
  177. Spline.b(i0) )*h0/2.0 + Spline.a(i0) )*h0;
  178. // Include integrals over intervening intervals.
  179. if (i1 > i0) {
  180. for (int i=i0; i<i1-1; ++i) {
  181. Real h = Spline.x(i+1) - Spline.x(i);
  182. cubint += (((Spline.d(i)*h/4.0 + Spline.c(i) )*h/3.0 +
  183. Spline.b(i))*h/2.0 + Spline.a(i) )*h;
  184. }
  185. }
  186. return cubint;
  187. } // ----- end of method CubicSplineInterpolator::Integrate -----
  188. //--------------------------------------------------------------------------------------
  189. // Class: CubicSplineInterpolator
  190. // Method: Interval
  191. //--------------------------------------------------------------------------------------
  192. int CubicSplineInterpolator::Interval ( const Real& x ) {
  193. std::cerr << "ENTERING CubicSplineInterpolator::Inverval. Known bugs here" << std::endl;
  194. int nx = Spline.x.size() - 2; // TODO check if this is correct or just -1
  195. // when x not in range
  196. if (x <= Spline.x(0) || nx <= 1 ) {
  197. mflag = -1;
  198. return 1;
  199. }
  200. if (x >= Spline.x(nx)) {
  201. mflag = 1;
  202. return nx;
  203. }
  204. mflag = 0;
  205. if (ilo >= nx) ilo = nx-1;
  206. int ihi = ilo+1;
  207. // if x is already in the interval
  208. if ( x<Spline.x(ihi) && x >= Spline.x(ilo) ) {
  209. //std::cout << "TRIVIAL INTERVAL " << Spline.x(ilo) << "\t" << x << "\t" << Spline.x(ihi) << std::endl;
  210. return ilo;
  211. }
  212. if (x <= Spline.x(ilo)) { // decrease ilo to capture
  213. int istep = 1;
  214. for (int ix=1; ix<nx; ++ix) {
  215. ihi = ilo;
  216. ilo = ihi - istep;
  217. ilo = std::max(1, ilo);
  218. if (x >= Spline.x(ilo) || ilo == 1) break;
  219. istep *= 2;
  220. }
  221. } else if (x >= Spline.x(ihi)) { // increase ihi to capture
  222. int istep = 1;
  223. for (int ix=1; ix<nx; ++ix) {
  224. ilo = ihi;
  225. ihi = ilo + istep;
  226. ihi = std::min(ihi, nx);
  227. if (x <= Spline.x(ihi) || ihi == nx) break;
  228. istep *= 2;
  229. }
  230. }
  231. // Now Spline.x(ilo) <= x < Spline.x(ihi) --> Narrow the interval.
  232. //std::cout << "WIDE INTERVAL " << Spline.x(ilo) << "\t" << x << "\t" << Spline.x(ihi) << std::endl;
  233. for (int ix=1; ix<nx; ++ix) {
  234. int middle = (ilo+ihi) / 2;
  235. if (middle == ilo) break;
  236. if (x < Spline.x(middle)) {
  237. ihi = middle;
  238. } else {
  239. ilo = middle;
  240. }
  241. }
  242. assert ( Spline.x(ilo) < x && x < Spline.x(ihi) );
  243. return ilo;
  244. } // ----- end of method CubicSplineInterpolator::Inverval -----
  245. //--------------------------------------------------------------------------------------
  246. // Class: CubicSplineInterplator
  247. // Method: GetAbscissa
  248. //--------------------------------------------------------------------------------------
  249. VectorXr CubicSplineInterpolator::GetKnotAbscissa ( ) {
  250. return Spline.x;
  251. } // ----- end of method CubicSplineInterplator::get_GetAbscissa -----
  252. //--------------------------------------------------------------------------------------
  253. // Class: CubicSplineInterpolator
  254. // Method: GetKnotOrdinate
  255. //--------------------------------------------------------------------------------------
  256. VectorXr CubicSplineInterpolator::GetKnotOrdinate ( ) {
  257. return Spline.a;
  258. } // ----- end of method CubicSplineInterpolator::GetKnotOrdinate -----
  259. } // ----- end of Lemma name -----