From b89e41a6f0312fd8a98823c7bcf1104217397753 Mon Sep 17 00:00:00 2001
From: David Dorchies <david.dorchies@irstea.fr>
Date: Mon, 13 May 2019 23:22:46 +0200
Subject: [PATCH] #33 Structure: Better management of discharge inversion. PAB
 tests are better for discharge calculation but still wrong.

---
 spec/pab/pab.spec.ts                          |  5 ++-
 spec/structure/structure_test.ts              |  3 +-
 src/dichotomie.ts                             |  2 +-
 src/structure/structure.ts                    | 40 ++++++++++++++-----
 src/structure/structure_cem88d.ts             |  3 +-
 src/structure/structure_cem88v.ts             |  3 +-
 src/structure/structure_cunge80.ts            |  3 +-
 src/structure/structure_kivi.ts               |  3 +-
 src/structure/structure_orifice_submerged.ts  |  3 +-
 .../structure_rectangular_orifice_free.ts     |  3 +-
 ...structure_rectangular_orifice_submerged.ts |  3 +-
 .../structure_triangular_trunc_weir.ts        |  3 +-
 src/structure/structure_triangular_weir.ts    |  3 +-
 src/structure/structure_weir_free.ts          |  3 +-
 .../structure_weir_submerged_larinier.ts      |  3 +-
 15 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/spec/pab/pab.spec.ts b/spec/pab/pab.spec.ts
index 6fc2ab06..cd7c1587 100644
--- a/spec/pab/pab.spec.ts
+++ b/spec/pab/pab.spec.ts
@@ -81,9 +81,12 @@ for (let i = 0; i < 14; i++) {
 // Tests
 
 describe("Class Pab: ", () => {
-    describe("Calc(Z1) Exemple Formation 2018-09 p.14", () => {
+    describe("Exemple Formation 2018-09 p.14", () => {
         it("vCalc(Z1) should return 78.27", () => {
             expect(pab.Calc("Z1").vCalc).toBeCloseTo(78.27, 2);
         });
+        it("vCalc(Q) should return 0.773", () => {
+            expect(pab.Calc("Q").vCalc).toBeCloseTo(0.773, 2);
+        });
     });
 });
diff --git a/spec/structure/structure_test.ts b/spec/structure/structure_test.ts
index d574a9fa..225bc0fd 100644
--- a/spec/structure/structure_test.ts
+++ b/spec/structure/structure_test.ts
@@ -31,9 +31,8 @@ class StructureTest extends Structure {
         return this.getFlowRegime();
     }
 
-    public Equation(sVarCalc: string): Result {
+    public CalcQ(): Result {
         this.prms.update_h1h2();
-        Structure.CheckEquation(sVarCalc);
         const data = this.getResultData();
 
         return new Result(this.prms.Z1.v - this.prms.Z2.v - this.prms.ZDV.v, this, data);
diff --git a/src/dichotomie.ts b/src/dichotomie.ts
index 21f74407..edaab56e 100644
--- a/src/dichotomie.ts
+++ b/src/dichotomie.ts
@@ -215,7 +215,7 @@ export class Dichotomie extends Debug {
      * Il faudra s'assurer que cette première variable correspond à la méthode de calcul la plus rapide
      */
     private Calcul(): Result {
-        const r: Result = this.nub.Calc(this.analyticalSymbol);
+        const r: Result = this.nub.Equation(this.analyticalSymbol);
         this.debug(
             "dicho : Calcul(vX=" + this.sVarCalc + "=" + this.vX + ") -> " +
             this.analyticalSymbol + "=" + r.vCalc);
diff --git a/src/structure/structure.ts b/src/structure/structure.ts
index 0d44f85b..2547d78f 100644
--- a/src/structure/structure.ts
+++ b/src/structure/structure.ts
@@ -180,14 +180,11 @@ export abstract class Structure extends Nub {
             );
         }
 
-        // Mise à jour de h1 et h2
-        this.prms.update_h1h2();
-
         // Gestion du débit nul
         const flagsNull = { ENUM_StructureFlowMode: StructureFlowMode.NULL,
                             ENUM_StructureFlowRegime: StructureFlowRegime.NULL };
         if (sVarCalc === "Q") {
-            if (this.prms.h1.v <= 0 || this.prms.Z1.v === this.prms.Z2.v || this.prms.W.v <= 0) {
+            if (this.prms.Z1.v <= this.prms.ZDV.v || this.prms.Z1.v === this.prms.Z2.v || this.prms.W.v <= 0) {
                 return new Result(0, this, flagsNull);
             }
         } else if (this.prms.Q.v === 0) {
@@ -229,20 +226,43 @@ export abstract class Structure extends Nub {
         }
 
         // Gestion de l'inversion de débit : on inverse l'amont et l'aval pour le calcul
-        if ((sVarCalc === "Q" && (this.prms.h1.v < this.prms.h2.v)) || (sVarCalc !== "Q" && this.prms.Q.v < 0)) {
-            [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion
+        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
+            return res;
+        }
+
+        // Calcul normal hors débit nul
+        return super.Calc(sVarCalc, rInit);
+    }
+
+    /**
+     * Equation preprocessing
+     * @return true if inverted discharge
+     */
+    public Equation(sVarCalc: string): Result {
+        Structure.CheckEquation(sVarCalc);
+        this.prms.update_h1h2();
+        let res: Result;
+        if (this.prms.h1.v < this.prms.h2.v) {
+            [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion
+            res = this.CalcQ();
             if (sVarCalc === "Q") {
                 res.vCalc = -res.vCalc;
             }
             [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion
-            return res;
+        } else {
+            res = this.CalcQ();
         }
-
-        // Calcul normal hors débit nul et inversion de débit
-        return super.Calc(sVarCalc, rInit);
+        return res;
     }
 
+    /**
+     * Function to implement for the stage discharge equation of hydraulic structure
+     */
+    protected abstract CalcQ(): Result;
+
     protected getResultData() {
         return {
             ENUM_StructureFlowMode: this.getFlowMode(),
diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts
index 7d960877..9b973e98 100644
--- a/src/structure/structure_cem88d.ts
+++ b/src/structure/structure_cem88d.ts
@@ -23,8 +23,7 @@ export class StructureWeirCem88d extends RectangularStructure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) CEM88D
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         let v: number;
diff --git a/src/structure/structure_cem88v.ts b/src/structure/structure_cem88v.ts
index f02f9f33..e416201c 100644
--- a/src/structure/structure_cem88v.ts
+++ b/src/structure/structure_cem88v.ts
@@ -20,8 +20,7 @@ export class StructureWeirCem88v extends RectangularStructure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) CEM88V
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         let v: number;
diff --git a/src/structure/structure_cunge80.ts b/src/structure/structure_cunge80.ts
index a6196e62..2df43729 100644
--- a/src/structure/structure_cunge80.ts
+++ b/src/structure/structure_cunge80.ts
@@ -25,8 +25,7 @@ export class StructureCunge80 extends RectangularStructure {
      * Calcul du débit avec l'équation Cunge80
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
         let v: number;
 
diff --git a/src/structure/structure_kivi.ts b/src/structure/structure_kivi.ts
index 7bbbaccb..55acfd95 100644
--- a/src/structure/structure_kivi.ts
+++ b/src/structure/structure_kivi.ts
@@ -22,8 +22,7 @@ export class StructureKivi extends Structure {
         return this._prms as StructureKiviParams;
     }
 
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const res: Result = new Result(0, this, this.getResultData());
 
         // p : pelle
diff --git a/src/structure/structure_orifice_submerged.ts b/src/structure/structure_orifice_submerged.ts
index ebbd4a20..c3538432 100644
--- a/src/structure/structure_orifice_submerged.ts
+++ b/src/structure/structure_orifice_submerged.ts
@@ -28,8 +28,7 @@ export class StructureOrificeSubmerged extends Structure {
      * Calcul du débit avec l'équation classique d'un orifice noyé
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         const v = this.prms.Cd.v * this.prms.S.v * Structure.R2G * Math.sqrt(this.prms.Z1.v - this.prms.Z2.v);
diff --git a/src/structure/structure_rectangular_orifice_free.ts b/src/structure/structure_rectangular_orifice_free.ts
index 22212ec0..0b9b96e2 100644
--- a/src/structure/structure_rectangular_orifice_free.ts
+++ b/src/structure/structure_rectangular_orifice_free.ts
@@ -21,8 +21,7 @@ export class StructureRectangularOrificeFree extends RectangularStructure {
      * Calcul du débit avec l'équation classique d'un orifice dénoyé
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         const v = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v
diff --git a/src/structure/structure_rectangular_orifice_submerged.ts b/src/structure/structure_rectangular_orifice_submerged.ts
index 6c278cc6..48e038be 100644
--- a/src/structure/structure_rectangular_orifice_submerged.ts
+++ b/src/structure/structure_rectangular_orifice_submerged.ts
@@ -24,8 +24,7 @@ export class StructureRectangularOrificeSubmerged extends RectangularStructure {
      * Calcul du débit avec l'équation classique d'un orifice noyé
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         const v = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v
diff --git a/src/structure/structure_triangular_trunc_weir.ts b/src/structure/structure_triangular_trunc_weir.ts
index 4a709256..dee0d35f 100644
--- a/src/structure/structure_triangular_trunc_weir.ts
+++ b/src/structure/structure_triangular_trunc_weir.ts
@@ -28,8 +28,7 @@ export class StructureTriangularTruncWeirFree extends Structure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) seuil dénoyé
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         let Q: number = this.prms.Cd.v * this.prms.BT.v / (this.prms.ZT.v - this.prms.ZDV.v);
diff --git a/src/structure/structure_triangular_weir.ts b/src/structure/structure_triangular_weir.ts
index ee505df9..e6def5d4 100644
--- a/src/structure/structure_triangular_weir.ts
+++ b/src/structure/structure_triangular_weir.ts
@@ -28,8 +28,7 @@ export class StructureTriangularWeir extends Structure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) seuil dénoyé
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         let Q = this.prms.Cd.v * this.getTanFromDegrees(this.prms.alpha2.v)
diff --git a/src/structure/structure_weir_free.ts b/src/structure/structure_weir_free.ts
index 957791c6..fcda6652 100644
--- a/src/structure/structure_weir_free.ts
+++ b/src/structure/structure_weir_free.ts
@@ -20,8 +20,7 @@ export class StructureWeirFree extends RectangularStructure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) seuil dénoyé
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         const v = this.prms.Cd.v * this.prms.L.v * Structure.R2G * Math.pow(this.prms.h1.v, 1.5);
diff --git a/src/structure/structure_weir_submerged_larinier.ts b/src/structure/structure_weir_submerged_larinier.ts
index f7d7af00..d34a1d33 100644
--- a/src/structure/structure_weir_submerged_larinier.ts
+++ b/src/structure/structure_weir_submerged_larinier.ts
@@ -22,8 +22,7 @@ export class StructureWeirSubmergedLarinier extends RectangularStructure {
      * Calcul analytique Q = f(Cd, L, h1, h2, W) seuil dénoyé
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
-    public Equation(sVarCalc: string): Result {
-        Structure.CheckEquation(sVarCalc);
+    public CalcQ(): Result {
         const data = this.getResultData();
 
         const v = this.prms.Cd.v * this.prms.L.v * Structure.R2G
-- 
GitLab