An error occurred while loading the file. Please try again.
-
Dorchies David authored
- Calculation code modified - Module test rewrited from simple example of Dominique Courret's Excel sheet Fix #212
03f8cf9e
import { CalculatorType } from "../compute-node";
import { Nub } from "../nub";
import { ParamCalculability, ParamFamily } from "../param/param-definition";
import { ParamValueMode } from "../param/param-value-mode";
import { Message, MessageCode } from "../util/message";
import { Result } from "../util/result";
import { JetParams } from "./jet_params";
export class Jet extends Nub {
/** steps for generating the trajectory */
protected precision = 50;
public constructor(prms: JetParams, dbg: boolean = false) {
super(prms, dbg);
this._calcType = CalculatorType.Jet;
this._defaultCalculatedParam = prms.D;
this.resetDefaultCalculatedParam();
}
/** paramètres castés au bon type */
get prms(): JetParams {
return this._prms as JetParams;
}
public Calc(sVarCalc: string, rInit?: number): Result {
this.currentResult = super.Calc(sVarCalc, rInit);
// omit extra results if calculation failed
if (this.result.vCalc !== undefined) {
// H: chute
this.result.resultElement.values.H = this.prms.ZJ.v - this.prms.ZW.v;
// Y: profondeur
this.result.resultElement.values.Y = this.prms.ZW.v - this.prms.ZF.v;
// YH: rapport profondeur/chute
this.result.resultElement.values.YH = this.result.resultElement.values.Y / this.result.resultElement.values.H;
// t: temps de vol
this.result.resultElement.values.t = this.prms.D.V / Math.cos(this.alpha) / this.prms.V0.V;
// Vx: vitesse horizontale à l'impact
this.result.resultElement.values.Vx = this.prms.V0.V * Math.cos(this.alpha);
// Vz: vitesse verticale à l'impact
this.result.resultElement.values.Vz =
this.prms.V0.V * Math.sin(this.alpha) - this.result.resultElement.values.t * 9.81;
// Vt: vitesse à l'impact
this.result.resultElement.values.Vt = Math.sqrt(
Math.pow(this.result.resultElement.values.Vx, 2)
+ Math.pow(this.result.resultElement.values.Vz, 2)
);
}
let ZF = this.prms.ZF.v;
let ZW = this.prms.ZW.v;
let ZJ = this.prms.ZJ.v;
if (this.calculatedParam === this.prms.ZF) {
ZF = this.result.resultElement.vCalc;
}
if (this.calculatedParam === this.prms.ZW) {
ZW = this.result.resultElement.vCalc;
}
if (this.calculatedParam === this.prms.ZJ) {
ZJ = this.result.resultElement.vCalc;
}
// y a-t-il de l'eau au dessus du sol ?
if (ZF > ZW) {
this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND));
}
// le jet est-il bien au dessus du sol ?
if (ZF > ZJ) {
this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_START_ELEVATION_UNDERGROUND));
}
// le jet est-il bien émergé ?
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
if (ZW > ZJ) {
this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_START_SUBMERGED));
}
return this.result;
}
public Equation(sVarCalc: string): Result {
const g: number = 9.81;
let v: number;
let h: number;
switch (sVarCalc) {
case ("ZJ"):
h = this.CalcH();
v = h + this.prms.ZW.v;
break;
case ("ZW"):
h = this.CalcH();
v = this.prms.ZJ.v - h;
break;
case ("D"):
h = (this.prms.ZJ.v - this.prms.ZW.v);
const sqrtArg = Math.pow(this.prms.V0.v * Math.sin(this.alpha), 2) + 2 * g * h;
if (sqrtArg < 0) {
return new Result(new Message(MessageCode.ERROR_JET_SUBMERGED_NO_SOLUTION), this);
}
v = this.prms.V0.v / g * Math.cos(this.alpha)
* (
this.prms.V0.v * Math.sin(this.alpha)
+ Math.sqrt(sqrtArg)
);
break;
default:
throw new Error("Jet.Equation() : invalid variable name " + sVarCalc);
}
return new Result(v);
}
/** clone casting */
public clone(): Jet {
return super.clone() as Jet;
}
/**
* Returns an array of trajectories built from the current Nub state.
* A trajectory is a list of coordinate pairs representing the fall height (y),
* for each abscissa (x) between 0 and the impact abscissa (D).
* A coordinate pair is a list of 2 numbers [ x, y ].
* If no parameter is varying, result will contain only 1 element.
* Trajectory calculation uses a copy of the current Nub to calculate ZW from D.
*/
public generateTrajectories(): number[][][] {
const trajectories: number[][][] = [];
// clone Nub so that ZW calculation will not impact current state
const nub = this.clone();
// is anything varying ?
if (this.resultHasMultipleValues()) {
const valuesLists: any = {};
const length = this.variatingLength();
// reset clone params to SINGLE mode
nub.prms.V0.valueMode = ParamValueMode.SINGLE;
nub.prms.S.valueMode = ParamValueMode.SINGLE;
nub.prms.D.valueMode = ParamValueMode.SINGLE;
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
// H will be calculated
// 1. find all extended values lists; ignore ZW (will be calculated) and D (will be reaffected)
for (const symbol of [ "S", "V0", "ZJ" ]) {
const p = this.getParameter(symbol);
valuesLists[symbol] = [];
if (this.calculatedParam.symbol === symbol) { // calculated
for (let i = 0; i < length; i++) {
valuesLists[symbol].push(this.result.resultElements[i].vCalc);
}
} else if (p.hasMultipleValues) { // variating
const iter = p.getExtendedValuesIterator(length);
while (iter.hasNext) {
const nv = iter.next();
valuesLists[symbol].push(nv.value);
}
} else { // single
for (let i = 0; i < length; i++) {
valuesLists[symbol].push(p.singleValue);
}
}
}
// 2. build one series for each variating step
for (let i = 0; i < length; i++) {
// exclude iteration if calculation has failed
if (this.result.resultElements[i].ok) {
// set clone params values; ignore ZW (will be calculated)
// and D (will be reaffected by getDAbscissae)
for (const symbol of [ "S", "V0", "ZJ" ]) {
const val = valuesLists[symbol][i];
nub.getParameter(symbol).v = val;
}
// compute series
trajectories.push(this.buildSeriesForIteration(nub, i));
} else {
// mark failed calculation using empty list
trajectories.push([]);
}
}
} else { // nothing is varying
for (const symbol of [ "S", "V0", "ZJ" ]) {
// init .v of clone
nub.getParameter(symbol).v = nub.getParameter(symbol).singleValue;
}
trajectories.push(this.buildSeriesForIteration(nub, 0));
}
return trajectories;
}
protected CalcH(): number {
const g: number = 9.81;
return (
0.5 * g * Math.pow(this.prms.D.v, 2)
/ (Math.pow(Math.cos(this.alpha), 2) * Math.pow(this.prms.V0.v, 2)
) - Math.tan(this.alpha) * this.prms.D.v);
}
/**
* Build a trajectory data series for a calculation iteration
*/
protected buildSeriesForIteration(nub: Jet, i: number): number[][] {
const traj: number[][] = [];
const xs = this.getDAbscissae(i);
for (const x of xs) {
// compute H for D = x
nub.prms.D.v = x;
// console.log("__computing H for x =", x, nub.prms.D.v);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
const h = nub.Calc("ZW");
traj.push([ x, h.vCalc ]);
}
return traj;
}
/**
* Returns a list of abscissae from 0 to D (number of steps is this.precision)
* @param variatingIndex if D is variating, index of the D value to fetch
*/
protected getDAbscissae(variatingIndex: number = 0): number[] {
const abs: number[] = [];
// divide impact abscissa into steps
let D: number;
if (this.calculatedParam.symbol === "D") {
D = this.result.resultElements[variatingIndex].vCalc;
} else if (this.prms.D.hasMultipleValues) {
const length = this.variatingLength();
const valsD: number[] = [];
const iter = this.prms.D.getExtendedValuesIterator(length);
while (iter.hasNext) {
const nv = iter.next();
valsD.push(nv.value);
}
D = valsD[variatingIndex];
} else {
D = this.prms.D.V;
}
const step = D / this.precision;
// zero-abscissa
let x = 0;
abs.push(x);
// abscissae in ]0,D[
for (let i = 0; i < this.precision - 1; i++) {
x += step;
abs.push(x);
}
// D-abscissa
abs.push(D);
return abs;
}
protected setParametersCalculability() {
this.prms.V0.calculability = ParamCalculability.DICHO;
this.prms.S.calculability = ParamCalculability.DICHO;
this.prms.ZJ.calculability = ParamCalculability.EQUATION;
this.prms.ZW.calculability = ParamCalculability.EQUATION;
this.prms.ZF.calculability = ParamCalculability.FIXED;
this.prms.D.calculability = ParamCalculability.EQUATION;
}
protected exposeResults() {
this._resultsFamilies = {
H: ParamFamily.TOTALFALLS,
Y: ParamFamily.HEIGHTS,
YH: undefined,
t: undefined,
Vx: undefined,
Vz: undefined,
Vt: undefined
};
}
private get alpha(): number {
return Math.atan(this.prms.S.v);
}
}