param.ts 12.46 KiB
import { Debug } from "./base";
import { DefinedNumber } from "./util/definedvalue";
import { Interval } from "./util/interval";
import { Message, MessageCode } from "./util/message";
import { MapIterator } from "./util/iterator";
import { JalhydObject } from "./jalhyd_object";
/**
 * domaine de définition du paramètre
export enum ParamDomainValue {
    /**
     * >0, =0, <0 (-inf -> +inf)
    ANY,
    /**
     * >=0
    POS_NULL,
    /**
     * > 0
    POS,
    /**
     * <>0
    NOT_NULL,
    /**
     * intervalle
    INTERVAL
export class ParamDomain {
    public static getDefaultBounds(d: ParamDomainValue): { min: number, max: number } {
        switch (d) {
            case ParamDomainValue.INTERVAL:
                const e: Message = new Message(MessageCode.ERROR_PARAMDOMAIN_INVALID);
                throw e;
            case ParamDomainValue.ANY:
            case ParamDomainValue.NOT_NULL:
                return { min: -Infinity, max: Infinity };
            case ParamDomainValue.POS:
                return { min: 1e-9, max: Infinity };
            case ParamDomainValue.POS_NULL:
                return { min: 0, max: Infinity };
            // default:
            //     throw "valeur de ParamDomainValue" + ParamDomainValue[d] + " non prise en charge";
    private _domain: ParamDomainValue;
    private _minValue: number;
    private _maxValue: number;
    constructor(d: ParamDomainValue, min?: number, max?: number) {
        this.checkValue(d, min, max);
        this._domain = d;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
switch (this._domain) { case ParamDomainValue.INTERVAL: this._minValue = min; this._maxValue = max; break; default: const b = ParamDomain.getDefaultBounds(this._domain); this._minValue = b.min; this._maxValue = b.max; break; } } get domain() { return this._domain; } get minValue() { return this._minValue; } get maxValue() { return this._maxValue; } public get interval(): Interval { switch (this._domain) { case ParamDomainValue.INTERVAL: return new Interval(this._minValue, this._maxValue); default: const b = ParamDomain.getDefaultBounds(this._domain); return new Interval(b.min, b.max); } } public clone(): ParamDomain { switch (this._domain) { case ParamDomainValue.INTERVAL: return new ParamDomain(this._domain, this._minValue, this._maxValue); default: return new ParamDomain(this._domain); } } private checkValue(val: number, min: number, max: number) { switch (val) { case ParamDomainValue.INTERVAL: if (min === undefined || max === undefined || min > max) { const e: Message = new Message(MessageCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS); e.extraVar.minValue = min; e.extraVar.maxValue = max; throw e; } break; default: // en dehors du cas INTERVAL, on ne doit pas fournir de valeur if (min !== undefined || max !== undefined) { const e: Message = new Message(MessageCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS); e.extraVar.minValue = min; e.extraVar.maxValue = max; throw e; } break; } }
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} /** * calculabilité du paramètre */ export enum ParamCalculability { /** * paramètre fixé (immuable, cad non modifiable après création) */ NONE, /** * paramètre libre (modifiable) */ FREE, /** * paramètre calculable analytiquement, par méthode de Newton, ... */ EQUATION, /** * paramètre calculable par dichotomie */ DICHO } /** * paramètre avec symbole et domaine de définition */ // tslint:disable-next-line:max-classes-per-file export class BaseParam extends JalhydObject { /** * symbole */ private _symbol: string; /** * domaine de définition */ private _domain: ParamDomain; /** * valeur numérique (éventuellement non définie) */ private _value: DefinedNumber; constructor(symb: string, d: ParamDomain | ParamDomainValue, val?: number) { super(); this._symbol = symb; this._value = new DefinedNumber(val); if (d instanceof ParamDomain) { this._domain = d; } else { this._domain = new ParamDomain(d as ParamDomainValue); } this.checkValue(val); } get symbol(): string { return this._symbol; } public getDomain(): ParamDomain { return this._domain; } public get interval(): Interval {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
return this._domain.interval; } /** * gestion de la valeur */ public get isDefined(): boolean { return this._value.isDefined; } public getValue(): number { if (!this._value.isDefined) { const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED); e.extraVar.symbol = this.symbol; throw e; } return this._value.value; } public setValue(val: number) { this.checkValue(val); this._value.value = val; // console.log("setting param " + this._symbol + " id=" + this._id + " to " + val); // A VIRER } public get uncheckedValue(): number { return this._value.uncheckedValue; } public checkValue(v: number) { const sDomain = ParamDomainValue[this._domain.domain]; switch (this._domain.domain) { case ParamDomainValue.ANY: break; case ParamDomainValue.POS: if (v <= 0) { const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_POS); f.extraVar.symbol = this.symbol; f.extraVar.value = v; throw f; } break; case ParamDomainValue.POS_NULL: if (v < 0) { const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_POSNULL); f.extraVar.symbol = this.symbol; f.extraVar.value = v; throw f; } break; case ParamDomainValue.NOT_NULL: if (v === 0) { const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_NULL); f.extraVar.symbol = this.symbol; throw f; } break; case ParamDomainValue.INTERVAL: const min = this._domain.minValue; const max = this._domain.maxValue; if (v < min || v > max) { const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_INTERVAL);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
f.extraVar.symbol = this.symbol; f.extraVar.value = v; f.extraVar.minValue = min; f.extraVar.maxValue = max; throw f; } break; default: const e = new Message(MessageCode.ERROR_PARAMDOMAIN_INVALID); e.extraVar.symbol = this.symbol; e.extraVar.domain = sDomain; throw e; } } } /** * définition d'un paramètre d'un noeud de calcul */ // tslint:disable-next-line:max-classes-per-file export class ParamDefinition extends BaseParam { /** * calculabilité */ private _calc: ParamCalculability; constructor(s: string, d: ParamDomain | ParamDomainValue, val?: number) { super(s, d, val); this._calc = undefined; this.checkValue(val); } get v(): number { return super.getValue(); } set v(val: number) { if (this.calculability === ParamCalculability.NONE) { const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED); e.extraVar.symbol = this.symbol; throw e; } super.setValue(val); } /* * méthodes de calculabilité */ /** * variable calculable par l'équation ? */ public isAnalytical(): boolean { return this.calculability === ParamCalculability.EQUATION; } get calculability(): ParamCalculability { if (this._calc === undefined) { // throw "value of parameter '" + this._symbol + "' calculability is not defined"; const e = new Message(MessageCode.ERROR_PARAMDEF_CALC_UNDEFINED); e.extraVar.symbol = this.symbol; throw e; } return this._calc; } set calculability(c: ParamCalculability) { this._calc = c;
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
} public clone(): ParamDefinition { const res = new ParamDefinition(this.symbol, this.getDomain().clone(), this.uncheckedValue); res._calc = this._calc; return res; } } /** * liste des paramètres d'une équation */ // tslint:disable-next-line:max-classes-per-file export abstract class ParamsEquation implements Iterable<ParamDefinition> { protected _paramMap: { [key: string]: ParamDefinition } = {}; public hasParameter(name: string): boolean { for (const ps in this._paramMap) { const p: ParamDefinition = this._paramMap[ps]; if (p.symbol === name) { return true; } } return false; } public getParameter(name: string): ParamDefinition { for (const ps in this._paramMap) { const p: ParamDefinition = this._paramMap[ps]; if (p.symbol === name) { return p; } } throw new Error("ParamsEquation.getParameter() : invalid parameter name " + name); } public getFirstAnalyticalParameter(): ParamDefinition { for (const ps in this._paramMap) { const p: ParamDefinition = this._paramMap[ps]; if (p.isAnalytical()) { return p; } } return undefined; } protected addParamDefinition(p: ParamDefinition) { if (!this.hasParameter(p.symbol)) { this._paramMap[p.symbol] = p; } } protected addParamDefinitions(ps: ParamsEquation) { for (const pi in ps._paramMap) { this.addParamDefinition(ps._paramMap[pi]); } } public get map(): { [key: string]: ParamDefinition } { return this._paramMap; } protected checkParametersCalculability() { const res = []; for (const ps in this._paramMap) { const p: ParamDefinition = this._paramMap[ps]; if (p.calculability === undefined) {
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
res.push(p.symbol); } } if (res.length > 0) { throw new Error("Calculability of parameter(s) " + res.toString() + " has not been defined"); } } [Symbol.iterator](): Iterator<ParamDefinition> { return this.iterator; } public get iterator() { return new MapIterator(this._paramMap); } } /** * type de calculette */ export enum CalculatorType { ConduiteDistributrice, LechaptCalmon, SectionParametree, RegimeUniforme, CourbeRemous, PabDimensions, // passe à bassin rectangulaire PabPuissance, // passe à bassin : puissance dissipée Structure, // ouvrages hydrauliques simples ParallelStructure // ouvrages hydrauliques en parallèle } /** * type de noeud de calcul (sous type de calculette) */ export enum ComputeNodeType { None, // types de sections SectionTrapeze, SectionRectangle, SectionCercle, SectionPuissance, // types d'ouvrages hydrauliques StructureRectangle, } /** * noeud de calcul */ // tslint:disable-next-line:max-classes-per-file export abstract class ComputeNode extends Debug { protected _prms: ParamsEquation; constructor(prms: ParamsEquation, dbg: boolean = false) { super(dbg); this._prms = prms; this.setParametersCalculability(); } public getParameter(name: string): ParamDefinition { return this._prms.getParameter(name); } public getFirstAnalyticalParameter(): ParamDefinition { return this._prms.getFirstAnalyticalParameter(); } protected abstract setParametersCalculability(): void; }