diff --git a/doc/scilab_tests/Qouvrage.sci b/doc/scilab_tests/Qouvrage.sci new file mode 100755 index 0000000000000000000000000000000000000000..67759194c7e4d8fb994be629c25aff07869677da --- /dev/null +++ b/doc/scilab_tests/Qouvrage.sci @@ -0,0 +1,262 @@ +function [Q,C,w] = Qouvrage(T,h1,h2,w,hv,L,Cd) + // T=1 : Seuil Orifice avec surverse éventuelle (SIC) + // 2 : Seuil Vanne avec surverse éventuelle (SIC) + // 3 : Classique Seuil + // 4 : Classique Orifice + // 5 : Classique Noyee + // 6 : Cunge avec differentes conditions d'ecoulement + // h1 : cote amont (par rapport au radier) + // h2 : cote aval (par rapport au radier) + // w : ouverture (par rapport au radier) + // hv : hauteur de la vanne (pour le calcul de la surverse éventuelle) + // L : largeur + // Cd : coefficient de debit + // Q : debit + // C : code couleur correspondant aux conditions d'ecoulement + // C=0; debit nul + // C=1; surface libre denoye + // C=2; surface libre noye + // C=3; charge denoye + // C=4; charge noye partiel + // C=5; charge noye total + // C=C+10; si surverse + // Initialisation --------------------------------------------- + R2G = sqrt(2*9.81); + R32 = 3*sqrt(3)/2; + // Tests ------------------------------------------------------ + Q=0; + C=0; + partiel="non" + if (w==0 & hv==0) + Q=0; + return + end + if (h2>h1) + Q=0; + return + end + if (h1==0) + Q=0; + return + end + // Seuil - Orifice =========================================== + if (T==1 & w>0) + // Conditions d'ecoulement ------------------------------------ + if (h1<=w) + surfacelibre='oui'; + else + surfacelibre='non'; + end + alfa=2/3; + if (h2<=alfa*h1) + denoye='oui'; + else + denoye='non'; + if (h2<=2/3*h1+w/3) + partiel='oui'; + else + partiel='non'; + end + end + // Seuil - Denoye --------------------------------------------- + if (surfacelibre=='oui') & (denoye=='oui') + Q=Cd*L*R2G*(h1^1.5); + C=1; + end + // Seuil - Noye ----------------------------------------------- + if (surfacelibre=='oui') & (denoye=='non') + Cs=R32*Cd; + Q=Cs*L*R2G*((h1-h2)^0.5)*h2; + C=2; + end + // Orifice - Denoye ------------------------------------------- + if (surfacelibre=='non') & (denoye=='oui') + Q=Cd*L*R2G*(h1^1.5-(h1-w)^1.5); + C=3; + end + // Orifice - Noye --------------------------------------------- + if (surfacelibre=='non') & (denoye=='non') + // Ennoyement partiel --------------------------------- + if (partiel=='oui') + Q=Cd*L*R2G*(R32*h2*(h1-h2)^0.5-(h1-w)^1.5); + C=4; + // Ennoyement total ----------------------------------- + else + Cs=R32*Cd; + Q=Cs*L*R2G*((h1-h2)^0.5)*w; + //~printf("b2= %f Cd1=%f\n",(h1-h2)^0.5, Cs*L*R2G); + C=5; + end + end + end + // Seuil - Vanne ============================================= + if (T==2 & w>0) + // Calcul de parametres --------------------------------------- + mu0=2/3*Cd; + // Conditions d'ecoulement ------------------------------------ + if (h1<=w) + surfacelibre='oui'; + muf=mu0-0.08; + alfa=0.75; + else + surfacelibre='non'; + mu =mu0-0.08/(h1/w); + mu1=mu0-0.08/(h1/w-1); + alfa=1-0.14*h2/w; + printf("alfa=%f \n",alfa) + if (alfa<0.4) + alfa=0.4; + end + if (alfa>0.75) + alfa=0.75; + end + end + if (h2<=alfa*h1) + denoye='oui'; + else + denoye='non'; + x=sqrt(1-h2/h1); + beta1=-2*alfa+2.6; + if (x>0.2) + KF=1-(1-x/sqrt(1-alfa))^beta1; + else + KF=5*x*(1-(1-0.2/sqrt(1-alfa))^beta1); + end + printf("beta1=%f x=%f alfa=%f KF=%f\n",beta1,x,alfa,KF) + alfa1=1-0.14*(h2-w)/w; + if (alfa1<0.4) + alfa1=0.4; + end + if (alfa1>0.75) + alfa1=0.75; + end + if (h2<=alfa1*h1+(1-alfa1)*w) + partiel='oui'; + else + partiel='non'; + end + end + // Seuil - Denoye --------------------------------------------- + if (surfacelibre=='oui') & (denoye=='oui') + Q=muf*L*R2G*(h1^1.5); + C=1; + end + // Seuil - Noye ----------------------------------------------- + if (surfacelibre=='oui') & (denoye=='non') + printf("KF=%f muf=%f\n", KF, muf); + Q=KF*muf*L*R2G*(h1^1.5); + C=2; + end + // Vanne - Denoye --------------------------------------------- + if (surfacelibre=='non') & (denoye=='oui') + Q=L*R2G*(mu*h1^1.5-mu1*(h1-w)^1.5); + C=3; + end + // Vanne - Noye ----------------------------------------------- + if (surfacelibre=='non') & (denoye=='non') + x1=sqrt(1-(h2-w)/(h1-w)); + beta1=-2*alfa1+2.6; + if (x1>0.2) + KF1=1-(1-x1/sqrt(1-alfa1))^beta1; + else + KF1=5*x1*(1-(1-0.2/sqrt(1-alfa1))^beta1); + end + printf("beta1=%f x1=%f alfa1=%f KF1=%f\n",beta1,x1,alfa1,KF1) + // Ennoyement partiel --------------------------------- + if (partiel=='oui') + Q=L*R2G*(KF*mu*(h1^1.5)-mu1*(h1-w)^1.5); + C=4; + // Ennoyement total ----------------------------------- + else + printf("%f ",[L,R2G,KF,mu,h1,KF1,mu1,w]') + printf("\n") + Q=L*R2G*(KF*mu*(h1^1.5)-KF1*mu1*(h1-w)^1.5); + printf("Q=%f\n", Q) + C=5; + end + end + end + // Surverse dans cas 1 et 2 =================================== + if hv==0 + hv=%inf; + end; + if (T==1) | (T==2) + if (h1>w+hv) + surverse='oui'; + alfa=2/3; + if (h2-w-hv<=alfa*(h1-w-hv)) + denoyesurverse='oui'; + else + denoyesurverse='non'; + end + else + surverse='non'; + end + // Surverse - Denoye ------------------------------------------- + if (surverse=='oui') + if (denoyesurverse=='oui') + Q=Q+0.4*L*R2G*(h1-w-hv)^1.5; + C=C+10; + else + Q=Q+1.04*L*R2G*((h1-h2)^0.5)*(h2-w-hv); + C=C+10; + end + end + end + // Classique - Seuil ========================================== + if (T==3) + Q=Cd*L*R2G*h1^1.5; + C=1; + end + // Classique - Orifice ======================================== + if (T==4) + Q=Cd*min(h1,w)*L*R2G*(h1 - min(h1,w)/2)^0.5; + if (h1>w) + C=3; + else + C=1; + end + end + // Classique - Noyee ========================================== + if (T==5) + if (h1>h2) + Q=Cd*min(h1,w)*L*R2G*(h1-h2)^0.5; + if (h1>w) + C=5; + else + C=2; + end + else + Q=0; + C=0; + end + end + // Classique Cunge =========================================== + if (T==6) + // Conditions d'ecoulement ------------------------------------ + if (h2<=2/3*h1) + denoye='oui'; + if (w<=2/3*h1) + surfacelibre='non'; + Q=Cd*L*R2G*w*((h1-w)^0.5); + C=3; + else + surfacelibre='oui'; + Q=Cd*L*R2G/R32*h1^1.5; + C=1; + end + else + denoye='non'; + if (w<=h2) + surfacelibre='non'; + Q=Cd*L*R2G*w*((h1-h2)^0.5); + C=5; + else + surfacelibre='oui'; + Q=Cd*L*R2G*h2*((h1-h2)^0.5); + C=2; + end + end + end + //~printf("surface libre=%s denoye=%s partiel=%s\n", surfacelibre, denoye, partiel) +endfunction diff --git a/doc/scilab_tests/TestQOuvrageLoopW.sci b/doc/scilab_tests/TestQOuvrageLoopW.sci new file mode 100755 index 0000000000000000000000000000000000000000..fb80ced32f6dfa2b0ae453e9859cca183d6c1546 --- /dev/null +++ b/doc/scilab_tests/TestQOuvrageLoopW.sci @@ -0,0 +1,39 @@ +function TestQOuvrageLoop(sTest, T, L, Cd, H1, h2, W) + printf("\n") + printf("*** %s ***\n", sTest) + + // Tests des différents régimes + sCodeC = ["debit nul","surface libre denoye","surface libre noye","charge denoye","charge noye partiel","charge noye total"]; + Q = [] + C = [] + CS = [] + for w = W + for h1 = H1 + [q, c] = Qouvrage(T,h1,h2,w,0,L,Cd) + Q = [Q q] + C = [C c] + CS = [CS sCodeC(c+1)] + end + end + + printf("W=[") + printf("%f,",W') + printf("];\n") + + printf("h1=[") + printf("%f,",H1') + printf("];\n") + + printf("Q=[") + printf("%f,",Q') + printf("];\n") + + printf("C=[") + printf("%i,",C') + printf("];\n") + + printf("Code=[") + printf("%s,",CS') + printf("];\n") + +endfunction diff --git a/doc/scilab_tests/describe.sci b/doc/scilab_tests/describe.sci new file mode 100755 index 0000000000000000000000000000000000000000..283e4056dccba63f18da3887e69b69dfb509f7d6 --- /dev/null +++ b/doc/scilab_tests/describe.sci @@ -0,0 +1,6 @@ +function describe(sSuite) + printf("\n") + printf("****************************************\n") + printf("* %-36s *\n", sSuite) + printf("****************************************\n") +endfunction diff --git a/doc/scilab_tests/main_ouvrages.sce b/doc/scilab_tests/main_ouvrages.sce new file mode 100755 index 0000000000000000000000000000000000000000..d0d7bbb266a86816f8f8e32a0b73582d3682cc4d --- /dev/null +++ b/doc/scilab_tests/main_ouvrages.sce @@ -0,0 +1,29 @@ +// Test des équations d'ouvrages pour JaLHyd +clear +sCurrentPath = get_absolute_file_path("main_ouvrages.sce"); +getd(sCurrentPath); + +function TestQOuvrageSuite(T) + //TestQOuvrageLoop(sTest, T, L, Cd, H1, h2, W) + TestQOuvrageLoop("Calcul Q avec W croissant",T, 2, 0.6, 1.2, 1, 0:0.1:1.3); + TestQOuvrageLoop("Calcul Q en charge avec h1 croissant",T, 2, 0.6, [1.05,1.3,1.5], 1, 0.8); + TestQOuvrageLoop("Calcul Q a surface libre avec h1 croissant",T, 2, 0.6, [1.1,1.5], 1, 2); +endfunction + +describe("CEM88D"); +TestQOuvrageSuite(1); + +describe("CEM88V"); +TestQOuvrageSuite(2); + +describe("Classique - Seuil dénoyé"); +TestQOuvrageSuite(3); + +describe("Classique - Orifice dénoyé"); +TestQOuvrageSuite(4); + +describe("Classique - Orifice noyé"); +TestQOuvrageSuite(5); + +describe("Cunge 80"); +TestQOuvrageSuite(6); diff --git a/spec/mock_jasmine.ts b/spec/mock_jasmine.ts new file mode 100644 index 0000000000000000000000000000000000000000..670e76f69a38bc7390b1c8d8d1ffe9701df48618 --- /dev/null +++ b/spec/mock_jasmine.ts @@ -0,0 +1,86 @@ +/** + * Mock fonction describe de Jasmine + * @param sTxt Texte de la suite de test + * @param fFun Fonction de la suite de test + */ +export function describe(sTxt: string, fFun: () => void) { + // tslint:disable-next-line:no-console + console.log(sTxt); + fFun(); +} + +/** + * Mock fonction xdescribe de Jasmine + * @param sTxt Texte de la suite de test + * @param fFun Fonction de la suite de test + */ +export function xdescribe(sTxt: string, fFun: () => void) { + // tslint:disable-next-line:no-console + console.log(sTxt + " ignored ***"); +} + +/** + * Mock fonction it de jasmine + * @param sTxt Texte à afficher pour la spec + * @param fFun Function à lancer pour la spec + */ +export function it(sTxt: string, fFun: () => void) { + // tslint:disable-next-line:no-console + console.log(sTxt); + fFun(); +} + +/** + * Mock expect et toBeCloseTo de Jasmine. + * Ne fonctionne pas à cause de this = undefined dans le contexte "use strict" + */ +export function expect(obj: object) { + this.testResult = obj; + + this.toBeCloseTo = function(expected: number, precision: number) { + const pow = Math.pow(10, precision + 1); + const delta = Math.abs(expected - this.testResult); + const maxDelta = Math.pow(10, -precision) / 2; + if (Math.round(delta * pow) / pow > maxDelta) { + // tslint:disable-next-line:no-console + console.error("Expected " + this.testResult + " to be close to " + expected + "," + precision); + } + return this; + }; + return this; +} + +/** + * Mock de la function chainée à expect de test d'une valeur à un epsilon près + * @param actual Valeur numérique sortie du test + * @param expected Valeur numérique attendue + * @param precision Précision attendue (nombre de chiffre après la virgule) + */ +export function toBeCloseTo(actual: number, expected: number, precision: number) { + const pow = Math.pow(10, precision + 1); + const delta = Math.abs(expected - actual); + const maxDelta = Math.pow(10, -precision) / 2; + if (Math.round(delta * pow) / pow > maxDelta) { + // tslint:disable-next-line:no-console + console.error("Expected " + actual + " to be close to " + expected + "," + precision); + } + return this; +} + +/** + * Mock de la fonction toBe de Jasmine : the actual value to be `===` to the expected value + * @param actual Objet à tester + * @param expected Objet de référence + */ +export function toBe(actual: any, expected: any) { + return actual === expected; +} + +/** + * Mock de la fonction toBe de Jasmine : the actual value to be `===` to the expected value + * @param actual Objet à tester + * @param expected Objet de référence + */ +export function toEqual(actual: any, expected: any) { + return actual === expected; +} diff --git a/spec/structure/rectangular_structure.ts b/spec/structure/rectangular_structure.ts new file mode 100644 index 0000000000000000000000000000000000000000..34b3b6ae4843767b257f7346875e0209a2ba316e --- /dev/null +++ b/spec/structure/rectangular_structure.ts @@ -0,0 +1,50 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructure } from "../../src/structure/rectangular_structure"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { precDigits } from "../nubtest"; + +/** + * Récupération du nom de la classe + * https://www.stevefenton.co.uk/2013/04/Obtaining-A-Class-Name-At-Runtime-In-TypeScript/ + */ +export class Describer { + /** + * Récupère le nom de la classe d'un objet + * @param inputClass Objet à tester + */ + public static getName(inputClass: any) { + const funcNameRegex = /function (.{1,})\(/; + const results = (funcNameRegex).exec((inputClass as any).constructor.toString()); + return (results && results.length > 1) ? results[1] : ""; + } +} + +export function itCalcQ( + struct: RectangularStructure, h1: number, W: number, Q: number, + mode?: StructureFlowMode, regime?: StructureFlowRegime) { + + struct.debug("itCalQ " + Describer.getName(struct) + " h1=" + h1 + " W=" + W + " Q=" + Q); + + struct.prms.h1.v = h1; + struct.prms.W.v = W; + const res: Result = struct.Calc("Q"); + struct.debug("struct.Calc(Q)=" + res.vCalc); + + it("Q(h1=" + h1 + ",W=" + W + ") should be " + Q, () => { + struct.debug("struct.Calc(Q)=" + res.vCalc); + expect(res.vCalc).toBeCloseTo(Q, precDigits); + }); + if (mode !== undefined) { + it("Q(h1=" + h1 + ",W=" + W + ") Mode should be " + mode, () => { + expect(res.extraVar.Mode).toBe(mode); + }); + } + if (regime !== undefined) { + it("Q(h1=" + h1 + ",W=" + W + ") Regime should be " + regime, () => { + expect(res.extraVar.Regime).toBe(regime); + }); + } +} diff --git a/spec/structure/structure.spec.ts b/spec/structure/structure.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f0ba77c6ab37ed73656d6fcac695d423c659b85 --- /dev/null +++ b/spec/structure/structure.spec.ts @@ -0,0 +1,112 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { Structure, StructureFlowMode, StructureFlowRegime, StructureParams} from "../../src/structure/structure"; +import { equalEpsilon } from "../nubtest"; + +function check(val1: Result, val2: number) { + expect(equalEpsilon(val1.vCalc, val2)).toBe(true); +} + +class StructureTest extends Structure { + + constructor(prms: StructureParams, dbg: boolean = false) { + super(prms, dbg); + } + + /** + * Test of getFlowMode + */ + public testGetFlowMode() { + return this.getFlowMode(); + } + + /** + * Test of getFlowRegime + */ + public testGetFlowRegime() { + return this.getFlowRegime(); + } + + public Equation(sVarCalc: string): Result { + let v: number; + switch (sVarCalc) { + case "Q": + v = this.prms.h1.v - this.prms.h2.v; + break; + default: + throw new Error("StructureTest.Equation() : invalid parameter name " + sVarCalc); + } + return new Result(v); + } + +} + +const structTestPrm: StructureParams = new StructureParams(1, 30, 15); +const structTest: StructureTest = new StructureTest(structTestPrm, false); + +describe("Class Structure: ", () => { + + describe("getFlowMode()", () => { + it("Flow Mode should be WEIR", () => { + expect(structTest.testGetFlowMode()).toBe(StructureFlowMode.WEIR); + }); + it("Flow Mode should be ORIFICE", () => { + structTest.prms.W.v = 10; + expect(structTest.testGetFlowMode()).toBe(StructureFlowMode.ORIFICE); + structTest.prms.W.v = Infinity; + }); + }); + + describe("getFlowRegime()", () => { + it("Flow Regime should be FREE", () => { + expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.FREE); + }); + it("Flow Regime should be SUBMERGED (WEIR)", () => { + structTest.prms.h2.v = 21; + expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.SUBMERGED); + }); + it("Flow Regime should be PARTIAL (ORIFICE)", () => { + structTest.prms.h2.v = 21; + structTest.prms.W.v = 15; + expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.PARTIAL); + }); + it("Flow Regime should be SUBMERGED (ORIFICE)", () => { + structTest.prms.h2.v = 25; + structTest.prms.W.v = 15; + expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.SUBMERGED); + }); + structTest.prms.h2.v = 15; + structTest.prms.W.v = Infinity; + }); + + describe("Calc()", () => { + const flagsNull = {Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL}; + it("h1=h2 => Q=0", () => { + structTest.prms.h2.v = structTest.prms.h1.v; + check(structTest.Calc("Q"), 0); + expect(structTest.Calc("Q").extraVar).toEqual(flagsNull); + structTest.prms.h2.v = 15; + }); + it("W=0 => Q=0", () => { + structTest.prms.W.v = 0; + check(structTest.Calc("Q"), 0); + expect(structTest.Calc("Q").extraVar).toEqual(flagsNull); + structTest.prms.W.v = Infinity; + }); + it("Q=0 => h1=h2", () => { + structTest.prms.Q.v = 0; + check(structTest.Calc("h1"), structTest.prms.h2.v); + expect(structTest.Calc("h1").extraVar).toEqual(flagsNull); + structTest.prms.Q.v = 1; + }); + it("Q=0 => W=0", () => { + structTest.prms.Q.v = 0; + check(structTest.Calc("W"), 0); + expect(structTest.Calc("W").extraVar).toEqual(flagsNull); + structTest.prms.Q.v = 1; + }); + // TODO Test inversion de débit + }); +}); diff --git a/spec/structure/structure_cem88d.spec.ts b/spec/structure/structure_cem88d.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..1be7f28a43b0e65a3f1207b6986065c5924e2f4b --- /dev/null +++ b/spec/structure/structure_cem88d.spec.ts @@ -0,0 +1,52 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureCem88d } from "../../src/structure/structure_cem88d"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCem88d = new StructureCem88d(structPrm, false); + +describe("Class StructureCem88d: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.617586, 1.235173, 1.852759, 2.470345, 3.087931, + 3.705518, 4.296608, 4.831177, 5.302464, 5.700445, 6.007777, 6.175863, 6.175863]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [2.470345, 5.684601, 6.651906]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.PARTIAL, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [4.366994, 9.764896]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/structure_cem88v.spec.ts b/spec/structure/structure_cem88v.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c2b3d1daccedac8d333f149c83284a1e54ffa2ca --- /dev/null +++ b/spec/structure/structure_cem88v.spec.ts @@ -0,0 +1,51 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureCem88v } from "../../src/structure/structure_cem88v"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCem88v = new StructureCem88v(structPrm, false); + +describe("Class StructureCem88v: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, + 0.600000, 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [.000000, 0.328260, 0.641822, 0.823867, 1.117381, 1.720738, + 2.225472, 2.575336, 2.873893, 3.113250, 3.280545, 3.349403, 3.149324, 3.149324]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.05, 1.3, 1.5]; + const Q: number[] = [1.365897, 3.623277, 4.214572]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.PARTIAL, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [2.086781, 5.207945]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/structure_cunge80.spec.ts b/spec/structure/structure_cunge80.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..69cb47d92783e0771efe2d91c160573b60a6094a --- /dev/null +++ b/spec/structure/structure_cunge80.spec.ts @@ -0,0 +1,52 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureCunge80 } from "../../src/structure/structure_cunge80"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCunge80 = new StructureCunge80(structPrm, false); + +describe("Class StructureCunge80: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545, + 1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.377091, 2.377091, 2.377091]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [0.950836, 2.329064, 3.557704]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [1.680857, 3.758510]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/structure_orifice_free.spec.ts b/spec/structure/structure_orifice_free.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..db51c1ec0ffa9ac9d4ca20837494efd5beae4518 --- /dev/null +++ b/spec/structure/structure_orifice_free.spec.ts @@ -0,0 +1,52 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureOrificeFree } from "../../src/structure/structure_orifice_free"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureOrificeFree = new StructureOrificeFree(structPrm, false); + +describe("Class StructureOrificeFree: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.582266, 1.164532, 1.746798, 2.329064, 2.911330, + 3.493596, 4.075861, 4.658127, 5.240393, 5.822659, 6.404925, 6.987191, 6.987191]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [4.357279, 4.848333, 5.207945]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.FREE, StructureFlowRegime.FREE, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [6.132249, 9.764896]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.FREE, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/structure_orifice_submerged.spec.ts b/spec/structure/structure_orifice_submerged.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..050bd6a7dc76407ed57d86d755b7cf5cb75e37a4 --- /dev/null +++ b/spec/structure/structure_orifice_submerged.spec.ts @@ -0,0 +1,52 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureOrificeSubmerged } from "../../src/structure/structure_orifice_submerged"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureOrificeSubmerged = new StructureOrificeSubmerged(structPrm, false); + +describe("Class StructureOrificeSubmerged: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545, + 1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.614800, 2.852509, 2.852509]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [0.950836, 2.329064, 3.006808]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [1.848943, 5.637766]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/structure_weir_free.spec.ts b/spec/structure/structure_weir_free.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..9a75c2d01c581992d620c12c5f41b9cbc612f0ce --- /dev/null +++ b/spec/structure/structure_weir_free.spec.ts @@ -0,0 +1,52 @@ +// tslint:disable-next-line:no-reference +/// <reference path="../../node_modules/@types/jasmine/index.d.ts" /> + +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureWeirFree } from "../../src/structure/structure_weir_free"; +import { itCalcQ } from "./rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureWeirFree = new StructureWeirFree(structPrm, false); + +describe("Class StructureWeirFree: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, + 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [5.718929, 7.878541, 9.764896]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.FREE, StructureFlowRegime.FREE, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [6.132249, 9.764896]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.FREE, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/spec/structure/test_rectangular_structure.ts b/spec/structure/test_rectangular_structure.ts new file mode 100644 index 0000000000000000000000000000000000000000..603fd06240d11313a8b55354b85167a37c5cb3e0 --- /dev/null +++ b/spec/structure/test_rectangular_structure.ts @@ -0,0 +1,33 @@ +import { Result } from "../../src/base"; +import { RectangularStructure } from "../../src/structure/rectangular_structure"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { it, toBe, toBeCloseTo } from "../mock_jasmine"; +import { precDigits } from "../nubtest"; +import { Describer } from "./rectangular_structure"; + +export function itCalcQ( + struct: RectangularStructure, h1: number, W: number, Q: number, + mode?: StructureFlowMode, regime?: StructureFlowRegime) { + + struct.debug("itCalQ " + Describer.getName(struct) + " h1=" + h1 + " W=" + W + " Q=" + Q); + + struct.prms.h1.v = h1; + struct.prms.W.v = W; + const res: Result = struct.Calc("Q"); + struct.debug("struct.Calc(Q)=" + res.vCalc); + + it("Q(h1=" + h1 + ",W=" + W + ") should be " + Q, () => { + struct.debug("struct.Calc(Q)=" + res.vCalc); + toBeCloseTo(res.vCalc, Q, precDigits); + }); + if (mode !== undefined) { + it("Q(h1=" + h1 + ",W=" + W + ") Mode should be " + mode, () => { + toBe(res.extraVar.Mode, mode); + }); + } + if (regime !== undefined) { + it("Q(h1=" + h1 + ",W=" + W + ") Regime should be " + regime, () => { + toBe(res.extraVar.Regime, regime); + }); + } +} diff --git a/spec/structure/test_structure_cem88d.ts b/spec/structure/test_structure_cem88d.ts new file mode 100644 index 0000000000000000000000000000000000000000..92c674710f9ba2602dabc00d4d9023ccf6583a7e --- /dev/null +++ b/spec/structure/test_structure_cem88d.ts @@ -0,0 +1,41 @@ +import { Result } from "../../src/base"; +import { RectangularStructureParams, StructureCem88d } from "../../src/structure/structure_cem88d"; +import { describe, xdescribe } from "../mock_jasmine"; +import { precDigits } from "../nubtest"; +import { itCalcQ } from "./test_rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCem88d = new StructureCem88d(structPrm, true); + +describe("Class StructureCem88d: ", () => { + + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, + 0.600000, 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.617586, 1.235173, 1.852759, 2.470345, 3.087931, 3.705518, + 4.296608, 4.831177, 5.302464, 5.700445, 6.007777, 6.175863, 6.175863]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [2.470345, 5.684601, 6.651906]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [4.366994, 9.764896]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i]); + } + }); +}); diff --git a/spec/structure/test_structure_cem88v.ts b/spec/structure/test_structure_cem88v.ts new file mode 100644 index 0000000000000000000000000000000000000000..20acbfaeeee65dc51f05d1400e21d6ba34729936 --- /dev/null +++ b/spec/structure/test_structure_cem88v.ts @@ -0,0 +1,40 @@ +import { Result } from "../../src/base"; +import { RectangularStructureParams, StructureCem88v } from "../../src/structure/structure_cem88v"; +import { describe, xdescribe } from "../mock_jasmine"; +import { precDigits } from "../nubtest"; +import { itCalcQ } from "./test_rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCem88v = new StructureCem88v(structPrm, true); + +describe("Class StructureCem88v: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [.000000, 0.328260, 0.641822, 0.823867, 1.117381, 1.720738, + 2.225472, 2.575336, 2.873893, 3.113250, 3.280545, 3.349403, 3.149324, 3.149324]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + xdescribe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.05, 1.3, 1.5]; + const Q: number[] = [1.365897, 3.623277, 4.214572]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i]); + } + }); + xdescribe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [2.086781, 5.207945]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i]); + } + }); +}); diff --git a/spec/structure/test_structure_cunge80.ts b/spec/structure/test_structure_cunge80.ts new file mode 100644 index 0000000000000000000000000000000000000000..7cc5df7cf6b296715fb54247ed5b4a4ebdcdc30f --- /dev/null +++ b/spec/structure/test_structure_cunge80.ts @@ -0,0 +1,50 @@ +import { Result } from "../../src/base"; +import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params"; +import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure"; +import { StructureCunge80 } from "../../src/structure/structure_cunge80"; +import { describe, xdescribe } from "../mock_jasmine"; +import { itCalcQ } from "./test_rectangular_structure"; + +const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0); +const structTest: StructureCunge80 = new StructureCunge80(structPrm, true); + +describe("Class StructureCunge80: ", () => { + describe("Calcul Q avec W croissant: ", () => { + const W: number[] = [ + 0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000, + 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000]; + const h1: number = 1.200000; + const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545, + 1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.377091, 2.377091, 2.377091]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1, W[i], Q[i]); + } + }); + describe("Calcul Q en charge avec h1 croissant: ", () => { + const W: number = 0.8; + const h1: number[] = [1.050000, 1.300000, 1.500000]; + const Q: number[] = [0.950836, 2.329064, 3.557704]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); + describe("Calcul Q a surface libre avec h1 croissant: ", () => { + const W: number = Infinity; + const h1: number[] = [1.100000, 1.500000]; + const Q: number[] = [1.680857, 3.758510]; + const mode: StructureFlowMode[] = [ + StructureFlowMode.WEIR, StructureFlowMode.WEIR]; + const regime: StructureFlowRegime[] = [ + StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE]; + + for (let i = 0; i < Q.length; i++ ) { + itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]); + } + }); +}); diff --git a/src/base.ts b/src/base.ts index 9e7c06fed8ec509d9ed578c3282cb0e94c6f1e2d..ad55b28fade5bb9b6959e5e2245d49c8adbfe241 100644 --- a/src/base.ts +++ b/src/base.ts @@ -4,17 +4,26 @@ import { Message, MessageCode } from "./util/message"; * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...) */ export class Result { + + /** Calculs intermédiaires ou supplémentaires, flags de calcul */ + public extraVar: { [key: string]: any }; + /** Valeur calculée */ - private _vCalc: number; + public vCalc: number; private _message: Message; - constructor(v: number, e: Message = undefined) { - this._vCalc = v; - this._message = e; - }; - - get vCalc() { return this._vCalc; } + /** + * Résultat de calcul + * @param v Valeur numérique du résultat + * @param m Message d'erreur + * @param e Calculs intermédiaires ou supplémentaires, flags de calcul + */ + constructor(v: number, e?: { [key: string]: any }, m?: Message) { + this.vCalc = v; + this.extraVar = e; + this._message = m; + } get code() { if (this._message == undefined) @@ -49,11 +58,11 @@ export abstract class Debug { */ constructor(private _DBG: boolean) { } - /** + /** * Affiche un message dans la console si le flag this.DBG est à true * @param s Message à afficher dans la console */ - protected debug(s: any) { + public debug(s: any) { if (this._DBG) console.log(s); } diff --git a/src/dichotomie.ts b/src/dichotomie.ts index 9485690c41128933c5a53034e6b579464b2aad21..d02fd2a010f6de02503138bd719bb0bcfd725890 100644 --- a/src/dichotomie.ts +++ b/src/dichotomie.ts @@ -360,7 +360,7 @@ export class Dichotomie extends Debug { // gestion de l'erreur - // la valeur cible de la fonction est elle trouvable ? + // la valeur cible de la fonction est elle trouvable ? let m; let res: Message; @@ -461,7 +461,7 @@ export class Dichotomie extends Debug { if (r.ok) var interv: SearchInterval = r.intSearch; else { - let result = new Result(undefined, r.res); + let result = new Result(undefined, undefined, r.res); return result; } diff --git a/src/structure/rectangular_structure.ts b/src/structure/rectangular_structure.ts new file mode 100644 index 0000000000000000000000000000000000000000..a835b146a9c764c11d7d25eac107557c4761c8c6 --- /dev/null +++ b/src/structure/rectangular_structure.ts @@ -0,0 +1,32 @@ +import { ParamCalculability } from "../param"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Classe mère pour toutes les structures ayant une base rectangulaire (vannes, seuils) + */ +export abstract class RectangularStructure extends Structure { + + constructor(prms: RectangularStructureParams, dbg: boolean = false) { + super(prms, dbg); + } + + /** + * paramètres castés au bon type + */ + get prms(): RectangularStructureParams { + return this._prms as RectangularStructureParams; + } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + super.setParametersCalculability(); + this.prms.L.calculability = ParamCalculability.DICHO; + this.prms.Cd.calculability = ParamCalculability.DICHO; + } + +} diff --git a/src/structure/rectangular_structure_params.ts b/src/structure/rectangular_structure_params.ts new file mode 100644 index 0000000000000000000000000000000000000000..edd24882d4056e5269a8d5361f6cb193c92fb18c --- /dev/null +++ b/src/structure/rectangular_structure_params.ts @@ -0,0 +1,22 @@ +import { ComputeNodeType, ParamCalculability, ParamDefinition, ParamDomainValue, ParamsEquation } from "../param"; +import { Structure } from "./structure"; +import { StructureParams } from "./structure_params"; + +/** + * Parameters for rectangular structures (common for all rectangular structure equations) + */ +export class RectangularStructureParams extends StructureParams { + /** Width of the gate or length of the sill (m) */ + public L: ParamDefinition; + + /** Discharge coefficient */ + public Cd: ParamDefinition; + + constructor(rQ: number, rh1: number, rh2: number, rL: number, rCd: number, rW: number = Infinity) { + super(rQ, rh1, rh2, rW); + this.L = new ParamDefinition(ComputeNodeType.CondDistri, "L", ParamDomainValue.POS, rL); + this.addParamDefinition(this.L); + this.Cd = new ParamDefinition(ComputeNodeType.CondDistri, "Cd", ParamDomainValue.POS, rCd); + this.addParamDefinition(this.Cd); + } +} diff --git a/src/structure/structure.ts b/src/structure/structure.ts new file mode 100644 index 0000000000000000000000000000000000000000..f1254a47f068523df82df5f3568d8ebc29d0b0a0 --- /dev/null +++ b/src/structure/structure.ts @@ -0,0 +1,167 @@ +import { Result } from "../base"; +import { Nub } from "../nub"; +import { ParamCalculability } from "../param"; +import { Message } from "../util/message"; + +import { StructureParams } from "./structure_params"; + +export { StructureParams }; + +/** + * Flow mode: weir or orifice flow + */ +export enum StructureFlowMode { + /** Weir flow */ + WEIR, + /** Orifice flow */ + ORIFICE, + /** Zéro flow */ + NULL, +} + +/** + * Flow regime: free flow, partially submerged or submerged + */ +export enum StructureFlowRegime { + /** Free flow (unsubmerged) */ + FREE, + /** Partially submerged flow */ + PARTIAL, + /** Submerged flow */ + SUBMERGED, + /** Zéro flow */ + NULL, + } + +/** + * classe de calcul sur la conduite distributrice + */ +export abstract class Structure extends Nub { + + /** Constante utile : Racine de 2g */ + protected static readonly R2G: number = Math.sqrt(2 * 9.81); + + constructor(prms: StructureParams, dbg: boolean = false) { + super(prms, dbg); + } + + /** + * paramètres castés au bon type + */ + get prms(): StructureParams { + return this._prms as StructureParams; + } + + /** + * Calcul du mode et du régime d'écoulement + */ + public Equation(sVarCalc: string): Result { + this.CheckEquation(sVarCalc); + const res: Result = new Result(undefined, { + Mode: this.getFlowMode(), + Regime: this.getFlowRegime()}); + return res; + } + + /** + * Calcul d'une équation quelque soit l'inconnue à calculer. + * Gestion du débit nul et de l'inversion de débit + * @param sVarCalc nom de la variable à calculer + * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie + * @param rPrec précision de calcul + */ + public Calc(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result { + const flagsNull = {Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL}; + // Gestion du débit nul + if (sVarCalc === "Q") { + if (this.prms.h1.v === this.prms.h2.v || this.prms.W.v <= 0) { + return new Result(0, flagsNull); + } + } else if (this.prms.Q.v === 0) { + // Débit nul <=> tirant d'eau amont = tirant d'eau aval ou tout autre paramètre nul + switch (sVarCalc) { + case "h1" : + return new Result(this.prms.h2.v, flagsNull); + case "h2" : + return new Result(this.prms.h1.v, flagsNull); + default : + // Est-ce toujours vrai ? Nécessitera peut-être d'étendre la méthode + return new Result(0, flagsNull); + } + } else if (this.prms.W.v === 0 && sVarCalc === "h1") { + return new Result(Infinity, flagsNull); // Si la vanne est fermée la cote amont est infinie + } + + // 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 + let res: Result; + res = super.Calc(sVarCalc, rInit, rPrec); + [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion + return res; + } + + return super.Calc(sVarCalc, rInit, rPrec); + + } + + /** + * paramétrage de la calculabilité des paramètres + */ + protected setParametersCalculability() { + this.prms.Q.calculability = ParamCalculability.EQUATION; + this.prms.h1.calculability = ParamCalculability.DICHO; + this.prms.h2.calculability = ParamCalculability.DICHO; + this.prms.W.calculability = ParamCalculability.DICHO; + } + + /** + * Give the flow mode : weir or orifice flow + */ + protected getFlowMode(): StructureFlowMode { + if (this.prms.h1.v > this.prms.W.v) { + this.debug("Structure.getFlowMode(h1=" + this.prms.h1.v + ",W=" + this.prms.W.v + ")=ORIFICE"); + return StructureFlowMode.ORIFICE; + } else { + this.debug("Structure.getFlowMode(h1=" + this.prms.h1.v + ",W=" + this.prms.W.v + ")=WEIR"); + return StructureFlowMode.WEIR; + } + + } + + /** + * Give the flow regime for a rectangular section : free, partially submerged or submerged flow + */ + protected getFlowRegime(): StructureFlowRegime { + // Weir have only two flow regimes: free and submerged flow + // Orifice have three flow regimes: free, partially submerged and (totally) submerged + if (this.prms.h2.v <= 2 / 3 * this.prms.h1.v) { + // free flow for both weirs and orifices + this.debug( + "Structure.getFlowRegime(h1=" + + this.prms.h1.v + ",h2=" + this.prms.h2.v + + ",W=" + this.prms.W.v + ")=FREE"); + return StructureFlowRegime.FREE; + } else if (this.prms.h1.v > this.prms.W.v && this.prms.h2.v < (2 * this.prms.h1.v + this.prms.W.v) / 3) { + // Partially submerged only for orifices + this.debug( + "Structure.getFlowRegime(h1=" + + this.prms.h1.v + ",h2=" + this.prms.h2.v + + ",W=" + this.prms.W.v + ")=PARTIAL"); + return StructureFlowRegime.PARTIAL; + } else { + // (Totally) submerged for both weirs and orifices + this.debug( + "Structure.getFlowRegime(h1=" + this.prms.h1.v + + ",h2=" + this.prms.h2.v + ",W=" + this.prms.W.v + ")=SUBMERGED"); + return StructureFlowRegime.SUBMERGED; + } + } + + /** + * Test générique si VarCalc="Q" pour l'utilisation de Equation + */ + private CheckEquation(sVarCalc: string) { + if (sVarCalc !== "Q") { throw new Error("Structure.Equation() : invalid parameter name " + sVarCalc); } + } +} diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts new file mode 100644 index 0000000000000000000000000000000000000000..8ddde8744cb93df31c65333fe725ae8583d6f80b --- /dev/null +++ b/src/structure/structure_cem88d.ts @@ -0,0 +1,58 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation CEM88D : déversoir / orifice (pelle importante) Cemagref 1988 + */ +export class StructureCem88d extends RectangularStructure { + + /** + * Calcul analytique Q = f(Cd, L, h1, h2, W) CEM88D + * @param sVarCalc Variable à calculer (doit être "Q") + */ + public Equation(sVarCalc: string): Result { + const res: Result = super.Equation(sVarCalc); + let v: number; + const cd: number = this.prms.Cd.v * this.prms.L.v * Structure.R2G; + const b1: number = Math.sqrt(this.prms.h1.v); + const b2: number = Math.sqrt(this.prms.h1.v - this.prms.h2.v); + const cd1: number = cd * 2.5981; // cd * 3*sqrt(3)/2 + this.debug("StructureCem88d.Equation b1=" + b1 + " b2=" + b2 + " cd1=" + cd1); + switch (res.extraVar.Mode) { + case StructureFlowMode.WEIR: + switch (res.extraVar.Regime) { + case StructureFlowRegime.FREE: + v = cd * this.prms.h1.v * b1; + break; + case StructureFlowRegime.SUBMERGED: + v = cd1 * this.prms.h2.v * b2; + this.debug("StructureCem88d.Equation WEIR SUBMERGED Q=" + v); + break; + } + break; + case StructureFlowMode.ORIFICE: + const b3: number = Math.pow(this.prms.h1.v - this.prms.W.v, 1.5); + switch (res.extraVar.Regime) { + case StructureFlowRegime.FREE: + v = cd * (this.prms.h1.v * b1 - b3); + break; + case StructureFlowRegime.PARTIAL: + v = cd1 * b2 * this.prms.h2.v - cd * b3; + break; + case StructureFlowRegime.SUBMERGED: + v = cd1 * b2 * this.prms.W.v; + this.debug("StructureCem88d.Equation ORIFICE SUBMERGED Q=" + v); + break; + } + } + this.debug( + "StructureCem88d.Equation(h1=" + this.prms.h1.v + ",h2=" + + this.prms.h2.v + ",W=" + this.prms.W.v + ") => Q=" + v); + res.vCalc = v; + return res; + } +} diff --git a/src/structure/structure_cem88v.ts b/src/structure/structure_cem88v.ts new file mode 100644 index 0000000000000000000000000000000000000000..457f430006452b553bedd14f5b744a29ed1bafff --- /dev/null +++ b/src/structure/structure_cem88v.ts @@ -0,0 +1,127 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation CEM88V : déversoir / vanne de fond (pelle faible) Cemagref 1988 + */ +export class StructureCem88v extends RectangularStructure { + + /** + * Calcul analytique Q = f(Cd, L, h1, h2, W) CEM88V + * @param sVarCalc Variable à calculer (doit être "Q") + */ + public Equation(sVarCalc: string): Result { + const res: Result = super.Equation(sVarCalc); + let v: number; + const mu0: number = 2 / 3 * this.prms.Cd.v; + let KF: number; + if (res.extraVar.Regime !== StructureFlowRegime.FREE) { + KF = this.getKF(Math.sqrt( 1 - this.prms.h2.v / this.prms.h1.v), this.getAlfa(this.prms.h2.v)); + } + switch (res.extraVar.Mode) { + case StructureFlowMode.WEIR: + const muf: number = mu0 - 0.08; + switch (res.extraVar.Regime) { + case StructureFlowRegime.FREE: + v = muf * this.prms.L.v * Structure.R2G * Math.pow(this.prms.h1.v, 1.5); + break; + case StructureFlowRegime.SUBMERGED: + // console.log("KF="+KF+" muf="+muf); + v = KF * muf * this.prms.L.v * Structure.R2G * Math.pow(this.prms.h1.v, 1.5); + break; + } + break; + case StructureFlowMode.ORIFICE: + const mu: number = mu0 - 0.08 / (this.prms.h1.v / this.prms.W.v); + const mu1: number = mu0 - 0.08 / (this.prms.h1.v / this.prms.W.v - 1); + if (res.extraVar.Regime === StructureFlowRegime.FREE) { + v = this.prms.L.v * Structure.R2G + * (mu * Math.pow(this.prms.h1.v, 1.5) + - mu1 * Math.pow(this.prms.h1.v - this.prms.W.v, 1.5)); + } else { + if (res.extraVar.Regime === StructureFlowRegime.PARTIAL) { + v = this.prms.L.v * Structure.R2G * ( + KF * mu * Math.pow(this.prms.h1.v, 1.5) + - mu1 * Math.pow(this.prms.h1.v - this.prms.W.v, 1.5) + ); + } else { + const KF1 = this.getKF( + Math.sqrt( 1 - (this.prms.h2.v - this.prms.W.v) / (this.prms.h1.v - this.prms.W.v)), + this.getAlfa(this.prms.h2.v - this.prms.W.v), + ); + v = this.prms.L.v * Structure.R2G * ( + KF * mu * Math.pow(this.prms.h1.v, 1.5) + - KF1 * mu1 * Math.pow(this.prms.h1.v - this.prms.W.v, 1.5) + ); + } + } + } + this.debug( + "StructureCem88v.Equation(h1=" + this.prms.h1.v + + ",h2=" + this.prms.h2.v + ",W=" + this.prms.W.v + ") => Q=" + v); + res.vCalc = v; + return res; + } + + /** + * Give the flow regime for Equation CEM88V : free, partially submerged or submerged flow + */ + protected getFlowRegime(): StructureFlowRegime { + const mode: StructureFlowMode = this.getFlowMode(); + // Weir have only two flow regimes: free and submerged flow + let alfa: number; + switch (mode) { + case StructureFlowMode.WEIR: + alfa = 0.75; + break; + case StructureFlowMode.ORIFICE: + alfa = this.getAlfa(this.prms.h2.v); + break; + } + if (this.prms.h2.v <= alfa * this.prms.h1.v) { + this.debug( + "StructureCem88v.getFlowRegime(h1=" + this.prms.h1.v + + ",h2=" + this.prms.h2.v + ",W=" + this.prms.W.v + ")=FREE"); + return StructureFlowRegime.FREE; + } else { + alfa = this.getAlfa(this.prms.h2.v - this.prms.W.v); + if ( + mode === StructureFlowMode.ORIFICE + && this.prms.h2.v <= alfa * this.prms.h1.v + (1 - alfa) * this.prms.W.v + ) { + this.debug( + "StructureCem88v.getFlowRegime(h1=" + this.prms.h1.v + + ",h2=" + this.prms.h2.v + ",W=" + this.prms.W.v + ")=PARTIAL"); + return StructureFlowRegime.PARTIAL; + } else { + this.debug( + "StructureCem88v.getFlowRegime(h1=" + this.prms.h1.v + + ",h2=" + this.prms.h2.v + ",W=" + this.prms.W.v + ")=SUBMERGED"); + return StructureFlowRegime.SUBMERGED; + } + } + } + + private getAlfa(h2: number): number { + let alfa: number = 1 - 0.14 * (h2) / this.prms.W.v; + alfa = Math.min(Math.max(alfa, 0.4), 0.75); + // console.log("alfa=" + alfa); + return alfa; + } + + private getKF(x: number, alfa: number): number { + const beta1 = -2 * alfa + 2.6; + let KF: number; + if (x > 0.2) { + KF = 1 - Math.pow(1 - x / Math.sqrt(1 - alfa), beta1); + } else { + KF = 5 * x * (1 - Math.pow(1 - 0.2 / Math.sqrt(1 - alfa), beta1)); + } + // console.log("KF(x="+x+")="+KF); + return KF; + } +} diff --git a/src/structure/structure_cunge80.ts b/src/structure/structure_cunge80.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9cc8f448aad3ae941fb0198a1c8d4e375339889 --- /dev/null +++ b/src/structure/structure_cunge80.ts @@ -0,0 +1,69 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation Cunge80 + */ +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 { + const res: Result = super.Equation(sVarCalc); + switch (res.extraVar.Regime) { + case StructureFlowRegime.FREE: + if (res.extraVar.Mode === StructureFlowMode.WEIR) { + const R32: number = 3 * Math.sqrt(3) / 2; + res.vCalc = this.prms.Cd.v * this.prms.L.v * Structure.R2G / R32 * Math.pow(this.prms.h1.v, 1.5); + this.debug("StructureCunge80.Equation WEIR FREE Q=" + res.vCalc); + } else { + res.vCalc = this.prms.Cd.v * this.prms.L.v * Structure.R2G + * this.prms.W.v * Math.pow(this.prms.h1.v - this.prms.W.v, 0.5); + this.debug("StructureCunge80.Equation ORIFICE FREE Q=" + res.vCalc); + } + break; + case StructureFlowRegime.SUBMERGED: + if (res.extraVar.Mode === StructureFlowMode.WEIR) { + res.vCalc = this.prms.Cd.v * this.prms.L.v * Structure.R2G * this.prms.h2.v + * Math.sqrt(this.prms.h1.v - this.prms.h2.v); + this.debug("StructureCunge80.Equation WEIR SUBMERGED Q=" + res.vCalc); + } else { + res.vCalc = this.prms.Cd.v * this.prms.L.v * Structure.R2G + * this.prms.W.v * Math.sqrt(this.prms.h1.v - this.prms.h2.v); + this.debug("StructureCunge80.Equation ORIFICE SUBMERGED Q=" + res.vCalc); + } + } + return res; + } + + protected getFlowRegime() { + if (this.prms.h1.v >= 1.5 * this.prms.h2.v) { + return StructureFlowRegime.FREE; + } else { + return StructureFlowRegime.SUBMERGED; + } + } + + protected getFlowMode() { + const regime: StructureFlowRegime = this.getFlowRegime(); + switch (regime) { + case StructureFlowRegime.FREE: + if (this.prms.W.v <= 2 / 3 * this.prms.h1.v) { + return StructureFlowMode.ORIFICE; + } else { + return StructureFlowMode.WEIR; + } + case StructureFlowRegime.SUBMERGED: + if (this.prms.W.v <= this.prms.h2.v) { + return StructureFlowMode.ORIFICE; + } else { + return StructureFlowMode.WEIR; + } + } + } +} diff --git a/src/structure/structure_orifice_free.ts b/src/structure/structure_orifice_free.ts new file mode 100644 index 0000000000000000000000000000000000000000..fcb3477baaeaebf07645bc770024b371c9adc367 --- /dev/null +++ b/src/structure/structure_orifice_free.ts @@ -0,0 +1,24 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation classique orifice dénoyé + */ +export class StructureOrificeFree 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 { + const res: Result = super.Equation(sVarCalc); + // TODO : Warning si les conditions hydrauliques ne correspondent pas à un écoulement dénoyé + res.extraVar.Regime = StructureFlowRegime.FREE; + res.vCalc = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v + * Structure.R2G * Math.sqrt(this.prms.h1.v); + return res; + } +} diff --git a/src/structure/structure_orifice_submerged.ts b/src/structure/structure_orifice_submerged.ts new file mode 100644 index 0000000000000000000000000000000000000000..bfdc4e57c0e68558e28e70945ae42d3036aea2ef --- /dev/null +++ b/src/structure/structure_orifice_submerged.ts @@ -0,0 +1,24 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation classique orifice noyé + */ +export class StructureOrificeSubmerged 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 { + const res: Result = super.Equation(sVarCalc); + // TODO : Warning si les conditions hydrauliques ne correspondent pas à un écoulement dénoyé + res.extraVar.Regime = StructureFlowRegime.SUBMERGED; + res.vCalc = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v + * Structure.R2G * Math.sqrt(this.prms.h1.v - this.prms.h2.v); + return res; + } +} diff --git a/src/structure/structure_params.ts b/src/structure/structure_params.ts new file mode 100644 index 0000000000000000000000000000000000000000..52305ce790126500672211ec1c528b423d480516 --- /dev/null +++ b/src/structure/structure_params.ts @@ -0,0 +1,42 @@ +import { Result } from "../base"; +import { Nub } from "../nub"; +import { ComputeNodeType, ParamDefinition, ParamDomain, ParamDomainValue, ParamsEquation } from "../param"; +import { Message } from "../util/message"; + +/** + * Common parameters of hydraulic structure equations + */ +export class StructureParams extends ParamsEquation { + /** Débit */ + public Q: ParamDefinition; + + /** Tirant d'eau amont */ + public h1: ParamDefinition; + + /** Tirant d'eau aval */ + public h2: ParamDefinition; + + /** Ouverture de la vanne + * @note Pour un seuil cette valeur vaut Infinity + */ + public W: ParamDefinition; + + /** + * Paramètres communs à toutes les équations de structure + * @param rQ Débit (m3/s) + * @param rh1 Hauteur amont au dessus de la crête (m) + * @param rh2 Hauteur aval au dessus de la crête (m) + * @param rW Ouverture de vanne (m) (infinity pour un seuil) + */ + constructor(rQ: number, rh1: number, rh2: number, rW: number = Infinity ) { + super(); + this.Q = new ParamDefinition(ComputeNodeType.CondDistri, "Q", ParamDomainValue.POS_NULL, rQ); + this.addParamDefinition(this.Q); + this.h1 = new ParamDefinition(ComputeNodeType.CondDistri, "h1", ParamDomainValue.POS_NULL, rh1); + this.addParamDefinition(this.h1); + this.h2 = new ParamDefinition(ComputeNodeType.CondDistri, "h2", ParamDomainValue.POS_NULL, rh2); + this.addParamDefinition(this.h2); + this.W = new ParamDefinition(ComputeNodeType.CondDistri, "W", ParamDomainValue.POS_NULL, rW); + this.addParamDefinition(this.W); + } +} diff --git a/src/structure/structure_weir_free.ts b/src/structure/structure_weir_free.ts new file mode 100644 index 0000000000000000000000000000000000000000..fd1246406f35b38b10429ab821e34edc7d8f3831 --- /dev/null +++ b/src/structure/structure_weir_free.ts @@ -0,0 +1,24 @@ +import { Result } from "../base"; +import { RectangularStructure } from "./rectangular_structure"; +import { RectangularStructureParams } from "./rectangular_structure_params"; +import { Structure, StructureFlowMode, StructureFlowRegime } from "./structure"; + +export { RectangularStructureParams }; + +/** + * Equation classique seuil dénoyé + */ +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 { + const res: Result = super.Equation(sVarCalc); + // TODO : Warning si les conditions hydrauliques ne correspondent pas à un seuil dénoyé + res.extraVar.Regime = StructureFlowRegime.FREE; + res.extraVar.Mode = StructureFlowMode.WEIR; + res.vCalc = this.prms.Cd.v * this.prms.L.v * Structure.R2G * Math.pow(this.prms.h1.v, 1.5); + return res; + } +}