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

Last change on this file since 2683 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

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