00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 #include <o2scl/columnify.h> 00032 00033 #ifndef DOXYGENP 00034 namespace o2scl { 00035 #endif 00036 00037 /** 00038 \brief Base for a square Jacobian where J is 00039 computed at x given y=f(x) [abstract base] 00040 00041 Compute 00042 \f[ 00043 J_{ij} = \frac{\partial f_i}{\partial x_j} 00044 \f] 00045 00046 The \c vec_t objects in operator() could have been written to be 00047 \c const, but they are not \c const so that they can be used as 00048 temporary workspace. They are typically restored to their 00049 original values before operator() exits. 00050 00051 For Jacobian functions with C-style arrays and matrices, use 00052 the corresponding children of \ref jac_vfunct . 00053 00054 */ 00055 template<class param_t, class vec_t=ovector_base, 00056 class mat_t=omatrix_base> class jac_funct { 00057 00058 public: 00059 00060 jac_funct() {} 00061 00062 virtual ~jac_funct() {} 00063 00064 /** \brief The operator() 00065 */ 00066 virtual int operator()(size_t nv, vec_t &x, 00067 vec_t &y, mat_t &j, param_t &pa)=0; 00068 00069 #ifndef DOXYGENP 00070 00071 private: 00072 00073 jac_funct(const jac_funct &); 00074 jac_funct& operator=(const jac_funct&); 00075 00076 #endif 00077 00078 }; 00079 00080 /** \brief Function pointer to jacobian 00081 */ 00082 template<class param_t, class vec_t=ovector_base, 00083 class mat_t=omatrix_base> class jac_funct_fptr : 00084 public jac_funct<param_t,vec_t,mat_t> { 00085 00086 public: 00087 00088 /** \brief Specify the function pointer 00089 */ 00090 jac_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &y, 00091 mat_t &j, param_t &pa)) { 00092 fptr=fp; 00093 } 00094 00095 virtual ~jac_funct_fptr(); 00096 00097 /** \brief The operator() 00098 */ 00099 virtual int operator()(size_t nv, vec_t &x, 00100 vec_t &y, mat_t &j, param_t &pa) { 00101 return fptr(nv,x,y,j,pa); 00102 } 00103 00104 #ifndef DOXYGENP 00105 00106 protected: 00107 00108 jac_funct_fptr() {}; 00109 00110 /// Function pointer 00111 int (*fptr)(size_t nv, vec_t &x, vec_t &y, 00112 mat_t &j, param_t &pa); 00113 00114 private: 00115 00116 jac_funct_fptr(const jac_funct_fptr &); 00117 jac_funct_fptr& operator=(const jac_funct_fptr&); 00118 00119 #endif 00120 00121 }; 00122 00123 /** \brief Member function pointer to a Jacobian 00124 */ 00125 template <class tclass, class param_t, class vec_t=ovector_base, 00126 class mat_t=omatrix_base> class jac_funct_mfptr : 00127 public jac_funct<param_t,vec_t,mat_t> { 00128 00129 public: 00130 00131 /** \brief Specify the member function pointer 00132 */ 00133 jac_funct_mfptr(tclass *tp, int (tclass::*fp) 00134 (size_t nv, vec_t &x, vec_t &y, 00135 mat_t &j, param_t &pa)) { 00136 tptr=tp; 00137 fptr=fp; 00138 } 00139 00140 virtual ~jac_funct_mfptr() {}; 00141 00142 /** \brief The operator() 00143 */ 00144 virtual int operator()(size_t nv, vec_t &x, 00145 vec_t &y, mat_t &j, param_t &pa) { 00146 return (*tptr.*fptr)(nv,x,y,j,pa); 00147 } 00148 00149 #ifndef DOXYGEN_INTERNAL 00150 00151 protected: 00152 00153 /// Member function pointer 00154 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y, 00155 mat_t &j, param_t &pa); 00156 00157 /// Class pointer 00158 tclass *tptr; 00159 00160 #endif 00161 00162 #ifndef DOXYGENP 00163 00164 private: 00165 00166 jac_funct_mfptr(const jac_funct_mfptr &); 00167 jac_funct_mfptr& operator=(const jac_funct_mfptr&); 00168 00169 #endif 00170 00171 }; 00172 00173 /** \brief Const member function pointer to a Jacobian 00174 */ 00175 template <class tclass, class param_t, class vec_t=ovector_base, 00176 class mat_t=omatrix_base> class jac_funct_cmfptr : 00177 public jac_funct<param_t,vec_t,mat_t> { 00178 00179 public: 00180 00181 /** \brief Specify the member function pointer 00182 */ 00183 jac_funct_cmfptr(tclass *tp, int (tclass::*fp) 00184 (size_t nv, vec_t &x, vec_t &y, 00185 mat_t &j, param_t &pa) const) { 00186 tptr=tp; 00187 fptr=fp; 00188 } 00189 00190 virtual ~jac_funct_cmfptr() {}; 00191 00192 /** \brief The operator() 00193 */ 00194 virtual int operator()(size_t nv, vec_t &x, 00195 vec_t &y, mat_t &j, param_t &pa) { 00196 return (*tptr.*fptr)(nv,x,y,j,pa); 00197 } 00198 00199 #ifndef DOXYGEN_INTERNAL 00200 00201 protected: 00202 00203 /// Member function pointer 00204 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y, 00205 mat_t &j, param_t &pa) const; 00206 00207 /// Class pointer 00208 tclass *tptr; 00209 00210 #endif 00211 00212 #ifndef DOXYGENP 00213 00214 private: 00215 00216 jac_funct_cmfptr(const jac_funct_cmfptr &); 00217 jac_funct_cmfptr& operator=(const jac_funct_cmfptr&); 00218 00219 #endif 00220 00221 }; 00222 00223 /** 00224 \brief Base for a square Jacobian where J is computed at x given 00225 y=f(x) with arrays [abstract base] 00226 00227 Compute 00228 \f[ 00229 J_{ij} = \frac{\partial f_i}{\partial x_j} 00230 \f] 00231 00232 The \c vec_t objects in operator() could have been written to be 00233 \c const, but they are not \c const so that they can be 00234 used as temporary workspace. They are restored to their 00235 original values before operator() exits. 00236 00237 */ 00238 template<class param_t, size_t nv> class jac_vfunct { 00239 00240 public: 00241 00242 jac_vfunct() {} 00243 00244 virtual ~jac_vfunct() {} 00245 00246 /** \brief The operator() 00247 */ 00248 virtual int operator()(size_t nv2, double x[nv], 00249 double y[nv], double j[nv][nv], param_t &pa)=0; 00250 00251 #ifndef DOXYGENP 00252 00253 private: 00254 00255 jac_vfunct(const jac_vfunct &); 00256 jac_vfunct& operator=(const jac_vfunct&); 00257 00258 #endif 00259 00260 }; 00261 00262 /** \brief Function pointer to jacobian with arrays 00263 */ 00264 template<class param_t, size_t nv> class jac_vfunct_fptr : 00265 public jac_vfunct<param_t,nv> { 00266 00267 public: 00268 00269 /** \brief Specify the function pointer 00270 */ 00271 jac_vfunct_fptr(int (*fp)(size_t nv2, double x[nv], double y[nv], 00272 double j[nv][nv], param_t &pa)) { 00273 fptr=fp; 00274 } 00275 00276 virtual ~jac_vfunct_fptr(); 00277 00278 /** \brief The operator() 00279 */ 00280 virtual int operator()(size_t nv2, double x[nv], 00281 double y[nv], double j[nv][nv], param_t &pa) { 00282 return fptr(nv2,x,y,j,pa); 00283 } 00284 00285 #ifndef DOXYGENP 00286 00287 protected: 00288 00289 jac_vfunct_fptr() {}; 00290 00291 /// Function pointer 00292 int (*fptr)(size_t nv2, double x[nv], double y[nv], 00293 double j[nv][nv], param_t &pa); 00294 00295 private: 00296 00297 jac_vfunct_fptr(const jac_vfunct_fptr &); 00298 jac_vfunct_fptr& operator=(const jac_vfunct_fptr&); 00299 00300 #endif 00301 00302 }; 00303 00304 /** \brief Member function pointer to a Jacobian with arrays 00305 */ 00306 template <class tclass, class param_t, size_t nv> class jac_vfunct_mfptr : 00307 public jac_vfunct<param_t,nv> { 00308 00309 public: 00310 00311 /** \brief Specify the member function pointer 00312 */ 00313 jac_vfunct_mfptr(tclass *tp, int (tclass::*fp) 00314 (size_t nv2, double x[nv], double y[nv], 00315 double j[nv][nv], param_t &pa)) { 00316 tptr=tp; 00317 fptr=fp; 00318 } 00319 00320 virtual ~jac_vfunct_mfptr() {}; 00321 00322 /** \brief The operator() 00323 */ 00324 virtual int operator()(size_t nv2, double x[nv], 00325 double y[nv], double j[nv][nv], param_t &pa) { 00326 return (*tptr.*fptr)(nv2,x,y,j,pa); 00327 } 00328 00329 #ifndef DOXYGEN_INTERNAL 00330 00331 protected: 00332 00333 /// Member function pointer 00334 int (tclass::*fptr)(size_t nv2, double x[nv], double y[nv], 00335 double j[nv][nv], param_t &pa); 00336 00337 /// Class pointer 00338 tclass *tptr; 00339 00340 #endif 00341 00342 #ifndef DOXYGENP 00343 00344 private: 00345 00346 jac_vfunct_mfptr(const jac_vfunct_mfptr &); 00347 jac_vfunct_mfptr& operator=(const jac_vfunct_mfptr&); 00348 00349 #endif 00350 00351 }; 00352 00353 /** \brief Const member function pointer to a Jacobian with arrays 00354 */ 00355 template <class tclass, class param_t, size_t nv> class jac_vfunct_cmfptr : 00356 public jac_vfunct<param_t,nv> { 00357 00358 public: 00359 00360 /** \brief Specify the member function pointer 00361 */ 00362 jac_vfunct_cmfptr(tclass *tp, int (tclass::*fp) 00363 (size_t nv2, double x[nv], double y[nv], 00364 double j[nv][nv], param_t &pa) const) { 00365 tptr=tp; 00366 fptr=fp; 00367 } 00368 00369 virtual ~jac_vfunct_cmfptr() {}; 00370 00371 /** \brief The operator() 00372 */ 00373 virtual int operator()(size_t nv2, double x[nv], 00374 double y[nv], double j[nv][nv], param_t &pa) { 00375 return (*tptr.*fptr)(nv2,x,y,j,pa); 00376 } 00377 00378 #ifndef DOXYGEN_INTERNAL 00379 00380 protected: 00381 00382 /// Member function pointer 00383 int (tclass::*fptr)(size_t nv2, double x[nv], double y[nv], 00384 double j[nv][nv], param_t &pa) const; 00385 00386 /// Class pointer 00387 tclass *tptr; 00388 00389 #endif 00390 00391 #ifndef DOXYGENP 00392 00393 private: 00394 00395 jac_vfunct_cmfptr(const jac_vfunct_cmfptr &); 00396 jac_vfunct_cmfptr& operator=(const jac_vfunct_cmfptr&); 00397 00398 #endif 00399 00400 }; 00401 00402 /** 00403 \brief Base for providing a numerical jacobian [abstract base] 00404 00405 This is provides a Jacobian which is numerically determined 00406 by differentiating a user-specified function (typically 00407 of the form of \ref mm_funct). 00408 */ 00409 template<class param_t, class func_t=mm_funct<param_t>, 00410 class vec_t=ovector_base, class mat_t=omatrix_base> 00411 class jacobian : public jac_funct<param_t,vec_t,mat_t> { 00412 public: 00413 00414 jacobian() { 00415 }; 00416 00417 virtual ~jacobian() {}; 00418 00419 /// Set the function to compute the Jacobian of 00420 virtual int set_function(func_t &f) { 00421 func=&f; 00422 return 0; 00423 } 00424 00425 /** \brief Evaluate the Jacobian \c j at point \c y(x) 00426 */ 00427 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00428 mat_t &j, param_t &pa)=0; 00429 00430 #ifndef DOXYGEN_INTERNAL 00431 00432 protected: 00433 00434 /// A pointer to the user-specified function 00435 func_t *func; 00436 00437 private: 00438 00439 jacobian(const jacobian &); 00440 jacobian& operator=(const jacobian&); 00441 00442 #endif 00443 00444 }; 00445 00446 /** 00447 \brief Simple automatic Jacobian 00448 00449 This class computes a numerical Jacobian by finite differencing. 00450 The stepsize is chosen to be \f$ h_j = \mathrm{epsrel}~x_j \f$ or 00451 \f$ h_j = \mathrm{epsmin} \f$ if \f$ \mathrm{epsrel}~x_j < 00452 \mathrm{epsmin} \f$. 00453 00454 This is nearly equivalent to the GSL method for computing 00455 Jacobians as in \c multiroots/fdjac.c. To obtain the GSL 00456 behavior, set \ref epsrel to \c GSL_SQRT_DBL_EPSILON and set 00457 \ref epsmin to zero. The \ref gsl_mroot_hybrids class sets \ref 00458 epsrel to \c GSL_SQRT_DBL_EPSILON in its constructor, 00459 but does not set \ref epsmin to zero. 00460 00461 This class does not separately check the vector and matrix sizes 00462 to ensure they are commensurate. 00463 00464 \future GSL-1.10 updated fdjac.c and this update could be 00465 implemented below. 00466 */ 00467 template<class param_t, class func_t=mm_funct<param_t>, 00468 class vec_t=ovector_base, class mat_t=omatrix_base, 00469 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00470 class simple_jacobian : 00471 public jacobian<param_t,func_t,vec_t,mat_t> { 00472 00473 public: 00474 00475 simple_jacobian() { 00476 epsrel=1.0e-4; 00477 epsmin=1.0e-15; 00478 err_nonconv=true; 00479 } 00480 00481 /** \brief The relative stepsize for finite-differencing 00482 (default \f$ 10^{-4} \f$ ) 00483 */ 00484 double epsrel; 00485 00486 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00487 double epsmin; 00488 00489 /// For memory allocation 00490 alloc_t ao; 00491 00492 /// If true, call the error handler if the routine does not "converge" 00493 bool err_nonconv; 00494 00495 /** \brief The operator() 00496 */ 00497 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00498 mat_t &jac, param_t &pa) { 00499 00500 size_t i,j; 00501 double h,temp; 00502 alloc_vec_t f; 00503 bool success=true; 00504 00505 ao.allocate(f,nv); 00506 00507 for (j=0;j<nv;j++) { 00508 00509 h=epsrel*fabs(x[j]); 00510 if (fabs(h)<=epsmin) h=epsrel; 00511 00512 x[j]+=h; 00513 (*this->func)(nv,x,f,pa); 00514 x[j]-=h; 00515 00516 bool nonzero=false; 00517 for (i=0;i<nv;i++) { 00518 temp=(f[i]-y[i])/h; 00519 if (temp!=0.0) nonzero=true; 00520 jac[i][j]=temp; 00521 } 00522 if (nonzero==false) success=false; 00523 } 00524 00525 ao.free(f); 00526 00527 if (success==false) { 00528 O2SCL_CONV2_RET("At least one row of the Jacobian is zero ", 00529 "in simple_jacobian::operator().",gsl_efailed, 00530 this->err_nonconv); 00531 } 00532 return 0; 00533 } 00534 }; 00535 00536 /** 00537 \brief A direct calculation of the jacobian using a \ref deriv object 00538 00539 Note that it is sometimes wasteful to use this Jacobian in a 00540 root-finding routine and using more approximate Jacobians is 00541 more efficient. This class is mostly useful for demonstration 00542 purposes. 00543 */ 00544 template<class param_t, class func_t=mm_funct<param_t>, 00545 class vec_t=ovector_base, class mat_t=omatrix_base> class exact_jacobian : 00546 public jacobian<param_t,func_t,vec_t,mat_t> { 00547 00548 public: 00549 00550 exact_jacobian() { 00551 def_deriv.h=1.0e-4; 00552 dptr=&def_deriv; 00553 } 00554 00555 /** 00556 \brief Parameter structure for passing information 00557 00558 This class is primarily useful for specifying derivatives 00559 for using the jacobian::set_deriv() function. 00560 00561 \comment 00562 This type needs to be publicly available so that the 00563 user can properly specify a base 1-dimensional derivative 00564 object. 00565 \endcomment 00566 */ 00567 typedef struct { 00568 /// The number of variables 00569 size_t nv; 00570 /// The current x value 00571 size_t xj; 00572 /// The current y value 00573 size_t yi; 00574 /// The x vector 00575 vec_t *x; 00576 /// The y vector 00577 vec_t *y; 00578 /// The parameters 00579 param_t *pa; 00580 } ej_parms; 00581 00582 /// The default derivative object 00583 gsl_deriv<ej_parms,funct<ej_parms> > def_deriv; 00584 00585 /// Set the derivative object 00586 int set_deriv(deriv<ej_parms,funct<ej_parms> > &de) { 00587 dptr=&de; 00588 return 0; 00589 } 00590 00591 /** \brief The operator() 00592 */ 00593 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00594 mat_t &jac, param_t &pa) { 00595 size_t i,j; 00596 double h,temp; 00597 00598 ej_parms ejp; 00599 ejp.nv=nv; 00600 ejp.x=&x; 00601 ejp.y=&y; 00602 ejp.pa=&pa; 00603 00604 funct_mfptr<exact_jacobian,ej_parms> dfnp(this,&exact_jacobian::dfn); 00605 00606 for (j=0;j<nv;j++) { 00607 ejp.xj=j; 00608 for (i=0;i<nv;i++) { 00609 ejp.yi=i; 00610 double tmp=(*ejp.x)[j]; 00611 jac[i][j]=dptr->calc(tmp,ejp,dfnp); 00612 (*ejp.x)[j]=tmp; 00613 } 00614 } 00615 00616 return 0; 00617 } 00618 00619 00620 #ifndef DOXYGEN_INTERNAL 00621 00622 protected: 00623 00624 /// Pointer to the derivative object 00625 deriv<ej_parms,funct<ej_parms> > *dptr; 00626 00627 /// Function for the derivative object 00628 int dfn(double x, double &y, ej_parms &ejp) { 00629 (*ejp.x)[ejp.xj]=x; 00630 (*this->func)(ejp.nv,*ejp.x,*ejp.y,*ejp.pa); 00631 y=(*ejp.y)[ejp.yi]; 00632 return 0; 00633 } 00634 00635 #endif 00636 00637 }; 00638 00639 #ifndef DOXYGENP 00640 } 00641 #endif 00642 00643 #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