RBFInterp.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include <vector>
  2. #include <iostream>
  3. #include <map>
  4. #include <cmath>
  5. #include "protos_lapack.hpp"
  6. #include "RBF_functions.hpp"
  7. using namespace std;
  8. using namespace lapack_c;
  9. #ifndef RBFInterp__hpp
  10. #define RBFInterp__hpp
  11. //-------------------------------------------------------------------------
  12. // Interpolation rbf.
  13. //-------------------------------------------------------------------------
  14. template<typename real,class Radial> class RBFInterp{
  15. double * matrix , *b;
  16. real * image;
  17. real eps;
  18. int imgsize_x,imgsize_y;
  19. double rcond,innorm; double *work; bool rcondok;
  20. public:
  21. // (x,y) -> valeur
  22. // Il ne faut pas d'ex-aequeo pour (x,y), d'où l'utilisation d'une map
  23. // pour décrire les noeuds de l'interpolation.
  24. typedef std::map<pair<int,int>,real> PointValue;
  25. // consructeur:
  26. RBFInterp(real epsilon):eps(epsilon){}
  27. //changer epsilon
  28. void set_epsilon(real epsilon){eps=epsilon;}
  29. // Calcule les RBF.
  30. void build(PointValue& values,bool comp_cond= false)
  31. // comp_cond : on calcule ou non le conditionnement L\infinity de
  32. // la matrice.
  33. {
  34. Radial R(eps);
  35. int np= values.size();
  36. matrix = new double[np*np];
  37. b= new double[np];
  38. // construire le système linéaire (on n'utilise pas la symétrie de la
  39. // matrice).
  40. // 1) matrice:
  41. auto indix= [np](int i, int j){return i*np+j;};
  42. int i=0;
  43. for(typename PointValue::const_iterator I=values.begin();
  44. I!=values.end();I++)
  45. {
  46. auto v= I->first; //la fonction est centrée en ce point.
  47. int j=i;
  48. for(typename PointValue::const_iterator J=I;J!=values.end();++J)
  49. {
  50. auto s = R(r(v,J->first));
  51. matrix[indix(i,j)]=s;
  52. if(i!=j)
  53. matrix[indix(j,i)] =s;
  54. ++j;
  55. }
  56. ++i;
  57. }
  58. //2) second membre.
  59. i=0;
  60. for(typename PointValue::iterator I= values.begin();I!=values.end();I++)
  61. b[i++]=I->second;
  62. // resolution (lapack + blas).
  63. int* ipiv= new int[np];
  64. int nrhs=1,lda=np,ldb=np,info;
  65. char trans='N'; char norm='I';
  66. //
  67. rcondok = comp_cond;
  68. if(comp_cond)
  69. {
  70. // norme oo de la matrice:
  71. work= new double[4*np];
  72. // norme infinie de la matrice:
  73. innorm= dlange_(&norm,&np,&np,matrix,&lda,work);
  74. }
  75. // factorisation PLU:
  76. dgetrf_(&np,&np,matrix,&lda,ipiv,&info);
  77. if(info != 0) throw LapackException(info);
  78. if(comp_cond)
  79. {
  80. int *iwork=new int[np];
  81. dgecon_(&norm,&np,matrix,&lda,&innorm,&rcond,work,iwork,&info);
  82. rcond= 1.0/rcond;
  83. if(info != 0) throw LapackException(info);
  84. delete[] work; delete[] iwork;
  85. }
  86. // résolution du système factorisé:
  87. dgetrs_(&trans,&np,&nrhs,matrix,&lda,ipiv,b,&ldb,&info);
  88. if(info != 0) throw LapackException(info);
  89. //
  90. delete[] matrix;
  91. delete[] ipiv;
  92. }
  93. real test(const PointValue& interpvalues,const PointValue& testvalues)
  94. {
  95. // Estimer l'erreur.
  96. // interpvalues: les noeuds d'interpolation
  97. // testvalues : les noeuds test.
  98. Radial R(eps);
  99. real ret=0.0;
  100. // boucle sur les noeuds test :
  101. for(typename PointValue::const_iterator K=testvalues.begin();
  102. K!=testvalues.end();K++)
  103. {
  104. int k=0;
  105. real u=0.0;
  106. for(typename PointValue::const_iterator L=interpvalues.begin();
  107. L!=interpvalues.end();L++)
  108. {
  109. auto dist= r(K->first,L->first);
  110. u+=b[k++]*R(dist);
  111. }
  112. ret=max(ret,abs(K->second-u));
  113. }
  114. return ret;
  115. }
  116. real Interpolator(PointValue& values,int nx,int i,int j,Radial R)
  117. {
  118. //auto indix= [nx](int i, int j){return i*nx+j;};
  119. real s=0.0;
  120. int k=0;
  121. for(typename PointValue::const_iterator K=values.begin();
  122. K!=values.end();K++)
  123. s+=b[k++]* R(r(K->first,make_pair(i,j)));
  124. return s;
  125. }
  126. // interpolation sur une image nx par ny
  127. void Interp(PointValue& values,real *image,int nx,int ny,int increment=1)
  128. {
  129. Radial R(eps);
  130. auto indix= [nx](int i, int j){return i*nx+j;};
  131. #pragma omp parallel for
  132. for(int i=0;i<ny;i+=increment)
  133. for(int j=0;j<nx;j+=increment)
  134. {
  135. // real s=0.0;
  136. // int k=0;
  137. // for(typename PointValue::const_iterator K=values.begin();
  138. // K!=values.end();K++)
  139. // s+=b[k++]* R(r(K->first,make_pair(i,j)));
  140. //image[indix(i,j)] = s;
  141. image[indix(i,j)] = Interpolator(values,nx,i,j,R);
  142. }
  143. if(increment == 2)
  144. {
  145. for(int i=ny-3;i<ny;i++)
  146. for(int j=0;j<nx;j++)
  147. image[indix(i,j)] = Interpolator(values,nx,i,j,R);
  148. for(int j=ny-3;j<nx;j++)
  149. for(int i=0;i<ny;i++)
  150. image[indix(i,j)] = Interpolator(values,nx,i,j,R);
  151. }
  152. }
  153. ~RBFInterp()
  154. {
  155. delete[] b;
  156. }
  157. double cond() const
  158. {
  159. // accesseur pour le conditionnement
  160. if(rcondok)
  161. return rcond;
  162. else
  163. throw "rcond pas calculé";
  164. }
  165. double norme_matrice() const
  166. {
  167. if(rcondok)
  168. return innorm;
  169. else
  170. throw "rcond pas calculé";
  171. }
  172. private:
  173. // distance euclidienne de 2 points .
  174. inline float r(pair<int,int> x1,pair<int,int> x2){return sqrt(r2(x1,x2));}
  175. // distance euclidienne de 2 points au carré.
  176. inline float r2(pair<int,int> x1,pair<int,int> x2)
  177. {return pow(get<0>(x1)-get<0>(x2),2) + pow(get<1>(x1)-get<1>(x2),2);}
  178. };
  179. #endif