Changeset 3196 in Sophya for trunk/Cosmo/SimLSS/geneutils.cc


Ignore:
Timestamp:
Apr 3, 2007, 4:06:50 PM (18 years ago)
Author:
cmv
Message:

les AGN selon C.Jackson, une premiere approche simplifiee, recodage from Jim Rich. cmv 03/04/2007

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Cosmo/SimLSS/geneutils.cc

    r3157 r3196  
    150150}
    151151
     152//----------------------------------------------------
     153double 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
    152197//-------------------------------------------------------------------
    153198int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex)
     
    252297  return n;
    253298}
     299
     300//-------------------------------------------------------------------
     301
     302static unsigned short IntegrateFunc_GlOrder = 0;
     303static vector<double> IntegrateFunc_x;
     304static vector<double> IntegrateFunc_w;
     305
     306///////////////////////////////////////////////////////////
     307//************** Integration of Functions ***************//
     308///////////////////////////////////////////////////////////
     309
     310
     311////////////////////////////////////////////////////////////////////////////////////
     312double 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////////////////////////////////////////////////////////////////////////////////////
     364double 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/*
     414Integration 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*/
     428void 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.