source: Sophya/trunk/Cosmo/SimLSS/geneutils.cc@ 3947

Last change on this file since 3947 was 3653, checked in by cmv, 16 years ago

add hshs EW, cmv 16/07/2009

File size: 19.4 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#include <vector>
9
10#include "pexceptions.h"
11
12#include "histos.h"
13#include "hisprof.h"
14#include "srandgen.h"
15
16#include "geneutils.h"
17
18namespace SOPHYA {
19
20//-------------------------------------------------------------------
21// Classe d'interpolation lineaire:
22// Le vecteur y a n elements y_i tels que y_i = f(x_i)
23// ou les x_i sont regulierement espaces
24// et x_0=xmin et x_{n-1}=xmax (xmax inclus!)
25InterpFunc::InterpFunc(double xmin,double xmax,vector<double>& y)
26 : _xmin(xmin), _xmax(xmax), _y(y)
27{
28 if(_xmin>=_xmax || _y.size()<=2) { // au moins 3 points!
29 cout<<"InterpFunc::InterpFunc : bad arguments values"<<endl;
30 throw ParmError("InterpFunc::InterpFunc : bad arguments values");
31 }
32 _nm1 = _y.size()-1;
33 _dx = (_xmax-_xmin)/(double)_nm1;
34}
35
36double InterpFunc::Linear(double x,unsigned short& ok)
37{
38 ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
39 x -= _xmin;
40 long i = long(x/_dx); // On prend le "i" juste en dessous
41 if(i<0) i=0; else if(i>=_nm1) i=_nm1-1;
42 return _y[i] + (_y[i+1]-_y[i])/_dx*(x-i*_dx);
43}
44
45double InterpFunc::Parab(double x,unsigned short& ok)
46{
47 ok=0; if(x<_xmin) ok=1; else if(x>_xmax) ok=2;
48 x -= _xmin;
49 long i = long(x/_dx+0.5); // On prend le "i" le + proche
50 if(i<1) i=1; else if(i>=_nm1-1) i=_nm1-2;
51 double a = (_y[i+1]-2.*_y[i]+_y[i-1])/(2.*_dx*_dx);
52 double b = (_y[i+1]-_y[i-1])/(2.*_dx);
53 return _y[i] + (x-i*_dx)*(a*(x-i*_dx)+b);
54}
55
56//-------------------------------------------------------------------
57// Classe d'inversion d'une fonction STRICTEMENT MONOTONE CROISSANTE
58//
59// - On part de deux vecteurs x,y de "Nin" elements tels que "y_i = f[x_i]"
60// ou la fonction "f" est strictement monotone croissante:
61// x(i) < x(i+1) et y(i) < y(i+1)
62// - Le but de la classe est de remplir un vecteur X de "Nout" elements
63// tels que: X_j = f^-1[Y_j] avec j=[0,Nout[
64// avec les Y_j regulierement espaces entre ymin=y(0) , ymax=y(Nin -1)
65// cad: X_j = f^-1[ ymin+j*(ymax-ymin)/(Nout-1) ]
66// - La construction du vecteur X est realisee
67// par interpolation lineaire (ComputeLinear) ou parabolique (ComputeParab)
68InverseFunc::InverseFunc(vector<double>& x,vector<double>& y)
69 : _ymin(0.) , _ymax(0.) , _x(x) , _y(y)
70{
71 uint_4 ns = _x.size();
72 if(ns<3 || _y.size()<=0 || ns!=_y.size())
73 throw ParmError("InverseFunc::InverseFunc_Error: bad array size");
74
75 // Check "x" strictement monotone croissant
76 for(uint_4 i=0;i<ns-1;i++)
77 if(_x[i+1]<=_x[i]) {
78 cout<<"InverseFunc::InverseFunc_Error: _x array not stricly growing"<<endl;
79 throw ParmError("InverseFunc::InverseFunc_Error: _x array not stricly growing");
80 }
81
82 // Check "y" monotone croissant
83 for(uint_4 i=0;i<ns-1;i++)
84 if(_y[i+1]<_y[i]) {
85 cout<<"InverseFunc::InverseFunc_Error: _y array not growing"<<endl;
86 throw ParmError("InverseFunc::InverseFunc_Error: _y array not growing");
87 }
88
89 // define limits
90 _ymin = _y[0];
91 _ymax = _y[ns-1];
92
93}
94
95InverseFunc::~InverseFunc(void)
96{
97}
98
99int InverseFunc::ComputeLinear(long nout,vector<double>& xfcty)
100// Compute table "xfcty" by linear interpolation of "x" versus "y"
101// on "nout" points from "ymin" to "ymax":
102// xfcty[i] = interpolation of function "x" for "ymin+i*(ymax-ymin)/(nout-1)"
103{
104 if(nout<3) return -1;
105
106 xfcty.resize(nout);
107
108 long i1,i2;
109 double x;
110 for(int_4 i=0;i<nout;i++) {
111 double y = _ymin + i*(_ymax-_ymin)/(nout-1.);
112 find_in_y(y,i1,i2);
113 double dy = _y[i2]-_y[i1];
114 if(dy==0.) {
115 x = (_x[i2]+_x[i1])/2.; // la fct a inverser est plate!
116 } else {
117 x = _x[i1] + (_x[i2]-_x[i1])/dy * (y-_y[i1]);
118 }
119 xfcty[i] = x;
120 }
121
122 return 0;
123}
124
125int InverseFunc::ComputeParab(long nout,vector<double>& xfcty)
126{
127 if(nout<3) return -1;
128
129 xfcty.resize(nout);
130
131 long i1,i2,i3;
132 double x;
133 for(int_4 i=0;i<nout;i++) {
134 double y = _ymin + i*(_ymax-_ymin)/(nout-1.);
135 find_in_y(y,i1,i2);
136 // On cherche le 3ieme point selon la position de y / au 2 premiers
137 double my = (_y[i1]+_y[i2])/2.;
138 if(y<my) {i3=i2; i2=i1; i1--;} else {i3=i2+1;}
139 // Protection
140 if(i1<0) {i1++; i2++; i3++;}
141 if(i3==(long)_y.size()) {i1--; i2--; i3--;}
142 // Interpolation parabolique
143 double dy = _y[i3]-_y[i1];
144 if(dy==0.) {
145 x = (_x[i3]+_x[i1])/2.; // la fct a inverser est plate!
146 } else {
147 double X1=_x[i1]-_x[i2], X3=_x[i3]-_x[i2];
148 double Y1=_y[i1]-_y[i2], Y3=_y[i3]-_y[i2];
149 double den = Y1*Y3*dy;
150 double a = (X3*Y1-X1*Y3)/den;
151 double b = (X1*Y3*Y3-X3*Y1*Y1)/den;
152 y -= _y[i2];
153 x = (a*y+b)*y + _x[i2];
154 }
155 xfcty[i] = x;
156 }
157
158 return 0;
159}
160
161//----------------------------------------------------
162double InterpTab(double x0,vector<double>& X,vector<double>& Y,unsigned short typint)
163// Interpole in x0 the table Y = f(X)
164// X doit etre ordonne par ordre croissant (strictement)
165// typint = 0 : nearest value
166// 1 : linear interpolation
167// 2 : parabolique interpolation
168{
169 long n = X.size();
170 if(n>(long)Y.size() || n<2)
171 throw ParmError("InterpTab_Error : incompatible size between X and Y tables!");
172
173 if(x0<X[0] || x0>X[n-1]) return 0.;
174 if(typint>2) typint = 0;
175
176 // Recherche des indices encadrants par dichotomie
177 long k, klo=0, khi=n-1;
178 while (khi-klo > 1) {
179 k = (khi+klo) >> 1;
180 if (X[k] > x0) khi=k; else klo=k;
181 }
182
183 // Quel est le plus proche?
184 k = (x0-X[klo]<X[khi]-x0) ? klo: khi;
185
186 // On retourne le plus proche
187 if(typint==0) return Y[k];
188
189 // On retourne l'extrapolation lineaire
190 if(typint==1 || n<3)
191 return Y[klo] + (Y[khi]-Y[klo])/(X[khi]-X[klo])*(x0-X[klo]);
192
193 // On retourne l'extrapolation parabolique
194 if(k==0) k++; else if(k==n-1) k--;
195 klo = k-1; khi = k+1;
196 double x1 = X[klo]-X[k], x2 = X[khi]-X[k];
197 double y1 = Y[klo]-Y[k], y2 = Y[khi]-Y[k];
198 double den = x1*x2*(x1-x2);
199 double a = (y1*x2-y2*x1)/den;
200 double b = (y2*x1*x1-y1*x2*x2)/den;
201 x0 -= X[k];
202 return Y[k] + (a*x0+b)*x0;;
203
204}
205
206//-------------------------------------------------------------------
207int FuncToHisto(GenericFunc& func,Histo& h,bool logaxex)
208// Remplit l'histo 1D "h" avec la fonction "func"
209// INPUT:
210// logaxex = false : remplissage lineaire
211// les abscisses "x" des bins sont remplis avec f(x)
212// logaxex = true : remplissage logarithmique (base 10)
213// les abscisses "x" des bins sont remplis avec f(10^x)
214// RETURN:
215// 0 = OK
216// 1 = error
217{
218 if(h.NBins()<=0) return 1;
219
220 h.Zero();
221
222 for(int_4 i=0;i<h.NBins();i++) {
223 double x = h.BinCenter(i);
224 if(logaxex) x = pow(10.,x);
225 h.SetBin(i,func(x));
226 }
227
228 return 0;
229}
230
231int FuncToVec(GenericFunc& func,TVector<r_8>& v,double xmin,double xmax,bool logaxex)
232// Remplit le TVector avec la fonction "func"
233// INPUT:
234// logaxex = false : remplissage lineaire
235// les abscisses "x" des bins sont remplis avec f(x)
236// logaxex = true : remplissage logarithmique (base 10)
237// les abscisses "x" des bins sont remplis avec f(10^x)
238// RETURN:
239// 0 = OK
240// 1 = error
241// Remarque:
242// v(i) = f(xmin+i*dx) avec dx = (xmax-xmin)/v.NElts()
243{
244 if(v.NElts()<=0 || xmax<=xmin) return 1;
245
246 v = 0.;
247 double dx = (xmax-xmin)/v.NElts();
248
249 for(int_4 i=0;i<v.NElts();i++) {
250 double x = xmin + i * dx;;
251 if(logaxex) x = pow(10.,x);
252 v(i) = func(x);
253 }
254
255 return 0;
256}
257
258//-------------------------------------------------------------------
259double AngSol(double dtheta,double dphi,double theta0)
260// Retourne l'angle solide d'un "rectangle" et coordonnees spheriques
261// de DEMI-COTE "dtheta" x "dphi" et centre en "theta0"
262// Attention: Le "theta0" de l'equateur est Pi/2 (et non pas zero)
263// Les unites des angles sont en radians
264// theta0 in [0,Pi]
265// dtheta in [0,Pi]
266// dphi in [0,2Pi]
267// Return: l'angle solide en steradian
268{
269 double theta1 = theta0-dtheta, theta2 = theta0+dtheta;
270 if(theta1<0.) theta1=0.;
271 if(theta2>M_PI) theta2=M_PI;
272
273 return 2.*dphi * (cos(theta1)-cos(theta2));
274}
275
276double AngSol(double dtheta)
277// Retourne l'angle solide d'une calotte spherique de demi-ouverture "dtheta"
278// Attention: Les unites des angles sont en radians
279// dtheta in [0,Pi]
280// Return: l'angle solide en steradian
281// Approx pour theta petit: PI * theta^2
282{
283 return 2.*M_PI * (1.-cos(dtheta));
284}
285
286double FrAngSol(double angsol)
287// Retourne la demi-ouverture "dtheta" d'une calotte spherique d'angle solide "angsol"
288// Input: angle solide de la calotte spherique en steradians
289// Return: demi-ouverture de la calotte spherique en radians
290{
291 angsol = 1. - angsol/(2.*M_PI);
292 if(angsol<-1. || angsol>1.) return -1.;
293 return acos(angsol);
294}
295
296//-------------------------------------------------------------------
297double SinXsX(double x,bool app)
298// Calcul de sin(x)/x
299// Le Dl est en O[x]^10 (cad on va jusqu'au terme en x^8 compris)
300// Approx: terme en x^6/(6*20*42) ~ 1e-13 -> x^2 ~ 1.7e-4
301{
302 double x2 = x*x;
303 if(app || x2<1.7e-4) return 1.-x2/6.*(1.-x2/20.*(1.-x2/42.*(1.-x2/72.)));
304 return sin(x)/x;
305}
306
307double SinXsX_Sqr(double x,bool app)
308// Calcul de (sin(x)/x)^2
309// Le Dl est en O[x]^10 (cad on va jusqu'au terme en x^8 compris)
310// Approx: terme 2*x^6/(3*15*14) ~ 1e-13 -> x^2 ~ 6.8e-5
311{
312 double x2 = x*x;
313 if(app || x2<6.8e-5) return 1.-x2/3.*(1.-2.*x2/15.*(1.-x2/14.*(1.-2.*x2/45.)));
314 x2 = sin(x)/x;
315 return x2*x2;
316}
317
318double SinNXsX(double x,unsigned long N,bool app)
319// Calcul de sin(N*x)/sin(x) avec N entier positif
320// ATTENTION: N est entier
321// 1. pour que sin(N*x) et sin(x) soient nuls en meme temps
322// (on peut faire le DL popur sin(N*x) et sin(x))
323// 2. pour traiter correctement le DL en x = p*Pi+e avec e<<1 et p entier
324// sin(N*x)/sin(x) = sin(N*p*Pi+N*e)/sin(p*Pi+e)
325// = [sin(N*p*Pi)*cos(N*e)+cos(N*p*Pi)*sin(N*e)]
326// / [sin(p*Pi)*cos(e)+cos(p*Pi)*sin(e)]
327// comme sin(N*p*Pi)=0
328// = [cos(N*p*Pi)*sin(N*e)] / [cos(p*Pi)*sin(e)]
329// = [sin(N*e)/sin(e)] * [cos(N*p*Pi)/cos(p*Pi)]
330// = [DL autour de x=0] * (+1 ou -1)
331// Le seul cas ou on a "-1" est quand "p=impair" (cos(p*Pi)=-1) et "N=pair"
332// Approx: dernier terme x^4*N^4/120 ~ 1e-13 -> x^2 ~ 3.5e-6/N^2
333{
334 if(N==0) return 0;
335 double sx = sin(x), N2 = N*N;
336 if(app || sx*sx<3.5e-6/N2) {
337 double x2 = asin(sx); x2 *= x2;
338 double s = 1.;
339 if(N%2==0 && cos(x)<0.) s = -1.; // cas x ~ (2p+1)*Pi et N pair
340 return s*N*(1.-(N-1.)*(N+1.)/6.*x2*(1.-(3.*N2-7.)/60.*x2));
341 }
342 return sin((double)N*x)/sx;
343}
344
345double SinNXsX_Sqr(double x,unsigned long N,bool app)
346// Calcul de [sin(N*x)/sin(x)]^2 avec N entier positif
347// ATTENTION: cf remarque pour N entier dans SinNXsX
348// maximum de la fonction: N^2
349// Approx: dernier terme x^4*2*N^4/45 ~ 1e-13 -> x^2 ~ 1.5e-6/N^2
350{
351 if(N==0) return 0;
352 double sx = sin(x), N2 = N*N;
353 if(app || sx*sx<1.5e-6/N2) {
354 double x2 = asin(sx); x2 *= x2;
355 //return N2*(1.-(N*N-1.)/3.*x2);
356 return N2*(1.-(N-1.)*(N+1.)/3.*x2*(1.-(2.*N2-3.)/15.*x2));
357 }
358 sx = sin((double)N*x)/sx;
359 return sx*sx;
360}
361
362//-------------------------------------------------------------------
363/*=========================================================
364Antenne de longueur totale d (lue au milieu cad 2 brins de d/2)
365see Jackson p401 (antenne selon Oz, centre z=0 en O)
366k = w/C = 2 Pi Nu / C = 2 Pi / Lambda
367- densite de courant: J = I sin(kd/2 - k|z|)*delta(x)*delta(y)
368 (selon Oz) et pour |z|<d/2
369 I current peak value if kd>=Pi
370- current at gap (center): I0 = I sin(kd/2)
371#
372Z=sqrt(Mu/Epsilon) is the impedance of the vacum (376.7 Ohms)
373 cad pour le vecteur de pointing: |S| = |E0|^2/Z
374- Time average radiated power by solid angle unit:
375 t is theta the polar angle, t=0 along antenna, Pi/2 perpendicular
376 dP/dOmega = Z*I^2/(8Pi^2) * (cos(kd/2*cos(t)) - cos(kd/2))^2 / sin(t)^2
377 if we define L = d/lambda , kd/2= Pi * L
378 dP/dOmega = Z*I^2/(8Pi^2) * (cos(Pi*L*cos(t)) - cos(Pi*L))^2 / sin(t)^2
379#
380- pour t -> 0
381 dP/dOmega = Z*I^2/(8Pi^2) * ( 1/4 * (Pi*L*sin(Pi*L)*t)^2 )
382- pour t -> Pi
383 dP/dOmega = Z*I^2/(8Pi^2) * ( 1/4 * (Pi*L*sin(Pi*L)*(t-Pi))^2 )
384#
385- Polarisation in plane containing antenna and the direction of propagation
386#
387- pour kd << 1 (L->0) -> approximation du dipole:
388 dP/dOmega = Z*I^2/(8Pi^2) * ( (Pi*L)^4/4 * sin(t)^2 )
389- pour kd=Pi (L=1/2) -> half-wave length:
390 dP/dOmega = Z*I^2/(8Pi^2) * cos(Pi/2*cos(t))^2/sin(t)^2
391- pour kd=2*Pi (L=1) -> full-wave length:
392 dP/dOmega = Z*I^2/(8Pi^2) * 4*cos(Pi/2*cos(t))^4/sin(t)^2
393#
394- Le programme retourne Val tel que: dP/dOmega = Z*I^2/(8Pi^2) * Val
395 L<0 (arg[0]<0) alors Val est normalise tel que le maximum = 1
396#
397La carte antenne fournie par Peterson:
398 d=8cm, distance entre 2 centres consecutifs 10cm
399#
400# ---- AntCentFed , AntDipole et LobeSinc
401# Input:
402# t = angle entre la direction de la radiation et le fil de l'antenne (radian)
403# L = d/Lambda (d=longueur totale de l'antenne)
404# Output:
405# (8Pi^2) dP/dOmega / (Z*I^2)
406========================================================= */
407
408double AntCentFed(double L, double trad)
409{
410 double pil = M_PI*L;
411 double st = sin(trad), ct = cos(trad);
412 // L'antenne standing-wave
413 double v = 0.;
414 if(fabs(st)<1e-3) {
415 if(ct>0.) { // theta ~= 0
416 v = pil*sin(pil)*trad/2.; v *= v;
417 } else { // theta ~= 180
418 v = -pil*sin(pil)*(trad-M_PI)/2.; v *= v;
419 }
420 } else {
421 v = (cos(pil*ct) - cos(pil))/st; v *= v;
422 }
423
424 return v;
425}
426
427double AntDipole(double L, double trad)
428{
429 double pil = M_PI*L;
430 double st = sin(trad);
431 // L'approximation du dipole
432 double vd = pil*pil*st/2.; vd *= vd;
433 return vd;
434}
435
436double LobeSinc(double L, double trad)
437{
438 double x = M_PI*L*sin(trad);
439 return SinXsX_Sqr(x);
440}
441
442//-------------------------------------------------------------------
443
444static unsigned short IntegrateFunc_GlOrder = 0;
445static vector<double> IntegrateFunc_x;
446static vector<double> IntegrateFunc_w;
447
448///////////////////////////////////////////////////////////
449//************** Integration of Functions ***************//
450///////////////////////////////////////////////////////////
451
452
453////////////////////////////////////////////////////////////////////////////////////
454double IntegrateFunc(GenericFunc& func,double xmin,double xmax
455 ,double perc,double dxinc,double dxmax,unsigned short glorder)
456// --- Integration adaptative ---
457// Integrate[func[x], {x,xmin,xmax}]
458// ..xmin,xmax are the integration limits
459// ..dxinc is the searching increment x = xmin+i*dxinc
460// if <0 npt = int(|dxinc|) (si<2 alors npt=100)
461// et dxinc = (xmax-xmin)/npt
462// ..dxmax is the maximum possible increment (if dxmax<=0 no test)
463// ---
464// Partition de [xmin,xmax] en intervalles [x(i),x(i+1)]:
465// on parcourt [xmin,xmax] par pas de "dxinc" : x(i) = xmin + i*dxinc
466// on cree un intervalle [x(i),x(i+1)]
467// - si |f[x(i+1)] - f[x(i)]| > perc*|f[[x(i)]|
468// - si |x(i+1)-x(i)| >= dxmax (si dxmax>0.)
469// Dans un intervalle [x(i),x(i+1)] la fonction est integree
470// avec une methode de gauss-legendre d'ordre "glorder"
471{
472 double signe = 1.;
473 if(xmin>xmax) {double tmp=xmax; xmax=xmin; xmin=tmp; signe=-1.;}
474
475 if(glorder==0) glorder = 4;
476 if(perc<=0.) perc=0.1;
477 if(dxinc<=0.) {int n=int(-dxinc); if(n<2) n=100; dxinc=(xmax-xmin)/n;}
478 if(glorder != IntegrateFunc_GlOrder) {
479 IntegrateFunc_GlOrder = glorder;
480 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
481 }
482
483 // Recherche des intervalles [x(i),x(i+1)]
484 int_4 ninter = 0;
485 double sum = 0., xbas=xmin, fbas=func(xbas), fabsfbas=fabs(fbas);
486 for(double x=xmin+dxinc; x<xmax+dxinc/2.; x += dxinc) {
487 double f = func(x);
488 double dx = x-xbas;
489 bool doit = false;
490 if( x>xmax ) {doit = true; x=xmax;}
491 else if( dxmax>0. && dx>dxmax ) doit = true;
492 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
493 if( ! doit ) continue;
494 double s = 0.;
495 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++)
496 s += IntegrateFunc_w[i]*func(xbas+IntegrateFunc_x[i]*dx);
497 sum += s*dx;
498 xbas = x; fbas = f; fabsfbas=fabs(fbas); ninter++;
499 }
500 //cout<<"Ninter="<<ninter<<endl;
501
502 return sum*signe;
503}
504
505////////////////////////////////////////////////////////////////////////////////////
506double IntegrateFuncLog(GenericFunc& func,double lxmin,double lxmax
507 ,double perc,double dlxinc,double dlxmax,unsigned short glorder)
508// --- Integration adaptative ---
509// Idem IntegrateFunc but integrate on logarithmic (base 10) intervals:
510// Int[ f(x) dx ] = Int[ x*f(x) dlog10(x) ] * log(10)
511// ..lxmin,lxmax are the log10() of the integration limits
512// ..dlxinc is the searching logarithmic (base 10) increment lx = lxmin+i*dlxinc
513// ..dlxmax is the maximum possible logarithmic (base 10) increment (if dlxmax<=0 no test)
514// Remarque: to be use if "x*f(x) versus log10(x)" looks like a polynomial
515// better than "f(x) versus x"
516// ATTENTION: la fonction func que l'on passe en argument
517// est "func(x)" et non pas "func(log10(x))"
518{
519 double signe = 1.;
520 if(lxmin>lxmax) {double tmp=lxmax; lxmax=lxmin; lxmin=tmp; signe=-1.;}
521
522 if(glorder==0) glorder = 4;
523 if(perc<=0.) perc=0.1;
524 if(dlxinc<=0.) {int n=int(-dlxinc); if(n<2) n=100; dlxinc=(lxmax-lxmin)/n;}
525 if(glorder != IntegrateFunc_GlOrder) {
526 IntegrateFunc_GlOrder = glorder;
527 Compute_GaussLeg(glorder,IntegrateFunc_x,IntegrateFunc_w,0.,1.);
528 }
529
530 // Recherche des intervalles [lx(i),lx(i+1)]
531 int_4 ninter = 0;
532 double sum = 0., lxbas=lxmin, fbas=func(pow(10.,lxbas)), fabsfbas=fabs(fbas);
533 for(double lx=lxmin+dlxinc; lx<lxmax+dlxinc/2.; lx += dlxinc) {
534 double f = func(pow(10.,lx));
535 double dlx = lx-lxbas;
536 bool doit = false;
537 if( lx>lxmax ) {doit = true; lx=lxmax;}
538 else if( dlxmax>0. && dlx>dlxmax ) doit = true;
539 else if( fabs(f-fbas)>perc*fabsfbas ) doit = true;
540 if( ! doit ) continue;
541 double s = 0.;
542 for(unsigned short i=0;i<IntegrateFunc_GlOrder;i++) {
543 double y = pow(10.,lxbas+IntegrateFunc_x[i]*dlx);
544 s += IntegrateFunc_w[i]*y*func(y);
545 }
546 sum += s*dlx;
547 lxbas = lx; fbas = f; fabsfbas=fabs(fbas); ninter++;
548 }
549 //cout<<"Ninter="<<ninter<<endl;
550
551 return M_LN10*sum*signe;
552}
553
554////////////////////////////////////////////////////////////////////////////////////
555/*
556Integration des fonctions a une dimension y=f(x) par la Methode de Gauss-Legendre.
557 --> Calcul des coefficients du developpement pour [x1,x2]
558| INPUT:
559| x1,x2 : bornes de l'intervalle (dans nbinteg.h -> x1=-0.5 x2=0.5)
560| glorder = degre n du developpement de Gauss-Legendre
561| OUTPUT:
562| x[] = valeur des abscisses ou l'on calcule (dim=n)
563| w[] = valeur des coefficients associes
564| REMARQUES:
565| - x et w seront dimensionnes a n.
566| - l'integration est rigoureuse si sur l'intervalle d'integration
567| la fonction f(x) peut etre approximee par un polynome
568| de degre 2*m (monome le + haut x**(2*n-1) )
569*/
570void Compute_GaussLeg(unsigned short glorder,vector<double>& x,vector<double>& w,double x1,double x2)
571{
572 if(glorder==0) return;
573 int n = (int)glorder;
574 x.resize(n,0.); w.resize(n,0.);
575
576 int m,j,i;
577 double z1,z,xm,xl,pp,p3,p2,p1;
578
579 m=(n+1)/2;
580 xm=0.5*(x2+x1);
581 xl=0.5*(x2-x1);
582 for (i=1;i<=m;i++) {
583 z=cos(M_PI*(i-0.25)/(n+0.5));
584 do {
585 p1=1.0;
586 p2=0.0;
587 for (j=1;j<=n;j++) {
588 p3=p2;
589 p2=p1;
590 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
591 }
592 pp=n*(z*p1-p2)/(z*z-1.0);
593 z1=z;
594 z=z1-p1/pp;
595 } while (fabs(z-z1) > 3.0e-11); // epsilon
596 x[i-1]=xm-xl*z;
597 x[n-i]=xm+xl*z;
598 w[i-1]=2.0*xl/((1.0-z*z)*pp*pp);
599 w[n-i]=w[i-1];
600 }
601}
602
603} // Fin namespace SOPHYA
Note: See TracBrowser for help on using the repository browser.