UCBsplines.h

00001 //===========================================================================
00002 // SINTEF LSMG library - version 1.1
00003 //
00004 // Copyright (C) 2000-2005 SINTEF ICT, Applied Mathematics, Norway.
00005 //
00006 // This program is free software; you can redistribute it and/or          
00007 // modify it under the terms of the GNU General Public License            
00008 // as published by the Free Software Foundation version 2 of the License. 
00009 //
00010 // This program is distributed in the hope that it will be useful,        
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00013 // GNU General Public License for more details.                           
00014 //
00015 // You should have received a copy of the GNU General Public License      
00016 // along with this program; if not, write to the Free Software            
00017 // Foundation, Inc.,                                                      
00018 // 59 Temple Place - Suite 330,                                           
00019 // Boston, MA  02111-1307, USA.                                           
00020 //
00021 // Contact information: e-mail: tor.dokken@sintef.no                      
00022 // SINTEF ICT, Department of Applied Mathematics,                         
00023 // P.O. Box 124 Blindern,                                                 
00024 // 0314 Oslo, Norway.                                                     
00025 //
00026 // Other licenses are also available for this software, notably licenses
00027 // for:
00028 // - Building commercial software.                                        
00029 // - Building software whose source code you wish to keep private.        
00030 //===========================================================================
00031 #ifndef _UNIF_QUBIC_BSPLINES_H_
00032 #define _UNIF_QUBIC_BSPLINES_H_
00033 
00034 #ifdef WIN32 
00035 #define WIN32ORSGI6 
00036 #endif
00037 
00038 #ifdef SGI6  // roxar definition
00039 #define WIN32ORSGI6
00040 #endif
00041 
00042 #ifdef SGI
00043 #define WIN32ORSGI6
00044 #endif
00045 
00046 #include <GenMatrix.h>
00047 #include <UCBtypedef.h>
00048 
00049 //#include <cmath>
00050 #include <math.h>
00051 
00054 namespace UCBspl {
00055 
00056 // Controls compilation for cubic C1 splines
00057 //old: #define MBA_CUBIC_C1 1
00058   
00059 //#define UNIFORM_CUBIC_C1_SPLINES 1
00060 
00061   
00062 #ifdef  UNIFORM_CUBIC_C1_SPLINES
00063   // Basis functions
00064   inline double B_0(double t) {double tmp = 1.0-t; return tmp*tmp*tmp/2.0;}
00065   inline double B_1(double t) {return (t*(t*(2.5*t - 4.5) + 1.5) + 0.5);}
00066   inline double B_2(double t) {return (t*t*(-2.5*t + 3.0));}
00067   inline double B_3(double t) {return t*t*t/2.0;}
00068   
00069   // And their derivatives
00070   inline double dB_0(double t) {return 1.5*(1.0-t)*(t-1.0);}
00071   inline double dB_1(double t) {return (t*(7.5*t - 9.0) + 1.5);}
00072   inline double dB_2(double t) {return (t*(-7.5*t + 6.0));}
00073   inline double dB_3(double t) {return 1.5*t*t;}
00074   
00075   // PRE EVALUATTED tensor products of B-splines, in a grid index
00076   // -------------------------------------------------------------
00077   
00078   // Pre-evaluated tensors equivalent to B(k,s)*B(l,t)
00079   static double tensor_BB[2][2] = {
00080     {1./4., 1./4.},
00081     {1./4., 1./4.}
00082   };
00083   
00084   // ???? only temp. for compilation
00085   // equivalent to dB(k,s)*B(l,t).
00086   static double tensor_dBB[2][2] = {
00087     {-3./4., -3./4.},
00088     { 3./4.,  3./4.}
00089   };
00090   
00091   // The transpose of the matrix above, for the y-components,
00092   // equivalent to B(k,s)*dB(l,t)
00093   static double tensor_BdB[2][2] = {
00094     {-3./4., 3./4.},
00095     {-3./4., 3./4.}
00096   };
00097   
00098 #else
00099   // The uniform (cardinal), univariate cubic C2 basis functions
00100   // 0 <= t < 1;
00101   inline double B_0(double t) {double tmp = 1.0-t; return tmp*tmp*tmp/6.0;}
00102   
00103   //static inline double B_1(double t) {return (3.0*t*t*t - 6.0*t*t+4.0)/6.0;}
00104   static double div46 = 4.0/6.0;
00105   inline double B_1(double t) {return (0.5*t*t*t - t*t + div46);}
00106   
00107   //static inline double B_2(double t) {return (-3.0*t*t*t + 3.0*t*t + 3.0*t + 1.0)/6.0;}
00108   static double div16 = 1.0/6.0;
00109   inline double B_2(double t) {return (-0.5*t*t*t + 0.5*t*t + 0.5*t + div16);}
00110   
00111   inline double B_3(double t) {return t*t*t/6.0;}
00112   
00113   // FIRST DERIVATIVES to the uniform cubic C2 basis functions
00114   inline double dB_0(double t) {return 0.5*(1.0-t)*(t-1.0);}
00115   inline double dB_1(double t) {return (1.5*t*t - 2.0*t);}
00116   inline double dB_2(double t) {return (-(1.5*t*t) + t + 0.5);}
00117   inline double dB_3(double t) {return t*t/2.0;}
00118   
00119   // Lagt til, Vegard (But not for C1 yet)
00120   // SECOND DERIVATIVES to the uniform cubic C2 basis functions
00121   inline double ddB_0(double t) {return (-t+1.0);}
00122   inline double ddB_1(double t) {return (3.0*t-2.0);}
00123   inline double ddB_2(double t) {return (-3.0*t+1.0);}
00124   inline double ddB_3(double t) {return t;}
00125   
00126   // PRE EVALUATTED tensor products of B-splines, in a grid index
00127   // -------------------------------------------------------------
00128   
00129   // Pre-evaluated tensors equivalent to B(k,s)*B(l,t)
00130   static double tensor_BB[3][3] = {
00131     {1./36., 1./9., 1./36.},
00132     {1./9., 4./9., 1./9.},
00133     {1./36., 1./9., 1./36.}
00134   };
00135   
00136   
00137   // Pre-evaluated tensor products of B-splines, in a grid index
00138   // Mixed derivative an positional tensor for the x-component.
00139   // equivalent to dB(k,s)*B(l,t).
00140   // (The second row with zeros is not used in evaluations.)
00141   static double tensor_dBB[3][3] = {
00142     {-1./12., -1./3., -1./12.},
00143     {     0.,     0.,      0.},
00144     { 1./12.,  1./3.,  1./12.}
00145   };
00146   
00147   // The transpose of the matrix above, for the y-components,
00148   // equivalent to B(k,s)*dB(l,t)
00149   static double tensor_BdB[3][3] = {
00150     {-1./12., 0., 1./12.},
00151     { -1./3., 0., 1./3.},
00152     {-1./12., 0., 1./12.}
00153   };
00154   
00155 #endif
00156   
00157   
00158   // Generic interface for evaluation to all univariate basis functions
00159   inline double B(int k, double t) {
00160     if (k == 0)
00161       return B_0(t);
00162     else if (k == 1)
00163       return B_1(t);
00164     else if (k == 2)
00165       return B_2(t);
00166     else
00167       return B_3(t);
00168   }
00169   
00170   // Generic interface to first derivatives
00171   inline double dB(int k, double t) {
00172     if (k == 0)
00173       return dB_0(t);
00174     else if (k == 1)
00175       return dB_1(t);
00176     else if (k == 2)
00177       return dB_2(t);
00178     else
00179       return dB_3(t);
00180   }
00181   
00182   // Lagt til, Vegard
00183   // Generic interface to second derivatives
00184   
00185   inline double ddB(int k, double t) {
00186     if (k == 0)
00187       return ddB_0(t);
00188     else if (k == 1)
00189       return ddB_1(t);
00190     else if (k == 2)
00191       return ddB_2(t);
00192     else
00193       return ddB_3(t);
00194   }
00195   
00196   // Evaluation of a bivariate tensor product basis function
00197   inline double w(int k, int l, double s, double t) {
00198     return B(k,s)*B(l,t);
00199   }
00200   
00201   // s,t \in [0,1) (but special on gridlines m and n)
00202   // i,j \in [-1, ???
00203   inline void ijst(int m, int n, double uc, double vc, int& i, int& j, double& s, double& t) {
00204     //int i = std::min((int)uc - 1, m-2);
00205     //int j = std::min((int)vc - 1, n-2);
00206     
00207 #ifdef  UNIFORM_CUBIC_C1_SPLINES
00208     i = 2*((int)uc) - 1;
00209     j = 2*((int)vc) - 1;
00210 #else
00211     i = (int)uc - 1;
00212     j = (int)vc - 1;
00213 #endif
00214     
00215     s = uc - floor(uc);
00216     t = vc - floor(vc);
00217     
00218     // adjust for x or y on gridlines m and n (since impl. has 0 <= x <= m and 0 <= y <= n 
00219 #ifdef  UNIFORM_CUBIC_C1_SPLINES
00220     if (i == 2*m-1) {
00221       i-=2;
00222       s = 1;
00223     }
00224     if (j == 2*n-1) {
00225       j-=2;
00226       t = 1;
00227     }
00228 #else
00229     if (i == m-1) {
00230       i--;
00231       s = 1;
00232     }
00233     if (j == n-1) {
00234       j--;
00235       t = 1;
00236     }
00237 #endif
00238   }
00239 
00240 inline void WKL(double s, double t, double w_kl[4][4])
00241 {
00242     double Bs0 = B_0(s); double Bt0 = B_0(t);
00243     double Bs1 = B_1(s); double Bt1 = B_1(t);
00244     double Bs2 = B_2(s); double Bt2 = B_2(t);
00245     double Bs3 = B_3(s); double Bt3 = B_3(t);
00246 
00247     w_kl[0][0] = Bs0 * Bt0;
00248     w_kl[0][1] = Bs0 * Bt1;
00249     w_kl[0][2] = Bs0 * Bt2;
00250     w_kl[0][3] = Bs0 * Bt3;     
00251 
00252     w_kl[1][0] = Bs1 * Bt0;      
00253     w_kl[1][1] = Bs1 * Bt1;     
00254     w_kl[1][2] = Bs1 * Bt2;     
00255     w_kl[1][3] = Bs1 * Bt3;      
00256 
00257     w_kl[2][0] = Bs2 * Bt0;     
00258     w_kl[2][1] = Bs2 * Bt1;
00259     w_kl[2][2] = Bs2 * Bt2;     
00260     w_kl[2][3] = Bs2 * Bt3;     
00261 
00262     w_kl[3][0] = Bs3 * Bt0;     
00263     w_kl[3][1] = Bs3 * Bt1;     
00264     w_kl[3][2] = Bs3 * Bt2;     
00265     w_kl[3][3] = Bs3 * Bt3;     
00266 
00267 }
00268   
00269 inline void WKLandSum2(double s, double t, double w_kl[4][4], double& sum_w_ab2) 
00270 {
00271     sum_w_ab2 = 0.0;
00272     double Bs0 = B_0(s); double Bt0 = B_0(t);
00273     double Bs1 = B_1(s); double Bt1 = B_1(t);
00274     double Bs2 = B_2(s); double Bt2 = B_2(t);
00275     double Bs3 = B_3(s); double Bt3 = B_3(t);
00276 
00277     double tmp;
00278 
00279     // unrolled by Odd Andersen 15. dec. 2003, for optimization
00280     tmp = Bs0 * Bt0; w_kl[0][0] = tmp; sum_w_ab2 += tmp * tmp;
00281     tmp = Bs0 * Bt1; w_kl[0][1] = tmp; sum_w_ab2 += tmp * tmp;
00282     tmp = Bs0 * Bt2; w_kl[0][2] = tmp; sum_w_ab2 += tmp * tmp;
00283     tmp = Bs0 * Bt3; w_kl[0][3] = tmp; sum_w_ab2 += tmp * tmp;
00284 
00285     tmp = Bs1 * Bt0; w_kl[1][0] = tmp; sum_w_ab2 += tmp * tmp;
00286     tmp = Bs1 * Bt1; w_kl[1][1] = tmp; sum_w_ab2 += tmp * tmp;
00287     tmp = Bs1 * Bt2; w_kl[1][2] = tmp; sum_w_ab2 += tmp * tmp;
00288     tmp = Bs1 * Bt3; w_kl[1][3] = tmp; sum_w_ab2 += tmp * tmp;
00289 
00290     tmp = Bs2 * Bt0; w_kl[2][0] = tmp; sum_w_ab2 += tmp * tmp;
00291     tmp = Bs2 * Bt1; w_kl[2][1] = tmp; sum_w_ab2 += tmp * tmp;
00292     tmp = Bs2 * Bt2; w_kl[2][2] = tmp; sum_w_ab2 += tmp * tmp;
00293     tmp = Bs2 * Bt3; w_kl[2][3] = tmp; sum_w_ab2 += tmp * tmp;
00294 
00295     tmp = Bs3 * Bt0; w_kl[3][0] = tmp; sum_w_ab2 += tmp * tmp;
00296     tmp = Bs3 * Bt1; w_kl[3][1] = tmp; sum_w_ab2 += tmp * tmp;
00297     tmp = Bs3 * Bt2; w_kl[3][2] = tmp; sum_w_ab2 += tmp * tmp;
00298     tmp = Bs3 * Bt3; w_kl[3][3] = tmp; sum_w_ab2 += tmp * tmp;
00299 
00300 //     int k,l;
00301 //     sum_w_ab2 = 0.0; 
00302 //     for (k = 0; k <= 3; k++) {
00303 //      for (l = 0; l <=3; l++) {
00304 //          double tmp = w(k, l, s, t);
00305 //          w_kl[k][l] = tmp;
00306 //          sum_w_ab2 += (tmp*tmp); 
00307 //      }
00308 //     }
00309 }
00310     
00311   // for check, should give unity
00312   // inline double sumWKL(double s, double t) {
00313   //  int k,l;
00314   //  double sum_w_ab = 0.0; 
00315   //  for (k = 0; k <= 3; k++) {
00316   //    for (l = 0; l <=3; l++) {
00317   //      sum_w_ab += w(k, l, s, t);
00318   //    }
00319   //  }
00320   //  return sum_w_ab;
00321   //}
00322   
00323   // -------------------------------------------------------------------------
00324   // Refinement (The Oslo algorithm)
00325   // Generic implementation for functional and parametric case
00326   // There are 4 different configurations of vertices in the refined lattice:
00327   
00328   // For the uniform bicubic C2 case
00329   
00330   // 1) On an existing vertex
00331   template <class Type>
00332     inline Type phi_2i_2j(const GenMatrix<Type>& mat, int i, int j) {
00333     return 1.0/64.0*( mat(i-1,j-1) + mat(i-1,j+1) + mat(i+1,j-1) + mat(i+1,j+1)
00334       +6.0*(mat(i-1,j) + mat(i,j-1) + mat(i,j+1) + mat(i+1,j)) + 36.0*mat(i,j) );
00335   }
00336   
00337   // 2) On an existing vertical line
00338   template <class Type>
00339     inline Type phi_2i_2jPluss1(const GenMatrix<Type>& mat, int i, int j) {
00340     return 1.0/16.0*( mat(i-1,j) + mat(i-1,j+1) + mat(i+1,j) + mat(i+1,j+1)
00341       +6.0*(mat(i,j) + mat(i,j+1)) );
00342   }
00343   
00344   // 3) On an existing horizontal line
00345   template <class Type>
00346     inline Type phi_2iPlus1_2j(const GenMatrix<Type>& mat, int i, int j) {
00347     return 1.0/16.0*( mat(i,j-1) + mat(i,j+1) + mat(i+1,j-1) + mat(i+1,j+1)
00348       +6.0*(mat(i,j) + mat(i+1,j)) );
00349   }
00350   
00351   // 4) a new crossing in both directions
00352   template <class Type>
00353     inline Type phi_2iPlus1_2jPlus1(const GenMatrix<Type>& mat, int i, int j) {
00354     return 1.0/4.0*( mat(i,j) + mat(i,j+1) + mat(i+1,j) + mat(i+1,j+1) );
00355   }
00356   
00357   
00358   // The Oslo Algorithm For the uniform bicubic C1 case 
00359   // There are 16 configurations:
00360   // ----------------------------
00361   //
00362   //      |       :
00363   //      |       :
00364   //      |       :
00365   //.....9|13...15:4...........
00366   //     7|11    3:16
00367   //      |       :
00368   //      |       :
00369   //_____5|2____12:14__________
00370   //     1|6     8:10
00371   //      |       :
00372   //      |       :
00373   //      |       :
00374   
00375   // !!!! int i, int j denotes (2i) and (2j) in the coefficient matrix PHI !!!
00376   // 1) SW of an existing grid point
00377   template <class Type>
00378     inline Type phi_4iMin1_4jMin1(const GenMatrix<Type>& mat, int i, int j) {
00379     return 1.0/16.0*( 9.0*mat(i-1,j-1) + 3.0*(mat(i-1,j) + mat(i,j-1)) + mat(i,j) );
00380   }
00381   
00382   // 2) NE of an existing grid point
00383   template <class Type>
00384     inline Type phi_4i_4j(const GenMatrix<Type>& mat, int i, int j) {
00385     return 1.0/16.0*( mat(i-1,j-1) + 3.0*(mat(i-1,j) + mat(i,j-1)) + 9.0*mat(i,j) );
00386   }
00387   
00388   // 3) SW of a new grid point
00389   template <class Type>
00390     inline Type phi_4iPlus1_4jPlus1(const GenMatrix<Type>& mat, int i, int j) {
00391     return 1.0/64.0*( mat(i-1,j-1) + 5.0*(mat(i-1,j) + mat(i,j-1)) + 25.0*mat(i,j) + 2.0*(mat(i-1,j+1) + mat(i+1,j-1)) + 10.0*(mat(i+1,j) + mat(i,j+1)) + 4.0*mat(i+1,j+1) );
00392   }
00393   
00394   // 4) NE of a new grid point
00395   template <class Type>
00396     inline Type phi_4iPlus2_4jPlus2(const GenMatrix<Type>& mat, int i, int j) {
00397     return 1.0/64.0*( 4.0*mat(i,j) + 5.0*mat(i+2,j+1) + 2*(mat(i+2,j) + mat(i,j+2)) + mat(i+2,j+2) + 25*mat(i+1,j+1) + 10.0*(mat(i+1,j) + mat(i,j+1)) + 5.0*mat(i+1,j+2) );
00398   }
00399   
00400   // 5) NW of an existing grid point
00401   template <class Type>
00402     inline Type phi_4iMin1_4j(const GenMatrix<Type>& mat, int i, int j) {
00403     return 1.0/16.0*( 3.0*(mat(i-1,j-1) + mat(i,j)) + 9.0*mat(i-1,j) + mat(i,j-1) );
00404   }
00405   
00406   // 6) SE of an existing grid point
00407   template <class Type>
00408     inline Type phi_4i_4jMin1(const GenMatrix<Type>& mat, int i, int j) {
00409     return 1.0/16.0*( 3.0*(mat(i-1,j-1) + mat(i,j)) + mat(i-1,j) + 9.0*mat(i,j-1) );
00410   }
00411   
00412   // 7) SW of a new grid point on an existing vertical line
00413   template <class Type>
00414     inline Type phi_4iMin1_4jPlus1(const GenMatrix<Type>& mat, int i, int j) {
00415     return 1.0/32.0*( 3.0*mat(i-1,j-1) + 15.0*mat(i-1,j) + mat(i,j-1) + 5.0*mat(i,j) + 2.0*mat(i,j+1) + 6.0*mat(i-1,j+1) );
00416   }
00417   
00418   // 8) SW of a new grid point on an existing horizontal line
00419   template <class Type>
00420     inline Type phi_4iPlus1_4jMin1(const GenMatrix<Type>& mat, int i, int j) {
00421     return 1.0/32.0*( 3.0*mat(i-1,j-1) + mat(i-1,j) + 15*mat(i,j-1) + 5.0*mat(i,j) + 2.0*mat(i+1,j) + 6.0*mat(i+1,j-1) );
00422   }
00423   
00424   // 9) NW of a new grid point on an existing vertical line
00425   template <class Type>
00426     inline Type phi_4iMin1_4jPlus2(const GenMatrix<Type>& mat, int i, int j) {
00427     return 1.0/32.0*( 6.0*mat(i-1,j) + 2.0*mat(i,j) + 15*mat(i-1,j+1) + 5.0*mat(i,j+1) + mat(i,j+2) + 3.0*mat(i-1,j+2) );
00428   }
00429   
00430   // 10) SE of a new grid point on an existing horizontal line
00431   template <class Type>
00432     inline Type phi_4iPlus2_4jMin1(const GenMatrix<Type>& mat, int i, int j) {
00433     return 1.0/32.0*( 6.0*mat(i,j-1) + 2.0*mat(i,j) + mat(i+2,j) + 15.0*mat(i+1,j-1) + 5.0*mat(i+1,j) + 3.0*mat(i+2,j-1) );
00434   }
00435   
00436   // 11) SE of a new grid point on an existing vertical line
00437   template <class Type>
00438     inline Type phi_4i_4jPlus1(const GenMatrix<Type>& mat, int i, int j) {
00439     return 1.0/32.0*( mat(i-1,j-1) + 5.0*mat(i-1,j) + 3.0*mat(i,j-1) + 15.0*mat(i,j) + 2.0*mat(i-1,j+1) + 6.0*mat(i,j+1) );
00440   }
00441   
00442   // 12) NW of a new grid point on an existing horizontal line
00443   template <class Type>
00444     inline Type phi_4iPlus1_4j(const GenMatrix<Type>& mat, int i, int j) {
00445     return 1.0/32.0*( mat(i-1,j-1) + 3.0*mat(i-1,j) + 5.0*mat(i,j-1) + 15.0*mat(i,j) + 2.0*mat(i+1,j-1) + 6.0*mat(i+1,j) );
00446   }
00447   
00448   // 13) NE of a new grid point on an existing vertical line
00449   template <class Type>
00450     inline Type phi_4i_4jPlus2(const GenMatrix<Type>& mat, int i, int j) {
00451     return 1.0/32.0*( 2.0*mat(i-1,j) + 6.0*mat(i,j) + 5.0*mat(i-1,j+1) + 15.0*mat(i,j+1) + mat(i-1,j+2) + 3.0*mat(i,j+2) );
00452   }
00453   
00454   // 14) NE of a new grid point on an existing horizontal line
00455   template <class Type>
00456     inline Type phi_4iPlus2_4j(const GenMatrix<Type>& mat, int i, int j) {
00457     return 1.0/32.0*( 2.0*mat(i,j-1) + 6.0*mat(i,j) + 5.0*mat(i+1,j-1) + 15.0*mat(i+1,j) + mat(i+2,j-1) + 3.0*mat(i+2,j) );
00458   }
00459   
00460   // 15) NW of a new grid point
00461   template <class Type>
00462     inline Type phi_4iPlus1_4jPlus2(const GenMatrix<Type>& mat, int i, int j) {
00463     return 1.0/64.0*( 2.0*(mat(i-1,j) + mat(i+1,j+2)) + 10.0*(mat(i,j) + mat(i+1,j+1)) + 5.0*(mat(i-1,j+1) + mat(i,j+2)) + 25.0*mat(i,j+1) + 4.0*mat(i+1,j) + mat(i-1,j+2) );
00464   }
00465   
00466   // 16) SE of a new grid point
00467   template <class Type>
00468     inline Type phi_4iPlus2_4jPlus1(const GenMatrix<Type>& mat, int i, int j) {
00469     return 1.0/64.0*( 2.0*(mat(i,j-1) + mat(i+2,j+1)) + 10.0*(mat(i,j) + mat(i+1,j+1)) + 5.0*(mat(i+1,j-1) + mat(i+2,j)) + 4.0*mat(i,j+1) + 25.0*mat(i+1,j) + mat(i+2,j-1) );
00470   }
00471   
00472   // Refinement (Similar to the Oslo algorithm)
00473   void refineCoeffsC1(const GenMatrix<UCBspl_real>& PSI, GenMatrix<UCBspl_real>& PSIprime);
00474   void refineCoeffsC2(const GenMatrix<UCBspl_real>& PSI, GenMatrix<UCBspl_real>& PSIprime);
00475 
00476   // Restriction (This is not used by Multilvel B-splines) "Transposed" of the refinement operator
00477   bool restrictCoeffsC2(const GenMatrix<UCBspl_real>& rr, GenMatrix<UCBspl_real>& r);
00478 
00479 }; // end namespace
00480 
00481 #endif  

Generated on Wed Nov 28 12:27:29 2007 for LSMG by  doxygen 1.5.1