UNPKG

jalhyd

Version:

JaLHyd, a Javascript Library for Hydraulics

959 lines 56.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Espece = void 0; const internal_modules_1 = require("../internal_modules"); const internal_modules_2 = require("../internal_modules"); const internal_modules_3 = require("../internal_modules"); const internal_modules_4 = require("../internal_modules"); const internal_modules_5 = require("../internal_modules"); const internal_modules_6 = require("../internal_modules"); const internal_modules_7 = require("../internal_modules"); const internal_modules_8 = require("../internal_modules"); const internal_modules_9 = require("../internal_modules"); const internal_modules_10 = require("../internal_modules"); const internal_modules_11 = require("../internal_modules"); const internal_modules_12 = require("../internal_modules"); const internal_modules_13 = require("../internal_modules"); /** * Settings for a given fish species (or custom settings), to verify crossing capacities on fish passes. * Meant to be used with Verificateur. */ class Espece extends internal_modules_1.Nub { constructor(prms, dbg = false) { super(prms, dbg); this.setCalculatorType(internal_modules_2.CalculatorType.Espece); this._props.addObserver(this); // Diving jets in PAB are not supported by default this.divingJetSupported = internal_modules_13.DivingJetSupport.NOT_SUPPORTED; // defaults to CUSTOM mode, for GUI instanciation this.species = internal_modules_4.FishSpecies.SPECIES_CUSTOM; this.indexToCheck = 0; this.calculatedParam = this.prms.OK; this.resetDefaultCalculatedParam(); // presets // Source: Informations sur la Continuité Ecologique (ICE), Onema 2014 this.presets = {}; // PAB this.presets[internal_modules_2.CalculatorType.Pab] = {}; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_1] = { DHMaxS: 0.35, BMin: 0.3, PMinS: 1, LMinS: 2.5, DHMaxP: 0.75, PMinP: 1, HMin: 0.3, LMinP: 2, PVMaxPrec: 200, PVMaxLim: 250, DivingJetSupported: internal_modules_13.DivingJetSupport.SUPPORTED }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_2] = { DHMaxS: 0.35, BMin: 0.2, PMinS: 1, LMinS: 1.75, DHMaxP: 0.6, PMinP: 0.75, HMin: 0.2, LMinP: 1.25, PVMaxPrec: 200, PVMaxLim: 250, DivingJetSupported: internal_modules_13.DivingJetSupport.SUPPORTED }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_3a] = this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_3b] = { DHMaxS: 0.3, BMin: 0.4, PMinS: 1, HMin: 0.4, LMinS: 3.5, PVMaxPrec: 150, PVMaxLim: 200 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_3c] = { DHMaxS: 0.3, BMin: 0.15, PMinS: 1, HMin: 0.15, LMinS: 1.25, PVMaxPrec: 200, PVMaxLim: 250 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_4a] = { DHMaxS: 0.35, BMin: 0.2, PMinS: 1, LMinS: 1.75, DHMaxP: 0.4, PMinP: 0.75, HMin: 0.2, LMinP: 1.25, PVMaxPrec: 200, PVMaxLim: 250, DivingJetSupported: internal_modules_13.DivingJetSupport.SUPPORTED }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_4b] = { DHMaxS: 0.3, BMin: 0.15, PMinS: 0.75, LMinS: 1, DHMaxP: 0.3, PMinP: 0.75, HMin: 0.2, LMinP: 1, PVMaxPrec: 200, PVMaxLim: 250, DivingJetSupported: internal_modules_13.DivingJetSupport.SUPPORTED }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_5] = { DHMaxS: 0.3, BMin: 0.3, PMinS: 0.75, HMin: 0.2, LMinS: 2.5, PVMaxPrec: 150, PVMaxLim: 200 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_6] = { DHMaxS: 0.3, BMin: 0.2, PMinS: 0.75, LMinS: 1.75, DHMaxP: 0.3, PMinP: 0.75, HMin: 0.2, LMinP: 1, PVMaxPrec: 200, PVMaxLim: 250, DivingJetSupported: internal_modules_13.DivingJetSupport.SUPPORTED }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_7a] = { DHMaxS: 0.3, BMin: 0.25, PMinS: 0.75, HMin: 0.2, LMinS: 2, PVMaxPrec: 150, PVMaxLim: 200 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_7b] = { DHMaxS: 0.3, BMin: 0.15, PMinS: 0.75, HMin: 0.15, LMinS: 1.25, PVMaxPrec: 130, PVMaxLim: 150 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_8a] = { DHMaxS: 0.25, BMin: 0.3, PMinS: 0.75, HMin: 0.2, LMinS: 2.5 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_8b] = { DHMaxS: 0.25, BMin: 0.3, PMinS: 0.75, HMin: 0.2, LMinS: 2.5, PVMaxPrec: 150, PVMaxLim: 200 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_8c] = { DHMaxS: 0.25, BMin: 0.3, PMinS: 0.75, HMin: 0.2, LMinS: 2.5, PVMaxPrec: 130, PVMaxLim: 150 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_8d] = { DHMaxS: 0.25, BMin: 0.3, PMinS: 0.75, HMin: 0.2, LMinS: 2.5, PVMaxPrec: 150, PVMaxLim: 200 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_9a] = { DHMaxS: 0.25, BMin: 0.25, PMinS: 0.75, HMin: 0.2, LMinS: 2, PVMaxPrec: 130, PVMaxLim: 150 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_9b] = { DHMaxS: 0.2, BMin: 0.15, PMinS: 0.5, HMin: 0.2, LMinS: 1.25, PVMaxPrec: 130, PVMaxLim: 150 }; this.presets[internal_modules_2.CalculatorType.Pab][internal_modules_4.FishSpecies.SPECIES_10] = { DHMaxS: 0.2, BMin: 0.15, PMinS: 0.5, HMin: 0.2, LMinS: 1.25, PVMaxPrec: 100, PVMaxLim: 150 }; // PAR Simulation this.presets[internal_modules_2.CalculatorType.ParSimulation] = {}; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_1] = { YMinSB: 0.2, YMinPB: 0.3 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_2] = { YMinSB: 0.15, YMinPB: 0.25 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_3a] = { YMinSB: 0.2, YMinPB: 0.3 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_3b] = { YMinSB: 0.15, YMinPB: 0.25 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_3c] = { YMinSB: 0.1, YMinPB: 0.1 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_4a] = { YMinSB: 0.15, YMinPB: 0.25 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_4b] = { YMinSB: 0.1, YMinPB: 0.2 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_5] = { YMinSB: 0.2, YMinPB: 0.3 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_6] = { YMinSB: 0.15, YMinPB: 0.25 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_7a] = { YMinSB: 0.15, YMinPB: 0.25 }; this.presets[internal_modules_2.CalculatorType.ParSimulation][internal_modules_4.FishSpecies.SPECIES_7b] = { YMinSB: 0.1, YMinPB: 0.1 }; // MacroRugo this.presets[internal_modules_2.CalculatorType.MacroRugo] = {}; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_1] = { YMin: 0.4, VeMax: 2.5 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_2] = { YMin: 0.3, VeMax: 2.5 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_3a] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_3b] = { YMin: 0.4, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_3c] = { YMin: 0.15, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_4a] = { YMin: 0.3, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_4b] = { YMin: 0.2, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_5] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_6] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_7a] = { YMin: 0.3, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_7b] = { YMin: 0.15, VeMax: 2 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_8a] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_8b] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_8c] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_8d] = { YMin: 0.3, VeMax: 1.5 }; this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_9a] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_9b] = this.presets[internal_modules_2.CalculatorType.MacroRugo][internal_modules_4.FishSpecies.SPECIES_10] = { YMin: 0.2, VeMax: 1.5 }; } get prms() { return this._prms; } get species() { return this._props.getPropValue("species"); } /** Changing the fish species will load adequate predefined values */ set species(s) { this.setPropValue("species", s); } set passToCheck(p) { this._passToCheck = p; this.loadPredefinedParametersValues(); } get divingJetSupported() { return this.getPropValue("divingJetSupported"); } set divingJetSupported(i) { this.setPropValue("divingJetSupported", i); } /** * Check that all given criteria are defined before controlling their values * @param symbols list of symbols of criteria that have to be defined * @return undefined if all criteria are present, a Result with appropriate error * log messages otherwise */ checkCriteriaPresence(symbols) { const r = new internal_modules_5.Result(); r.addResultElement(new internal_modules_10.ResultElement()); let error = false; for (const s of symbols) { if (this.getParameter(s).singleValue === undefined) { error = true; const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_MISSING_CRITERION); m.extraVar.var_criterion = s; r.log.add(m); } } if (error) { return r; } else { return undefined; // everything OK } } /** Returns 1 if the fish can go through the pass, 0 if it cannot */ Equation() { // default result is 1 (OK) const res = new internal_modules_5.Result(1, this); const sp = this.species; // detect pass characteristics and species let pt = this._passToCheck.calcType; // MacroRugoCompound is just a repetition of the MacroRugo check if (pt === internal_modules_2.CalculatorType.MacroRugoCompound) { pt = internal_modules_2.CalculatorType.MacroRugo; } // get result to examine const r = this._passToCheck.result.resultElements[this.indexToCheck]; if (r === undefined) { throw new Error(`Espece.Equation(): pass to check has no resultElements[${this.indexToCheck}]`); } // is there a valid preset for the pass type / species couple ? if (sp !== internal_modules_4.FishSpecies.SPECIES_CUSTOM && this.presets[pt][sp] === undefined) { res.vCalc = 0; res.log.add(new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_NO_PRESET)); return res; } else { // normal processing switch (this._passToCheck.calcType) { // not pt, to detect MacroRugoCompound case internal_modules_2.CalculatorType.Pab: const passB = this._passToCheck; // Check criteria presence (depends on jet types) let hasAtLeastOneSurfaceJet = false; let hasAtLeastOneDivingJet = false; for (const wall of passB.children) { hasAtLeastOneSurfaceJet = hasAtLeastOneSurfaceJet || this.hasJet(wall, internal_modules_6.StructureJetType.SURFACE); hasAtLeastOneDivingJet = hasAtLeastOneDivingJet || this.hasJet(wall, internal_modules_6.StructureJetType.PLONGEANT); } hasAtLeastOneDivingJet = hasAtLeastOneDivingJet || this.hasJet(passB.downWall, internal_modules_6.StructureJetType.PLONGEANT); let cpRetPAB; let criteriaToCheck = [/* "PVMaxPrec", "PVMaxLim", */ "HMin", "BMin"]; if (hasAtLeastOneSurfaceJet) { criteriaToCheck = criteriaToCheck.concat(["DHMaxS", "PMinS", "LMinS"]); } if (hasAtLeastOneDivingJet && this.divingJetSupported === internal_modules_13.DivingJetSupport.SUPPORTED) { criteriaToCheck = criteriaToCheck.concat(["DHMaxP", "PMinP", "LMinP"]); } if (criteriaToCheck.length > 0) { cpRetPAB = this.checkCriteriaPresence(criteriaToCheck); if (cpRetPAB !== undefined) { return cpRetPAB; } } // A -- walls let cloisonNumber = 1; for (const wall of passB.children) { const iRes = wall.result.resultElements[this.indexToCheck]; const hasSJet = this.hasJet(wall, internal_modules_6.StructureJetType.SURFACE); const hasPJet = this.hasJet(wall, internal_modules_6.StructureJetType.PLONGEANT); // Wall crossability array, one element for each device, by default every device is crossable; // marked only when device is receiving a Warning, to avoid errors redundancy const wca = []; wca.length = wall.structures.length; wca.fill(true); // 0. diving jet support this.checkDivingJetSupport(wall, res, wca); // 1. falls this.checkFalls(wall, iRes, res, wca, hasSJet, hasPJet); // 2. weirs and slots witdh this.checkWeirsAndSlotsWidth(wall, res, wca); // 3. basins depth this.checkBasinDepth(wall, iRes, res, wca, hasSJet, hasPJet); // diving jets only: depth < 2x fall if (hasPJet) { if ((0, internal_modules_12.isLowerThan)(iRes.values.YMOY, (2 * iRes.values.DH), 1e-3)) { let m; // diving jet fails, but surface jet exists if (hasSJet) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_YMOY_2_DH); const failingDevices = this.getDevicesHavingJet(wall, internal_modules_6.StructureJetType.PLONGEANT); for (const idx of failingDevices) { wca[idx] = false; } } else { m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_YMOY_2_DH); res.vCalc = 0; } ; m.parent = iRes.log; // trick to prefix message with Nub position inside parent m.extraVar.PB = iRes.values.YMOY; m.extraVar.DH = iRes.values.DH; res.log.add(m); } } // 4. head on weirs this.checkHeadOnWeirs(wall, res, wca); // 5. basins length this.checkBasinLength(wall, res, wca, hasSJet, hasPJet); // 6. dissipated power /* this.checkDissipatedPowerPAB(wall, res); */ // 7. orifices this.checkOrifices(wall, res, wca); // check crossability let ok = false; for (const devC of wca) { ok = ok || devC; } if (!ok) { const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_WALL_NOT_CROSSABLE); m.extraVar.N = String(cloisonNumber); // keep the "+1" for readability res.log.add(m); } cloisonNumber++; } // B -- downwall const dw = passB.downWall; const iResDw = dw.result.resultElements[this.indexToCheck]; const hasSJetDw = this.hasJet(dw, internal_modules_6.StructureJetType.SURFACE); const hasPJetDw = this.hasJet(dw, internal_modules_6.StructureJetType.PLONGEANT); // Downwall crossability array, one element for each device, by default every device is crossable; // marked only when device is receiving a Warning, to avoid errors redundancy const dwca = []; dwca.length = dw.structures.length; dwca.fill(true); // 0. diving jet support this.checkDivingJetSupport(dw, res, dwca); // 1. falls this.checkFalls(dw, iResDw, res, dwca, hasSJetDw, hasPJetDw); // 2. weirs and slots witdh this.checkWeirsAndSlotsWidth(dw, res, dwca); // 3. head on weirs this.checkHeadOnWeirs(dw, res, dwca); // 4. orifices this.checkOrifices(dw, res, dwca); // check crossability let okDw = false; for (const devC of dwca) { okDw = okDw || devC; } if (!okDw) { const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_DW_NOT_CROSSABLE); res.log.add(m); } break; case internal_modules_2.CalculatorType.ParSimulation: const passR = this._passToCheck; // Check criteria presence, depending on baffle type let parCriteria = []; if ([internal_modules_8.ParType.PLANE, internal_modules_8.ParType.FATOU].includes(passR.parType)) { parCriteria = ["YMinPB"]; } else if ([internal_modules_8.ParType.SUPERACTIVE, internal_modules_8.ParType.CHEVRON].includes(passR.parType)) { parCriteria = ["YMinSB"]; } if (parCriteria.length > 0) { const cpRetPAR = this.checkCriteriaPresence(parCriteria); if (cpRetPAR !== undefined) { return cpRetPAR; } } // 1. species groups 3a, 3b, 7b are discouraged if ([internal_modules_4.FishSpecies.SPECIES_3a, internal_modules_4.FishSpecies.SPECIES_3b, internal_modules_4.FishSpecies.SPECIES_7b].includes(this.species)) { res.log.add(new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAR_SPECIES_GROUP)); } // 2. water level let minY = 0; // if this.prms.YMin(P|S)B is undefined, "skip test" if ([internal_modules_8.ParType.PLANE, internal_modules_8.ParType.FATOU].includes(passR.parType)) { minY = this.prms.YMinPB.singleValue; } else if ([internal_modules_8.ParType.SUPERACTIVE, internal_modules_8.ParType.CHEVRON].includes(passR.parType)) { minY = this.prms.YMinSB.singleValue; } if ((0, internal_modules_12.isLowerThan)(r.values.h, minY, 1e-3)) { res.vCalc = 0; const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAR_YMIN); m.extraVar.h = r.values.h; m.extraVar.minY = minY; res.log.add(m); } break; case internal_modules_2.CalculatorType.MacroRugoCompound: const passMRC = this._passToCheck; // Check criteria presence const cpRetMRC = this.checkCriteriaPresence(["YMin", "VeMax"]); if (cpRetMRC !== undefined) { return cpRetMRC; } let atLeastOneOK = false; let apronNumber = 1; const consecutiveWidths = []; let previousApronFailed = true; // loop on aprons with MacroRugo check; at least one is required for (const mr of passMRC.children) { const mrRes = this.checkMacroRugo(mr, mr.result.resultElements[this.indexToCheck], res, apronNumber); if (mrRes === 1) { atLeastOneOK = true; if (previousApronFailed) { consecutiveWidths.push(0); previousApronFailed = false; } consecutiveWidths[consecutiveWidths.length - 1] += mr.prms.B.v; } else { previousApronFailed = true; } apronNumber++; } if (!atLeastOneOK) { res.vCalc = 0; res.log.add(new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_MRC_AT_LEAST_ONE_APRON)); } else { // Check max. crossable width const maxCrossableWidth = Math.max(...consecutiveWidths); const patternWidth = passMRC.prms.PBD.v / Math.sqrt(passMRC.prms.C.v); if ((0, internal_modules_12.isLowerThan)(maxCrossableWidth, patternWidth, 1e-3)) { res.vCalc = 0; const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_MRC_CROSSABLE_WIDTH); m.extraVar.width = maxCrossableWidth; m.extraVar.patternWidth = patternWidth; res.log.add(m); } else { const m = new internal_modules_7.Message(internal_modules_7.MessageCode.INFO_VERIF_MRC_CROSSABLE_WIDTH); m.extraVar.width = maxCrossableWidth; res.log.add(m); } } break; case internal_modules_2.CalculatorType.MacroRugo: // Check criteria presence const cpRetMR = this.checkCriteriaPresence(["YMin", "VeMax"]); if (cpRetMR !== undefined) { return cpRetMR; } res.vCalc = this.checkMacroRugo(this._passToCheck, r, res); break; default: // should never happen throw new Error(`Espece.Equation(): undefined pass type ${internal_modules_2.CalculatorType[this._passToCheck.calcType]}`); } } return res; } update(sender, data) { if (data.action === "propertyChange") { if (data.name === "species") { this.loadPredefinedParametersValues(); // no parameter visibility update: GUI will never show anything but SPECIES_CUSTOM mode, // where all parameters are visible } } } /** * Checks the diving jet support on every structure of the given wall of a Pab * @param wall the current wall to check * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index */ checkDivingJetSupport(wall, res, ca) { // if diving jets are not supported by the current species if (this.divingJetSupported === internal_modules_13.DivingJetSupport.NOT_SUPPORTED) { const devices = this.getDevicesHavingJet(wall, internal_modules_6.StructureJetType.PLONGEANT); // mark every device having a diving jet as not crossable for (const idx of devices) { ca[idx] = false; } // if every device is failing, add an error for the whole wall if (devices.length === wall.structures.length) { let m; m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_DIVING_JET_NOT_SUPPORTED); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent res.log.add(m); } else { // add a warning for every device having a diving jet for (const idx of devices) { let m; m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_DIVING_JET_NOT_SUPPORTED); m.parent = wall.structures[idx].result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent res.log.add(m); } } } } /** * Checks the falls on every structure of the given wall of a Pab * @param wall the current wall to check * @param iRes the current result element to check on the wall result * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index * @param hasSJet true if current wall has at least one device with a surface jet (or an Orifice) * @param hasPJet true if current wall has at least one device with a diving jet */ checkFalls(wall, iRes, res, ca, hasSJet, hasPJet) { const fallSJetFails = (hasSJet && this.prms.DHMaxS.singleValue !== undefined && (0, internal_modules_12.isGreaterThan)(iRes.values.DH, this.prms.DHMaxS.singleValue, 1e-3)); const fallPJetFails = (this.divingJetSupported === internal_modules_13.DivingJetSupport.SUPPORTED && hasPJet && this.prms.DHMaxP.singleValue !== undefined && (0, internal_modules_12.isGreaterThan)(iRes.values.DH, this.prms.DHMaxP.singleValue, 1e-3)); // error cases if (fallSJetFails || fallPJetFails) { let m; // everything fails: error if (fallSJetFails && fallPJetFails) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_DHMAX); m.parent = iRes.log; // trick to prefix message with Nub position inside parent res.vCalc = 0; m.extraVar.maxDHS = this.prms.DHMaxS.singleValue; m.extraVar.maxDHP = this.prms.DHMaxP.singleValue; } else { // only one type of jet fails, the other type may be present or not const failingJetType = fallSJetFails ? internal_modules_6.StructureJetType.SURFACE : internal_modules_6.StructureJetType.PLONGEANT; // one jet fails, but other jet is present (and succeeds) if ((fallSJetFails && hasPJet) || (fallPJetFails && hasSJet)) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_DHMAX_JET); m.parent = iRes.log; // trick to prefix message with Nub position inside parent const failingDevices = this.getDevicesHavingJet(wall, failingJetType); for (const idx of failingDevices) { ca[idx] = false; } } else { // one jet fails and there is no other jet m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_DHMAX_JET); m.parent = iRes.log; // trick to prefix message with Nub position inside parent res.vCalc = 0; } m.extraVar.maxDH = fallSJetFails ? this.prms.DHMaxS.singleValue : this.prms.DHMaxP.singleValue; m.extraVar.jetType = String(failingJetType); } m.extraVar.DH = iRes.values.DH; res.log.add(m); } // else everything ok } /** * Checks the basin depth on every structure of the given wall of a Pab * @param wall the current wall to check * @param iRes the current result element to check on the wall result * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index * @param hasSJet true if current wall has at least one device with a surface jet (or an Orifice) * @param hasPJet true if current wall has at least one device with a diving jet */ checkBasinDepth(wall, iRes, res, ca, hasSJet, hasPJet) { const fallSJetFails = (hasSJet && this.prms.PMinS.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(iRes.values.YMOY, this.prms.PMinS.singleValue, 1e-3)); const fallPJetFails = (this.divingJetSupported === internal_modules_13.DivingJetSupport.SUPPORTED && hasPJet && this.prms.PMinP.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(iRes.values.YMOY, this.prms.PMinP.singleValue, 1e-3)); // error cases if (fallSJetFails || fallPJetFails) { let m; // everything fails: error if (fallSJetFails && fallPJetFails) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_YMOY); m.parent = iRes.log; // trick to prefix message with Nub position inside parent res.vCalc = 0; m.extraVar.minPBS = this.prms.PMinS.singleValue; m.extraVar.minPBP = this.prms.PMinP.singleValue; } else { // only one type of jet fails, the other type may be present or not const failingJetType = fallSJetFails ? internal_modules_6.StructureJetType.SURFACE : internal_modules_6.StructureJetType.PLONGEANT; // other jet is present (and succeeds) if ((fallSJetFails && hasPJet) || (fallPJetFails && hasSJet)) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_YMOY_JET); m.parent = iRes.log; // trick to prefix message with Nub position inside parent const failingDevices = this.getDevicesHavingJet(wall, failingJetType); for (const idx of failingDevices) { ca[idx] = false; } } else { // there is no other jet m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_YMOY_JET); m.parent = iRes.log; // trick to prefix message with Nub position inside parent res.vCalc = 0; } m.extraVar.minPB = fallSJetFails ? this.prms.PMinS.singleValue : this.prms.PMinP.singleValue; m.extraVar.jetType = String(failingJetType); } m.extraVar.PB = iRes.values.YMOY; res.log.add(m); } // else everything ok } /** * Checks the basin length on every structure of the given wall of a Pab * @param wall the current wall to check * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index * @param hasSJet true if current wall has at least one device with a surface jet (or an Orifice) * @param hasPJet true if current wall has at least one device with a diving jet */ checkBasinLength(wall, res, ca, hasSJet, hasPJet) { const fallSJetFails = (hasSJet && this.prms.LMinS.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(wall.prms.LB.singleValue, this.prms.LMinS.singleValue, 1e-3)); const fallPJetFails = (this.divingJetSupported === internal_modules_13.DivingJetSupport.SUPPORTED && hasPJet && this.prms.LMinP.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(wall.prms.LB.singleValue, this.prms.LMinP.singleValue, 1e-3)); // error cases if (fallSJetFails || fallPJetFails) { let m; // everything fails: error if (fallSJetFails && fallPJetFails) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_LMIN); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent res.vCalc = 0; m.extraVar.minLBS = this.prms.LMinS.singleValue; m.extraVar.minLBP = this.prms.LMinP.singleValue; ca.fill(false); // no device is crossable } else { // only one type of jet fails, the other type may be present or not const failingJetType = fallSJetFails ? internal_modules_6.StructureJetType.SURFACE : internal_modules_6.StructureJetType.PLONGEANT; // other jet is present (and succeeds) if ((fallSJetFails && hasPJet) || (fallPJetFails && hasSJet)) { m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_LMIN_JET); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent const failingDevices = this.getDevicesHavingJet(wall, failingJetType); for (const idx of failingDevices) { ca[idx] = false; } } else { // there is no other jet m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_LMIN_JET); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent res.vCalc = 0; } m.extraVar.minLB = fallSJetFails ? this.prms.LMinS.singleValue : this.prms.LMinP.singleValue; m.extraVar.jetType = String(failingJetType); } m.extraVar.LB = wall.prms.LB.singleValue; res.log.add(m); } // else everything ok } /** * Checks the weirs and slots widths on every structure of the given wall of a Pab * @param wall the Pab wall to check * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index */ checkWeirsAndSlotsWidth(wall, res, ca) { let structureNumber = 1; for (const device of wall.structures) { const hasOtherDevicesThanWeirs = (this.hasJet(wall, [internal_modules_6.StructureJetType.PLONGEANT]) || (this.getDevicesHavingLaw(wall, [internal_modules_11.LoiDebit.WeirVillemonte, internal_modules_11.LoiDebit.WeirSubmergedLarinier]).length < wall.structures.length)); const hasOtherDevicesThanOrifice = (this.hasJet(wall, [internal_modules_6.StructureJetType.PLONGEANT]) || (this.getDevicesHavingLaw(wall, internal_modules_11.LoiDebit.OrificeSubmerged).length < wall.structures.length)); const iRes = device.result.resultElements[this.indexToCheck]; const jt = iRes.values.ENUM_StructureJetType; if (jt !== internal_modules_6.StructureJetType.PLONGEANT) { // Surface jets: for "Villemonte 1947" ("échancrure") or "Fente noyée (Larinier 1992)" ("fente") only if ([internal_modules_11.LoiDebit.WeirVillemonte, internal_modules_11.LoiDebit.WeirSubmergedLarinier].includes(device.loiDebit)) { const structParams = device.prms; if (this.prms.BMin.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(structParams.L.v, this.prms.BMin.singleValue, 1e-3)) { let m; if (hasOtherDevicesThanWeirs) { ca[structureNumber - 1] = false; // device is not crossable m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_BMIN); m.parent = device.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent } else { res.vCalc = 0; m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_BMIN); m.parent = device.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent } m.extraVar.L = structParams.L.v; m.extraVar.minB = this.prms.BMin.singleValue; res.log.add(m); } } else if (device.loiDebit === internal_modules_11.LoiDebit.OrificeSubmerged) { const structParams = device.prms; // Orifices (no jet) if (this.prms.BMin.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(structParams.S.v, Math.pow(this.prms.BMin.singleValue, 2), 1e-3)) { let m; if (hasOtherDevicesThanOrifice) { ca[structureNumber - 1] = false; // device is not crossable m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_SMIN); m.parent = device.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent } else { res.vCalc = 0; m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_SMIN); m.parent = device.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent } m.extraVar.S = structParams.S.v; m.extraVar.minS = Math.pow(this.prms.BMin.singleValue, 2); res.log.add(m); } } } structureNumber++; } } /** * Checks the head on weirs on every structure of the given wall of a Pab * @param wall the Pab wall to check * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index */ checkHeadOnWeirs(wall, res, ca) { let structureNumber = 1; for (const device of wall.structures) { let zdv = device.prms.ZDV.singleValue; // if device is a regulated weir, get calculated ZDV at current iteration from parent downWall if (internal_modules_11.loiAdmissiblesCloisonAval.VanneLevante.includes(device.getPropValue("loiDebit"))) { zdv = device.parent.result.resultElements[this.indexToCheck].values.ZDV; } // do not use device.prms.h1.v, that contains only the latest calculated value if pass is variyng const h1 = wall.result.resultElements[this.indexToCheck].vCalc - zdv; /* console.log( `wall ${wall.findPositionInParent() + 1} / device ${structureNumber} : h1=${h1}, ZDV=${zdv}, class=${device.constructor.name}` ); */ if (this.prms.HMin.singleValue !== undefined && (0, internal_modules_12.isLowerThan)(h1, this.prms.HMin.singleValue, 1e-3)) { let m; ca[structureNumber - 1] = false; // device is not crossable m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_HMIN); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent m.extraVar.h1 = Math.max(0, h1); m.extraVar.minH = this.prms.HMin.singleValue; res.log.add(m); } structureNumber++; } } /** * Checks the dissipated power on the given wall of a Pab * @param wall the Pab wall to check * @param res the current result to add logs to, and set value */ checkDissipatedPowerPAB(wall, res) { const pv = wall.result.resultElements[this.indexToCheck].values.PV; if (this.prms.PVMaxLim.singleValue !== undefined && (0, internal_modules_12.isGreaterThan)(pv, this.prms.PVMaxLim.singleValue, 1e-3)) { res.vCalc = 0; const m = new internal_modules_7.Message(internal_modules_7.MessageCode.ERROR_VERIF_PAB_PVMAX); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent m.extraVar.PV = pv; m.extraVar.maxPV = this.prms.PVMaxLim.singleValue; res.log.add(m); } else if (this.prms.PVMaxPrec.singleValue !== undefined && (0, internal_modules_12.isGreaterThan)(pv, this.prms.PVMaxPrec.singleValue, 1e-3)) { res.vCalc = 0; const m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_PVMAX); m.parent = wall.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent m.extraVar.PV = pv; m.extraVar.maxPV = this.prms.PVMaxPrec.singleValue; res.log.add(m); } } /** * Marks orifices as not supposed to be crossable, with a warning (jalhyd#249) * @param wall the Pab wall to check * @param res the current result to add logs to, and set value * @param ca crossability array; mark non-crossable devices with "false" value at their index */ checkOrifices(wall, res, ca) { let structureNumber = 1; for (const device of wall.structures) { // a structure is considered an orifice if its flow mode is "Orifice" if (device.result.resultElements[this.indexToCheck].values.ENUM_StructureFlowMode === internal_modules_6.StructureFlowMode.ORIFICE) { let m; ca[structureNumber - 1] = false; // device is not crossable m = new internal_modules_7.Message(internal_modules_7.MessageCode.WARNING_VERIF_PAB_ORIFICE); m.parent = device.result.resultElements[this.indexToCheck].log; // trick to prefix message with Nub position inside parent res.log.add(m); } structureNumber++; } } /** * Returns true if given wall has at least one device with a jet type among given jetTypes */ hasJet(wall, jetTypes) { if (!Array.isArray(jetTypes)) { jetTypes = [jetTypes]; } for (const device of wall.structures) { const deviceJetType = device.result.resultElements[this.indexToCheck].values.ENUM_StructureJetType; if (jetTypes.includes(deviceJetType)) { return true; } } return false; } /** * Returns indexes of the devices having given jet type, on the given wall * @param wall wall to check devices on * @param t jet type */ getDevicesHavingJet(wall, t) { const idxs = []; for (let i = 0; i < wall.structures.length; i++) { const deviceJetType = wall.structures[i].result.resultElements[this.indexToCheck].values.ENUM_StructureJetType; if (deviceJetType === t) { idxs.push(i); } } return idxs; } /** * Returns indexes of the devices having given discharge law, on the given wall * @param wall wall to check devices on * @param l discharge law */ getDevicesHavingLaw(wall, l) { const idxs = []; if (!Array.isArray(l)) { l = [l]; } for (let i = 0; i < wall.structures.length; i++) { if (l.includes(wall.structures[i].loiDebit)) { idxs.push(i); } } return idxs; } /** * Checks a MacroRugo pass (factorized to use when checking MacroRugoCompound) * @param pass the MacroRugo pass to check * @param passResult the current result of the pass to check * @param verifResult the result of the check, to add logs to * @param apronNumber if def