#include "sopnamsp.h" #include "integ.h" #include "generalfit.h" // A faire : // 1 dans GLInteg, optimiser recalcul en utilisant des poids // calcules sur [0,1] et chgt de variable // 2 dans GLInteg, distinction nStep = subdivisions de l'intervalle, // et on applique GL d'ordre "ordre" sur chaque subdivision, en // utilisant le (1) /*! \ingroup NTools \class SOPHYA::Integrator \brief Classe abstraite d'intégration numérique 1D. On fournit une fonction double f(double) au constructeur, ou une classe-fonction (ClassFuc) ou une GeneralFunction avec des paramètres définis. L'objet Integrator est convertible en valeur double qui est la valeur de l'intégrale. Diverses méthodes permettent de choisir des options de calcul, et ces méthodes retournent une référence sur l'objet, pour permettre une notation chaînée. \sa TrpzInteg GLInteg */ //! Constructeur par défaut. L'objet n'est pas utilisable en l'état. Integrator::Integrator() : mFunc(NULL), mClFun(NULL), mGFF(NULL), mGFFParm(NULL), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(0), mXMax(1) {} //! Constructeur à partir d'une classe-fonction, et des bornes d'intégration. Integrator::Integrator(ClassFunc & f, double xmin, double xmax) : mFunc(NULL), mClFun(&f), mGFF(NULL), mGFFParm(NULL), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(xmin), mXMax(xmax) {} //! Constructeur à partir de la fonction double->double, et des bornes d'intégration. Integrator::Integrator(FUNC f, double xmin, double xmax) : mFunc(f), mClFun(NULL), mGFF(NULL), mGFFParm(NULL), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(xmin), mXMax(xmax) {} /*! Constructeur a partir d'une classe-fonction sans spécifier les bornes. Elles sont positionnées à [0,1], et on pourra les modifier plus tard. */ Integrator::Integrator(ClassFunc & f) : mFunc(NULL), mClFun(&f), mGFF(NULL), mGFFParm(NULL), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(0), mXMax(1) {} /*! Constructeur sans spécifier les bornes. Elles sont positionnées à [0,1], et on pourra les modifier plus tard. */ Integrator::Integrator(FUNC f) : mFunc(f), mClFun(NULL), mGFF(NULL), mGFFParm(NULL), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(0), mXMax(1) {} /*! Constructeur à partir d'une GeneralFunction. La fonction doit être une fonction de une variable, et on fournit les valeurs des paramètres ainsi que les bornes d'intégration. */ Integrator::Integrator(GeneralFunction* gff, double* par, double xmin, double xmax) : mFunc(NULL), mClFun(NULL), mGFF(gff), mGFFParm(par), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(xmin), mXMax(xmax) { DBASSERT(gff->NVar() == 1); } /*! Constructeur à partir d'une GeneralFunction. La fonction doit être une fonction de une variable, et on fournit les valeurs des paramètres. On ne spécifie pas les bornes. Elles sont positionnées à [0,1], et on pourra les modifier plus tard. */ Integrator::Integrator(GeneralFunction* gff, double* par) : mFunc(NULL), mClFun(NULL), mGFF(gff), mGFFParm(par), mNStep(50), mDX(-1), mReqPrec(-1), mXMin(0), mXMax(1) { DBASSERT(gff->NVar() == 1); } Integrator::~Integrator() { } /*! \brief Spécifie le nombre de pas pour l'intégration numérique. La signification peut dépendre de la méthode d'intégration. */ Integrator& Integrator::NStep(int n) { mNStep = n; mDX = mReqPrec = -1; StepsChanged(); return *this; } /*! \brief Spécifie le nombre de pas pour l'intégration numérique. La signification peut dépendre de la méthode d'intégration. */ Integrator& Integrator::DX(double d) { mDX = d; mNStep = -1; mReqPrec = -1.; StepsChanged(); return *this; } /*! \brief Spécifie la précision souhaitée. La signification peut dépendre de la méthode d'intégration. Non disponible dans toutes les méthodes d'intégration. */ Integrator& Integrator::ReqPrec(double p) { DBASSERT( !"Pas encore implemente !"); mReqPrec = p; mDX = mNStep = -1; StepsChanged(); return *this; } //! Spécifie les bornes de l'intégrale. Integrator& Integrator::Limits(double xmin, double xmax) { mXMin = xmin; mXMax = xmax; LimitsChanged(); return *this; } //! Spécifie la fonction à intégrer, sous forme double f(double). Integrator& Integrator::SetFunc(ClassFunc & f) { mFunc = NULL; mClFun = &f; mGFFParm = NULL; mFunc = NULL; FuncChanged(); return *this; } //! Spécifie la fonction à intégrer, sous forme double f(double). Integrator& Integrator::SetFunc(FUNC f) { mFunc = f; mClFun = NULL; mGFFParm = NULL; mFunc = NULL; FuncChanged(); return *this; } /*! \brief Spécifie la fonction à intégrer, sous forme de GeneralFunction à une variable, et les paramètres sont fournis. */ Integrator& Integrator::SetFunc(GeneralFunction* gff, double* par) { mGFF = gff; mGFFParm = par; mFunc = NULL; DBASSERT(gff->NVar() == 1); FuncChanged(); return *this; } double Integrator::FVal(double x) const { DBASSERT( mFunc || mClFun || (mGFF && mGFFParm) ); if (mFunc) return mFunc(x); else return mClFun ? (*mClFun)(x) : mGFF->Value(&x, mGFFParm); } double Integrator::ValueBetween(double xmin, double xmax) { Limits(xmin,xmax); return Value(); } void Integrator::Print(int lp) { cout<<"Integrator between "<1) cout<<"mFunc="<=mXMax) throw range_error("GLInteg::AddBound bound outside interval"); mBounds.insert(x); return *this; } //! Definit l'ordre de la methode d'integration Gauus-Legendre GLInteg& GLInteg::SetOrder(int order) { mOrder = order; InvalWeights(); return *this; } //! Retourne la valeur de l'integrale double GLInteg::Value() { if (!mXPos) ComputeWeights(); double s = 0; set::iterator i=mBounds.begin(); set::iterator j=i; j++; while (j != mBounds.end()) { double s1 = 0; double x1 = *i; double x2 = *j; for(int k=0; k EPS_gauleg); mXPos[i-1] = xm-xl*z; mXPos[mOrder-i] = xm+xl*z; mWeights[i-1] = 2.0*xl/((1.0-z*z)*pp*pp); mWeights[mOrder-i] = mWeights[i-1]; } } //! Imprime l'ordre et la valeur des poids sur cout void GLInteg::Print(int lp) { Integrator::Print(lp); cout<<"GLInteg order="<0 && mOrder>0) { for(int i=0;i