diff --git a/jalhyd_branch b/jalhyd_branch index 16cc54ad77db05c20884afc3b44ba04d67f8db09..7f8147304dea3e5f1ef135be121d42f63648ed3f 100644 --- a/jalhyd_branch +++ b/jalhyd_branch @@ -1 +1 @@ -143-module-de-calcul-pente +146-passer-les-courbes-de-remous-en-cote diff --git a/src/app/calculators/remous/remous.config.json b/src/app/calculators/remous/remous.config.json index 2e0c26fc12efa3f382c2b77e0b16c9cc1bee0752..5abc2662d643c4e80977e7bb0856c11c3d25993c 100644 --- a/src/app/calculators/remous/remous.config.json +++ b/src/app/calculators/remous/remous.config.json @@ -27,8 +27,9 @@ "fields": [ "Ks", "Long", - "If", - "YB" + "YB", + "ZF1", + "ZF2" ] }, { @@ -36,8 +37,8 @@ "type": "fieldset", "fields": [ "Q", - "Yaval", - "Yamont" + "Z1", + "Z2" ] }, { diff --git a/src/app/calculators/remous/remous.en.json b/src/app/calculators/remous/remous.en.json index fadadf72f0ebf7c16258cb8e2725e3394c9abd4e..39ad2d88e3ff517beb05011e0e83d945a02042fe 100644 --- a/src/app/calculators/remous/remous.en.json +++ b/src/app/calculators/remous/remous.en.json @@ -14,17 +14,19 @@ "LargeurBerge": "Width at embankment level", "fs_bief": "Features reach", "Ks": "Strickler coefficient", + "Hs": "Head", "Long": "Length of reach", - "If": "Bottom slope", "YB": "Embankment elevation", "fs_condlim": "Boundary conditions", "Q": "Upstream flow", "S": "Wet surface", - "Yaval": "Water level imposed at downstream", - "Yamont": "Water level imposed at upstream", "fs_param_calc": "Calculation parameters", "Dx": "Discretisation step", "select_resolution": "Resolution method", + "Z1": "Upstream water elevation", + "Z2": "Downstream water elevation", + "ZF1": "Upstream bottom elevation", + "ZF2": "Downstream bottom elevation", "UNIT_FLU": "m", "UNIT_HS": "m", @@ -48,7 +50,7 @@ "fs_target_data": "Data to compute", "select_target": "Choice of the data to compute", "select_target_none": "None", - "select_target_Hs": "Specific head (m)", + "select_target_Hs": "Head (m)", "select_target_Hsc": "Critical head (m)", "select_target_B": "Surface width (m)", "select_target_P": "Wetted perimeter (m)", diff --git a/src/app/calculators/remous/remous.fr.json b/src/app/calculators/remous/remous.fr.json index ed9116978b353c4e710cc629faaa181fda1e5593..6c6d61121e0bf756d89b8dc2f5530fa3747d3e1e 100644 --- a/src/app/calculators/remous/remous.fr.json +++ b/src/app/calculators/remous/remous.fr.json @@ -14,16 +14,18 @@ "LargeurBerge": "Largeur de berge", "fs_bief": "Caractéristiques du bief", "Ks": "Coefficient de Strickler", + "Hs": "Charge", "Long": "Longueur du bief", - "If": "Pente du fond", "YB": "Hauteur de berge", "fs_condlim": "Conditions aux limites", "Q": "Débit amont", "S": "Surface mouillée", - "Yaval": "Tirant d'eau imposé à l'aval", - "Yamont": "Tirant d'eau imposé à l'amont", "Dx": "Pas de discrétisation", "select_resolution": "Méthode de résolution", + "Z1": "Cote de l'eau à l'amont", + "Z2": "Cote de l'eau à l'aval", + "ZF1": "Cote du fond à l'amont", + "ZF2": "Cote du fond à l'aval", "UNIT_FLU": "m", "UNIT_HS": "m", @@ -47,7 +49,7 @@ "fs_target_data": "Donnée à calculer", "select_target": "Choix de la donnée à calculer", "select_target_none": "Aucune", - "select_target_Hs": "La charge spécifique (m)", + "select_target_Hs": "La charge (m)", "select_target_Hsc": "La charge critique (m)", "select_target_B": "La largeur au miroir (m)", "select_target_P": "Le périmètre mouillé (m)", diff --git a/src/app/calculators/section-param/section-param.en.json b/src/app/calculators/section-param/section-param.en.json index 09723fabfc1197facf051bcd018377a3f9fc6b49..915cdb5055cb5218113354b196c051f533179875 100644 --- a/src/app/calculators/section-param/section-param.en.json +++ b/src/app/calculators/section-param/section-param.en.json @@ -20,8 +20,8 @@ "Q": "Flow", "Y": "Draft", "fs_param_calc": "Calculation parameters", - "Hs": "Specific cahrge", - "Hsc": "Critical charge", + "Hs": "Specific head", + "Hsc": "Critical head", "B": "Width at mirror", "P": "Wet perimeter", "S": "Wet surface", diff --git a/src/app/components/remous-results/remous-results.component.ts b/src/app/components/remous-results/remous-results.component.ts index bed67125d94dd8488c4e38f4d71075618a553633..ab9f3f71800041e327cad3c6cec6cc8e0ef655db 100644 --- a/src/app/components/remous-results/remous-results.component.ts +++ b/src/app/components/remous-results/remous-results.component.ts @@ -1,6 +1,6 @@ import { Component, ViewChild, DoCheck } from "@angular/core"; -import { ArrayReverseIterator, ResultElement, INumberIterator } from "jalhyd"; +import { INumberIterator, CourbeRemousParams, CourbeRemous } from "jalhyd"; import { I18nService } from "../../services/internationalisation.service"; import { LogComponent } from "../../components/log/log.component"; @@ -165,6 +165,20 @@ class ChartData { }; } + /** + * Dessigne une ligne droite entre y0 (abscisse 0) et ymax (abscisse max), + * sans passer par les méthodes mapPoint() et mapY() utilisées dans drawLine + */ + public drawSimpleLine(y0: number, ymax: number, prof: number, color: string, lbl: string, fillColor?: string) { + const l = this.newLine(prof); + l.setPoint(0, y0); + l.setPoint(this._longBief, ymax); + l.data = { + label: lbl, fill: fillColor !== undefined, tension: 0, spanGaps: true, + borderColor: color, backgroundColor: fillColor, pointRadius: 0 + }; + } + public get data() { const ds = []; this._lines.sort((a, b) => { @@ -384,62 +398,26 @@ export class RemousResultsComponent extends ResultsComponent implements DoCheck private connectRessaut(lineFlu: LineData, lineTor: LineData) { if (lineFlu !== undefined && lineTor !== undefined) { - const tX = lineFlu.tx.slice(0); // copie - - tX.sort((a, b) => { - if (a > b) { - return 1; - } - if (a < b) { - return -1; - } - return 0; - }); - - let minXflu; // abscisse de début de la courbe fluviale - let itX = this.abscisseIterator; - for (const re of this._remousResults.result.resultElements) { - if (!itX.hasNext) { - throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)"); - } - const x = itX.next().value; - if (re.getValue("flu") !== undefined) { - minXflu = x; - break; + const p = this._remousResults.varResults.variatedParameters[0].paramDefinition; + const xs = p.getInferredValuesList(); + // 1e passe : prolonger la torrentielle + outerloop1: + for (let i = 0; i < xs.length; i++) { + const x = xs[i]; + if (lineTor.getYat(x) === null) { + lineTor.setPoint(x, lineFlu.getYat(x)); + break outerloop1; } } - - if (minXflu !== undefined && minXflu !== tX[0]) { - // la courbe fluviale ne démarre pas au début, on ajoute un point de raccord avec la ligne torrentielle - - const i = tX.indexOf(minXflu); - const xflu = tX[i - 1]; - const yflu = lineTor.getYat(xflu); - lineFlu.setPoint(xflu, yflu); - } - - let maxXtor; // abscisse de fin de la courbe torrentielle - const itRE = new ArrayReverseIterator<ResultElement>(this._remousResults.result.resultElements); - itX = this.abscisseIterator; - for (const r of itRE) { - if (!itX.hasNext) { - throw new Error("RemousResultsComponent.connectRessaut() : erreur interne (itérateur sur x)"); - } - const x = itX.next(); - if (r.getValue("tor") !== undefined) { - maxXtor = x; - break; + // 2e passe : prolonger la fluviale + outerloop2: + for (let i = xs.length - 1; i >= 0; i--) { + const x = xs[i]; + if (lineFlu.getYat(x) === null) { + lineFlu.setPoint(x, lineTor.getYat(x)); + break outerloop2; } } - - if (maxXtor !== undefined && maxXtor !== tX[tX.length - 1]) { - // la courbe torrentielle ne finit pas à la fin des abscisses, on ajoute un point de raccord avec la ligne fluviale - - const i = tX.indexOf(maxXtor); - const xflu = tX[i + 1]; - const yflu = lineFlu.getYat(xflu); - lineTor.setPoint(xflu, yflu); - } } } @@ -452,6 +430,11 @@ export class RemousResultsComponent extends ResultsComponent implements DoCheck this.varResultsComponent.results = this._remousResults.varResults; } + const nub = this._remousResults.result.sourceNub as CourbeRemous; + const params = nub.prms as CourbeRemousParams; + const ZF1 = params.ZF1.singleValue; + const ZF2 = params.ZF2.singleValue; + const hauteurBerge = nub.section.prms.YB.singleValue; const penteFond: number = this._remousResults.penteFond; // abscisses @@ -480,29 +463,30 @@ export class RemousResultsComponent extends ResultsComponent implements DoCheck } // ligne de fond - gr1.drawLine(0, 0, 3, "#753F00", this.uitextFond, "#753F00"); + gr1.drawSimpleLine(ZF1, ZF2, 3, "#753F00", this.uitextFond, "#753F00"); // ligne de berge - if (this._remousResults.hautBerge) { - gr1.drawLine(this._remousResults.hautBerge, this._remousResults.hautBerge, 4, "#C58F50", this.uitextBerge); + if (hauteurBerge) { + gr1.drawSimpleLine(ZF1 + hauteurBerge, ZF2 + hauteurBerge, 4, "#C58F50", this.uitextBerge); } // hauteur normale if (this._remousResults.hautNormale !== undefined && this._remousResults.hautNormale.ok) { - gr1.drawLine(this._remousResults.hautNormale.vCalc, this._remousResults.hautNormale.vCalc, + const Yn = this._remousResults.hautNormale.vCalc; + gr1.drawSimpleLine(Yn + ZF1, Yn + ZF2, 5, "#A4C537", this.uitextTirantNormal ); } // hauteur critique if (this._remousResults.hautCritique !== undefined && this._remousResults.hautCritique.ok) { - gr1.drawLine(this._remousResults.hautCritique.vCalc, this._remousResults.hautCritique.vCalc, + const Yc = this._remousResults.hautCritique.vCalc; + gr1.drawSimpleLine(Yc + ZF1, Yc + ZF2, 6, "#FF0000", this.uitextTirantCritique ); } // lignes d'eau torrentielle et fluviale - let lineFlu: LineData; if (this._remousResults.hasFluData) { lineFlu = gr1.newLine(0); @@ -529,17 +513,17 @@ export class RemousResultsComponent extends ResultsComponent implements DoCheck const x = itX.next().value; const yExtra = re.getValue(this._remousResults.extraParamSymbol); if (yExtra !== undefined) { - lineExtra.mapPoint(x, yExtra); + lineExtra.setPoint(x, yExtra); } const yFlu = re.getValue("flu"); if (yFlu !== undefined) { - lineFlu.mapPoint(x, yFlu); + lineFlu.setPoint(x, yFlu); } const yTor = re.getValue("tor"); if (yTor !== undefined) { - lineTor.mapPoint(x, yTor); + lineTor.setPoint(x, yTor); } } @@ -558,11 +542,9 @@ export class RemousResultsComponent extends ResultsComponent implements DoCheck } // raccordement ligne fluviale -> torrentielle pour dessiner le ressaut - this.connectRessaut(lineFlu, lineTor); // ajout des données au graphique - if (lineTor !== undefined) { lineTor.data = { label: this.uitextLigneTorrentielle, diff --git a/src/app/formulaire/definition/form-compute-courbe-remous.ts b/src/app/formulaire/definition/form-compute-courbe-remous.ts index 2491a2683b2a8a97f8b522e7396ed9d7606b22d1..2a837d31a92a47b78f5306e8604dc84df2fe10e0 100644 --- a/src/app/formulaire/definition/form-compute-courbe-remous.ts +++ b/src/app/formulaire/definition/form-compute-courbe-remous.ts @@ -40,7 +40,8 @@ export class FormComputeCourbeRemous extends FormCompute { this.remousResults.extraParamSymbol = this._formBase.currentNub.properties.getPropValue("varCalc"); // calcul - this.remousResults.result = cr.calculRemous(this.remousResults.extraParamSymbol); + // this.remousResults.result = cr.calculRemous(this.remousResults.extraParamSymbol); + this.remousResults.result = cr.CalcSerie(); // données du graphe this.remousResults.hauteurNormale = this.resultYn.resultElement; diff --git a/src/app/formulaire/definition/form-compute.ts b/src/app/formulaire/definition/form-compute.ts index 0917ded925a3e3d16c44fe4872c584d289db850e..e733e6e51e7a8da49c8a527db1c87e917c0784d2 100644 --- a/src/app/formulaire/definition/form-compute.ts +++ b/src/app/formulaire/definition/form-compute.ts @@ -36,66 +36,8 @@ export abstract class FormCompute implements Observer { * Lance le calcul d'un paramètre en déterminant une valeur initiale. * Si nécessaire déclenche un calcul en chaîne des modules en amont. */ - protected runNubCalc(nub: Nub, computedParam?: ParamDefinition): Result { - let init: number; - - // by default, use Nub's calculatedParam - if (computedParam === undefined) { - computedParam = nub.calculatedParam; - } - - if (computedParam === undefined) { - // modules that have no calculated param (ex: Grille) - return nub.CalcSerie(); - - } else { - // const computedParamValue = computedParam.getValue(); - const computedParamValue = computedParam.singleValue; - - switch (computedParam.domain.domain) { - case ParamDomainValue.ANY: - if (computedParam && computedParam.isDefined) { - init = computedParamValue; - } - if (init === undefined) { - init = 0; - } - break; - - case ParamDomainValue.POS_NULL: - if (computedParam && computedParam.isDefined) { - init = Math.max(computedParamValue, 0); - } - if (init === undefined) { - init = 0; - } - break; - - case ParamDomainValue.INTERVAL: - init = (computedParam.domain.minValue + computedParam.domain.maxValue) / 2; - break; - - case ParamDomainValue.NOT_NULL: - if (computedParam && computedParam.isDefined) { - init = computedParamValue; - } - if (init === undefined || init === 0) { - init = 1e-8; - } - break; - - case ParamDomainValue.POS: - if (computedParam && computedParam.isDefined) { - init = Math.max(computedParamValue, 1e-8); - } - if (init === undefined) { - init = 1e-8; - } - break; - } - - return nub.CalcSerie(init, this.getParameterRefid(computedParam)); - } + protected runNubCalc(nub: Nub): Result { + return nub.CalcSerie(); } protected getComputedParameter(): NgParameter { diff --git a/src/app/results/remous-results.ts b/src/app/results/remous-results.ts index ba7c03a9590464f90bbcbcefe1274d3766abfec0..60b6b6a7485ac3244311042a9fdb2b532b615b6a 100644 --- a/src/app/results/remous-results.ts +++ b/src/app/results/remous-results.ts @@ -98,7 +98,7 @@ export class RemousResults extends CalculatorResults { // série de valeurs de X this._xValues = new ParamDefinition(p, "Abscisse", ParamDomainValue.POS_NULL); - this._xValues.paramValues.setValues(0, Long, Dx); + this._xValues.setValues(0, Long, Dx); } public get log() { diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json index 9e11bf181847bb5f14b4bec7979d25d67fb79fea..e8cbdf1d3a141377537f4acc845dc41418d5d792 100644 --- a/src/locale/messages.en.json +++ b/src/locale/messages.en.json @@ -40,6 +40,7 @@ "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "invalid %minValue%/%maxValue% min/max boundaries for 'interval' parameter definition domain", "ERROR_PARAMDOMAIN_INVALID": "parameter '%symbol%: non supported '%domain%' definition domain", "ERROR_PROBLEM_LOADING_SESSION": "Session loaded, with errors", + "ERROR_REMOUS_NO_WATER_LINE": "No water line can be calculated", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Upstream boundary condition < Critical elevation: no possible calculation from upstream", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Downstream boundary condition < Critical elevation: no possible calculation from downstream", "ERROR_REMOUS_PENTE_FORTE": "The water line slope is too steep at abscissa %x% m (the discretisation step should be reduced)", @@ -49,6 +50,7 @@ "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Non convergence of the calculation of the normal depth (Newton's method)", "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "The slope is negative or zero, the normal depth is infinite", "ERROR_STRUCTURE_Q_TROP_ELEVE": "The flow passing through the other devices is too high: the requested parameter is not calculable.", + "ERROR_SECTION_SURFACE_NULLE": "Section : calcul impossible à cause d'une surface nulle", "INFO_CALCULATOR_CALC_NAME": "Calculator name", "INFO_CALCULATOR_CALCULER": "Compute", "INFO_CALCULATOR_CLONE": "Duplicate", @@ -448,5 +450,9 @@ "WARNING_VANLEV_ZDV_SUP_MAX": "Regulated weir: maximum sill elevation reached", "WARNING_GRILLE_ALPHA_GREATER_THAN_45": "Recommendation for fish guiding : α ≤ 45°", "WARNING_GRILLE_BETA_GREATER_THAN_26": "Recommendation for fish guiding : β ≤ 26°", - "WARNING_GRILLE_VN_GREATER_THAN_05": "Recommendation to prevent fish getting stuck on grid plan (physical barrier) or prematurely passing through the grid (behavioural barrier) : VN ≤ 0.5 m/s.<br>Above average value calculated here, refer to the recommendations taken from experimental caracterisation of effective speed values." + "WARNING_GRILLE_VN_GREATER_THAN_05": "Recommendation to prevent fish getting stuck on grid plan (physical barrier) or prematurely passing through the grid (behavioural barrier) : VN ≤ 0.5 m/s.<br>Above average value calculated here, refer to the recommendations taken from experimental caracterisation of effective speed values.", + "WARNING_UPSTREAM_BOTTOM_HIGHER_THAN_WATER": "Upstream water elevation is lower or equal to bottom elevation", + "WARNING_DOWNSTREAM_BOTTOM_HIGHER_THAN_WATER": "Downstream water elevation is lower or equal to bottom elevation", + "WARNING_YN_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "Normal depth: slope is negative or zero, normal depth is infinite", + "WARNING_YN_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Normal depth: non convergence of the calculation (Newton's method)" } diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json index 56324143c725e03322a2ee308787071667c66397..f2199ec48ec6217d359dedb84a5a225299f8cd82 100644 --- a/src/locale/messages.fr.json +++ b/src/locale/messages.fr.json @@ -40,6 +40,7 @@ "ERROR_PARAMDOMAIN_INTERVAL_BOUNDS": "Les bornes (%minValue%/%maxValue%) de l'intervalle sont incorrectes", "ERROR_PARAMDOMAIN_INVALID": "Paramètre '%symbol%' : le domaine de définition '%domain%' est incorrect", "ERROR_PROBLEM_LOADING_SESSION": "Session chargée, avec des erreurs", + "ERROR_REMOUS_NO_WATER_LINE": "Aucune ligne d'eau ne peut être calculée", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT": "Condition limite amont > Hauteur critique : pas de calcul possible depuis l'amont", "ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL": "Condition limite aval < Hauteur critique : pas de calcul possible depuis l'aval", "ERROR_REMOUS_PENTE_FORTE": "La pente de la ligne d'eau est trop forte à l'abscisse %x% m (il faudrait réduire le pas de discrétisation)", @@ -48,6 +49,7 @@ "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCOR": "Non convergence du calcul de la hauteur correspondante (Méthode de Newton)", "ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Non convergence du calcul de la hauteur normale (Méthode de Newton)", "ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "La pente est négative ou nulle, la hauteur normale est infinie", + "ERROR_SECTION_SURFACE_NULLE": "Section: calculation is impossible when surface is null", "ERROR_STRUCTURE_Q_TROP_ELEVE": "Le débit passant par les autres ouvrages est trop élevé: le paramètre demandé n'est pas calculable.", "INFO_CALCULATOR_CALC_NAME": "Nom du module de calcul", "INFO_CALCULATOR_CALCULER": "Calculer", @@ -447,5 +449,9 @@ "WARNING_VANLEV_ZDV_SUP_MAX": "Seuil régulé : cote maximale de seuil atteinte", "WARNING_GRILLE_ALPHA_GREATER_THAN_45": "Préconisation pour le guidage des poissons : α ≤ 45°", "WARNING_GRILLE_BETA_GREATER_THAN_26": "Préconisation pour le guidage des poissons : β ≤ 26°", - "WARNING_GRILLE_VN_GREATER_THAN_05": "Préconisation pour éviter le placage des poissons sur le plan de grille (barrière physique) ou leur passage prématuré au travers (barrière comportementale) : VN ≤ 0.5 m/s.<br>Au-delà de la valeur moyenne calculée ici, se reporter aux préconisations tirées de la caractérisation expérimentale des valeurs effectives de vitesses." + "WARNING_GRILLE_VN_GREATER_THAN_05": "Préconisation pour éviter le placage des poissons sur le plan de grille (barrière physique) ou leur passage prématuré au travers (barrière comportementale) : VN ≤ 0.5 m/s.<br>Au-delà de la valeur moyenne calculée ici, se reporter aux préconisations tirées de la caractérisation expérimentale des valeurs effectives de vitesses.", + "WARNING_UPSTREAM_BOTTOM_HIGHER_THAN_WATER": "La cote de l'eau à l'amont est plus basse ou égale à la cote de fond", + "WARNING_DOWNSTREAM_BOTTOM_HIGHER_THAN_WATER": "La cote de l'eau à l'aval est plus basse ou égale à la cote de fond", + "WARNING_YN_SECTION_PENTE_NEG_NULLE_HNORMALE_INF": "Hauteur normale: pente négative ou nulle, hauteur normale infinie", + "WARNING_YN_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE": "Hauteur normale: non convergence du calcul (méthode de Newton)" }