[3115] | 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 |
|
---|