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

Last change on this file since 220 was 220, checked in by ansari, 26 years ago

Creation module DPC/NTools Reza 09/04/99

File size: 8.9 KB
Line 
1#include "defs.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
57//++
58Integrator::Integrator(FUNC f)
59//
60// Constructeur sans spécifier les bornes. Elles sont positionnées
61// à [0,1], et on pourra les modifier plus tard.
62//--
63: mFunc(f), mGFF(NULL), mGFFParm(NULL),
64 mNStep(50), mDX(-1), mReqPrec(-1),
65 mXMin(0), mXMax(1)
66{}
67
68//++
69Integrator::Integrator(GeneralFunction* gff, double* par, double xmin, double xmax)
70//
71// Constructeur à partir d'une GeneralFunction. La fonction doit être une
72// fonction de une variable, et on fournit les valeurs des paramètres ainsi
73// que les bornes d'intégration.
74//--
75: mFunc(NULL), mGFF(gff), mGFFParm(par),
76 mNStep(50), mDX(-1), mReqPrec(-1),
77 mXMin(xmin), mXMax(xmax)
78{
79 DBASSERT(gff->NVar() == 1);
80}
81
82//++
83Integrator::Integrator(GeneralFunction* gff, double* par)
84//
85// Constructeur à partir d'une GeneralFunction. La fonction doit être une
86// fonction de une variable, et on fournit les valeurs des paramètres.
87// On ne spécifie pas les bornes. Elles sont positionnées
88// à [0,1], et on pourra les modifier plus tard.
89//--
90: mFunc(NULL), mGFF(gff), mGFFParm(par),
91 mNStep(50), mDX(-1), mReqPrec(-1),
92 mXMin(0), mXMax(1)
93{
94 DBASSERT(gff->NVar() == 1);
95}
96
97Integrator::~Integrator()
98{}
99
100//++
101// Titre Méthodes
102//--
103
104//++
105Integrator&
106Integrator::NStep(int n)
107//
108// Spécifie le nombre de pas pour l'intégration numérique.
109// La signification peut dépendre de la méthode d'intégration.
110//--
111{
112 mNStep = n;
113 mDX = mReqPrec = -1;
114 StepsChanged();
115 return *this;
116}
117
118//++
119Integrator&
120Integrator::DX(double d)
121//
122// Spécifie le pas d'intégration.
123// La signification peut dépendre de la méthode d'intégration.
124//--
125{
126 mDX = d;
127 mNStep = mReqPrec = -1;
128 StepsChanged();
129 return *this;
130}
131
132//++
133Integrator&
134Integrator::ReqPrec(double p)
135//
136// Spécifie la précision souhaitée.
137// La signification peut dépendre de la méthode d'intégration.
138// Non disponible dans toutes les méthodes d'intégration.
139//--
140{
141 DBASSERT( !"Pas encore implemente !");
142 mReqPrec = p;
143 mDX = mNStep = -1;
144 StepsChanged();
145 return *this;
146}
147
148//++
149Integrator&
150Integrator::Limits(double xmin, double xmax)
151//
152// Spécifie les bornes de l'intégrale.
153//--
154{
155 mXMin = xmin;
156 mXMax = xmax;
157 LimitsChanged();
158 return *this;
159}
160
161//++
162Integrator&
163Integrator::Func(FUNC f)
164//
165// Spécifie la fonction à intégrer, sous forme double f(double).
166//--
167{
168 mFunc = f;
169 mGFFParm = NULL;
170 mFunc = NULL;
171 FuncChanged();
172 return *this;
173}
174
175//++
176Integrator&
177Integrator::Func(GeneralFunction* gff, double* par)
178//
179// Spécifie la fonction à intégrer, sous forme de GeneralFunction
180// à une variable, et les paramètres sont fournis.
181//--
182{
183 mGFF = gff;
184 mGFFParm = par;
185 mFunc = NULL;
186 DBASSERT(gff->NVar() == 1);
187 FuncChanged();
188 return *this;
189}
190
191double
192Integrator::FVal(double x) const
193{
194 DBASSERT( mFunc || (mGFF && mGFFParm) );
195 return mFunc ? (*mFunc)(x) : mGFF->Value(&x, mGFFParm);
196}
197
198double
199Integrator::ValueBetween(double xmin, double xmax)
200{
201 Limits(xmin,xmax);
202 return Value();
203}
204
205//++
206// Class TrpzInteg
207// Lib Outils++
208// include integ.h
209//
210// Classe d'intégration par la méthode des trapèzes.
211// Voir Integrator pour les méthodes. Le nombre de pas
212// est le nombre de trapèze, le pas d'intégration est
213// la largeur des trapèzez. Impossible de demander une
214// précision.
215//
216//--
217//++
218// Links Parents
219// Integrator
220//--
221
222//++
223// Titre Constructeurs
224// Voir Integrator pour les détails.
225//--
226
227//++
228TrpzInteg::TrpzInteg()
229//
230//--
231{}
232
233//++
234TrpzInteg::TrpzInteg(FUNC f, double xmin, double xmax)
235//
236//--
237: Integrator(f, xmin, xmax)
238{}
239
240//++
241TrpzInteg::TrpzInteg(FUNC f)
242//
243//--
244: Integrator(f)
245{}
246
247//++
248TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
249//
250//--
251: Integrator(gff, par, xmin, xmax)
252{}
253
254//++
255TrpzInteg::TrpzInteg(GeneralFunction* gff, double* par)
256//
257//--
258: Integrator(gff, par)
259{}
260
261TrpzInteg::~TrpzInteg()
262{}
263
264double
265TrpzInteg::Value()
266{
267 double dx = mDX;
268 double nstep = mNStep;
269
270 if (dx > 0)
271 nstep = (mXMax - mXMin)/dx;
272
273 if (nstep <= 0)
274 nstep = 10;
275
276 dx = (mXMax - mXMin) / nstep;
277
278 double s = (FVal(mXMin) + FVal(mXMax))/2;
279 double x = dx + mXMin;
280 for (int i=1; i<nstep; i++, x += dx)
281 s += FVal(x);
282
283 return s * dx;
284}
285
286
287
288//++
289// Class GLInteg
290// Lib Outils++
291// include integ.h
292//
293// Classe d'intégration par la méthode de Gauss-Legendre.
294// Voir Integrator pour les méthodes.
295// Pour le moment, nstep est l'ordre de la méthode.
296// Il est prévu un jour de spécifier l'ordre, et que NStep
297// découpe en intervalles sur chacun desquels on applique GL.
298// Le principe de la méthode est de calculer les valeurs de la
299// fonction aux zéros des polynomes de Legendre. Avec les poids
300// qui vont bien, GL d'ordre n est exacte pour des polynomes de
301// degré <= 2n+1.
302// Impossible de demander une précision donnée.
303//
304//--
305//++
306// Links Parents
307// Integrator
308//--
309
310//++
311// Titre Constructeurs
312// Voir Integrator pour les détails.
313//--
314
315
316
317
318//++
319GLInteg::GLInteg()
320//
321//--
322: mXPos(NULL), mWeights(NULL)
323{}
324
325
326//++
327GLInteg::GLInteg(FUNC f, double xmin, double xmax)
328//
329//--
330: Integrator(f, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
331{
332 NStep(1);
333}
334
335//++
336GLInteg::GLInteg(FUNC f)
337//
338//--
339: Integrator(f), mXPos(NULL), mWeights(NULL), mOrder(8)
340{
341 NStep(1);
342}
343
344//++
345GLInteg::GLInteg(GeneralFunction* gff, double* par, double xmin, double xmax)
346//
347//--
348: Integrator(gff, par, xmin, xmax), mXPos(NULL), mWeights(NULL), mOrder(8)
349{
350 NStep(1);
351}
352
353//++
354GLInteg::GLInteg(GeneralFunction* gff, double* par)
355//
356//--
357: Integrator(gff, par), mXPos(NULL), mWeights(NULL), mOrder(8)
358{
359 NStep(1);
360}
361
362GLInteg::~GLInteg()
363{
364 delete[] mXPos;
365 delete[] mWeights;
366 mXPos = mWeights = NULL;
367}
368
369void
370GLInteg::InvalWeights()
371{
372 delete[] mXPos;
373 delete[] mWeights;
374 mXPos = mWeights = NULL;
375}
376
377
378void
379GLInteg::LimitsChanged()
380{
381 ComputeBounds();
382}
383
384void
385GLInteg::StepsChanged()
386{
387 ComputeBounds();
388}
389
390GLInteg&
391GLInteg::AddBound(double x)
392{
393 if (x<=mXMin || x>=mXMax) THROW(rangeCheckErr);
394 // On introduira les classes d'exections apres reflexion et de maniere systematique (Rz+cmv)
395 // if (x<=mXMin || x>=mXMax) throw range_error("GLInteg::AddBound bound outside interval");
396 mBounds.insert(x);
397 return *this;
398}
399
400
401GLInteg&
402GLInteg::SetOrder(int order)
403{
404 mOrder = order;
405 InvalWeights();
406 return *this;
407}
408
409
410
411double
412GLInteg::Value()
413{
414 if (!mXPos) ComputeWeights();
415 double s = 0;
416 set<double>::iterator i=mBounds.begin();
417 set<double>::iterator j=i; j++;
418 while (j != mBounds.end()) {
419 double s1 = 0;
420 double x1 = *i;
421 double x2 = *j;
422 for (int k=0; k<mOrder; k++)
423 s1 += mWeights[k] * FVal(x1 + (x2-x1)*mXPos[k]);
424 s += s1*(x2-x1);
425 i++; j++;
426 }
427 return s;
428}
429
430void
431GLInteg::ComputeBounds()
432{
433 mBounds.erase(mBounds.begin(), mBounds.end());
434 for (int i=0; i<=mNStep; i++)
435 mBounds.insert(mXMin + (mXMax-mXMin)*i/mNStep);
436}
437
438void
439GLInteg::ComputeWeights()
440{
441 const double EPS_gauleg = 3.0e-11;
442
443 int m=(mOrder+1)/2;
444 const double xxMin = 0;
445 const double xxMax = 1;
446
447 mXPos = new double[mOrder];
448 mWeights = new double[mOrder];
449
450 double xm=0.5*(xxMax+xxMin);
451 double xl=0.5*(xxMax-xxMin);
452 for (int i=1;i<=m;i++) {
453 double z=cos(3.141592654*(i-0.25)/(mOrder+0.5));
454 double z1, pp;
455 do {
456 double p1=1.0;
457 double p2=0.0;
458 for (int j=1;j<=mOrder;j++) {
459 double p3=p2;
460 p2=p1;
461 p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
462 }
463 pp=mOrder*(z*p1-p2)/(z*z-1.0);
464 z1=z;
465 z=z1-p1/pp;
466 } while (fabs(z-z1) > EPS_gauleg);
467 mXPos[i-1] = xm-xl*z;
468 mXPos[mOrder-i] = xm+xl*z;
469 mWeights[i-1] = 2.0*xl/((1.0-z*z)*pp*pp);
470 mWeights[mOrder-i] = mWeights[i-1];
471 }
472
473}
474
Note: See TracBrowser for help on using the repository browser.