jalhyd
Version:
JaLHyd, a Javascript Library for Hydraulics
263 lines • 11.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Solveur = 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");
class Solveur extends internal_modules_2.Nub {
/**
* Finds all parameters whose value can be searched for by dichotomy, for
* a given value of calculated param of given Nub
* @param nub Nub calculated by Solveur
* @param addSelf if true, will also return parameters of the current Nub
*/
static getDependingNubsSearchableParams(nub, addSelf = false) {
const searchableParams = [];
if (nub !== undefined) {
const upstreamNubs = nub.getRequiredNubsDeep();
if (addSelf) {
upstreamNubs.push(nub);
}
for (const un of upstreamNubs) {
for (const p of un.parameterIterator) {
// only visible, non-varying, non-calculated parameters can be looked for
if (p.visible && p.valueMode === internal_modules_4.ParamValueMode.SINGLE) {
searchableParams.push(p);
}
}
}
}
return searchableParams;
}
constructor(prms, dbg = false) {
super(prms, dbg);
this.setCalculatorType(internal_modules_1.CalculatorType.Solveur);
this._props.addObserver(this);
this.prms.addObserver(this);
// UID of Session Nub to calculate, the result of the which must be this.prms.Ytarget.singleValue
this.nubToCalculate = undefined;
// symbol of extra result targetted on the Nub to calculate; if specified, then this.prms.Ytarget.singleValue
// will be the expected value not for nubToCalculate.vCalc, but for nubToCalculate.values[this.targettedResult]
this.targettedResult = undefined;
// UID of Session Nub / symbol of source parameter to vary (the "searched" parameter)
this.searchedParameter = undefined;
// calculated param should always be pseudo-parameter "X" (the one whose value we're looking for)
this._defaultCalculatedParam = prms.X;
this.resetDefaultCalculatedParam();
}
get prms() {
return this._prms;
}
/** finds the Nub to calculate by its UID */
get nubToCalculate() {
let nub;
const nubUID = this._props.getPropValue("nubToCalculate");
if (nubUID !== undefined && nubUID !== "") {
nub = internal_modules_5.Session.getInstance().findNubByUid(nubUID);
if (nub === undefined) {
// silent fail
// throw new Error(`Solveur.get nubToCalculate(): cannot find Nub ${nubUID} in session`);
}
}
return nub;
}
/** defines the Nub to calculate by setting property "nubToCalculate" to the UID of the given Nub */
set nubToCalculate(n) {
let uid = ""; // empty value
if (n !== undefined) {
uid = n.uid;
}
this.setPropValue("nubToCalculate", uid);
}
get targettedResult() {
return this._props.getPropValue("targettedResult");
}
set targettedResult(symbol) {
this._props.setPropValue("targettedResult", symbol);
}
/** finds the source parameter whose value we're looking for, by its Nub UID / symbol */
get searchedParameter() {
let p;
const nubUIDAndSymbol = this._props.getPropValue("searchedParameter");
if (nubUIDAndSymbol !== undefined && nubUIDAndSymbol !== "") {
const slashPos = nubUIDAndSymbol.indexOf("/");
const nubUID = nubUIDAndSymbol.substring(0, slashPos);
const paramSymbol = nubUIDAndSymbol.substring(slashPos + 1);
// console.log("(i) searched param Nub UID / symbol :", nubUID, paramSymbol);
if (nubUID) {
const nub = internal_modules_5.Session.getInstance().findNubByUid(nubUID);
if (nub !== undefined) {
if (paramSymbol) {
p = nub.getParameter(paramSymbol);
if (p === undefined) {
throw new Error(`Solveur.get searchedParameter(): cannot find Parameter ${paramSymbol} in Nub`);
}
}
}
else {
// silent fail
// throw new Error(`Solveur.get searchedParameter(): cannot find Nub ${nubUID} in session`);
}
}
}
return p;
}
/**
* defines the searched parameter by setting property "searchedParameter" to the UID of the
* parameter's Nub / the parameter's symbol
*/
set searchedParameter(p) {
let sp = ""; // empty value
if (p !== undefined) {
sp = p.nubUid + "/" + p.symbol;
}
this.setPropValue("searchedParameter", sp);
}
/**
* Looks for potential errors before calling Nub.Calc()
*/
Calc(sVarCalc, rInit) {
const r = new internal_modules_6.Result(new internal_modules_7.ResultElement());
if (this.nubToCalculate.resultHasMultipleValues()) {
r.resultElement.addMessage(new internal_modules_8.Message(internal_modules_8.MessageCode.ERROR_SOLVEUR_NO_VARIATED_PARAMS_ALLOWED));
this.currentResultElement = r;
return this.result;
}
return super.Calc(sVarCalc, rInit);
}
CalcSerie(rInit) {
// affect initial value of X for Dichotomie search
this.prms.X.singleValue = this.prms.Xinit.currentValue;
const res = super.CalcSerie(rInit);
res.updateSourceNub(this);
res.removeExtraResults();
// clodo trick: realculate nubToCalculate() dissociates results @see jalhyd#157
this.nubToCalculate.CalcSerie();
return res;
}
/**
* Calculates the target "downstream" Nub, that will trigger calculation of
* all linked "upstream" Nubs, including the one that contains the variating
* parameter X
* @param sVarCalc should always be pseudo-parameter "Y"
*/
Equation(sVarCalc) {
if (sVarCalc !== "Y") {
throw new Error(`Solveur: calculated param should always be Y (found ${sVarCalc})`);
}
// set the Y value we have to obtain
this.prms.Y.v = this.prms.Ytarget.v;
// set the current value of X, determined by Dichotomie, on the upstream Nub
this.searchedParameter.singleValue = this.prms.X.v;
// calculate Nubs chain
const res = this.nubToCalculate.CalcSerie();
// if targetting an extraresult, replace vCalc with targetted extraresult
if (this.targettedResult) { // might be undefined, or "" (when unserializing)
res.vCalc = res.values[this.targettedResult];
}
return res;
}
getFirstAnalyticalParameter() {
// always use pseudo-parameter Y for Dichotomie iterations;
// always update target value from input parameter
this.prms.Y.v = this.prms.Ytarget.v;
return this.prms.Y;
}
// interface Observer
update(sender, data) {
if (data.action === "propertyChange") {
if (data.name === "nubToCalculate" || data.name === "searchedParameter" || data.name === "targettedResult") {
const n = this.nubToCalculate;
const t = this.targettedResult;
const p = this.searchedParameter;
if (n !== undefined && p !== undefined) {
if (n !== p.parentNub && !n.dependsOnNubResult(p.parentNub)) {
throw new Error("Solveur.update(): Nub to calculate is not linked to result of searchedParameter parent Nub");
}
}
if (data.name === "nubToCalculate") {
if (n !== undefined) {
if (n.resultHasMultipleValues()) {
throw new Error("Solveur.update(): Nub to calculate must not have multiple values");
}
// reset targetted result
this.targettedResult = undefined;
}
}
if (data.name === "searchedParameter") {
if (p !== undefined) {
if (p.valueMode !== internal_modules_4.ParamValueMode.SINGLE) {
throw new Error("Solveur.update(): searched parameter X must be in SINGLE mode");
}
// update pseudo-parameter X
this.prms.setX(p);
}
}
if (data.name === "targettedResult") {
if (t !== undefined && t !== "") {
if (n.resultsFamilies
&& !Object.keys(n.resultsFamilies).includes(t)) {
throw new Error("Solveur.update(): targetted result T is not a declared extra result of Nub to calculate");
}
}
else {
// empty value − is nubToCalc single ? If so, invalidate searchedParam
if (Solveur.getDependingNubsSearchableParams(n).length === 0) {
this.searchedParameter = undefined;
}
}
}
}
}
if (data.action === "XUpdated") {
this._defaultCalculatedParam = this.prms.X;
this.resetDefaultCalculatedParam();
}
}
/**
* Once session is loaded, run a second pass on targetted
* objects if they couldn't be set before
*/
fixTargets(obj) {
// return value
const ret = {
hasErrors: false
};
try {
// do not use setters, to allow setting directly the string UIDs
this.setPropValue("nubToCalculate", obj.props.nubToCalculate);
this.setPropValue("targettedResult", obj.props.targettedResult);
this.setPropValue("searchedParameter", obj.props.searchedParameter);
}
catch (e) {
ret.hasErrors = true;
}
return ret;
}
setParametersCalculability() {
if (this.prms.X !== undefined) {
this.prms.X.calculability = internal_modules_3.ParamCalculability.DICHO;
}
this.prms.Xinit.calculability = internal_modules_3.ParamCalculability.FIXED;
this.prms.Ytarget.calculability = internal_modules_3.ParamCalculability.FREE;
this.prms.Y.calculability = internal_modules_3.ParamCalculability.FREE;
}
Solve(sVarCalc, rInit) {
const res = super.Solve(sVarCalc, rInit);
// if Y has log about a failure in calc chain, copy it to
// a resultElement so that Nub.Calc() does not complain
if (res.resultElements.length === 0) {
const re = new internal_modules_7.ResultElement();
re.log.addLog(res.globalLog);
res.addResultElement(re);
}
return res;
}
}
exports.Solveur = Solveur;
//# sourceMappingURL=solveur.js.map