Lemma is an Electromagnetics API
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

CubicSplineInterpolator.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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, Trevor Irons
  15. */
  16. #include "CubicSplineInterpolator.h"
  17. #include<iostream>
  18. #include<fstream>
  19. #include<vector>
  20. #include<algorithm>
  21. #include<cmath>
  22. namespace Lemma {
  23. // ==================== FRIEND METHODS =====================
  24. std::ostream &operator << (std::ostream &stream, const CubicSplineInterpolator &ob) {
  25. stream << ob.Serialize() << "\n---\n"; // End of doc --- as a direct stream should encapulste thingy
  26. return stream;
  27. }
  28. // ==================== LIFECYCLE =======================
  29. //--------------------------------------------------------------------------------------
  30. // Class: CubicSplineInterpolator
  31. // Method: CubicSplineInterpolator
  32. // Description: constructor (protected)
  33. //--------------------------------------------------------------------------------------
  34. CubicSplineInterpolator::CubicSplineInterpolator ( ) : LemmaObject( ) {
  35. } // ----- end of method CubicSplineInterpolator::CubicSplineInterpolator (constructor) -----
  36. //--------------------------------------------------------------------------------------
  37. // Class: CubicSplineInterpolator
  38. // Method: CubicSplineInterpolator
  39. // Description: DeSerializing constructor (protected)
  40. //--------------------------------------------------------------------------------------
  41. CubicSplineInterpolator::CubicSplineInterpolator (const YAML::Node& node) : LemmaObject(node) {
  42. } // ----- end of method CubicSplineInterpolator::CubicSplineInterpolator (constructor) -----
  43. //--------------------------------------------------------------------------------------
  44. // Class: CubicSplineInterpolator
  45. // Method: NewSP()
  46. // Description: public constructor
  47. //--------------------------------------------------------------------------------------
  48. std::shared_ptr<CubicSplineInterpolator> CubicSplineInterpolator::NewSP() {
  49. std::shared_ptr<CubicSplineInterpolator> sp(new CubicSplineInterpolator( ), LemmaObjectDeleter() );
  50. return sp;
  51. }
  52. //--------------------------------------------------------------------------------------
  53. // Class: CubicSplineInterpolator
  54. // Method: Serialize
  55. //--------------------------------------------------------------------------------------
  56. YAML::Node CubicSplineInterpolator::Serialize ( ) const {
  57. YAML::Node node = LemmaObject::Serialize();;
  58. node.SetTag( GetName() );
  59. // FILL IN CLASS SPECIFICS HERE
  60. return node;
  61. } // ----- end of method CubicSplineInterpolator::Serialize -----
  62. //--------------------------------------------------------------------------------------
  63. // Class: CubicSplineInterpolator
  64. // Method: DeSerialize
  65. //--------------------------------------------------------------------------------------
  66. std::shared_ptr<CubicSplineInterpolator> CubicSplineInterpolator::DeSerialize ( const YAML::Node& node ) {
  67. if (node.Tag() != "CubicSplineInterpolator") {
  68. throw DeSerializeTypeMismatch( "CubicSplineInterpolator", node.Tag());
  69. }
  70. std::shared_ptr<CubicSplineInterpolator> Object(new CubicSplineInterpolator(node), LemmaObjectDeleter() );
  71. return Object ;
  72. }
  73. //--------------------------------------------------------------------------------------
  74. // Class: CubicSplineInterpolator
  75. // Method: ~CubicSplineInterpolator
  76. // Description: destructor (protected)
  77. //--------------------------------------------------------------------------------------
  78. CubicSplineInterpolator::~CubicSplineInterpolator () {
  79. } // ----- end of method CubicSplineInterpolator::~CubicSplineInterpolator (destructor) -----
  80. //--------------------------------------------------------------------------------------
  81. // Class: CubicSplineInterpolator
  82. // Method: Release
  83. // Description: destructor (protected)
  84. //--------------------------------------------------------------------------------------
  85. void CubicSplineInterpolator::Release() {
  86. delete this;
  87. }
  88. // ==================== OPERATIONS =======================
  89. //--------------------------------------------------------------------------------------
  90. // Class: CubicSplineInterpolator
  91. // Method: SetKnots
  92. //--------------------------------------------------------------------------------------
  93. void CubicSplineInterpolator::SetKnots ( const VectorXr& x, const VectorXr& y ) {
  94. int n = x.size()-1;
  95. Spline = SplineSet(n);
  96. Spline.a = y;
  97. Spline.x = x;
  98. VectorXr h = VectorXr::Zero(n);
  99. for(int i=0; i<n; ++i)
  100. h(i) = Spline.x(i+1)-Spline.x(i);
  101. VectorXr alpha(n-1);
  102. for(int i=1; i<n-1; ++i)
  103. alpha(i) = 3.*(Spline.a[i+1]-Spline.a[i])/h[i] - 3.*(Spline.a[i]-Spline.a[i-1])/h[i-1] ;
  104. VectorXr l = VectorXr::Zero(n+1);
  105. VectorXr mu = VectorXr::Zero(n+1);
  106. VectorXr z = VectorXr::Zero(n+1);
  107. l[0] = 1;
  108. mu[0] = 0;
  109. z[0] = 0;
  110. for(int i = 1; i < n-1; ++i) {
  111. l[i] = 2 *(Spline.x[i+1]-Spline.x[i-1])-h[i-1]*mu[i-1];
  112. mu[i] = h[i]/l[i];
  113. z[i] = (alpha[i]-h[i-1]*z[i-1])/l[i];
  114. }
  115. l[n] = 1;
  116. z[n] = 0;
  117. for(int j = n-1; j >= 0; --j) {
  118. Spline.c[j] = z[j] - mu[j] * Spline.c[j+1];
  119. Spline.b[j] = (Spline.a[j+1]-Spline.a[j])/h[j]-h[j]*(Spline.c[j+1]+2*Spline.c[j])/3;
  120. Spline.d[j] = (Spline.c[j+1]-Spline.c[j])/3/h[j];
  121. }
  122. // On OSX, this causes a strange bug 'sometimes', alignment?
  123. //Spline.c = Spline.c.head(n);
  124. return;
  125. } // ----- end of method CubicSplineInterpolator::SetKnots -----
  126. //--------------------------------------------------------------------------------------
  127. // Class: CubicSplineInterplator
  128. // Method: ResetKnotOrdinate
  129. //--------------------------------------------------------------------------------------
  130. void CubicSplineInterpolator::ResetKnotOrdinate ( const VectorXr& y ) {
  131. VectorXr x = Spline.x;
  132. SetKnots(x, y);
  133. return ;
  134. } // ----- end of method CubicSplineInterplator::ResetKnotOrdinate -----
  135. //--------------------------------------------------------------------------------------
  136. // Class: CubicSplineInterpolator
  137. // Method: InterpolateOrderedSet
  138. //--------------------------------------------------------------------------------------
  139. VectorXr CubicSplineInterpolator::InterpolateOrderedSet ( const VectorXr& x ) {
  140. VectorXr y = VectorXr::Zero(x.size());
  141. int ii = 0;
  142. for (int iy=0; iy<y.size(); ++iy) {
  143. y[iy] = Interpolate(x[iy], ii);
  144. }
  145. return y;
  146. } // ----- end of method CubicSplineInterpolator::InterpolateOrderedSet -----
  147. //--------------------------------------------------------------------------------------
  148. // Class: CubicSplineInterpolator
  149. // Method: Interpolate
  150. //--------------------------------------------------------------------------------------
  151. Real CubicSplineInterpolator::Interpolate ( const Real& x, int& i) {
  152. // O(n) search, could do bisection, but if these are sorted, then this is quick
  153. while(Spline.x[i] < x && i<Spline.x.size()) {
  154. ++i;
  155. }
  156. --i;
  157. //if ( x > Spline.x[i] ) {
  158. // throw std::runtime_error("CubicSplineInterpolator::Interpolate ATTEMPT TO INTERPOLATE PAST LAST KNOT");
  159. //}
  160. return Spline.a[i] + Spline.b[i]*(x-Spline.x[i]) + Spline.c[i]*((x-Spline.x[i])*(x-Spline.x[i])) +
  161. Spline.d[i]*((x-Spline.x[i])*(x-Spline.x[i])*(x-Spline.x[i]) );
  162. } // ----- end of method CubicSplineInterpolator::Interpolate -----
  163. //--------------------------------------------------------------------------------------
  164. // Class: CubicSplineInterpolator
  165. // Method: Interpolate
  166. //--------------------------------------------------------------------------------------
  167. Real CubicSplineInterpolator::Interpolate ( const Real& x ) {
  168. int ii(0);
  169. return Interpolate(x, ii);
  170. }
  171. //--------------------------------------------------------------------------------------
  172. // Class: CubicSplineInterpolator
  173. // Method: Integrate
  174. //--------------------------------------------------------------------------------------
  175. Real CubicSplineInterpolator::Integrate ( const Real& x0, const Real& x1, const int& n ) {
  176. assert(n > 0);
  177. // force n to be even?
  178. //n += (n % 2);
  179. Real S = Interpolate(x0) + Interpolate(x1);
  180. Real h = (x1 - x0) / Real(n);
  181. int ik = 0;
  182. for (int i=1; i<n; i+=2) {
  183. S += 4. * Interpolate(x0 + (Real)(i)*h, ik);
  184. }
  185. ik = 0;
  186. for (int i=2; i<n-1; i+=2) {
  187. S += 2. * Interpolate(x0 + (Real)(i)*h, ik);
  188. }
  189. return S * h / 3.;
  190. }
  191. //--------------------------------------------------------------------------------------
  192. // Class: CubicSplineInterpolator
  193. // Method: Integrate
  194. //--------------------------------------------------------------------------------------
  195. Real CubicSplineInterpolator::Integrate ( const Real& x0, const Real& x1 ) {
  196. int i0 = Interval(x0);
  197. int i1 = Interval(x1);
  198. Real h0 = x0 - Spline.x(i0);
  199. if (mflag == -1) h0 = 0;
  200. Real h1 = x1 - Spline.x(i1);
  201. Real cubint = (((Spline.d(i1)*h1/4.0 + Spline.c(i1) )*h1/3.0 +
  202. Spline.b(i1) )*h1/2.0 + Spline.a(i1) )*h1
  203. - (((Spline.d(i0)*h0/4.0 + Spline.c(i0) )*h0/3.0 +
  204. Spline.b(i0) )*h0/2.0 + Spline.a(i0) )*h0;
  205. // Include integrals over intervening intervals.
  206. if (i1 > i0) {
  207. for (int i=i0; i<i1-1; ++i) {
  208. Real h = Spline.x(i+1) - Spline.x(i);
  209. cubint += (((Spline.d(i)*h/4.0 + Spline.c(i) )*h/3.0 +
  210. Spline.b(i))*h/2.0 + Spline.a(i) )*h;
  211. }
  212. }
  213. return cubint;
  214. } // ----- end of method CubicSplineInterpolator::Integrate -----
  215. //--------------------------------------------------------------------------------------
  216. // Class: CubicSplineInterpolator
  217. // Method: Interval
  218. //--------------------------------------------------------------------------------------
  219. int CubicSplineInterpolator::Interval ( const Real& x ) {
  220. std::cerr << "ENTERING CubicSplineInterpolator::Inverval. Known bugs here" << std::endl;
  221. int nx = Spline.x.size() - 2; // TODO check if this is correct or just -1
  222. // when x not in range
  223. if (x <= Spline.x(0) || nx <= 1 ) {
  224. mflag = -1;
  225. return 1;
  226. }
  227. if (x >= Spline.x(nx)) {
  228. mflag = 1;
  229. return nx;
  230. }
  231. mflag = 0;
  232. if (ilo >= nx) ilo = nx-1;
  233. int ihi = ilo+1;
  234. // if x is already in the interval
  235. if ( x<Spline.x(ihi) && x >= Spline.x(ilo) ) {
  236. //std::cout << "TRIVIAL INTERVAL " << Spline.x(ilo) << "\t" << x << "\t" << Spline.x(ihi) << std::endl;
  237. return ilo;
  238. }
  239. if (x <= Spline.x(ilo)) { // decrease ilo to capture
  240. int istep = 1;
  241. for (int ix=1; ix<nx; ++ix) {
  242. ihi = ilo;
  243. ilo = ihi - istep;
  244. ilo = std::max(1, ilo);
  245. if (x >= Spline.x(ilo) || ilo == 1) break;
  246. istep *= 2;
  247. }
  248. } else if (x >= Spline.x(ihi)) { // increase ihi to capture
  249. int istep = 1;
  250. for (int ix=1; ix<nx; ++ix) {
  251. ilo = ihi;
  252. ihi = ilo + istep;
  253. ihi = std::min(ihi, nx);
  254. if (x <= Spline.x(ihi) || ihi == nx) break;
  255. istep *= 2;
  256. }
  257. }
  258. // Now Spline.x(ilo) <= x < Spline.x(ihi) --> Narrow the interval.
  259. //std::cout << "WIDE INTERVAL " << Spline.x(ilo) << "\t" << x << "\t" << Spline.x(ihi) << std::endl;
  260. for (int ix=1; ix<nx; ++ix) {
  261. int middle = (ilo+ihi) / 2;
  262. if (middle == ilo) break;
  263. if (x < Spline.x(middle)) {
  264. ihi = middle;
  265. } else {
  266. ilo = middle;
  267. }
  268. }
  269. assert ( Spline.x(ilo) < x && x < Spline.x(ihi) );
  270. return ilo;
  271. } // ----- end of method CubicSplineInterpolator::Inverval -----
  272. //--------------------------------------------------------------------------------------
  273. // Class: CubicSplineInterplator
  274. // Method: GetAbscissa
  275. //--------------------------------------------------------------------------------------
  276. VectorXr CubicSplineInterpolator::GetKnotAbscissa ( ) {
  277. return Spline.x;
  278. } // ----- end of method CubicSplineInterplator::get_GetAbscissa -----
  279. //--------------------------------------------------------------------------------------
  280. // Class: CubicSplineInterpolator
  281. // Method: GetKnotOrdinate
  282. //--------------------------------------------------------------------------------------
  283. VectorXr CubicSplineInterpolator::GetKnotOrdinate ( ) {
  284. return Spline.a;
  285. } // ----- end of method CubicSplineInterpolator::GetKnotOrdinate -----
  286. } // ----- end of Lemma name -----
  287. /* vim: set tabstop=4 expandtab: */
  288. /* vim: set filetype=cpp: */