An error occurred while loading the file. Please try again.
-
Grand Francois authored5dc07a45
import { round, XOR } from "./base";
import { Dichotomie } from "./dichotomie";
import { Nub } from "./nub";
import { ParamCalculability, ParamDefinition, ParamDomainValue, ParamsEquation } from "./param";
import { acSection, ParamsSection } from "./section/section_type";
import { cLog } from "./util/log";
import { Message, MessageCode } from "./util/message";
import { Result } from "./util/result";
import { ResultElement } from "./util/resultelement";
export enum MethodeResolution {
Trapezes, EulerExplicite, RungeKutta4
}
/**
* paramètres pour les courbes de remous
*/
export class CourbeRemousParams extends ParamsEquation {
/**
* section associée
*/
private _section: acSection;
/**
* Débit amont
*/
// private _Qamont: ParamDefinition;
/**
* Tirant imposé à l'amont
*/
private _Yamont: ParamDefinition;
/**
* Tirant imposé à l'aval
*/
private _Yaval: ParamDefinition;
/**
* Longueur du bief
*/
private _Long: ParamDefinition;
/**
* Pas de discrétisation de l'espace (positif en partant de l'aval, négatif en partant de l'amont)
*/
private _Dx: ParamDefinition;
/**
* Méthode de résolution de l'équation différentielle
*/
private _methodeResolution: MethodeResolution;
constructor(s: acSection, rYamont: number, rYAval: number, rLong: number, rDx: number, meth: MethodeResolution) {
super();
this._section = s;
this._Yamont = new ParamDefinition("Yamont", ParamDomainValue.POS, rYamont);
this._Yaval = new ParamDefinition("Yaval", ParamDomainValue.POS, rYAval);
this._Long = new ParamDefinition("Long", ParamDomainValue.POS, rLong);
this._Dx = new ParamDefinition("Dx", ParamDomainValue.POS, rDx);
this._methodeResolution = meth;
this.addParamDefinition(this._Yamont);
this.addParamDefinition(this._Yaval);
this.addParamDefinition(this._Long);
this.addParamDefinition(this._Dx);
this.addParamDefinitions(this._section.prms);
}
get Sn() {
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
return this._section;
}
get Yamont() {
return this._Yamont;
}
get Yaval() {
return this._Yaval;
}
get Long() {
return this._Long;
}
get Dx(): ParamDefinition {
return this._Dx;
}
get methodeResolution() {
return this._methodeResolution;
}
}
/**
* Calcul d'une courbe de remous
*/
// tslint:disable-next-line:max-classes-per-file
export class CourbeRemous extends Nub {
[key: string]: any; // pour pouvoir faire this['methode]();
private _debugDicho: boolean = false;
/**
* Journal de calcul
*/
// private _log: cLog;
private prmSect: ParamsSection;
/**
* Pas de discrétisation de l'espace (positif en partant de l'aval, négatif en partant de l'amont)
*/
private Dx: number;
constructor(crp: CourbeRemousParams, dbg: boolean = false) {
super(crp, dbg);
// this._log = crp.Sn.log;
this.prmSect = crp.Sn.prms;
this.Sn.Calc("Yc");
}
/**
* calcul de la ligne fluviale depuis l'aval (si possible)
*/
public calculFluvial(): ResultElement {
if (!this.Sn.HautCritique.ok) {
return new ResultElement(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
}
let res: ResultElement;
// Calcul depuis l'aval
if (this.Sn.HautCritique.vCalc <= this.prms.Yaval.v) {
// this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
this.debug(
`Condition limite aval (${this.prms.Yaval.v}) >= ` +
`Hauteur critique (${this.Sn.HautCritique}) : calcul de la partie fluviale à partir de l'aval`);
this.Dx = this.prms.Dx.v;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
res = this.calcul(this.prms.Yaval.v);
res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
} else {
this.debug(
"Condition limite aval (" + this.prms.Yaval.v +
") < Hauteur critique (" + this.Sn.HautCritique +
") : pas de calcul possible depuis l'aval");
// this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
res = new ResultElement();
res.addMessage(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
}
return res;
}
/**
* calcul de la ligne torrentielle depuis l'amont (si possible)
*/
public calculTorrentiel(): ResultElement {
if (!this.Sn.HautCritique.ok) {
return new ResultElement(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
}
let res: ResultElement;
// Calcul depuis l'amont
if (this.Sn.HautCritique.vCalc >= this.prms.Yamont.v) {
// this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
this.debug(
"Condition limite amont (" + this.prms.Yamont.v +
") <= Hauteur critique (" + this.Sn.HautCritique +
") : calcul de la partie torrentielle à partir de l'amont");
this.Dx = -this.prms.Dx.v;
res = this.calcul(this.prms.Yamont.v);
res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
} else {
// this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
this.debug(
"Condition limite amont (" + this.prms.Yamont.v +
") > Hauteur critique (" + this.Sn.HautCritique +
") : pas de calcul possible depuis l'amont");
res = new ResultElement();
res.addMessage(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
}
return res;
}
/**
* @param val_a_cal nom de la variable à calculer
*/
public calculRemous(val_a_cal: string):
// {
// "flu": { [key: number]: number; },
// "tor": { [key: number]: number; },
// "trX": string[],
// "tRes": { [key: number]: number }
// }
Result {
const res = new Result();
// let Yc: number = this.Sn.Calc("Yc");
const rYC = this.Sn.Calc("Yc");
if (!rYC.ok) {
res.addLog(rYC.log);
return res;
}
const Yc: number = rYC.vCalc;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
const rB: Result = this.Sn.Calc("B", this.Sn.prms.YB.v);
if (!rB.ok) {
res.addLog(rB.log);
return res;
}
let m: Message = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
// m.extraVar["B"] = this.Sn.Calc("B", this.Sn.prms.YB.v);
m.extraVar.B = rB.vCalc;
// this._log.add(m);
res.addMessage(m);
m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
m.extraVar.Yc = Yc;
// this._log.add(m);
res.addMessage(m);
const rYN = this.Sn.Calc("Yn");
if (!rYN.ok) {
res.addLog(rYN.log);
return res;
}
const Yn = rYN.vCalc;
m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
m.extraVar.Yn = Yn;
// this._log.add(m);
res.addMessage(m);
// this.debug("largeur berge " + this.Sn.Calc("B"));
// const rB2: Result = this.Sn.Calc("B")
// this.debug("largeur berge " + rB2.vCalc);
// this.debug("hauteur critique " + Yc);
// this.Sn.HautNormale = this.Sn.Calc("Yn");
// this.debug("hauteur normale " + this.Sn.HautNormale);
// this.debug("hauteur normale " + Yn);
// Calcul des courbes de remous
// let crbFlu: { [key: number]: number; } = this.calculFluvial();
const rCourbeFlu: ResultElement = this.calculFluvial();
// if (!rCourbeFlu.ok) {
res.addLog(rCourbeFlu.log);
// return res;
// }
// let crbTor: { [key: number]: number; } = this.calculTorrentiel();
const rCourbeTor: ResultElement = this.calculTorrentiel();
// if (!rCourbeTor.ok) {
res.addLog(rCourbeTor.log);
// return res;
// }
let crbFlu = rCourbeFlu.getExtraResult("trY");
if (crbFlu === undefined) {
crbFlu = {};
}
let crbTor = rCourbeTor.getExtraResult("trY");
if (crbTor === undefined) {
crbTor = {};
}
// this.debug("HautCritique ", this.Sn.HautCritique);
this.debug("flu ");
// this.logObject(crbFlu);
this.debug(JSON.stringify(crbFlu));
this.debug("tor");
// this.logObject(crbTor);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
this.debug(JSON.stringify(crbTor));
// tslint:disable-next-line:forin
for (const xflu in crbFlu) {
const yflu = crbFlu[xflu];
// this.debug("imp x " + xflu + " flu " + this.Sn.Calc('Imp', yflu));
}
// tslint:disable-next-line:forin
for (const xtor in crbTor) {
const ytor = crbTor[xtor];
// this.debug("imp x " + xtor + " tor " + this.Sn.Calc('Imp', ytor));
}
// Détection du ressaut hydraulique
const nFlu: number = this.size(crbFlu);
const nTor: number = this.size(crbTor);
if (nFlu !== 0 && nTor !== 0) {
const firstYFlu = crbFlu[0];
const lastYTor = this.last(crbTor);
// this.debug("end flu " + firstYFlu);
// this.debug("end tor " + lastYTor);
// this.debug("nFlu " + nFlu);
// this.debug("nTor " + nTor);
// this.debug("Imp flu " + this.Sn.Calc('Imp', firstYFlu));
// this.debug("Imp tor " + this.Sn.Calc('Imp', lastYTor));
let crbComplete: any;
let crbPartielle: any;
let iSens: number;
let sSens: string;
if (nFlu > nTor || (nFlu === nTor && Yn < Yc)) {
// La courbe fluviale va jusqu'au bout
crbComplete = crbFlu; // courbe calculée sur tout le bief
crbPartielle = crbTor; // courbe calculée sur une partie seulement du bief
iSens = 1; // On cherche l'aval du ressaut
sSens = "amont";
this.debug("complete=flu, partielle=tor");
// this.debug("complete(flu)");
// this.debug(crbComplete);
// this.debug("partielle(tor)");
// this.debug(crbPartielle);
} else {
// La courbe torrentielle va jusqu'au bout
crbComplete = crbTor;
crbPartielle = crbFlu;
iSens = -1; // On cherche l'amont du ressaut
sSens = "aval";
this.debug("complete=tor, partielle=flu");
// this.debug("complete(tor)");
// this.debug(crbComplete);
// this.debug("partielle(flu)");
// this.debug(crbPartielle);
}
// Parcours des sections de la ligne d'eau la plus courte
const trX: string[] = Object.keys(crbPartielle);
if (iSens === -1) {// tri dans l'ordre croissant { {
trX.sort((a, b) => {
if (+a > +b) { return 1; }
if (+a < +b) { return -1; }
return 0;
});
} else { // tri dans l'ordre décroissant { {
trX.sort((a, b) => {
if (+a > +b) { return -1; }
if (+a < +b) { return 1; }
return 0;
});
}
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
const trXr = trX.slice(0); // copie
trXr.reverse();
// this.debug("trX");
// this.debug(trX);
let bRessaut = false;
const Dx = this.prms.Dx.v;
for (let irX = 0; irX < trX.length; irX++) {
const rX: number = +trX[irX];
// this.debug("irX=" + irX);
// this.debug("rX=" + rX);
// this.debug("partielle[" + rX + "]=" + crbPartielle[rX]);
// Calcul de l'abscisse de la section dans l'autre régime
const rYCO = this.Sn.Calc("Yco", crbPartielle[rX]); // Y conjugué
if (!rYCO.ok) {
res.addLog(rYCO.log);
return res;
}
const Yco = rYCO.vCalc;
// this.debug("rX=" + rX + " Yco(Ypartiel=" + crbPartielle[rX] + ")=" + Yco);
const rLongRst = 5 * Math.abs(crbPartielle[rX] - Yco); // Longueur du ressaut
// this.debug("longueur ressaut=" + rLongRst);
let xRst = rX + Math.round(iSens * rLongRst / Dx) * Dx; // Abscisse où comparer Yconj et Y
// this.debug("xRst=" + xRst);
// let rxRst = rX + iSens * rLongRst; // Abscisse réelle du ressaut
// this.debug("xRst reel=" + (rX + iSens * rLongRst));
xRst = round(xRst, this.prmSect.iPrec.v);
// this.debug("xRst (arr)=" + xRst);
const impYpartielle = this.Sn.Calc("Imp", crbPartielle[rX]);
// this.debug("imp(Ypartiel[rX=" + rX + "]=" + crbPartielle[rX] + ")=" + impYpartielle);
if (!impYpartielle.ok) {
res.addLog(impYpartielle.log);
return res;
}
if (crbComplete[xRst] !== undefined) {
// Hauteur décalée de la longueur du ressaut (il faut gérer la pente du fond)
const Ydec: number = crbComplete[xRst] + rLongRst * this.prmSect.If.v * iSens;
// this.debug("Ydec=" + Ydec);
const impYcomplete = this.Sn.Calc("Imp", crbComplete[xRst]);
// this.debug("imp(Ycomplet[xRst=" + xRst + "]=" + crbComplete[xRst] + ")=" + impYcomplete);
if (!impYcomplete.ok) {
res.addLog(impYcomplete.log);
return res;
}
if (impYpartielle.vCalc > impYcomplete.vCalc) {
this.debug(
"Ressaut hydraulique détecté entre les abscisses " +
Math.min(rX, xRst) + " et " + Math.max(rX, xRst));
m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
m.extraVar.xmin = Math.min(rX, xRst);
m.extraVar.xmax = Math.max(rX, xRst);
// this._log.add(m);
res.addMessage(m);
// this.debug("rX=" + rX + " xRst=" + xRst);
// Modification de la ligne d'eau complète
for (const pi of trXr) {
const rXCC: number = +pi;
// this.debug("rXCC=" + rXCC);
if (iSens * (rXCC - rX) <= 0) {
delete crbComplete[rXCC];
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
this.debug(
"Modification de la ligne d'eau complète : suppression de la valeur à rXCC=" +
rXCC + ", rX=" + rX + ", iSens*(rXCC-rX)=" + (iSens * (rXCC - rX))
);
}
}
// Modification de la ligne d'eau partielle
for (const xcn of trX) {
const rXCN = +xcn;
// this.debug("rXCN=" + rXCN);
if (iSens * (rXCN - xRst) >= 0) {
this.debug(
"Modification de la ligne d'eau partielle : suppression de la valeur à rX=" + rXCN
);
delete crbPartielle[rXCN];
}
}
bRessaut = true;
break;
}
}
}
if (!bRessaut) {
// Le ressaut est en dehors du canal
m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
m.extraVar.sens = sSens;
m.extraVar.x = +this.last(trX);
// this._log.add(m);
res.addMessage(m);
this.debug("Ressaut hydraulique détecté à l'" + sSens + " de l'abscisse " + this.last(trX));
if (iSens === 1) {
crbTor = {};
} else {
crbFlu = {};
}
crbPartielle = {}; // pour le log uniquement, à virer
}
this.debug("complete (" + (iSens === 1 ? "flu" : "tor") + ") modifiée");
// this.logObject(crbComplete);
this.debug(JSON.stringify(crbComplete));
this.debug("partielle (" + (iSens === 1 ? "tor" : "flu") + ") modifiée");
// this.logObject(crbPartielle);
this.debug(JSON.stringify(crbPartielle));
}
// Définition des abscisses
let trX: number[] = [];
if (nFlu !== 0) {
trX = Object.keys(crbFlu).map((k) => +k);
}
if (nTor !== 0) {
const kTor = Object.keys(crbTor).map(k => +k);
trX = trX.concat(kTor);
}
// this.debug("trX=" + trX);
trX.sort((a, b) => {
if (a > b) { return 1; }
if (a < b) { return -1; }
return 0;
});
// this.debug("trX tri=" + trX);
trX = trX.filter((elem, index, array) => {
if (index > 0) {
return elem !== array[index - 1];
}