jalhyd
Version:
JaLHyd, a Javascript Library for Hydraulics
959 lines • 56.6 kB
JavaScript
"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