Newer
Older

Grand Francois
committed
import { ParamsSection, acSection } from "./section/section_type";
import { XOR, Result, round } from "./base";
import { ParamsEquation, ParamDefinition, ParamCalculability, ComputeNodeType, ParamDomainValue } from "./param";

Grand Francois
committed
import { Dichotomie } from "./dichotomie";
import { Nub } from "./nub";
import { Message, MessageCode } from "./util/message";
import { cLog } from "./util/log";

Grand Francois
committed
export enum MethodeResolution {
Trapezes, EulerExplicite, RungeKutta4
}
/**
* paramètres pour les courbes de remous
*/
export class CourbeRemousParams extends ParamsEquation {
/**
* section associée
*/
private _section: acSection;

Grand Francois
committed
/**
* 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;

Grand Francois
committed
/**
* Méthode de résolution de l'équation différentielle
*/
private _methodeResolution: MethodeResolution;
// constructor(rQamont: number, rYamont: number, rYAval: number, meth: MethodeResolution) {
constructor(s: acSection, rYamont: number, rYAval: number, rLong: number, rDx: number, meth: MethodeResolution) {
super();
this._section = s;
this._Yamont = new ParamDefinition(ComputeNodeType.CourbeRemous, 'Yamont', ParamDomainValue.POS, rYamont);
this._Yaval = new ParamDefinition(ComputeNodeType.CourbeRemous, 'Yaval', ParamDomainValue.POS, rYAval);
this._Long = new ParamDefinition(ComputeNodeType.CourbeRemous, 'Long', ParamDomainValue.POS, rLong);
this._Dx = new ParamDefinition(ComputeNodeType.CourbeRemous, 'Dx', ParamDomainValue.POS, rDx);

Grand Francois
committed
this._methodeResolution = meth;
this.addParamDefinition(this._Yamont);
this.addParamDefinition(this._Yaval);
this.addParamDefinition(this._Long);
this.addParamDefinition(this._Dx);
this.addParamDefinitions(this._section.prms);

Grand Francois
committed
}
get Sn() {
return this._section;
}

Grand Francois
committed
get Yamont() {
return this._Yamont;
}
get Yaval() {
return this._Yaval;
}
get Long() {
return this._Long;
}
get Dx(): ParamDefinition {
return this._Dx;
}

Grand Francois
committed
get methodeResolution() {
return this._methodeResolution;
}
}
/**
* Calcul d'une courbe de remous
*/
export class CourbeRemous extends Nub {
[key: string]: any; // pour pouvoir faire this['methode]();
private _debugDicho: boolean = false;
/**
* Journal de calcul

Grand Francois
committed
*/
private _log: cLog;

Grand Francois
committed
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;

Grand Francois
committed

Grand Francois
committed
constructor(crp: CourbeRemousParams, dbg: boolean = false) {
super(crp, dbg);

Grand Francois
committed
this._log = crp.Sn.log;
this.prmSect = crp.Sn.prms;

Grand Francois
committed
this.Sn.Calc("Yc");
}

Grand Francois
committed
public get log() {
return this._log;
}
private get Sn(): acSection {
return this.prms.Sn;
}
private get prms(): CourbeRemousParams {
return <CourbeRemousParams>this._prms;
}

Grand Francois
committed
protected setParametersCalculability() {
this.prms.map.Y.calculability = ParamCalculability.DICHO;
this.prms.Long.calculability = ParamCalculability.FREE;
this.prms.map.Dx.calculability = ParamCalculability.FREE;
this.prms.map.Yamont.calculability = ParamCalculability.FREE;
this.prms.map.Yaval.calculability = ParamCalculability.FREE;

Grand Francois
committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
}
public Equation(sVarCalc: string): Result {
if (sVarCalc == "Hs") {
// Equation de l'intégration par la méthode des trapèzes
// let res: number = this.Sn.Calc('Hs', this.VarCal) - this.Sn.Calc('J', this.VarCal) / 2 * this.Dx;
this.Sn.Reset(); // pour forcer le calcul avec la nouvelle valeur de prmSect.Y
let res: number = this.Sn.Calc('Hs') - this.Sn.Calc('J') / 2 * this.Dx;
return new Result(res);
}
throw "CourbeRemous.Equation() : paramètre " + sVarCalc + " non pris en charge";
}
/**
* Calcul de dy/dx (utilisé par Euler explicite et Runge-Kutta 4)
* @param Y Tirant d'eau initial
*/
private Calc_dYdX(Y: number): number {
// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
return - (this.prmSect.If.v - this.Sn.Calc('J', Y)) / (1 - Math.pow(this.Sn.Calc('Fr', Y), 2));
}
/**
* Calcul du point suivant de la courbe de remous par la méthode Euler explicite.
* @param Y Tirant d'eau initial
* @return Tirant d'eau
*/
private Calc_Y_EulerExplicite(Y: number): Result {
// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
let Y2 = Y + this.Dx * this.Calc_dYdX(Y);
if (XOR(this.Dx > 0, !(Y2 < this.Sn.HautCritique)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
return new Result(Y2);
}
/**
* Calcul du point suivant de la courbe de remous par la méthode RK4.
* @param Y Tirant d'eau initial
* @return Tirant d'eau
*/
private Calc_Y_RK4(Y: number): Result {
// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
//$rDx = $this ->rDx;
let Dx = this.Dx;
//$rk1 = $this ->Calc_dYdX($Y);
let k1 = this.Calc_dYdX(Y);
let hc = this.Sn.HautCritique;
//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk1 < $this ->oSect ->rHautCritique)) { return false; }
if (XOR(Dx > 0, !(Y + Dx / 2 * k1 < hc)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
//$rk2 = $this ->Calc_dYdX($Y + $rDx / 2 * $rk1);
let k2 = this.Calc_dYdX(Y + Dx / 2 * k1);
//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk2 < $this ->oSect ->rHautCritique)) { return false; }
if (XOR(Dx > 0, !(Y + Dx / 2 * k2 < hc)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
//$rk3 = $this ->Calc_dYdX($Y + $rDx / 2 * $rk2);
let k3 = this.Calc_dYdX(Y + Dx / 2 * k2);
//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk3 < $this ->oSect ->rHautCritique)) { return false; }
if (XOR(Dx > 0, !(Y + Dx / 2 * k3 < hc)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
//$rk4 = $this ->Calc_dYdX($Y + $rDx * $rk3);
let k4 = this.Calc_dYdX(Y + Dx * k3);
//$Yout = $Y + $rDx / 6 * ($rk1 + 2 * ($rk2 + $rk3) + $rk4);
let Yout = Y + Dx / 6 * (k1 + 2 * (k2 + k3) + k4);
//if ($this ->rDx > 0 xor !($Yout < $this ->oSect ->rHautCritique)) { return false; }
if (XOR(Dx > 0, !(Yout < hc)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
return new Result(Yout);
}
/**
* Equation de l'intégration par la méthode des trapèzes
*/
// private Calc_Y_Trapez_Fn(): number {
// // return $this ->oSect ->Calc('Hs', $this ->VarCal) - $this ->oSect ->Calc('J', $this ->VarCal) / 2 * $this ->rDx;
// return this.Sn.Calc('Hs', this.VarCal) - this.Sn.Calc('J', this.VarCal) / 2 * this.Dx;
// }
/**
* Calcul du point suivant de la courbe de remous par la méthode de l'intégration par trapèze
* @param Y Tirant d'eau initial
* @return Tirant d'eau
*/
private Calc_Y_Trapez(Y: number): Result {
//include_spip('hyd_inc/dichotomie.class');
//$this ->VarCal = &$Y;
// this.VarCal = Y;
// $oDicho = new cDichotomie($this ->oLog, $this, 'Calc_Y_Trapez_Fn', false);
let Dicho = new Dichotomie(this, "Y", this._debugDicho, "Hs");
// Calcul de H + J * \Delta x / 2
// $Trapez_Fn = $this ->oSect ->Calc('Hs', $this ->VarCal) + $this ->oSect ->Calc('J', $this ->VarCal) / 2 * $this ->rDx;
// let Trapez_Fn = this.Sn.Calc('Hs', this.VarCal) + this.Sn.Calc('J', this.VarCal) / 2 * this.Dx
let Trapez_Fn = this.Sn.Calc('Hs', Y) + this.Sn.Calc('J', Y) / 2 * this.Dx
// H est la charge totale. On se place dans le référentiel ou Zf de la section à calculer = 0
// $Trapez_Fn = $Trapez_Fn - $this ->rDx * $this ->oP ->rIf;
Trapez_Fn -= this.Dx * this.prmSect.If.v;
// list($Y2, $flag) = $oDicho ->calculer($Trapez_Fn, $this ->oP ->rPrec, $this ->oSect ->rHautCritique);
// let r: Result = Dicho.Dichotomie(Trapez_Fn, this.prmSect.Prec.v, this.Sn.HautCritique);
let r: Result = Dicho.Dichotomie(Trapez_Fn, this.prmSect.Prec.v, Y);
// if ($flag < 0) {
if (r.code != MessageCode.ERROR_OK)

Grand Francois
committed
return r;
let Y2 = r.vCalc;
// } elseif($this ->rDx > 0 xor !($Y2 < $this ->oSect ->rHautCritique)) {
if (XOR(this.Dx > 0, !(Y2 < this.Sn.HautCritique)))
return new Result(undefined, new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));

Grand Francois
committed
return new Result(Y2);
}
/**
* Calcul du point suivant d'une courbe de remous
* @param Y Tirant d'eau initial
* @return Tirant d'eau
*/
private Calc_Y(Y: number): Result {
// let funcCalcY = 'Calc_Y_' + Resolution;
// return this[funcCalcY](Y);
switch (this.prms.methodeResolution) {

Grand Francois
committed
case MethodeResolution.Trapezes:
return this.Calc_Y_Trapez(Y);
case MethodeResolution.RungeKutta4:
return this.Calc_Y_RK4(Y);
case MethodeResolution.EulerExplicite:
return this.Calc_Y_EulerExplicite(Y);
// default:
// throw "CourbeRemous.Calc_Y() : type de méthode de résolution " + MethodeResolution[this.prms.methodeResolution] + " non pris en charge";

Grand Francois
committed
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
}
}
private size(o: {}): number {
let res: number = 0;
for (let i in o)
res++;
return res;
}
private last(o: any): any {
let res: any = undefined;
for (let i in o)
res = o[i];
return res;
}
/**
* Calcul d'une courbe de remous en fluvial ou torrentiel
* @param YCL Condition limite amont (torrentiel) ou aval (fluvial)
*/
private calcul(YCL: number): { [key: number]: number } {
let trY: { [key: number]: number; } = {};
if (this.Dx > 0) {
// Calcul depuis l'aval
var Deb: number = this.prms.Long.v;

Grand Francois
committed
var Fin: number = 0;
}
else {
// Calcul depuis l'amont
Deb = 0;
Fin = this.prms.Long.v;

Grand Francois
committed
}
let dx = -this.Dx;

Grand Francois
committed
let lastY = YCL;
trY[round(Deb, this.prmSect.iPrec.v)] = lastY;
// Boucle de calcul de la courbe de remous
for (let x = Deb + dx; (dx > 0 && x <= Fin) || (dx < 0 && x >= Fin); x += dx) {

Grand Francois
committed
// this.debug("lastY " + lastY);

Grand Francois
committed
let rY: Result = this.Calc_Y(lastY);

Grand Francois
committed
// this.debug("calcul : x " + x + " y " + rY.vCalc);

Grand Francois
committed
// this.debug("trY ");
// this.logObject(trY);
// this.debug("end trY " + this.last(trY));

Grand Francois
committed
// this.debug("Yn " + this.Sn.HautNormale);

Grand Francois
committed
if (rY.code == MessageCode.ERROR_OK) {
// on vérifie qu'on ne traverse pas la hauteur normale (à la précision de calcul près)
let prec: number = this.prms.map.Prec.v;
let b1: boolean = lastY - this.Sn.HautNormale > prec;
let b2: boolean = rY.vCalc - this.Sn.HautNormale > prec;
if (XOR(b1, b2)) {

Grand Francois
committed
this.debug("La pente de la ligne d'eau est trop forte à l'abscisse " + x + " m (Il faudrait réduire le pas de discrétisation)");
let m: Message = new Message(MessageCode.ERROR_REMOUS_PENTE_FORTE);
m.extraVar["x"] = x;
this._log.add(m);

Grand Francois
committed
}
trY[round(x, this.prmSect.iPrec.v)] = rY.vCalc;
} else {
let m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
m.extraVar["x"] = x;
this._log.add(m);

Grand Francois
committed
this.debug("Arrêt du calcul : Hauteur critique atteinte à l'abscisse " + x + " m");

Grand Francois
committed
break;
}
lastY = rY.vCalc;
}
return trY;
}

Grand Francois
committed
private logArray(a: string[]) {
let s = "[";
let first = true;
for (let e of a) {
if (!first)
s += ",";
s += +e;
first = false;
}
s += "]";
this.debug(s);
}

Grand Francois
committed
private logObject(o: { [key: number]: number }) {

Grand Francois
committed
if (o == undefined)
this.debug("<undefined>");
else {
let ks: string[] = Object.keys(o);
ks.sort((a, b) => {
if (+a > +b) return 1;
if (+a < +b) return -1;
return 0;
});
for (let k of ks)
this.debug("[" + (+k).toFixed(3) + "]=" + o[+k]);
}

Grand Francois
committed
}

Grand Francois
committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/**
* calcul de la ligne fluviale depuis l'aval (si possible)
*/
public calculFluvial() {
let res: { [key: number]: number; } = {};
// Calcul depuis l'aval
if (this.Sn.HautCritique <= 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;
res = this.calcul(this.prms.Yaval.v);
}
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));
}
return res;
}
/**
* calcul de la ligne torrentielle depuis l'amont (si possible)
*/
public calculTorrentiel() {
let res: { [key: number]: number; } = {};
// Calcul depuis l'amont
if (this.Sn.HautCritique >= 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);
}
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");
}
return res;
}

Grand Francois
committed
/**
* @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[],

Grand Francois
committed
"tRes": { [key: number]: number }

Grand Francois
committed
} {
let Yc: number = this.Sn.Calc("Yc");

Grand Francois
committed
let m: Message = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
m.extraVar["B"] = this.Sn.Calc("B", this.Sn.prms.YB.v);
this._log.add(m);

Grand Francois
committed
m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
m.extraVar["Yc"] = Yc;
this._log.add(m);

Grand Francois
committed

Grand Francois
committed
let Yn = this.Sn.Calc("Yn");
m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);

Grand Francois
committed
m.extraVar["Yn"] = Yn;
this._log.add(m);

Grand Francois
committed
this.debug("largeur berge " + this.Sn.Calc("B"));
this.debug("hauteur critique " + Yc);
this.Sn.HautNormale = this.Sn.Calc("Yn");
this.debug("hauteur normale " + this.Sn.HautNormale);
// Calcul des courbes de remous

Grand Francois
committed
let crbFlu: { [key: number]: number; } = this.calculFluvial();
let crbTor: { [key: number]: number; } = this.calculTorrentiel();

Grand Francois
committed
//this.debug("HautCritique ", this.Sn.HautCritique);
this.debug("flu ");

Grand Francois
committed
// this.logObject(crbFlu);
this.debug(JSON.stringify(crbFlu));

Grand Francois
committed
this.debug("tor");

Grand Francois
committed
// this.logObject(crbTor);
this.debug(JSON.stringify(crbTor));

Grand Francois
committed

Grand Francois
committed
for (let xflu in crbFlu) {
let yflu = crbFlu[xflu];
this.debug("imp x " + xflu + " flu " + this.Sn.Calc('Imp', yflu));
}
for (let xtor in crbTor) {
let ytor = crbTor[xtor];
this.debug("imp x " + xtor + " tor " + this.Sn.Calc('Imp', ytor));
}

Grand Francois
committed
// Détection du ressaut hydraulique
let nFlu: number = this.size(crbFlu);
let nTor: number = this.size(crbTor);
if (nFlu != 0 && nTor != 0) {

Grand Francois
committed
let firstYFlu = crbFlu[0];
let lastYTor = this.last(crbTor);
// this.debug("end flu " + firstYFlu);
// this.debug("end tor " + lastYTor);

Grand Francois
committed
// this.debug("nFlu " + nFlu);
// this.debug("nTor " + nTor);

Grand Francois
committed
// this.debug("Imp flu " + this.Sn.Calc('Imp', firstYFlu));
// this.debug("Imp tor " + this.Sn.Calc('Imp', lastYTor));
if (nFlu > nTor || (nFlu == nTor && Yn < Yc)) {

Grand Francois
committed
// La courbe fluviale va jusqu'au bout
var crbComplete = crbFlu; // courbe calculée sur tout le bief
var crbPartielle = crbTor; // courbe calculée sur une partie seulement du bief
var iSens = 1; // On cherche l'aval du ressaut
var 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

Grand Francois
committed
let trX: string[] = Object.keys(crbPartielle);

Grand Francois
committed
if (iSens == -1) // tri dans l'ordre croissant

Grand Francois
committed
trX.sort((a, b) => {
if (+a > +b) return 1;
if (+a < +b) return -1;
return 0;
});

Grand Francois
committed
else // tri dans l'ordre décroissant

Grand Francois
committed
trX.sort((a, b) => {
if (+a > +b) return -1;
if (+a < +b) return 1;
return 0;
});
let trXr = trX.slice(0); // copie
trXr.reverse();
// this.debug("trX");
// this.debug(trX);
let bRessaut = false;
let Dx = this.prms.Dx.v;

Grand Francois
committed
for (let irX = 0; irX < trX.length; irX++) {
let rX: number = +trX[irX];
// this.debug("irX=" + irX);
// this.debug("rX=" + rX);
// this.debug("partielle[" + rX + "]=" + crbPartielle[rX]);

Grand Francois
committed
// Calcul de l'abscisse de la section dans l'autre régime
let Yco = this.Sn.Calc('Yco', crbPartielle[rX]); // Y conjugué

Grand Francois
committed
// this.debug("rX=" + rX + " Yco(Ypartiel=" + crbPartielle[rX] + ")=" + Yco);

Grand Francois
committed
let rLongRst = 5 * Math.abs(crbPartielle[rX] - Yco); // Longueur du ressaut

Grand Francois
committed
// this.debug("longueur ressaut=" + rLongRst);

Grand Francois
committed
let xRst = rX + Math.round(iSens * rLongRst / Dx) * Dx; // Abscisse où comparer Yconj et Y

Grand Francois
committed
// this.debug("xRst=" + xRst);

Grand Francois
committed
//let rxRst = rX + iSens * rLongRst; // Abscisse réelle du ressaut
//this.debug("xRst reel=" + (rX + iSens * rLongRst));
xRst = round(xRst, this.prmSect.iPrec.v);

Grand Francois
committed
// this.debug("xRst (arr)=" + xRst);

Grand Francois
committed

Grand Francois
committed
let impYpartielle = this.Sn.Calc('Imp', crbPartielle[rX]);
// this.debug("imp(Ypartiel[rX=" + rX + "]=" + crbPartielle[rX] + ")=" + impYpartielle);

Grand Francois
committed
if (crbComplete[xRst] != undefined) {
// Hauteur décalée de la longueur du ressaut (il faut gérer la pente du fond)
let Ydec: number = crbComplete[xRst] + rLongRst * this.prmSect.If.v * iSens;

Grand Francois
committed
// this.debug("Ydec=" + Ydec);

Grand Francois
committed
let impYcomplete = this.Sn.Calc('Imp', crbComplete[xRst]);
// this.debug("imp(Ycomplet[xRst=" + xRst + "]=" + crbComplete[xRst] + ")=" + impYcomplete);

Grand Francois
committed

Grand Francois
committed
if (impYpartielle > impYcomplete) {

Grand Francois
committed
this.debug("Ressaut hydraulique détecté entre les abscisses " + Math.min(rX, xRst) + " et " + Math.max(rX, xRst));
m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
m.extraVar["xmin"] = Math.min(rX, xRst);
m.extraVar["xmax"] = Math.max(rX, xRst);
this._log.add(m);

Grand Francois
committed
// this.debug("rX=" + rX + " xRst=" + xRst);

Grand Francois
committed
// Modification de la ligne d'eau complète

Grand Francois
committed
for (let pi of trXr) {
let rXCC: number = +pi;
// this.debug("rXCC=" + rXCC);

Grand Francois
committed
if (iSens * (rXCC - rX) <= 0) {

Grand Francois
committed
delete crbComplete[rXCC];

Grand Francois
committed
this.debug("Modification de la ligne d'eau complète : suppression de la valeur à rXCC=" + rXCC + ", rX=" + rX + ", iSens*(rXCC-rX)=" + (iSens * (rXCC - rX)));

Grand Francois
committed
}
}

Grand Francois
committed
// Modification de la ligne d'eau partielle

Grand Francois
committed
for (let xcn of trX) {
let rXCN = +xcn;
// this.debug("rXCN=" + rXCN);

Grand Francois
committed
if (iSens * (rXCN - xRst) >= 0) {

Grand Francois
committed
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
let m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
m.extraVar["sens"] = sSens;
m.extraVar["x"] = +this.last(trX);
this._log.add(m);

Grand Francois
committed
this.debug("Ressaut hydraulique détecté à l'" + sSens + " de l'abscisse " + this.last(trX));
if (iSens == 1)
crbTor = {};
else
crbFlu = {};

Grand Francois
committed
crbPartielle = {}; // pour le log uniquement, à virer

Grand Francois
committed
}
}
this.debug("complete (" + (iSens == 1 ? "flu" : "tor") + ") modifiée");

Grand Francois
committed
// this.logObject(crbComplete);
this.debug(JSON.stringify(crbComplete));

Grand Francois
committed
this.debug("partielle (" + (iSens == 1 ? "tor" : "flu") + ") modifiée");

Grand Francois
committed
// this.logObject(crbPartielle);
this.debug(JSON.stringify(crbPartielle));

Grand Francois
committed
// Définition des abscisses
let trX: string[] = [];
if (nFlu != 0)
trX = Object.keys(crbFlu);
if (nTor != 0)
trX = trX.concat(Object.keys(crbTor));
// 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];
return true;
});
// this.debug("trX unique=" + trX);

Grand Francois
committed
this.debug("abscisses ");
this.logArray(trX);

Grand Francois
committed
// Calcul de la variable à calculer

Grand Francois
committed
let tRes: { [key: number]: number } = {};

Grand Francois
committed
if (val_a_cal != undefined && (nFlu != 0 || nTor != 0)) {

Grand Francois
committed
for (let rX of trX) {
let rY = undefined;
let hasFlu: boolean = crbFlu[+rX] != undefined;
let hasTor: boolean = crbTor[+rX] != undefined;

Grand Francois
committed
if (hasFlu && !hasTor)

Grand Francois
committed
rY = crbFlu[+rX];
if (hasTor)
if (!hasFlu || (hasFlu && crbFlu[+rX] == crbTor[+rX]))

Grand Francois
committed
rY = crbTor[+rX];
if (rY != undefined) {
tRes[+rX] = this.Sn.Calc(val_a_cal, rY);
this.debug('X=' + rX + ' Calc(' + val_a_cal + ', Y=' + rY + ')=' + tRes[+rX]);

Grand Francois
committed
}
}
this.debug("extra param " + val_a_cal);
this.logObject(tRes);

Grand Francois
committed
}
return { "flu": crbFlu, "tor": crbTor, "trX": trX, "tRes": tRes };
}
}