Changeset 3196 in Sophya for trunk/Cosmo/SimLSS/geneutils.cc
- Timestamp:
- Apr 3, 2007, 4:06:50 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cosmo/SimLSS/geneutils.cc
r3157 r3196 150 150 } 151 151 152 //---------------------------------------------------- 153 double InterpTab(double x0,vector<double>& X,vector<double>& Y,unsigned short typint) 154 // Interpole in x0 the table Y = f(X) 155 // X doit etre ordonne par ordre croissant (strictement) 156 // typint = 0 : nearest value 157 // 1 : linear interpolation 158 // 2 : parabolique interpolation 159 { 160 long n = X.size(); 161 if(Y.size()<n || n<2) 162 throw ParmError("InterpTab_Error : incompatible size between X and Y tables!"); 163 164 if(x0<X[0] || x0>X[n-1]) return 0.; 165 if(typint>2) typint = 0; 166 167 // Recherche des indices encadrants par dichotomie 168 long k, klo=0, khi=n-1; 169 while (khi-klo > 1) { 170 k = (khi+klo) >> 1; 171 if (X[k] > x0) khi=k; else klo=k; 172 } 173 174 // Quel est le plus proche? 175 k = (x0-X[klo]<X[khi]-x0) ? klo: khi; 176 177 // On retourne le plus proche 178 if(typint==0) return Y[k]; 179 180 // On retourne l'extrapolation lineaire 181 if(typint==1 || n<3) 182 return Y[klo] + (Y[khi]-Y[klo])/(X[khi]-X[klo])*(x0-X[klo]); 183 184 // On retourne l'extrapolation parabolique 185 if(k==0) k++; else if(k==n-1) k--; 186 klo = k-1; khi = k+1; 187 double x1 = X[klo]-X[k], x2 = X[khi]-X[k]; 188 double y1 = Y[klo]-Y[k], y2 = Y[khi]-Y[k]; 189 double den = x1*x2*(x1-x2); 190 double a = (y1*x2-y2*x1)/den; 191 double b = (y2*x1*x1-y1*x2*x2)/den; 192 x0 -= X[k]; 193 return Y[k] + (a*x0+b)*x0;; 194 195 } 196 152 197 //------------------------------------------------------------------- 153 198 int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex) … … 252 297 return n; 253 298 } 299 300 //------------------------------------------------------------------- 301 302 static unsigned short IntegrateFunc_GlOrder = 0; 303 static vector<double> IntegrateFunc_x; 304 static vector<double> IntegrateFunc_w; 305 306 /////////////////////////////////////////////////////////// 307 //************** Integration of Functions ***************// 308 /////////////////////////////////////////////////////////// 309 310 311 //////////////////////////////////////////////////////////////////////////////////// 312 double IntegrateFunc(GenericFunc& func,double xmin,double xmax 313 ,double perc,double dxinc,double dxmax,unsigned short glorder) 314 // --- Integration adaptative --- 315 // Integrate[func[x], {x,xmin,xmax}] 316 // ..xmin,xmax are the integration limits 317 // ..dxinc is the searching increment x = xmin+i*dxinc 318 // if <0 npt = int(|dxinc|) (si<2 alors npt=100) 319 // et dxinc = (xmax-xmin)/npt 320 // ..dxmax is the maximum possible increment (if dxmax<=0 no test) 321 // --- 322 // Partition de [xmin,xmax] en intervalles [x(i),x(i+1)]: 323 // on parcourt [xmin,xmax] par pas de "dxinc" : x(i) = xmin + i*dxinc 324 // on cree un intervalle [x(i),x(i+1)] 325 // - si |f[x(i+1)] - f[x(i)]| > perc*|f[[x(i)]| 326 // - si |x(i+1)-x(i)| >= dxmax (si dxmax>0.) 327 // Dans un intervalle [x(i),x(i+1)] la fonction est integree 328 // avec une methode de gauss-legendre d'ordre "glorder" 329 { 330 double signe = 1.; 331 if(xmin>xmax) {double tmp=xmax; xmax=xmin; xmin=tmp; signe=-1.;} 332 333 if(glorder==0) glorder = 4; 334 if(perc<=0.) perc=0.1; 335 if(dxinc<=0.) {int n=int(-dxinc); if(n<2) n=100; dxinc=(xmax-xmin)/n;} 336 if(glorder != IntegrateFunc_GlOrder) { 337 IntegrateFunc_GlOrder = glorder; 338 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.); 339 } 340 341 // Recherche des intervalles [x(i),x(i+1)] 342 int_4 ninter = 0; 343 double sum = 0., xbas=xmin, fbas=func(xbas), fabsfbas=fabs(fbas); 344 for(double x=xmin+dxinc; x<xmax+dxinc/2.; x += dxinc) { 345 double f = func(x); 346 double dx = x-xbas; 347 bool doit = false; 348 if( x>xmax ) {doit = true; x=xmax;} 349 else if( dxmax>0. && dx>dxmax ) doit = true; 350 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true; 351 if( ! doit ) continue; 352 double s = 0.; 353 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) 354 s += IntegrateFunc_w[i]*func(xbas+IntegrateFunc_x[i]*dx); 355 sum += s*dx; 356 xbas = x; fbas = f; fabsfbas=fabs(fbas); ninter++; 357 } 358 //cout<<"Ninter="<<ninter<<endl; 359 360 return sum*signe; 361 } 362 363 //////////////////////////////////////////////////////////////////////////////////// 364 double IntegrateFuncLog(GenericFunc& func,double lxmin,double lxmax 365 ,double perc,double dlxinc,double dlxmax,unsigned short glorder) 366 // --- Integration adaptative --- 367 // Idem IntegrateFunc but integrate on logarithmic (base 10) intervals: 368 // Int[ f(x) dx ] = Int[ x*f(x) dlog10(x) ] * log(10) 369 // ..lxmin,lxmax are the log10() of the integration limits 370 // ..dlxinc is the searching logarithmic (base 10) increment lx = lxmin+i*dlxinc 371 // ..dlxmax is the maximum possible logarithmic (base 10) increment (if dlxmax<=0 no test) 372 // Remarque: to be use if "x*f(x) versus log10(x)" looks like a polynomial 373 // better than "f(x) versus x" 374 // ATTENTION: la fonction func que l'on passe en argument 375 // est "func(x)" et non pas "func(log10(x))" 376 { 377 double signe = 1.; 378 if(lxmin>lxmax) {double tmp=lxmax; lxmax=lxmin; lxmin=tmp; signe=-1.;} 379 380 if(glorder==0) glorder = 4; 381 if(perc<=0.) perc=0.1; 382 if(dlxinc<=0.) {int n=int(-dlxinc); if(n<2) n=100; dlxinc=(lxmax-lxmin)/n;} 383 if(glorder != IntegrateFunc_GlOrder) { 384 IntegrateFunc_GlOrder = glorder; 385 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.); 386 } 387 388 // Recherche des intervalles [lx(i),lx(i+1)] 389 int_4 ninter = 0; 390 double sum = 0., lxbas=lxmin, fbas=func(pow(10.,lxbas)), fabsfbas=fabs(fbas); 391 for(double lx=lxmin+dlxinc; lx<lxmax+dlxinc/2.; lx += dlxinc) { 392 double f = func(pow(10.,lx)); 393 double dlx = lx-lxbas; 394 bool doit = false; 395 if( lx>lxmax ) {doit = true; lx=lxmax;} 396 else if( dlxmax>0. && dlx>dlxmax ) doit = true; 397 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true; 398 if( ! doit ) continue; 399 double s = 0.; 400 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) { 401 double y = pow(10.,lxbas+IntegrateFunc_x[i]*dlx); 402 s += IntegrateFunc_w[i]*y*func(y); 403 } 404 sum += s*dlx; 405 lxbas = lx; fbas = f; fabsfbas=fabs(fbas); ninter++; 406 } 407 //cout<<"Ninter="<<ninter<<endl; 408 409 return M_LN10*sum*signe; 410 } 411 412 //////////////////////////////////////////////////////////////////////////////////// 413 /* 414 Integration des fonctions a une dimension y=f(x) par la Methode de Gauss-Legendre. 415 --> Calcul des coefficients du developpement pour [x1,x2] 416 | INPUT: 417 | x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5) 418 | glorder = degre n du developpement de Gauss-Legendre 419 | OUTPUT: 420 | x[] = valeur des abscisses ou l'on calcule (dim=n) 421 | w[] = valeur des coefficients associes 422 | REMARQUES: 423 | - x et w seront dimensionnes a n. 424 | - l'integration est rigoureuse si sur l'intervalle d'integration 425 | la fonction f(x) peut etre approximee par un polynome 426 | de degre 2*m (monome le + haut x**(2*n-1) ) 427 */ 428 void Compute_GaussLeg(unsigned short glorder,vector<double>& x,vector<double>& w,double x1,double x2) 429 { 430 if(glorder==0) return; 431 int n = (int)glorder; 432 x.resize(n,0.); w.resize(n,0.); 433 434 int m,j,i; 435 double z1,z,xm,xl,pp,p3,p2,p1; 436 437 m=(n+1)/2; 438 xm=0.5*(x2+x1); 439 xl=0.5*(x2-x1); 440 for (i=1;i<=m;i++) { 441 z=cos(M_PI*(i-0.25)/(n+0.5)); 442 do { 443 p1=1.0; 444 p2=0.0; 445 for (j=1;j<=n;j++) { 446 p3=p2; 447 p2=p1; 448 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j; 449 } 450 pp=n*(z*p1-p2)/(z*z-1.0); 451 z1=z; 452 z=z1-p1/pp; 453 } while (fabs(z-z1) > 3.0e-11); // epsilon 454 x[i-1]=xm-xl*z; 455 x[n-i]=xm+xl*z; 456 w[i-1]=2.0*xl/((1.0-z*z)*pp*pp); 457 w[n-i]=w[i-1]; 458 } 459 }
Note:
See TracChangeset
for help on using the changeset viewer.