An error occurred while loading the file. Please try again.
-
Dorchies David authoredd6b482ad
import { Nub } from "../nub";
import { ParamCalculability } from "../param/param-definition";
import { ParamValueMode } from "../param/param-value-mode";
import { Result } from "../util/result";
import { MacrorugoParams } from "./macrorugo_params";
export { MacrorugoParams };
export enum MacroRugoFlowType {
EMERGENT,
QUASI_EMERGENT,
IMMERGE
}
export class MacroRugo extends Nub {
private static readonly g = 9.81;
/** nu: water kinematic viscosity */
private static readonly nu = 1E-6;
// Water at 20 °C has a kinematic viscosity of about 10−6 m2·s−1
// (https://en.wikipedia.org/wiki/Viscosity#Kinematic_viscosity,_%CE%BD)
/** Ratio between the width (perpendicular to flow) and the lenght (parallel to flow) of a cell (-) */
private static readonly fracAxAy = 1;
/** Limit between emergent and submerged flow */
private static readonly limitSubmerg = 1.1;
/** Rugosité de fond (m) */
private ks: number;
/** Averaged velocity (m.s-1) */
private U0: number;
/** Velocity at the bed (m.s-1) */
private u0: number;
private _cache: { [key: string]: number };
constructor(prms: MacrorugoParams, dbg: boolean = false) {
super(prms, dbg);
this._cache = {};
}
/**
* paramètres castés au bon type
*/
get prms(): MacrorugoParams {
return this._prms as MacrorugoParams;
}
/**
* Calcul du débit total, de la cote amont ou aval ou d'un paramètre d'une structure
* @param sVarCalc Nom du paramètre à calculer :
* "Q", "Z1", "Z2" ou "n.X" avec "n" l'index de l'ouvrage et "X" son paramètre
* @param rInit Valeur initiale
* @param rPrec Précision attendue
*/
public Calc(sVarCalc: string, rInit?: number, rPrec: number = 0.001): Result {
/** @todo Voir pour déclarer le paramètre en calcul dans nub */
this.getParameter(sVarCalc).valueMode = ParamValueMode.CALCUL;
const r: Result = super.Calc(sVarCalc, rInit, rPrec);
// Ajout des résultats complémentaires
// Cote de fond aval
r.extraResults.ZF2 = this.prms.ZF1.v - this.prms.If.v * this.prms.L.v;
// Vitesse débitante
r.extraResults.Vdeb = this.V(this.prms.Q) / this.prms.B.v / this.prms.Y.v;
// Froude
r.extraResults.Fr = r.extraResults.Vdeb / (1 - Math.sqrt(MacroRugo.fracAxAy * this.prms.C.v))
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/ Math.sqrt(MacroRugo.g * this.prms.Y.v);
// Vitesse maximale
r.extraResults.V = r.extraResults.Vdeb * this.calc_fFr(r.extraResults.Vdeb);
// Puissance dissipée
r.extraResults.PV = 1000 * MacroRugo.g * this.V(this.prms.Q) / this.prms.B.v * this.prms.If.v;
// Type d'écoulement
if (this.prms.Y.v / this.prms.PBH.v < 1) {
r.extraResults.ENUM_MacroRugoFlowType = MacroRugoFlowType.EMERGENT;
} else if (this.prms.Y.v / this.prms.PBH.v < MacroRugo.limitSubmerg) {
r.extraResults.ENUM_MacroRugoFlowType = MacroRugoFlowType.QUASI_EMERGENT;
} else {
r.extraResults.ENUM_MacroRugoFlowType = MacroRugoFlowType.IMMERGE;
}
// Vitesse et débit du guide technique
let cQ: [number, number, number, number];
let cV: [number, number, number];
let hdk: number;
if (this.prms.Y.v / this.prms.PBH.v > MacroRugo.limitSubmerg) {
cQ = [0.955, 2.282, 0.466, -0.23];
hdk = this.prms.PBH.v;
} else {
hdk = this.prms.PBD.v;
if (Math.abs(this.prms.Cd0.v - 2) < 0.05) {
cQ = [0.648, 1.084, 0.56, -0.456];
cV = [3.35, 0.27, 0.53];
} else {
cQ = [0.815, 1.45, 0.557, -0.456];
cV = [4.54, 0.32, 0.56];
}
}
r.extraResults.Q_GuideTech = cQ[0] * Math.pow(this.prms.Y.v / hdk, cQ[1]) *
Math.pow(this.prms.If.v, cQ[2]) * Math.pow(this.prms.C.v, cQ[3]) *
Math.sqrt(MacroRugo.g * this.prms.PBD.v) * this.prms.PBD.v * this.prms.B.v;
if (this.prms.Y.v / this.prms.PBH.v <= MacroRugo.limitSubmerg) {
r.extraResults.V_GuideTech = cV[0] * Math.pow(this.prms.Y.v / this.prms.PBD.v, cV[1]) *
Math.pow(this.prms.If.v, cQ[2]) * Math.sqrt(MacroRugo.g * this.prms.PBD.v);
}
return r;
}
public Equation(sVarCalc: string): Result {
const Q = uniroot(this.resolveQ, this, 0, 1E7) * this.prms.B.v;
return new Result(Q);
}
/**
* paramétrage de la calculabilité des paramètres
*/
protected setParametersCalculability() {
this.prms.ZF1.calculability = ParamCalculability.FREE;
this.prms.L.calculability = ParamCalculability.FREE;
this.prms.Ks.calculability = ParamCalculability.FREE;
this.prms.B.calculability = ParamCalculability.DICHO;
this.prms.If.calculability = ParamCalculability.DICHO;
this.prms.Q.calculability = ParamCalculability.EQUATION;
this.prms.Y.calculability = ParamCalculability.DICHO;
this.prms.C.calculability = ParamCalculability.DICHO;
this.prms.PBD.calculability = ParamCalculability.FREE;
this.prms.PBH.calculability = ParamCalculability.FREE;
this.prms.Cd0.calculability = ParamCalculability.FREE;
}
/**
* Equation from Cassan, L., Laurens, P., 2016. Design of emergent and submerged rock-ramp fish passes.
* Knowledge & Management of Aquatic Ecosystems 45.
* @param sVarCalc Variable à calculer
*/
private resolveQ(this: MacroRugo, Q: number): number {
// Reset cached variables depending on Q (or not...)
this._cache = {};
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
/** Longueur (m) */
const L: number = this.prms.L.v;
/** Tirant d'eau (m) */
const h: number = this.prms.Y.v;
/** Paramètre de bloc : Forme (1 pour rond, 2 pour carré)
* drag coefficient of a block considering a single block
* infinitely high with F ≪ 1;
*/
// tslint:disable-next-line:variable-name
const Cd0: number = this.prms.Cd0.v;
/** Concentration de blocs (-) */
const C: number = this.prms.C.v;
/** Paramètre de bloc : Diamètre (m) */
const D: number = this.prms.PBD.v;
/** Paramètre de bloc : Hauteur (m) */
const k: number = this.prms.PBH.v;
/** Pente (m/m) */
const S: number = this.prms.If.v;
const g = MacroRugo.g;
const kappa = 0.41; // von Karman constant
// U0 = Averaged velocity (m.s-1)
this.U0 = Q / this.prms.B.v / h;
/** Calulated average velocity */
let uMoy: number;
if (h / k > MacroRugo.limitSubmerg) {
// Submerged conditions
/** Velocity at the bed §2.3.2 Cassan et al., 2016 */
this.u0 = Math.sqrt(2 * g * S * D * this.R / (this.calcCd(this.calc_fFr(this.U0)) * C));
/** turbulent length scale (m) within the blocks layer (alpha_t) */
const alpha = uniroot(this.resolveAlpha_t, this, 1E-6, 100);
/** averaged velocity at the top of blocks (m.s-1) */
const uk = this.calcUz(alpha);
/** Equation (13) Cassan et al., 2016 */
const d = k - 1 / kappa * alpha * uk / this.ustar;
/** Equation (14) Cassan et al., 2016 */
const z0 = (k - d) * Math.exp(- kappa * uk / this.ustar);
/** Integral of Equation (12) Cassan et al., 2016 */
// tslint:disable-next-line:variable-name
const Qsup = this.ustar / kappa * (
(h - d) * (Math.log((h - d) / z0) - 1)
- ((k - d) * (Math.log((k - d) / z0) - 1))
);
// calcul intégrale dans la canopée----
// tslint:disable-next-line:variable-name
let Qinf: number = this.u0;
let u = this.u0;
let uOld: number;
const step = 0.1;
for (let z = step; z <= 1; z += step) {
uOld = u;
u = this.calcUz(alpha, z);
Qinf += (uOld + u) / 2;
}
Qinf = Qinf * step * k;
// Calcul de u moyen
uMoy = (Qinf + Qsup) / k;
} else {
// Emergent conditions
// Resolve equation (4) Cassan et al., 2016
uMoy = uniroot(this.resolveU0, this, 0, 1E7);
}
return this.U0 - uMoy;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
}
private get CdChD(): number {
if (this._cache.CdChD !== undefined) {
return this._cache.CdChD;
}
return this.calcCd(1) * this.prms.C.v * this.prms.PBH.v / this.prms.PBD.v;
}
/**
* sigma ratio between the block area in the x, y plane and D2
*/
private get sigma(): number {
if (this._cache.sigma !== undefined) {
return this._cache.sigma;
}
if (this.prms.Cd0.v === 2) {
return 1;
} else {
return Math.PI / 4;
}
}
private get R(): number {
if (this._cache.R !== undefined) {
return this._cache.R;
}
return (1 - this.sigma * this.prms.C.v);
}
/**
* Bed friction coefficient Equation (3) (Cassan et al., 2016)
*/
private calcCf(U0: number): number {
if (this.prms.Ks.v < 1E-6) {
// Between Eq (8) and (9) (Cassan et al., 2016)
const reynolds = U0 * this.prms.Y.v / MacroRugo.nu;
return 0.3164 / 4. * Math.pow(reynolds, -0.25);
} else {
// Equation (3) (Cassan et al., 2016)
return 2 / Math.pow(5.1 * Math.log10(this.prms.Y.v / this.prms.Ks.v - 1) + 6, 2);
}
}
/**
* Calculation of Cd : drag coefficient of a block under the actual flow conditions
* @param fFr
*/
private calcCd(fFr: number): number {
return this.prms.Cd0.v * (1 + 0.4 / Math.pow(this.prms.Y.v / this.prms.PBD.v, 2)) * fFr;
}
/**
* Calcul de Beta force ratio between drag and turbulent stress (Cassan et al. 2016 eq(8))
* \Beta = (k / alpha_t) (C_d C k / D) / (1 - \sigma C)
* @param alpha \alpha_t turbulent length scale (m) within the blocks layer
*/
private calcBeta(alpha: number): number {
return Math.sqrt(this.prms.PBH.v * this.CdChD / alpha / this.R);
}
/**
* Averaged velocity at a given vertical position (m.s-1)
* @param alpha turbulent length scale (m) within the blocks layer
* @param z dimensionless vertical position z / k
*/
private calcUz(alpha: number, z: number = 1): number {
const beta = this.calcBeta(alpha);
// Equation (9) Cassan et al., 2016