From 4dfa0ec2fff99e6d6d7d21db5ce20c777f04f584 Mon Sep 17 00:00:00 2001
From: David Dorchies <david.dorchies@irstea.fr>
Date: Thu, 20 Jun 2019 15:40:28 +0200
Subject: [PATCH] =?UTF-8?q?#33=20Generation=20de=20la=20g=C3=A9om=C3=A9tri?=
 =?UTF-8?q?e=20de=20la=20PAB=20=C3=A0=20partir=20d'une=20cloison?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 spec/pab/pab.spec.ts                |  91 +++++++++++++++---------
 src/pab/cloisons.ts                 |   2 +-
 src/pab/cloisons_params.ts          |   7 +-
 src/pab/pab.ts                      | 103 +++++++++++++++++++---------
 src/session.ts                      |   2 +-
 src/structure/parallel_structure.ts |   4 ++
 6 files changed, 140 insertions(+), 69 deletions(-)

diff --git a/spec/pab/pab.spec.ts b/spec/pab/pab.spec.ts
index f842852e..f032e23e 100644
--- a/spec/pab/pab.spec.ts
+++ b/spec/pab/pab.spec.ts
@@ -20,35 +20,39 @@ const dbg: boolean = false;
  * Exemple formation Cassiopée 2018-09
  */
 
-// Modèle de cloison
-const modelCloisons = new Cloisons(
-    new CloisonsParams(
-        0.773,      // Débit total (m3/s)
-        78.27,    // Cote de l'eau amont (m)
-        3.1,     // Longueur des bassins (m)
-        2.5,      // Largeur des bassins (m)
-        1.5,      // Profondeur moyenne (m)
-        0.23     // Hauteur de chute (m)
-    )
-);
+function createModelCloisonTest(): Cloisons {
+    // Modèle de cloison
+    const modelCloisons = new Cloisons(
+        new CloisonsParams(
+            0,      // Débit total (m3/s)
+            78.27,    // Cote de l'eau amont (m)
+            3.1,     // Longueur des bassins (m)
+            2.5,      // Largeur des bassins (m)
+            1.5,      // Profondeur moyenne (m)
+            0.23     // Hauteur de chute (m)
+        )
+    );
 
-const rectStructPrms = new RectangularStructureParams(
-    0.773,  // Q
-    76.67,        // ZDV
-    0,        // Z1
-    0,      // Z2
-    0.35,          // L
-    0.65        // Cd pour un seuil rectangulaire
-    // W = Infinity par défaut pour un seuil
-);
+    const rectStructPrms = new RectangularStructureParams(
+        0,  // Q
+        76.67,        // ZDV
+        0,        // Z1
+        0,      // Z2
+        0.35,          // L
+        0.65        // Cd pour un seuil rectangulaire
+        // W = Infinity par défaut pour un seuil
+    );
+
+    // Ajout d'ouvrage dans la cloison
+    modelCloisons.addChild(new StructureWeirSubmergedLarinier(rectStructPrms));
 
-// Ajout d'ouvrage dans la cloison
-modelCloisons.addChild(new StructureWeirSubmergedLarinier(rectStructPrms));
+    return modelCloisons;
+}
 
 // Création de la cloison aval
 const downWall = new ParallelStructure(new ParallelStructureParams(0, 0, 0));
 const kiviPrms = new StructureKiviParams(
-    0.773,  // Q
+    0,  // Q
     73.95,        // ZDV
     0,        // Z1
     0,      // Z2
@@ -62,8 +66,8 @@ downWall.addChild(new StructureKivi(kiviPrms));
 // Création de la passe
 const pab: Pab = new Pab(
     new PabParams(
-        modelCloisons.prms.Q.v,
-        100,
+        0.773,
+        78.27,
         74.86
     ),
     downWall,
@@ -71,24 +75,43 @@ const pab: Pab = new Pab(
 );
 
 // Ajout des cloisons
+pab.addCloisonsFromModel(createModelCloisonTest(), 15);
 
-const pabCloison = new PabCloisons(modelCloisons, 0, dbg);
-
-for (let i = 0; i < 14; i++) {
-    pab.addChild(pabCloison);
+function TestGeometry(b: Cloisons, ZRMB: number, ZRAM: number, ZDV: number) {
+    it(`ZRMB should be egal to ${ZRMB}`, () => {
+        expect(b.prms.ZRMB.currentValue).toBeCloseTo(ZRMB, 3);
+    });
+    it(`ZRAM should be egal to ${ZRAM}`, () => {
+        expect(b.prms.ZRAM.currentValue).toBeCloseTo(ZRAM, 3);
+    });
+    it(`ZDV should be egal to ${ZDV}`, () => {
+        expect(b.structures[0].prms.ZDV.currentValue).toBeCloseTo(ZDV, 3);
+    });
 }
 
 // Tests
-
-xdescribe("Class Pab: ", () => {
+describe("Class Pab: ", () => {
     describe("Exemple Formation 2018-09 p.14", () => {
+        let ZRMB = pab.prms.Z1.currentValue - pab.children[0].prms.PB.currentValue
+            - pab.children[0].prms.DH.currentValue;
+        let ZDV = pab.prms.Z1.currentValue - pab.children[0].structures[0].prms.h1.currentValue;
+        let i: number = 0;
+        for (const b of pab.children) {
+            describe(`Geometry Basin #${i}`, () => {
+                TestGeometry(
+                    b, ZRMB,
+                    ZRMB + pab.children[0].prms.DH.currentValue / 2,
+                    ZDV);
+            });
+            i++;
+            ZRMB -= pab.children[0].prms.DH.currentValue;
+            ZDV -= pab.children[0].prms.DH.currentValue;
+        }
         it("CalcSerie(Z1) should return 78.27", () => {
             pab.calculatedParam = pab.prms.Z1;
             expect(pab.CalcSerie().vCalc).toBeCloseTo(78.27, 2);
         });
-        it("Calc(Q) should return 0.773", () => {
-            pab.prms.Z1.v = modelCloisons.prms.Z1.v;
-            pab.prms.Q.v = 0;
+        xit("Calc(Q) should return 0.773", () => {
             expect(pab.Calc("Q").vCalc).toBeCloseTo(0.773, 2);
         });
     });
diff --git a/src/pab/cloisons.ts b/src/pab/cloisons.ts
index 9e1f30a0..dc3e4f94 100644
--- a/src/pab/cloisons.ts
+++ b/src/pab/cloisons.ts
@@ -105,8 +105,8 @@ export class Cloisons extends ParallelStructure {
             // Z2 is the variable to find if DH is the calculated param
             this.prms.Z2.v = this.prms.Z1.v - this.prms.DH.v;
         }
-        this.prms.ZRAM.v = this.prms.Z1.v - this.prms.PB.v;
         this.prms.ZRMB.v = this.prms.Z1.v - this.prms.PB.v - this.prms.DH.v;
+        this.prms.ZRAM.v = this.prms.ZRMB.v + this.prms.DH.v / 2;
         for (const structure of this.structures) {
             const prms = structure.prms;
             if (prms.h1.visible) {
diff --git a/src/pab/cloisons_params.ts b/src/pab/cloisons_params.ts
index 38ff2534..c27d8ce8 100644
--- a/src/pab/cloisons_params.ts
+++ b/src/pab/cloisons_params.ts
@@ -24,6 +24,9 @@ export class CloisonsParams extends ParallelStructureParams {
     /** Cote radier amont paroi (m) */
     public ZRAM: ParamDefinition;
 
+    /** Débit d'attrait (m3/s) */
+    public QA: ParamDefinition;
+
     /**
      * Paramètres communs à toutes les équations de structure
      * @param rQ Débit total (m3/s)
@@ -47,9 +50,11 @@ export class CloisonsParams extends ParallelStructureParams {
         this.addParamDefinition(this.ZRMB);
         this.ZRAM = new ParamDefinition(this, "ZRAM", ParamDomainValue.ANY, 0, ParamFamily.ELEVATIONS);
         this.addParamDefinition(this.ZRAM);
-        // hide Z2
+        this.QA = new ParamDefinition(this, "QA", ParamDomainValue.ANY, 0, ParamFamily.FLOWS);
+        this.addParamDefinition(this.QA);
         this.Z2.visible = false;
         this.ZRAM.visible = false;
         this.ZRMB.visible = false;
+        this.QA.visible = false;
     }
 }
diff --git a/src/pab/pab.ts b/src/pab/pab.ts
index 3c693009..c976576c 100644
--- a/src/pab/pab.ts
+++ b/src/pab/pab.ts
@@ -2,9 +2,10 @@ import { CalculatorType } from "../compute-node";
 import { Nub } from "../nub";
 import { ParamCalculability } from "../param/param-definition";
 import { Session } from "../session";
-import { ParallelStructure } from "../structure/parallel_structure";
+import { ParallelStructure, ParallelStructureParams } from "../structure/parallel_structure";
+import { StructureTriangularTruncWeirFree } from "../structure/structure_triangular_trunc_weir";
 import { Result } from "../util/result";
-import { PabCloisons } from "./pab_cloisons";
+import { Cloisons } from "./cloisons";
 import { PabParams } from "./pab_params";
 
 export { PabParams };
@@ -32,16 +33,56 @@ export class Pab extends Nub {
     /**
      * enfants castés au bon type
      */
-    get children(): PabCloisons[] {
-        return this._children as PabCloisons[];
+    get children(): Cloisons[] {
+        return this._children as Cloisons[];
     }
 
-    public Calc(sVarCalc?: string, rInit?: number): Result  {
-        // Update array of PabCloisons with last Models current values
-        /* for (const cl of this.children) {
-            cl.prms.setCurrentValuesFromModel();
-        } */
-        return super.Calc(sVarCalc, rInit);
+    /**
+     * Add Cloisons to the PAB from a cloison model
+     * @param cloisonModel Cloison model parametrised as first upstream basin
+     * @param n Number of walls of the PAB (Number of basin = n - 1)
+     */
+    public addCloisonsFromModel(cloisonModel: Cloisons , n: number) {
+        // Fix some parameters of the upstream cloison (= Wall + basin)
+        const DH: number = cloisonModel.prms.DH.currentValue;
+        const ZRMB: number = this.prms.Z1.currentValue - cloisonModel.prms.PB.currentValue - DH;
+        const ZRAM: number = ZRMB + DH / 2;
+
+        // Generate an image of the object for multiplication
+        const serialisedCloisonModel = cloisonModel.serialise();
+        for (let i = 0; i < n; i++) {
+            const cl: Cloisons = Session.getInstance().unserialiseSingleNub(serialisedCloisonModel).nub as Cloisons;
+            const p = cl.prms;
+            for (const st of cl.structures) {
+                if (st.prms.h1.visible) {
+                    // Set ZDV from h1 for rectangular weirs
+                    st.prms.ZDV.singleValue = this.prms.Z1.currentValue - st.prms.h1.currentValue;
+                    // Set parameter visibility for ZDV and h1 in PAB context
+                    st.prms.ZDV.visible = true;
+                    st.prms.h1.visible = false;
+                }
+            }
+            p.ZRMB.singleValue = ZRMB - i * DH;
+            p.ZRAM.singleValue = ZRAM - i * DH;
+            // Set Structure ZDVs
+            for (const st of cl.structures) {
+                if (st.isZDVcalculable) {
+                    st.prms.ZDV.singleValue = st.prms.ZDV.currentValue - i * DH;
+                    if (st.getParameter("ZT") !== undefined) {
+                        const stTT = st as StructureTriangularTruncWeirFree;
+                        stTT.prms.ZT.singleValue = stTT.prms.ZT.currentValue - i * DH;
+                    }
+                }
+            }
+            if (i !== n - 1) {
+                // Add wall + basin = cloison
+                this.addChild(cl);
+            } else {
+                // The last wall is a ParallelStructure (= Wall only, without basin)
+                this.downWall = new ParallelStructure(new ParallelStructureParams(0, 0, 0));
+                this.downWall.structures = cl.structures;
+            }
+        }
     }
 
     /**
@@ -53,35 +94,35 @@ export class Pab extends Nub {
         const r: Result = new Result(0, this);
 
         // Up to down course : discharge distribution and bottom elevation
-        let Q: number = this.prms.Q.v; // Upstream discharge
-        // upstream basin apron elevation
-        let rZRam: number = this.children[0].prms.Z1.currentValue - this.children[0].Yam;
-
-        for (const cl of this.children) {
-            Q += cl.prms.QA.v;  // Discharge in the current basin
-            rZRam -= cl.prms.DH.currentValue;
+        // tslint:disable-next-line:prefer-for-of
+        for (let i = 0; i < this.children.length; i++) {
+            let wall: ParallelStructure;
+            if (i !== this.children.length - 1) {
+                wall = this.children[i + 1];
+            } else {
+                wall = this.downWall;
+            }
+            // Set discharge for the next wall from the current basin
+            wall.prms.Q.v = this.children[i].prms.Q.v + this.children[i].prms.QA.v;
         }
 
         // Down to up course : water surface calculation
         let Z: number = this.prms.Z2.v;
-        Z = this.calcCloisonZ1(this.downWall, Q, Z);
-        this.downWall.result.extraResults.ZRAM = rZRam;
+        Z = this.calcCloisonZ1(this.downWall, Z);
 
         for (let i = this.children.length - 1; i >= 0; i--) {
 
             // Initialisations for current cloison
-            const cl: PabCloisons = this.children[i];
-            rZRam += cl.prms.DH.currentValue;
-            cl.updateZDV(rZRam);
+            const cl: Cloisons = this.children[i];
 
             // Calculation of upstream water elevation
-            Z = this.calcCloisonZ1(cl, Q, Z);
+            Z = this.calcCloisonZ1(cl, Z);
             if (this.debug) {
                 console.log("Bassin n°" + i);
                 let s: string = "";
                 for (const p of cl.prms) {
                     // tslint:disable-next-line:no-console
-                    s += p.symbol + " = " + p.v + "; " ;
+                    s += p.symbol + " = " + p.v + "; ";
                 }
                 console.log(s);
 
@@ -90,12 +131,11 @@ export class Pab extends Nub {
                     s = "";
                     for (const p of c.prms) {
                         // tslint:disable-next-line:no-console
-                        s += p.symbol + " = " + p.v;
+                        s += p.symbol + " = " + p.v + "; ";
                     }
                     console.log(s);
                 }
             }
-            Q -= cl.prms.QA.v;
         }
 
         r.vCalc = Z;
@@ -127,9 +167,9 @@ export class Pab extends Nub {
                     const childUid = c.uid;
                     const targetCloisonsUid = c.props.modeleCloisons;
                     // find child PabCloisons to relink
-                    const pabCloisons = (this.getChild(childUid) as PabCloisons);
-                    if (pabCloisons) {
-                        pabCloisons.setModel(targetCloisonsUid);
+                    const cloisons = (this.getChild(childUid) as Cloisons);
+                    if (cloisons) {
+                        // cloisons.setModel(targetCloisonsUid);
                     } // else cannot find target
                 }
             }
@@ -149,9 +189,8 @@ export class Pab extends Nub {
         this.prms.Q.calculability = ParamCalculability.DICHO;
     }
 
-    private calcCloisonZ1(cl: ParallelStructure, Q: number, Z: number): number {
+    private calcCloisonZ1(cl: ParallelStructure, Z: number): number {
         // Initialisations for current cloison
-        cl.prms.Q.v = Q;
         cl.prms.Z2.v = Z;
 
         // Calculation of upstream water elevation
@@ -161,6 +200,6 @@ export class Pab extends Nub {
         cl.result.extraResults.YMOY = cl.prms.Z2.v - cl.result.extraResults.ZRMB;
 
         // Update elevation and discharge for next basin
-        return cl.prms.Z1.v;
+        return cl.result.vCalc;
     }
 }
diff --git a/src/session.ts b/src/session.ts
index 65bf09ea..ff547732 100644
--- a/src/session.ts
+++ b/src/session.ts
@@ -37,7 +37,7 @@ import { LoiDebit } from "./structure/structure_props";
 
 export class Session {
 
-    public static getInstance() {
+    public static getInstance(): Session {
         if (Session._instance === undefined) {
             Session._instance = new Session();
         }
diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts
index 0b13bd51..993685de 100644
--- a/src/structure/parallel_structure.ts
+++ b/src/structure/parallel_structure.ts
@@ -27,6 +27,10 @@ export class ParallelStructure extends Nub {
         return this._children as Structure[];
     }
 
+    public set structures(structures: Structure[]) {
+        this._children = structures;
+    }
+
     /**
      * paramètres castés au bon type
      */
-- 
GitLab