diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..7ca0dc5577d8533754f994538ca949512c6368b5
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,20 @@
+{
+    // Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
+    // Pointez pour afficher la description des attributs existants.
+    // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Program",
+            "type": "node",
+            "request": "launch",
+            "program": "${file}",
+            "sourceMaps": true,
+            "outFiles": [
+                "${workspaceRoot}/build/**/*.js"
+            ],
+            "cwd": "${workspaceRoot}",
+            "preLaunchTask": "buildspec"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000000000000000000000000000000000000..03efa3f6e6f3976e97516d27e13b8ffb58c89480
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,13 @@
+{
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "buildspec",
+            "type": "npm",
+            "script": "buildspec",
+            "problemMatcher": []
+        }
+    ]
+}
diff --git a/spec/mock_jasmine.ts b/spec/mock_jasmine.ts
index 8f03ee968fd9695c3b0ce6b1619a724d6b577bfb..2ba5f986c0158e410e0ab085db02e0cb5eb59786 100644
--- a/spec/mock_jasmine.ts
+++ b/spec/mock_jasmine.ts
@@ -98,6 +98,16 @@ class Expect {
             console.error(message);
         }
     }
+
+    public toBeUndefined(message?: string) {
+        if (this.actual !== undefined) {
+            if (message === undefined) {
+                console.error(message);
+            } else {
+                console.error(this.actual + " should be undefined");
+            }
+        }
+    }
 }
 
 /**
diff --git a/spec/regime_uniforme/regime_uniforme_puissance.spec.ts b/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
index 37ec2a7ef51c66176e8686675f96ac5875c9dac0..f6088e27c8fcbf41c97d7348fb1cdaa4b23be48b 100644
--- a/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
+++ b/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
@@ -1,12 +1,17 @@
-// tslint:disable-next-line:no-reference
-/// <reference path="../../node_modules/@types/jasmine/index.d.ts" />
+/**
+ * IMPORTANT !
+ * Décommenter temporairement la ligne suivante (import { } from "./mock_jasmine")
+ * Pour exécuter ce code dans le débugger.
+ * Faire de même avec le fichier test_func.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RegimeUniforme } from "../../src/regime_uniforme";
 import { cSnPuiss, ParamsSectionPuiss } from "../../src/section/section_puissance";
 import { MessageCode } from "../../src/util/message";
-import { equalEpsilon, checkResult } from "../test_func";
-import { precDist, precDigits } from "../test_config";
+import { Result } from "../../src/util/result";
+import { precDigits, precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 describe("Class RegimeUniforme / section puissance :", () => {
     describe("pas de débordement :", () => {
diff --git a/spec/structure/parallel_structure.spec.ts b/spec/structure/parallel_structure.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e4601e2dbbf1b0e6365f7022606fc855dac857cf
--- /dev/null
+++ b/spec/structure/parallel_structure.spec.ts
@@ -0,0 +1,39 @@
+/**
+ * IMPORTANT !
+ * Décommenter temporairement la ligne suivante (import { } from "./mock_jasmine")
+ * Pour exécuter ce code dans le débugger.
+ * Faire de même avec le fichier test_func.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
+
+import { ParallelStructure } from "../../src/structure/parallel_structure";
+import { ParallelStructureParams } from "../../src/structure/parallel_structure_params";
+import { Result } from "../../src/util/result";
+import { checkResult } from "../test_func";
+import { structTest } from "./structure_test";
+
+const pstruct: ParallelStructure = new ParallelStructure(
+    new ParallelStructureParams(30, 30, 15), // Q = 30, Z1 = 30, Z2 = 15
+    false // debug
+);
+
+// Test avec deux structures test identiques
+pstruct.addStructure(structTest);
+pstruct.addStructure(structTest);
+
+describe("Class ParallelStructure: ", () => {
+    describe("Calc()", () => {
+        itParallelStructure("Q", 30, 15);
+        itParallelStructure("Z1", 30, 15);
+        itParallelStructure("Z2", 15, 15);
+    });
+});
+
+function itParallelStructure(sVarCalc: string, rVcalc: number, Q: number) {
+    it(`${sVarCalc} should be ${rVcalc}`, () => {
+        const res: Result = pstruct.Calc(sVarCalc);
+        checkResult(res, rVcalc);
+        checkResult(res.extractResult(1), Q);
+        checkResult(res.extractResult(2), Q);
+    });
+}
diff --git a/spec/structure/structure.spec.ts b/spec/structure/structure.spec.ts
index 5a976904d4ac85fe929e717d0d896543288606d3..f1c23d0a8339db96b1e55bcffe6c0f9ee313de5e 100644
--- a/spec/structure/structure.spec.ts
+++ b/spec/structure/structure.spec.ts
@@ -6,42 +6,9 @@
  */
 // import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Structure, StructureFlowMode, StructureFlowRegime, StructureParams } from "../../src/structure/structure";
-import { Result } from "../../src/util/result";
+import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { checkResult } from "../test_func";
-
-class StructureTest extends Structure {
-
-    constructor(prms: StructureParams, dbg: boolean = false) {
-        super(prms, dbg);
-    }
-
-    /**
-     * Test of getFlowMode
-     */
-    public testGetFlowMode() {
-        this.prms.update_h1h2();
-        return this.getFlowMode();
-    }
-
-    /**
-     * Test of getFlowRegime
-     */
-    public testGetFlowRegime() {
-        this.prms.update_h1h2();
-        return this.getFlowRegime();
-    }
-
-    public Equation(sVarCalc: string): Result {
-        this.prms.update_h1h2();
-        this.CheckEquation(sVarCalc);
-        return new Result(this.prms.Z1.v - this.prms.Z2.v);
-    }
-
-}
-
-const structTestPrm: StructureParams = new StructureParams(1, 0, 30, 15);
-const structTest: StructureTest = new StructureTest(structTestPrm, false);
+import { structTest } from "./structure_test";
 
 describe("Class Structure: ", () => {
 
@@ -80,7 +47,7 @@ describe("Class Structure: ", () => {
 
     describe("Calc()", () => {
         const flagsNull = { Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL };
-        it("h1=h2 => Q=0", () => {
+        it("Z1=Z2 => Q=0", () => {
             structTest.prms.Z2.v = structTest.prms.Z1.v;
             checkResult(structTest.Calc("Q"), 0);
             expect(structTest.Calc("Q").extraResults).toEqual(flagsNull);
@@ -92,10 +59,10 @@ describe("Class Structure: ", () => {
             expect(structTest.Calc("Q").extraResults).toEqual(flagsNull);
             structTest.prms.W.v = Infinity;
         });
-        it("Q=0 => h1=h2", () => {
+        it("Q=0 => Z1=Z2", () => {
             structTest.prms.Q.v = 0;
-            checkResult(structTest.Calc("h1"), structTest.prms.h2.v);
-            expect(structTest.Calc("h1").extraResults).toEqual(flagsNull);
+            checkResult(structTest.Calc("Z1"), structTest.prms.h2.v);
+            expect(structTest.Calc("Z1").extraResults).toEqual(flagsNull);
             structTest.prms.Q.v = 1;
         });
         it("Q=0 => W=0", () => {
diff --git a/spec/structure/structure_test.ts b/spec/structure/structure_test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c4e582feafa5f8011717b2fe3b84eec917649034
--- /dev/null
+++ b/spec/structure/structure_test.ts
@@ -0,0 +1,43 @@
+import { Structure, StructureParams } from "../../src/structure/structure";
+import { Result } from "../../src/util/result";
+
+class StructureTest extends Structure {
+
+    constructor(prms: StructureParams, dbg: boolean = false) {
+        super(prms, dbg);
+    }
+
+    /**
+     * Test of getFlowMode
+     */
+    public testGetFlowMode() {
+        this.prms.update_h1h2();
+        return this.getFlowMode();
+    }
+
+    /**
+     * Test of getFlowRegime
+     */
+    public testGetFlowRegime() {
+        this.prms.update_h1h2();
+        return this.getFlowRegime();
+    }
+
+    public Equation(sVarCalc: string): Result {
+        this.prms.update_h1h2();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
+
+        return new Result(this.prms.Z1.v - this.prms.Z2.v, data);
+    }
+
+}
+
+/* Test structure with :
+ *  - ZDV = 0
+ *  - Z1 = 30
+ *  - Z2 = 15
+ *  - expected Q = 15
+ */
+export const structTestPrm: StructureParams = new StructureParams(1, 0, 30, 15);
+export const structTest: StructureTest = new StructureTest(structTestPrm, false);
diff --git a/src/base.ts b/src/base.ts
index 4365b942d68073c04d6fc6d7a26abd39a54cf317..f74f97a4a38d112ac8224622d167b277c5de2fd1 100644
--- a/src/base.ts
+++ b/src/base.ts
@@ -16,6 +16,7 @@ export class Serie {
  * @note Etendre cette classe pour toutes les classes à debugguer
  * Dans le constructeur, utiliser super(true) pour debugger la classe, super(false) sinon.
  */
+// tslint:disable-next-line:max-classes-per-file
 export abstract class Debug {
     /**
      * @param _DBG Flag de débuggage
@@ -27,13 +28,13 @@ export abstract class Debug {
      * @param s Message à afficher dans la console
      */
     public debug(s: any) {
-        if (this._DBG) console.log(s);
+        // tslint:disable-next-line:no-console
+        if (this._DBG) { console.log(s); }
     }
 
     get DBG() { return this._DBG; }
 }
 
-
 /**
  * Méthode simulant l'opérateur booléen xor
  * @see http://www.howtocreate.co.uk/xor.html
@@ -49,16 +50,12 @@ export function BoolIdentity(a: boolean, b: boolean): boolean {
     return (a && b) || (!a && !b);
 }
 
-
 /**
  * arrondi d'un nombre avec une précision donnée
  * @param val nombre à arrondir
  * @param prec nombre de chiffres
  */
 export function round(val: number, prec: number) {
-    let m = Math.pow(10, prec || 0);
+    const m = Math.pow(10, prec || 0);
     return Math.round(val * m) / m;
 }
-
-// export class UndefinedError extends Error {
-// }
diff --git a/src/dichotomie.ts b/src/dichotomie.ts
index 55e4b48a2740ff685d6bd1ff703c68ce5adb3ef1..3b79383e8da773e92fc5548fbdd54d32f2573b08 100644
--- a/src/dichotomie.ts
+++ b/src/dichotomie.ts
@@ -1,12 +1,11 @@
 // import { XOR, BoolIdentity, Debug, Result, ResultCode, UndefinedError } from "./base";
-import { XOR, BoolIdentity, Debug } from "./base";
-import { Result } from "./util/result";
-import { Message, MessageCode } from "./util/message";
+import { BoolIdentity, Debug, XOR } from "./base";
 import { Nub } from "./nub";
-import { ParamDefinition, ParamDomain, ParamDomainValue } from "./param"
-import { Pair } from "./util/pair";
+import { ParamDefinition, ParamDomain, ParamDomainValue } from "./param";
 import { Interval } from "./util/interval";
-
+import { Message, MessageCode } from "./util/message";
+import { Pair } from "./util/pair";
+import { Result } from "./util/result";
 
 class SearchInterval extends Interval {
     private _step: number;
@@ -17,21 +16,21 @@ class SearchInterval extends Interval {
 
     constructor(d: Dichotomie, min: number, max: number, s: number) {
         super(min, max);
-        if (s == 0) {
-            let e = new Message(MessageCode.ERROR_DICHO_NULL_STEP);
+        if (s === 0) {
+            const e = new Message(MessageCode.ERROR_DICHO_NULL_STEP);
             throw e;
         }
         this._step = s;
         this._dicho = d;
     }
 
-    reverse() {
+    public reverse() {
         this._step = -this._step;
     }
 
-    growStep(k: number) {
-        if (k == 0) {
-            let e = new Message(MessageCode.ERROR_DICHO_INVALID_STEP_GROWTH);
+    public growStep(k: number) {
+        if (k === 0) {
+            const e = new Message(MessageCode.ERROR_DICHO_INVALID_STEP_GROWTH);
             throw e;
         }
         this._step *= k;
@@ -42,22 +41,12 @@ class SearchInterval extends Interval {
     }
 
     get targets() {
-        if (this._targets == undefined)
+        if (this._targets === undefined) {
             this._targets = new Pair(undefined, undefined);
+        }
         return this._targets;
     }
 
-    private updateTargets() {
-        let t1 = this.targets.val1;
-        if (t1 == undefined)
-            t1 = this._dicho.CalculX(this._val1).vCalc
-
-        let t2 = this.targets.val2;
-        if (t2 == undefined)
-            t2 = this._dicho.CalculX(this._val2).vCalc;
-        this.targets.setValues(t1, t2);
-    }
-
     /**
      * get target value for lower bound
      */
@@ -74,35 +63,49 @@ class SearchInterval extends Interval {
         return this.targets.val2;
     }
 
-    next() {
+    public next() {
         if (this._step > 0) {
             this._val1 = this._val2;
             this._val2 += this._step;
             this.targets.setValues(this.targets.val2, undefined);
-        }
-        else {
+        } else {
             this._val2 = this._val1;
             this._val1 += this._step;
             this.targets.setValues(undefined, this.targets.val1);
         }
     }
 
-    hasTargetValue(targ: number) {
+    public hasTargetValue(targ: number) {
         this.updateTargets();
         return this.targets.intervalHasValue(targ);
     }
 
-    toString(): string {
+    public toString(): string {
         return super.toString() + " step=" + this._step;
     }
-}
 
+    private updateTargets() {
+        let t1 = this.targets.val1;
+        if (t1 === undefined) {
+            t1 = this._dicho.CalculX(this._val1).vCalc;
+        }
+
+        let t2 = this.targets.val2;
+        if (t2 === undefined) {
+            t2 = this._dicho.CalculX(this._val2).vCalc;
+        }
+        this.targets.setValues(t1, t2);
+    }
+
+}
 
 /**
  * calcul par dichotomie
- * principe : y=f(x1,x2,...), on connait une valeur de y, on cherche par ex le x2 correspondant, les autres xi étant fixés.
+ * principe : y=f(x1,x2,...), on connait une valeur de y,
+ * on cherche par ex le x2 correspondant, les autres xi étant fixés.
  * la méthode Equation() calcule analytiquement y=f(xi)
  */
+// tslint:disable-next-line:max-classes-per-file
 export class Dichotomie extends Debug {
     /**
      * définition de la variable de la fonction
@@ -120,18 +123,19 @@ export class Dichotomie extends Debug {
     private analyticalSymbol: string;
 
     /**
-    * Construction de la classe.
-    * @param nub Noeud de calcul contenant la méthode de calcul Equation
-    * @param sVarCalc Nom de la variable à calculer
-    * @param targetSymbol nom du paramètre calculé analytiquement par Equation()
-    */
-    constructor(private nub: Nub, private sVarCalc: string, dbg: boolean = false, targetSymbol: string = undefined) {
+     * Construction de la classe.
+     * @param nub Noeud de calcul contenant la méthode de calcul Equation
+     * @param sVarCalc Nom de la variable à calculer
+     * @param targetSymbol nom du paramètre calculé analytiquement par Equation()
+     */
+    constructor(private nub: Nub, private sVarCalc: string, dbg: boolean = false, targetSymbol?: string) {
         super(dbg);
         this._paramX = this.nub.getParameter(this.sVarCalc);
-        if (targetSymbol == undefined)
+        if (targetSymbol === undefined) {
             this.analyticalSymbol = this.nub.getFirstAnalyticalParameter().symbol;
-        else
+        } else {
             this.analyticalSymbol = targetSymbol;
+        }
     }
 
     /**
@@ -156,6 +160,40 @@ export class Dichotomie extends Debug {
         this._startIntervalMaxSteps = n;
     }
 
+    public CalculX(x: number): Result {
+        this.vX = x;
+        return this.Calcul();
+    }
+
+    /**
+     * trouve la valeur x pour y=f(x) avec un y donné
+     * @param rTarget valeur de y
+     * @param rTol tolérance pour l'arrêt de la recherche
+     * @param rInit valeur initiale approximative de x
+     */
+    public Dichotomie(rTarget: number, rTol: number, rInit: number): Result {
+        // console.log("-----");
+        // for (let x = 0; x <= 1; x += 0.1)
+        //     console.log(this.CalculX(x).vCalc);
+        // console.log("-----");
+
+        // recherche de l'intervalle de départ
+
+        this.debug(
+            "Dichotomie : valeur cible de " + this.analyticalSymbol + "=" + rTarget
+            + ", valeur initiale de " + this.sVarCalc + "=" + rInit
+        );
+
+        const r = this.getStartInterval(rTarget, rInit);
+        if (r.ok) {
+            const interv: SearchInterval = r.intSearch;
+            // Dichotomie
+            return this.dichoSearch(rTarget, rTol, interv.min, interv.max, interv.targetLower, interv.targetUpper);
+        } else {
+            return new Result(r.res);
+        }
+    }
+
     /**
      * Calcul de l'équation analytique.
      * @note Wrapper vers this.nub.Equation pour simplifier le code.
@@ -163,28 +201,25 @@ export class Dichotomie extends Debug {
      * Il faudra s'assurer que cette première variable correspond à la méthode de calcul la plus rapide
      */
     private Calcul(): Result {
-        let r: Result = this.nub.Equation(this.analyticalSymbol);
-        this.debug("dicho : Calcul(vX=" + this.sVarCalc + "=" + this.vX + ") -> " + this.analyticalSymbol + "=" + r.vCalc);
+        const r: Result = this.nub.Equation(this.analyticalSymbol);
+        this.debug(
+            "dicho : Calcul(vX=" + this.sVarCalc + "=" + this.vX + ") -> " +
+            this.analyticalSymbol + "=" + r.vCalc);
         return r;
     }
 
-    CalculX(x: number): Result {
-        this.vX = x
-        return this.Calcul();
-    }
-
     /**
      * Détermine si une fonction est croissante ou décroissante.
      * @param x point auquel on calcul la dérivée
      * @param dom domaine de définition de la variable
      */
     private isIncreasingFunction(x: number, dom: Interval): boolean {
-        let epsilon = 1e-8;
-        let bounds = new Interval(x - epsilon, x + epsilon);
+        const epsilon = 1e-8;
+        const bounds = new Interval(x - epsilon, x + epsilon);
         bounds.setBounds(bounds.intersect(dom)); // au cas où l'on sorte du domaine de la variable de la fonction
 
-        let y1 = this.CalculX(bounds.min).vCalc;
-        let y2 = this.CalculX(bounds.max).vCalc;
+        const y1 = this.CalculX(bounds.min).vCalc;
+        const y2 = this.CalculX(bounds.max).vCalc;
         return y2 > y1;
     }
 
@@ -200,9 +235,10 @@ export class Dichotomie extends Debug {
         let n = 0;
         let ok: boolean = false;
         do {
-            var inters: Interval = intSearch.intersect(intMax);
-            if (inters.length == 0)
+            const inters: Interval = intSearch.intersect(intMax);
+            if (inters.length === 0) {
                 break;
+            }
             intSearch.setBounds(inters);
             if (intSearch.hasTargetValue(rTarget)) {
                 ok = true;
@@ -223,79 +259,73 @@ export class Dichotomie extends Debug {
     private getStartInterval(rTarget: number, rInit: number): any {
         this.debug("intervalle de départ");
 
-        let prmDom: ParamDomain = this._paramX.getDomain();
-        let step = 0.001;
+        const prmDom: ParamDomain = this._paramX.getDomain();
+        const step = 0.001;
 
-        let min, max;
-        switch (prmDom.domain) {
-            case ParamDomainValue.INTERVAL:
-                min = prmDom.minValue;
-                max = prmDom.maxValue;
-                break;
-
-            case ParamDomainValue.NOT_NULL:
-                if (rInit == 0)
-                    rInit = 1e-8;
-            // pas de break
-
-            default:
-                let a = ParamDomain.getDefaultBounds(prmDom.domain);
-                min = a.min;
-                max = a.max;
+        const min: number = prmDom.minValue;
+        const max: number = prmDom.maxValue;
+        if (prmDom.domain === ParamDomainValue.NOT_NULL) {
+            if (rInit === 0) {
+                rInit = 1e-8;
+            }
         }
 
-        let intMax: Interval = new Interval(min, max);
+        const intMax: Interval = new Interval(min, max);
         try {
             intMax.checkValue(rInit);
-        }
-        catch (m) {
-            return { ok: false, "res": m };
+        } catch (m) {
+            return { ok: false, res: m };
         }
 
         // initialisation de l'intervalle de recherche
         let intSearch: SearchInterval = new SearchInterval(this, rInit - step / 2, rInit + step / 2, step);
-        intSearch.setBounds(intSearch.intersect(intMax)); // au cas où l'on sorte du domaine de la variable de la fonction
+        // au cas où l'on sorte du domaine de la variable de la fonction
+        intSearch.setBounds(intSearch.intersect(intMax));
 
         // sens de variation de la fonction
-        let inc = this.isIncreasingFunction(rInit, intMax);
+        const inc = this.isIncreasingFunction(rInit, intMax);
 
-        let initTarget = this.CalculX(rInit).vCalc;
+        const initTarget = this.CalculX(rInit).vCalc;
         // if (initTarget > rTarget && inc || initTarget < rTarget && !inc)
-        if (BoolIdentity(initTarget > rTarget, inc))
-            intSearch.reverse(); // par ex, la fonction est croissante et la valeur initiale de la variable a une image par la fonction > valeur cible
+        if (BoolIdentity(initTarget > rTarget, inc)) {
+            intSearch.reverse();
+            // par ex, la fonction est croissante et la valeur initiale
+            // de la variable a une image par la fonction > valeur cible
+        }
 
         // on cherche dans une première direction
 
         let a = this.searchTarget(rTarget, intSearch, intMax);
-        if (a.ok)
+        if (a.ok) {
             return a;
+        }
 
         // il se peut que la fonction ne soit pas monotone et qu'il faille chercher dans l'autre direction
 
-        let oldStepSign = intSearch.step > 0 ? 1 : -1;
+        const oldStepSign = intSearch.step > 0 ? 1 : -1;
         intSearch = new SearchInterval(this, rInit + step / 2, rInit + step, step * -oldStepSign);
-        intSearch.setBounds(intSearch.intersect(intMax));  // au cas où l'on sorte du domaine de la variable de la fonction
+        // au cas où l'on sorte du domaine de la variable de la fonction
+        intSearch.setBounds(intSearch.intersect(intMax));
 
         a = this.searchTarget(rTarget, intSearch, intMax);
-        if (a.ok)
+        if (a.ok) {
             return a;
+        }
 
         // gestion de l'erreur
 
         // la valeur cible de la fonction est elle trouvable ?
-
-        let m;
         let res: Message;
         let errDomain = false;
         switch (prmDom.domain) {
             case ParamDomainValue.INTERVAL:
-                let si: SearchInterval = new SearchInterval(this, intMax.min, intMax.max, 1);
+                const si: SearchInterval = new SearchInterval(this, intMax.min, intMax.max, 1);
                 errDomain = !si.hasTargetValue(rTarget);
                 break;
 
             case ParamDomainValue.POS:
             case ParamDomainValue.POS_NULL:
-                let y = this.CalculX(1e-8).vCalc;
+                const y = this.CalculX(1e-8).vCalc;
                 errDomain = inc && (rTarget < y);
                 break;
 
@@ -303,28 +333,28 @@ export class Dichotomie extends Debug {
                 break;
 
             default:
-                throw "unsupported parameter domain value";
+                throw new Error("unsupported parameter domain value");
         }
 
         if (errDomain) {
             res = new Message(MessageCode.ERROR_DICHO_INIT_DOMAIN);
-            res.extraVar["targetSymbol"] = this.analyticalSymbol; // symbole de la variable calculée par la fonction
-            res.extraVar["targetValue"] = rTarget; // valeur cible pour la fonction
-            res.extraVar["variableInterval"] = intMax.toString(); // intervalle de valeurs pour la variable d'entrée de la fonction
-            res.extraVar["variableSymbol"] = this._paramX.symbol; // symbole de la variable d'entrée de la fonction
-        }
-        else {
+            res.extraVar.targetSymbol = this.analyticalSymbol; // symbole de la variable calculée par la fonction
+            res.extraVar.targetValue = rTarget; // valeur cible pour la fonction
+            // intervalle de valeurs pour la variable d'entrée de la fonction
+            res.extraVar.variableInterval = intMax.toString();
+            res.extraVar.variableSymbol = this._paramX.symbol; // symbole de la variable d'entrée de la fonction
+        } else {
             // if (intSearch.step < 0)
-            if (BoolIdentity(initTarget > rTarget, inc))
+            if (BoolIdentity(initTarget > rTarget, inc)) {
                 res = new Message(MessageCode.ERROR_DICHO_INITVALUE_HIGH);
-            else
+            } else {
                 res = new Message(MessageCode.ERROR_DICHO_INITVALUE_LOW);
-
-            res.extraVar["variableSymbol"] = this._paramX.symbol; // symbole de la variable de la fonction
-            res.extraVar["variableInitValue"] = rInit; // valeur initiale de la variable
-            res.extraVar["targetSymbol"] = this.analyticalSymbol; // symbole de la variable calculée par la fonction
-            res.extraVar["targetValue"] = rTarget; // valeur cible pour la fonction
-            res.extraVar["initTarget"] = initTarget; // valeur de la fonction pour la valeur initiale de la variable
+            }
+            res.extraVar.variableSymbol = this._paramX.symbol; // symbole de la variable de la fonction
+            res.extraVar.variableInitValue = rInit; // valeur initiale de la variable
+            res.extraVar.targetSymbol = this.analyticalSymbol; // symbole de la variable calculée par la fonction
+            res.extraVar.targetValue = rTarget; // valeur cible pour la fonction
+            res.extraVar.initTarget = initTarget; // valeur de la fonction pour la valeur initiale de la variable
         }
 
         return { ok: false, res };
@@ -338,56 +368,34 @@ export class Dichotomie extends Debug {
      * @param Ymin valeur de la fonction pour Xmin
      * @param Ymax valeur de la fonction pour Xmax
      */
+    // tslint:disable-next-line:variable-name
     private dichoSearch(Ytarg: number, rTol: number, Xmin: number, Xmax: number, Ymin: number, Ymax: number): Result {
         this.debug("dichoSearch : yTarget " + Ytarg + " X " + Xmin + "->" + Xmax + " tol " + rTol);
 
-        let Xmid = (Xmin + Xmax) / 2;
+        // tslint:disable-next-line:variable-name
+        const Xmid = (Xmin + Xmax) / 2;
 
-        if (Math.abs(Xmin - Xmax) <= rTol)
+        if (Math.abs(Xmin - Xmax) <= rTol) {
             return new Result(Xmid);
+        }
 
-        let Ymid = this.CalculX(Xmid).vCalc;
+        // tslint:disable-next-line:variable-name
+        const Ymid = this.CalculX(Xmid).vCalc;
         if (Ymin < Ymax) {
             // fonction croissante
 
-            if (Ytarg > Ymid)
-                return this.dichoSearch(Ytarg, rTol, Xmid, Xmax, Ymid, Ymax); // intervalle supérieur
+            if (Ytarg > Ymid) {
+                return this.dichoSearch(Ytarg, rTol, Xmid, Xmax, Ymid, Ymax);
+            } // intervalle supérieur
             return this.dichoSearch(Ytarg, rTol, Xmin, Xmid, Ymin, Ymid); // intervalle inférieur
-        }
-        else {
+        } else {
             // fonction décroissante
 
-            if (Ytarg > Ymid)
-                return this.dichoSearch(Ytarg, rTol, Xmin, Xmid, Ymin, Ymid); // intervalle inférieur
+            if (Ytarg > Ymid) {
+                return this.dichoSearch(Ytarg, rTol, Xmin, Xmid, Ymin, Ymid);
+            } // intervalle inférieur
             return this.dichoSearch(Ytarg, rTol, Xmid, Xmax, Ymid, Ymax); // intervalle supérieur
         }
     }
 
-    /**
-     * trouve la valeur x pour y=f(x) avec un y donné
-     * @param rTarget valeur de y
-     * @param rTol tolérance pour l'arrêt de la recherche
-     * @param rInit valeur initiale approximative de x
-     */
-    Dichotomie(rTarget: number, rTol: number, rInit: number): Result {
-        // console.log("-----");
-        // for (let x = 0; x <= 1; x += 0.1)
-        //     console.log(this.CalculX(x).vCalc);
-        // console.log("-----");
-
-        // recherche de l'intervalle de départ
-
-        this.debug("Dichotomie : valeur cible de " + this.analyticalSymbol + "=" + rTarget + ", valeur initiale de " + this.sVarCalc + "=" + rInit);
-
-        let r = this.getStartInterval(rTarget, rInit);
-        if (r.ok)
-            var interv: SearchInterval = r.intSearch;
-        else {
-            return new Result(r.res);
-        }
-
-        // Dichotomie
-
-        return this.dichoSearch(rTarget, rTol, interv.min, interv.max, interv.targetLower, interv.targetUpper);
-    }
 }
diff --git a/src/nub.ts b/src/nub.ts
index d3822c3ab8c3d24aabe033a8a341c5b483683da4..c88151028dc73ab235e781aebaf6b080e70ca7e1 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -1,7 +1,7 @@
-import { Debug, Serie } from "./base"
+import { Debug, Serie } from "./base";
+import { Dichotomie } from "./dichotomie";
+import { ComputeNode, ParamDefinition, ParamsEquation } from "./param";
 import { Result } from "./util/result";
-import { Dichotomie } from "./dichotomie"
-import { ComputeNode, ParamDefinition, ParamsEquation } from "./param"
 
 /**
  * Classe abstraite de Noeud de calcul : classe de base pour tous les calculs
@@ -14,49 +14,58 @@ export abstract class Nub extends ComputeNode {
      */
 
     /**
-    * étapes de recherche de l'intervalle de départ
-    */
+     * étapes de recherche de l'intervalle de départ
+     */
     set dichoStartIntervalMaxSteps(n: number) {
         this._dichoStartIntervalMaxSteps = n;
     }
 
-    /** 
+    /**
      * Formule utilisée pour le calcul analytique (solution directe ou méthode de résolution spécifique)
      */
-    abstract Equation(sVarCalc: string): Result;
+    public abstract Equation(sVarCalc: string): Result;
 
-    /** 
+    /**
      * Calcul d'une équation quelque soit l'inconnue à calculer
      * @param sVarCalc nom de la variable à calculer
      * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie
      * @param rPrec précision de calcul
      */
-    Calc(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result {
-        if (this._prms.map[sVarCalc].isAnalytical())
+    public Calc(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result {
+        if (this._prms.map[sVarCalc].isAnalytical()) {
             return this.Equation(sVarCalc);
+        }
 
-        return this.Solve(sVarCalc, rInit, rPrec);
+        const resSolve: Result = this.Solve(sVarCalc, rInit, rPrec);
+        if (!resSolve.ok) {
+            return resSolve;
+        }
+        const sAnalyticalPrm: string = this.getFirstAnalyticalParameter().symbol;
+        this._prms.map[sVarCalc].v = resSolve.vCalc;
+        const res: Result = this.Equation(sAnalyticalPrm);
+        res.vCalc = resSolve.vCalc;
+        return res;
     }
 
-    CalcSerie(svarCalc: string, serie: Serie): Result[] {
+    public CalcSerie(svarCalc: string, serie: Serie): Result[] {
         /** @todo faire une boucle pour appeler this.Calc avec chaque valeur de serie.values
-         * 
+         *
          */
         // let results = [new (Result)];
-        let results = [new Result(0)];
+        const results = [new Result(0)];
         return results;
     }
 
-    /** 
+    /**
      * Résoud l'équation par une méthode numérique
      * @param sVarCalc nom de la variable à calculer
      * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie
      * @param rPrec précision de calcul
      */
-    Solve(sVarCalc: string, rInit: number, rPrec: number): Result {
-        let dicho: Dichotomie = new Dichotomie(this, sVarCalc, this.DBG);
+    private Solve(sVarCalc: string, rInit: number, rPrec: number): Result {
+        const dicho: Dichotomie = new Dichotomie(this, sVarCalc, this.DBG);
         dicho.startIntervalMaxSteps = this._dichoStartIntervalMaxSteps;
-        var target = this._prms.getFirstAnalyticalParameter();
+        const target = this._prms.getFirstAnalyticalParameter();
         return dicho.Dichotomie(target.v, rPrec, rInit);
     }
 }
diff --git a/src/param.ts b/src/param.ts
index d8aa8ee04f8ff60a352471ec7c15fd86e6efcd7f..32700fab30f383f1dabd7fd2042fc97cc39de408 100644
--- a/src/param.ts
+++ b/src/param.ts
@@ -1,8 +1,8 @@
 // import { Debug, UndefinedError } from './base';
-import { Debug } from './base';
-import { DefinedNumber } from './util/definedvalue';
+import { Debug } from "./base";
+import { DefinedNumber } from "./util/definedvalue";
+import { Interval } from "./util/interval";
 import { Message, MessageCode } from "./util/message";
-import { Interval } from './util/interval';
 
 /**
  * domaine de définition du paramètre
@@ -18,7 +18,6 @@ export enum ParamDomainValue {
      */
     POS_NULL,
 
-
     /**
      * > 0
      */
@@ -36,13 +35,35 @@ export enum ParamDomainValue {
 }
 
 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 = undefined, max: number = undefined) {
+    constructor(d: ParamDomainValue, min?: number, max?: number) {
         this.checkValue(d, min, max);
         this._domain = d;
 
@@ -53,37 +74,13 @@ export class ParamDomain {
                 break;
 
             default:
-                let b = ParamDomain.getDefaultBounds(this._domain);
+                const b = ParamDomain.getDefaultBounds(this._domain);
                 this._minValue = b.min;
                 this._maxValue = b.max;
                 break;
         }
     }
 
-    private checkValue(val: number, min: number, max: number) {
-        switch (val) {
-            case ParamDomainValue.INTERVAL:
-                if (min == undefined || max == undefined || min > max) {
-                    // throw "invalid " + min + "/" + max + " min/max boundaries for 'interval' parameter definition domain"
-                    let 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) {
-                    let e: Message = new Message(MessageCode.ERROR_PARAMDOMAIN_INTERVAL_BOUNDS);
-                    e.extraVar["minValue"] = min;
-                    e.extraVar["maxValue"] = max;
-                    throw e;
-                }
-                break;
-        }
-    }
-
     get domain() {
         return this._domain;
     }
@@ -102,41 +99,44 @@ export class ParamDomain {
                 return new Interval(this._minValue, this._maxValue);
 
             default:
-                let b = ParamDomain.getDefaultBounds(this._domain);
-                return new Interval(b["min"], b["max"]);
+                const b = ParamDomain.getDefaultBounds(this._domain);
+                return new Interval(b.min, b.max);
         }
     }
 
-    public static getDefaultBounds(d: ParamDomainValue): { min: number, max: number } {
-        switch (d) {
+    public clone(): ParamDomain {
+        switch (this._domain) {
             case ParamDomainValue.INTERVAL:
-                let 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 };
+                return new ParamDomain(this._domain, this._minValue, this._maxValue);
 
-            // default:
-            //     throw "valeur de ParamDomainValue" + ParamDomainValue[d] + " non prise en charge";
+            default:
+                return new ParamDomain(this._domain);
         }
     }
 
-    public clone(): ParamDomain {
-        switch (this._domain) {
+    private checkValue(val: number, min: number, max: number) {
+        switch (val) {
             case ParamDomainValue.INTERVAL:
-                return new ParamDomain(this._domain, this._minValue, this._maxValue);
+                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:
-                return new ParamDomain(this._domain);
+                // 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;
         }
     }
+
 }
 
 /**
@@ -167,6 +167,7 @@ export enum ParamCalculability {
 /**
  * paramètre avec symbole et domaine de définition
  */
+// tslint:disable-next-line:max-classes-per-file
 export class BaseParam extends DefinedNumber {
     /**
      * symbole
@@ -178,14 +179,15 @@ export class BaseParam extends DefinedNumber {
      */
     private _domain: ParamDomain;
 
-    constructor(symb: string, d: ParamDomain | ParamDomainValue, val: number = undefined) {
+    constructor(symb: string, d: ParamDomain | ParamDomainValue, val?: number) {
         super(val);
         this._symbol = symb;
 
-        if (d instanceof ParamDomain)
+        if (d instanceof ParamDomain) {
             this._domain = d;
-        else
-            this._domain = new ParamDomain(<ParamDomainValue>d);
+        } else {
+            this._domain = new ParamDomain(d as ParamDomainValue);
+        }
 
         this.checkValue(val);
     }
@@ -194,7 +196,7 @@ export class BaseParam extends DefinedNumber {
         return this._symbol;
     }
 
-    getDomain(): ParamDomain {
+    public getDomain(): ParamDomain {
         return this._domain;
     }
 
@@ -202,22 +204,21 @@ export class BaseParam extends DefinedNumber {
         return this._domain.interval;
     }
 
-
     /**
      * gestion de la valeur
      */
 
-    getValue(): number {
+    public getValue(): number {
         if (!this.isDefined) {
-            let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
-            e.extraVar["symbol"] = this.symbol;
+            const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
+            e.extraVar.symbol = this.symbol;
             throw e;
         }
 
         return super.getValue();
     }
 
-    setValue(val: number) {
+    public setValue(val: number) {
         this.checkValue(val);
         super.setValue(val);
 
@@ -225,7 +226,7 @@ export class BaseParam extends DefinedNumber {
     }
 
     public checkValue(v: number) {
-        let sDomain = ParamDomainValue[this._domain.domain];
+        const sDomain = ParamDomainValue[this._domain.domain];
 
         switch (this._domain.domain) {
             case ParamDomainValue.ANY:
@@ -233,47 +234,47 @@ export class BaseParam extends DefinedNumber {
 
             case ParamDomainValue.POS:
                 if (v <= 0) {
-                    let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_POS);
-                    e.extraVar["symbol"] = this.symbol;
-                    e.extraVar["value"] = v;
-                    throw e;
+                    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) {
-                    let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_POSNULL);
-                    e.extraVar["symbol"] = this.symbol;
-                    e.extraVar["value"] = v;
-                    throw e;
+                    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) {
-                    let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_NULL);
-                    e.extraVar["symbol"] = this.symbol;
-                    throw e;
+                if (v === 0) {
+                    const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_NULL);
+                    f.extraVar.symbol = this.symbol;
+                    throw f;
                 }
                 break;
 
             case ParamDomainValue.INTERVAL:
-                let min = this._domain.minValue;
-                let max = this._domain.maxValue;
+                const min = this._domain.minValue;
+                const max = this._domain.maxValue;
                 if (v < min || v > max) {
-                    let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_INTERVAL);
-                    e.extraVar["symbol"] = this.symbol;
-                    e.extraVar["value"] = v;
-                    e.extraVar["minValue"] = min;
-                    e.extraVar["maxValue"] = max;
-                    throw e;
+                    const f = new Message(MessageCode.ERROR_PARAMDEF_VALUE_INTERVAL);
+                    f.extraVar.symbol = this.symbol;
+                    f.extraVar.value = v;
+                    f.extraVar.minValue = min;
+                    f.extraVar.maxValue = max;
+                    throw f;
                 }
                 break;
 
             default:
-                let e = new Message(MessageCode.ERROR_PARAMDOMAIN_INVALID);
-                e.extraVar["symbol"] = this.symbol;
-                e.extraVar["domain"] = sDomain;
+                const e = new Message(MessageCode.ERROR_PARAMDOMAIN_INVALID);
+                e.extraVar.symbol = this.symbol;
+                e.extraVar.domain = sDomain;
                 throw e;
         }
     }
@@ -282,6 +283,7 @@ export class BaseParam extends DefinedNumber {
 /**
  * définition d'un paramètre d'un neud de calcul
  */
+// tslint:disable-next-line:max-classes-per-file
 export class ParamDefinition extends BaseParam {
     /**
      * calculabilité
@@ -291,7 +293,7 @@ export class ParamDefinition extends BaseParam {
     /**
      * noeud de calcul parent
      */
-    private _computeNodeType: ComputeNodeType
+    private _computeNodeType: ComputeNodeType;
 
     // private static _idGen: number = 0; // A VIRER
     // private _id: number; // A VIRER
@@ -320,9 +322,9 @@ export class ParamDefinition extends BaseParam {
     }
 
     set v(val: number) {
-        if (this.calculability == ParamCalculability.NONE) {
-            let e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED);
-            e.extraVar["symbol"] = this.symbol;
+        if (this.calculability === ParamCalculability.NONE) {
+            const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED);
+            e.extraVar.symbol = this.symbol;
             throw e;
         }
         super.setValue(val);
@@ -335,15 +337,15 @@ export class ParamDefinition extends BaseParam {
     /**
      * variable calculable par l'équation ?
      */
-    isAnalytical(): boolean {
-        return this.calculability == ParamCalculability.EQUATION;
+    public isAnalytical(): boolean {
+        return this.calculability === ParamCalculability.EQUATION;
     }
 
     get calculability(): ParamCalculability {
-        if (this._calc == undefined) {
+        if (this._calc === undefined) {
             //   throw "value of parameter '" + this._symbol + "' calculability is not defined";
-            let e = new Message(MessageCode.ERROR_PARAMDEF_CALC_UNDEFINED);
-            e.extraVar["symbol"] = this.symbol;
+            const e = new Message(MessageCode.ERROR_PARAMDEF_CALC_UNDEFINED);
+            e.extraVar.symbol = this.symbol;
             throw e;
         }
 
@@ -355,27 +357,61 @@ export class ParamDefinition extends BaseParam {
     }
 
     public clone(): ParamDefinition {
-        let res = new ParamDefinition(this._computeNodeType, this.symbol, this.getDomain().clone());
+        const res = new ParamDefinition(this._computeNodeType, this.symbol, this.getDomain().clone());
         res._calc = this._calc;
         res.value = this.uncheckedValue;
         return res;
     }
 }
 
-
 /**
  * liste des paramètres d'une équation
  */
+// tslint:disable-next-line:max-classes-per-file
 export abstract class ParamsEquation {
+
     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))
+        if (!this.hasParameter(p.symbol)) {
             this._paramMap[p.symbol] = p;
+        }
     }
 
     protected addParamDefinitions(ps: ParamsEquation) {
-        for (let pi in ps._paramMap) {
+        for (const pi in ps._paramMap) {
             this.addParamDefinition(ps._paramMap[pi]);
         }
     }
@@ -385,46 +421,20 @@ export abstract class ParamsEquation {
     }
 
     protected checkParametersCalculability() {
-        let res = [];
+        const res = [];
 
-        for (let ps in this._paramMap) {
-            let p: ParamDefinition = this._paramMap[ps];
-            if (p.calculability == undefined)
+        for (const ps in this._paramMap) {
+            const p: ParamDefinition = this._paramMap[ps];
+            if (p.calculability === undefined) {
                 res.push(p.symbol);
+            }
         }
 
-        if (res.length > 0)
-            throw 'Calculability of parameter(s) ' + res.toString() + ' has not been defined';
-    }
-
-    public hasParameter(name: string): boolean {
-        for (let ps in this._paramMap) {
-            let p: ParamDefinition = this._paramMap[ps];
-            if (p.symbol == name)
-                return true;
-        }
-
-        return false;
-    }
-
-    public getParameter(name: string): ParamDefinition {
-        for (let ps in this._paramMap) {
-            let p: ParamDefinition = this._paramMap[ps];
-            if (p.symbol == name)
-                return p;
+        if (res.length > 0) {
+            throw new Error("Calculability of parameter(s) " + res.toString() + " has not been defined");
         }
-
-        throw 'ParamsEquation.getParameter() : invalid parameter name ' + name;
     }
 
-    public getFirstAnalyticalParameter(): ParamDefinition {
-        for (let ps in this._paramMap) {
-            let p: ParamDefinition = this._paramMap[ps];
-            if (p.isAnalytical())
-                return p;
-        }
-        return undefined;
-    }
 }
 
 /**
@@ -446,11 +456,10 @@ export enum ComputeNodeType {
 /**
  * noeud de calcul
  */
+// tslint:disable-next-line:max-classes-per-file
 export abstract class ComputeNode extends Debug {
     protected _prms: ParamsEquation;
 
-    protected abstract setParametersCalculability(): void;
-
     constructor(prms: ParamsEquation, dbg: boolean = false) {
         super(dbg);
         this._prms = prms;
@@ -464,4 +473,7 @@ export abstract class ComputeNode extends Debug {
     public getFirstAnalyticalParameter(): ParamDefinition {
         return this._prms.getFirstAnalyticalParameter();
     }
+
+    protected abstract setParametersCalculability(): void;
+
 }
diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c692fd4b67dc9d68cd7efa14ad3ad1f69bb20e12
--- /dev/null
+++ b/src/structure/parallel_structure.ts
@@ -0,0 +1,152 @@
+import { Nub } from "../nub";
+import { ParamCalculability } from "../param";
+import { Message } from "../util/message";
+import { Result } from "../util/result";
+import { Structure } from "./structure";
+
+import { ParallelStructureParams } from "./parallel_structure_params";
+
+/**
+ * Calcul de une ou plusieurs structures hydrauliques en parallèles
+ * reliées par les cotes amont et aval et dont le débit est égal à la
+ * somme des débits de chaque structure.
+ */
+export class ParallelStructure extends Nub {
+
+    /** Tableau des structures hydrauliques en parallèle */
+    public structures: Structure[] = [];
+
+    /**
+     * paramètres castés au bon type
+     */
+    get prms(): ParallelStructureParams {
+        return this._prms as ParallelStructureParams;
+    }
+
+    /**
+     * Mise à jour de Z1 pour toutes les structures en parallèle
+     */
+    set Z1(Z1: number) {
+        this.prms.Z1.v = Z1;
+        for (const structure of this.structures) {
+            structure.prms.Z1.v = Z1;
+            structure.prms.update_h1h2();
+        }
+    }
+
+    /**
+     * Mise à jour de Z2 pour toutes les structures en parallèle
+     */
+    set Z2(Z2: number) {
+        this.prms.Z2.v = Z2;
+        for (const structure of this.structures) {
+            structure.prms.Z2.v = Z2;
+            structure.prms.update_h1h2();
+        }
+    }
+
+    /**
+     * Ajout d'une structure en parallèle
+     * @param structure La structure à rajouter
+     */
+    public addStructure(structure: Structure) {
+        this.structures.push(structure);
+    }
+
+    /**
+     * Supprime une structure hydraulique
+     * @param index numéro de la structure dans le tableau
+     */
+    public deleteStructure(index: number) {
+        if (index > -1) {
+            this.structures.splice(index, 1);
+        } else {
+            throw new Error("ParallelStructure.deleteStructure invalid index=" + index);
+        }
+    }
+
+    /**
+     * Calcul du débit des structures en parallèle (sans détail pour chaque structure)
+     * @param sVarCalc Variable à calculer (Q uniquement)
+     */
+    public Equation(sVarCalc: string): Result {
+        Structure.CheckEquation(sVarCalc);
+        this.Z1 = this.prms.Z1.v;
+        this.Z2 = this.prms.Z2.v;
+        return this.CalcQ();
+    }
+
+    /**
+     * Calcul de la somme des débits de chaque structure
+     * @param iExcept Index de la structure à ne pas additionner (optionel)
+     */
+    public CalcQ(iExcept?: number): Result {
+        if (iExcept !== undefined) {
+            if (iExcept < 0 || iExcept >= this.structures.length) {
+                throw new Error(
+                    "ParallelStructure.CalcQ iExcept not in [0;" + (this.structures.length - 1) + "]",
+                );
+            }
+        }
+        const calcRes: Result = new Result();
+        let qTot: number = 0;
+        for (let i = 0 ; i < this.structures.length; i++) {
+            if (i !== iExcept) {
+                const res: Result = this.structures[i].Calc("Q");
+                calcRes.addResult(res.result);
+                qTot += res.vCalc;
+            }
+        }
+        // Insert le débit total en premier résultat
+        calcRes.insertResult(new Result(qTot).result, 0);
+        return calcRes;
+    }
+
+    /**
+     * Calcul du débit total, de la cote amont ou aval ou d'un paramètre d'une structure
+     * @param sVarCalc Nom du paramètre à calculer :
+     *                 "Q", "Z1", "Z2" ou "n.X" avec "n" l'index de l'ouvrage et "X" son paramètre
+     * @param rInit Valeur initiale
+     * @param rPrec Précision attendue
+     */
+    public Calc(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result {
+        switch (sVarCalc) {
+            case "Z1" :
+            case "Z2" :
+            case "Q" :
+                return super.Calc(sVarCalc, rInit, rPrec);
+            default:
+                // Pour les caractéristiques des ouvrages
+                return this.CalcStructPrm(sVarCalc, rInit, rPrec);
+        }
+    }
+
+    /**
+     * paramétrage de la calculabilité des paramètres
+     */
+    protected setParametersCalculability() {
+        this.prms.Q.calculability = ParamCalculability.EQUATION;
+        this.prms.Z1.calculability = ParamCalculability.DICHO;
+        this.prms.Z2.calculability = ParamCalculability.DICHO;
+    }
+
+    /**
+     * Calcul du paramètre d'un des ouvrages en parallèle
+     * @param sVarCalc Nom du paramètre à calculer : "n.X" avec "n" l'index de l'ouvrage et "X" son paramètre
+     * @param rInit Valeur initiale
+     * @param rPrec Précision attendue
+     */
+    private CalcStructPrm(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result {
+        // Détection de la structure où calculer le paramètre
+        let sIndex: string;
+        let sPrm: string;
+        [sIndex, sPrm] = sVarCalc.split(".");
+        const index = parseInt(sIndex, 10);
+
+        // Le débit restant sur la structure en calcul est :
+        const qTarget: number = this.prms.Q.v - this.CalcQ(index).vCalc;
+
+        // Calcul du paramètre de la structure en calcul
+        return this.structures[index].Calc(sPrm, rInit, rPrec);
+    }
+}
diff --git a/src/structure/parallel_structure_params.ts b/src/structure/parallel_structure_params.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c7d556dbfc0eb1b920e3da8ea900491eecd8023c
--- /dev/null
+++ b/src/structure/parallel_structure_params.ts
@@ -0,0 +1,32 @@
+import { Nub } from "../nub";
+import { ComputeNodeType, ParamDefinition, ParamDomainValue, ParamsEquation } from "../param";
+
+/**
+ * Common parameters of hydraulic structure equations
+ */
+export class ParallelStructureParams extends ParamsEquation {
+    /** Débit (m3/s) */
+    public Q: ParamDefinition;
+
+    /** Cote de l'eau amont (m) */
+    public Z1: ParamDefinition;
+
+    /** Cote de l'eau aval (m) */
+    public Z2: ParamDefinition;
+
+    /**
+     * Paramètres communs à toutes les équations de structure
+     * @param rQ Débit total (m3/s)
+     * @param rZ1 Cote de l'eau amont (m)
+     * @param rZ2 Cote de l'eau aval (m)
+     */
+    constructor(rQ: number, rZ1: number, rZ2: number) {
+        super();
+        this.Q = new ParamDefinition(ComputeNodeType.CondDistri, "Q", ParamDomainValue.ANY, rQ);
+        this.addParamDefinition(this.Q);
+        this.Z1 = new ParamDefinition(ComputeNodeType.CondDistri, "Z1", ParamDomainValue.ANY, rZ1);
+        this.addParamDefinition(this.Z1);
+        this.Z2 = new ParamDefinition(ComputeNodeType.CondDistri, "Z2", ParamDomainValue.ANY, rZ2);
+        this.addParamDefinition(this.Z2);
+    }
+}
diff --git a/src/structure/rectangular_structure_params.ts b/src/structure/rectangular_structure_params.ts
index 4d5d267e1a5f90482132903ea625e6d31aadd612..485d540bdfa2b17d1d4363d1edcac93da1be0ff4 100644
--- a/src/structure/rectangular_structure_params.ts
+++ b/src/structure/rectangular_structure_params.ts
@@ -10,6 +10,7 @@ export class RectangularStructureParams extends StructureParams {
     public L: ParamDefinition;
 
     /** Discharge coefficient */
+    // tslint:disable-next-line:variable-name
     public Cd: ParamDefinition;
 
     /**
diff --git a/src/structure/structure.ts b/src/structure/structure.ts
index 612c197fb6ebb9ec7c39ec285675904da9135d3e..809ab19b02c5645c081e3dbec810d14c14b6260f 100644
--- a/src/structure/structure.ts
+++ b/src/structure/structure.ts
@@ -11,12 +11,12 @@ export { StructureParams };
  * Flow mode: weir or orifice flow
  */
 export enum StructureFlowMode {
-   /** Weir flow */
-   WEIR,
-   /** Orifice flow */
-   ORIFICE,
-   /** Zéro flow */
-   NULL,
+    /** Weir flow */
+    WEIR,
+    /** Orifice flow */
+    ORIFICE,
+    /** Zéro flow */
+    NULL,
 }
 
 /**
@@ -31,13 +31,20 @@ export enum StructureFlowRegime {
     SUBMERGED,
     /** Zéro flow */
     NULL,
- }
+}
 
 /**
  * classe de calcul sur la conduite distributrice
  */
 export abstract class Structure extends Nub {
 
+    /**
+     * Test générique si VarCalc="Q" pour l'utilisation de Equation
+     */
+    public static CheckEquation(sVarCalc: string) {
+        if (sVarCalc !== "Q") { throw new Error("Structure.Equation() : invalid parameter name " + sVarCalc); }
+    }
+
     /** Constante utile : Racine de 2g */
     protected static readonly R2G: number = Math.sqrt(2 * 9.81);
 
@@ -52,11 +59,6 @@ export abstract class Structure extends Nub {
         return this._prms as StructureParams;
     }
 
-    /**
-     * Calcul du mode et du régime d'écoulement
-     */
-    public abstract Equation(sVarCalc: string): Result;
-
     /**
      * Calcul d'une équation quelque soit l'inconnue à calculer.
      * Gestion du débit nul et de l'inversion de débit
@@ -77,23 +79,42 @@ export abstract class Structure extends Nub {
         } else if (this.prms.Q.v === 0) {
             // Débit nul <=> tirant d'eau amont = tirant d'eau aval ou tout autre paramètre nul
             switch (sVarCalc) {
-                case "h1" :
-                    return new Result(this.prms.h2.v, flagsNull);
-                case "h2" :
-                    return new Result(this.prms.h1.v, flagsNull);
+                case "Z1" :
+                return new Result(this.prms.h2.v, flagsNull);
+                case "Z2" :
+                return new Result(this.prms.h1.v, flagsNull);
                 default :
-                    // Est-ce toujours vrai ? Nécessitera peut-être d'étendre la méthode
-                    return new Result(0, flagsNull);
+                // Est-ce toujours vrai ? Nécessitera peut-être d'étendre la méthode
+                return new Result(0, flagsNull);
             }
-        } else if (this.prms.W.v === 0 && sVarCalc === "h1") {
+        } else if (this.prms.W.v === 0 && sVarCalc === "Z1") {
             return new Result(Infinity, flagsNull); // Si la vanne est fermée la cote amont est infinie
         }
 
+        // Gestion du cas d'écoulement impossible Z1 > Z2 et Q <= 0
+        if (!(sVarCalc === "Q" || sVarCalc === "Z1" || sVarCalc === "Z2")) {
+            if (
+                (this.prms.Z1.v > this.prms.Z2.v && this.prms.Q.v <= 0) ||
+                (this.prms.Z1.v < this.prms.Z2.v && this.prms.Q.v >= 0)
+            ) {
+                // On ferme l'ouvrage et on renvoie un code d'erreur
+                let rPrm: number;
+                switch (sVarCalc) {
+                    case "ZDV":
+                    rPrm = Infinity;
+                    default:
+                    rPrm = 0;
+                }
+                // TODO Ajouter un message d'erreur
+                // "Les cotes et le débit ne sont pas cohérents => fermeture de l'ouvrage
+                return new Result(rPrm, flagsNull);
+            }
+        }
+
         // Gestion de l'inversion de débit : on inverse l'amont et l'aval pour le calcul
         if ((sVarCalc === "Q" && (this.prms.h1.v < this.prms.h2.v)) || (sVarCalc !== "Q" && this.prms.Q.v < 0)) {
             [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion
-            let res: Result;
-            res = super.Calc(sVarCalc, rInit, rPrec);
+            const res: Result = super.Calc(sVarCalc, rInit, rPrec);
             [this.prms.h1.v, this.prms.h2.v] = [this.prms.h2.v, this.prms.h1.v]; // Swap ES6 fashion
             return res;
         }
@@ -102,7 +123,7 @@ export abstract class Structure extends Nub {
         return super.Calc(sVarCalc, rInit, rPrec);
     }
 
-    protected defaultResultData() {
+    protected getResultData() {
         return {
             Mode: this.getFlowMode(),
             Regime: this.getFlowRegime(),
@@ -164,11 +185,4 @@ export abstract class Structure extends Nub {
             return StructureFlowRegime.SUBMERGED;
         }
     }
-
-    /**
-     * Test générique si VarCalc="Q" pour l'utilisation de Equation
-     */
-    protected CheckEquation(sVarCalc: string) {
-        if (sVarCalc !== "Q") { throw new Error("Structure.Equation() : invalid parameter name " + sVarCalc); }
-    }
 }
diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts
index 345e6825f5ca9008efc551a3324ce23c14839b37..27c2405d7bc35b16eb5633bcd088feac5ea74d3d 100644
--- a/src/structure/structure_cem88d.ts
+++ b/src/structure/structure_cem88d.ts
@@ -15,8 +15,8 @@ export class StructureCem88d extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
 
         let v: number;
         const cd: number = this.prms.Cd.v * this.prms.L.v * Structure.R2G;
diff --git a/src/structure/structure_cem88v.ts b/src/structure/structure_cem88v.ts
index cef783f7cb1adb6d65f57ca65d1bfce705b20c05..c0dc94caaaef79047b945e1fd85517529441c697 100644
--- a/src/structure/structure_cem88v.ts
+++ b/src/structure/structure_cem88v.ts
@@ -15,8 +15,8 @@ export class StructureCem88v extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
 
         let v: number;
         const mu0: number = 2 / 3 * this.prms.Cd.v;
diff --git a/src/structure/structure_cunge80.ts b/src/structure/structure_cunge80.ts
index bc8b05c40545d4128eb3351d70b42bc434eae8f0..155aa52ccefcc731842e9645cc77b26d3ffe6060 100644
--- a/src/structure/structure_cunge80.ts
+++ b/src/structure/structure_cunge80.ts
@@ -14,8 +14,8 @@ export class StructureCunge80 extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
         let v: number;
 
         switch (data.Regime) {
diff --git a/src/structure/structure_orifice_free.ts b/src/structure/structure_orifice_free.ts
index 39272136e8abf5a59581bb2e84ed0a02bcb4a0a3..4d18544dcf38ff1823b7a8b9f9b2856bec36a744 100644
--- a/src/structure/structure_orifice_free.ts
+++ b/src/structure/structure_orifice_free.ts
@@ -14,14 +14,16 @@ export class StructureOrificeFree extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
 
-        // TODO : Warning si les conditions hydrauliques ne correspondent pas à un écoulement dénoyé
-        data.Regime = StructureFlowRegime.FREE;
         const v = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v
             * Structure.R2G * Math.sqrt(this.prms.h1.v);
 
         return new Result(v, data);
     }
+
+    protected getFlowRegime() {
+        return StructureFlowRegime.FREE;
+    }
 }
diff --git a/src/structure/structure_orifice_submerged.ts b/src/structure/structure_orifice_submerged.ts
index c8a670153bdffe166825e33770b2427b1eecd966..dd91446e475f119e28d99423f07863ba4d8662df 100644
--- a/src/structure/structure_orifice_submerged.ts
+++ b/src/structure/structure_orifice_submerged.ts
@@ -14,14 +14,16 @@ export class StructureOrificeSubmerged extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être égale à Q ici)
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
 
-        // TODO : Warning si les conditions hydrauliques ne correspondent pas à un écoulement dénoyé
-        data.Regime = StructureFlowRegime.SUBMERGED;
         const v = this.prms.Cd.v * Math.min(this.prms.W.v, this.prms.h1.v) * this.prms.L.v
             * Structure.R2G * Math.sqrt(this.prms.h1.v - this.prms.h2.v);
 
         return new Result(v, data);
     }
+
+    protected getFlowRegime() {
+        return StructureFlowRegime.SUBMERGED;
+    }
 }
diff --git a/src/structure/structure_params.ts b/src/structure/structure_params.ts
index 5929b5bc684b4804d56edf25b92a05ed895728bf..468fd6a43cb48b9e032dcdb416ea052a0723e533 100644
--- a/src/structure/structure_params.ts
+++ b/src/structure/structure_params.ts
@@ -38,13 +38,13 @@ export class StructureParams extends ParamsEquation {
      */
     constructor(rQ: number, rZDV: number, rZ1: number, rZ2: number, rW: number = Infinity ) {
         super();
-        this.Q = new ParamDefinition(ComputeNodeType.CondDistri, "Q", ParamDomainValue.POS_NULL, rQ);
+        this.Q = new ParamDefinition(ComputeNodeType.CondDistri, "Q", ParamDomainValue.ANY, rQ);
         this.addParamDefinition(this.Q);
-        this.ZDV = new ParamDefinition(ComputeNodeType.CondDistri, "ZDV", ParamDomainValue.POS_NULL, rZDV);
+        this.ZDV = new ParamDefinition(ComputeNodeType.CondDistri, "ZDV", ParamDomainValue.ANY, rZDV);
         this.addParamDefinition(this.ZDV);
-        this.Z1 = new ParamDefinition(ComputeNodeType.CondDistri, "Z1", ParamDomainValue.POS_NULL, rZ1);
+        this.Z1 = new ParamDefinition(ComputeNodeType.CondDistri, "Z1", ParamDomainValue.ANY, rZ1);
         this.addParamDefinition(this.Z1);
-        this.Z2 = new ParamDefinition(ComputeNodeType.CondDistri, "Z2", ParamDomainValue.POS_NULL, rZ2);
+        this.Z2 = new ParamDefinition(ComputeNodeType.CondDistri, "Z2", ParamDomainValue.ANY, rZ2);
         this.addParamDefinition(this.Z2);
         this.h1 = new ParamDefinition(ComputeNodeType.CondDistri, "h1", ParamDomainValue.POS_NULL,
             Math.max(0, this.Z1.v - this.ZDV.v));
diff --git a/src/structure/structure_weir_free.ts b/src/structure/structure_weir_free.ts
index 4f862723bb97b245245a9775db7402e63d8e88de..444dc37259efab1ba4d2a4305cc5b7273ce756f0 100644
--- a/src/structure/structure_weir_free.ts
+++ b/src/structure/structure_weir_free.ts
@@ -14,14 +14,19 @@ export class StructureWeirFree extends RectangularStructure {
      * @param sVarCalc Variable à calculer (doit être "Q")
      */
     public Equation(sVarCalc: string): Result {
-        super.CheckEquation(sVarCalc);
-        const data = super.defaultResultData();
+        Structure.CheckEquation(sVarCalc);
+        const data = this.getResultData();
 
-        // TODO : Warning si les conditions hydrauliques ne correspondent pas à un seuil dénoyé
-        data.Regime = StructureFlowRegime.FREE;
-        data.Mode = StructureFlowMode.WEIR;
         const v = this.prms.Cd.v * this.prms.L.v * Structure.R2G * Math.pow(this.prms.h1.v, 1.5);
 
         return new Result(v, data);
     }
+
+    protected getFlowRegime() {
+        return StructureFlowRegime.FREE;
+    }
+
+    protected getFlowMode() {
+        return StructureFlowMode.WEIR;
+    }
 }
diff --git a/src/util/result.ts b/src/util/result.ts
index 2b64d20a6078c2d15e8dc1d2cdd1d7d5b933730c..066a4d72b6c7a8c3a0b5f976804e60658ea53458 100644
--- a/src/util/result.ts
+++ b/src/util/result.ts
@@ -1,6 +1,6 @@
 import { cLog } from "./log";
+import { Message, MessageCode, MessageSeverity } from "./message";
 import { ResultElement } from "./resultelement";
-import { MessageSeverity, Message, MessageCode } from "./message";
 
 /**
  * Résultat global d'un calcul
@@ -18,29 +18,31 @@ export class Result {
     constructor(v?: number | Message | ResultElement, d?: any) {
         this._globalLog = new cLog();
         this._results = [];
-        if (typeof (v) === "number" || v instanceof Message)
+        if (typeof (v) === "number" || v instanceof Message) {
             this._results.push(new ResultElement(v));
-        else if (v instanceof ResultElement)
+        } else if (v instanceof ResultElement) {
             this._results.push(v);
+        }
 
-        if (d != undefined) {
-            for (const i in d) {
-                const re = new ResultElement();
-                re.addExtraResult(i, d[i]);
-            }
+        if (d !== undefined) {
+            this.result.extraResults = d;
         }
     }
 
     /**
-     * retourne le journal du 1er ResultElement
+     * retourne le journal de la calculette
      */
     public get globalLog() {
         return this._globalLog;
     }
 
-    private get result(): ResultElement {
-        if (this._results.length == 0)
+    /**
+     * Retourne le résultat du premier ResultElement
+     */
+    get result(): ResultElement {
+        if (this._results.length === 0) {
             throw new Error("appel à la méthode de Result.result() invalide, il n'y a pas au moins un 'ResultElement'");
+        }
 
         return this._results[0];
     }
@@ -59,6 +61,13 @@ export class Result {
         return this.result.vCalc;
     }
 
+    /**
+     * @return le résultat de calcul du 1er ResultElement
+     */
+    set vCalc(r: number) {
+        this.result.vCalc = r;
+    }
+
     /**
      * retourne le journal du 1er ResultElement
      */
@@ -75,12 +84,27 @@ export class Result {
     }
 
     /**
-      * retourne les résultats complémentaires du 1er ResultElement
-      */
+     * retourne les résultats complémentaires du 1er ResultElement
+     */
     get extraResults() {
         return this.result.extraResults;
     }
 
+    /**
+     * Extract one ResultElement as a Result
+     * @param i index of the ResultElement
+     */
+    public extractResult(i: number): Result {
+        if (i < 0 || i >= this._results.length) {
+            throw new Error("Result.extractResult index outside [0;" + (this._results.length - 1) + "]");
+        }
+        return new Result(this._results[i]);
+    }
+
+    /**
+     * Ajoute un ResultElement au tableau
+     * @param r ResultElement à ajouter
+     */
     public addResult(r: ResultElement) {
         this._results.push(r);
     }
@@ -124,7 +148,8 @@ export class Result {
 
             default:
                 throw new Error(
-                    "Result.getExtraResult() : il existe plusieurs ResultElement avec un extratresult dont le nom est '" + name + "'",
+                    "Result.getExtraResult() : il existe plusieurs ResultElement avec" +
+                    " un extratresult dont le nom est '" + name + "'",
                 );
         }
     }
@@ -182,12 +207,13 @@ export class Result {
      * @returns true si au moins un message de log comporte un code d'erreur
      */
     public get hasErrorMessages(): boolean {
-        for (const m of this.log.messages) {
+        // Test du journal global
+        for (const m of this._globalLog.messages) {
             if (m.getSeverity() === MessageSeverity.ERROR) {
                 return true;
             }
         }
-
+        // Test des journaux des résultats
         for (const r of this._results) {
             if (r.hasErrorMessages) {
                 return true;
diff --git a/src/util/resultelement.ts b/src/util/resultelement.ts
index 8d58b6f4cbeddd67457517e8ab9868c5818d8c3f..dc301486fdeeabcfc22d9e77a3a37418139c546f 100644
--- a/src/util/resultelement.ts
+++ b/src/util/resultelement.ts
@@ -34,6 +34,10 @@ export class ResultElement {
 
     get vCalc() { return this._vCalc; }
 
+    set vCalc(r: number) {
+        this._vCalc = r;
+    }
+
     public get log() {
         return this._log;
     }
@@ -95,10 +99,14 @@ export class ResultElement {
      * résultats complémentaires
      */
 
-    public get extraResults() {
+    get extraResults() {
         return this._extraResults;
     }
 
+    set extraResults(d: { [key: string]: any }) {
+        this._extraResults = d;
+    }
+
     public addExtraResult(name: string, value: any) {
         this._extraResults[name] = value;
     }
diff --git a/tslint.json b/tslint.json
index dfff889c26a98d256d0c7ab79ff413ac5e6e894c..e74a30c408954408442094702dbca063db8137a9 100644
--- a/tslint.json
+++ b/tslint.json
@@ -4,6 +4,12 @@
         "tslint:recommended"
     ],
     "jsRules": {},
-    "rules": {},
+    "rules": {
+        "variable-name": [true,
+            "check-format",
+            "allow-leading-underscore"
+        ],
+        "trailing-comma": [false]
+    },
     "rulesDirectory": []
 }
\ No newline at end of file