diff --git a/spec/fuzzing.spec.ts b/spec/fuzzing.spec.ts index 060e09dcab6f3ea9098423aa5876a141276f7c79..3af87a89694738a80bdb1d376e5a32e31d9c2b17 100644 --- a/spec/fuzzing.spec.ts +++ b/spec/fuzzing.spec.ts @@ -1,4 +1,5 @@ import { CalculatorType } from "../src/compute-node"; +import { MacrorugoCompound } from "../src/macrorugo/macrorugo_compound"; import { Nub } from "../src/nub"; import { CloisonAval } from "../src/pab/cloison_aval"; import { Pab } from "../src/pab/pab"; @@ -110,6 +111,10 @@ function setPab(pab: Pab, nClMax = 30, nStMax = 3) { addRandomStructures(pab.downWall, nStMax); } +function setMacrorugoCompound(n: MacrorugoCompound) { + n.properties.setPropValue("inclinedApron", Math.random() > 0.5); +} + function CreateTestNub(iCalType: number): Nub { const n = Session.getInstance().createNub( new Props({ calcType: iCalType }) @@ -129,6 +134,9 @@ function CreateTestNub(iCalType: number): Nub { if (iCalType === CalculatorType.Pab) { setPab(n as Pab, fuzzyCfg.Pab.poolMax, fuzzyCfg.Pab.structureMax); } + if (iCalType === CalculatorType.MacroRugoCompound) { + setMacrorugoCompound(n as MacrorugoCompound); + } for (const p of n.parameterIterator) { if (p.visible) { randomizeParameter(p); @@ -155,6 +163,7 @@ describe("Fuzz testing", () => { } }); for (const iCalType of calTypes) { + // if ([CalculatorType.MacroRugoCompound].includes(iCalType)) { if (!nubsNotTested.includes(iCalType)) { describe(CalculatorType[iCalType], () => { for (let i = 0; i < fuzzyCfg.nTests; i++) { diff --git a/spec/macrorugo/macrorugo_compound.spec.ts b/spec/macrorugo/macrorugo_compound.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..096533774ad01d008b189a9341f837750755d316 --- /dev/null +++ b/spec/macrorugo/macrorugo_compound.spec.ts @@ -0,0 +1,111 @@ +import { CalculatorType } from "../../src/compute-node"; +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", () => { + it("should return same result as Macrorugo", () => { + const mrc = Session.getInstance().createNub( + new Props({ calcType: CalculatorType.MacroRugoCompound }) + ) as MacrorugoCompound; + mrc.addDefaultChild(); + 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", () => { + beforeAll(() => { + BR = 0; + }); + beforeEach(() => { + BR += 1; + }); + for (let i = 1; i < 10; i += 1) { + it(`B = ${i} should return same result as Macrorugo`, () => { + const mrc = Session.getInstance().createNub( + new Props({ calcType: CalculatorType.MacroRugoCompound }) + ) as MacrorugoCompound; + mrc.properties.setPropValue("inclinedApron", true); + mrc.prms.BR.singleValue = BR; + const mr = getMacroRugoRef(); + expect(mrc.CalcSerie().vCalc) + .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) { + expect(child.result.values.xCenter) + .toBeCloseTo(B + child.prms.B.v / 2); + B += child.prms.B.v; + expect(child.prms.B.v).toBeGreaterThanOrEqual(ax / 4); + } + expect(B).toBeCloseTo(mrc.prms.BR.currentValue, 6); + }); + } + }); + 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 0c321f7861a8103a7233d5b99eb09ca811b16b45..014b58a701db2685808c7b51ddfe6c3fda3e7e74 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/base.ts b/src/base.ts index 4feba95707ac3a45d08a178cc56a3cc33cb4ae69..16915a29e79559433329c4c2529d784aec3d396b 100644 --- a/src/base.ts +++ b/src/base.ts @@ -131,3 +131,7 @@ export function formattedValue(value: number, nDigits: number) { return value.toFixed(nDigits); } } + +export function capitalize(s: string): string { + return s.charAt(0).toUpperCase() + s.slice(1); +} diff --git a/src/compute-node.ts b/src/compute-node.ts index a7b0795f2f122ff2da6d284f49caea41920d8006..9619bdda8ec8f66eeea9aec10639c1f4a98689d1 100644 --- a/src/compute-node.ts +++ b/src/compute-node.ts @@ -23,7 +23,8 @@ export enum CalculatorType { PabNombre, Section, Pab, // Passe à bassins; - CloisonAval + CloisonAval, + MacroRugoCompound // Passe à enrochement composée } /** diff --git a/src/index.ts b/src/index.ts index 8fc065d4efe1f8a4626265a4740e15509429bfe5..243c278ee7ca6342658d4a54aa8d057b5c7af0bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,3 +42,5 @@ export * from "./pab/cloison_aval"; export * from "./lechaptcalmon"; export * from "./lc-material"; export * from "./structure/dever"; +export * from "./macrorugo/macrorugo"; +export * from "./macrorugo/macrorugo_compound"; diff --git a/src/macrorugo/macrorugo.ts b/src/macrorugo/macrorugo.ts index 2f1bb744be7f26d1ce36ebd779c7489a7ac91133..1adc516b0486cc9972da5b3cbab4c0ee7f64d94f 100644 --- a/src/macrorugo/macrorugo.ts +++ b/src/macrorugo/macrorugo.ts @@ -66,6 +66,8 @@ export class MacroRugo extends Nub { this.getParameter(sVarCalc).valueMode = ParamValueMode.CALCUL; const r: Result = super.Calc(sVarCalc, rInit); + this.getParameter(sVarCalc).valueMode = originalValueMode; + // Ajout des résultats complémentaires // Cote de fond aval r.resultElement.values.ZF2 = this.prms.ZF1.v - this.prms.If.v * this.prms.L.v; @@ -115,9 +117,6 @@ export class MacroRugo extends Nub { Math.pow(this.prms.If.v, cV[2]) * Math.sqrt(MacroRugo.g * this.prms.PBD.v); } - // mode d'origine du paramètre; voir le haut de la fonction - this.getParameter(sVarCalc).valueMode = originalValueMode; - return r; } @@ -125,8 +124,13 @@ export class MacroRugo extends Nub { this.Q = this.prms.Q.v; const q0 = Math.sqrt(2 * MacroRugo.g * this.prms.If.v * this.prms.PBD.v * ( 1 - (this.sigma * this.prms.C.v)) / (this.prms.Cd0.v * this.prms.C.v)) * this.prms.Y.v * this.prms.B.v; - const dicho = new Dichotomie(this, "Q", false, this.resolveQ); - const r: Result = dicho.Dichotomie(0, this.prms.Pr.v, q0); + let r: Result; + if (q0 > 0) { + const dicho = new Dichotomie(this, "Q", false, this.resolveQ); + r = dicho.Dichotomie(0, this.prms.Pr.v, q0); + } else { + r = new Result(0); + } this.prms.Q.v = this.Q; return r; diff --git a/src/macrorugo/macrorugo_compound.ts b/src/macrorugo/macrorugo_compound.ts new file mode 100644 index 0000000000000000000000000000000000000000..b91bab5eb4e2bab05441565ca4d674b20912cbaf --- /dev/null +++ b/src/macrorugo/macrorugo_compound.ts @@ -0,0 +1,193 @@ +import { round } from "../base"; +import { CalculatorType } from "../compute-node"; +import { ParamCalculability } from "../param/param-definition"; +import { Props } from "../props"; +import { Session } from "../session"; +import { Observer } from "../util/observer"; +import { Result } from "../util/result"; +import { MacroRugo } from "./macrorugo"; +import { MacrorugoCompoundParams } from "./macrorugo_compound_params"; + +export class MacrorugoCompound extends MacroRugo implements Observer { + + /** enfants castés au bon type */ + get children(): MacroRugo[] { + return this._children as MacroRugo[]; + } + + /** parameters cast to the right type */ + get prms(): MacrorugoCompoundParams { + return this._prms as MacrorugoCompoundParams; + } + + constructor(prms: MacrorugoCompoundParams, dbg: boolean = false) { + super(prms, dbg); + this._calcType = CalculatorType.MacroRugoCompound; + this._props.addObserver(this); + this.properties.setPropValue("inclinedApron", false); + this._childrenType = "MacroRugo"; + } + + public CalcSerie(rInit?: number, sDonnee?: any): Result { + if (this.properties.getPropValue("inclinedApron")) { + // important to regenerate it here, at every iteration of CalcSerie() + this.generateInclinedFishway(); + } + return super.CalcSerie(rInit, sDonnee); + } + + /** + * Calcul du débit total, de la cote amont ou aval ou d'un paramètre d'une structure + * @param sVarCalc Nom du paramètre à calculer + * @param rInit Valeur initiale + */ + public Calc(sVarCalc: string, rInit?: number): Result { + if (sVarCalc !== "Q") { + throw new Error("MacrorugoCompound.Calc() : invalid parameter " + sVarCalc); + } + this.copyPrmsToChildren(); + this.currentResult = this.Equation(sVarCalc); + return this._result; + } + + public Equation(sVarCalc: string): Result { + let QT: number = 0; + let B: number = 0; + for (const child of this.children) { + child.Calc(sVarCalc); + QT += child.result.vCalc; + child.result.values.xCenter = B + child.prms.B.v / 2; + B += child.prms.B.v; + } + return new Result(QT); + } + + public addChild(child: MacroRugo, after?: number) { + super.addChild(child, after); + for (const p of child.parameterIterator) { + p.visible = false; + } + child.prms.ZF1.visible = true; + child.prms.B.visible = true; + child.prms.B.calculability = ParamCalculability.FREE; + } + + public addDefaultChild(after?: number) { + this.addChild( + Session.getInstance().createNub(new Props({ calcType: CalculatorType.MacroRugo })) as MacroRugo, + after + ); + } + + // interface Observer + + public update(sender: any, data: any) { + if (data.action === "propertyChange" && data.name === "inclinedApron") { + if (data.value) { // switch to inclined apron mode + this.prms.ZRL.visible = true; + this.prms.ZRR.visible = true; + this.prms.BR.visible = true; + this.prms.PBD.calculability = ParamCalculability.FIXED; + this.prms.C.calculability = ParamCalculability.FIXED; + } else { // switch to multiple aprons mode + this.prms.ZRL.visible = false; + this.prms.ZRR.visible = false; + this.prms.BR.visible = false; + this.prms.PBD.calculability = ParamCalculability.FREE; + this.prms.C.calculability = ParamCalculability.FREE; + } + } + } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + this.prms.ZF1.calculability = ParamCalculability.FREE; + this.prms.L.calculability = ParamCalculability.FREE; + this.prms.Ks.calculability = ParamCalculability.FREE; + this.prms.B.calculability = ParamCalculability.FREE; + this.prms.If.calculability = ParamCalculability.FREE; + this.prms.Q.calculability = ParamCalculability.EQUATION; + this.prms.Y.calculability = ParamCalculability.FREE; + this.prms.C.calculability = ParamCalculability.FREE; + this.prms.PBD.calculability = ParamCalculability.FREE; + this.prms.PBH.calculability = ParamCalculability.FREE; + this.prms.Cd0.calculability = ParamCalculability.FREE; + + this.prms.ZRL.calculability = ParamCalculability.FIXED; + this.prms.ZRR.calculability = ParamCalculability.FIXED; + this.prms.BR.calculability = ParamCalculability.FIXED; + } + + private copyPrmsToChildren() { + for (const child of this.children) { + // Copy common parameters with MacrorugoCompound + for (const v of ["Ks", "If", "C", "PBD", "PBH", "Cd0"]) { + 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; + child.prms.Y.v = Math.max(this.prms.Z1.v - child.prms.ZF1.v, 0); + } + } + + /** + * Discrétisation d'un radier incliné en radiers horizontaux + * Le pas de discrétisationest fixée à D / C^0.5. + * Les cellules discrétisées sont centrées sur la passe, on crée + * les cellules manquantes aux extrémités si le reste > ax / 2 + * sinon les cellules aux extrémités sont étendues jusqu'aux bords. + * La cote de radier de chaque cellule est calculée au milieu de celles-ci. + */ + private generateInclinedFishway() { + // Calcul de la position des cellules + // Taille d'une cellule de calcul + const ax: number = this.prms.PBD.singleValue / Math.sqrt(this.prms.C.singleValue); + // Nombre entier de cellules et reste + let nCells: number = Math.floor(this.prms.BR.singleValue / ax); + const xRest: number = this.prms.BR.singleValue % ax; + const xCenters: number[] = []; + let lastBorder: number = 0; + // Position du centre de la première cellule + if (xRest > ax / 2) { + // Ajout d'une cellule à gauche + xCenters.push(xRest / 4); + nCells++; + } else { + if (nCells < 2) { + xCenters.push(this.prms.BR.singleValue / 2); + } else { + xCenters.push((ax + xRest / 2) / 2); + } + } + if (nCells > 1 || xRest > ax / 2) { + lastBorder = xCenters[0] * 2; + // Ajout des cellules centrales décalées de ax + for (let i = 1; i < nCells; i++) { + xCenters.push(lastBorder + ax / 2); + lastBorder += ax; + } + if (xRest > ax / 2) { + // Ajout de la cellule supplémentaire à droite + xCenters.push(this.prms.BR.singleValue - xRest / 4); + } else { + xCenters[xCenters.length - 1] = this.prms.BR.singleValue - (ax + xRest / 2) / 2; + } + } + // Génération des radiers + // Suppression des radiers existants + this.deleteAllChildren(); + // Ajout des radiers et calcul de leur cote amont et de leur largeur + lastBorder = 0; + for (const xCenter of xCenters) { + this.addDefaultChild(); + this.children[this.children.length - 1].prms.ZF1.singleValue = round( + this.prms.ZRL.singleValue + xCenter / this.prms.BR.singleValue + * (this.prms.ZRR.singleValue - this.prms.ZRL.singleValue) + , 3); + this.children[this.children.length - 1].prms.B.singleValue = round((xCenter - lastBorder) * 2, 3); + lastBorder += this.children[this.children.length - 1].prms.B.singleValue; + } + } +} diff --git a/src/macrorugo/macrorugo_compound_params.ts b/src/macrorugo/macrorugo_compound_params.ts new file mode 100644 index 0000000000000000000000000000000000000000..93e55e4917b56b3ad922b15802a22e7a47902f47 --- /dev/null +++ b/src/macrorugo/macrorugo_compound_params.ts @@ -0,0 +1,96 @@ +import { ParamDefinition, ParamFamily } from "../param/param-definition"; +import { ParamDomain, ParamDomainValue } from "../param/param-domain"; +import { MacrorugoParams } from "./macrorugo"; + +export class MacrorugoCompoundParams extends MacrorugoParams { + + /** Upstream water elevation (m) */ + private _Z1: ParamDefinition; + + /** Water fall (m) */ + private _DH: ParamDefinition; + + /** Inclined apron: Left bank apron elevation (m) */ + private _ZRL: ParamDefinition; + + /** Inclined apron: Right bank apron elevation (m) */ + private _ZRR: ParamDefinition; + + /** Inclined apron: Apron total width (m) */ + private _BR: ParamDefinition; + + /** + * + * @param rZ1 Cote de l'eau amont (m) + * @param rZRL Cote de radier gauche (m) (Radier incliné seulement) + * @param rZRR Cote de radier droit (m) (Radier incliné seulement) + * @param rB Largeur (m) (Radier incliné seulement) + * @param rDH Chute (m) + * @param rIf Pente (m/m) + * @param rY Tirant d'eau (m) + * @param rRF Rugosité de fond (m) + * @param rCB Concentration de blocs (m) + * @param rPBD Paramètre de bloc : Diamètre (m) + * @param rPBH Paramètre de bloc : Hauteur (m) + * @param rCd0 Paramètre de bloc : Forme (1 pour rond, 2 pour carré) + */ + constructor( + rZ1: number, + rZRL: number, + rZRR: number, + rB: number, + rDH: number, + rIf: number, + rRF: number, + rCB: number, + rPBD: number, + rPBH: number, + rCd0: number + ) { + super((rZRL + rZRR) / 2, 1, rDH / rIf, rIf, 1, 1, rRF, rCB, rPBD, rPBH, rCd0); + + this._Z1 = new ParamDefinition(this, "Z1", ParamDomainValue.ANY, "m", rZ1, ParamFamily.ELEVATIONS); + this.addParamDefinition(this._Z1); + + this._ZRL = new ParamDefinition(this, "ZRL", ParamDomainValue.ANY, "m", rZRL, ParamFamily.ELEVATIONS); + this.addParamDefinition(this.ZRL); + + this._ZRR = new ParamDefinition(this, "ZRR", ParamDomainValue.ANY, "m", rZRR, ParamFamily.ELEVATIONS); + this.addParamDefinition(this._ZRR); + + this._BR = new ParamDefinition(this, "BR", + new ParamDomain(ParamDomainValue.INTERVAL, 0, 100), "m", rB, ParamFamily.WIDTHS); + this.addParamDefinition(this._BR); + + this._DH = new ParamDefinition(this, "DH", + new ParamDomain(ParamDomainValue.INTERVAL, 0, 100), "m", rDH, ParamFamily.ELEVATIONS); + this.addParamDefinition(this._DH); + + // Width, water depth, and Bottom elevation are defined in Macrorugo children + this.B.visible = false; + this.ZF1.visible = false; + this.Y.visible = false; + this.Q.visible = false; + + } + + public get Z1(): ParamDefinition { + return this._Z1; + } + + public get ZRL(): ParamDefinition { + return this._ZRL; + } + + public get ZRR(): ParamDefinition { + return this._ZRR; + } + + public get BR(): ParamDefinition { + return this._BR; + } + + public get DH(): ParamDefinition { + return this._DH; + } +} diff --git a/src/macrorugo/macrorugo_params.ts b/src/macrorugo/macrorugo_params.ts index 9c88e88b6eee8492e205adb46326569551e258dc..123d120c1c4d3d384280baac1430ce54e31a3513 100644 --- a/src/macrorugo/macrorugo_params.ts +++ b/src/macrorugo/macrorugo_params.ts @@ -1,5 +1,5 @@ import { ParamDefinition, ParamFamily } from "../param/param-definition"; -import { ParamDomainValue } from "../param/param-domain"; +import { ParamDomain, ParamDomainValue } from "../param/param-domain"; import { ParamsEquation } from "../param/params-equation"; export class MacrorugoParams extends ParamsEquation { @@ -56,7 +56,7 @@ export class MacrorugoParams extends ParamsEquation { rY: number, rRF: number, rCB: number, rPBD: number, rPBH: number, rCd0: number) { super(); - this._ZF1 = new ParamDefinition(this, "ZF1", ParamDomainValue.POS, "m", rZF1, ParamFamily.ELEVATIONS); + this._ZF1 = new ParamDefinition(this, "ZF1", ParamDomainValue.ANY, "m", rZF1, ParamFamily.ELEVATIONS); this.addParamDefinition(this._ZF1); this._L = new ParamDefinition(this, "L", ParamDomainValue.POS, "m", rL, ParamFamily.LENGTHS); @@ -65,22 +65,23 @@ export class MacrorugoParams extends ParamsEquation { this._B = new ParamDefinition(this, "B", ParamDomainValue.POS, "m", rB, ParamFamily.WIDTHS); this.addParamDefinition(this._B); - this._If = new ParamDefinition(this, "If", ParamDomainValue.POS, "m/m", rIf, ParamFamily.SLOPES); + this._If = new ParamDefinition(this, "If", + new ParamDomain(ParamDomainValue.INTERVAL, 0, 0.5), "m/m", rIf, ParamFamily.SLOPES); this.addParamDefinition(this._If); this._Q = new ParamDefinition(this, "Q", ParamDomainValue.POS, "m³/s", rQ, ParamFamily.FLOWS); this.addParamDefinition(this._Q); - this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS, "m", rY, ParamFamily.HEIGHTS); + this._Y = new ParamDefinition(this, "Y", ParamDomainValue.POS_NULL, "m", rY, ParamFamily.HEIGHTS); this.addParamDefinition(this._Y); - this._Ks = new ParamDefinition(this, "Ks", ParamDomainValue.POS_NULL, "m", rRF); + this._Ks = new ParamDefinition(this, "Ks", new ParamDomain(ParamDomainValue.INTERVAL, 0, 1), "m", rRF); this.addParamDefinition(this._Ks); - this._C = new ParamDefinition(this, "C", ParamDomainValue.POS, "m", rCB); + this._C = new ParamDefinition(this, "C", new ParamDomain(ParamDomainValue.INTERVAL, 0, 1), "-", rCB); this.addParamDefinition(this._C); - this._PBD = new ParamDefinition(this, "PBD", ParamDomainValue.POS, "m", rPBD); + this._PBD = new ParamDefinition(this, "PBD", new ParamDomain(ParamDomainValue.INTERVAL, 0, 2), "m", rPBD); this.addParamDefinition(this._PBD); this._PBH = new ParamDefinition(this, "PBH", ParamDomainValue.POS, "m", rPBH, ParamFamily.HEIGHTS); diff --git a/src/nub.ts b/src/nub.ts index f82d1baa7d1c7a1029f53827b327e89909f596a9..c4cc38959b2f202b98c4d0ca764cb1f5d4192ac4 100644 --- a/src/nub.ts +++ b/src/nub.ts @@ -105,7 +105,6 @@ export abstract class Nub extends ComputeNode implements IObservable { for (const p of this.parameterIterator) { if ( p.symbol !== "Pr" && - p.visible && [ParamCalculability.DICHO, ParamCalculability.EQUATION].includes(p.calculability) ) { calcPrms.push(p); diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts index c5adb6fb9b49823b6a6c630681317650255d1c1d..83687c884714c5fb2edf68ecede54532a1483ec2 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/props.ts b/src/props.ts index e058eebd3c77717462fe9dca34a22e52d85f141d..99f40d377583c8baea39f650cd095498d5e83602 100644 --- a/src/props.ts +++ b/src/props.ts @@ -71,6 +71,7 @@ export class Props implements IObservable { */ public clone(): Props { const res = new Props(); + // copy values for (const k in this._props) { if (this._props.hasOwnProperty(k)) { res._props[k] = this._props[k]; diff --git a/src/session.ts b/src/session.ts index 53adab86b305db40349bfe034571dacf77b0fe2c..e9c64acdc7192d6a0a3ea73101ab9d4d98126de9 100644 --- a/src/session.ts +++ b/src/session.ts @@ -10,6 +10,8 @@ import { config } from "./config"; import { ConduiteDistrib, ConduiteDistribParams } from "./cond_distri"; import { LechaptCalmon, LechaptCalmonParams } from "./lechaptcalmon"; import { MacroRugo, MacrorugoParams } from "./macrorugo/macrorugo"; +import { MacrorugoCompound } from "./macrorugo/macrorugo_compound"; +import { MacrorugoCompoundParams } from "./macrorugo/macrorugo_compound_params"; import { PabChute, PabChuteParams } from "./pab/pab_chute"; import { PabDimension, PabDimensionParams } from "./pab/pab_dimension"; import { PabNombre, PabNombreParams } from "./pab/pab_nombre"; @@ -38,7 +40,6 @@ import { Dever, DeverParams } from "./structure/dever"; import { CreateStructure } from "./structure/factory_structure"; import { ParallelStructure, ParallelStructureParams } from "./structure/parallel_structure"; import { LoiDebit, StructureType } from "./structure/structure_props"; - export class Session { public static getInstance(): Session { @@ -76,6 +77,7 @@ export class Session { res[k] = LCMaterial[res[k]]; break; // "varCalc" is not an enum + // "inclinedApron" is not an enum } } } @@ -255,162 +257,147 @@ export class Session { let prms: any; switch (calcType) { - case CalculatorType.ConduiteDistributrice: { - prms = new ConduiteDistribParams( - 3, // débit Q - 1.2, // diamètre D - 0.6, // perte de charge J - 100, // Longueur de la conduite Lg - 1e-6, // Viscosité dynamique Nu - ); - nub = new ConduiteDistrib(prms, dbg); - break; - } + case CalculatorType.ConduiteDistributrice: + prms = new ConduiteDistribParams( + 3, // débit Q + 1.2, // diamètre D + 0.6, // perte de charge J + 100, // Longueur de la conduite Lg + 1e-6, // Viscosité dynamique Nu + ); + nub = new ConduiteDistrib(prms, dbg); + break; - case CalculatorType.LechaptCalmon: { - prms = new LechaptCalmonParams( - 3, // débit - 1.2, // diamètre - 0.6, /// perte de charge - 100, // longueur du toyo - 1.863, // paramètre L du matériau - 2, // paramètre M du matériau - 5.33// paramètre N du matériau - ); - nub = new LechaptCalmon(prms, dbg); - break; - } + case CalculatorType.LechaptCalmon: + prms = new LechaptCalmonParams( + 3, // débit + 1.2, // diamètre + 0.6, /// perte de charge + 100, // longueur du toyo + 1.863, // paramètre L du matériau + 2, // paramètre M du matériau + 5.33// paramètre N du matériau + ); + nub = new LechaptCalmon(prms, dbg); + break; - case CalculatorType.SectionParametree: { - nub = new SectionParametree(undefined, dbg); - break; - } + case CalculatorType.SectionParametree: + nub = new SectionParametree(undefined, dbg); + break; - case CalculatorType.RegimeUniforme: { - nub = new RegimeUniforme(undefined, dbg); - break; - } + case CalculatorType.RegimeUniforme: + nub = new RegimeUniforme(undefined, dbg); + break; - case CalculatorType.CourbeRemous: { - prms = new CourbeRemousParams( - 0.15, // Yamont = tirant amont - 0.4, // Yaval = tirant aval - 100, // Long= Longueur du bief - 5, // Dx=Pas d'espace - ); - nub = new CourbeRemous(undefined, prms, MethodeResolution.EulerExplicite, dbg); - break; - } + case CalculatorType.CourbeRemous: + prms = new CourbeRemousParams( + 0.15, // Yamont = tirant amont + 0.4, // Yaval = tirant aval + 100, // Long= Longueur du bief + 5, // Dx=Pas d'espace + ); + nub = new CourbeRemous(undefined, prms, MethodeResolution.EulerExplicite, dbg); + break; - case CalculatorType.PabDimensions: { - prms = new PabDimensionParams( - 2, // Longueur L - 1, // Largeur W - 0.5, // Tirant d'eau Y - 2 // Volume V - ); - nub = new PabDimension(prms, dbg); - break; - } + case CalculatorType.PabDimensions: + prms = new PabDimensionParams( + 2, // Longueur L + 1, // Largeur W + 0.5, // Tirant d'eau Y + 2 // Volume V + ); + nub = new PabDimension(prms, dbg); + break; - case CalculatorType.PabPuissance: { - prms = new PabPuissanceParams( - 0.3, // Chute entre bassins DH (m) - 0.1, // Débit Q (m3/s) - 0.5, // Volume V (m3) - 588.6 // Puissance dissipée PV (W/m3) - ); - nub = new PabPuissance(prms, dbg); - break; - } + case CalculatorType.PabPuissance: + prms = new PabPuissanceParams( + 0.3, // Chute entre bassins DH (m) + 0.1, // Débit Q (m3/s) + 0.5, // Volume V (m3) + 588.6 // Puissance dissipée PV (W/m3) + ); + nub = new PabPuissance(prms, dbg); + break; - case CalculatorType.Structure: { - const loiDebit: LoiDebit = params.getPropValue("loiDebit"); - nub = CreateStructure(loiDebit, (parentNub as ParallelStructure)); - break; - } + case CalculatorType.Structure: + const loiDebit: LoiDebit = params.getPropValue("loiDebit"); + nub = CreateStructure(loiDebit, (parentNub as ParallelStructure)); + break; - case CalculatorType.ParallelStructure: { - prms = new ParallelStructureParams( - 0.5, // Q - 102, // Z1 - 101.5 // Z2 - ); - nub = new ParallelStructure(prms, dbg); - break; - } + case CalculatorType.ParallelStructure: + prms = new ParallelStructureParams( + 0.5, // Q + 102, // Z1 + 101.5 // Z2 + ); + nub = new ParallelStructure(prms, dbg); + break; - case CalculatorType.Dever: { - const deverPrms = new DeverParams( - 0.5, // Q - 102, // Z1 - 10, // BR : largeur du cours d'eau - 99 // ZR : cote du lit du cours d'eau - ); - nub = new Dever(deverPrms, dbg); - break; - } + case CalculatorType.Dever: + const deverPrms = new DeverParams( + 0.5, // Q + 102, // Z1 + 10, // BR : largeur du cours d'eau + 99 // ZR : cote du lit du cours d'eau + ); + nub = new Dever(deverPrms, dbg); + break; - case CalculatorType.Cloisons: { - nub = new Cloisons( - new CloisonsParams( - 1.5, // Débit total (m3/s) - 102, // Cote de l'eau amont (m) - 10, // Longueur des bassins (m) - 1, // Largeur des bassins (m) - 1, // Profondeur moyenne (m) - 0.5 // Hauteur de chute (m) - ), dbg - ); - break; - } + case CalculatorType.Cloisons: + nub = new Cloisons( + new CloisonsParams( + 1.5, // Débit total (m3/s) + 102, // Cote de l'eau amont (m) + 10, // Longueur des bassins (m) + 1, // Largeur des bassins (m) + 1, // Profondeur moyenne (m) + 0.5 // Hauteur de chute (m) + ), dbg + ); + break; - case CalculatorType.MacroRugo: { - nub = new MacroRugo( - new MacrorugoParams( - 12.5, // ZF1 - 6, // L - 1, // B - 0.05, // If - 1.57, // Q - 0.6, // h - 0.01, // Ks - 0.05, // C - 0.5, // D - 0.8, // k - 1.5 // Cd0 - ), dbg - ); - break; - } + case CalculatorType.MacroRugo: + nub = new MacroRugo( + new MacrorugoParams( + 12.5, // ZF1 + 6, // L + 1, // B + 0.05, // If + 1.57, // Q + 0.6, // h + 0.01, // Ks + 0.05, // C + 0.5, // D + 0.8, // k + 1.5 // Cd0 + ), dbg + ); + break; - case CalculatorType.PabChute: { - nub = new PabChute( - new PabChuteParams( - 2, // Z1 - 0.5, // Z2 - 1.5 // DH - ), dbg - ); - break; - } + case CalculatorType.PabChute: + nub = new PabChute( + new PabChuteParams( + 2, // Z1 + 0.5, // Z2 + 1.5 // DH + ), dbg + ); + break; - case CalculatorType.PabNombre: { - nub = new PabNombre( - new PabNombreParams( - 6, // DHT - 10, // N - 0.6 // DH - ), dbg - ); - break; - } + case CalculatorType.PabNombre: + nub = new PabNombre( + new PabNombreParams( + 6, // DHT + 10, // N + 0.6 // DH + ), dbg + ); + break; - case CalculatorType.Section: { - const nodeType: ComputeNodeType = params.getPropValue("nodeType"); - nub = this.createSection(nodeType, dbg); - break; - } + case CalculatorType.Section: + const nodeType: ComputeNodeType = params.getPropValue("nodeType"); + nub = this.createSection(nodeType, dbg); + break; case CalculatorType.Pab: nub = new Pab( @@ -433,11 +420,28 @@ export class Session { break; } - default: { - throw new Error( - `Session.createNub() : type de module '${CalculatorType[calcType]}' non pris en charge` - ); - } + case CalculatorType.MacroRugoCompound: + nub = new MacrorugoCompound( + new MacrorugoCompoundParams( + 13.1, // Z1 + 12.5, // ZRL + 12.5, // ZRR + 4, // B + 3, // DH + 0.05, // If + 0.01, // Ks + 0.05, // C + 0.5, // D + 0.8, // k + 1.5 // Cd0 + ) + ); + break; + + default: + throw new Error( + `Session.createNub() : type de module '${CalculatorType[calcType]}' non pris en charge` + ); } // propagate properties @@ -512,51 +516,51 @@ export class Session { switch (nt) { case ComputeNodeType.None: // pour les paramètres communs, n'importe quelle section convient case ComputeNodeType.SectionTrapeze: { - const prms = new ParamsSectionTrapez(2.5, // largeur de fond - 0.56, // fruit - 0.8, // tirant d'eau - 40, // Ks=Strickler - 1.2, // Q=Débit - 0.001, // If=pente du fond - 1, // YB= hauteur de berge - ); + const prms = new ParamsSectionTrapez(2.5, // largeur de fond + 0.56, // fruit + 0.8, // tirant d'eau + 40, // Ks=Strickler + 1.2, // Q=Débit + 0.001, // If=pente du fond + 1, // YB= hauteur de berge + ); - return new cSnTrapez(prms, dbg); - } + return new cSnTrapez(prms, dbg); + } case ComputeNodeType.SectionRectangle: { - const prms = new ParamsSectionRectang(0.8, // tirant d'eau - 2.5, // largeur de fond - 40, // Ks=Strickler - 1.2, // Q=Débit - 0.001, // If=pente du fond - 1 // YB=hauteur de berge - ); - return new cSnRectang(prms, dbg); - } + const prms = new ParamsSectionRectang(0.8, // tirant d'eau + 2.5, // largeur de fond + 40, // Ks=Strickler + 1.2, // Q=Débit + 0.001, // If=pente du fond + 1 // YB=hauteur de berge + ); + return new cSnRectang(prms, dbg); + } case ComputeNodeType.SectionCercle: { - const prms = new ParamsSectionCirc(2, // diamètre - 0.8, // tirant d'eau - 40, // Ks=Strickler - 1.2, // Q=Débit - 0.001, // If=pente du fond - 1, // YB= hauteur de berge - ); - return new cSnCirc(prms, dbg); - } + const prms = new ParamsSectionCirc(2, // diamètre + 0.8, // tirant d'eau + 40, // Ks=Strickler + 1.2, // Q=Débit + 0.001, // If=pente du fond + 1, // YB= hauteur de berge + ); + return new cSnCirc(prms, dbg); + } case ComputeNodeType.SectionPuissance: { - const prms = new ParamsSectionPuiss(0.5, // coefficient - 0.8, // tirant d'eau - 4, // largeur de berge - 40, // Ks=Strickler - 1.2, // Q=Débit - 0.001, // If=pente du fond - 1, // YB= hauteur de berge - ); - return new cSnPuiss(prms, dbg); - } + const prms = new ParamsSectionPuiss(0.5, // coefficient + 0.8, // tirant d'eau + 4, // largeur de berge + 40, // Ks=Strickler + 1.2, // Q=Débit + 0.001, // If=pente du fond + 1, // YB= hauteur de berge + ); + return new cSnPuiss(prms, dbg); + } default: throw new Error(`type de section ${ComputeNodeType[nt]} non pris en charge`); diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts index 107b5b571a63ba2f13b20e3f6f2117c9460d176a..d9c7483e5c436af4b7c82ef0c9cbc708016758d7 100644 --- a/src/structure/parallel_structure.ts +++ b/src/structure/parallel_structure.ts @@ -21,6 +21,7 @@ export class ParallelStructure extends Nub { constructor(prms: ParamsEquation, dbg: boolean = false) { super(prms, dbg); this._calcType = CalculatorType.ParallelStructure; + this._childrenType = "Structure"; } /** children casting */ @@ -128,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; @@ -205,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; } } diff --git a/src/structure/structure.ts b/src/structure/structure.ts index 01980793bd25b7caecb98d4437e8971bf6631551..75285fdc5c0d19e9c5ae176dc28afb9d70496b33 100644 --- a/src/structure/structure.ts +++ b/src/structure/structure.ts @@ -320,7 +320,7 @@ export abstract class Structure extends Nub { this.prms.Z2.calculability = ParamCalculability.DICHO; this.prms.h1.calculability = ParamCalculability.DICHO; this.prms.h2.calculability = ParamCalculability.DICHO; - this.prms.W.calculability = ParamCalculability.DICHO; + this.prms.W.calculability = ParamCalculability.FIXED; } /** diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts index 08bfeb4c0f176b18dc3ae35b0997933dc417d1a4..51d820c5f311d05969f50d2d9e69be4983040851 100644 --- a/src/structure/structure_cem88d.ts +++ b/src/structure/structure_cem88d.ts @@ -1,3 +1,4 @@ +import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { RectangularStructure } from "./rectangular_structure"; import { RectangularStructureParams } from "./rectangular_structure_params"; @@ -65,6 +66,14 @@ export class StructureGateCem88d extends RectangularStructure { return new Result(v, this, data); } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.W.calculability = ParamCalculability.DICHO; + } } // tslint:disable-next-line:max-classes-per-file @@ -81,4 +90,5 @@ export class StructureWeirCem88d extends StructureGateCem88d { protected getFlowMode(): StructureFlowMode { return StructureFlowMode.WEIR; } + } diff --git a/src/structure/structure_cem88v.ts b/src/structure/structure_cem88v.ts index 8a5d9c49dc4e65fa1f17d165bad5fe3c28e7f096..dec63d4005427e6400fb2ffbe4793e3d70d0da34 100644 --- a/src/structure/structure_cem88v.ts +++ b/src/structure/structure_cem88v.ts @@ -1,3 +1,4 @@ +import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { RectangularStructure } from "./rectangular_structure"; import { RectangularStructureParams } from "./rectangular_structure_params"; @@ -115,6 +116,14 @@ export class StructureGateCem88v extends RectangularStructure { } } + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.W.calculability = ParamCalculability.DICHO; + } + private getAlfa(h2: number): number { let alfa: number = 1 - 0.14 * (h2) / this.W; alfa = Math.min(Math.max(alfa, 0.4), 0.75); @@ -147,4 +156,5 @@ export class StructureWeirCem88v extends StructureGateCem88v { protected getFlowMode(): StructureFlowMode { return StructureFlowMode.WEIR; } + } diff --git a/src/structure/structure_cunge80.ts b/src/structure/structure_cunge80.ts index 79c2fff0fad296935982686a32f4d529251aa001..a19f4354df4cf259671c08d13d11d653697f8d51 100644 --- a/src/structure/structure_cunge80.ts +++ b/src/structure/structure_cunge80.ts @@ -1,3 +1,4 @@ +import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { RectangularStructure } from "./rectangular_structure"; import { RectangularStructureParams } from "./rectangular_structure_params"; @@ -80,6 +81,14 @@ export class StructureGateCunge80 extends RectangularStructure { } } } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.W.calculability = ParamCalculability.DICHO; + } } // tslint:disable-next-line:max-classes-per-file @@ -94,4 +103,5 @@ export class StructureWeirCunge80 extends StructureGateCunge80 { protected getFlowMode(): StructureFlowMode { return StructureFlowMode.WEIR; } + } diff --git a/src/structure/structure_rectangular_orifice_free.ts b/src/structure/structure_rectangular_orifice_free.ts index 8f0592b63d02705193da02a36847125862538040..18c2cc80128182f82fc4b37c2c37bae8dd383a0f 100644 --- a/src/structure/structure_rectangular_orifice_free.ts +++ b/src/structure/structure_rectangular_orifice_free.ts @@ -1,3 +1,4 @@ +import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { RectangularStructure } from "./rectangular_structure"; import { RectangularStructureParams } from "./rectangular_structure_params"; @@ -34,4 +35,12 @@ export class StructureRectangularOrificeFree extends RectangularStructure { protected getFlowRegime() { return StructureFlowRegime.FREE; } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.W.calculability = ParamCalculability.DICHO; + } } diff --git a/src/structure/structure_rectangular_orifice_submerged.ts b/src/structure/structure_rectangular_orifice_submerged.ts index 2550a70e5e02d748e56d526183728d7872ca9401..257bbd495b86d677eb85ba04ee657e9fdbaddd96 100644 --- a/src/structure/structure_rectangular_orifice_submerged.ts +++ b/src/structure/structure_rectangular_orifice_submerged.ts @@ -1,3 +1,4 @@ +import { ParamCalculability } from "../param/param-definition"; import { Result } from "../util/result"; import { RectangularStructure } from "./rectangular_structure"; import { RectangularStructureParams } from "./rectangular_structure_params"; @@ -37,4 +38,12 @@ export class StructureRectangularOrificeSubmerged extends RectangularStructure { protected getFlowRegime() { return StructureFlowRegime.SUBMERGED; } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.W.calculability = ParamCalculability.DICHO; + } }