Herezh_dev/Util/Algo_edp.h

282 lines
15 KiB
C++

// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2021 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
/************************************************************************
* DATE: 12/02/2006 *
* $ *
* AUTEUR: G RIO (mailto:gerardrio56@free.fr) *
* $ *
* PROJET: Herezh++ *
* $ *
************************************************************************
* BUT: Algorithmes de base pour la résolution d'équations *
* différentielles. *
* $ *
* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' *
* $ *
************************************************************************/
#ifndef ALGO_EDP_H
#define ALGO_EDP_H
#include "Vecteur.h"
#include "Mat_abstraite.h"
#include "Racine.h"
/** @defgroup Les_classes_algo
*
* BUT: Algorithmes de base pour la résolution d'équations
* différentielles, recherche de zéros, intégration.
*
*
* \author Gérard Rio
* \version 1.0
* \date 12/02/2006
* \brief Algorithmes de base pour la résolution d'équations différentielles, recherche de zéros, intégration.
*
*/
/// @addtogroup Les_classes_algo
/// @{
///
/// BUT: Algorithmes de base pour la résolution d'équations
/// différentielles.
class Algo_edp
{
public :
// CONSTRUCTEURS :
// constructeur par défaut
Algo_edp();
// constructeur de copie
Algo_edp(const Algo_edp& a);
// DESTRUCTEUR :
~Algo_edp();
// METHODES PUBLIQUES :
/// résolution par runge kutta imbriqué --> estimation d'erreur
/// il y a 3 calcul de la fonction dérivée
/// 2 et 3 ième ordre imbriquée
/// calcul de la solution à t+dt en fonction de la solution à t,
/// en entrée:
/// *Ptder_fonc : pointeur de la fonction de calcul de la dérivées
/// en entrée: t et f : temps et la valeur de la fonction a t
/// en sortie: df : dérivée de la fonction a t
/// erreur : si diff de 0, indique qu'il y a eu une erreur
/// *Ptverif_fonc : pointeur de fonction, pour tester val_finale après la prédiction explicite finale
///
/// val_initiale : valeur des fonctions en t0
/// der_initiale : valeur de la dérivée pour t0
/// t0 : temps initiale
/// deltat : incrément de temps demandé
/// en sortie :
/// val_finale : valeur des fonctions à tdt
/// estime_erreur : estimation d'erreur pour chaque fonction
/// --> si estime_erreur(i) est >= à ConstMath::tresgrand, la valeur finale = la valeur initiale (c-a-d pas de calcul valide)
template <class T> void Runge_Kutta_step23(T& instance
,Vecteur& (T::*Ptder_fonc) (const double & t,const Vecteur& f,Vecteur& df,int& erreur)
,void (T::*Ptverif_fonc) (const double & t,const Vecteur& f,int& erreur_final)
,const Vecteur& val_initiale,const Vecteur& der_initiale
,const double& t0,const double& deltat
,Vecteur& val_finale,Vecteur& estime_erreur) ;
/// résolution par runge kutta imbriqué --> estimation d'erreur
/// il y a 4 calcul de la fonction dérivée
/// 3 et 4 ième ordre imbriquée (Fehlberg)
/// calcul de la solution à t+dt en fonction de la solution à t,
/// en entrée:
/// *Ptder_fonc : pointeur de la fonction de calcul de la dérivées
/// en entrée: t et f : temps et la valeur de la fonction a t
/// en sortie: df : dérivée de la fonction a t
/// erreur : si diff de 0, indique qu'il y a eu une erreur
/// *Ptverif_fonc : pointeur de fonction, pour tester val_finale après la prédiction explicite finale
///
/// val_initiale : valeur des fonctions en t0
/// der_initiale : valeur de la dérivée pour t0
/// t0 : temps initiale
/// deltat : incrément de temps demandé
/// en sortie :
/// val_finale : valeur des fonctions à tdt
/// estime_erreur : estimation d'erreur pour chaque fonction
/// --> si estime_erreur(i) est >= à ConstMath::tresgrand, la valeur finale = la valeur initiale (c-a-d pas de calcul valide)
template <class T> void Runge_Kutta_step34(T& instance
,Vecteur& (T::*Ptder_fonc) (const double & t,const Vecteur& f,Vecteur& df,int& erreur)
,void (T::*Ptverif_fonc) (const double & t,const Vecteur& f,int& erreur_final)
,const Vecteur& val_initiale,const Vecteur& der_initiale
,const double& t0,const double& deltat
,Vecteur& val_finale,Vecteur& estime_erreur) ;
/// résolution par runge kutta imbriqué --> estimation d'erreur
/// il y a 5 calcul de la fonction dérivée
/// l'algorithme s'appuis sur la présentation de numerical recipes
/// fifth-order Cash-Karp Runge-Kutta
/// calcul de la solution à t+dt en fonction de la solution à t,
/// en entrée:
/// *Ptder_fonc : pointeur de la fonction de calcul de la dérivées
/// en entrée: t et f : temps et la valeur de la fonction a t
/// en sortie: df : dérivée de la fonction a t
/// erreur : si diff de 0, indique qu'il y a eu une erreur
/// *Ptverif_fonc : pointeur de fonction, pour tester val_finale après la prédiction explicite finale
///
/// val_initiale : valeur des fonctions en t0
/// der_initiale : valeur de la dérivée pour t0
/// t0 : temps initiale
/// deltat : incrément de temps demandé
/// en sortie :
/// val_finale : valeur des fonctions à tdt
/// estime_erreur : estimation d'erreur pour chaque fonction
/// --> si estime_erreur(i) est >= à ConstMath::tresgrand, la valeur finale = la valeur initiale (c-a-d pas de calcul valide)
template <class T> void Runge_Kutta_step45(T& instance
,Vecteur& (T::*Ptder_fonc) (const double & t,const Vecteur& f,Vecteur& df,int& erreur)
,void (T::*Ptverif_fonc) (const double & t,const Vecteur& f,int& erreur_final)
,const Vecteur& val_initiale,const Vecteur& der_initiale
,const double& t0,const double& deltat
,Vecteur& val_finale,Vecteur& estime_erreur) ;
/// un programme de pilotage de l'intégration d'un pas (on s'inspire du programme libre rkf45)
/// on distingue une erreur globale et une erreur relative
/// l'erreur réelle utilisée sur chaque step est: erreurRelative * |f| + erreurAbsolue
/// ==== en entrée: =====
/// cas_kutta : donne le type de routine kutta imbriqué a employer:
/// =3 pour kutta23, =4 pour kutta34, =5 pour kutta45
/// tdebut et tfin : temps de début et de fin du calcul, demandé
/// val_initiale : valeur initiale de la fonction (donc à tdebut)
/// der_initiale : dérivée initiale de la fonction (donc à tdebut)
/// erreurAbsolue : erreur absolue demandée
/// erreurRelative : erreur relative (à la fonction) demandée
/// Ptder_fonc : pointeur de fonction
/// en entrée: t et f : temps et la valeur de la fonction a t
/// en sortie: df : dérivée de la fonction a t
/// en entrée: t et f : temps et la valeur de la fonction a t
/// en sortie: df : dérivée de la fonction a t
/// erreur : si diff de 0, indique qu'il y a eu une erreur
/// Ptverif_fonc : pointeur de fonction, pour tester l'intégrité du résultat
/// cela signifie que val_finale est testée avec cette fonction, systématiquement
/// - à la fin de chaque prédiction des kuttas imbriqués
/// - au retour du pilotage
/// ---- en sortie: -----
/// dernierTemps : temps final utilisé = tfin si calcul ok, sinon = le dernier temps calculé
/// val_finale : valeur de la fonction à "dernierTemps"
/// der_finale : dérivée finale
/// dernierdeltat : le dernier deltat utilisé
/// nombreAppelF : nombre d'appel de la fonction réellement utilisé dans le programme
/// erreurRelative : si retour = 3 ==> erreur relative (à la fonction) minimum possible,
/// nb_step : nombre de step utilisé pour le calcul (non compté les steps avec trop d'erreur)
/// erreur_maxi_global : une approximation de l'erreur maxi global cumulant les erreurs sur tous les steps
/// === en retour un entier qui donne le résultat du calcul : ====
/// =2 : tout est ok : seul cas où toutes les valeurs de retour sont valides
/// =3 : erreur: la précision relative demandée est trop petite, en retour la précision mini possible
/// =4 : erreur: on a dépassé le nombre maxi d'appel fixé, d'où a peu près à (nombreAppelF/6) step de calcul.
/// =6 : erreur: l'intégration pas possible, due aux précisions demandées, on doit augmenter ces précisions
/// souvent du à une solution qui varie très rapidemment --> problème potentiel
/// =8 : erreur: cas_kutta ne correspond pas à une routine de base existante
/// = 0 : erreur inconnue
template <class T>
int Pilotage_kutta(int cas_kutta, T& instance
,Vecteur& (T::*Ptder_fonc) (const double & t,const Vecteur& f,Vecteur& df,int& erreur)
,void (T::*Ptverif_fonc) (const double & t,const Vecteur& f,int& erreur_final)
,const Vecteur& val_initiale,const Vecteur& der_initiale
,const double& tdebut,const double& tfin
,const double& erreurAbsolue, double& erreurRelative
,Vecteur& val_finale,Vecteur& der_finale
,double& dernierTemps, double& dernierdeltat,int& nombreAppelF,int& nb_step
,double& erreur_maxi_global);
/// explication erreur
/// affiche à l'écran l'explication de l'erreur de Pilotage_kutta
void Affiche_Explication_erreur_RG(int type_erreur);
/// --méthodes pour modifier les différents paramètres
/// nombre maxi d'appel de fonction permis
/// dans le cas du runge 4-5 -> 6 appels par step (à la louche)
void Modif_nbMaxiAppel (int nb) {nbMaxiAppel = nb;};
/// initialisation de tous les paramètres à leurs valeurs par défaut
void Init_param_val_defaut();
/// modifie le niveau d'affichage par exemple pour le débug
void Change_niveau_affichage(int niveau) {permet_affichage=niveau;};
private :
// VARIABLES PROTEGEES :
// ----- controle de la sortie des informations
int permet_affichage; // pour permettre un affichage spécifique dans les méthodes, pour les erreurs et warning
int nbMaxiAppel; // nombre maxi d'Appel autorisé de la fonction
// ---- variables intermédiaires utilisées par la méthode Runge_Kutta_step23
static double AB1,AB2,AB3,A2,aa2,aa3
,bb21,bb31,bb32
,dA1,dA2,dA3;
// ---- variables intermédiaires utilisées par la méthode Runge_Kutta_step34
static double A_B1,A_B3,A_B4,A_B5,A_1,A_3,A_4
,a_a2,a_a3,a_a4,a_a5
,b_b21,b_b31,b_b32,b_b41,b_b42,b_b43,b_b51,b_b53,b_b54
,d_A1,d_A3,d_A4,d_A5;
// --- variables intermédiaires utilisées par la méthode Runge_Kutta_step45
Vecteur k2,k3,k4,k5,k6;
// Vecteur f_inter;
static double a2,a3,a4,a5,a6 // les ai de Cash-karp paramètres
,b21,b31,b32,b41,b42,b43 //
,b51,b52,b53,b54,b61,b62,b63,b64,b65 // les bij
,c1,c3,c4,c6; // les ci
// c2 =0, c5=0
static double ce1,ce3,ce4,ce5,ce6; // ce2=0; : les c-c_étoile_i
// --- variables intermédiaires utilisées par la méthode Pilotage_kutta
Vecteur val_inter; // valeur de la fonction, intermédiaire
Vecteur der_inter; // dérivée de la fonction, intermédiaire
Vecteur estime_erreur; // estimation d'erreur calculée
// puis des sauvegardes pour pouvoir revenir en arrière
Vecteur val_prec_inter; // sauve avant appel: valeur de la fonction, intermédiaire
Vecteur der_prec_inter; // sauve avant appel: dérivée de la fonction, intermédiaire
Vecteur estime_prec_erreur; // sauve avant appel: estimation d'erreur calculée
double coef; // coeff de sécurité préconnisé pour les variations de temps
static double remin; // pour calculer l'erreur mini acceptable dans le runge
// METHODES PROTEGEES :
// impression du temps
void timestamp ();
// -- méthode test ---
// on défini une fonction a intégrer
Vecteur& FoncDeriv(const double & t,const Vecteur& f,Vecteur& df,int& erreur);
// on défini une fonction de vérification d'intégrité
void FoncVerif_fonc(const double & t,const Vecteur& f,int& erreur);
int nb_cas_test; // nb pour choisir entre différents cas test
// la méthode qui fait les tests
void Test_template();
};
// pour faire de l'inline: nécessaire avec les templates
// on n'inclut que les méthodes templates
#include "Algo_edp_2.cc"
#define Algo_edp_deja_inclus
/// @} // end of group
#endif