structure.ts 15.16 KiB
import { ChildNub } from "../internal_modules";
import { CalculatorType } from "../internal_modules";
import { ParamCalculability, ParamDefinition, ParamFamily } from "../internal_modules";
import { Props } from "../internal_modules";
import { Message, MessageCode } from "../internal_modules";
import { Result } from "../internal_modules";
import { StructureParams } from "../internal_modules";
import { LoiDebit, StructureProperties } from "../internal_modules";
import { ParallelStructure } from "../internal_modules";
import { round } from "../internal_modules";
import { Nub } from "../internal_modules";
/**
 * Flow mode: weir or orifice flow
export enum StructureFlowMode {
    /** Weir flow */
    WEIR,
    /** Orifice flow */
    ORIFICE,
    /** Zéro flow */
    NULL
/**
 * Flow regime: free flow, partially submerged or submerged
export enum StructureFlowRegime {
    /** Free flow (unsubmerged) */
    FREE,
    /** Partially submerged flow */
    PARTIAL,
    /** Submerged flow */
    SUBMERGED,
    /** Zéro flow */
    NULL
/** Type de jet : Sans objet (orifice), plongeant, de surface */
export enum StructureJetType {
    /** Plongeant */
    PLONGEANT,
    /** De surface */
    SURFACE,
    /** Sans objet (orifice) */
/**
 * classe de calcul sur la conduite distributrice
export abstract class Structure extends ChildNub {
    /**
     * Test générique si VarCalc="Q" pour l'utilisation de Equation
    public static CheckEquation(sVarCalc: string) {
        if (sVarCalc !== "Q") { throw new Error("Structure.Equation() : invalid parameter name " + sVarCalc); }
    /**
     * calcul du pourcentage d'ennoiement arrondi à l'unité
    public computeSubmergencePercentage(H2?: number): number {
        const h1 = this._prms.get("h1").v;
        const h2 = H2 === undefined ? this._prms.get("h2").v : H2;
        return Structure.computeSubmergencePercentage(h1, h2);
    /**
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
* calcul du pourcentage d'ennoiement arrondi à l'unité (version statique) */ public static computeSubmergencePercentage(h1: number, h2: number): number { if (h1 !== 0) { return round(h2 / h1 * 100, 1); } return 100; } /** * méthode générique de vérification que l'ennoiement est supérieur à une valeur donnée * @param min valeur minimum de l'ennoiement */ protected checkSubmergenceMin(res: Result, min: number) { // on fait le test soit : // - si cette structure n'est pas une vanne levante // - si cette structure est une vanne levante et le flag d'autorisation du test est vrai if (!this.isVanneLevante || this.doVanLevSubmergenceCheck) { const h2h1ratio = this.prms.h2.v / this.prms.h1.v; if (h2h1ratio < min) { res.resultElement.addMessage(new Message( // this._result.globalLog.add(new Message( MessageCode.ERROR_STRUCTURE_SUBMERGENCE_LOWER_THAN, { submergencePerc: this.computeSubmergencePercentage().toString(), min: min * 100 } )); } } } /** * fonction appelée dans Calc() pour vérifier l'ennoiement (cf. classes dérivées) */ public checkSubmergence(res: Result) { } // si une erreur d'ennoiement est survenue, on annule les résultats public static filterResultsOnSubmergenceError(res: Result): boolean { if (res.resultElement.hasMessage(MessageCode.ERROR_STRUCTURE_SUBMERGENCE_LOWER_THAN)) { res.resultElement.removeValues(); return true; } return false; } /** Constante utile : Racine de 2g */ protected static readonly R2G: number = Math.sqrt(2 * 9.81); /** Peut-on calculer ZDV ? */ protected _isZDVcalculable: boolean; private _loiDebit: LoiDebit; constructor(prms: StructureParams, dbg: boolean = false) { super(prms, dbg); this.setCalculatorType(CalculatorType.Structure); this._isZDVcalculable = true; // Q is always the only calculated variable; setting another parameter // of a Structure to CALC mode makes it the calculated variable of the // *parent* ParallelStructures this.calculatedParam = this.prms.Q; this._intlType = "Ouvrage"; } public get doVanLevSubmergenceCheck(): boolean { const ps = this.parent as ParallelStructure; return ps.doVanLevSubmergenceCheck;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} /** * true si la structure est une vanne levante * @see StructureVanLevLarinier * @see StructureVanLevVillemonte */ protected get isVanneLevante(): boolean { return false; } public get isZDVcalculable(): boolean { return this._isZDVcalculable; } /** * paramètres castés au bon type */ public get prms(): StructureParams { return this._prms as StructureParams; } public get W(): number { if (this.prms.W.visible) { return this.prms.W.v; } else { return Infinity; } } public get loiDebit(): LoiDebit { return this._loiDebit; } protected setLoiDebit(ld: LoiDebit) { if (ld === undefined) { throw new Error("invalid null LoiDebit"); } // completes props with structureType and loiDebit this._loiDebit = ld; this._props.setPropValue("loiDebit", this._loiDebit); this.updateStructureType(); } public setParent(p: Nub): void { super.setParent(p); this.updateStructureType(); } private updateStructureType() { if (this._loiDebit !== undefined && this.parent !== undefined) { this._props.setPropValue("structureType", StructureProperties.findCompatibleStructure(this._loiDebit, this.parent as ParallelStructure)); } } /** * Returns the nth visible parameter (used in nghyd/PabTable) */ public getNthVisibleParam(n: number): ParamDefinition { let i = 0; for (const p of this.parameterIterator) { if (p.visible) { if (n === i) { return p; } i++; } } return undefined; }
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
/** * Calcul d'une équation quelle que soit l'inconnue à calculer. * Gestion du débit nul et de l'inversion de débit * @param sVarCalc nom de la variable à calculer * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie */ public Calc(sVarCalc: string, rInit?: number): Result { // Gestion de l'exception de calcul de W sur les seuils if (rInit === undefined) { rInit = this.getParameter(sVarCalc).v; } if (sVarCalc === "W" && rInit === Infinity) { throw new Error("Structure:Calc : Calcul de W impossible sur un seuil"); } // Gestion de l'erreur de calcul de ZDV quand il n'est pas calculable if (sVarCalc === "ZDV" && !this.isZDVcalculable) { return new Result( new Message(MessageCode.ERROR_STRUCTURE_ZDV_PAS_CALCULABLE) ); } this.prms.update_h1h2(); // Gestion du débit nul const flagsNull = { ENUM_StructureFlowMode: StructureFlowMode.NULL, ENUM_StructureFlowRegime: StructureFlowRegime.NULL, ENUM_StructureJetType: StructureJetType.SO }; if (sVarCalc === "Q") { if (this.prms.h1.v <= 1E-20 || Math.abs(this.prms.h1.v - this.prms.h2.v) < 1E-20 || this.W <= 1E-20) { this.currentResultElement = new Result(0, this, flagsNull); return this._result; } } else if (this.prms.Q.v === 0) { // Débit nul <=> tirant d'eau amont = tirant d'eau aval ou tout autre paramètre nul switch (sVarCalc) { case "Z1": // max(Z2,ZDV) dans le cas dénoyé et noyé // on met Z1 à ZDV pour faciliter les calculs sur les prébarrages this.currentResultElement = new Result(Math.max(this.prms.Z2.v, this.prms.ZDV.v), this, flagsNull); return this._result; case "Z2": // max(Z1,ZDV) dans le cas dénoyé et noyé this.currentResultElement = new Result(Math.max(this.prms.Z1.v, this.prms.ZDV.v), this, flagsNull); return this._result; default: // Est-ce toujours vrai ? Nécessitera peut-être d'étendre la méthode this.currentResultElement = new Result(0, this, flagsNull); return this._result; } } else if (this.W === 0 && sVarCalc === "Z1") { // Si la vanne est fermée la cote amont est infinie this.currentResultElement = new Result(Infinity, this, flagsNull); return this._result; } // Gestion du cas d'écoulement impossible Z1 > Z2 et Q <= 0 if (!(sVarCalc === "Q" || sVarCalc === "Z1" || sVarCalc === "Z2")) { if ( (this.prms.Z1.v >= this.prms.Z2.v && this.prms.Q.v <= 0) || (this.prms.Z1.v <= this.prms.Z2.v && this.prms.Q.v >= 0) ) { // On ferme l'ouvrage et on renvoie un code d'erreur let rPrm: number; switch (sVarCalc) { case "ZDV": rPrm = Math.max(this.prms.Z1.v, this.prms.Z2.v); break;
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
default: rPrm = 0; } let res: Result; if (this.prms.Z1.v === this.prms.Z2.v && this.prms.Q.v !== 0) { res = new Result(new Message(MessageCode.ERROR_STRUCTURE_Z_EGAUX_Q_NON_NUL), this); } else { res = new Result(new Message(MessageCode.ERROR_STRUCTURE_Q_TROP_ELEVE), this, flagsNull); } res.vCalc = rPrm; this.currentResultElement = res; // "Les cotes et le débit ne sont pas cohérents => fermeture de l'ouvrage return res; } } // Gestion de l'inversion de débit : on inverse l'amont et l'aval pour le calcul if (sVarCalc !== "Q" && this.prms.Q.v < 0) { [this.prms.Z1.v, this.prms.Z2.v] = [this.prms.Z2.v, this.prms.Z1.v]; // Swap ES6 fashion const res: Result = super.Calc(sVarCalc, rInit); [this.prms.Z1.v, this.prms.Z2.v] = [this.prms.Z2.v, this.prms.Z1.v]; // Swap ES6 fashion this.currentResultElement = res; return res; } // Calcul normal hors débit nul const res = super.Calc(sVarCalc, rInit); this.checkSubmergence(res); Structure.filterResultsOnSubmergenceError(res); return res; } /** * Equation preprocessing * @return true if inverted discharge */ public Equation(sVarCalc: string): Result { Structure.CheckEquation(sVarCalc); let res: Result; let bInverted: boolean = false; if (this.prms.Z1.v < this.prms.Z2.v) { [this.prms.Z1.v, this.prms.Z2.v] = [this.prms.Z2.v, this.prms.Z1.v]; // Swap ES6 fashion bInverted = true; } this.prms.update_h1h2(); res = this.CalcQ(); if (bInverted) { if (sVarCalc === "Q") { res.vCalc = -res.vCalc; } [this.prms.Z1.v, this.prms.Z2.v] = [this.prms.Z2.v, this.prms.Z1.v]; // Swap ES6 fashion } return res; } /** * Function to implement for the stage discharge equation of hydraulic structure */ protected abstract CalcQ(): Result; protected getResultData() { return { ENUM_StructureFlowMode: this.getFlowMode(), ENUM_StructureFlowRegime: this.getFlowRegime(), ENUM_StructureJetType: this.getJetType() }; } /**
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
* paramétrage de la calculabilité des paramètres */ protected setParametersCalculability() { this.prms.Q.calculability = ParamCalculability.EQUATION; this.prms.ZDV.calculability = ParamCalculability.DICHO; this.prms.Z1.calculability = ParamCalculability.DICHO; this.prms.Z2.calculability = ParamCalculability.DICHO; this.prms.h1.calculability = ParamCalculability.DICHO; this.prms.h2.calculability = ParamCalculability.DICHO; this.prms.W.calculability = ParamCalculability.FIXED; } /** * Give the flow mode : weir or orifice flow */ protected getFlowMode(): StructureFlowMode { if (this.prms.h1.v > this.W) { this.debug("Structure.getFlowMode(h1=" + this.prms.h1.v + ",W=" + this.W + ")=ORIFICE"); return StructureFlowMode.ORIFICE; } else { this.debug("Structure.getFlowMode(h1=" + this.prms.h1.v + ",W=" + this.W + ")=WEIR"); return StructureFlowMode.WEIR; } } /** * Give the flow regime for a rectangular section : free, partially submerged or submerged flow */ protected getFlowRegime(): StructureFlowRegime { // Weir have only two flow regimes: free and submerged flow // Orifice have three flow regimes: free, partially submerged and (totally) submerged if (this.prms.h2.v <= 2 / 3 * this.prms.h1.v) { // free flow for both weirs and orifices this.debug( "Structure.getFlowRegime(h1=" + this.prms.h1.v + ",h2=" + this.prms.h2.v + ",W=" + this.W + ")=FREE"); return StructureFlowRegime.FREE; } else if (this.prms.h1.v > this.W && this.prms.h2.v < (2 * this.prms.h1.v + this.W) / 3) { // Partially submerged only for orifices this.debug( "Structure.getFlowRegime(h1=" + this.prms.h1.v + ",h2=" + this.prms.h2.v + ",W=" + this.W + ")=PARTIAL"); return StructureFlowRegime.PARTIAL; } else { // (Totally) submerged for both weirs and orifices this.debug( "Structure.getFlowRegime(h1=" + this.prms.h1.v + ",h2=" + this.prms.h2.v + ",W=" + this.W + ")=SUBMERGED"); return StructureFlowRegime.SUBMERGED; } } /** * Give the Jet Type for weir flow * Cf. Baudoin J.M., Burgun V., Chanseau M., Larinier M., Ovidio M., Sremski W., Steinbach P. et Voegtle B., 2014. * Evaluer le franchissement des obstacles par les poissons. Principes et méthodes. Onema. 200 pages */ protected getJetType(): StructureJetType { if (this.getFlowMode() === StructureFlowMode.WEIR) { if (Math.abs(this.prms.h1.v - this.prms.h2.v) < 0.5 * this.prms.h1.v) { return StructureJetType.SURFACE; } else { return StructureJetType.PLONGEANT; } } else { return StructureJetType.SO; }
421422423424425426427428429430431432433
} protected exposeResults() { this._resultsFamilies = { Q: ParamFamily.FLOWS }; } public getFirstAnalyticalParameter() { return this.prms.Q; } }