UNPKG

jalhyd

Version:

JaLHyd, a Javascript Library for Hydraulics

859 lines (858 loc) 38.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CourbeRemous = 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"); const internal_modules_6 = require("../internal_modules"); const internal_modules_7 = require("../internal_modules"); const internal_modules_8 = require("../internal_modules"); const internal_modules_9 = require("../internal_modules"); const internal_modules_10 = require("../internal_modules"); const internal_modules_11 = require("../internal_modules"); const internal_modules_12 = require("../internal_modules"); const internal_modules_13 = require("../internal_modules"); /** * Calcul d'une courbe de remous */ class CourbeRemous extends internal_modules_13.SectionNub { constructor(s, crp, method = internal_modules_12.MethodeResolution.Trapezes, dbg = false) { super(crp, dbg); this._debugDicho = false; this.setCalculatorType(internal_modules_2.CalculatorType.CourbeRemous); this.setSection(s); this.methodeResolution = method; // no calculated parameter this._defaultCalculatedParam = undefined; } get methodeResolution() { return this.getPropValue("methodeResolution"); } set methodeResolution(m) { this.setPropValue("methodeResolution", m); } setSection(s) { super.setSection(s); this.setParametersCalculability(); // to override acSection's tuning if (this.section !== undefined) { // If from Section is neither visible nor linkable here this.section.prms.If.visible = false; this.section.prms.Y.visible = false; } } /** * This needs to be called before calculation if Z1, Z2, ZF1 or ZF2 was modified */ setIfFromElevations() { if (this.section !== undefined) { this.section.prms.If.singleValue = (this.prms.ZF1.v - this.prms.ZF2.v) / this.prms.Long.v; this.section.prms.If.v = this.section.prms.If.singleValue; } } static get availableTargets() { return CourbeRemous._availableTargets; } /** * Prepare parameters for calculRemous */ preCalc() { this.triggerChainCalculation(); this.copySingleValuesToSandboxValues(); this.prms.setYamontYavalFromElevations(); this.setIfFromElevations(); } /** * @param valACal nom de la variable à calculer */ calculRemous(valACal) { this.preCalc(); const res = new internal_modules_10.Result(undefined, this); const Z1 = this.prms.Z1.singleValue; const Z2 = this.prms.Z2.singleValue; // vérifier qu'il y a de l'eau à l'amont / à l'aval if (Z1 !== undefined && this.prms.ZF1.singleValue >= Z1) { res.globalLog.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_UPSTREAM_BOTTOM_HIGHER_THAN_WATER)); } if (Z2 !== undefined && this.prms.ZF2.singleValue >= Z2) { res.globalLog.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_DOWNSTREAM_BOTTOM_HIGHER_THAN_WATER)); } // s'il n'y en a nulle part, on arrête tout if (Z1 !== undefined && Z2 !== undefined && this.prms.ZF1.singleValue >= Z1 && this.prms.ZF2.singleValue >= Z2) { res.globalLog.add(new internal_modules_9.Message(internal_modules_9.MessageCode.ERROR_REMOUS_NO_WATER_LINE)); return res; } // si le pas de discrétisation est supérieur à la longueur du bief if (this.prms.Dx.singleValue >= this.prms.Long.singleValue) { res.globalLog.add(new internal_modules_9.Message(internal_modules_9.MessageCode.ERROR_REMOUS_PAS_SUPERIEUR_BIEF)); return res; } // let Yc: number = this.Sn.CalcSection("Yc"); const rYC = this.Sn.CalcSection("Yc"); if (!rYC.ok) { res.addLog(rYC.log); return res; } // tslint:disable-next-line:variable-name const Yc = rYC.vCalc; const rB = this.Sn.CalcSection("B", this.Sn.prms.YB.v); if (!rB.ok) { res.addLog(rB.log); return res; } let m = new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_H_CRITIQUE); m.extraVar.Yc = Yc; // this._log.add(m); res.addMessage(m); const rYN = this.Sn.CalcSection("Yn"); // tslint:disable-next-line:variable-name let Yn; if (!rYN.ok) { const mc = rYN.log.messages[0].code; if (mc === internal_modules_9.MessageCode.ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF) { res.addMessage(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_YN_SECTION_PENTE_NEG_NULLE_HNORMALE_INF)); } else if (mc === internal_modules_9.MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE) { res.addMessage(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_YN_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE)); } Yn = 2 * Yc; // si le calcul de Yn échoue, on est en régime fluvial, d'où un Yn imposé > Yc } else { // tslint:disable-next-line:variable-name Yn = rYN.vCalc; m = new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_H_NORMALE, { Yn }); res.addMessage(m); } // this.debug("largeur berge " + this.Sn.CalcSection("B")); // const rB2: Result = this.Sn.CalcSection("B") // this.debug("largeur berge " + rB2.vCalc); // this.debug("hauteur critique " + Yc); // this.Sn.HautNormale = this.Sn.CalcSection("Yn"); // this.debug("hauteur normale " + this.Sn.HautNormale); // this.debug("hauteur normale " + Yn); // Calcul des courbes de remous const xValues = new internal_modules_6.ParamValues(); xValues.setValues(0, this.prms.Long.v, this.prms.Dx.v); // vérifier les tirants d'eau amont/aval par rapport à la hauteur critique if (this.Sn.HautCritique.vCalc > this.prms.Yaval.v && this.Sn.HautCritique.vCalc < this.prms.Yamont.v) { res.globalLog.add(new internal_modules_9.Message(internal_modules_9.MessageCode.ERROR_REMOUS_PAS_CALCUL)); return res; } // on ne peut pas calculer la courbe fluviale s'il ny 'a pas d'eau à l'aval let rCourbeFlu; if (Z2 !== undefined && this.prms.ZF2.singleValue < Z2) { rCourbeFlu = this.calculFluvial(xValues); res.addLog(rCourbeFlu.log); } // on ne peut pas calculer la courbe torrentielle s'il ny 'a pas d'eau à l'amont let rCourbeTor; if (Z1 !== undefined && this.prms.ZF1.singleValue < Z1) { rCourbeTor = this.calculTorrentiel(xValues); res.addLog(rCourbeTor.log); } let crbFlu; if ((rCourbeFlu === null || rCourbeFlu === void 0 ? void 0 : rCourbeFlu.trY) !== undefined) { crbFlu = rCourbeFlu.trY; } else { crbFlu = {}; } let crbTor; if ((rCourbeTor === null || rCourbeTor === void 0 ? void 0 : rCourbeTor.trY) !== undefined) { crbTor = rCourbeTor.trY; } else { crbTor = {}; } // this.debug("HautCritique ", this.Sn.HautCritique); this.debug("flu"); // this.logObject(crbFlu); this.debug(JSON.stringify(crbFlu)); this.debug("tor"); // this.logObject(crbTor); this.debug(JSON.stringify(crbTor)); /* // tslint:disable-next-line:forin for (const xflu in crbFlu) { const yflu = crbFlu[xflu]; // this.debug("imp x " + xflu + " flu " + this.Sn.CalcSection('Imp', yflu)); } // tslint:disable-next-line:forin for (const xtor in crbTor) { const ytor = crbTor[xtor]; // this.debug("imp x " + xtor + " tor " + this.Sn.CalcSection('Imp', ytor)); } */ // Détection du ressaut hydraulique const nFlu = this.size(crbFlu); const nTor = this.size(crbTor); if (nFlu !== 0 && nTor !== 0) { /* const firstYFlu = crbFlu[0]; const lastYTor = this.last(crbTor); // this.debug("end flu " + firstYFlu); // this.debug("end tor " + lastYTor); // this.debug("nFlu " + nFlu); // this.debug("nTor " + nTor); // this.debug("Imp flu " + this.Sn.CalcSection('Imp', firstYFlu)); // this.debug("Imp tor " + this.Sn.CalcSection('Imp', lastYTor)); */ let crbComplete; let crbPartielle; let iSens; let sSens; if (nFlu > nTor || (nFlu === nTor && Yn < Yc)) { // La courbe fluviale va jusqu'au bout crbComplete = crbFlu; // courbe calculée sur tout le bief crbPartielle = crbTor; // courbe calculée sur une partie seulement du bief iSens = 1; // On cherche l'aval du ressaut sSens = "amont"; this.debug("complete=flu, partielle=tor"); // this.debug("complete(flu)"); // this.debug(crbComplete); // this.debug("partielle(tor)"); // this.debug(crbPartielle); } else { // La courbe torrentielle va jusqu'au bout crbComplete = crbTor; crbPartielle = crbFlu; iSens = -1; // On cherche l'amont du ressaut sSens = "aval"; this.debug("complete=tor, partielle=flu"); // this.debug("complete(tor)"); // this.debug(crbComplete); // this.debug("partielle(flu)"); // this.debug(crbPartielle); } // Parcours des sections de la ligne d'eau la plus courte const trX = Object.keys(crbPartielle); if (iSens === -1) { // tri dans l'ordre croissant { { trX.sort((a, b) => { if (+a > +b) { return 1; } if (+a < +b) { return -1; } return 0; }); } else { // tri dans l'ordre décroissant { { trX.sort((a, b) => { if (+a > +b) { return -1; } if (+a < +b) { return 1; } return 0; }); } const trXr = trX.slice(0); // copie trXr.reverse(); // this.debug("trX"); // this.debug(trX); let bRessaut = false; // tslint:disable-next-line:variable-name const Dx = xValues.step; // tslint:disable-next-line:prefer-for-of for (let irX = 0; irX < trX.length; irX++) { const rX = +trX[irX]; // this.debug("irX=" + irX); // this.debug("rX=" + rX); // this.debug("partielle[" + rX + "]=" + crbPartielle[rX]); // Calcul de l'abscisse de la section dans l'autre régime const rYCO = this.Sn.CalcSection("Ycon", crbPartielle[rX]); // Y conjugué if (!rYCO.ok) { res.addLog(rYCO.log); return res; } // tslint:disable-next-line:variable-name const Ycon = rYCO.vCalc; // this.debug("rX=" + rX + " Ycon(Ypartiel=" + crbPartielle[rX] + ")=" + Ycon); const rLongRst = 5 * Math.abs(crbPartielle[rX] - Ycon); // Longueur du ressaut // this.debug("longueur ressaut=" + rLongRst); let xRst = rX + Math.round(iSens * rLongRst / Dx) * Dx; // Abscisse où comparer Yconj et Y // this.debug("xRst=" + xRst); // let rxRst = rX + iSens * rLongRst; // Abscisse réelle du ressaut // this.debug("xRst reel=" + (rX + iSens * rLongRst)); xRst = (0, internal_modules_1.round)(xRst, this.section.prms.iPrec); // this.debug("xRst (arr)=" + xRst); const impYpartielle = this.Sn.CalcSection("Imp", crbPartielle[rX]); // this.debug("imp(Ypartiel[rX=" + rX + "]=" + crbPartielle[rX] + ")=" + impYpartielle); if (!impYpartielle.ok) { res.addLog(impYpartielle.log); return res; } if (crbComplete[xRst] !== undefined) { // Hauteur décalée de la longueur du ressaut (il faut gérer la pente du fond) // const Ydec: number = crbComplete[xRst] + rLongRst * this.section.prms.If.v * iSens; // this.debug("Ydec=" + Ydec); const impYcomplete = this.Sn.CalcSection("Imp", crbComplete[xRst]); // this.debug("imp(Ycomplet[xRst=" + xRst + "]=" + crbComplete[xRst] + ")=" + impYcomplete); if (!impYcomplete.ok) { res.addLog(impYcomplete.log); return res; } if (impYpartielle.vCalc > impYcomplete.vCalc) { this.debug("Ressaut hydraulique détecté entre les abscisses " + Math.min(rX, xRst) + " et " + Math.max(rX, xRst)); m = new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_RESSAUT_HYDRO); m.extraVar.xmin = Math.min(rX, xRst); m.extraVar.xmax = Math.max(rX, xRst); // this._log.add(m); res.addMessage(m); // this.debug("rX=" + rX + " xRst=" + xRst); // Modification de la ligne d'eau complète for (const pi of trXr) { const rXCC = +pi; // this.debug("rXCC=" + rXCC); if ((rX !== xRst && iSens * (rXCC - rX) <= 0) || (rX === xRst && iSens * (rXCC - rX) < 0)) { delete crbComplete[rXCC]; this.debug("Modification de la ligne d'eau complète : suppression de la valeur à rXCC=" + rXCC + ", rX=" + rX + ", iSens*(rXCC-rX)=" + (iSens * (rXCC - rX))); } } // Modification de la ligne d'eau partielle for (const xcn of trX) { const rXCN = +xcn; // this.debug("rXCN=" + rXCN); if ((rX !== xRst && iSens * (rXCN - xRst) >= 0) || (rX === xRst && iSens * (rXCN - xRst) > 0)) { this.debug("Modification de la ligne d'eau partielle : suppression de la valeur à rX=" + rXCN); delete crbPartielle[rXCN]; } } bRessaut = true; break; } } } if (!bRessaut) { // Le ressaut est en dehors du canal m = new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_RESSAUT_DEHORS); m.extraVar.sens = sSens; m.extraVar.x = +this.last(trX); // this._log.add(m); res.addMessage(m); this.debug("Ressaut hydraulique détecté à l'" + sSens + " de l'abscisse " + this.last(trX)); if (iSens === 1) { crbTor = {}; } else { crbFlu = {}; } crbPartielle = {}; // pour le log uniquement, à virer } this.debug("complete (" + (iSens === 1 ? "flu" : "tor") + ") modifiée"); // this.logObject(crbComplete); this.debug(JSON.stringify(crbComplete)); this.debug("partielle (" + (iSens === 1 ? "tor" : "flu") + ") modifiée"); // this.logObject(crbPartielle); this.debug(JSON.stringify(crbPartielle)); } // Définition des abscisses let trXabsc = []; if (nFlu !== 0) { trXabsc = Object.keys(crbFlu).map((k) => +k); } if (nTor !== 0) { const kTor = Object.keys(crbTor).map((k) => +k); trXabsc = trXabsc.concat(kTor); } // this.debug("trX=" + trX); trXabsc.sort((a, b) => { if (a > b) { return 1; } if (a < b) { return -1; } return 0; }); // this.debug("trX tri=" + trX); trXabsc = trXabsc.filter((elem, index, array) => { if (index > 0) { return elem !== array[index - 1]; } return true; }); // this.debug("trX unique=" + trX); this.debug("abscisses "); this.logArray(trXabsc); // est-ce que ça déborde ? let xDebordeMin; let xDebordeMax; // compilation des résultats for (const x of trXabsc) { let ligneDeau; if (crbFlu[x] === undefined) { ligneDeau = crbTor[x]; } else if (crbTor[x] === undefined) { ligneDeau = crbFlu[x]; } else { ligneDeau = Math.max(crbFlu[x], crbTor[x]); } const re = new internal_modules_11.ResultElement({ ZW: ligneDeau + this.getCoteFond(x) }); re.addExtraResult("X", x); re.addExtraResult("Y", ligneDeau); if (crbFlu[x]) { re.addExtraResult("flu", crbFlu[x] + this.getCoteFond(x)); } if (crbTor[x]) { re.addExtraResult("tor", crbTor[x] + this.getCoteFond(x)); } // Détection du débordement if (xDebordeMin === undefined) { if (ligneDeau > this.section.prms.YB.v) { xDebordeMin = x; } } else { if (xDebordeMax === undefined && ligneDeau <= this.section.prms.YB.v) { xDebordeMax = x; } } // Calcul de la variable à calculer if (valACal) { if (ligneDeau !== undefined) { const rVar = this.Sn.CalcSection(valACal, ligneDeau); if (!rVar.ok) { res.addLog(rVar.log); } else { let val = rVar.vCalc; if (["Hs", "Hsc", "Ycor", "Ycon"].includes(valACal)) { val += this.getCoteFond(x); } re.addExtraResult(valACal, val); } } } res.addResultElement(re); } if (xDebordeMin !== undefined || xDebordeMax !== undefined) { xDebordeMin = (xDebordeMin === undefined) ? trXabsc[0] : xDebordeMin; xDebordeMax = (xDebordeMax === undefined) ? trXabsc[trXabsc.length - 1] : xDebordeMax; const md = new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_SECTION_OVERFLOW_ABSC); md.extraVar.xa = xDebordeMin; md.extraVar.xb = xDebordeMax; res.globalLog.add(md); } return res; } /** * Calcule un seul point de la courbe, uniquement pour le solveur de la méthode Trapezes * @WARNING scorie toute pourrie */ Calc(sVarCalc, rInit) { this.prms.setYamontYavalFromElevations(); this.setIfFromElevations(); if (sVarCalc === "Hs") { return this.Equation("Hs"); } throw new Error("CourbeRemous.Calc() : parameter " + sVarCalc + " not allowed"); } Equation(sVarCalc) { if (sVarCalc === "Hs") { const rHS = this.CalcHS(); return new internal_modules_10.Result(rHS, this); } throw new Error("CourbeRemous.Equation() : parameter " + sVarCalc + " not allowed"); } /** * Effectue une série de calculs sur un paramètre; déclenche le calcul en chaîne * des modules en amont si nécessaire * @param rInit solution approximative du paramètre * @param sDonnee éventuel symbole / paire symbole-uid du paramètre à calculer */ CalcSerie(rInit) { const varCalc = this.getPropValue("varCalc"); const res = this.calculRemous(varCalc); return res; } CalcHS() { // Equation de l'intégration par la méthode des trapèzes this.Sn.Reset(); // pour forcer le calcul avec la nouvelle valeur de section.prms.Y return this.Sn.CalcSection("Hs").vCalc - this.Sn.CalcSection("J").vCalc / 2 * this.Dx; } get Sn() { return this.section; } get prms() { return this._prms; } isComputable() { if (super.isComputable()) { // au moins Z1 ou Z2 doit être défini const z1 = this.prms.Z1; const z2 = this.prms.Z2; return z1.isDefined || z2.isDefined; } return false; } /** * Retourne la cote de fond à l'abscisse x * @param x abscisse en m (0 = amont) */ getCoteFond(x) { return (this.prms.ZF1.v - this.prms.ZF2.v) * (1 - x / this.prms.Long.v) + this.prms.ZF2.v; } /** * calcul de la ligne fluviale depuis l'aval (si possible) */ calculFluvial(xValues) { let res = { log: new internal_modules_8.cLog(), trY: {} }; if (!this.Sn.HautCritique.ok) { res.log.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE)); return res; } if (this.Sn.HautCritique.vCalc > this.prms.Yaval.v) { this.debug("Condition limite aval (" + this.prms.Yaval.v + ") < Hauteur critique (" + this.Sn.HautCritique + ") : pas de calcul possible depuis l'aval"); res.log.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_PAS_CALCUL_DEPUIS_AVAL)); } // Calcul depuis l'aval if (this.Sn.HautCritique.vCalc <= this.prms.Yaval.v) { this.debug(`Condition limite aval (${this.prms.Yaval.v}) >= ` + `Hauteur critique (${this.Sn.HautCritique}) : calcul de la partie fluviale à partir de l'aval`); this.Dx = this.prms.Dx.v; xValues.initValuesIterator(true, undefined, true); // reverse iterator does not work here if Dx is not a multiple of Long @see jalhyd#147 // ex: Long = 10, Dx = 3 // forward: [ 0, 3, 6, 9, 10 ] // reverse: [ 10, 7, 4, 1, 0 ] instead of [ 10, 9, 6, 3, 0 ] const mirror = new internal_modules_4.MirrorIterator(xValues); res = this.calcul(this.prms.Yaval.v, mirror); res.log.insert(new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_CALCUL_FLUVIAL)); } return res; } /** * calcul de la ligne torrentielle depuis l'amont (si possible) */ calculTorrentiel(xValues) { let res = { log: new internal_modules_8.cLog(), trY: {} }; if (!this.Sn.HautCritique.ok) { res.log.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE)); return res; } if (this.Sn.HautCritique.vCalc < this.prms.Yamont.v) { this.debug("Condition limite amont (" + this.prms.Yamont.v + ") > Hauteur critique (" + this.Sn.HautCritique + ") : pas de calcul possible depuis l'amont"); res.log.add(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_PAS_CALCUL_DEPUIS_AMONT)); } // Calcul depuis l'amont if (this.Sn.HautCritique.vCalc >= this.prms.Yamont.v) { this.debug("Condition limite amont (" + this.prms.Yamont.v + ") <= Hauteur critique (" + this.Sn.HautCritique + ") : calcul de la partie torrentielle à partir de l'amont"); this.Dx = -this.prms.Dx.v; xValues.initValuesIterator(false, undefined, true); res = this.calcul(this.prms.Yamont.v, xValues); res.log.insert(new internal_modules_9.Message(internal_modules_9.MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL)); } return res; } setParametersCalculability() { this.prms.Long.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.Dx.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.Yamont.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.Yaval.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.Z1.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.Z2.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.ZF1.calculability = internal_modules_5.ParamCalculability.FIXED; this.prms.ZF2.calculability = internal_modules_5.ParamCalculability.FIXED; // section params if (this.section) { this.section.prms.Ks.calculability = internal_modules_5.ParamCalculability.FIXED; this.section.prms.Q.calculability = internal_modules_5.ParamCalculability.FIXED; this.section.prms.If.calculability = internal_modules_5.ParamCalculability.FIXED; this.section.prms.YB.calculability = internal_modules_5.ParamCalculability.FIXED; this.section.prms.Y.calculability = internal_modules_5.ParamCalculability.FIXED; this.section.prms.LargeurBerge.calculability = internal_modules_5.ParamCalculability.FIXED; // parameters depending on section type const D = this.section.getParameter("D"); if (D) { D.calculability = internal_modules_5.ParamCalculability.FIXED; } const k = this.section.getParameter("k"); if (k) { k.calculability = internal_modules_5.ParamCalculability.FIXED; } const fruit = this.section.getParameter("Fruit"); if (fruit) { fruit.calculability = internal_modules_5.ParamCalculability.FIXED; } const largeurFond = this.section.getParameter("LargeurFond"); if (largeurFond) { largeurFond.calculability = internal_modules_5.ParamCalculability.FIXED; } } } adjustChildParameters() { this.section.prms.Y.calculability = internal_modules_5.ParamCalculability.DICHO; } /** * Calcul de dy/dx (utilisé par Euler explicite et Runge-Kutta 4) * @param Y Tirant d'eau initial */ Calc_dYdX(Y) { // L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau // return - (this.section.prms.If.v - this.Sn.CalcSection('J', Y)) // / (1 - Math.pow(this.Sn.CalcSection('Fr', Y), 2)); const rJ = this.Sn.CalcSection("J", Y); if (!rJ.ok) { return rJ; } const rFR = this.Sn.CalcSection("Fr", Y); if (!rFR.ok) { return rFR; } const v = -(this.section.prms.If.v - rJ.vCalc) / (1 - Math.pow(rFR.vCalc, 2)); return new internal_modules_10.Result(v, this); } /** * Calcul du point suivant de la courbe de remous par la méthode Euler explicite. * @param Y Tirant d'eau initial * @return Tirant d'eau */ Calc_Y_EulerExplicite(Y) { if (!this.Sn.HautCritique.ok) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } // L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau const rDXDY = this.Calc_dYdX(Y); if (!rDXDY.ok) { return rDXDY; } // let Y2 = Y + this.Dx * this.Calc_dYdX(Y); const Y2 = Y + this.Dx * rDXDY.vCalc; return new internal_modules_10.Result(Y2, this); } /** * Calcul du point suivant de la courbe de remous par la méthode RK4. * @param Y Tirant d'eau initial * @return Tirant d'eau */ Calc_Y_RK4(Y) { if (!this.Sn.HautCritique.ok) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } // L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau const rDx = this.Dx; // let k1 = this.Calc_dYdX(Y); const rDXDY = this.Calc_dYdX(Y); if (!rDXDY.ok) { return rDXDY; } const k1 = rDXDY.vCalc; const hc = this.Sn.HautCritique.vCalc; if ((0, internal_modules_1.XOR)(rDx > 0, !(Y + rDx / 2 * k1 < hc))) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } // let k2 = this.Calc_dYdX(Y + Dx / 2 * k1); const rDXDY2 = this.Calc_dYdX(Math.max(Y + rDx / 2 * k1, 0)); if (!rDXDY2.ok) { return rDXDY2; } const k2 = rDXDY2.vCalc; if ((0, internal_modules_1.XOR)(rDx > 0, !(Y + rDx / 2 * k2 < hc))) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } // let k3 = this.Calc_dYdX(Y + Dx / 2 * k2); const rDXDY3 = this.Calc_dYdX(Math.max(Y + rDx / 2 * k2, 0)); if (!rDXDY3.ok) { return rDXDY3; } const k3 = rDXDY3.vCalc; if ((0, internal_modules_1.XOR)(rDx > 0, !(Y + rDx / 2 * k3 < hc))) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } // let k4 = this.Calc_dYdX(Y + Dx * k3); const rDXDY4 = this.Calc_dYdX(Math.max(Y + rDx * k3, 0)); if (!rDXDY4.ok) { return rDXDY4; } const k4 = rDXDY4.vCalc; // tslint:disable-next-line:variable-name const Yout = Math.max(Y + rDx / 6 * (k1 + 2 * (k2 + k3) + k4), 0); // if ($this ->rDx > 0 xor !($Yout < $this ->oSect ->rHautCritique)) { return false; } if ((0, internal_modules_1.XOR)(rDx > 0, !(Yout < hc))) { const res = new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); return res; } return new internal_modules_10.Result(Yout, this); } /** * Calcul du point suivant de la courbe de remous par la méthode de l'intégration par trapèze * @param Y Tirant d'eau initial * @return Tirant d'eau */ Calc_Y_Trapez(Y) { if (!this.Sn.HautCritique.ok) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } const dicho = new internal_modules_3.Dichotomie(this, "Y", this._debugDicho, this.CalcHS); // Calcul de H + J * \Delta x / 2 // let Trapez_Fn = this.Sn.CalcSection('Hs', Y) + this.Sn.CalcSection('J', Y) / 2 * this.Dx const rHS = this.Sn.CalcSection("Hs", Y); if (!rHS.ok) { return rHS; } const rJ = this.Sn.CalcSection("J", Y); if (!rJ.ok) { return rJ; } let trapezFn = rHS.vCalc + rJ.vCalc / 2 * this.Dx; // H est la charge totale. On se place dans le référentiel ou Zf de la section à calculer = 0 trapezFn -= this.Dx * this.section.prms.If.v; const r = dicho.Dichotomie(trapezFn, internal_modules_7.SessionSettings.precision, Y); if (!r.ok) { return r; } // return new Result(Y2, this); return r; } /** * Calcul du point suivant d'une courbe de remous * @param Y Tirant d'eau initial * @return Tirant d'eau */ Calc_Y(Y) { // let funcCalcY = 'Calc_Y_' + Resolution; // return this[funcCalcY](Y); let res; const methodeResolution = this.getPropValue("methodeResolution"); switch (methodeResolution) { case internal_modules_12.MethodeResolution.Trapezes: res = this.Calc_Y_Trapez(Y); break; case internal_modules_12.MethodeResolution.RungeKutta4: res = this.Calc_Y_RK4(Y); break; case internal_modules_12.MethodeResolution.EulerExplicite: res = this.Calc_Y_EulerExplicite(Y); break; default: throw new Error("CourbeRemous.Calc_Y() : type de méthode de résolution " + internal_modules_12.MethodeResolution[methodeResolution] + " non pris en charge"); } if (!res.ok || (0, internal_modules_1.XOR)(this.Dx > 0, !(res.vCalc < this.Sn.HautCritique.vCalc))) { return new internal_modules_10.Result(new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE), this); } return res; } size(o) { return Object.keys(o).length; } last(o) { let res; // tslint:disable-next-line:forin for (const i in o) { res = o[i]; } return res; } /** * Calcul d'une courbe de remous en fluvial ou torrentiel * @param YCL Condition limite amont (torrentiel) ou aval (fluvial) */ calcul(YCL, varParam) { const res = { log: new internal_modules_8.cLog(), trY: {} }; const abs0 = varParam.next().value; let lastY = YCL; res.trY[(0, internal_modules_1.round)(abs0, this.section.prms.iPrec)] = lastY; // Boucle de calcul de la courbe de remous while (varParam.hasNext) { const x = varParam.next().value; // this.debug("lastY " + lastY); const rY = this.Calc_Y(lastY); // this.debug("calcul : x " + x + " y " + rY.vCalc); // this.debug("trY "); // this.logObject(trY); // this.debug("end trY " + this.last(trY)); // this.debug("Yn " + this.Sn.HautNormale); if (rY.ok) { // on vérifie qu'on ne traverse pas la hauteur normale (à la précision de calcul près) const prec = internal_modules_7.SessionSettings.precision; const b1 = lastY - this.Sn.HautNormale > prec; const b2 = rY.vCalc - this.Sn.HautNormale > prec; if ((0, internal_modules_1.XOR)(b1, b2)) { this.debug("La pente de la ligne d'eau est trop forte à l'abscisse " + x + " m (Il faudrait réduire le pas de discrétisation)"); const m = new internal_modules_9.Message(internal_modules_9.MessageCode.ERROR_REMOUS_PENTE_FORTE); m.extraVar.x = x; // this._log.add(m); res.log.add(m); } // ligne d'eau res.trY[(0, internal_modules_1.round)(x, this.section.prms.iPrec)] = rY.vCalc; } else { const m = new internal_modules_9.Message(internal_modules_9.MessageCode.WARNING_REMOUS_ARRET_CRITIQUE); m.extraVar.x = x; // this._log.add(m); res.log.add(m); this.debug("Arrêt du calcul : Hauteur critique atteinte à l'abscisse " + x + " m"); break; } lastY = rY.vCalc; } return res; } logArray(a) { let s = "["; let first = true; for (const e of a) { if (!first) { s += ","; } s += String(e); first = false; } s += "]"; this.debug(s); } logObject(o) { if (o === undefined) { this.debug("<undefined>"); } else { const ks = Object.keys(o); ks.sort((a, b) => { if (+a > +b) { return 1; } if (+a < +b) { return -1; } return 0; }); for (const k of ks) { this.debug("[" + (+k).toFixed(3) + "]=" + o[+k]); } } } } exports.CourbeRemous = CourbeRemous; CourbeRemous._availableTargets = [ "Hs", "Hsc", "B", "P", "S", "R", "V", "Fr", "Ycor", "Ycon", "J", "I-J", "Imp", "Tau0" ]; //# sourceMappingURL=remous.js.map