// This may look like C code, but it is really -*- C++ -*-
// Simple differential equation solver
// E. Aubourg 1996-
// DAPNIA/SPP (Saclay) / CEA LAL - IN2P3/CNRS (Orsay)
#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 {
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 v 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 {
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