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

Last change on this file since 2928 was 2808, checked in by ansari, 20 years ago

MAJ documentation - Reza 14/6/2005

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