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 |
|
---|
13 | static unsigned short IntegrateFunc_GlOrder = 0;
|
---|
14 | static vector<double> IntegrateFunc_x;
|
---|
15 | static vector<double> IntegrateFunc_w;
|
---|
16 |
|
---|
17 | ///////////////////////////////////////////////////////////
|
---|
18 | //************** Integration of Functions ***************//
|
---|
19 | ///////////////////////////////////////////////////////////
|
---|
20 |
|
---|
21 |
|
---|
22 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
23 | double 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 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
75 | double 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 | /*
|
---|
125 | Integration 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 | */
|
---|
139 | void 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 |
|
---|