// This may look like C code, but it is really -*- C++ -*- #ifndef DIFEQ_H_SEEN #define DIFEQ_H_SEEN #include "machdefs.h" #include "pexceptions.h" #include "tvector.h" namespace SOPHYA { class GeneralFunction; // fonction pour equadifs // Une fonction utilisee pour les equations differentielles. // On resoud de facon generale un systeme de n equations differentielles, // donnant les derivees fpi de n fonctions fi. class DiffEqFunction EXC_AWARE { public: // Constructeur. n = nombre de fonctions dans le systeme DiffEqFunction(int n) : mNFunc(n), mNFuncApp(n) {} // Constructeur. n = nombre reel de fonctions dans le systeme, // m = nombre apparent (il y a dans certaines cas des fonctions a // usage interne, par exemple la fonction constante valant 1...) DiffEqFunction(int n, int m) : mNFunc(n), mNFuncApp(m) {} // Destructeur virtual ~DiffEqFunction() {} // Calcule les valeurs des derivees fpi a partir des valeurs des fonctions fi virtual void ComputeV(Vector& fpi, Vector const& fi) { Compute(fpi(0), fi(0)); } // Dans le cas ou on a une seule fonction, calcule la valeur de la derivee fp // a partir de la valeur de la fonction virtual void Compute(double& /*fp*/, double /*f*/) { ASSERT(mNFunc == 1); } // Nombre apparent de fonctions dans le systeme int NFunc() {return mNFuncApp;} // Nombre reel de fonctions dans le systeme int NFuncReal() {return mNFunc;} // Pour ajuster vecteur de depart quand il y a des fonctions a usage // interne... virtual void AdjustStart(Vector& /*start*/, double /*tstart*/) {} protected: // Nombre de fonctions dans le systeme int mNFunc; // Nombre apparent de fonctions int mNFuncApp; }; // Cas y' = f(y) typedef double(*DIFEQFCN1)(double); // Cas y' = f(y) // Cas y' = f(y), on fournit la fonction f, sous la forme // double f(double), et ca construit la bonne DiffEqFunction class DiffEqFcn1 : public DiffEqFunction { public: // Constructeur, on fournit une fonction double->double // qui donne y' en fonction de y. DiffEqFcn1(DIFEQFCN1); // Implementation de Compute qui va utiliser la fonction fournie // au constructeur. virtual void Compute(double& fp, double f); protected: DIFEQFCN1 mFcn; }; // Cas y' = f(y,t) typedef double(*DIFEQFCNT1)(double, double); // y' = f(y,t) // Cas y' = f(y,t), on fournit la fonction f, sous la forme // double f(double, double), et ca construit la bonne DiffEqFunction class DiffEqFcnT1 : public DiffEqFunction { public: // Constructeur, on fournit une fonction (double, double)->double // qui donne y' en fonction de y et t. DiffEqFcnT1(DIFEQFCNT1); // Implementation de Compute qui va utiliser la fonction fournie // au constructeur. virtual void ComputeV(Vector& fpi, Vector const& fi); // Implementation de AdjustStart qui gere la fonction a usage interne. virtual void AdjustStart(Vector& start, double tstart); protected: DIFEQFCNT1 mFcn; }; // Cas y'' = f(y',y) typedef double(*DIFEQFCN2)(double, double); class DiffEqFcn2 : public DiffEqFunction { public: DiffEqFcn2(DIFEQFCN2); virtual void ComputeV(Vector& fpi, Vector const& fi); protected: DIFEQFCN2 mFcn; }; // Cas y'' = f(y',y,t) typedef double(*DIFEQFCNT2)(double, double, double); // y'' = f(y',y,t) // Cas y'' = f(y',y,t), on fournit la fonction f, sous la forme // double f(double, double, double), et ca construit la bonne DiffEqFunction class DiffEqFcnT2 : public DiffEqFunction { public: // Constructeur, on fournit une fonction (double, double, double)->double // qui donne y'' en fonction de y', y et t. DiffEqFcnT2(DIFEQFCNT2); // Implementation de Compute qui va utiliser la fonction fournie // au constructeur. virtual void ComputeV(Vector& fpi, Vector const& fi); // Implementation de AdjustStart qui gere la fonction a usage interne. virtual void AdjustStart(Vector& start, double tstart); protected: DIFEQFCNT2 mFcn; }; // Cas y'' = f(y',y) avec des 3-vecteurs typedef void(*DIFEQFCNV)(Vector&, Vector const&, Vector const&); // y'' = f(y',y,t) // Cas y'' = f(y',y,t), on fournit la fonction f, sous la forme // double f(Vector), et ca construit la bonne DiffEqFunction class DiffEqFcnV : public DiffEqFunction { public: // Constructeur, on fournit une fonction (Vector)->double // qui donne y'' en fonction du vecteur (t, y, y') DiffEqFcnV(DIFEQFCNV); // Implementation de Compute qui va utiliser la fonction fournie // au constructeur. virtual void ComputeV(Vector& fpi, Vector const& fi); protected: DIFEQFCNV mFcn; Vector tmp1, tmp2, tmp3; }; // Classe abstraite de resolveur d'equadif // Classe abstraite de resolveur d'equadif // Beaucoup de fonctions renvoient l'objet pour pouvoir faire une // notation chainee s.Step(...).Start(...).Solve(...) class DiffEqSolver EXC_AWARE { public: // Constructeurs. L'equadif est donnee sous forme de DiffEqFunction. // On a prevu le cas particulier du premier degre directement // DiffEqSolver(); DiffEqSolver(DiffEqFunction*); DiffEqSolver(DIFEQFCN1); // // Destructeur virtual ~DiffEqSolver(); // Change la fonction. Notation chainee possible // DiffEqSolver& Func(DiffEqFunction*); DiffEqSolver& Func(DIFEQFCN1); // // Change le pas d'integration. Notation chainee possible DiffEqSolver& Step(double); // Change les conditions initiales. Notation chainee possible. // DiffEqSolver& StartV(Vector const& yi, double t); // si NFunc == 1 DiffEqSolver& Start1(double yi, double t); DiffEqSolver& Start(double const* yi, double t); // // Lance la resolution, avec ou sans conservation de n valeurs intermediaires // virtual void SolveV(Vector& yf, double tf); // si NFunc == 1 virtual void Solve1(double& yf, double tf); virtual void Solve(double* yf, double tf); virtual void SolveArr(Matrix& y, double* t, double tf, int n)=0; // si NFunc == 1 virtual void SolveArr1(double* y, double* t, double tf, int n); virtual void SolveArr2(double** y, double* t, double tf, int n); // protected: DiffEqFunction* mFunc; bool mOwnFunc; Vector mYStart; double mXStart; double mStep; }; // Runge-Kutta ordre 4 // Runge-Kutta ordre 4 class RK4DiffEq : public DiffEqSolver { public: // Constructeurs. Voir DiffEqSolver // RK4DiffEq(); RK4DiffEq(DiffEqFunction*); RK4DiffEq(DIFEQFCN1); // // Implementation de RK4 virtual void SolveArr(Matrix& y, double* t, double tf, int n); protected: // Un pas RK4 void RKStep(Vector& newY, Vector const& y0, double dt); // Vecteurs utilises en interne, pour ne pas les reallouer. Vector k1, k2, k3, k4; }; } // Fin du namespace #endif