00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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
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
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
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
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
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
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
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
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
00151 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y,
00152 mat_t &j, param_t &pa);
00153
00154
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
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
00183 virtual int set_function(func_t &f) {
00184 func=&f;
00185 return 0;
00186 }
00187
00188
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
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
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
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
00239
00240
00241 double epsrel;
00242
00243
00244 double epsmin;
00245
00246
00247 alloc_t ao;
00248
00249
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
00290
00291
00292
00293
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
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
00315 gsl_deriv<ej_parms,funct<ej_parms> > def_deriv;
00316
00317
00318 int set_deriv(deriv<ej_parms,funct<ej_parms> > &de) {
00319 dptr=&de;
00320 return 0;
00321 }
00322
00323
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
00357 deriv<ej_parms,funct<ej_parms> > *dptr;
00358
00359
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