UNPKG

jalhyd

Version:

JaLHyd, a Javascript Library for Hydraulics

122 lines 4.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.acNewton = void 0; const internal_modules_1 = require("../../internal_modules"); const internal_modules_2 = require("../../internal_modules"); const internal_modules_3 = require("../../internal_modules"); const internal_modules_4 = require("../../internal_modules"); const internal_modules_5 = require("../../internal_modules"); // tslint:disable-next-line:class-name class acNewton extends internal_modules_1.Debug { /** * Constructeur de la classe * @param prms Paramètres supplémentaires (Débit, précision...) */ constructor(prms, maxIter, dbg = false) { super(dbg); this.rRelax = 1; /// Coefficient de relaxation this.rFnPrec = 0; /// Mémorisation du Fn précédent pour détecter le changement de signe this.iOscil = 0; /// Nombre de changement de signe de Delta this.rTol = internal_modules_2.SessionSettings.precision; this.Dx = internal_modules_2.SessionSettings.precision / 10; this.iCptMax = maxIter; } Newton(rX) { this.iCpt = 0; return this.doNewton(rX); } /** * Calcul de la dérivée f'(x) (peut être redéfini pour calcul analytique) * @param rX x * @return Calcul de la fonction */ CalcDer(x) { const rFN1 = this.CalcFn(x - this.Dx); if (!rFN1.ok) { return rFN1; } const rFN2 = this.CalcFn(x + this.Dx); if (!rFN2.ok) { return rFN2; } // return (this.CalcFn(x + this.Dx) - this.CalcFn(x - this.Dx)) / (2 * this.Dx); const v = (rFN2.vCalc - rFN1.vCalc) / (2 * this.Dx); return new internal_modules_4.Result(v); } /** * Test d'égalité à une tolérance près * @param rFn x * @return True si égal, False sinon */ FuzzyEqual(rFn) { return (Math.abs(rFn) < this.rTol); } /** * Fonction récursive de calcul de la suite du Newton * @param rX x * @return Solution du zéro de la fonction */ doNewton(rX) { this.iCpt++; const rFN = this.CalcFn(rX); if (!rFN.ok) { return rFN; } const rFn = rFN.vCalc; // if (this.FuzzyEqual(rFn) || this.iCpt >= this.iCptMax) // return new Result(rX); if (this.FuzzyEqual(rFn)) { // convergence return new internal_modules_4.Result(rX); } if (this.iCpt >= this.iCptMax) { // non convergence const mess = new internal_modules_3.Message(internal_modules_3.MessageCode.ERROR_NEWTON_NON_CONVERGENCE); const res = new internal_modules_5.ResultElement(mess); res.addExtraResult("res", rX); return new internal_modules_4.Result(res); } const rDER = this.CalcDer(rX); if (!rDER.ok) { return rDER; } const rDer = Math.max(-1E10, Math.min(rDER.vCalc, 1E10)); // Bornage de la dérivée pour éviter Delta=0 if (rDer !== 0) { if ((0, internal_modules_1.XOR)(rFn < 0, this.rFnPrec < 0)) { this.iOscil++; if (this.rRelax > 1) { // Sur une forte relaxation, au changement de signe on réinitialise this.rRelax = 1; } else if (this.iOscil > 2) { // On est dans le cas d'une oscillation autour de la solution // On réduit le coefficient de relaxation this.rRelax = this.rRelax * 0.5; } } this.rFnPrec = rFn; // tslint:disable-next-line:variable-name const Delta = rFn / rDer; // 2^8 = 2E8 ? while (Math.abs(Delta * this.rRelax) < this.rTol && rFn > 10 * this.rTol && this.rRelax < 2E8) { // On augmente le coefficicient de relaxation s'il est trop petit this.rRelax = this.rRelax * 2; } let rRelax = this.rRelax; while (rX - Delta * rRelax <= 0 && rRelax > 1E-4) { // On diminue le coefficient de relaxation si on passe en négatif rRelax = rRelax * 0.5; // Mais on ne le mémorise pas pour les itérations suivantes } rX = rX - Delta * rRelax; // this.rDelta = Delta; ??? if (rX < 0) { rX = this.rTol; } // Aucune valeur recherchée ne peut être négative ou nulle return this.doNewton(rX); } // Echec de la résolution // return undefined; const m = new internal_modules_3.Message(internal_modules_3.MessageCode.ERROR_NEWTON_DERIVEE_NULLE); return new internal_modules_4.Result(m); } } exports.acNewton = acNewton; //# sourceMappingURL=newton.js.map