source: Sophya/trunk/Cosmo/SimLSS/integfunc.cc@ 3120

Last change on this file since 3120 was 3115, checked in by ansari, 19 years ago

Creation initiale du groupe Cosmo avec le repertoire SimLSS de
simulation de distribution de masse 3D des galaxies par CMV+Rz
18/12/2006

File size: 5.9 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <iostream>
4#include <stdlib.h>
5#include <stdio.h>
6#include <string.h>
7#include <math.h>
8
9#include "pexceptions.h"
10
11#include "integfunc.h"
12
13static unsigned short IntegrateFunc_GlOrder = 0;
14static vector<double> IntegrateFunc_x;
15static vector<double> IntegrateFunc_w;
16
17///////////////////////////////////////////////////////////
18//************** Integration of Functions ***************//
19///////////////////////////////////////////////////////////
20
21
22////////////////////////////////////////////////////////////////////////////////////
23double IntegrateFunc(GenericFunc& func,double xmin,double xmax
24 ,double perc,double dxinc,double dxmax,unsigned short glorder)
25// --- Integration adaptative ---
26// Integrate[func[x], {x,xmin,xmax}]
27// ..xmin,xmax are the integration limits
28// ..dxinc is the searching increment x = xmin+i*dxinc
29// if <0 npt = int(|dxinc|) (si<2 alors npt=100)
30// et dxinc = (xmax-xmin)/npt
31// ..dxmax is the maximum possible increment (if dxmax<=0 no test)
32// ---
33// Partition de [xmin,xmax] en intervalles [x(i),x(i+1)]:
34// on parcourt [xmin,xmax] par pas de "dxinc" : x(i) = xmin + i*dxinc
35// on cree un intervalle [x(i),x(i+1)]
36// - si |f[x(i+1)] - f[x(i)]| > perc*|f[[x(i)]|
37// - si |x(i+1)-x(i)| >= dxmax (si dxmax>0.)
38// Dans un intervalle [x(i),x(i+1)] la fonction est integree
39// avec une methode de gauss-legendre d'ordre "glorder"
40{
41 double signe = 1.;
42 if(xmin>xmax) {double tmp=xmax; xmax=xmin; xmin=tmp; signe=-1.;}
43
44 if(glorder==0) glorder = 4;
45 if(perc<=0.) perc=0.1;
46 if(dxinc<=0.) {int n=int(-dxinc); if(n<2) n=100; dxinc=(xmax-xmin)/n;}
47 if(glorder != IntegrateFunc_GlOrder) {
48 IntegrateFunc_GlOrder = glorder;
49 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
50 }
51
52 // Recherche des intervalles [x(i),x(i+1)]
53 int_4 ninter = 0;
54 double sum = 0., xbas=xmin, fbas=func(xbas), fabsfbas=fabs(fbas);
55 for(double x=xmin+dxinc; x<xmax+dxinc/2.; x += dxinc) {
56 double f = func(x);
57 double dx = x-xbas;
58 bool doit = false;
59 if( x>xmax ) {doit = true; x=xmax;}
60 else if( dxmax>0. && dx>dxmax ) doit = true;
61 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
62 if( ! doit ) continue;
63 double s = 0.;
64 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++)
65 s += IntegrateFunc_w[i]*func(xbas+IntegrateFunc_x[i]*dx);
66 sum += s*dx;
67 xbas = x; fbas = f; fabsfbas=fabs(fbas); ninter++;
68 }
69 //cout<<"Ninter="<<ninter<<endl;
70
71 return sum*signe;
72}
73
74////////////////////////////////////////////////////////////////////////////////////
75double IntegrateFuncLog(GenericFunc& func,double lxmin,double lxmax
76 ,double perc,double dlxinc,double dlxmax,unsigned short glorder)
77// --- Integration adaptative ---
78// Idem IntegrateFunc but integrate on logarithmic (base 10) intervals:
79// Int[ f(x) dx ] = Int[ x*f(x) dlog10(x) ] * log(10)
80// ..lxmin,lxmax are the log10() of the integration limits
81// ..dlxinc is the searching logarithmic (base 10) increment lx = lxmin+i*dlxinc
82// ..dlxmax is the maximum possible logarithmic (base 10) increment (if dlxmax<=0 no test)
83// Remarque: to be use if "x*f(x) versus log10(x)" looks like a polynomial
84// better than "f(x) versus x"
85// ATTENTION: la fonction func que l'on passe en argument
86// est "func(x)" et non pas "func(log10(x))"
87{
88 double signe = 1.;
89 if(lxmin>lxmax) {double tmp=lxmax; lxmax=lxmin; lxmin=tmp; signe=-1.;}
90
91 if(glorder==0) glorder = 4;
92 if(perc<=0.) perc=0.1;
93 if(dlxinc<=0.) {int n=int(-dlxinc); if(n<2) n=100; dlxinc=(lxmax-lxmin)/n;}
94 if(glorder != IntegrateFunc_GlOrder) {
95 IntegrateFunc_GlOrder = glorder;
96 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
97 }
98
99 // Recherche des intervalles [lx(i),lx(i+1)]
100 int_4 ninter = 0;
101 double sum = 0., lxbas=lxmin, fbas=func(pow(10.,lxbas)), fabsfbas=fabs(fbas);
102 for(double lx=lxmin+dlxinc; lx<lxmax+dlxinc/2.; lx += dlxinc) {
103 double f = func(pow(10.,lx));
104 double dlx = lx-lxbas;
105 bool doit = false;
106 if( lx>lxmax ) {doit = true; lx=lxmax;}
107 else if( dlxmax>0. && dlx>dlxmax ) doit = true;
108 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
109 if( ! doit ) continue;
110 double s = 0.;
111 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) {
112 double y = pow(10.,lxbas+IntegrateFunc_x[i]*dlx);
113 s += IntegrateFunc_w[i]*y*func(y);
114 }
115 sum += s*dlx;
116 lxbas = lx; fbas = f; fabsfbas=fabs(fbas); ninter++;
117 }
118 //cout<<"Ninter="<<ninter<<endl;
119
120 return M_LN10*sum*signe;
121}
122
123////////////////////////////////////////////////////////////////////////////////////
124/*
125Integration des fonctions a une dimension y=f(x) par la Methode de Gauss-Legendre.
126 --> Calcul des coefficients du developpement pour [x1,x2]
127| INPUT:
128| x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5)
129| glorder = degre n du developpement de Gauss-Legendre
130| OUTPUT:
131| x[] = valeur des abscisses ou l'on calcule (dim=n)
132| w[] = valeur des coefficients associes
133| REMARQUES:
134| - x et w seront dimensionnes a n.
135| - l'integration est rigoureuse si sur l'intervalle d'integration
136| la fonction f(x) peut etre approximee par un polynome
137| de degre 2*m (monome le + haut x**(2*n-1) )
138*/
139void Compute_GaussLeg(unsigned short glorder,vector<double>& x,vector<double>& w,double x1,double x2)
140{
141 if(glorder==0) return;
142 int n = (int)glorder;
143 x.resize(n,0.); w.resize(n,0.);
144
145 int m,j,i;
146 double z1,z,xm,xl,pp,p3,p2,p1;
147
148 m=(n+1)/2;
149 xm=0.5*(x2+x1);
150 xl=0.5*(x2-x1);
151 for (i=1;i<=m;i++) {
152 z=cos(M_PI*(i-0.25)/(n+0.5));
153 do {
154 p1=1.0;
155 p2=0.0;
156 for (j=1;j<=n;j++) {
157 p3=p2;
158 p2=p1;
159 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
160 }
161 pp=n*(z*p1-p2)/(z*z-1.0);
162 z1=z;
163 z=z1-p1/pp;
164 } while (fabs(z-z1) > 3.0e-11); // epsilon
165 x[i-1]=xm-xl*z;
166 x[n-i]=xm+xl*z;
167 w[i-1]=2.0*xl/((1.0-z*z)*pp*pp);
168 w[n-i]=w[i-1];
169 }
170}
171
Note: See TracBrowser for help on using the repository browser.