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_EQI_DERIV_H
00024 #define O2SCL_EQI_DERIV_H
00025
00026 #include <cmath>
00027 #include <o2scl/deriv.h>
00028 #include <o2scl/collection.h>
00029
00030 #ifndef DOXYGENP
00031 namespace o2scl {
00032 #endif
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 template<class param_t, class func_t, class vec_t=ovector_view>
00135 class eqi_deriv : public deriv<param_t, func_t> {
00136 public:
00137
00138 eqi_deriv() {
00139 h=1.0e-4;
00140 xoff=0.0;
00141 cap=&eqi_deriv::calc_array5;
00142 cp=&eqi_deriv::calcp5;
00143 c2p=&eqi_deriv::calc2p5;
00144 }
00145
00146
00147 double h;
00148
00149
00150 double xoff;
00151
00152
00153
00154
00155
00156
00157 int set_npoints(int npoints) {
00158 if (npoints==2) {
00159 cap=&eqi_deriv::calc_array3;
00160 cp=&eqi_deriv::calcp2;
00161 } else if (npoints==3) {
00162 cap=&eqi_deriv::calc_array3;
00163 cp=&eqi_deriv::calcp3;
00164 } else if (npoints==4) {
00165 cap=&eqi_deriv::calc_array4;
00166 cp=&eqi_deriv::calcp4;
00167 } else {
00168 cap=&eqi_deriv::calc_array5;
00169 cp=&eqi_deriv::calcp5;
00170 }
00171 if (npoints<=1 || npoints>5) {
00172 set_err_ret("Invalid # of points in set_npoints(). Using default",
00173 gsl_einval);
00174 }
00175 return 0;
00176 }
00177
00178
00179
00180
00181
00182
00183 int set_npoints2(int npoints) {
00184 if (npoints==3) {
00185 c2p=&eqi_deriv::calc2p3;
00186 } else if (npoints==4) {
00187 c2p=&eqi_deriv::calc2p4;
00188 } else {
00189 c2p=&eqi_deriv::calc2p5;
00190 }
00191 if (npoints<=2 || npoints>5) {
00192 set_err_ret("Invalid # of points in set_npoints2(). Using default",
00193 gsl_einval);
00194 }
00195 return 0;
00196 }
00197
00198
00199
00200
00201 virtual double calc(double x, void *pa, func_t &func) {
00202 double df, p=xoff/h;
00203 df=(this->*cp)(x,p,pa,func)/h;
00204 return df;
00205 }
00206
00207
00208
00209 virtual double calc2(double x, void *pa, func_t &func) {
00210 double df, p=xoff/h;
00211 df=(this->*c2p)(x,p,pa,func)/h/h;
00212 return df;
00213 }
00214
00215
00216
00217 virtual double calc3(double x, void *pa, func_t &func) {
00218 double df, p=xoff/h;
00219 df=(this->*c3p)(x,h,p,pa,func)/h;
00220 return df;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 double calc_array(double x, double x0, double dx,
00235 size_t nx, const vec_t &y) {
00236 size_t ix=(size_t)((x-x0+dx/100.0)/dx);
00237 return (this->*cap)(x,x0,dx,nx,y,ix)/dx;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 double calc2_array(double x, double x0, double dx,
00252 size_t nx, const vec_t &y)
00253 {
00254 size_t ix=(size_t)((x-x0+dx/100.0)/dx);
00255 return (this->*c2ap)(x,x0,dx,nx,y,ix)/dx;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 double calc3_array(double x, double x0, double dx,
00270 size_t nx, const vec_t &y)
00271 {
00272 size_t ix=(size_t)((x-x0+dx/100.0)/dx);
00273 return (this->*c3ap)(x,x0,dx,nx,y,ix)/dx;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283 int deriv_array(size_t nv, double dx, const vec_t &y,
00284 vec_t &dydx)
00285 {
00286 dydx[0]=(-25.0/12.0*y[0]+4.0*y[1]-3.0*y[2]+4.0/3.0*y[3]-0.25*y[4])/dx;
00287 dydx[1]=(-0.25*y[0]-5.0/6.0*y[1]+1.5*y[2]-0.5*y[3]+1.0/12.0*y[4])/dx;
00288 for(size_t i=2;i<nv-2;i++) {
00289 dydx[i]=(1.0/12.0*y[i-2]-2.0/3.0*y[i-1]+2.0/3.0*y[i+1]-
00290 1.0/12.0*y[i+2])/dx;
00291 }
00292 dydx[nv-2]=(-1.0/12.0*y[nv-5]+0.5*y[nv-4]-1.5*y[nv-3]+
00293 5.0/6.0*y[nv-2]+0.25*y[nv-1])/dx;
00294 dydx[nv-1]=(0.25*y[nv-5]-4.0/3.0*y[nv-4]+3.0*y[nv-3]-
00295 4.0*y[nv-2]+25.0/12.0*y[nv-1])/dx;
00296 return 0;
00297 }
00298
00299
00300 virtual const char *type() { return "eqi_deriv"; }
00301
00302 #ifndef DOXYGENP
00303
00304 protected:
00305
00306
00307 double calcp2(double x, double p, void *pa,
00308 func_t &func) {
00309 return (func(x+h,pa)-func(x,pa));
00310 }
00311
00312
00313 double calcp3(double x, double p, void *pa,
00314 func_t &func) {
00315 if (p==0.0) {
00316 return ((-0.5)*func(x-h,pa)+(0.5)*func(x+h,pa));
00317 }
00318 return ((p-0.5)*func(x-h,pa)-2.0*p*func(x,pa)+(p+0.5)*func(x+h,pa));
00319 }
00320
00321
00322 double calcp4(double x, double p, void *pa,
00323 func_t &func) {
00324 double p2=p*p;
00325 return (-(3.0*p2-6.0*p+2.0)/6.0*func(x-h,pa)+
00326 (1.5*p2-2.0*p-0.5)*func(x,pa)-
00327 (1.5*p2-p-1.0)*func(x+h,pa)+
00328 (3.0*p2-1.0)/6.0*func(x+2.0*h,pa));
00329 }
00330
00331
00332 double calcp5(double x, double p, void *pa,
00333 func_t &func) {
00334 double p2=p*p, p3=p*p*p;
00335 if (p==0.0) {
00336 return ((1.0)/12.0*func(x-2.0*h,pa)-
00337 (4.0)/6.0*func(x-h,pa)-
00338 (-4.0)/6.0*func(x+h,pa)+
00339 (-1.0)/12.0*func(x+2.0*h,pa));
00340 }
00341 return ((2.0*p3-3.0*p2-p+1.0)/12.0*func(x-2.0*h,pa)-
00342 (4.0*p3-3.0*p2-8.0*p+4.0)/6.0*func(x-h,pa)+
00343 (p3-2.5*p)*func(x,pa)-
00344 (4.0*p3+3.0*p2-8.0*p-4.0)/6.0*func(x+h,pa)+
00345 (2.0*p3+3.0*p2-p-1.0)/12.0*func(x+2.0*h,pa));
00346 }
00347
00348
00349
00350 double calc_array3(double x, double x0, double dx, size_t nx,
00351 const vec_t &y, size_t ix) {
00352 double p;
00353 if (ix>0 && ix<nx-1) {
00354 p=x-(x0+ix*dx);
00355 return ((p-0.5)*y[ix-1]-2.0*p*y[ix]+(p+0.5)*y[ix+1]);
00356 } else if (ix==0) {
00357 p=x-(x0+dx);
00358 return ((p-0.5)*y[0]-2.0*p*y[1]+(p+0.5)*y[2]);
00359 }
00360 p=x-(x0+(nx-2)*dx);
00361 return ((p-0.5)*y[nx-3]-2.0*p*y[nx-2]+(p+0.5)*y[nx-1]);
00362 }
00363
00364
00365 double calc_array4(double x, double x0, double dx, size_t nx,
00366 const vec_t &y, size_t ix) {
00367 double p, p2;
00368 if (ix>0 && ix<nx-2) {
00369 p=x-(x0+ix*dx);
00370 p2=p*p;
00371 return (-(3.0*p2-6.0*p+2.0)/6.0*y[ix-1]+
00372 (1.5*p2-2.0*p-0.5)*y[ix]-
00373 (1.5*p2-p-1.0)*y[ix+1]+
00374 (3.0*p2-1.0)/6.0*y[ix+2]);
00375 } else if (ix==0) {
00376 p=x-(x0+dx);
00377 p2=p*p;
00378 return (-(3.0*p2-6.0*p+2.0)/6.0*y[0]+
00379 (1.5*p2-2.0*p-0.5)*y[1]-
00380 (1.5*p2-p-1.0)*y[2]+
00381 (3.0*p2-1.0)/6.0*y[3]);
00382 }
00383 p=x-(x0+(nx-3)*dx);
00384 p2=p*p;
00385 return (-(3.0*p2-6.0*p+2.0)/6.0*y[nx-4]+
00386 (1.5*p2-2.0*p-0.5)*y[nx-3]-
00387 (1.5*p2-p-1.0)*y[nx-2]+
00388 (3.0*p2-1.0)/6.0*y[nx-1]);
00389 }
00390
00391
00392 double calc_array5(double x, double x0,
00393 double dx, size_t nx,
00394 const vec_t &y, size_t ix) {
00395 double p, p2, p3;
00396 if (ix>1 && ix<nx-2) {
00397 p=x-(x0+ix*dx);
00398 p2=p*p, p3=p*p*p;
00399 return ((2.0*p3-3.0*p2-p+1.0)/12.0*y[ix-2]-
00400 (4.0*p3-3.0*p2-8.0*p+4.0)/6.0*y[ix-1]+
00401 (p3-2.5*p)*y[ix]-
00402 (4.0*p3+3.0*p2-8.0*p-4.0)/6.0*y[ix+1]+
00403 (2.0*p3+3.0*p2-p-1.0)/12.0*y[ix+2]);
00404 } else if (ix<=1) {
00405 p=x-(x0+2*dx);
00406 p2=p*p, p3=p*p*p;
00407 return ((2.0*p3-3.0*p2-p+1.0)/12.0*y[0]-
00408 (4.0*p3-3.0*p2-8.0*p+4.0)/6.0*y[1]+
00409 (p3-2.5*p)*y[2]-
00410 (4.0*p3+3.0*p2-8.0*p-4.0)/6.0*y[3]+
00411 (2.0*p3+3.0*p2-p-1.0)/12.0*y[4]);
00412 }
00413 p=x-(x0+(nx-3)*dx);
00414 p2=p*p, p3=p*p*p;
00415 return ((2.0*p3-3.0*p2-p+1.0)/12.0*y[nx-5]-
00416 (4.0*p3-3.0*p2-8.0*p+4.0)/6.0*y[nx-4]+
00417 (p3-2.5*p)*y[nx-3]-
00418 (4.0*p3+3.0*p2-8.0*p-4.0)/6.0*y[nx-2]+
00419 (2.0*p3+3.0*p2-p-1.0)/12.0*y[nx-1]);
00420 }
00421
00422
00423 double calc2p3(double x, double p, void *pa,
00424 func_t &func) {
00425 return (func(x-h,pa)-2*func(x,pa)+func(x+h,pa));
00426 }
00427
00428
00429 double calc2p4(double x, double p, void *pa,
00430 func_t &func) {
00431 return ((1.0-2.0*p)*func(x-h,pa)-(1.0-6.0*p)*func(x,pa)
00432 -(1.0-6.0*p)*func(x+h,pa)+(1.0+2.0*p)*func(x+2.0*h,pa))/2.0;
00433 }
00434
00435
00436 double calc2p5(double x, double p, void *pa,
00437 func_t &func) {
00438 return ((1.0-2.0*p)*(1.0-2.0*p)*func(x-2.0*h,pa)
00439 +(8.0*p-16.0*p*p)*func(x-h,pa)
00440 -(2.0-24.0*p*p)*func(x,pa)
00441 -(8.0*p+16.0*p*p)*func(x+h,pa)
00442 +(1.0+2.0*p)*(1.0+2.0*p)*func(x+2.0*h,pa))/4.0;
00443 }
00444
00445
00446 double (eqi_deriv::*cp)(double x, double p, void *pa,
00447 func_t &func);
00448
00449
00450 double (eqi_deriv::*cap)(double x, double x0,
00451 double dx, size_t nx,
00452 const vec_t &y, size_t ix);
00453
00454
00455 double (eqi_deriv::*c2p)(double x, double p, void *pa,
00456 func_t &func);
00457
00458
00459 double (eqi_deriv::*c2ap)(double x, double x0,
00460 double dx, size_t nx,
00461 const vec_t &y, size_t ix);
00462
00463
00464 double (eqi_deriv::*c3p)(double x, double h, double p, void *pa,
00465 func_t &func);
00466
00467
00468 double (eqi_deriv::*c3ap)(double x, double x0,
00469 double dx, size_t nx,
00470 const vec_t &y, size_t ix);
00471
00472 #endif
00473
00474 };
00475
00476 #ifndef DOXYGENP
00477 }
00478 #endif
00479
00480 #endif