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

Last change on this file since 2283 was 2283, checked in by plaszczy, 23 years ago

ajout de classfunc et changements dans integ pour que ca colle

File size: 9.8 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{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
226//++
227// Class TrpzInteg
228// Lib Outils++
229// include integ.h
230//
231// Classe d'intégration par la méthode des trapèzes.
232// Voir Integrator pour les méthodes. Le nombre de pas
233// est le nombre de trapèze, le pas d'intégration est
234// la largeur des trapèzez. Impossible de demander une
235// précision.
236//
237//--
238//++
239// Links Parents
240// Integrator
241//--
242
243//++
244// Titre Constructeurs
245// Voir Integrator pour les détails.
246//--
247
248//++
249TrpzInteg::TrpzInteg()
250//
251//--
252{}
253
254//++
255TrpzInteg::TrpzInteg(FUNC f, double xmin, double xmax)
256//
257//--
258: Integrator(f, xmin, xmax)
259{}
260//++
261TrpzInteg::TrpzInteg(fun f, double xmin, double xmax)
262//
263//--
264: Integrator(f, xmin, xmax)
265{}
266
267//++
268TrpzInteg::TrpzInteg(FUNC f)
269//
270//--
271: Integrator(f)
272{}
273
274TrpzInteg::TrpzInteg(fun f)
275//
276//--
277: Integrator(f)
278{}
279
280//++
281TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
282//
283//--
284: Integrator(gff, par, xmin, xmax)
285{}
286
287//++
288TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par)
289//
290//--
291: Integrator(gff, par)
292{}
293
294TrpzInteg::~TrpzInteg()
295{}
296
297double
298TrpzInteg::Value()
299{
300 double dx = mDX;
301 double nstep = mNStep;
302
303 if (dx > 0)
304 nstep = (mXMax - mXMin)/dx;
305
306 if (nstep <= 0)
307 nstep = 10;
308
309 dx = (mXMax - mXMin) / nstep;
310
311 double s = (FVal(mXMin) + FVal(mXMax))/2;
312 double x = dx + mXMin;
313 for (int i=1; i<nstep; i++, x += dx)
314 s += FVal(x);
315
316 return s * dx;
317}
318
319
320
321//++
322// Class GLInteg
323// Lib Outils++
324// include integ.h
325//
326// Classe d'intégration par la méthode de Gauss-Legendre.
327// Voir Integrator pour les méthodes.
328// Pour le moment, nstep est l'ordre de la méthode.
329// Il est prévu un jour de spécifier l'ordre, et que NStep
330// découpe en intervalles sur chacun desquels on applique GL.
331// Le principe de la méthode est de calculer les valeurs de la
332// fonction aux zéros des polynomes de Legendre. Avec les poids
333// qui vont bien, GL d'ordre n est exacte pour des polynomes de
334// degré <= 2n+1.
335// Impossible de demander une précision donnée.
336//
337//--
338//++
339// Links Parents
340// Integrator
341//--
342
343//++
344// Titre Constructeurs
345// Voir Integrator pour les détails.
346//--
347
348
349
350
351//++
352GLInteg::GLInteg()
353//
354//--
355: mXPos(NULL), mWeights(NULL)
356{}
357
358
359//++
360GLInteg::GLInteg(FUNC f, double xmin, double xmax)
361//
362//--
363: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
364{
365 NStep(1);
366}
367GLInteg::GLInteg(fun f, double xmin, double xmax)
368//
369//--
370: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
371{
372 NStep(1);
373}
374//++
375GLInteg::GLInteg(FUNC f)
376//
377//--
378: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
379{
380 NStep(1);
381}
382GLInteg::GLInteg(fun f)
383//
384//--
385: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
386{
387 NStep(1);
388}
389
390//++
391GLInteg::GLInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
392//
393//--
394: Integrator(gff, par, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
395{
396 NStep(1);
397}
398
399//++
400GLInteg::GLInteg(GeneralFunction* gff, double* par)
401//
402//--
403: Integrator(gff, par), mXPos(NULL), mWeights(NULL), mOrder(8)
404{
405 NStep(1);
406}
407
408GLInteg::~GLInteg()
409{
410 delete[] mXPos;
411 delete[] mWeights;
412 mXPos = mWeights = NULL;
413}
414
415void
416GLInteg::InvalWeights()
417{
418 delete[] mXPos;
419 delete[] mWeights;
420 mXPos = mWeights = NULL;
421}
422
423
424void
425GLInteg::LimitsChanged()
426{
427 ComputeBounds();
428}
429
430void
431GLInteg::StepsChanged()
432{
433 ComputeBounds();
434}
435
436GLInteg&
437GLInteg::AddBound(double x)
438{
439 if (x<=mXMin || x>=mXMax) THROW(rangeCheckErr);
440 // On introduira les classes d'exections apres reflexion et de maniere systematique (Rz+cmv)
441 // if (x<=mXMin || x>=mXMax) throw range_error("GLInteg::AddBound bound outside interval");
442 mBounds.insert(x);
443 return *this;
444}
445
446
447GLInteg&
448GLInteg::SetOrder(int order)
449{
450 mOrder = order;
451 InvalWeights();
452 return *this;
453}
454
455
456
457double
458GLInteg::Value()
459{
460 if (!mXPos) ComputeWeights();
461 double s = 0;
462 set<double>::iterator i=mBounds.begin();
463 set<double>::iterator j=i; j++;
464 while (j != mBounds.end()) {
465 double s1 = 0;
466 double x1 = *i;
467 double x2 = *j;
468 for (int k=0; k<mOrder; k++)
469 s1 += mWeights[k] * FVal(x1 + (x2-x1)*mXPos[k]);
470 s += s1*(x2-x1);
471 i++; j++;
472 }
473 return s;
474}
475
476void
477GLInteg::ComputeBounds()
478{
479 mBounds.erase(mBounds.begin(), mBounds.end());
480 for (int i=0; i<=mNStep; i++)
481 mBounds.insert(mXMin + (mXMax-mXMin)*i/mNStep);
482}
483
484void
485GLInteg::ComputeWeights()
486{
487 const double EPS_gauleg = 3.0e-11;
488
489 int m=(mOrder+1)/2;
490 const double xxMin = 0;
491 const double xxMax = 1;
492
493 mXPos = new double[mOrder];
494 mWeights = new double[mOrder];
495
496 double xm=0.5*(xxMax+xxMin);
497 double xl=0.5*(xxMax-xxMin);
498 for (int i=1;i<=m;i++) {
499 double z=cos(3.141592654*(i-0.25)/(mOrder+0.5));
500 double z1, pp;
501 do {
502 double p1=1.0;
503 double p2=0.0;
504 for (int j=1;j<=mOrder;j++) {
505 double p3=p2;
506 p2=p1;
507 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
508 }
509 pp=mOrder*(z*p1-p2)/(z*z-1.0);
510 z1=z;
511 z=z1-p1/pp;
512 } while (fabs(z-z1) > EPS_gauleg);
513 mXPos[i-1] = xm-xl*z;
514 mXPos[mOrder-i] = xm+xl*z;
515 mWeights[i-1] = 2.0*xl/((1.0-z*z)*pp*pp);
516 mWeights[mOrder-i] = mWeights[i-1];
517 }
518
519}
520
Note: See TracBrowser for help on using the repository browser.