An error occurred while loading the file. Please try again.
-
Dorchies David authored35e86aa2
import { Debug, Nub, Result } from "base";
export class Dichotomie extends Debug {
/** Pas de parcours de l'intervalle pour initialisation dichotomie */
readonly IDEFINT = 100;
/** Nombre d'itérations maximum de la dichotomie */
readonly IDICMAX = 100;
/**
* Construction de la classe.
* @param nub Noeud de calcul contenant la méthode de calcul Equation
* @param sVarCalc Nom de la variable à calculer
*/
constructor(private nub: Nub, private sVarCalc: string) {
super(false);
}
/** Valeur inconnue à rechercher */
get vX() {
return this.nub.v[this.sVarCalc];
}
/** Valeur inconnue à rechercher */
set vX(vCalc) {
this.nub.v[this.sVarCalc] = vCalc;
}
/**
* Méthode simulant l'opérateur booléen xor
* @see http://www.howtocreate.co.uk/xor.html
*/
XOR(a, b) {
return (a || b) && !(a && b);
}
/**
* Calcul de l'équation analytique.
* @note Wrapper vers this.nub.Equation pour simplifier le code.
* On utilise la première variable du tableau des variables pourvant être calculées analytiquement
* Il faudra s'assurer que cette première variable correspond à la méthode de calcul la plus rapide
*/
private Calcul() {
/**
* @note
*/
return this.nub.Equation(this.nub.sVarsEq[0]);
}
/**
* Calcul à l'ouvrage
* @param sVarCalc Nom de la variable à calculer
* @param rTarget Valeur cible
* @param rtol Précision attendue du résultat
* @param rInit Valeur initiale de l'inconnue à rechercher
*/
Dichotomie(rTarget: number, rTol: number, rInit: number): Result {
let res: Result
let XminInit = 1E-8;
this.vX = XminInit;
let v1: number = this.Calcul().vCalc;
let XmaxInit: number = Math.max(1, rInit) * 100;
this.vX = XmaxInit;
let v2 = this.Calcul().vCalc;
let DX = (XmaxInit - XminInit) / this.IDEFINT;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
let nIterMax = Math.floor(Math.max(XmaxInit - rInit, rInit - XminInit) / DX + 1);
let Xmin = rInit;
let Xmax = rInit;
let X1 = rInit;
let X2 = rInit;
this.debug("rInit: " + rInit);
this.vX = rInit;
let v = this.Calcul().vCalc;
v1 = v;
v2 = v;
this.debug(nIterMax);
//** @todo : Chercher en dehors de l'intervalle en le décalant à droite ou à gauche en fonction de la valeur */
let nIter: number;
for (nIter = 1; nIter < nIterMax; nIter++) {
//Ouverture de l'intervalle des deux côtés : à droite puis à gauche
Xmax = Xmax + DX;
if (this.XOR(Xmax > XmaxInit, DX <= 0)) Xmax = XmaxInit;
this.vX = Xmax;
v = this.Calcul().vCalc;
if (this.XOR(v1 < v2, v <= v2)) {
v2 = v;
X2 = Xmax;
}
if (this.XOR(v1 < v2, v >= v1)) {
v1 = v;
X1 = Xmax;
}
Xmin = Xmin - DX;
if (this.XOR(Xmin < XminInit, DX <= 0)) {
Xmin = XminInit;
}
this.vX = Xmin;
v = this.Calcul().vCalc;
if (this.XOR(v1 < v2, v <= v2)) {
v2 = v;
X2 = Xmin;
}
if (this.XOR(v1 < v2, v >= v1)) {
v1 = v;
X1 = Xmin;
}
if (this.XOR(rTarget > v1, rTarget >= v2)) { break; }
}
if (nIter >= this.IDEFINT) {
this.debug("in if");
// Pas d'intervalle trouvé avec au moins une solution
if (v2 < rTarget && v1 < rTarget) {
// Cote de l'eau trop basse pour passer le débit il faut ouvrir un autre ouvrage
this.vX = XmaxInit;
}
else {
// Cote de l'eau trop grande il faut fermer l'ouvrage
this.vX = XminInit;
}
res = this.Calcul();
res.extraVar["flag"] = -1; // la valeur cible n'est pas dans l'intervalle de recherche
return res;
}
else {
// Dichotomie
this.debug("in dicho");
let X = rInit;
for (nIter = 1; nIter <= this.IDICMAX; nIter++) {
this.vX = X;
v = this.Calcul().vCalc;
if (rTarget != 0 && Math.abs(X1 - X2) <= rTol) { break; }
if (this.XOR(rTarget < v, v1 <= v2)) {
// rTarget < IQ et v(X1) > v(X2) ou pareil en inversant les inégalités
141142143144145146147148149150151152153154155156157158159
X1 = this.vX;
}
else {
// rTarget < IQ et v(X1) < v(X2) ou pareil en inversant les inégalités
X2 = this.vX;
}
X = (X2 + X1) * 0.5;
this.debug((X));
}
if (nIter == this.IDICMAX) {
res = this.Calcul();
res.extraVar["flag"] = -1; // la valeur cible n'est pas dans l'intervalle de recherche
return res;
}
}
res.vCalc = v
return ;
}
}