source: Sophya/trunk/SophyaLib/NTools/integ.cc@ 2506

Last change on this file since 2506 was 2506, checked in by ansari, 22 years ago

Remplacement THROW par throw - Reza 15/03/2004

File size: 10.4 KB
Line 
1#include "integ.h"
2#include "generalfit.h"
3
4// A faire :
5// 1 dans GLInteg, optimiser recalcul en utilisant des poids
6// calcules sur [0,1] et chgt de variable
7// 2 dans GLInteg, distinction nStep = subdivisions de l'intervalle,
8// et on applique GL d'ordre "ordre" sur chaque subdivision, en
9// utilisant le (1)
10
11//++
12// Class Integrator
13// Lib Outils++
14// include integ.h
15//
16// Classe abstraite d'intégration numérique 1D.
17// On fournit une fonction double f(double) au constructeur, ou
18// une GeneralFunction avec des paramètres définis.
19// L'objet Integrator est convertible en valeur double qui est la valeur
20// de l'intégrale. Diverses méthodes permettent de choisir des options
21// de calcul, et ces méthodes retournent une référence sur l'objet, pour
22// permettre une notation chaînée.
23//--
24//++
25// Links Implementations
26// TrpzInteg
27// GLInteg
28//--
29
30//++
31// Titre Constructeurs
32//--
33
34//++
35Integrator::Integrator()
36//
37// Constructeur par défaut. L'objet n'est pas utilisable en l'état.
38//--
39
40: mFunc(NULL), mGFF(NULL), mGFFParm(NULL),
41 mNStep(50), mDX(-1), mReqPrec(-1),
42 mXMin(0), mXMax(1)
43{}
44
45//++
46Integrator::Integrator(FUNC f, double xmin, double xmax)
47//
48// Constructeur à partir de la fonction double->double, et des
49// bornes d'intégration.
50//--
51: mFunc(f), mGFF(NULL), mGFFParm(NULL),
52 mNStep(50), mDX(-1), mReqPrec(-1),
53 mXMin(xmin), mXMax(xmax)
54{}
55
56Integrator::Integrator(fun f, double xmin, double xmax)
57//
58// Constructeur à partir de la fonction double->double, et des
59// bornes d'intégration.
60//--
61: mFunc(new Function(f)), mGFF(NULL), mGFFParm(NULL),
62 mNStep(50), mDX(-1), mReqPrec(-1),
63 mXMin(xmin), mXMax(xmax)
64{}
65
66
67//++
68Integrator::Integrator(FUNC f)
69//
70// Constructeur sans spécifier les bornes. Elles sont positionnées
71// à [0,1], et on pourra les modifier plus tard.
72//--
73: mFunc(f), mGFF(NULL), mGFFParm(NULL),
74 mNStep(50), mDX(-1), mReqPrec(-1),
75 mXMin(0), mXMax(1)
76{}
77
78//++
79Integrator::Integrator(fun f)
80//
81// Constructeur sans spécifier les bornes. Elles sont positionnées
82// à [0,1], et on pourra les modifier plus tard.
83//--
84: mFunc(new Function(f)), mGFF(NULL), mGFFParm(NULL),
85 mNStep(50), mDX(-1), mReqPrec(-1),
86 mXMin(0), mXMax(1)
87{}
88
89//++
90Integrator::Integrator(GeneralFunction* gff, double* par, double xmin, double xmax)
91//
92// Constructeur à partir d'une GeneralFunction. La fonction doit être une
93// fonction de une variable, et on fournit les valeurs des paramètres ainsi
94// que les bornes d'intégration.
95//--
96: mFunc(NULL), mGFF(gff), mGFFParm(par),
97 mNStep(50), mDX(-1), mReqPrec(-1),
98 mXMin(xmin), mXMax(xmax)
99{
100 DBASSERT(gff->NVar() == 1);
101}
102
103//++
104Integrator::Integrator(GeneralFunction* gff, double* par)
105//
106// Constructeur à partir d'une GeneralFunction. La fonction doit être une
107// fonction de une variable, et on fournit les valeurs des paramètres.
108// On ne spécifie pas les bornes. Elles sont positionnées
109// à [0,1], et on pourra les modifier plus tard.
110//--
111: mFunc(NULL), mGFF(gff), mGFFParm(par),
112 mNStep(50), mDX(-1), mReqPrec(-1),
113 mXMin(0), mXMax(1)
114{
115 DBASSERT(gff->NVar() == 1);
116}
117
118Integrator::~Integrator()
119{if(mFunc) delete mFunc;}
120
121//++
122// Titre Méthodes
123//--
124
125//++
126Integrator&
127Integrator::NStep(int n)
128//
129// Spécifie le nombre de pas pour l'intégration numérique.
130// La signification peut dépendre de la méthode d'intégration.
131//--
132{
133 mNStep = n;
134 mDX = mReqPrec = -1;
135 StepsChanged();
136 return *this;
137}
138
139//++
140Integrator&
141Integrator::DX(double d)
142//
143// Spécifie le pas d'intégration.
144// La signification peut dépendre de la méthode d'intégration.
145//--
146{
147 mDX = d;
148 mNStep = mReqPrec = -1;
149 StepsChanged();
150 return *this;
151}
152
153//++
154Integrator&
155Integrator::ReqPrec(double p)
156//
157// Spécifie la précision souhaitée.
158// La signification peut dépendre de la méthode d'intégration.
159// Non disponible dans toutes les méthodes d'intégration.
160//--
161{
162 DBASSERT( !"Pas encore implemente !");
163 mReqPrec = p;
164 mDX = mNStep = -1;
165 StepsChanged();
166 return *this;
167}
168
169//++
170Integrator&
171Integrator::Limits(double xmin, double xmax)
172//
173// Spécifie les bornes de l'intégrale.
174//--
175{
176 mXMin = xmin;
177 mXMax = xmax;
178 LimitsChanged();
179 return *this;
180}
181
182//++
183Integrator&
184Integrator::Func(FUNC f)
185//
186// Spécifie la fonction à intégrer, sous forme double f(double).
187//--
188{
189 mFunc = f;
190 mGFFParm = NULL;
191 mFunc = NULL;
192 FuncChanged();
193 return *this;
194}
195
196//++
197Integrator&
198Integrator::Func(GeneralFunction* gff, double* par)
199//
200// Spécifie la fonction à intégrer, sous forme de GeneralFunction
201// à une variable, et les paramètres sont fournis.
202//--
203{
204 mGFF = gff;
205 mGFFParm = par;
206 mFunc = NULL;
207 DBASSERT(gff->NVar() == 1);
208 FuncChanged();
209 return *this;
210}
211
212double
213Integrator::FVal(double x) const
214{
215 DBASSERT( mFunc || (mGFF && mGFFParm) );
216 return mFunc ? (*mFunc)(x) : mGFF->Value(&x, mGFFParm);
217 }
218
219double
220Integrator::ValueBetween(double xmin, double xmax)
221{
222 Limits(xmin,xmax);
223 return Value();
224}
225
226void
227Integrator::Print(int lp)
228{
229 cout<<"Integrator between "<<mXMin<<" and "<<mXMax
230 <<" in "<<mNStep<<" steps"<<endl;
231 if(lp>1) cout<<"mFunc="<<mFunc<<"mGFF="<<mGFF
232 <<"mReqPrec="<<mReqPrec<<"mDX="<<mDX<<endl;
233}
234
235//++
236// Class TrpzInteg
237// Lib Outils++
238// include integ.h
239//
240// Classe d'intégration par la méthode des trapèzes.
241// Voir Integrator pour les méthodes. Le nombre de pas
242// est le nombre de trapèze, le pas d'intégration est
243// la largeur des trapèzez. Impossible de demander une
244// précision.
245//
246//--
247//++
248// Links Parents
249// Integrator
250//--
251
252//++
253// Titre Constructeurs
254// Voir Integrator pour les détails.
255//--
256
257//++
258TrpzInteg::TrpzInteg()
259//
260//--
261{}
262
263//++
264TrpzInteg::TrpzInteg(FUNC f, double xmin, double xmax)
265//
266//--
267: Integrator(f, xmin, xmax)
268{}
269//++
270TrpzInteg::TrpzInteg(fun f, double xmin, double xmax)
271//
272//--
273: Integrator(f, xmin, xmax)
274{}
275
276//++
277TrpzInteg::TrpzInteg(FUNC f)
278//
279//--
280: Integrator(f)
281{}
282
283TrpzInteg::TrpzInteg(fun f)
284//
285//--
286: Integrator(f)
287{}
288
289//++
290TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
291//
292//--
293: Integrator(gff, par, xmin, xmax)
294{}
295
296//++
297TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par)
298//
299//--
300: Integrator(gff, par)
301{}
302
303TrpzInteg::~TrpzInteg()
304{}
305
306double
307TrpzInteg::Value()
308{
309 double dx = mDX;
310 double nstep = mNStep;
311
312 if (dx > 0)
313 nstep = (mXMax - mXMin)/dx;
314
315 if (nstep <= 0)
316 nstep = 10;
317
318 dx = (mXMax - mXMin) / nstep;
319
320 double s = (FVal(mXMin) + FVal(mXMax))/2;
321 double x = dx + mXMin;
322 for (int i=1; i<nstep; i++, x += dx)
323 s += FVal(x);
324
325 return s * dx;
326}
327
328
329
330//++
331// Class GLInteg
332// Lib Outils++
333// include integ.h
334//
335// Classe d'intégration par la méthode de Gauss-Legendre.
336// Voir Integrator pour les méthodes.
337// Pour le moment, nstep est l'ordre de la méthode.
338// Il est prévu un jour de spécifier l'ordre, et que NStep
339// découpe en intervalles sur chacun desquels on applique GL.
340// Le principe de la méthode est de calculer les valeurs de la
341// fonction aux zéros des polynomes de Legendre. Avec les poids
342// qui vont bien, GL d'ordre n est exacte pour des polynomes de
343// degré <= 2n+1 (monome le + haut x^(2*n-1).
344// Impossible de demander une précision donnée.
345//
346//--
347//++
348// Links Parents
349// Integrator
350//--
351
352//++
353// Titre Constructeurs
354// Voir Integrator pour les détails.
355//--
356
357
358
359
360//++
361GLInteg::GLInteg()
362//
363//--
364: mXPos(NULL), mWeights(NULL)
365{}
366
367
368//++
369GLInteg::GLInteg(FUNC f, double xmin, double xmax)
370//
371//--
372: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
373{
374 NStep(1);
375}
376GLInteg::GLInteg(fun f, double xmin, double xmax)
377//
378//--
379: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
380{
381 NStep(1);
382}
383//++
384GLInteg::GLInteg(FUNC f)
385//
386//--
387: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
388{
389 NStep(1);
390}
391GLInteg::GLInteg(fun f)
392//
393//--
394: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
395{
396 NStep(1);
397}
398
399//++
400GLInteg::GLInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
401//
402//--
403: Integrator(gff, par, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
404{
405 NStep(1);
406}
407
408//++
409GLInteg::GLInteg(GeneralFunction* gff, double* par)
410//
411//--
412: Integrator(gff, par), mXPos(NULL), mWeights(NULL), mOrder(8)
413{
414 NStep(1);
415}
416
417GLInteg::~GLInteg()
418{
419 if(mXPos) delete[] mXPos; mXPos = NULL;
420 if(mWeights) delete[] mWeights; mWeights = NULL;
421}
422
423void
424GLInteg::InvalWeights()
425{
426 if(mXPos) delete[] mXPos; mXPos = NULL;
427 if(mWeights) delete[] mWeights; mWeights = NULL;
428}
429
430
431void
432GLInteg::LimitsChanged()
433{
434 ComputeBounds();
435}
436
437void
438GLInteg::StepsChanged()
439{
440 ComputeBounds();
441}
442
443GLInteg&
444GLInteg::AddBound(double x)
445{
446 if (x<=mXMin || x>=mXMax) throw RangeCheckError("GLInteg::AddBound()") ;
447 // On introduira les classes d'exections apres reflexion et de maniere systematique (Rz+cmv)
448 // if (x<=mXMin || x>=mXMax) throw range_error("GLInteg::AddBound bound outside interval");
449 mBounds.insert(x);
450 return *this;
451}
452
453
454GLInteg&
455GLInteg::SetOrder(int order)
456{
457 mOrder = order;
458 InvalWeights();
459 return *this;
460}
461
462
463
464double
465GLInteg::Value()
466{
467 if (!mXPos) ComputeWeights();
468 double s = 0;
469 set<double>::iterator i=mBounds.begin();
470 set<double>::iterator j=i; j++;
471 while (j != mBounds.end()) {
472 double s1 = 0;
473 double x1 = *i;
474 double x2 = *j;
475 for(int k=0; k<mOrder; k++)
476 s1 += mWeights[k] * FVal(x1 + (x2-x1)*mXPos[k]);
477 s += s1*(x2-x1);
478 i++; j++;
479 }
480 return s;
481}
482
483void
484GLInteg::ComputeBounds()
485{
486 mBounds.erase(mBounds.begin(), mBounds.end());
487 for (int i=0; i<=mNStep; i++)
488 mBounds.insert(mXMin + (mXMax-mXMin)*i/mNStep);
489}
490
491void
492GLInteg::ComputeWeights()
493{
494 const double EPS_gauleg = 5.0e-12;
495
496 int m=(mOrder+1)/2;
497 const double xxMin = 0;
498 const double xxMax = 1;
499
500 mXPos = new double[mOrder];
501 mWeights = new double[mOrder];
502
503 double xm=0.5*(xxMax+xxMin);
504 double xl=0.5*(xxMax-xxMin);
505 for (int i=1;i<=m;i++) {
506 double z=cos(3.141592654*(i-0.25)/(mOrder+0.5));
507 double z1, pp;
508 do {
509 double p1=1.0;
510 double p2=0.0;
511 for (int j=1;j<=mOrder;j++) {
512 double p3=p2;
513 p2=p1;
514 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
515 }
516 pp=mOrder*(z*p1-p2)/(z*z-1.0);
517 z1=z;
518 z=z1-p1/pp;
519 } while (fabs(z-z1) > EPS_gauleg);
520 mXPos[i-1] = xm-xl*z;
521 mXPos[mOrder-i] = xm+xl*z;
522 mWeights[i-1] = 2.0*xl/((1.0-z*z)*pp*pp);
523 mWeights[mOrder-i] = mWeights[i-1];
524 }
525
526}
527
528void
529GLInteg::Print(int lp)
530{
531 Integrator::Print(lp);
532 cout<<"GLInteg order="<<mOrder<<endl;
533 if(lp>0 && mOrder>0) {
534 for(int i=0;i<mOrder;i++)
535 cout<<" ("<<mXPos[i]<<","<<mWeights[i]<<")";
536 cout<<endl;
537 }
538}
Note: See TracBrowser for help on using the repository browser.