From 996705ee3330a31648dbee9fcb92dd3bfa17b78c Mon Sep 17 00:00:00 2001 From: David Dorchies <david.dorchies@irstea.fr> Date: Fri, 6 Sep 2019 17:05:20 +0200 Subject: [PATCH] Fix #137 Miscalculation in MacroRugoCompound --- spec/macrorugo/macrorugo_compound.spec.ts | 76 ++++++++++++++++++++--- spec/test_func.ts | 23 +++++++ src/macrorugo/macrorugo_compound.ts | 2 +- src/param/param-definition.ts | 6 +- src/structure/parallel_structure.ts | 24 +++---- 5 files changed, 103 insertions(+), 28 deletions(-) diff --git a/spec/macrorugo/macrorugo_compound.spec.ts b/spec/macrorugo/macrorugo_compound.spec.ts index f2a1ecf4..09653377 100644 --- a/spec/macrorugo/macrorugo_compound.spec.ts +++ b/spec/macrorugo/macrorugo_compound.spec.ts @@ -1,10 +1,29 @@ import { CalculatorType } from "../../src/compute-node"; -import { MacroRugo } from "../../src/macrorugo/macrorugo"; +import { MacroRugo, MacrorugoParams } from "../../src/macrorugo/macrorugo"; import { MacrorugoCompound } from "../../src/macrorugo/macrorugo_compound"; import { Props } from "../../src/props"; import { Session } from "../../src/session"; +import { compareTwoResults } from "../test_func"; let BR: number; +let mrc2: MacrorugoCompound; + +/** + * Return default instance of MacroRugo as reference for one apron + * @param i Offset of ZF1 (- 0.2 * i) and B (+ i) + */ +function getMacroRugoRef(i: number = 0): MacroRugo { + const mr = Session.getInstance().createNub( + new Props({ calcType: CalculatorType.MacroRugo }) + ) as MacroRugo; + mr.prms.ZF1.singleValue -= 0.21 * i; + mr.prms.Y.singleValue += 0.21 * i; + mr.prms.B.singleValue += i; + mr.prms.L.singleValue = 3 / mr.prms.If.currentValue; + mr.prms.Q.setCalculated(); + mr.CalcSerie(); + return mr; +} describe("MacroRugoCompound", () => { describe("Default 1 apron", () => { @@ -13,9 +32,20 @@ describe("MacroRugoCompound", () => { new Props({ calcType: CalculatorType.MacroRugoCompound }) ) as MacrorugoCompound; mrc.addDefaultChild(); - const mr = Session.getInstance().createNub(new Props({ calcType: CalculatorType.MacroRugo })) as MacroRugo; - mr.prms.Q.setCalculated(); - expect(mrc.CalcSerie().vCalc).toBeCloseTo(mr.CalcSerie().vCalc, 3); + const mr = getMacroRugoRef(); + expect(mrc.CalcSerie().vCalc).toBeCloseTo(mr.result.vCalc, 3); + }); + it("should return same result as Macrorugo", () => { + const mrc = Session.getInstance().createNub( + new Props({ calcType: CalculatorType.MacroRugoCompound }) + ) as MacrorugoCompound; + mrc.addDefaultChild(); + mrc.children[0].prms.L.singleValue = 0.5; + mrc.CalcSerie(); + const mr = getMacroRugoRef(); + mr.prms.L.singleValue = mrc.children[0].prms.L.v; + mr.CalcSerie(); + compareTwoResults(mrc.children[0].result, mr.result, 3); }); }); describe("Default inclined but flat apron", () => { @@ -32,11 +62,9 @@ describe("MacroRugoCompound", () => { ) as MacrorugoCompound; mrc.properties.setPropValue("inclinedApron", true); mrc.prms.BR.singleValue = BR; - const mr = Session.getInstance() - .createNub(new Props({ calcType: CalculatorType.MacroRugo })) as MacroRugo; - mr.prms.Q.setCalculated(); + const mr = getMacroRugoRef(); expect(mrc.CalcSerie().vCalc) - .toBeCloseTo(mr.CalcSerie().vCalc * mrc.prms.BR.currentValue / mr.prms.B.currentValue, 3); + .toBeCloseTo(mr.result.vCalc * mrc.prms.BR.currentValue / mr.prms.B.currentValue, 3); const ax = mrc.prms.PBD.v / Math.sqrt(mrc.prms.C.v); let B: number = 0; for (const child of mrc.children) { @@ -49,5 +77,35 @@ describe("MacroRugoCompound", () => { }); } }); - + describe("Multiple apron", () => { + beforeAll(() => { + mrc2 = Session.getInstance().createNub( + new Props({ calcType: CalculatorType.MacroRugoCompound }) + ) as MacrorugoCompound; + for (let i = 0; i < 3; i++) { + mrc2.addChild( + new MacroRugo( + new MacrorugoParams(0, 100, 100, 0.5, 1, 10, 1, 1, 1, 10, 0.5) + ) + ); + mrc2.children[i].prms.ZF1.singleValue = 12.5 - 0.21 * i; + mrc2.children[i].prms.B.singleValue = 1 + i; + } + mrc2.CalcSerie(); + }); + for (let i = 0; i < 3; i++) { + it(`Apron #${i} should return same parameters as Macrorugo`, () => { + const mr = getMacroRugoRef(i); + for (const p of mrc2.children[i].parameterIterator) { + if (p.symbol !== "Q") { + expect(p.v).toBeCloseTo(mr.getParameter(p.symbol).v, 3); + } + } + }); + it(`Apron #${i} should return same result as Macrorugo`, () => { + const mr = getMacroRugoRef(i); + compareTwoResults(mrc2.children[i].result, mr.result, 3); + }); + } + }); }); diff --git a/spec/test_func.ts b/spec/test_func.ts index 0c321f78..014b58a7 100644 --- a/spec/test_func.ts +++ b/spec/test_func.ts @@ -210,6 +210,29 @@ export function checkResult(result: Result, valRef: number, prec?: number) { } } +/** + * Compare the content of two results objects + * @param rTest Result to test + * @param rRef Result used as reference + * @param prec numbers of digits of the needed precision + */ +export function compareTwoResults(rTest: Result, rRef: Result, prec: number = Math.max(0, precDigits - 1)) { + expect(rTest.ok).toEqual(rRef.ok, `ok should be $rRef.ok`); + if (!rTest.ok) { return; } + expect(rTest.resultElements.length).toEqual(rRef.resultElements.length, `resultElements.length should be $rRef.ok`); + if (rTest.resultElements.length !== rRef.resultElements.length) { return; } + for (let i = 0; i < rRef.resultElements.length; i++) { + for (const k of Object.keys(rRef.resultElements[i].values)) { + expect(rTest.resultElements[i].values[k]) + .toBeCloseTo( + rRef.resultElements[i].values[k], + prec, + k + ); + } + } +} + export function checkResultConsistency(nub: Nub, r?: Result) { if (r === undefined) { r = nub.result; diff --git a/src/macrorugo/macrorugo_compound.ts b/src/macrorugo/macrorugo_compound.ts index 35dd6038..b91bab5e 100644 --- a/src/macrorugo/macrorugo_compound.ts +++ b/src/macrorugo/macrorugo_compound.ts @@ -124,7 +124,7 @@ export class MacrorugoCompound extends MacroRugo implements Observer { for (const child of this.children) { // Copy common parameters with MacrorugoCompound for (const v of ["Ks", "If", "C", "PBD", "PBH", "Cd0"]) { - child.getParameter(v).singleValue = this.getParameter(v).v; + child.getParameter(v).v = this.getParameter(v).v; } // Calculate Length and depth from other parameters child.prms.L.v = this.prms.DH.v / this.prms.If.v; diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index c5adb6fb..83687c88 100644 --- a/src/param/param-definition.ts +++ b/src/param/param-definition.ts @@ -1100,9 +1100,9 @@ export class ParamDefinition implements INamedIterableValues, IObservable { */ get V(): number { if (this.valueMode === ParamValueMode.CALCUL) { - if (this.originNub.result !== undefined) { - if (this.originNub.result.resultElement.ok) { - return this.originNub.result.vCalc; + if (this.parentNub.result !== undefined) { + if (this.parentNub.result.resultElement.ok) { + return this.parentNub.result.vCalc; } } } diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index f42fee6c..d9c7483e 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -129,21 +129,13 @@ export class ParallelStructure extends Nub { } // Pour les caractéristiques des ouvrages const structureIndex = this.getIndexForChild(sVarCalc.uid); - this.currentResult = this.CalcStructPrm(structureIndex, sVarCalc.symbol, rInit); - if (this.result.ok) { - this._children[structureIndex].getParameter(sVarCalc.symbol).v = this.result.resultElement.vCalc; - } - } - if (this.result.ok) { - // Recalcul du débit total pour récupérer les résultats des ouvrages dans les résultats complémentaires - const resQtot: Result = this.CalcQ(); - for (const extraResKey in resQtot.extraResults) { - if (resQtot.resultElement.values.hasOwnProperty(extraResKey)) { - this.result.resultElement.addExtraResult( - extraResKey, resQtot.extraResults.resultElement.values[extraResKey] - ); + const r = this.CalcStructPrm(structureIndex, sVarCalc.symbol, rInit); + if (r.ok) { + this.result.symbol = r.symbol; + this.result.vCalc = r.vCalc; + } else { + this.currentResult = r; } - } } return this.result; @@ -206,7 +198,9 @@ export class ParallelStructure extends Nub { this.structures[index].prms.Q.v = this.prms.Q.v - this.CalcQ(index).vCalc; // Calcul du paramètre de la structure en calcul - return this.structures[index].Calc(symbol, rInit); + const r: Result = this.structures[index].Calc(symbol, rInit); + this.structures[index].result.values.Q = this.structures[index].prms.Q.v; + return r; } } -- GitLab