00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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_JACOBIAN_H 00024 #define O2SCL_JACOBIAN_H 00025 00026 #include <string> 00027 #include <o2scl/collection.h> 00028 #include <o2scl/omatrix_tlate.h> 00029 #include <o2scl/mm_funct.h> 00030 #include <o2scl/gsl_deriv.h> 00031 00032 #ifndef DOXYGENP 00033 namespace o2scl { 00034 #endif 00035 00036 /** 00037 \brief Base for a square Jacobian where J is computed at x given y=f(x) 00038 00039 Compute 00040 \f[ 00041 J_(i,j) = \frac{\partial f_i}{\partial x_j} 00042 \f] 00043 00044 The \c vec_t objects in operator() could have been written to be 00045 \c const, but they are not \c const so that they can be 00046 used as temporary workspace. They are restored to their 00047 original values before operator() exits. 00048 00049 */ 00050 template<class param_t, class vec_t=ovector_view, 00051 class mat_t=omatrix_view> class jac_funct { 00052 00053 public: 00054 00055 jac_funct() {} 00056 00057 virtual ~jac_funct() {} 00058 00059 /** \brief The operator() 00060 */ 00061 virtual int operator()(size_t nv, vec_t &x, 00062 vec_t &y, mat_t &j, param_t &pa) { 00063 set_err_ret("Missing base in mm_funct::operator().",gsl_nobase); 00064 } 00065 00066 #ifndef DOXYGENP 00067 00068 private: 00069 00070 jac_funct(const jac_funct &); 00071 jac_funct& operator=(const jac_funct&); 00072 00073 #endif 00074 00075 }; 00076 00077 /** \brief Function pointer to jacobian 00078 */ 00079 template<class param_t, class vec_t=ovector_view, 00080 class mat_t=omatrix_view> class jac_funct_fptr : 00081 public jac_funct<param_t,vec_t,mat_t> { 00082 00083 public: 00084 00085 /** \brief Specify the function pointer 00086 */ 00087 jac_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &y, 00088 mat_t &j, param_t &pa)) { 00089 fptr=fp; 00090 } 00091 00092 virtual ~jac_funct_fptr(); 00093 00094 /** \brief The operator() 00095 */ 00096 virtual int operator()(size_t nv, vec_t &x, 00097 vec_t &y, mat_t &j, param_t &pa) { 00098 return fptr(nv,x,y,j,pa); 00099 } 00100 00101 #ifndef DOXYGENP 00102 00103 protected: 00104 00105 jac_funct_fptr() {}; 00106 00107 /// Desc 00108 int (*fptr)(size_t nv, vec_t &x, vec_t &y, 00109 mat_t &j, param_t &pa); 00110 00111 private: 00112 00113 jac_funct_fptr(const jac_funct_fptr &); 00114 jac_funct_fptr& operator=(const jac_funct_fptr&); 00115 00116 #endif 00117 00118 }; 00119 00120 /** \brief Member function pointer to a Jacobian 00121 */ 00122 template <class tclass, class param_t, class vec_t=ovector_view, 00123 class mat_t=omatrix_view> class jac_funct_mfptr : 00124 public jac_funct<param_t,vec_t,mat_t> { 00125 00126 public: 00127 00128 /** \brief Specify the member function pointer 00129 */ 00130 jac_funct_mfptr(tclass *tp, int (tclass::*fp) 00131 (size_t nv, vec_t &x, vec_t &y, 00132 mat_t &j, param_t &pa)) { 00133 tptr=tp; 00134 fptr=fp; 00135 } 00136 00137 virtual ~jac_funct_mfptr() {}; 00138 00139 /** \brief The operator() 00140 */ 00141 virtual int operator()(size_t nv, vec_t &x, 00142 vec_t &y, mat_t &j, param_t &pa) { 00143 return (*tptr.*fptr)(nv,x,y,j,pa); 00144 } 00145 00146 #ifndef DOXYGEN_INTERNAL 00147 00148 protected: 00149 00150 /// Desc 00151 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y, 00152 mat_t &j, param_t &pa); 00153 00154 /// Desc 00155 tclass *tptr; 00156 00157 #endif 00158 00159 #ifndef DOXYGENP 00160 00161 private: 00162 00163 jac_funct_mfptr(const jac_funct_mfptr &); 00164 jac_funct_mfptr& operator=(const jac_funct_mfptr&); 00165 00166 #endif 00167 00168 }; 00169 00170 /** \brief Base for providing a numerical jacobian 00171 */ 00172 template<class param_t, class func_t, class vec_t=ovector_view, 00173 class mat_t=omatrix_view> 00174 class jacobian : public jac_funct<param_t,vec_t,mat_t> { 00175 public: 00176 00177 jacobian() { 00178 }; 00179 00180 virtual ~jacobian() {}; 00181 00182 /// Set the function to compute the Jacobian of 00183 virtual int set_function(func_t &f) { 00184 func=&f; 00185 return 0; 00186 } 00187 00188 /** \brief The operator() 00189 */ 00190 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00191 mat_t &j, param_t &pa) { 00192 return 0; 00193 } 00194 00195 #ifndef DOXYGEN_INTERNAL 00196 00197 protected: 00198 00199 /// A pointer to the user-specified function 00200 func_t *func; 00201 00202 private: 00203 00204 jacobian(const jacobian &); 00205 jacobian& operator=(const jacobian&); 00206 00207 #endif 00208 00209 }; 00210 00211 /** 00212 \brief Simple automatic Jacobian 00213 00214 This simple routine is nearly equivalent to GSL as given in \c 00215 multiroots/fdjac.c. It has an additional test to ensure that the 00216 finite-differencing stepsize does not vanish, and returns an 00217 error if the Jacobian is singular. To obtain the GSL behavior, 00218 set \ref epsrel to \c GSL_SQRT_DBL_EPSILON and set epsmin to 00219 zero. 00220 00221 This class does not separately check the vector and matrix sizes 00222 to ensure they are commensurate. 00223 00224 \todo Double check that this class works with arrays 00225 */ 00226 template<class param_t, class func_t, class vec_t=ovector_view, 00227 class mat_t=omatrix_view, class alloc_vec_t=ovector, 00228 class alloc_t=ovector_alloc> class simple_jacobian : 00229 public jacobian<param_t,func_t,vec_t,mat_t> { 00230 00231 public: 00232 00233 simple_jacobian() { 00234 epsrel=1.0e-4; 00235 epsmin=1.0e-15; 00236 } 00237 00238 /** \brief The relative stepsize for finite-differencing 00239 (default \f$ 10^{-4} \f$ ) 00240 */ 00241 double epsrel; 00242 00243 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00244 double epsmin; 00245 00246 /// For memory allocation 00247 alloc_t ao; 00248 00249 /** \brief The operator() 00250 */ 00251 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00252 mat_t &jac, param_t &pa) { 00253 00254 size_t i,j; 00255 double h,temp; 00256 alloc_vec_t f; 00257 bool success=true; 00258 00259 ao.allocate(f,nv); 00260 00261 for (j=0;j<nv;j++) { 00262 00263 h=epsrel*fabs(x[j]); 00264 if (fabs(h)<=epsmin) h=epsrel; 00265 00266 x[j]+=h; 00267 (*this->func)(nv,x,f,pa); 00268 x[j]-=h; 00269 00270 bool nonzero=false; 00271 for (i=0;i<nv;i++) { 00272 temp=(f[i]-y[i])/h; 00273 if (temp!=0.0) nonzero=true; 00274 jac[i][j]=temp; 00275 } 00276 if (nonzero==false) success=false; 00277 } 00278 00279 ao.free(f); 00280 00281 if (success==false) { 00282 set_err_ret("At least one row of the Jacobian is zero.",gsl_efailed); 00283 } 00284 return 0; 00285 } 00286 }; 00287 00288 /** 00289 \brief A direct calculation of the jacobian using a \ref deriv object 00290 00291 Note that it is sometimes wasteful to use this Jacobian in a 00292 root-finding routine and using more approximate Jacobians is 00293 more efficient. 00294 */ 00295 template<class param_t, class func_t, class vec_t=ovector_view, 00296 class mat_t=omatrix_view> class exact_jacobian : 00297 public jacobian<param_t,func_t,vec_t,mat_t> { 00298 00299 public: 00300 00301 exact_jacobian() { 00302 def_deriv.h=1.0e-4; 00303 dptr=&def_deriv; 00304 } 00305 00306 /// Desc 00307 typedef struct { 00308 size_t nv, xj, yi; 00309 vec_t *x; 00310 vec_t *y; 00311 param_t *pa; 00312 } ej_parms; 00313 00314 /// The default derivative object 00315 gsl_deriv<ej_parms,funct<ej_parms> > def_deriv; 00316 00317 /// Set the derivative object 00318 int set_deriv(deriv<ej_parms,funct<ej_parms> > &de) { 00319 dptr=&de; 00320 return 0; 00321 } 00322 00323 /** \brief The operator() 00324 */ 00325 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00326 mat_t &jac, param_t &pa) { 00327 size_t i,j; 00328 double h,temp; 00329 00330 ej_parms ejp; 00331 ejp.nv=nv; 00332 ejp.x=&x; 00333 ejp.y=&y; 00334 ejp.pa=&pa; 00335 00336 funct_mfptr<exact_jacobian,ej_parms> dfnp(this,&exact_jacobian::dfn); 00337 00338 for (j=0;j<nv;j++) { 00339 ejp.xj=j; 00340 for (i=0;i<nv;i++) { 00341 ejp.yi=i; 00342 double tmp=(*ejp.x)[j]; 00343 jac[i][j]=dptr->calc(tmp,ejp,dfnp); 00344 (*ejp.x)[j]=tmp; 00345 } 00346 } 00347 00348 return 0; 00349 } 00350 00351 00352 #ifndef DOXYGEN_INTERNAL 00353 00354 protected: 00355 00356 /// Desc 00357 deriv<ej_parms,funct<ej_parms> > *dptr; 00358 00359 /// Desc 00360 int dfn(double x, double &y, ej_parms &ejp) { 00361 (*ejp.x)[ejp.xj]=x; 00362 (*this->func)(ejp.nv,*ejp.x,*ejp.y,*ejp.pa); 00363 y=(*ejp.y)[ejp.yi]; 00364 return 0; 00365 } 00366 00367 #endif 00368 00369 }; 00370 00371 #ifndef DOXYGENP 00372 } 00373 #endif 00374 00375 #endif
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