00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_QUAD_INTP_H 00024 #define O2SCL_QUAD_INTP_H 00025 00026 #include <iostream> 00027 #include <string> 00028 #include <cmath> 00029 #include <map> 00030 #include <gsl/gsl_linalg.h> 00031 #include <o2scl/err_hnd.h> 00032 #include <o2scl/ovector_tlate.h> 00033 00034 #ifndef DOXYGENP 00035 namespace o2scl { 00036 #endif 00037 00038 /** 00039 \brief Interpolate a function of two independent variables with 00040 a quadratic polynomial 00041 00042 This is a "conic-section" interpolation for two 00043 dimensions, using the function 00044 \f[ 00045 z(x,y) = a_1 x^2 + a_2 x y + a_3 y^2 + a_4 x + a_5 y + a_6 00046 \f] 00047 For a set of data \f${x_i,y_i,z_i}\f$, a value of z is predicted 00048 given a value of x and y. This is done by finding the conic 00049 section obeying the above relation that goes through six closest 00050 points in the data set. 00051 00052 This procedure does not always succeed. It fails when the 00053 6 closest points are somehow degenerate, for example, if they 00054 are all colinear. 00055 00056 The vector and matrix types can be any types which have 00057 suitably defined functions \c operator[]. 00058 00059 There is no caching so the numeric values of the data may be 00060 freely changed between calls to interp(). 00061 00062 \bug This class doesn't seem to work at present. 00063 */ 00064 template<class vec_t, class mat_t> class quad_intp { 00065 public: 00066 00067 quad_intp() { 00068 data_set=false; 00069 } 00070 00071 typedef struct { 00072 int i; 00073 double c; 00074 } point; 00075 00076 int compare(const void *x, const void *y) { 00077 point *p=(point *)x; 00078 point *q=(point *)y; 00079 return (p->c)>(q->c); 00080 } 00081 00082 /** 00083 \brief Initialize the data for the quad interpolation 00084 */ 00085 int set_data(size_t n_points, vec_t &x, vec_t &y, 00086 size_t n_dat, mat_t &dat) { 00087 if (n_points<6) { 00088 set_err_ret("Must provide at least six points in set_data()", 00089 gsl_efailed); 00090 } 00091 np=n_points; 00092 nd=n_dat; 00093 ux=&x; 00094 uy=&y; 00095 udat=&dat; 00096 data_set=true; 00097 return 0; 00098 } 00099 00100 /** 00101 \brief Perform the quadratic interpolation 00102 00103 It is assumed that \c ip is properly allocated beforehand. 00104 */ 00105 int interp(double x, double y, vec_t &ip) { 00106 int i, j, mat_ret=0; 00107 00108 if (data_set==false) { 00109 set_err("Data not set in quad_intp::interp().",gsl_einval); 00110 return gsl_einval; 00111 } 00112 if (ip.is_owner()==false) { 00113 set_err("Provided ovector does not own its data. Proceeding anyway.", 00114 gsl_einval); 00115 } 00116 00117 std::map<double,int> pmap; 00118 for (i=0;i<np;i++) { 00119 pmap.insert(make_pair(sqrt(pow(x-(*ux)[i],2.0)+ 00120 pow(y-(*uy)[i],2.0)),i)); 00121 } 00122 std::map<double,int>::iterator pit; 00123 00124 gsl_matrix *gm=gsl_matrix_alloc(6,6); 00125 gsl_vector *gx=gsl_vector_alloc(6), *gb=gsl_vector_alloc(6); 00126 00127 for(j=0;j<nd;j++) { 00128 00129 pit=pmap.begin(); 00130 for(i=0;i<6;i++) { 00131 gsl_matrix_set(gm,i,0,(*ux)[pit->second]*(*ux)[pit->second]); 00132 gsl_matrix_set(gm,i,1,(*ux)[pit->second]*(*uy)[pit->second]); 00133 gsl_matrix_set(gm,i,2,(*uy)[pit->second]*(*uy)[pit->second]); 00134 gsl_matrix_set(gm,i,3,(*ux)[pit->second]); 00135 gsl_matrix_set(gm,i,4,(*uy)[pit->second]); 00136 gsl_matrix_set(gm,i,5,1.0); 00137 gsl_vector_set(gb,i,(*(udat[j]))[i]); 00138 pit++; 00139 } 00140 int ret=gsl_linalg_HH_solve(gm,gb,gx); 00141 if (ret!=0) mat_ret=ret; 00142 ip[j]=gsl_vector_get(gx,0)*x*x+ 00143 gsl_vector_get(gx,1)*x*y+ 00144 gsl_vector_get(gx,2)*y*y+ 00145 gsl_vector_get(gx,3)*x+ 00146 gsl_vector_get(gx,4)*y+ 00147 gsl_vector_get(gx,5); 00148 } 00149 00150 if (mat_ret!=0) { 00151 add_err("Matrix solver failed in quad_intp::interp().", 00152 gsl_efailed); 00153 } 00154 00155 gsl_matrix_free(gm); 00156 gsl_vector_free(gx); 00157 gsl_vector_free(gb); 00158 00159 return mat_ret; 00160 } 00161 00162 #ifndef DOXYGEN_INTERNAL 00163 00164 protected: 00165 00166 /// The number of grid points 00167 int np; 00168 /// The number of functions 00169 int nd; 00170 /// The x-values 00171 vec_t *ux; 00172 /// The y-values 00173 vec_t *uy; 00174 /// The data 00175 mat_t *udat; 00176 /// True if the data has been given by the user 00177 bool data_set; 00178 00179 // Swap points 1 and 2 00180 int swap(int &i1, double &c1, int &i2, double &c2); 00181 00182 #endif 00183 00184 }; 00185 00186 #ifndef DOXYGENP 00187 } 00188 #endif 00189 00190 #endif 00191 00192 00193
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page