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/base.spec.ts b/spec/base.spec.ts
index 1c61ec68a92c1d931d2e99808a52641cf607d764..8f000e314ed60a88683806e034715737068bea87 100644
--- a/spec/base.spec.ts
+++ b/spec/base.spec.ts
@@ -1,6 +1,7 @@
 /// <reference path="../node_modules/@types/jasmine/index.d.ts" />
 
-import { nub, precDigits } from "./nubtest";
+import { nub } from "./nubtest";
+import { precDigits } from "./test_config";
 import { Message, MessageCode, MessageSeverity } from "../src/util/message";
 
 
diff --git a/spec/cond_distri.spec.ts b/spec/cond_distri.spec.ts
index fc6fe224613958965102662f411285cfe3546043..ec93042b6fc3ea956a7f7bba38bba3c3e1ad3be5 100644
--- a/spec/cond_distri.spec.ts
+++ b/spec/cond_distri.spec.ts
@@ -1,13 +1,8 @@
 // tslint:disable-next-line:no-reference
 /// <reference path="../node_modules/@types/jasmine/index.d.ts" />
 
-import { Result } from "../src/util/result";
 import { ConduiteDistrib, ConduiteDistribParams } from "../src/cond_distri";
-import { equalEpsilon } from "./nubtest";
-
-function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBe(true);
-}
+import { checkResult } from "./test_func";
 
 describe("Class ConduiteDistrib: ", () => {
     // beforeEach(() => {
@@ -26,7 +21,7 @@ describe("Class ConduiteDistrib: ", () => {
 
             const nub = new ConduiteDistrib(prms);
 
-            check(nub.Calc("Q"), 9.393);
+            checkResult(nub.Calc("Q"), 9.393);
         });
     });
 
@@ -45,7 +40,7 @@ describe("Class ConduiteDistrib: ", () => {
             nub.prms.Lg.v = 10;
             nub.prms.Nu.v = 1e-6;
 
-            check(nub.Calc("Q"), 152.992);
+            checkResult(nub.Calc("Q"), 152.992);
         });
     });
 
@@ -60,7 +55,7 @@ describe("Class ConduiteDistrib: ", () => {
 
             const nub = new ConduiteDistrib(prms);
 
-            check(nub.Calc("D"), 2.12847);
+            checkResult(nub.Calc("D"), 2.12847);
         });
     });
 
@@ -75,7 +70,7 @@ describe("Class ConduiteDistrib: ", () => {
 
             const nub = new ConduiteDistrib(prms);
 
-            check(nub.Calc("J"), 0.00814);
+            checkResult(nub.Calc("J"), 0.00814);
         });
     });
 
@@ -90,7 +85,7 @@ describe("Class ConduiteDistrib: ", () => {
 
             const nub = new ConduiteDistrib(prms);
 
-            check(nub.Calc("Lg"), 737.021);
+            checkResult(nub.Calc("Lg"), 737.021);
         });
     });
 
@@ -105,7 +100,7 @@ describe("Class ConduiteDistrib: ", () => {
 
             const nub = new ConduiteDistrib(prms);
 
-            check(nub.Calc("Nu"), 0.00295);
+            checkResult(nub.Calc("Nu"), 0.00295);
         });
     });
 });
diff --git a/spec/iterator/array_reverse_iterator.spec.ts b/spec/iterator/array_reverse_iterator.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a783167af6f90dbc58c709cd768c609284c33172
--- /dev/null
+++ b/spec/iterator/array_reverse_iterator.spec.ts
@@ -0,0 +1,40 @@
+/// <reference path="../../node_modules/@types/jasmine/index.d.ts" />
+
+import { ArrayReverseIterator } from "../../src/util/iterator";
+
+describe('array reverse iterator : ', () => {
+    it("reverse ( undefined )", () => {
+        const arr: Object[] = undefined;
+        const it = new ArrayReverseIterator<Object>(arr);
+        expect(it.next().done).toBeTruthy();
+    });
+
+    it("reverse( [] )", () => {
+        const arr: Object[] = [];
+        const it = new ArrayReverseIterator<Object>(arr);
+        expect(it.next().done).toBeTruthy();
+    });
+
+    it("reverse( [1] )", () => {
+        const arr: number[] = [1];
+        const it = new ArrayReverseIterator<number>(arr);
+        const v1 = it.next();
+        expect(v1.done).toBeFalsy();
+        expect(v1.value).toEqual(1);
+        const v2 = it.next();
+        expect(v2.done).toBeTruthy();
+    });
+
+    it("reverse( [1,2] )", () => {
+        const arr: number[] = [1, 2];
+        const it = new ArrayReverseIterator<number>(arr);
+        const v1 = it.next();
+        expect(v1.done).toBeFalsy();
+        expect(v1.value).toEqual(2);
+        const v2 = it.next();
+        expect(v2.done).toBeFalsy();
+        expect(v2.value).toEqual(1);
+        const v3 = it.next();
+        expect(v3.done).toBeTruthy();
+    });
+});
diff --git a/spec/iterator/map_iterator.spec.ts b/spec/iterator/map_iterator.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb6eacad19a4368759a4eab371e678f1c5b210bb
--- /dev/null
+++ b/spec/iterator/map_iterator.spec.ts
@@ -0,0 +1,75 @@
+/// <reference path="../../node_modules/@types/jasmine/index.d.ts" />
+
+import { MapIterator } from "../../src/util/iterator";
+
+describe('param map iterator : ', () => {
+    it("sur undefined", () => {
+        const it: MapIterator<any> = new MapIterator(undefined);
+
+        const v1 = it.next();
+        expect(v1.done).toBeTruthy();
+        expect(v1.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+
+        const v2 = it.next();
+        expect(v2.done).toBeTruthy();
+        expect(v2.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+    });
+
+    it("sur {}", () => {
+        const it: MapIterator<any> = new MapIterator({});
+
+        const v1 = it.next();
+        expect(v1.done).toBeTruthy();
+        expect(v1.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+
+        const v2 = it.next();
+        expect(v2.done).toBeTruthy();
+        expect(v2.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+    });
+
+    it("sur {'a':1}", () => {
+        const o = { "a": 1 };
+        const it: MapIterator<number> = new MapIterator(o);
+
+        const v1 = it.next();
+        expect(v1.done).toBeTruthy();
+        expect(v1.value).toEqual(1);
+        expect(it.key).toEqual("a");
+        expect(it.index).toEqual(0);
+
+        const v2 = it.next();
+        expect(v2.done).toBeTruthy();
+        expect(v2.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+    });
+
+    it("sur {'a':1, 'b':2}", () => {
+        const o = { "a": 1, "b": 2 };
+        const it: MapIterator<number> = new MapIterator(o);
+
+        const v1 = it.next();
+        expect(v1.done).toBeFalsy();
+        expect(v1.value).toEqual(1);
+        expect(it.key).toEqual("a");
+
+        const v2 = it.next();
+        expect(v2.done).toBeTruthy();
+        expect(v2.value).toEqual(2);
+        expect(it.key).toEqual("b");
+
+        const v3 = it.next();
+        expect(v3.done).toBeTruthy();
+        expect(v3.value).toBeUndefined();
+        expect(it.key).toBeUndefined();
+        expect(it.index).toBeUndefined();
+    });
+});
diff --git a/spec/iterator/param_equation.spec.ts b/spec/iterator/param_equation.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b6a26d3ceb96eb847fce8cbdbb7e5ce017b433f
--- /dev/null
+++ b/spec/iterator/param_equation.spec.ts
@@ -0,0 +1,33 @@
+/// <reference path="../../node_modules/@types/jasmine/index.d.ts" />
+
+import { ConduiteDistribParams, ConduiteDistrib } from "../../src/cond_distri";
+import { ParamDefinition } from "../../src/index";
+
+describe("iterator ConduiteDistribParams : ", () => {
+    it("test 1", () => {
+        const cdp: ConduiteDistribParams = new ConduiteDistribParams(1, 2, 3, 4, 5)
+
+        let n = 0;
+        for (let p of cdp) {
+            n++;
+            expect(p.v == n);
+        }
+        expect(n === 5);
+    });
+
+    it("test 2", () => {
+        const cdp: ConduiteDistribParams = new ConduiteDistribParams(1, 2, 3, 4, 5)
+
+        const symbs = ["Q", "D", "J", "Lg", "Nu"];
+        let n = 0;
+        const it = cdp.iterator;
+        do {
+            var itnext = it.next();
+            const p: ParamDefinition = itnext.value;
+            expect(p.v == n + 1);
+            expect(p.symbol == symbs[n]);
+            n++;
+        } while (!itnext.done)
+        expect(n === 5);
+    });
+});
diff --git a/spec/lechaptcalmon.spec.ts b/spec/lechaptcalmon.spec.ts
index 076c66e1ff0f5e0f5ac7600dcf1c85980aae3fd8..573a60b30c29efdb56db7621683806713f973442 100644
--- a/spec/lechaptcalmon.spec.ts
+++ b/spec/lechaptcalmon.spec.ts
@@ -1,16 +1,11 @@
 /// <reference path="../node_modules/@types/jasmine/index.d.ts" />
 
-import { Result } from "../src/util/result";
-import { equalEpsilon } from "./nubtest";
 import { LechaptCalmonParams, LechaptCalmon } from "../src/lechaptcalmon"
+import { checkResult } from "./test_func";
 
 let lechapt: LechaptCalmon;
 let prms: LechaptCalmonParams;
 
-function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBe(true);
-}
-
 describe('Class LechaptCalmon : ', () => {
     describe('Calc() : ', () => {
         it('Q should be 2.917', () => {
@@ -24,7 +19,7 @@ describe('Class LechaptCalmon : ', () => {
             );
             lechapt = new LechaptCalmon(prms);
 
-            check(lechapt.Calc("Q"), 2.917);
+            checkResult(lechapt.Calc("Q"), 2.917);
         });
 
         it('D should be 1.213', () => {
@@ -38,7 +33,7 @@ describe('Class LechaptCalmon : ', () => {
             );
             lechapt = new LechaptCalmon(prms);
 
-            check(lechapt.Calc("D"), 1.213);
+            checkResult(lechapt.Calc("D"), 1.213);
         });
 
         it('J should be 0.634', () => {
@@ -52,7 +47,7 @@ describe('Class LechaptCalmon : ', () => {
             );
             lechapt = new LechaptCalmon(prms);
 
-            check(lechapt.Calc("J"), 0.634);
+            checkResult(lechapt.Calc("J"), 0.634);
         });
 
         it('Lg should be 94.565', () => {
@@ -66,7 +61,7 @@ describe('Class LechaptCalmon : ', () => {
             );
             lechapt = new LechaptCalmon(prms);
 
-            check(lechapt.Calc("Lg"), 94.565);
+            checkResult(lechapt.Calc("Lg"), 94.565);
         });
     });
 });
diff --git a/spec/mock_jasmine.ts b/spec/mock_jasmine.ts
index 134851d5b0d9379cf18827c8a3728af29e8315ab..2a9c3fb0928a4f2d21eed9cd4476115d4acf2e55 100644
--- a/spec/mock_jasmine.ts
+++ b/spec/mock_jasmine.ts
@@ -1,10 +1,10 @@
+// tslint:disable:no-console
 /**
  * Mock fonction describe de Jasmine
  * @param sTxt Texte de la suite de test
  * @param fFun Fonction de la suite de test
  */
 export function describe(sTxt: string, fFun: () => void) {
-    // tslint:disable-next-line:no-console
     console.log(sTxt);
     fFun();
 }
@@ -15,7 +15,6 @@ export function describe(sTxt: string, fFun: () => void) {
  * @param fFun Fonction de la suite de test
  */
 export function xdescribe(sTxt: string, fFun: () => void) {
-    // tslint:disable-next-line:no-console
     console.log(sTxt + " ignored ***");
 }
 
@@ -25,7 +24,6 @@ export function xdescribe(sTxt: string, fFun: () => void) {
  * @param fFun Function à lancer pour la spec
  */
 export function it(sTxt: string, fFun: () => void) {
-    // tslint:disable-next-line:no-console
     console.log(sTxt);
     fFun();
 }
@@ -52,8 +50,7 @@ class Expect {
         const delta = Math.abs(expected - this.actual);
         const maxDelta = Math.pow(10, -precision) / 2;
         if (Math.round(delta * pow) / pow > maxDelta) {
-            // tslint:disable-next-line:no-console
-            console.error("Expected " + this.actual + " to be close to " + expected + "," + precision);
+            console.error("Expected " + this.actual + " to be close to " + expected + " with precision " + precision);
         }
         return this;
     }
@@ -63,7 +60,11 @@ class Expect {
      * @param expected Objet de référence
      */
     public toBe(expected: any) {
-        return this.actual === expected;
+        const res = this.actual === expected;
+        if (!res) {
+            console.error("Error : expected " + this.actual + " to be " + expected);
+        }
+        return res;
     }
 
     /**
@@ -71,9 +72,42 @@ class Expect {
      * @param expected Objet de référence
      */
     public toEqual(expected: any) {
-        return this.actual === expected;
+        const res = this.actual === expected;
+        if (!res) {
+            console.warn("Warning : test 'to be equal to' not tested");
+        }
+        return res;
+    }
+
+    /**
+     * Mock de la fonction toBeTruthy de Jasmine : the actual value should be true
+     * @param message message d'erreur
+     */
+    public toBeTruthy(message: string) {
+        if (!this.actual) {
+            console.error(message);
+        }
     }
 
+    /**
+     * Mock de la fonction toBeFalsy de Jasmine : the actual value should be false
+     * @param message message d'erreur
+     */
+    public toBeFalsy(message: string) {
+        if (this.actual) {
+            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/nubtest.ts b/spec/nubtest.ts
index ef4affddfd3b37eb7b9e7c7c95e65b9f856a3b20..5ed87f706f82a99ead44bb06a76fc33ac4d3bb5f 100644
--- a/spec/nubtest.ts
+++ b/spec/nubtest.ts
@@ -1,10 +1,6 @@
 import { Result } from "../src/util/result";
 import { Nub } from "../src/nub";
-import {
-    ComputeNodeType, ParamCalculability, ParamDefinition, ParamDomain, ParamDomainValue, ParamsEquation,
- } from "../src/param";
-import { cLog } from "../src/util/log";
-import { Message, MessageCode } from "../src/util/message";
+import { ComputeNodeType, ParamCalculability, ParamDefinition, ParamDomainValue, ParamsEquation } from "../src/param";
 
 class NubTestParams extends ParamsEquation {
     private _A: ParamDefinition;
@@ -57,175 +53,3 @@ export class NubTest extends Nub {
 }
 
 export let nub = new NubTest(new NubTestParams());
-
-/**
- * précision de calcul (nombre de décimales)
- */
-export let precDigits = 3;
-
-/**
- * précision de calcul (max de abs(v-v'))
- */
-export let precDist: number = Math.pow(10, -precDigits);
-
-/**
- * Compare deux valeurs réelles à un epsilon près
- * @param val1 Première valeur à comparer
- * @param val2 Deuxième valeur à comparer
- * @param epsilon Erreur de comparaison acceptable
- * @return Vrai si les valeurs sont égales, faux sinon
- */
-export function equalEpsilon(val1: number, val2: number, epsilon: number = precDist) {
-    return Math.abs(val1 - val2) < epsilon;
-}
-
-/**
- * Test jasmine de deux valeurs réelles à un epsilon près
- * @param val1 Première valeur à comparer
- * @param val2 Deuxième valeur à comparer
- */
-export function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBe(true);
-}
-
-/**
- * compare 2 objets
- * @param s message
- * @param objTest objet à tester
- * @param objValid objet de référence
- * @param epsilon tolérance pour les comparaisons de nombres
- */
-export function compareObject(
-    s: string,
-    objTest: { [key: number]: number },
-    objValid: { [key: number]: number },
-    epsilon: number,
-) {
-    const n1 = Object.keys(objTest).length;
-    const n2 = Object.keys(objValid).length;
-    let b: boolean = n1 === n2;
-    expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
-    if (!b) { return; }
-
-    for (let i = 0; i < n1; i++) {
-        const v1: number = objTest[+Object.keys(objTest)[i]];
-        const v2: number = objValid[+Object.keys(objValid)[i]];
-        b = equalEpsilon(v1, v2, epsilon);
-        expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
-        if (!b) { return; }
-    }
-}
-
-/**
- * compare 2 tableaux
- * @param s message
- * @param arrTest tableau à tester
- * @param arrValid tableau de référence
- */
-export function compareArray(s: string, arrTest: string[], arrValid: number[]) {
-    const n1 = arrTest.length;
-    const n2 = arrValid.length;
-    let b: boolean = n1 === n2;
-    expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
-    if (!b) { return; }
-
-    for (let i = 0; i < arrTest.length; i++) {
-        const v1: number = +arrTest[i];
-        const v2: number = arrValid[i];
-        b = equalEpsilon(v1, v2);
-        expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
-        if (!b) { return; }
-    }
-}
-
-/**
- * compare 2 journaux
- */
-export function compareLog(logTest: cLog, logValid: cLog) {
-    // console.log(JSON.stringify(logTest));
-    // console.log("journal :\n" + logTest.toString());
-
-    // taille
-
-    const n1 = logTest.messages.length;
-    const n2 = logValid.messages.length;
-    let b: boolean = n1 === n2;
-    expect(b).toBeTruthy("journal : nombre de messages incorrect (" + n1 + "), devrait etre " + n2);
-    if (!b) { return; }
-
-    // codes
-
-    for (let i = 0; i < n1; i++) {
-        const m1: Message = logTest.messages[i];
-        const m2: Message = logValid.messages[i];
-        b = m1.code === m2.code;
-        expect(b).toBeTruthy(
-            "journal : message n°" + i + ", code " + MessageCode[m1.code]
-            + " incorrect, devrait être " + MessageCode[m2.code],
-        );
-        if (!b) { return; }
-    }
-
-    // données
-
-    for (let i = 0; i < n1; i++) {
-        const m1: Message = logTest.messages[i];
-        const m2: Message = logValid.messages[i];
-        const code1 = MessageCode[m1.code];
-
-        // taille des données
-
-        const nd1 = Object.keys(m1.extraVar).length;
-        const nd2 = Object.keys(m2.extraVar).length;
-        b = nd1 === nd2;
-        expect(b).toBeTruthy(
-            "journal : message n°" + i + ", code " + code1 + " : nombre de données incorrect "
-            + nd1 + ", devrait etre " + nd2,
-        );
-        if (!b) { return; }
-
-        // clés des données
-
-        for (const j in m1.extraVar) {
-            b = m2.extraVar[j] !== undefined;
-            expect(b).toBeTruthy(
-                "journal : message n°" + i + ", code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
-                + " ne devrait pas être présente");
-            // if (!b) return;
-        }
-
-        for (const j in m2.extraVar) {
-            b = m1.extraVar[j] !== undefined;
-            expect(b).toBeTruthy(
-                "journal : message n°" + i + ", code " + code1 + " : la donnée " + j + "=" + m2.extraVar[j]
-                + " devrait être présente");
-            // if (!b) return;
-        }
-
-        // type des données
-
-        for (const j in m1.extraVar) {
-            b = typeof m1.extraVar[j] === typeof m2.extraVar[j];
-            expect(b).toBeTruthy(
-                "journal : " + i + "ieme message, code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
-                + " a un type " + (typeof m1.extraVar[j]) + " incorrect, devrait être du type "
-                + (typeof m2.extraVar[j]));
-            if (!b) { return; }
-        }
-
-        // valeur des données
-
-        for (const j in m1.extraVar) {
-            const d: any = m1.extraVar[j];
-            if (typeof d === "number") {
-                b = equalEpsilon(d, m2.extraVar[j]);
-            } else {
-                b = d === m2.extraVar[j];
-            }
-            expect(b).toBeTruthy(
-                "journal : " + i + "ieme message, code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
-                + " a une valeur incorrecte, devrait être " + m2.extraVar[j]);
-            if (!b) { return; }
-        }
-    }
-}
diff --git a/spec/pab/pab_dimension.spec.ts b/spec/pab/pab_dimension.spec.ts
index 33808a7aa1a7a38575865152a2a01e3630f6b731..1b217e1897744f0689e8e6147a55d5dd6eeeed4d 100644
--- a/spec/pab/pab_dimension.spec.ts
+++ b/spec/pab/pab_dimension.spec.ts
@@ -3,7 +3,7 @@
 
 import { Result } from "../../src/util/result";
 import { PabDimension, PabDimensionParams } from "../../src/pab/pab_dimension";
-import { check } from "../nubtest";
+import { checkResult } from "../test_func";
 
 function pabDimensionTest(varTest: string) {
     describe("Calc(): ", () => {
@@ -20,7 +20,7 @@ function pabDimensionTest(varTest: string) {
             const nub = new PabDimension(prms);
             prms[varTest].v = undefined;
 
-            check(nub.Calc(varTest), res);
+            checkResult(nub.Calc(varTest), res);
         });
     });
 }
diff --git a/spec/pab/pab_puissance.spec.ts b/spec/pab/pab_puissance.spec.ts
index 5da5561a996b3adf45c602ccf3d3a42571124e32..a8856b4b4caf71ab6c5ae604efea3a5b06da474d 100644
--- a/spec/pab/pab_puissance.spec.ts
+++ b/spec/pab/pab_puissance.spec.ts
@@ -3,7 +3,7 @@
 
 import { Result } from "../../src/util/result";
 import { PabPuissance, PabPuissanceParams } from "../../src/pab/pab_puissance";
-import { check } from "../nubtest";
+import { checkResult } from "../test_func";
 
 function PabPuissanceTest(varTest: string) {
     describe("Calc(): ", () => {
@@ -20,7 +20,7 @@ function PabPuissanceTest(varTest: string) {
             const nub = new PabPuissance(prms);
             prms[varTest].v = undefined;
 
-            check(nub.Calc(varTest, 1e-9), res);
+            checkResult(nub.Calc(varTest, 1e-9), res);
         });
     });
 }
diff --git a/spec/regime_uniforme/regime_uniforme_circ.spec.ts b/spec/regime_uniforme/regime_uniforme_circ.spec.ts
index 720976c225d74be59be2364f7ffa35093fc83e19..076ca634672d756293b6c8fe4e53a2ec9fc9d62f 100644
--- a/spec/regime_uniforme/regime_uniforme_circ.spec.ts
+++ b/spec/regime_uniforme/regime_uniforme_circ.spec.ts
@@ -4,12 +4,8 @@
 import { Result } from "../../src/util/result";
 import { RegimeUniforme } from "../../src/regime_uniforme";
 import { cSnCirc, ParamsSectionCirc } from "../../src/section/section_circulaire";
-import { equalEpsilon, precDist } from "../nubtest";
-
-function check(val1: Result, val2: number) {
-    // expect(val1).toBeCloseTo(val2);
-    expect(equalEpsilon(val1.vCalc, val2)).toBeTruthy("expected " + val2 + ", got " + val1.vCalc);
-}
+import { equalEpsilon, checkResult } from "../test_func";
+import { precDigits, precDist } from "../test_config";
 
 describe("Class RegimeUniforme / section circulaire :", () => {
     describe("pas de débordement : ", () => {
@@ -25,7 +21,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSect);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("D", 1e-8), 6.001);
+            checkResult(ru.Calc("D", 1e-8), 6.001);
         });
 
         it("Ks should be 40.003", () => {
@@ -40,7 +36,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 40.003);
+            checkResult(ru.Calc("Ks", 1e-8), 40.003);
         });
 
         it("If should be 0.001", () => {
@@ -55,7 +51,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("If"), 0.001);
+            checkResult(ru.Calc("If", 0.0001), 0.001);
         });
 
         it("Q should be 1.2", () => {
@@ -70,7 +66,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 1.2);
+            checkResult(ru.Calc("Q"), 1.2);
         });
 
         it("Y should be 0.6613", () => {
@@ -85,7 +81,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Y"), 0.6613);
+            checkResult(ru.Calc("Y"), 0.6613);
         });
     });
 
@@ -102,7 +98,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSect);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("D", 1e-8), 2);
+            checkResult(ru.Calc("D", 1e-8), 2);
         });
 
         it("Ks should be 13.551", () => {
@@ -117,7 +113,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 13.551);
+            checkResult(ru.Calc("Ks", 1e-8), 13.551);
         });
 
         it("If should be 0.001", () => {
@@ -132,7 +128,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("If"), 0.001);
+            checkResult(ru.Calc("If"), 0.001);
         });
 
         it("Q should be 1.2", () => {
@@ -147,7 +143,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 1.2);
+            checkResult(ru.Calc("Q"), 1.2);
         });
 
         it("Y should be 2", () => {
@@ -162,7 +158,7 @@ describe("Class RegimeUniforme / section circulaire :", () => {
             const sect = new cSnCirc(paramSection);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Y"), 2);
+            checkResult(ru.Calc("Y"), 2);
         });
     });
 });
diff --git a/spec/regime_uniforme/regime_uniforme_puissance.spec.ts b/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
index 54c9221eaf4f138f26c098b1bc09b3d43dc60658..f6088e27c8fcbf41c97d7348fb1cdaa4b23be48b 100644
--- a/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
+++ b/spec/regime_uniforme/regime_uniforme_puissance.spec.ts
@@ -1,15 +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, precDist } from "../nubtest";
-
-function check(val1: Result, val2: number, eps: number = precDist) {
-    expect(equalEpsilon(val1.vCalc, val2, eps)).toBeTruthy("expected " + val2 + ", got " + val1.vCalc);
-}
+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 :", () => {
@@ -26,7 +28,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("k"), 0.635);
+            checkResult(ru.Calc("k"), 0.635);
         });
 
         it("LargeurBerge should be 3.473", () => {
@@ -42,7 +44,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurBerge"), 3.473);
+            checkResult(ru.Calc("LargeurBerge"), 3.473);
         });
 
         it("Strickler should be 33.774", () => {
@@ -58,7 +60,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Ks", 1e-8), 33.774);
+            checkResult(ru.Calc("Ks", 1e-8), 33.774);
         });
 
         it("If should be 0.002", () => {
@@ -74,7 +76,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("If", 0, 0.00001), 0.00071, 0.00001);
+            checkResult(ru.Calc("If", 0.001, 0.00001), 0.00071, 0.00001);
         });
 
         it("Q should be 1.421", () => {
@@ -90,7 +92,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Q"), 1.421);
+            checkResult(ru.Calc("Q"), 1.421);
         });
 
         it("Y should be 0.742", () => {
@@ -106,7 +108,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(paramCnl);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Y"), 0.742);
+            checkResult(ru.Calc("Y"), 0.742);
         });
     });
 
@@ -142,7 +144,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("k"), 0.933);
+            checkResult(ru.Calc("k"), 0.933);
         });
 
         it("LargeurBerge should be 0.721", () => {
@@ -158,7 +160,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurBerge"), 0.721);
+            checkResult(ru.Calc("LargeurBerge"), 0.721);
         });
 
         it("Strickler should be 4.367", () => {
@@ -174,7 +176,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Ks", 1e-8), 4.367);
+            checkResult(ru.Calc("Ks", 1e-8), 4.367);
         });
 
         it("Ks should be undefined", () => {
@@ -228,7 +230,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("If"), 0.001);
+            checkResult(ru.Calc("If", 0.001), 0.001);
         });
 
         it("Q should be 10.993", () => {
@@ -244,7 +246,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Q"), 10.993);
+            checkResult(ru.Calc("Q"), 10.993);
         });
 
         it("Y should be 0.742", () => {
@@ -260,7 +262,7 @@ describe("Class RegimeUniforme / section puissance :", () => {
             const sect = new cSnPuiss(paramCnl);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("Y"), 0.742);
+            checkResult(ru.Calc("Y"), 0.742);
         });
     });
 });
diff --git a/spec/regime_uniforme/regime_uniforme_rect.spec.ts b/spec/regime_uniforme/regime_uniforme_rect.spec.ts
index bf8c7b37c5242498290a730162d50575580ddfab..63ef6843ea4f2b7ce96ddb9c97e237c5e657b2ee 100644
--- a/spec/regime_uniforme/regime_uniforme_rect.spec.ts
+++ b/spec/regime_uniforme/regime_uniforme_rect.spec.ts
@@ -4,11 +4,8 @@
 import { Result } from "../../src/util/result";
 import { RegimeUniforme } from "../../src/regime_uniforme";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
-import { equalEpsilon, precDist } from "../nubtest";
-
-function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBeTruthy("expected " + val2 + ", got " + val1.vCalc);
-}
+import { equalEpsilon, checkResult } from "../test_func";
+import { precDist } from "../test_config";
 
 describe("Class RegimeUniforme / section rectangulaire :", () => {
     describe("pas de débordement : ", () => {
@@ -27,7 +24,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms, false);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurBerge"), 2.5);
+            checkResult(ru.Calc("LargeurBerge"), 2.5);
         });
 
         it("Strickler should be 30.619", () => {
@@ -43,7 +40,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 30.619);
+            checkResult(ru.Calc("Ks", 1e-8), 30.619);
         });
 
         it("If should be 0.001", () => {
@@ -60,7 +57,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const ru = new RegimeUniforme(sect, false);
 
             // nom variable à calculer, valeur de Ks
-            check(ru.Calc("If", 0, precDist), 0.001);
+            checkResult(ru.Calc("If", 0.001, precDist), 0.001);
         });
 
         it("Q should be 1.568", () => {
@@ -76,7 +73,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 1.568);
+            checkResult(ru.Calc("Q"), 1.568);
         });
 
         it("Q should be 0.731", () => {
@@ -92,7 +89,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 0.731);
+            checkResult(ru.Calc("Q"), 0.731);
         });
 
         it("Y should be 0.663", () => {
@@ -109,7 +106,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const ru = new RegimeUniforme(sect);
 
             // nom variable à calculer, valeur de Ks
-            check(ru.Calc("Y"), 0.663);
+            checkResult(ru.Calc("Y"), 0.663);
         });
     });
 
@@ -130,10 +127,10 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms, false);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurBerge"), 2.5);
+            checkResult(ru.Calc("LargeurBerge"), 2.5);
         });
 
-        it("Strickler should be 9.041", () => {
+        it("Strickler should be 9.04", () => {
             const prms = new ParamsSectionRectang(2, // tirant d'eau
                 2.5, // largeur de fond
                 undefined, //  Ks=Strickler
@@ -146,7 +143,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 9.041);
+            checkResult(ru.Calc("Ks", 1e-8), 9.04);
         });
 
         it("If should be 0.001", () => {
@@ -163,7 +160,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const ru = new RegimeUniforme(sect, false);
 
             // nom variable à calculer, valeur de Ks
-            check(ru.Calc("If", 0, precDist), 0.001);
+            checkResult(ru.Calc("If", 0.001, precDist), 0.001);
         });
 
         it("Q should be 5.31", () => {
@@ -179,7 +176,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 5.31);
+            checkResult(ru.Calc("Q"), 5.31);
         });
 
         it("Q should be 1.624", () => {
@@ -195,7 +192,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const sect = new cSnRectang(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 1.624);
+            checkResult(ru.Calc("Q"), 1.624);
         });
 
         it("Y should be 0.663", () => {
@@ -212,7 +209,7 @@ describe("Class RegimeUniforme / section rectangulaire :", () => {
             const ru = new RegimeUniforme(sect);
 
             // nom variable à calculer, valeur de Ks
-            check(ru.Calc("Y"), 0.663);
+            checkResult(ru.Calc("Y"), 0.663);
         });
     });
 });
diff --git a/spec/regime_uniforme/regime_uniforme_trapeze.spec.ts b/spec/regime_uniforme/regime_uniforme_trapeze.spec.ts
index 7bf9f87815e1bca8ad5141767845b9d2faa58fb9..626c04f557b82c7e49a96b46cbc130b8052f5ad7 100644
--- a/spec/regime_uniforme/regime_uniforme_trapeze.spec.ts
+++ b/spec/regime_uniforme/regime_uniforme_trapeze.spec.ts
@@ -4,11 +4,8 @@
 import { Result } from "../../src/util/result";
 import { RegimeUniforme } from "../../src/regime_uniforme";
 import { cSnTrapez, ParamsSectionTrapez } from "../../src/section/section_trapez";
-import { equalEpsilon, precDist } from "../nubtest";
-
-function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBeTruthy("expected " + val2 + ", got " + val1.vCalc);
-}
+import { equalEpsilon, checkResult } from "../test_func";
+import { precDist } from "../test_config";
 
 describe("Class RegimeUniforme / section trapèze :", () => {
     describe("pas de débordement :", () => {
@@ -27,7 +24,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
 
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurFond", 0, precDist), 2.5);
+            checkResult(ru.Calc("LargeurFond", 0, precDist), 2.5);
         });
 
         it("Fruit should be 0.56", () => {
@@ -44,7 +41,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Fruit"), 0.56);
+            checkResult(ru.Calc("Fruit"), 0.56);
         });
 
         it("Ks should be 24.14", () => {
@@ -61,7 +58,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 24.14);
+            checkResult(ru.Calc("Ks", 1e-8), 24.14);
         });
 
         it("If should be 0.001", () => {
@@ -78,7 +75,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("If"), 0.001);
+            checkResult(ru.Calc("If", 0.001), 0.001);
         });
 
         it("Q should be 1.2", () => {
@@ -95,7 +92,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 1.2);
+            checkResult(ru.Calc("Q"), 1.2);
         });
 
         it("Y should be 0.587", () => {
@@ -112,7 +109,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Y"), 0.587);
+            checkResult(ru.Calc("Y"), 0.587);
         });
     });
 
@@ -130,7 +127,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect, false);
 
-            check(ru.Calc("LargeurFond", 0, precDist), 0.03);
+            checkResult(ru.Calc("LargeurFond", 0, precDist), 0.03);
         });
 
         it("Fruit should be 0.56", () => {
@@ -147,7 +144,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Fruit"), 0.56);
+            checkResult(ru.Calc("Fruit"), 0.56);
         });
 
         it("Ks should be 5.744", () => {
@@ -163,7 +160,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Ks", 1e-8), 5.744);
+            checkResult(ru.Calc("Ks", 1e-8), 5.744);
         });
 
         it("If should be 0.001", () => {
@@ -179,7 +176,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("If"), 0.001);
+            checkResult(ru.Calc("If", 0.001), 0.001);
         });
 
         it("Q should be 8.356", () => {
@@ -196,7 +193,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Q"), 8.356);
+            checkResult(ru.Calc("Q"), 8.356);
         });
 
         it("Y should be 0.587", () => {
@@ -213,7 +210,7 @@ describe("Class RegimeUniforme / section trapèze :", () => {
             const sect = new cSnTrapez(prms);
             const ru = new RegimeUniforme(sect);
 
-            check(ru.Calc("Y"), 0.587);
+            checkResult(ru.Calc("Y"), 0.587);
         });
     });
 });
diff --git a/spec/remous/remous_rect_euler_pentefaible.spec.ts b/spec/remous/remous_rect_euler_pentefaible.spec.ts
index c5ebf8edded33b311da7e17db49315e52f5fe3d1..8959ff342fea7f7d0657703c43b92611401f4686 100644
--- a/spec/remous/remous_rect_euler_pentefaible.spec.ts
+++ b/spec/remous/remous_rect_euler_pentefaible.spec.ts
@@ -1,9 +1,10 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject } from "../test_func";
+import { precDist } from "../test_config";
+import { Result } from "../../src/util/result";
 
 describe("Class Remous / section rectangulaire :", () => {
     describe("méthode Euler explicite :", () => {
@@ -69,7 +70,7 @@ describe("Class Remous / section rectangulaire :", () => {
 
         //     expLog.add(new ErrorMessage(ErrorCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
 
-        //     m = new ErrorMessage(ErrorCode.ERROR_REMOUS_ARRET_CRITIQUE)
+        //     m = new ErrorMessage(ErrorCode.WARNING_REMOUS_ARRET_CRITIQUE)
         //     m.extraVar["x"] = 10;
         //     expLog.add(m);
 
@@ -145,7 +146,7 @@ describe("Class Remous / section rectangulaire :", () => {
 
         //     expLog.add(new ErrorMessage(ErrorCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
 
-        //     m = new ErrorMessage(ErrorCode.ERROR_REMOUS_ARRET_CRITIQUE)
+        //     m = new ErrorMessage(ErrorCode.WARNING_REMOUS_ARRET_CRITIQUE)
         //     m.extraVar["x"] = 20;
         //     expLog.add(m);
 
@@ -240,36 +241,36 @@ describe("Class Remous / section rectangulaire :", () => {
 
             let rem = new CourbeRemous(prem);
 
-            let res = rem.calculRemous(undefined);
+            let res: Result = rem.calculRemous(undefined);
 
             // données de validation : version Typescript (Oct 2017) méthode des trapèzes
 
             let f = { "0": 0.9872500000000014, "5": 0.9872500000000014, "10": 0.9872500000000014, "15": 0.9872500000000014, "20": 0.9880000000000013, "25": 0.9887500000000012, "30": 0.9895000000000012, "35": 0.9902500000000011, "40": 0.991000000000001, "45": 0.9917500000000009, "50": 0.9925000000000008, "55": 0.9932500000000007, "60": 0.9940000000000007, "65": 0.9947500000000006, "70": 0.9955000000000005, "75": 0.9962500000000004, "80": 0.9970000000000003, "85": 0.9977500000000002, "90": 0.9985000000000002, "95": 0.9992500000000001, "100": 1 };
-            compareObject("Yfluvial", res["flu"], f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-            expect(Object.keys(res["tor"]).length == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
             let x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
-            compareArray("abscisses", res["trX"], x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             let expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar["B"] = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar["Yc"] = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar["Yn"] = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("faible pente, pas de ressaut, Yamont > Yc, Yc < Yaval < Yn", () => {
@@ -298,31 +299,31 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version Typescript (Oct 2017) méthode trapèzes
 
             let f = { "0": 0.805499999999999, "5": 0.802249999999999, "10": 0.7984999999999991, "15": 0.7947499999999992, "20": 0.7909999999999993, "25": 0.7867499999999993, "30": 0.7824999999999993, "35": 0.7782499999999993, "40": 0.7739999999999994, "45": 0.7692499999999994, "50": 0.7644999999999995, "55": 0.7592499999999995, "60": 0.7539999999999996, "65": 0.7482499999999996, "70": 0.7424999999999997, "75": 0.7362499999999997, "80": 0.7299999999999998, "85": 0.7232499999999998, "90": 0.7159999999999999, "95": 0.7082499999999999, "100": 0.7 };
-            compareObject("Yfluvial", res["flu"], f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-            expect(Object.keys(res["tor"]).length == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
             let x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
-            compareArray("abscisses", res["trX"], x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             let expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar["B"] = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar["Yc"] = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar["Yn"] = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 });
diff --git a/spec/remous/remous_rect_euler_penteforte.spec.ts b/spec/remous/remous_rect_euler_penteforte.spec.ts
index fa51807b18e9f938e02aaaf8fc8d1a07b1a1600a..040fe15450e0c511c1527dbd58b4eebf13b32732 100644
--- a/spec/remous/remous_rect_euler_penteforte.spec.ts
+++ b/spec/remous/remous_rect_euler_penteforte.spec.ts
@@ -1,9 +1,9 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject, equalEpsilon } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
    Certaines valeurs de ligne d'eau torrentielle étaient auparavant remplacées par une valeur fluviale
@@ -40,36 +40,36 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version Typescript (Oct 2017) méthode des trapèzes
 
             const f = { 0: 0.9767500000000044, 5: 1.2360000000000044, 10: 1.4910000000000045, 15: 1.7437500000000046, 20: 1.9955000000000045, 25: 2.2465000000000046, 30: 2.497500000000005, 35: 2.7485000000000053, 40: 2.9985000000000053, 45: 3.2485000000000053, 50: 3.4985000000000053, 55: 3.7485000000000053, 60: 3.9985000000000053, 65: 4.248500000000004, 70: 4.498750000000004, 75: 4.749000000000003, 80: 4.999250000000003, 85: 5.249500000000002, 90: 5.4997500000000015, 95: 5.750000000000001, 100: 6 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = {};
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "amont";
             m.extraVar.x = 0;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, ressaut après l'aval", () => {
@@ -99,42 +99,42 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version Typescript (Oct 2017) méthode des trapèzes
 
             const f = {};
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { "0": 0.15, "5": 0.20725000000000002, "10": 0.23500000000000001, "15": 0.24675000000000002, "20": 0.251, "25": 0.25225, "30": 0.25249999999999995, "35": 0.2527499999999999, "40": 0.2529999999999999, "45": 0.2527499999999999, "50": 0.2529999999999999, "55": 0.2527499999999999, "60": 0.2529999999999999, "65": 0.2527499999999999, "70": 0.2529999999999999, "75": 0.2527499999999999, "80": 0.2529999999999999, "85": 0.2527499999999999, "90": 0.2529999999999999, "95": 0.2527499999999999, "100": 0.45 };
             const t = { 0: 0.15, 5: 0.20725000000000002, 10: 0.23500000000000001, 15: 0.24675000000000002, 20: 0.251, 25: 0.25225, 30: 0.25249999999999995, 35: 0.2527499999999999, 40: 0.2529999999999999, 45: 0.2527499999999999, 50: 0.2529999999999999, 55: 0.2527499999999999, 60: 0.2529999999999999, 65: 0.2527499999999999, 70: 0.2529999999999999, 75: 0.2527499999999999, 80: 0.2529999999999999, 85: 0.2527499999999999, 90: 0.2529999999999999, 95: 0.2527499999999999, 100: 0.253 }; // dernière valeur modifiée pour la raison en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 95;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "aval";
             m.extraVar.x = 100;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         // it("forte pente, ressaut (1 point) à l'intérieur du bief", () => {
@@ -190,7 +190,7 @@ describe("Class Remous / section rectangulaire :", () => {
 
         //     expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
 
-        //     m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE)
+        //     m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE)
         //     m.extraVar["x"] = 85;
         //     expLog.add(m);
 
@@ -237,37 +237,37 @@ describe("Class Remous / section rectangulaire :", () => {
             // "1.5": 0.7845000000000006, "1.25": 0.7702500000000007, "0.75": 0.7417500000000007,
             // "0.5": 0.7275000000000007, "0.25": 0.7132500000000007 };
             const f = { 0: 0.698, 1: 0.7560000000000007, 2: 0.8120000000000005, 3: 0.8670000000000002, 4: 0.9205000000000001, 5: 0.9735, 5.5: 1, 5.25: 0.98675, 4.75: 0.96025, 4.5: 0.9470000000000001, 4.25: 0.9337500000000001, 3.75: 0.9072500000000001, 3.5: 0.8940000000000001, 3.25: 0.8807500000000001, 2.75: 0.8532500000000003, 2.5: 0.8395000000000004, 2.25: 0.8257500000000004, 1.75: 0.7982500000000006, 1.5: 0.7845000000000006, 1.25: 0.7702500000000007, 0.75: 0.7417500000000007, 0.5: 0.7275000000000007, 0.25: 0.7132500000000007 }; // première valeur modifiée pour la raison en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0: 0.15, 1: 0.161, 2: 0.17200000000000001, 3: 0.18100000000000002, 0.25: 0.15275, 0.5: 0.1555, 0.75: 0.15825, 1.25: 0.16375, 1.5: 0.1665, 1.75: 0.16925, 2.25: 0.17425000000000002, 2.5: 0.17650000000000002, 2.75: 0.17875000000000002, 3.25: 0.18325000000000002, 3.5: 0.18550000000000003, 3.75: 0.9072500000000001 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.25, 4.5, 4.75, 5, 5.25, 5.5];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 3.75;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yamont < Yn", () => {
@@ -295,7 +295,7 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version Typescript (Oct 2017) méthode trapèzes
 
-            expect(Object.keys(res.flu).length === 0).toBeTruthy(
+            expect(res.extraResultLength("flu") == 0).toBeTruthy(
                 "la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = {
@@ -306,31 +306,32 @@ describe("Class Remous / section rectangulaire :", () => {
                 16: 0.23600000000000013, 17: 0.23875000000000013, 18: 0.24100000000000013, 19: 0.24325000000000013,
                 20: 0.24500000000000013, 21: 0.24625000000000014, 22: 0.24750000000000014, 23: 0.2485000000000001,
                 24: 0.2492500000000001, 25: 0.2502500000000001, 26: 0.25050000000000006, 27: 0.25075000000000003,
-                28: 0.251, 29: 0.25125, 30: 0.25149999999999995 };
-            compareObject("Ytorrentiel", res.tor, t, 0.01);
+                28: 0.251, 29: 0.25125, 30: 0.25149999999999995
+            };
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.01);
 
             const x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
                 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yn < Yamont < Yc", () => {
@@ -358,32 +359,32 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
-            expect(Object.keys(res.flu).length === 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("flu") == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = { 0.000: 0.35, 0.100: 0.345, 0.200: 0.34, 0.300: 0.336, 0.400: 0.332, 0.500: 0.329, 0.600: 0.326, 0.700: 0.323, 0.800: 0.32, 0.900: 0.318, 1.000: 0.316, 1.100: 0.313, 1.200: 0.311, 1.300: 0.309, 1.400: 0.308, 1.500: 0.306, 1.600: 0.305, 1.700: 0.303, 1.800: 0.302, 1.900: 0.3, 2.000: 0.298, 2.100: 0.297, 2.200: 0.295, 2.300: 0.294, 2.400: 0.293, 2.500: 0.292, 2.600: 0.291, 2.700: 0.291, 2.800: 0.29, 2.900: 0.289, 3.000: 0.288, 3.100: 0.287, 3.200: 0.287, 3.300: 0.286, 3.400: 0.285, 3.500: 0.284, 3.600: 0.283, 3.700: 0.283, 3.800: 0.282, 3.900: 0.281, 4.000: 0.28, 4.100: 0.28, 4.200: 0.279, 4.300: 0.278, 4.400: 0.277, 4.500: 0.276, 4.600: 0.276, 4.700: 0.275, 4.800: 0.274, 4.900: 0.273, 5.000: 0.272, 5.100: 0.272, 5.200: 0.271, 5.300: 0.27, 5.400: 0.269, 5.500: 0.269, 5.600: 0.269, 5.700: 0.269, 5.800: 0.269, 5.900: 0.269, 6.000: 0.269, 6.100: 0.269, 6.200: 0.269, 6.300: 0.269, 6.400: 0.269, 6.500: 0.269, 6.600: 0.269, 6.700: 0.269, 6.800: 0.269, 6.900: 0.269, 7.000: 0.269, 7.100: 0.269, 7.200: 0.269, 7.300: 0.269, 7.400: 0.269, 7.500: 0.269, 7.600: 0.269, 7.700: 0.269, 7.800: 0.269, 7.900: 0.269, 8.000: 0.269, 8.100: 0.269, 8.200: 0.269, 8.300: 0.269, 8.400: 0.269, 8.500: 0.269, 8.600: 0.269, 8.700: 0.269, 8.800: 0.269, 8.900: 0.269, 9.000: 0.269, 9.100: 0.269, 9.200: 0.269, 9.300: 0.269, 9.400: 0.269, 9.500: 0.269, 9.600: 0.269, 9.700: 0.269, 9.800: 0.269, 9.900: 0.269, 10.000: 0.269 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 0.100, 0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.800, 0.900, 1.000, 1.100, 1.200, 1.300, 1.400, 1.500, 1.600, 1.700, 1.800, 1.900, 2.000, 2.100, 2.200, 2.300, 2.400, 2.500, 2.600, 2.700, 2.800, 2.900, 3.000, 3.100, 3.200, 3.300, 3.400, 3.500, 3.600, 3.700, 3.800, 3.900, 4.000, 4.100, 4.200, 4.300, 4.400, 4.500, 4.600, 4.700, 4.800, 4.900, 5.000, 5.100, 5.200, 5.300, 5.400, 5.500, 5.600, 5.700, 5.800, 5.900, 6.000, 6.100, 6.200, 6.300, 6.400, 6.500, 6.600, 6.700, 6.800, 6.900, 7.000, 7.100, 7.200, 7.300, 7.400, 7.500, 7.600, 7.700, 7.800, 7.900, 8.000, 8.100, 8.200, 8.300, 8.400, 8.500, 8.600, 8.700, 8.800, 8.900, 9.000, 9.100, 9.200, 9.300, 9.400, 9.500, 9.600, 9.700, 9.800, 9.900, 10.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 });
diff --git a/spec/remous/remous_rect_rk4_pentefaible.spec.ts b/spec/remous/remous_rect_rk4_pentefaible.spec.ts
index 5d4fa2ae4e4ac965df30c881dc2f1921d69fd93c..8e6938564f8741f3f54c93c82724781311aa57ab 100644
--- a/spec/remous/remous_rect_rk4_pentefaible.spec.ts
+++ b/spec/remous/remous_rect_rk4_pentefaible.spec.ts
@@ -1,9 +1,9 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject, equalEpsilon } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
   Le code de modification des lignes fluviale et torrentielle a été modifié, on enlève un point de plus
@@ -43,43 +43,44 @@ describe("Class Remous / section rectangulaire :", () => {
                 100.000: 0.41, 95.000: 0.876, 90.000: 0.877, 85.000: 0.879, 80.000: 0.88, 75.000: 0.881,
                 70.000: 0.883, 65.000: 0.884, 60.000: 0.885, 55.000: 0.886, 50.000: 0.888, 45.000: 0.889,
                 40.000: 0.89, 35.000: 0.891, 30.000: 0.892, 25.000: 0.893, 20.000: 0.894, 15.000: 0.895,
-                10.000: 0.896, 5.000: 0.897, 0.000: 0.898 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+                10.000: 0.896, 5.000: 0.897, 0.000: 0.898
+            };
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = {};
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000,
                 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "amont";
             m.extraVar.x = 0;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("faible pente, ressaut (1 point) à l'intérieur du bief", () => {
@@ -109,42 +110,42 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // let f = { 100.000: 0.42, 95.000: 0.583, 90.000: 0.604, 85.000: 0.621, 80.000: 0.636, 75.000: 0.65, 70.000: 0.662, 65.000: 0.673, 60.000: 0.683, 55.000: 0.692, 50.000: 0.701, 45.000: 0.709, 40.000: 0.717, 35.000: 0.724, 30.000: 0.731, 25.000: 0.737, 20.000: 0.743, 15.000: 0.749, 10.000: 0.755, 5.000: 0.76, 0.000: 0.15 };
             const f = { 100.000: 0.42, 95.000: 0.583, 90.000: 0.604, 85.000: 0.621, 80.000: 0.636, 75.000: 0.65, 70.000: 0.662, 65.000: 0.673, 60.000: 0.683, 55.000: 0.692, 50.000: 0.701, 45.000: 0.709, 40.000: 0.717, 35.000: 0.724, 30.000: 0.731, 25.000: 0.737, 20.000: 0.743, 15.000: 0.749, 10.000: 0.755, 5.000: 0.76 }; // dernière valeur supprimée pour la raison en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.76 };
             const t = { 0.000: 0.15 }; // dernière valeur supprimée pour la raison en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 15;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 5;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("faible pente, ressaut (plusieurs points) à l'intérieur du bief", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -173,37 +174,37 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
             const f = { 5.000: 0.42, 4.750: 0.434, 4.500: 0.443, 4.250: 0.45, 4.000: 0.457, 3.750: 0.462, 3.500: 0.467, 3.250: 0.471, 3.000: 0.476, 2.750: 0.48, 2.500: 0.483, 2.250: 0.487, 2.000: 0.49, 1.750: 0.493, 1.500: 0.496, 1.250: 0.499, 1.000: 0.502, 0.750: 0.504, 0.500: 0.507, 0.250: 0.509, 0.000: 0.01 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0.000: 0.01, 0.250: 0.017, 0.500: 0.022, 0.750: 0.028, 1.000: 0.502 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 0.250, 0.500, 0.750, 1.000, 1.250, 1.500, 1.750, 2.000, 2.250, 2.500, 2.750, 3.000, 3.250, 3.500, 3.750, 4.000, 4.250, 4.500, 4.750, 5.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 1;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("faible pente, pas de ressaut, Yamont > Yc, Yaval > Yn", () => {
@@ -232,31 +233,31 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
             const f = { 100.000: 1, 95.000: 0.999, 90.000: 0.999, 85.000: 0.998, 80.000: 0.997, 75.000: 0.997, 70.000: 0.996, 65.000: 0.996, 60.000: 0.995, 55.000: 0.994, 50.000: 0.994, 45.000: 0.993, 40.000: 0.993, 35.000: 0.992, 30.000: 0.991, 25.000: 0.991, 20.000: 0.99, 15.000: 0.99, 10.000: 0.989, 5.000: 0.989, 0.000: 0.988 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-            expect(Object.keys(res.tor).length === 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("faible pente, pas de ressaut, Yamont > Yc, Yc < Yaval < Yn", () => {
@@ -285,31 +286,31 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
             const f = { 100.000: 0.7, 95.000: 0.708, 90.000: 0.716, 85.000: 0.723, 80.000: 0.73, 75.000: 0.737, 70.000: 0.743, 65.000: 0.749, 60.000: 0.754, 55.000: 0.759, 50.000: 0.764, 45.000: 0.769, 40.000: 0.774, 35.000: 0.779, 30.000: 0.783, 25.000: 0.787, 20.000: 0.791, 15.000: 0.795, 10.000: 0.799, 5.000: 0.802, 0.000: 0.806 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-            expect(Object.keys(res.tor).length === 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 });
diff --git a/spec/remous/remous_rect_rk4_penteforte.spec.ts b/spec/remous/remous_rect_rk4_penteforte.spec.ts
index 2b0fc783d44ff1cf773d043614d1e58486c6327d..379ee1b1b598d410ecaa37cb7b35caa878201f0e 100644
--- a/spec/remous/remous_rect_rk4_penteforte.spec.ts
+++ b/spec/remous/remous_rect_rk4_penteforte.spec.ts
@@ -1,9 +1,9 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject, equalEpsilon } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
    cas 1 :
@@ -49,36 +49,36 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
             const f = { 100.000: 6, 95.000: 5.75, 90.000: 5.5, 85.000: 5.25, 80.000: 5, 75.000: 4.75, 70.000: 4.5, 65.000: 4.25, 60.000: 4, 55.000: 3.749, 50.000: 3.499, 45.000: 3.249, 40.000: 2.999, 35.000: 2.748, 30.000: 2.498, 25.000: 2.247, 20.000: 1.996, 15.000: 1.744, 10.000: 1.491, 5.000: 1.237, 0.000: 0.977 };
-            compareObject("Yfluvial", res.flu, f, 0.01);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.01);
 
             const t = {};
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "amont";
             m.extraVar.x = 0;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, ressaut après l'aval", () => {
@@ -108,42 +108,42 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
             const f = {};
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.198, 10.000: 0.228, 15.000: 0.243, 20.000: 0.249, 25.000: 0.251, 30.000: 0.252, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.45 };
             const t = { 0.000: 0.15, 5.000: 0.198, 10.000: 0.228, 15.000: 0.243, 20.000: 0.249, 25.000: 0.251, 30.000: 0.252, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.253 }; // dernière valeur remplacée pour la raison 1 en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE)
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE)
             m.extraVar.x = 95;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "aval";
             m.extraVar.x = 100;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("forte pente, ressaut (1 point) à l'intérieur du bief", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -173,42 +173,42 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // let f = { 100.000: 1, 95.000: 0.728, 90.000: 0.521 };
             const f = { 100.000: 1, 95.000: 0.728 }; // dernière valeur supprimée pour la raison 2 en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.198, 10.000: 0.228, 15.000: 0.243, 20.000: 0.249, 25.000: 0.251, 30.000: 0.252, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.521 };
             const t = { 0.000: 0.15, 5.000: 0.198, 10.000: 0.228, 15.000: 0.243, 20.000: 0.249, 25.000: 0.251, 30.000: 0.252, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253 }; // dernière valeur remplacée pour la raison 1 en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE)
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE)
             m.extraVar.x = 85;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 90;
             m.extraVar.xmax = 90;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("forte pente, ressaut (plusieurs points) à l'intérieur du bief", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -238,37 +238,37 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // let f = { 5.500: 1, 5.250: 0.987, 5.000: 0.974, 4.750: 0.96, 4.500: 0.947, 4.250: 0.934, 4.000: 0.921, 3.750: 0.907, 3.500: 0.894, 3.250: 0.88, 3.000: 0.867, 2.750: 0.853, 2.500: 0.84, 2.250: 0.826, 2.000: 0.812, 1.750: 0.798, 1.500: 0.785, 1.250: 0.771, 1.000: 0.756, 0.750: 0.742, 0.500: 0.728, 0.250: 0.713, 0.000: 0.15 };
             const f = { 5.500: 1, 5.250: 0.987, 5.000: 0.974, 4.750: 0.96, 4.500: 0.947, 4.250: 0.934, 4.000: 0.921, 3.750: 0.907, 3.500: 0.894, 3.250: 0.88, 3.000: 0.867, 2.750: 0.853, 2.500: 0.84, 2.250: 0.826, 2.000: 0.812, 1.750: 0.798, 1.500: 0.785, 1.250: 0.771, 1.000: 0.756, 0.750: 0.742, 0.500: 0.728, 0.250: 0.713, 0.000: 0.699 }; // dernière valeur remplacée pour la raison 1 en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0.000: 0.15, 0.250: 0.153, 0.500: 0.156, 0.750: 0.158, 1.000: 0.161, 1.250: 0.164, 1.500: 0.166, 1.750: 0.169, 2.000: 0.171, 2.250: 0.174, 2.500: 0.176, 2.750: 0.179, 3.000: 0.181, 3.250: 0.183, 3.500: 0.186, 3.750: 0.907 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 0.250, 0.500, 0.750, 1.000, 1.250, 1.500, 1.750, 2.000, 2.250, 2.500, 2.750, 3.000, 3.250, 3.500, 3.750, 4.000, 4.250, 4.500, 4.750, 5.000, 5.250, 5.500];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 3.75;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yamont < Yn", () => {
@@ -296,32 +296,32 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
-            expect(Object.keys(res.flu).length == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("flu") == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = { 0.000: 0.1, 5.000: 0.162, 10.000: 0.206, 15.000: 0.232, 20.000: 0.244, 25.000: 0.25, 30.000: 0.252, 35.000: 0.252, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.253 };
-            compareObject("Ytorrentiel", res.tor, t, 0.01);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.01);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yn < Yamont < Yc", () => {
@@ -349,32 +349,32 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version PHP (Oct 2017) méthode RungeKutta4
 
-            expect(Object.keys(res.flu).length == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("flu") == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = { 0.000: 0.35, 0.100: 0.344, 0.200: 0.34, 0.300: 0.335, 0.400: 0.332, 0.500: 0.328, 0.600: 0.325, 0.700: 0.322, 0.800: 0.32, 0.900: 0.317, 1.000: 0.315, 1.100: 0.313, 1.200: 0.31, 1.300: 0.309, 1.400: 0.307, 1.500: 0.305, 1.600: 0.303, 1.700: 0.302, 1.800: 0.3, 1.900: 0.299, 2.000: 0.297, 2.100: 0.296, 2.200: 0.295, 2.300: 0.294, 2.400: 0.293, 2.500: 0.291, 2.600: 0.29, 2.700: 0.289, 2.800: 0.288, 2.900: 0.287, 3.000: 0.287, 3.100: 0.286, 3.200: 0.285, 3.300: 0.284, 3.400: 0.283, 3.500: 0.282, 3.600: 0.282, 3.700: 0.281, 3.800: 0.28, 3.900: 0.279, 4.000: 0.279, 4.100: 0.278, 4.200: 0.278, 4.300: 0.277, 4.400: 0.276, 4.500: 0.276, 4.600: 0.275, 4.700: 0.275, 4.800: 0.274, 4.900: 0.274, 5.000: 0.273, 5.100: 0.273, 5.200: 0.272, 5.300: 0.272, 5.400: 0.271, 5.500: 0.271, 5.600: 0.271, 5.700: 0.27, 5.800: 0.27, 5.900: 0.269, 6.000: 0.269, 6.100: 0.269, 6.200: 0.268, 6.300: 0.268, 6.400: 0.268, 6.500: 0.267, 6.600: 0.267, 6.700: 0.267, 6.800: 0.266, 6.900: 0.266, 7.000: 0.266, 7.100: 0.265, 7.200: 0.265, 7.300: 0.265, 7.400: 0.265, 7.500: 0.264, 7.600: 0.264, 7.700: 0.264, 7.800: 0.264, 7.900: 0.263, 8.000: 0.263, 8.100: 0.263, 8.200: 0.263, 8.300: 0.263, 8.400: 0.262, 8.500: 0.262, 8.600: 0.262, 8.700: 0.262, 8.800: 0.262, 8.900: 0.261, 9.000: 0.261, 9.100: 0.261, 9.200: 0.261, 9.300: 0.261, 9.400: 0.26, 9.500: 0.26, 9.600: 0.26, 9.700: 0.26, 9.800: 0.26, 9.900: 0.26, 10.000: 0.26 };
-            compareObject("Ytorrentiel", res.tor, t, 0.01);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.01);
 
             const x = [0.000, 0.100, 0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.800, 0.900, 1.000, 1.100, 1.200, 1.300, 1.400, 1.500, 1.600, 1.700, 1.800, 1.900, 2.000, 2.100, 2.200, 2.300, 2.400, 2.500, 2.600, 2.700, 2.800, 2.900, 3.000, 3.100, 3.200, 3.300, 3.400, 3.500, 3.600, 3.700, 3.800, 3.900, 4.000, 4.100, 4.200, 4.300, 4.400, 4.500, 4.600, 4.700, 4.800, 4.900, 5.000, 5.100, 5.200, 5.300, 5.400, 5.500, 5.600, 5.700, 5.800, 5.900, 6.000, 6.100, 6.200, 6.300, 6.400, 6.500, 6.600, 6.700, 6.800, 6.900, 7.000, 7.100, 7.200, 7.300, 7.400, 7.500, 7.600, 7.700, 7.800, 7.900, 8.000, 8.100, 8.200, 8.300, 8.400, 8.500, 8.600, 8.700, 8.800, 8.900, 9.000, 9.100, 9.200, 9.300, 9.400, 9.500, 9.600, 9.700, 9.800, 9.900, 10.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 });
diff --git a/spec/remous/remous_rect_trapezes_pentefaible.spec.ts b/spec/remous/remous_rect_trapezes_pentefaible.spec.ts
index 3fc514a0065ffdae4c0d63cb4fce2bbcff5bfd6c..c7dedf8d96ab0c1081507292f9910235cbf95126 100644
--- a/spec/remous/remous_rect_trapezes_pentefaible.spec.ts
+++ b/spec/remous/remous_rect_trapezes_pentefaible.spec.ts
@@ -1,9 +1,9 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject, equalEpsilon } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
   Le code de modification des lignes fluviale et torrentielle a été modifié, on enlève un point de plus
@@ -40,41 +40,41 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
             const f = { 100.000: 0.403, 95.000: 0.524, 90.000: 0.558, 85.000: 0.584, 80.000: 0.604, 75.000: 0.621, 70.000: 0.637, 65.000: 0.65, 60.000: 0.662, 55.000: 0.673, 50.000: 0.684, 45.000: 0.693, 40.000: 0.701, 35.000: 0.709, 30.000: 0.717, 25.000: 0.725, 20.000: 0.731, 15.000: 0.738, 10.000: 0.744, 5.000: 0.75, 0.000: 0.755 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = {};
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "amont";
             m.extraVar.x = 0;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("faible pente, ressaut (1 point) à l'intérieur du bief", () => {
@@ -104,42 +104,42 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // let f = { 100.000: 0.403, 95.000: 0.524, 90.000: 0.558, 85.000: 0.584, 80.000: 0.604, 75.000: 0.621, 70.000: 0.637, 65.000: 0.65, 60.000: 0.662, 55.000: 0.673, 50.000: 0.684, 45.000: 0.693, 40.000: 0.701, 35.000: 0.709, 30.000: 0.717, 25.000: 0.725, 20.000: 0.731, 15.000: 0.738, 10.000: 0.744, 5.000: 0.75, 0.000: 0.15 };
             const f = { 100.000: 0.403, 95.000: 0.524, 90.000: 0.558, 85.000: 0.584, 80.000: 0.604, 75.000: 0.621, 70.000: 0.637, 65.000: 0.65, 60.000: 0.662, 55.000: 0.673, 50.000: 0.684, 45.000: 0.693, 40.000: 0.701, 35.000: 0.709, 30.000: 0.717, 25.000: 0.725, 20.000: 0.731, 15.000: 0.738, 10.000: 0.744, 5.000: 0.75 };  // dernière valeur supprimée pour la raison en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.75 };
             const t = { 0.000: 0.15 }; // dernière valeur supprimée pour la raison en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 15;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 5;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("faible pente, ressaut (plusieurs points) à l'intérieur du bief (1)", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -180,37 +180,37 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // dx = 0.25
             const f = { 5.000: 0.403, 4.750: 0.43, 4.500: 0.44, 4.250: 0.448, 4.000: 0.455, 3.750: 0.46, 3.500: 0.465, 3.250: 0.47, 3.000: 0.474, 2.750: 0.479, 2.500: 0.482, 2.250: 0.486, 2.000: 0.489, 1.750: 0.492, 1.500: 0.495, 1.250: 0.498, 1.000: 0.501, 0.750: 0.504, 0.500: 0.506, 0.250: 0.508, 0.000: 0.01 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0.000: 0.01, 0.250: 0.022, 0.500: 0.027, 0.750: 0.033, 1.000: 0.501 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 0.250, 0.500, 0.750, 1.000, 1.250, 1.500, 1.750, 2.000, 2.250, 2.500, 2.750, 3.000, 3.250, 3.500, 3.750, 4.000, 4.250, 4.500, 4.750, 5.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 1;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("faible pente, ressaut (plusieurs points) à l'intérieur du bief (2)", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -239,37 +239,37 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
             const f = { 5.0000: 0.403, 4.9500: 0.415, 4.9000: 0.42, 4.8500: 0.423, 4.8000: 0.426, 4.7500: 0.429, 4.7000: 0.432, 4.6500: 0.434, 4.6000: 0.436, 4.5500: 0.438, 4.5000: 0.44, 4.4500: 0.441, 4.4000: 0.443, 4.3500: 0.445, 4.3000: 0.446, 4.2500: 0.448, 4.2000: 0.449, 4.1500: 0.45, 4.1000: 0.452, 4.0500: 0.453, 4.0000: 0.454, 3.9500: 0.455, 3.9000: 0.457, 3.8500: 0.458, 3.8000: 0.459, 3.7500: 0.46, 3.7000: 0.461, 3.6500: 0.462, 3.6000: 0.463, 3.5500: 0.464, 3.5000: 0.465, 3.4500: 0.466, 3.4000: 0.467, 3.3500: 0.468, 3.3000: 0.469, 3.2500: 0.47, 3.2000: 0.471, 3.1500: 0.471, 3.1000: 0.472, 3.0500: 0.473, 3.0000: 0.474, 2.9500: 0.475, 2.9000: 0.476, 2.8500: 0.476, 2.8000: 0.477, 2.7500: 0.478, 2.7000: 0.479, 2.6500: 0.479, 2.6000: 0.48, 2.5500: 0.481, 2.5000: 0.482, 2.4500: 0.482, 2.4000: 0.483, 2.3500: 0.484, 2.3000: 0.484, 2.2500: 0.485, 2.2000: 0.486, 2.1500: 0.487, 2.1000: 0.487, 2.0500: 0.488, 2.0000: 0.489, 1.9500: 0.489, 1.9000: 0.49, 1.8500: 0.49, 1.8000: 0.491, 1.7500: 0.492, 1.7000: 0.492, 1.6500: 0.493, 1.6000: 0.494, 1.5500: 0.494, 1.5000: 0.495, 1.4500: 0.495, 1.4000: 0.496, 1.3500: 0.497, 1.3000: 0.497, 1.2500: 0.498, 1.2000: 0.498, 1.1500: 0.499, 1.1000: 0.499, 1.0500: 0.5, 1.0000: 0.5, 0.9500: 0.501, 0.9000: 0.502, 0.8500: 0.502, 0.8000: 0.503, 0.7500: 0.503, 0.7000: 0.504, 0.6500: 0.504, 0.6000: 0.505, 0.5500: 0.505, 0.5000: 0.506, 0.4500: 0.506, 0.4000: 0.507, 0.3500: 0.507, 0.3000: 0.508, 0.2500: 0.508, 0.2000: 0.509, 0.1500: 0.509, 0.1000: 0.51, 0.0500: 0.51, 0.0000: 0.01 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0.0000: 0.01, 0.0500: 0.011, 0.1000: 0.013, 0.1500: 0.014, 0.2000: 0.015, 0.2500: 0.017, 0.3000: 0.018, 0.3500: 0.019, 0.4000: 0.02, 0.4500: 0.021, 0.5000: 0.022, 0.5500: 0.024, 0.6000: 0.025, 0.6500: 0.026, 0.7000: 0.027, 0.7500: 0.028, 0.8000: 0.029, 0.8500: 0.03, 0.9000: 0.502 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.0000, 0.0500, 0.1000, 0.1500, 0.2000, 0.2500, 0.3000, 0.3500, 0.4000, 0.4500, 0.5000, 0.5500, 0.6000, 0.6500, 0.7000, 0.7500, 0.8000, 0.8500, 0.9000, 0.9500, 1.0000, 1.0500, 1.1000, 1.1500, 1.2000, 1.2500, 1.3000, 1.3500, 1.4000, 1.4500, 1.5000, 1.5500, 1.6000, 1.6500, 1.7000, 1.7500, 1.8000, 1.8500, 1.9000, 1.9500, 2.0000, 2.0500, 2.1000, 2.1500, 2.2000, 2.2500, 2.3000, 2.3500, 2.4000, 2.4500, 2.5000, 2.5500, 2.6000, 2.6500, 2.7000, 2.7500, 2.8000, 2.8500, 2.9000, 2.9500, 3.0000, 3.0500, 3.1000, 3.1500, 3.2000, 3.2500, 3.3000, 3.3500, 3.4000, 3.4500, 3.5000, 3.5500, 3.6000, 3.6500, 3.7000, 3.7500, 3.8000, 3.8500, 3.9000, 3.9500, 4.0000, 4.0500, 4.1000, 4.1500, 4.2000, 4.2500, 4.3000, 4.3500, 4.4000, 4.4500, 4.5000, 4.5500, 4.6000, 4.6500, 4.7000, 4.7500, 4.8000, 4.8500, 4.9000, 4.9500, 5.0000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.953;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 0.9;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 
@@ -299,31 +299,31 @@ describe("Class Remous / section rectangulaire :", () => {
         // données de validation : version PHP (Oct 2017) méthode trapèzes
 
         const f = { 100.000: 1, 95.000: 0.999, 90.000: 0.999, 85.000: 0.998, 80.000: 0.997, 75.000: 0.997, 70.000: 0.996, 65.000: 0.996, 60.000: 0.995, 55.000: 0.994, 50.000: 0.994, 45.000: 0.993, 40.000: 0.992, 35.000: 0.992, 30.000: 0.991, 25.000: 0.991, 20.000: 0.99, 15.000: 0.989, 10.000: 0.989, 5.000: 0.988, 0.000: 0.988 };
-        compareObject("Yfluvial", res.flu, f, 0.03);
+        compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-        expect(Object.keys(res.tor).length === 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+        expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
         const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-        compareArray("abscisses", res.trX, x);
+        compareArray("abscisses", res.getExtraResult("trX"), x);
 
         const expLog = new cLog();
-        let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+        let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
         m.extraVar.B = 2.5;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+        m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
         m.extraVar.Yc = 0.403;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+        m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
         m.extraVar.Yn = 0.953;
         expLog.add(m);
 
-        expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+        expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
         expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-        compareLog(rem.log, expLog);
+        compareLog(res.globalLog, expLog);
     });
 
     it("faible pente, pas de ressaut, Yamont > Yc, Yc < Yaval < Yn", () => {
@@ -352,31 +352,31 @@ describe("Class Remous / section rectangulaire :", () => {
         // données de validation : version PHP (Oct 2017) méthode trapèzes
 
         const f = { 100.000: 0.7, 95.000: 0.708, 90.000: 0.716, 85.000: 0.723, 80.000: 0.73, 75.000: 0.737, 70.000: 0.743, 65.000: 0.749, 60.000: 0.754, 55.000: 0.76, 50.000: 0.765, 45.000: 0.77, 40.000: 0.775, 35.000: 0.779, 30.000: 0.783, 25.000: 0.787, 20.000: 0.792, 15.000: 0.795, 10.000: 0.799, 5.000: 0.803, 0.000: 0.806 };
-        compareObject("Yfluvial", res.flu, f, 0.03);
+        compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
-        expect(Object.keys(res.tor).length === 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
+        expect(res.extraResultLength("tor") == 0).toBeTruthy("la ligne d'eau torrentielle ne devrait comporter aucune valeur");
 
         const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-        compareArray("abscisses", res.trX, x);
+        compareArray("abscisses", res.getExtraResult("trX"), x);
 
         const expLog = new cLog();
-        let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+        let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
         m.extraVar.B = 2.5;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+        m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
         m.extraVar.Yc = 0.403;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+        m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
         m.extraVar.Yn = 0.953;
         expLog.add(m);
 
-        expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+        expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
         expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 
-        compareLog(rem.log, expLog);
+        compareLog(res.globalLog, expLog);
     });
 
     it("faible pente, pas de fluvial, torrentiel tronqué, calcul Hs", () => {
@@ -404,38 +404,38 @@ describe("Class Remous / section rectangulaire :", () => {
 
         // données de validation : version PHP (Oct 2017) méthode trapèzes
 
-        expect(Object.keys(res.flu).length === 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
+        expect(res.extraResultLength("flu") == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
         const t = { 0.000: 0.15, 5.000: 0.239, 10.000: 0.34 };
-        compareObject("Ytorrentiel", res.tor, t, 0.008);
+        compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.008);
 
         const x = [0.000, 5.000, 10.000];
-        compareArray("abscisses", res.trX, x);
+        compareArray("abscisses", res.getExtraResult("trX"), x);
 
         const extraHS = { 0.000: 1.6, 5.000: 0.808, 10.000: 0.618 };
-        compareObject("extra (Hs)", res.tRes, extraHS, 0.001);
+        compareObject("extra (Hs)", res.getExtraResult("tRes"), extraHS, 0.001);
 
         const expLog = new cLog();
-        let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+        let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
         m.extraVar.B = 2.5;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+        m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
         m.extraVar.Yc = 0.403;
         expLog.add(m);
 
-        m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+        m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
         m.extraVar.Yn = 0.953;
         expLog.add(m);
 
         expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-        expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+        expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-        m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+        m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
         m.extraVar.x = 15;
         expLog.add(m);
 
-        compareLog(rem.log, expLog);
+        compareLog(res.globalLog, expLog);
     });
 });
diff --git a/spec/remous/remous_rect_trapezes_penteforte.spec.ts b/spec/remous/remous_rect_trapezes_penteforte.spec.ts
index 20e2674c7c8d40cc63ab191d2f4be9fcde45143d..fd8875a93d9450d984634d49ac0e1b791d000ab0 100644
--- a/spec/remous/remous_rect_trapezes_penteforte.spec.ts
+++ b/spec/remous/remous_rect_trapezes_penteforte.spec.ts
@@ -1,9 +1,9 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { cLog } from "../../src/util/log";
 import { Message, MessageCode } from "../../src/util/message";
-import { compareArray, compareLog, compareObject, equalEpsilon, precDigits, precDist } from "../nubtest";
+import { compareArray, compareLog, compareObject, equalEpsilon } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
    cas 1 :
@@ -49,36 +49,36 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
             const f = { 100.000: 6, 95.000: 5.75, 90.000: 5.5, 85.000: 5.25, 80.000: 4.999, 75.000: 4.749, 70.000: 4.499, 65.000: 4.249, 60.000: 3.998, 55.000: 3.748, 50.000: 3.498, 45.000: 3.248, 40.000: 2.997, 35.000: 2.747, 30.000: 2.497, 25.000: 2.246, 20.000: 1.995, 15.000: 1.744, 10.000: 1.491, 5.000: 1.237, 0.000: 0.977 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = {};
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "amont";
             m.extraVar.x = 0;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, ressaut après l'aval", () => {
@@ -108,43 +108,43 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
             const f = {};
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.207, 10.000: 0.235, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252, 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.253 };
             // let t = { 0.000: 0.15, 5.000: 0.207, 10.000: 0.235, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252, 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.45 }; // dernière valeur modifiée pour la raison 1 en tête de fichier
             const t = { 0.000: 0.15, 5.000: 0.207, 10.000: 0.235, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252, 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.253, 100.000: 0.253 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 95;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
             m.extraVar.sens = "aval";
             m.extraVar.x = 100;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, ressaut (1 point) à l'intérieur du bief", () => {
@@ -173,42 +173,42 @@ describe("Class Remous / section rectangulaire :", () => {
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
             const f = { 100.000: 1, 95.000: 0.729 };
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             // let t = { 0.000: 0.15, 5.000: 0.207, 10.000: 0.235, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252, 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253, 95.000: 0.729 };
             const t = { 0.000: 0.15, 5.000: 0.207, 10.000: 0.235, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252, 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253, 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253, 90.000: 0.253 }; // dernière valeur supprimée pour la raison 2 en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000, 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+            m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
             m.extraVar.x = 90;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 90;
             m.extraVar.xmax = 95;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         xit("forte pente, ressaut (plusieurs points) à l'intérieur du bief", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -238,37 +238,37 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // let f = { 5.500: 1, 5.250: 0.987, 5.000: 0.974, 4.750: 0.96, 4.500: 0.947, 4.250: 0.933, 4.000: 0.92, 3.750: 0.906, 3.500: 0.893, 3.250: 0.88, 3.000: 0.866, 2.750: 0.853, 2.500: 0.839, 2.250: 0.826, 2.000: 0.812, 1.750: 0.798, 1.500: 0.784, 1.250: 0.77, 1.000: 0.756, 0.750: 0.742, 0.500: 0.727, 0.250: 0.712, 0.000: 0.15 };
             const f = { 5.500: 1, 5.250: 0.987, 5.000: 0.974, 4.750: 0.96, 4.500: 0.947, 4.250: 0.933, 4.000: 0.92, 3.750: 0.906, 3.500: 0.893, 3.250: 0.88, 3.000: 0.866, 2.750: 0.853, 2.500: 0.839, 2.250: 0.826, 2.000: 0.812, 1.750: 0.798, 1.500: 0.784, 1.250: 0.77, 1.000: 0.756, 0.750: 0.742, 0.500: 0.727, 0.250: 0.712, 0.000: 0.699 };  // dernière valeur modifiée pour la raison 1 en tête de fichier
-            compareObject("Yfluvial", res.flu, f, 0.03);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.03);
 
             const t = { 0.000: 0.15, 0.250: 0.153, 0.500: 0.156, 0.750: 0.158, 1.000: 0.161, 1.250: 0.163, 1.500: 0.166, 1.750: 0.168, 2.000: 0.17, 2.250: 0.173, 2.500: 0.175, 2.750: 0.177, 3.000: 0.18, 3.250: 0.182, 3.500: 0.184, 3.750: 0.906 };
-            compareObject("Ytorrentiel", res.tor, t, 0.03);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.03);
 
             const x = [0.000, 0.250, 0.500, 0.750, 1.000, 1.250, 1.500, 1.750, 2.000, 2.250, 2.500, 2.750, 3.000, 3.250, 3.500, 3.750, 4.000, 4.250, 4.500, 4.750, 5.000, 5.250, 5.500];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+            m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
             m.extraVar.xmin = 0;
             m.extraVar.xmax = 3.75;
             expLog.add(m);
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yamont < Yn", () => {
@@ -296,38 +296,39 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
-            expect(Object.keys(res.flu).length === 0).toBeTruthy(
+            expect(res.extraResultLength("flu") == 0).toBeTruthy(
                 "la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = {
                 0.000: 0.1, 5.000: 0.205, 10.000: 0.234, 15.000: 0.246, 20.000: 0.25, 25.000: 0.252,
                 30.000: 0.253, 35.000: 0.253, 40.000: 0.253, 45.000: 0.253, 50.000: 0.253, 55.000: 0.253,
                 60.000: 0.253, 65.000: 0.253, 70.000: 0.253, 75.000: 0.253, 80.000: 0.253, 85.000: 0.253,
-                90.000: 0.253, 95.000: 0.253, 100.000: 0.253 };
-            compareObject("Ytorrentiel", res.tor, t, 0.01);
+                90.000: 0.253, 95.000: 0.253, 100.000: 0.253
+            };
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.01);
 
             const x = [0.000, 5.000, 10.000, 15.000, 20.000, 25.000, 30.000, 35.000, 40.000, 45.000, 50.000,
                 55.000, 60.000, 65.000, 70.000, 75.000, 80.000, 85.000, 90.000, 95.000, 100.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
 
         it("forte pente, pas de ressaut, Yaval < Yc, Yn < Yamont < Yc", () => {
@@ -355,32 +356,32 @@ describe("Class Remous / section rectangulaire :", () => {
 
             // données de validation : version PHP (Oct 2017) méthode trapèzes
 
-            expect(Object.keys(res.flu).length === 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
+            expect(res.extraResultLength("flu") == 0).toBeTruthy("la ligne d'eau fluviale ne devrait comporter aucune valeur");
 
             const t = { 0.000: 0.35, 0.100: 0.345, 0.200: 0.34, 0.300: 0.336, 0.400: 0.332, 0.500: 0.329, 0.600: 0.326, 0.700: 0.323, 0.800: 0.32, 0.900: 0.318, 1.000: 0.316, 1.100: 0.313, 1.200: 0.311, 1.300: 0.309, 1.400: 0.308, 1.500: 0.306, 1.600: 0.305, 1.700: 0.303, 1.800: 0.302, 1.900: 0.3, 2.000: 0.298, 2.100: 0.297, 2.200: 0.295, 2.300: 0.294, 2.400: 0.293, 2.500: 0.292, 2.600: 0.291, 2.700: 0.291, 2.800: 0.29, 2.900: 0.289, 3.000: 0.288, 3.100: 0.287, 3.200: 0.287, 3.300: 0.286, 3.400: 0.285, 3.500: 0.284, 3.600: 0.283, 3.700: 0.283, 3.800: 0.282, 3.900: 0.281, 4.000: 0.28, 4.100: 0.28, 4.200: 0.279, 4.300: 0.278, 4.400: 0.277, 4.500: 0.276, 4.600: 0.276, 4.700: 0.275, 4.800: 0.274, 4.900: 0.273, 5.000: 0.272, 5.100: 0.272, 5.200: 0.271, 5.300: 0.27, 5.400: 0.269, 5.500: 0.269, 5.600: 0.269, 5.700: 0.269, 5.800: 0.269, 5.900: 0.269, 6.000: 0.269, 6.100: 0.269, 6.200: 0.269, 6.300: 0.269, 6.400: 0.269, 6.500: 0.269, 6.600: 0.269, 6.700: 0.269, 6.800: 0.269, 6.900: 0.269, 7.000: 0.269, 7.100: 0.269, 7.200: 0.269, 7.300: 0.269, 7.400: 0.269, 7.500: 0.269, 7.600: 0.269, 7.700: 0.269, 7.800: 0.269, 7.900: 0.269, 8.000: 0.269, 8.100: 0.269, 8.200: 0.269, 8.300: 0.269, 8.400: 0.269, 8.500: 0.269, 8.600: 0.269, 8.700: 0.269, 8.800: 0.269, 8.900: 0.269, 9.000: 0.269, 9.100: 0.269, 9.200: 0.269, 9.300: 0.269, 9.400: 0.269, 9.500: 0.269, 9.600: 0.269, 9.700: 0.269, 9.800: 0.269, 9.900: 0.269, 10.000: 0.269 };
-            compareObject("Ytorrentiel", res.tor, t, 0.01);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.01);
 
             const x = [0.000, 0.100, 0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.800, 0.900, 1.000, 1.100, 1.200, 1.300, 1.400, 1.500, 1.600, 1.700, 1.800, 1.900, 2.000, 2.100, 2.200, 2.300, 2.400, 2.500, 2.600, 2.700, 2.800, 2.900, 3.000, 3.100, 3.200, 3.300, 3.400, 3.500, 3.600, 3.700, 3.800, 3.900, 4.000, 4.100, 4.200, 4.300, 4.400, 4.500, 4.600, 4.700, 4.800, 4.900, 5.000, 5.100, 5.200, 5.300, 5.400, 5.500, 5.600, 5.700, 5.800, 5.900, 6.000, 6.100, 6.200, 6.300, 6.400, 6.500, 6.600, 6.700, 6.800, 6.900, 7.000, 7.100, 7.200, 7.300, 7.400, 7.500, 7.600, 7.700, 7.800, 7.900, 8.000, 8.100, 8.200, 8.300, 8.400, 8.500, 8.600, 8.700, 8.800, 8.900, 9.000, 9.100, 9.200, 9.300, 9.400, 9.500, 9.600, 9.700, 9.800, 9.900, 10.000];
-            compareArray("abscisses", res.trX, x);
+            compareArray("abscisses", res.getExtraResult("trX"), x);
 
             const expLog = new cLog();
-            let m = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
+            let m = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
             m.extraVar.B = 2.5;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+            m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
             m.extraVar.Yc = 0.403;
             expLog.add(m);
 
-            m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+            m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
             m.extraVar.Yn = 0.253;
             expLog.add(m);
 
             expLog.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 
-            expLog.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+            expLog.add(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 
-            compareLog(rem.log, expLog);
+            compareLog(res.globalLog, expLog);
         });
     });
 });
diff --git a/spec/remous/remous_trapez.spec.ts b/spec/remous/remous_trapez.spec.ts
index 49594e031173e8e795a0a851b89d74dc2157f722..563c42cea8bbbd2bd51b57af7ac7f02d7e935d7a 100644
--- a/spec/remous/remous_trapez.spec.ts
+++ b/spec/remous/remous_trapez.spec.ts
@@ -1,9 +1,8 @@
-import { round } from "../../src/base";
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnTrapez, ParamsSectionTrapez } from "../../src/section/section_trapez";
 import { cLog } from "../../src/util/log";
-import { equalEpsilon, precDigits, precDist } from "../nubtest";
-import { compareArray, compareObject } from "../nubtest";
+import { equalEpsilon, compareArray, compareObject } from "../test_func";
+import { precDist } from "../test_config";
 
 /*
    Certaines valeurs de ligne d'eau torrentielle étaient auparavant remplacées par une valeur fluviale
@@ -39,14 +38,14 @@ describe("Class Remous / section trapèze :", () => {
             const res = rem.calculRemous(undefined);
 
             const f = { 9: 0.278, 10: 0.4 };
-            compareObject("Yfluvial", res.flu, f, 0.002);
+            compareObject("Yfluvial", res.getExtraResult("flu"), f, 0.002);
 
             // let t = { 0.000: 0.15, 1.000: 0.16369914454109, 2.000: 0.17743613485223, 3.000: 0.19117312516337, 4.000: 0.20491011547451, 5.000: 0.21864710578565, 6.000: 0.23238409609679, 7.000: 0.24688425253633, 8.000: 0.26214757510426, 9.000: 0.27817406380059, 10.000: 0.4 };
             const t = { 0.000: 0.15, 1.000: 0.16369914454109, 2.000: 0.17743613485223, 3.000: 0.19117312516337, 4.000: 0.20491011547451, 5.000: 0.21864710578565, 6.000: 0.23238409609679, 7.000: 0.24688425253633, 8.000: 0.26214757510426, 9.000: 0.27817406380059, 10.000: 0.293 };  // dernière valeur modifiée pour la raison en tête de fichier
-            compareObject("Ytorrentiel", res.tor, t, 0.002);
+            compareObject("Ytorrentiel", res.getExtraResult("tor"), t, 0.002);
 
             const x = [0.000, 1.000, 2.000, 3.000, 4.000, 5.000, 6.000, 7.000, 8.000, 9.000, 10.000];
-            compareArray("abcisses", res.trX, x);
+            compareArray("abcisses", res.getExtraResult("trX"), x);
         });
 
         // it('pente forte, ressaut dans le bief sur plusieurs points', () => {
@@ -113,7 +112,7 @@ describe("Class Remous / section trapèze :", () => {
 
             // données de validation : version PHP (oct 2017)
             const hs = { 0.000: 1.507, 5.000: 0.735, 10.000: 0.731, 15.000: 0.727, 20.000: 0.723, 25.000: 0.719, 30.000: 0.715, 35.000: 0.71, 40.000: 0.704, 45.000: 0.699, 50.000: 0.693, 55.000: 0.687, 60.000: 0.68, 65.000: 0.673, 70.000: 0.665, 75.000: 0.656, 80.000: 0.646, 85.000: 0.634, 90.000: 0.62, 95.000: 0.603, 100.000: 0.572 };
-            compareObject("Hs", res.tRes, hs, 0.002);
+            compareObject("Hs", res.getExtraResult("tRes"), hs, 0.002);
         });
 
         xit("Hs (test 2)", () => { // désactivé car échoue depuis les modifs apportées depuis la version PHP (calcul du ressaut hydraulique)
@@ -144,7 +143,7 @@ describe("Class Remous / section trapèze :", () => {
             // données de validation : version PHP (oct 2017)
             // ici j'ai supprimé un point (x=2.5)
             const hs = { 0.000: 1.507, 2.600: 0.753, 2.700: 0.757, 2.800: 0.762, 2.900: 0.767, 3.000: 0.771, 3.100: 0.776, 3.200: 0.781, 3.300: 0.786, 3.400: 0.79, 3.500: 0.795, 3.600: 0.8, 3.700: 0.805, 3.800: 0.81, 3.900: 0.814, 4.000: 0.819, 4.100: 0.824, 4.200: 0.829, 4.300: 0.834, 4.400: 0.839, 4.500: 0.844, 4.600: 0.849, 4.700: 0.854, 4.800: 0.859, 4.900: 0.864, 5.000: 0.869, 5.100: 0.874, 5.200: 0.879, 5.300: 0.884, 5.400: 0.889, 5.500: 0.894, 5.600: 0.899, 5.700: 0.904, 5.800: 0.909, 5.900: 0.914, 6.000: 0.919, 6.100: 0.924, 6.200: 0.929, 6.300: 0.934, 6.400: 0.939, 6.500: 0.944, 6.600: 0.95, 6.700: 0.955, 6.800: 0.96, 6.900: 0.965, 7.000: 0.97, 7.100: 0.975, 7.200: 0.98, 7.300: 0.986, 7.400: 0.991, 7.500: 0.996, 7.600: 1.001, 7.700: 1.006, 7.800: 1.012, 7.900: 1.017, 8.000: 1.022 };
-            compareObject("Hs", res.tRes, hs, 0.009);
+            compareObject("Hs", res.getExtraResult("tRes"), hs, 0.009);
         });
     });
 });
diff --git a/spec/remous/test-remous-fenetre.ts b/spec/remous/test-remous-fenetre.ts
index 1a1a89fee7bb12e4a943dd83bc8a5c75034f544d..e62ae2aaf72c37741400ec9d6c4471aee4f91b46 100644
--- a/spec/remous/test-remous-fenetre.ts
+++ b/spec/remous/test-remous-fenetre.ts
@@ -1,9 +1,9 @@
 // tslint:disable:no-console
 import { CourbeRemous, CourbeRemousParams, MethodeResolution } from "../../src/remous";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
-import { cLog } from "../../src/util/log";
-import { Message, MessageCode, MessageSeverity } from "../../src/util/message";
-import { equalEpsilon, nub, precDist } from "../nubtest";
+import { equalEpsilon, compareArray } from "../test_func";
+import { Result } from "../../src/util/result";
+import { ResultElement } from "../../src/util/resultelement";
 
 /*
    Tentative de validation automatique du calcul des courbes de remous.
@@ -16,21 +16,6 @@ import { equalEpsilon, nub, precDist } from "../nubtest";
    $ npm run runtestremous
  */
 
-class Expect {
-    constructor(private b: boolean) {
-
-    }
-    public toBeTruthy(m: string) {
-        if (!this.b) {
-            console.log(m);
-        }
-    }
-}
-
-function expect(b: boolean): Expect {
-    return new Expect(b);
-}
-
 export function compareObject(
     s: string,
     objTest: { [key: number]: number },
@@ -70,24 +55,6 @@ export function compareObject(
     return true;
 }
 
-export function compareArray(s: string, arrTest: string[], arrValid: string[]): boolean {
-    const n1 = arrTest.length;
-    const n2 = arrValid.length;
-    let b: boolean = n1 === n2;
-    expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
-    if (!b) { return false; }
-
-    for (let i = 0; i < arrTest.length; i++) {
-        const v1: number = +arrTest[i];
-        const v2: number = +arrValid[i];
-        b = equalEpsilon(v1, v2);
-        expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
-        if (!b) { return false; }
-    }
-
-    return true;
-}
-
 function logObject(obj: {}, m?: string) {
     // évite le message "Value below was evaluated just now" dans le debugger de Chrome
     if (m === undefined) {
@@ -217,52 +184,64 @@ function testFenetre() {
     // calcul du bief
 
     const r = computeFenetreRect(Yamont, Yaval, longBief, false);
-    const res: {
-        "flu": { [key: number]: number; },
-        "tor": { [key: number]: number; },
-        "trX": string[],
-        "tRes": { [key: number]: number },
-    } = r.res;
+    // const res: {
+    //     "flu": { [key: number]: number; },
+    //     "tor": { [key: number]: number; },
+    //     "trX": string[],
+    //     "tRes": { [key: number]: number },
+    // } = r.res;
+    const res: Result = r.res;
+    expect(res.ok).toBeTruthy("erreur de calcul de la courbe globale");
 
     const remous = r.remous;
 
     // ligne fluviale totale, utilisée pour les conditions initiales
-    const ligneFluviale: { [key: number]: number; } = remous.calculFluvial();
+    // const ligneFluviale: { [key: number]: number; } = remous.calculFluvial();
+    const rLigneFluviale: ResultElement = remous.calculFluvial();
+    expect(rLigneFluviale.ok).toBeTruthy("erreur de calcul de la ligne fluviale");
+    const ligneFluviale: { [key: number]: number; } = rLigneFluviale.getExtraResult("trY");
 
     // ligne torrentielle totale, utilisée pour les conditions initiales
-    const ligneTorrentielle: { [key: number]: number; } = remous.calculTorrentiel();
+    // const ligneTorrentielle: { [key: number]: number; } = remous.calculTorrentiel();
+    const rLigneTorrentielle: ResultElement = remous.calculTorrentiel();
+    expect(rLigneTorrentielle.ok).toBeTruthy("erreur de calcul de la ligne torrentielle");
+    const ligneTorrentielle: { [key: number]: number; } = rLigneTorrentielle.getExtraResult("trY");
 
     console.log(remous.log.toString());
     // let ms = r["remous"].log.messages;
 
+    const trX = res.getExtraResult("trX");
+    const flu = res.getExtraResult("flu");
+    const tor = res.getExtraResult("tor");
+
     //  saveCSV(res);
 
     console.log("X");
-    logObject(res.trX);
-    logArray("flu", res.flu);
-    logArray("tor", res.tor);
+    logObject(trX);
+    logArray("flu", flu);
+    logArray("tor", tor);
 
     // mouvement de la fenêtre
 
     console.log("\n\nMOUVEMENT DE LA FENETRE\n\n");
 
-    const sizeFenetre = Math.round(res.trX.length / 3.5);
+    const sizeFenetre = Math.round(trX.length / 3.5);
     console.log("taille de la fenetre (points) " + sizeFenetre);
     if (sizeFenetre < 3) {
         throw new Error("pas de discrétisation trop grand !");
     }
 
-    const nFlu = Object.keys(res.flu).length;
+    const nFlu = Object.keys(flu).length;
     if (nFlu < sizeFenetre * 2) {
         throw new Error("pb de calcul de la ligne fluviale : nb de points (" + nFlu + ") < fenetre * 2");
     }
 
-    const nTor = Object.keys(res.tor).length;
+    const nTor = Object.keys(tor).length;
     if (nTor < sizeFenetre * 2) {
         throw new Error("pb de calcul de la ligne torrentielle : nb de points (" + nTor + ") < fenetre * 2");
     }
 
-    const nX = res.trX.length;
+    const nX = trX.length;
     console.log("taille du bief (points)=" + nX);
 
     const ni = 13;
@@ -271,8 +250,8 @@ function testFenetre() {
         console.log("i1", i1);
 
         const i2 = i1 + sizeFenetre - 1;
-        const xBief1: number = Number(res.trX[i1]);
-        const xBief2: number = Number(res.trX[i2]);
+        const xBief1: number = Number(trX[i1]);
+        const xBief2: number = Number(trX[i2]);
         console.log("test fenetre xBief=[" + xBief1 + "," + xBief2 + "]");
         console.log("longueur fenetre " + (+xBief2 - +xBief1));
 
@@ -304,19 +283,23 @@ function testFenetre() {
         console.log("computeFenetre y am/av=" + yAmont + " " + yAval);
 
         const r2 = computeFenetreRect(yAmont, yAval, +xBief2 - +xBief1, i1 === ni);
-        const resFenetre = r2.res;
+        const resFenetre: Result = r2.res;
+        expect(resFenetre.ok).toBeTruthy("erreur de calcul de la fenêtre");
+        let trX_fenetre = resFenetre.getExtraResult("trX");
+        let flu_fenetre = resFenetre.getExtraResult("flu");
+        let tor_fenetre = resFenetre.getExtraResult("tor");
 
         // validation du tableau d'abscisses
 
-        const validX: string[] = [];
+        const validX: number[] = [];
         for (let i = i1; i <= i2; i++) {
-            validX.push(String(+res.trX[i] - dxBief * i1));
+            validX.push(+trX[i] - dxBief * i1);
         }
-        if (!compareArray("X", resFenetre.trX, validX)) {
+        if (!compareArray("X", trX_fenetre, validX)) {
             console.log("X valid");
             logObject(validX);
             console.log("X fenetre");
-            logObject(resFenetre.trX);
+            logObject(trX_fenetre);
             break;
         }
         /**/
@@ -328,19 +311,19 @@ function testFenetre() {
 
         const validFlu: { [key: number]: number; } = {};
         for (let i = i1; i <= i2; i++) {
-            const x: number = +res.trX[i];
-            const y: number = res.flu[x];
+            const x: number = +trX[i];
+            const y: number = flu[x];
             if (y !== undefined) {
                 validFlu[(i - i1) * dxBief] = y;
             }
             // validFlu[x] = y;
         }
         if (Object.keys(validFlu).length > 0) {
-            if (!compareObject("Flu", resFenetre.flu, validFlu, prec)) {
+            if (!compareObject("Flu", flu_fenetre, validFlu, prec)) {
                 console.log("flu valid");
                 logObject(validFlu);
                 console.log("flu fenetre");
-                logObject(resFenetre.flu);
+                logObject(flu_fenetre);
                 // break;
             }
         }
@@ -350,19 +333,19 @@ function testFenetre() {
 
         const validTor: { [key: number]: number; } = {};
         for (let i = i1; i <= i2; i++) {
-            const x: number = +res.trX[i];
-            const y: number = res.tor[x];
+            const x: number = +trX[i];
+            const y: number = tor[x];
             if (y !== undefined) {
                 validTor[(i - i1) * dxBief] = y;
             }
             // validTor[x] = y;
         }
         if (Object.keys(validTor).length > 0) {
-            if (!compareObject("Tor", resFenetre.tor, validTor, prec)) {
+            if (!compareObject("Tor", tor_fenetre, validTor, prec)) {
                 console.log("tor valid");
                 logObject(validTor);
                 console.log("tor fenetre");
-                logObject(resFenetre.tor);
+                logObject(tor_fenetre);
                 // break;
             }
         }
diff --git a/spec/section_param/section_param_circ_fluvial.spec.ts b/spec/section_param/section_param_circ_fluvial.spec.ts
index 50c651bb557ab2c8928aeab3f6150d6c1b2d5019..b301178606bede9e0c634e2600f02ab43e42075f 100644
--- a/spec/section_param/section_param_circ_fluvial.spec.ts
+++ b/spec/section_param/section_param_circ_fluvial.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnCirc, ParamsSectionCirc } from "../../src/section/section_circulaire";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionCirc;
 let sect: cSnCirc;
@@ -31,10 +31,6 @@ function createSectionDebordement(prec: number): cSnCirc {
     return new cSnCirc(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée circulaire : ", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -43,89 +39,89 @@ describe("Section paramétrée circulaire : ", () => {
     describe("fluvial / pas de débordement :", () => {
         // charge spécifique
         it("Hs should equal to 0.853", () => {
-            check(sect.Calc("Hs"), 0.853);
+            checkResult(sect.Calc("Hs"), 0.853);
         });
 
         // charge critique
         it("Hsc should equal to 0.694", () => {
-            check(sect.Calc("Hsc"), 0.694);
+            checkResult(sect.Calc("Hsc"), 0.694);
         });
 
         // largeur au miroir
         it("B should equal to 1.959", () => {
-            check(sect.Calc("B"), 1.959);
+            checkResult(sect.Calc("B"), 1.959);
         });
 
         // périmètre mouillé
         it("P should equal to 2.738", () => {
-            check(sect.Calc("P"), 2.738);
+            checkResult(sect.Calc("P"), 2.738);
         });
 
         // surface mouillée
         it("S should equal to 1.173", () => {
-            check(sect.Calc("S"), 1.173);
+            checkResult(sect.Calc("S"), 1.173);
         });
 
         // rayon hydraulique
         it("R should equal to 0.428", () => {
-            check(sect.Calc("R"), 0.428);
+            checkResult(sect.Calc("R"), 0.428);
         });
 
         // vitesse moyenne
         it("V should equal to 1.023", () => {
-            check(sect.Calc("V"), 1.023);
+            checkResult(sect.Calc("V"), 1.023);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.422", () => {
-            check(sect.Calc("Fr"), 0.422);
+            checkResult(sect.Calc("Fr"), 0.422);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.512", () => {
-            check(sect.Calc("Yc"), 0.512);
+            checkResult(sect.Calc("Yc"), 0.512);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.976", () => {
-            check(sect.Calc("Yn"), 0.976);
+            checkResult(sect.Calc("Yn"), 0.976);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 0.8", () => {
-            check(sect.Calc("Yf"), 0.8);
+            checkResult(sect.Calc("Yf"), 0.8);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.361", () => {
-            check(sect.Calc("Yt"), 0.361);
+            checkResult(sect.Calc("Yt"), 0.361);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.307", () => {
-            check(sect.Calc("Yco"), 0.307);
+            checkResult(sect.Calc("Yco"), 0.307);
         });
 
         // perte de charge
         it("J should equal to 0.002", () => {
             // sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.002);
+            checkResult(sect.Calc("J"), 0.002);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to -0.00102", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("I-J"), -0.00102);
+            checkResult(sect.Calc("I-J"), -0.00102);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 5076.304", () => {
-            check(sect.Calc("Imp"), 5076.304);
+            checkResult(sect.Calc("Imp"), 5076.304);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 8.505", () => {
-            check(sect.Calc("Tau0"), 8.505);
+            checkResult(sect.Calc("Tau0"), 8.505);
         });
     });
 });
@@ -138,89 +134,89 @@ describe("Section paramétrée circulaire : ", () => {
     describe("fluvial / débordement :", () => {
         // charge spécifique
         it("Hs should equal to 2.006", () => {
-            check(sect.Calc("Hs"), 2.006);
+            checkResult(sect.Calc("Hs"), 2.006);
         });
 
         // charge critique
         it("Hsc should equal to 0.694", () => {
-            check(sect.Calc("Hsc"), 0.694);
+            checkResult(sect.Calc("Hsc"), 0.694);
         });
 
         // largeur au miroir
         it("B should equal to 2", () => {
-            check(sect.Calc("B"), 2);
+            checkResult(sect.Calc("B"), 2);
         });
 
         // périmètre mouillé
         it("P should equal to 5.142", () => {
-            check(sect.Calc("P"), 5.142);
+            checkResult(sect.Calc("P"), 5.142);
         });
 
         // surface mouillée
         it("S should equal to 3.571", () => {
-            check(sect.Calc("S"), 3.571);
+            checkResult(sect.Calc("S"), 3.571);
         });
 
         // rayon hydraulique
         it("R should equal to 0.694", () => {
-            check(sect.Calc("R"), 0.694);
+            checkResult(sect.Calc("R"), 0.694);
         });
 
         // vitesse moyenne
         it("V should equal to 0.336", () => {
-            check(sect.Calc("V"), 0.336);
+            checkResult(sect.Calc("V"), 0.336);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.08", () => {
-            check(sect.Calc("Fr"), 0.08);
+            checkResult(sect.Calc("Fr"), 0.08);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.512", () => {
-            check(sect.Calc("Yc"), 0.512);
+            checkResult(sect.Calc("Yc"), 0.512);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.976", () => {
-            check(sect.Calc("Yn"), 0.976);
+            checkResult(sect.Calc("Yn"), 0.976);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 2", () => {
-            check(sect.Calc("Yf"), 2);
+            checkResult(sect.Calc("Yf"), 2);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.232", () => {
-            check(sect.Calc("Yt"), 0.232);
+            checkResult(sect.Calc("Yt"), 0.232);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.24", () => {
-            check(sect.Calc("Yco"), 0.24);
+            checkResult(sect.Calc("Yco"), 0.24);
         });
 
         // perte de charge
         it("J should equal to 0.0001", () => {
             sect = createSectionDebordement(0.00001);
-            check(sect.Calc("J"), 0.0001);
+            checkResult(sect.Calc("J"), 0.0001);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.001", () => {
             sect = createSectionDebordement(0.00001);
-            check(sect.Calc("I-J"), 0.001);
+            checkResult(sect.Calc("I-J"), 0.001);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 6943.271", () => {
-            check(sect.Calc("Imp"), 6943.271);
+            checkResult(sect.Calc("Imp"), 6943.271);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 0.782", () => {
-            check(sect.Calc("Tau0"), 0.782);
+            checkResult(sect.Calc("Tau0"), 0.782);
         });
     });
 });
diff --git a/spec/section_param/section_param_circ_torrentiel.spec.ts b/spec/section_param/section_param_circ_torrentiel.spec.ts
index 917eb5e3354a24977d7691dd5f22a11191368590..35a11220ca9f03fac04cd86a49fc41ad91ccf705 100644
--- a/spec/section_param/section_param_circ_torrentiel.spec.ts
+++ b/spec/section_param/section_param_circ_torrentiel.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnCirc, ParamsSectionCirc } from "../../src/section/section_circulaire";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionCirc;
 let sect: cSnCirc;
@@ -18,10 +18,6 @@ function createSection(prec: number): cSnCirc {
     return new cSnCirc(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée circulaire : ", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -30,89 +26,89 @@ describe("Section paramétrée circulaire : ", () => {
     describe("torrentiel :", () => {
         // charge spécifique
         it("Hs should equal to 4.501", () => {
-            check(sect.Calc("Hs"), 4.501);
+            checkResult(sect.Calc("Hs"), 4.501);
         });
 
         // charge critique
         it("Hsc should equal to 2.263", () => {
-            check(sect.Calc("Hsc"), 2.263);
+            checkResult(sect.Calc("Hsc"), 2.263);
         });
 
         // largeur au miroir
         it("B should equal to 1.960", () => {
-            check(sect.Calc("B"), 1.960);
+            checkResult(sect.Calc("B"), 1.960);
         });
 
         // périmètre mouillé
         it("P should equal to 2.739", () => {
-            check(sect.Calc("P"), 2.739);
+            checkResult(sect.Calc("P"), 2.739);
         });
 
         // surface mouillée
         it("S should equal to 1.173", () => {
-            check(sect.Calc("S"), 1.173);
+            checkResult(sect.Calc("S"), 1.173);
         });
 
         // rayon hydraulique
         it("R should equal to 0.428", () => {
-            check(sect.Calc("R"), 0.428);
+            checkResult(sect.Calc("R"), 0.428);
         });
 
         // vitesse moyenne
         it("V should equal to 8.522", () => {
-            check(sect.Calc("V"), 8.522);
+            checkResult(sect.Calc("V"), 8.522);
         });
 
         // nombre de Froude
         it("Fr should equal to 3.516", () => {
-            check(sect.Calc("Fr"), 3.516);
+            checkResult(sect.Calc("Fr"), 3.516);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 1.581", () => {
-            check(sect.Calc("Yc"), 1.581);
+            checkResult(sect.Calc("Yc"), 1.581);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 4.624", () => {
-            check(sect.Calc("Yn"), 4.624);
+            checkResult(sect.Calc("Yn"), 4.624);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 4.43", () => {
-            check(sect.Calc("Yf"), 4.43);
+            checkResult(sect.Calc("Yf"), 4.43);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.8", () => {
-            check(sect.Calc("Yt"), 0.8);
+            checkResult(sect.Calc("Yt"), 0.8);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.8", () => {
-            check(sect.Calc("Yco"), 0.8);
+            checkResult(sect.Calc("Yco"), 0.8);
         });
 
         // perte de charge
         it("J should equal to 0.141", () => {
             // sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.141);
+            checkResult(sect.Calc("J"), 0.141);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to -0.14", () => {
             // sect = createSection(0.00001);
-            check(sect.Calc("I-J"), -0.14);
+            checkResult(sect.Calc("I-J"), -0.14);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 89065.861", () => {
-            check(sect.Calc("Imp"), 89065.861);
+            checkResult(sect.Calc("Imp"), 89065.861);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 590.605", () => {
-            check(sect.Calc("Tau0"), 590.605);
+            checkResult(sect.Calc("Tau0"), 590.605);
         });
     });
 });
diff --git a/spec/section_param/section_param_puiss_fluvial.spec.ts b/spec/section_param/section_param_puiss_fluvial.spec.ts
index 5b5df72221b9509e61c7508da5dee1a902348ea2..221092f4ffee3694762891fb2b80136207ba4fd2 100644
--- a/spec/section_param/section_param_puiss_fluvial.spec.ts
+++ b/spec/section_param/section_param_puiss_fluvial.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnPuiss, ParamsSectionPuiss } from "../../src/section/section_puissance";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionPuiss;
 let sect: cSnPuiss;
@@ -33,10 +33,6 @@ function createSectionDebordement(prec: number): cSnPuiss {
     return new cSnPuiss(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée puissance :", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -45,89 +41,89 @@ describe("Section paramétrée puissance :", () => {
     describe("fluvial / pas de débordement :", () => {
         // charge spécifique
         it("Hs should equal to 0.82", () => {
-            check(sect.Calc("Hs"), 0.82);
+            checkResult(sect.Calc("Hs"), 0.82);
         });
 
         // charge critique
         it("Hsc should equal to 0.559", () => {
-            check(sect.Calc("Hsc"), 0.559);
+            checkResult(sect.Calc("Hsc"), 0.559);
         });
 
         // largeur au miroir
         it("B should equal to 3.578", () => {
-            check(sect.Calc("B"), 3.578);
+            checkResult(sect.Calc("B"), 3.578);
         });
 
         // périmètre mouillé
         it("P should equal to 4.223", () => {
-            check(sect.Calc("P"), 4.223);
+            checkResult(sect.Calc("P"), 4.223);
         });
 
         // surface mouillée
         it("S should equal to 1.908", () => {
-            check(sect.Calc("S"), 1.908);
+            checkResult(sect.Calc("S"), 1.908);
         });
 
         // rayon hydraulique
         it("R should equal to 0.452", () => {
-            check(sect.Calc("R"), 0.452);
+            checkResult(sect.Calc("R"), 0.452);
         });
 
         // vitesse moyenne
         it("V should equal to 0.629", () => {
-            check(sect.Calc("V"), 0.629);
+            checkResult(sect.Calc("V"), 0.629);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.275", () => {
-            check(sect.Calc("Fr"), 0.275);
+            checkResult(sect.Calc("Fr"), 0.275);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.419", () => {
-            check(sect.Calc("Yc"), 0.419);
+            checkResult(sect.Calc("Yc"), 0.419);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.742", () => {
-            check(sect.Calc("Yn"), 0.742);
+            checkResult(sect.Calc("Yn"), 0.742);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 0.8", () => {
-            check(sect.Calc("Yf"), 0.8);
+            checkResult(sect.Calc("Yf"), 0.8);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.265", () => {
-            check(sect.Calc("Yt"), 0.265);
+            checkResult(sect.Calc("Yt"), 0.265);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.189", () => {
-            check(sect.Calc("Yco"), 0.189);
+            checkResult(sect.Calc("Yco"), 0.189);
         });
 
         // perte de charge
         it("J should equal to 0.0007", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.0007);
+            checkResult(sect.Calc("J"), 0.0007);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.000335", () => {
             sect = createSection(0.000001);
-            check(sect.Calc("I-J"), 0.000335);
+            checkResult(sect.Calc("I-J"), 0.000335);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 6744.616", () => {
-            check(sect.Calc("Imp"), 6744.616);
+            checkResult(sect.Calc("Imp"), 6744.616);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 3.16", () => {
-            check(sect.Calc("Tau0"), 3.16);
+            checkResult(sect.Calc("Tau0"), 3.16);
         });
     });
 });
@@ -140,89 +136,89 @@ describe("Section paramétrée puissance :", () => {
     describe("fluvial / débordement :", () => {
         // charge spécifique
         it("Hs should equal to 2.001", () => {
-            check(sect.Calc("Hs"), 2.001);
+            checkResult(sect.Calc("Hs"), 2.001);
         });
 
         // charge critique
         it("Hsc should equal to 0.559", () => {
-            check(sect.Calc("Hsc"), 0.559);
+            checkResult(sect.Calc("Hsc"), 0.559);
         });
 
         // largeur au miroir
         it("B should equal to 4", () => {
-            check(sect.Calc("B"), 4);
+            checkResult(sect.Calc("B"), 4);
         });
 
         // périmètre mouillé
         it("P should equal to 6.098", () => {
-            check(sect.Calc("P"), 6.098);
+            checkResult(sect.Calc("P"), 6.098);
         });
 
         // surface mouillée
         it("S should equal to 7.542", () => {
-            check(sect.Calc("S"), 7.542);
+            checkResult(sect.Calc("S"), 7.542);
         });
 
         // rayon hydraulique
         it("R should equal to 1.237", () => {
-            check(sect.Calc("R"), 1.237);
+            checkResult(sect.Calc("R"), 1.237);
         });
 
         // vitesse moyenne
         it("V should equal to 0.159", () => {
-            check(sect.Calc("V"), 0.159);
+            checkResult(sect.Calc("V"), 0.159);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.037", () => {
-            check(sect.Calc("Fr"), 0.037);
+            checkResult(sect.Calc("Fr"), 0.037);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.419", () => {
-            check(sect.Calc("Yc"), 0.419);
+            checkResult(sect.Calc("Yc"), 0.419);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.742", () => {
-            check(sect.Calc("Yn"), 0.742);
+            checkResult(sect.Calc("Yn"), 0.742);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 2", () => {
-            check(sect.Calc("Yf"), 2);
+            checkResult(sect.Calc("Yf"), 2);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.178", () => {
-            check(sect.Calc("Yt"), 0.178);
+            checkResult(sect.Calc("Yt"), 0.178);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.044", () => {
-            check(sect.Calc("Yco"), 0.044);
+            checkResult(sect.Calc("Yco"), 0.044);
         });
 
         // perte de charge
         it("J should equal to 0.00059", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.00059);
+            checkResult(sect.Calc("J"), 0.00059);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.00041", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("I-J"), 0.00041);
+            checkResult(sect.Calc("I-J"), 0.00041);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 59384.242", () => {
-            check(sect.Calc("Imp"), 59384.242);
+            checkResult(sect.Calc("Imp"), 59384.242);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 0.145", () => {
-            check(sect.Calc("Tau0"), 0.145);
+            checkResult(sect.Calc("Tau0"), 0.145);
         });
     });
 });
diff --git a/spec/section_param/section_param_puiss_torrentiel.spec.ts b/spec/section_param/section_param_puiss_torrentiel.spec.ts
index 6cc2be4a7041d2a29a7fe0c835b73838625a9a56..f49ce1bb8318ae2ec0136b543d4992d0c06176da 100644
--- a/spec/section_param/section_param_puiss_torrentiel.spec.ts
+++ b/spec/section_param/section_param_puiss_torrentiel.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnPuiss, ParamsSectionPuiss } from "../../src/section/section_puissance";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionPuiss;
 let sect: cSnPuiss;
@@ -19,10 +19,6 @@ function createSection(prec: number): cSnPuiss {
     return new cSnPuiss(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée puissance :", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -31,89 +27,89 @@ describe("Section paramétrée puissance :", () => {
     describe("torrentiel / pas de débordement :", () => {
         // charge spécifique
         it("Hs should equal to 2.2", () => {
-            check(sect.Calc("Hs"), 2.2);
+            checkResult(sect.Calc("Hs"), 2.2);
         });
 
         // charge critique
         it("Hsc should equal to 1.616", () => {
-            check(sect.Calc("Hsc"), 1.616);
+            checkResult(sect.Calc("Hsc"), 1.616);
         });
 
         // largeur au miroir
         it("B should equal to 3.578", () => {
-            check(sect.Calc("B"), 3.578);
+            checkResult(sect.Calc("B"), 3.578);
         });
 
         // périmètre mouillé
         it("P should equal to 4.223", () => {
-            check(sect.Calc("P"), 4.223);
+            checkResult(sect.Calc("P"), 4.223);
         });
 
         // surface mouillée
         it("S should equal to 1.908", () => {
-            check(sect.Calc("S"), 1.908);
+            checkResult(sect.Calc("S"), 1.908);
         });
 
         // rayon hydraulique
         it("R should equal to 0.452", () => {
-            check(sect.Calc("R"), 0.452);
+            checkResult(sect.Calc("R"), 0.452);
         });
 
         // vitesse moyenne
         it("V should equal to 5.241", () => {
-            check(sect.Calc("V"), 5.241);
+            checkResult(sect.Calc("V"), 5.241);
         });
 
         // nombre de Froude
         it("Fr should equal to 2.291", () => {
-            check(sect.Calc("Fr"), 2.291);
+            checkResult(sect.Calc("Fr"), 2.291);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 1.186", () => {
-            check(sect.Calc("Yc"), 1.186);
+            checkResult(sect.Calc("Yc"), 1.186);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 1.916", () => {
-            check(sect.Calc("Yn"), 1.916);
+            checkResult(sect.Calc("Yn"), 1.916);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 2.126", () => {
-            check(sect.Calc("Yf"), 2.126);
+            checkResult(sect.Calc("Yf"), 2.126);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.8", () => {
-            check(sect.Calc("Yt"), 0.8);
+            checkResult(sect.Calc("Yt"), 0.8);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 1.746", () => {
-            check(sect.Calc("Yco"), 1.746);
+            checkResult(sect.Calc("Yco"), 1.746);
         });
 
         // perte de charge
         it("J should equal to 0.05", () => {
             // sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.05);
+            checkResult(sect.Calc("J"), 0.05);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to -0.049", () => {
             // sect = createSection(0.00001);
-            check(sect.Calc("I-J"), -0.049);
+            checkResult(sect.Calc("I-J"), -0.049);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 58397.786", () => {
-            check(sect.Calc("Imp"), 58397.786);
+            checkResult(sect.Calc("Imp"), 58397.786);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 219.455", () => {
-            check(sect.Calc("Tau0"), 219.455);
+            checkResult(sect.Calc("Tau0"), 219.455);
         });
     });
 });
diff --git a/spec/section_param/section_param_rect_conv_newton.spec.ts b/spec/section_param/section_param_rect_conv_newton.spec.ts
index 5a12b6238a608c6803493d454af86b0108430d39..9a526d05c970acaa7591c70826397b2da4039a49 100644
--- a/spec/section_param/section_param_rect_conv_newton.spec.ts
+++ b/spec/section_param/section_param_rect_conv_newton.spec.ts
@@ -2,15 +2,10 @@
 import { Result } from "../../src/util/result";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
 import { MessageCode } from "../../src/util/message";
-import { equalEpsilon, precDist } from "../nubtest";
 
 let paramSection: ParamsSectionRectang;
 let sect: cSnRectang;
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée rectangulaire : ", () => {
     beforeEach(() => {
         paramSection = new ParamsSectionRectang(0.8, // tirant d'eau
@@ -28,71 +23,88 @@ describe("Section paramétrée rectangulaire : ", () => {
 
     describe("non convergence de la méthode de Newton :", () => {
         it("hauteur critique", () => {
-            sect.Calc("Yc");
-            expect(sect.log.messages.length).toEqual(1);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            const r: Result = sect.Calc("Yc");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
         });
 
         it("hauteur normale", () => {
-            sect.Calc("Yn");
-            expect(sect.log.messages.length).toEqual(2);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE);
+            const r: Result = sect.Calc("Yn");
+            // expect(r.log.messages.length).toEqual(2);
+            expect(r.ok).toBeFalsy("le calcul devrait avoir échoué");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE);
+        });
+
+        it("hauteur normale, pente nulle", () => {
+            sect.prms.If.v = 0;
+            const r: Result = sect.Calc("Yn");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF);
         });
 
         it("hauteur normale, pente négative", () => {
             sect.prms.If.v = -0.001;
-            sect.Calc("Yn");
-            expect(sect.log.messages.length).toEqual(1);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF);
+            const r: Result = sect.Calc("Yn");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF);
         });
 
         it("hauteur fluviale, Y < Yc", () => {
-            sect.Calc("Yf");
-            expect(sect.log.messages.length).toEqual(3);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HFLU);
+            const r: Result = sect.Calc("Yf");
+            // expect(r.log.messages.length).toEqual(3);
+            expect(r.ok).toBeFalsy("le calcul devrait avoir échoué");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HFLU);
         });
 
         it("hauteur fluviale, Y > Yc", () => {
             sect.prms.Y.v = 2;
-            sect.Calc("Yf");
-            expect(sect.log.messages.length).toEqual(1);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            const r: Result = sect.Calc("Yf");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
         });
 
         it("hauteur torrentielle, Y < Yc", () => {
-            sect.Calc("Yt");
-            expect(sect.log.messages.length).toEqual(1);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            const r: Result = sect.Calc("Yt");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
         });
 
         it("hauteur torrentielle, Y > Yc", () => {
             sect.prms.Y.v = 2;
-            sect.Calc("Yt");
-            expect(sect.log.messages.length).toEqual(2);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR);
+            const r: Result = sect.Calc("Yt");
+            //            expect(r.log.messages.length).toEqual(2);
+            expect(r.ok).toBeFalsy("le calcul devrait avoir échoué");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR);
         });
 
         it("hauteur conjuguée, Froude < 1", () => {
             sect.prms.Y.v = 2;
-            sect.Calc("Yco");
-            // console.log(sect.log.toString());
-            expect(sect.log.messages.length).toEqual(3);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR);
-            expect(sect.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
+            const r: Result = sect.Calc("Yco");
+            // console.log(r.log.toString());
+            // expect(r.log.messages.length).toEqual(3);
+            expect(r.ok).toBeFalsy("le calcul devrait avoir échoué");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR);
+            // expect(r.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
         });
 
         it("hauteur conjuguée, Froude > 1", () => {
-            sect.Calc("Yco");
-            expect(sect.log.messages.length).toEqual(4);
-            expect(sect.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-            expect(sect.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HFLU);
-            expect(sect.log.messages[3].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
+            const r: Result = sect.Calc("Yco");
+            // expect(r.log.messages.length).toEqual(4);
+            expect(r.ok).toBeFalsy("le calcul devrait avoir échoué");
+            expect(r.log.messages.length).toEqual(1);
+            expect(r.log.messages[0].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[1].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
+            // expect(r.log.messages[2].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HFLU);
+            // expect(r.log.messages[3].code).toEqual(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
         });
     });
 });
diff --git a/spec/section_param/section_param_rect_fluvial.spec.ts b/spec/section_param/section_param_rect_fluvial.spec.ts
index 8ae7cca92cdc0cdddd1677f45e2f79a7e001b349..d3f318e0a652179da8cd616bbe6904a7f0803e1d 100644
--- a/spec/section_param/section_param_rect_fluvial.spec.ts
+++ b/spec/section_param/section_param_rect_fluvial.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionRectang;
 let sect: cSnRectang;
@@ -31,10 +31,6 @@ function createSectionDebordement(prec: number): cSnRectang {
     return new cSnRectang(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée rectangulaire : ", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -43,89 +39,89 @@ describe("Section paramétrée rectangulaire : ", () => {
     describe("fluvial / pas de débordement :", () => {
         // charge spécifique
         it("Hs should equal to 0.818", () => {
-            check(sect.Calc("Hs"), 0.818);
+            checkResult(sect.Calc("Hs"), 0.818);
         });
 
         // charge critique
         it("Hsc should equal to 0.43", () => {
-            check(sect.Calc("Hsc"), 0.43);
+            checkResult(sect.Calc("Hsc"), 0.43);
         });
 
         // largeur au miroir
         it("B should equal to 2.5", () => {
-            check(sect.Calc("B"), 2.5);
+            checkResult(sect.Calc("B"), 2.5);
         });
 
         // périmètre mouillé
         it("P should equal to 4.1", () => {
-            check(sect.Calc("P"), 4.1);
+            checkResult(sect.Calc("P"), 4.1);
         });
 
         // surface mouillée
         it("S should equal to 2", () => {
-            check(sect.Calc("S"), 2);
+            checkResult(sect.Calc("S"), 2);
         });
 
         // rayon hydraulique
         it("R should equal to 0.488", () => {
-            check(sect.Calc("R"), 0.488);
+            checkResult(sect.Calc("R"), 0.488);
         });
 
         // vitesse moyenne
         it("V should equal to 0.6", () => {
-            check(sect.Calc("V"), 0.6);
+            checkResult(sect.Calc("V"), 0.6);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.214", () => {
-            check(sect.Calc("Fr"), 0.214);
+            checkResult(sect.Calc("Fr"), 0.214);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.286", () => {
-            check(sect.Calc("Yc"), 0.286);
+            checkResult(sect.Calc("Yc"), 0.286);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.663", () => {
-            check(sect.Calc("Yn"), 0.663);
+            checkResult(sect.Calc("Yn"), 0.663);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 0.8", () => {
-            check(sect.Calc("Yf"), 0.8);
+            checkResult(sect.Calc("Yf"), 0.8);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.131", () => {
-            check(sect.Calc("Yt"), 0.131);
+            checkResult(sect.Calc("Yt"), 0.131);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.068", () => {
-            check(sect.Calc("Yco"), 0.068);
+            checkResult(sect.Calc("Yco"), 0.068);
         });
 
         // perte de charge
         it("J should equal to 0.00059", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.00059);
+            checkResult(sect.Calc("J"), 0.00059);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.00041", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("I-J"), 0.00041);
+            checkResult(sect.Calc("I-J"), 0.00041);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 8568", () => {
-            check(sect.Calc("Imp"), 8568);
+            checkResult(sect.Calc("Imp"), 8568);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 2.804", () => {
-            check(sect.Calc("Tau0"), 2.804);
+            checkResult(sect.Calc("Tau0"), 2.804);
         });
     });
 });
@@ -138,89 +134,89 @@ describe("Section paramétrée rectangulaire : ", () => {
     describe("fluvial / débordement :", () => {
         // charge spécifique
         it("Hs should equal to 2.003", () => {
-            check(sect.Calc("Hs"), 2.003);
+            checkResult(sect.Calc("Hs"), 2.003);
         });
 
         // charge critique
         it("Hsc should equal to 0.43", () => {
-            check(sect.Calc("Hsc"), 0.43);
+            checkResult(sect.Calc("Hsc"), 0.43);
         });
 
         // largeur au miroir
         it("B should equal to 2.5", () => {
-            check(sect.Calc("B"), 2.5);
+            checkResult(sect.Calc("B"), 2.5);
         });
 
         // périmètre mouillé
         it("P should equal to 6.5", () => {
-            check(sect.Calc("P"), 6.5);
+            checkResult(sect.Calc("P"), 6.5);
         });
 
         // surface mouillée
         it("S should equal to 5", () => {
-            check(sect.Calc("S"), 5);
+            checkResult(sect.Calc("S"), 5);
         });
 
         // rayon hydraulique
         it("R should equal to 0.769", () => {
-            check(sect.Calc("R"), 0.769);
+            checkResult(sect.Calc("R"), 0.769);
         });
 
         // vitesse moyenne
         it("V should equal to 0.24", () => {
-            check(sect.Calc("V"), 0.24);
+            checkResult(sect.Calc("V"), 0.24);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.0542", () => {
-            check(sect.Calc("Fr"), 0.0542);
+            checkResult(sect.Calc("Fr"), 0.0542);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.286", () => {
-            check(sect.Calc("Yc"), 0.286);
+            checkResult(sect.Calc("Yc"), 0.286);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.663", () => {
-            check(sect.Calc("Yn"), 0.663);
+            checkResult(sect.Calc("Yn"), 0.663);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 2", () => {
-            check(sect.Calc("Yf"), 2);
+            checkResult(sect.Calc("Yf"), 2);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.078", () => {
-            check(sect.Calc("Yt"), 0.078);
+            checkResult(sect.Calc("Yt"), 0.078);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.012", () => {
-            check(sect.Calc("Yco"), 0.012);
+            checkResult(sect.Calc("Yco"), 0.012);
         });
 
         // perte de charge
         it("J should equal to 0.00059", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.00059);
+            checkResult(sect.Calc("J"), 0.00059);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.0009", () => {
             sect = createSection(0.00001);
-            check(sect.Calc("I-J"), 0.0009);
+            checkResult(sect.Calc("I-J"), 0.0009);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 49338", () => {
-            check(sect.Calc("Imp"), 49338);
+            checkResult(sect.Calc("Imp"), 49338);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 0.385", () => {
-            check(sect.Calc("Tau0"), 0.385);
+            checkResult(sect.Calc("Tau0"), 0.385);
         });
     });
 });
diff --git a/spec/section_param/section_param_rect_torrentiel.spec.ts b/spec/section_param/section_param_rect_torrentiel.spec.ts
index a5e7e374339f26e939bc788b1869d76dcbe974f1..caed1035417dbf3eb2c8e1f275db407fc32a936b 100644
--- a/spec/section_param/section_param_rect_torrentiel.spec.ts
+++ b/spec/section_param/section_param_rect_torrentiel.spec.ts
@@ -1,14 +1,10 @@
-import { Result } from "../../src/util/result";
 import { cSnRectang, ParamsSectionRectang } from "../../src/section/section_rectang";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionRectang;
 let sect: cSnRectang;
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée rectangulaire : ", () => {
     beforeEach(() => {
         paramSection = new ParamsSectionRectang(0.8, // tirant d'eau
@@ -26,89 +22,89 @@ describe("Section paramétrée rectangulaire : ", () => {
     describe("torrentiel :", () => {
         // charge spécifique
         it("Hs should equal to 2.074", () => {
-            check(sect.Calc("Hs"), 2.074);
+            checkResult(sect.Calc("Hs"), 2.074);
         });
 
         // charge critique
         it("Hsc should equal to 1.766", () => {
-            check(sect.Calc("Hsc"), 1.766);
+            checkResult(sect.Calc("Hsc"), 1.766);
         });
 
         // largeur au miroir
         it("B should equal to 2.5", () => {
-            check(sect.Calc("B"), 2.5);
+            checkResult(sect.Calc("B"), 2.5);
         });
 
         // périmètre mouillé
         it("P should equal to 4.1", () => {
-            check(sect.Calc("P"), 4.1);
+            checkResult(sect.Calc("P"), 4.1);
         });
 
         // surface mouillée
         it("S should equal to 2", () => {
-            check(sect.Calc("S"), 2);
+            checkResult(sect.Calc("S"), 2);
         });
 
         // rayon hydraulique
         it("R should equal to 0.488", () => {
-            check(sect.Calc("R"), 0.488);
+            checkResult(sect.Calc("R"), 0.488);
         });
 
         // vitesse moyenne
         it("V should equal to 5", () => {
-            check(sect.Calc("V"), 5);
+            checkResult(sect.Calc("V"), 5);
         });
 
         // nombre de Froude
         it("Fr should equal to 1.785", () => {
-            check(sect.Calc("Fr"), 1.785);
+            checkResult(sect.Calc("Fr"), 1.785);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 1.177", () => {
-            check(sect.Calc("Yc"), 1.177);
+            checkResult(sect.Calc("Yc"), 1.177);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 3.364", () => {
-            check(sect.Calc("Yn"), 3.364);
+            checkResult(sect.Calc("Yn"), 3.364);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 1.831", () => {
-            check(sect.Calc("Yf"), 1.831);
+            checkResult(sect.Calc("Yf"), 1.831);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.8", () => {
-            check(sect.Calc("Yt"), 0.8);
+            checkResult(sect.Calc("Yt"), 0.8);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 1.659", () => {
-            check(sect.Calc("Yco"), 1.659);
+            checkResult(sect.Calc("Yco"), 1.659);
         });
 
         // perte de charge
         it("J should equal to 0.041", () => {
             // paramCnl.v.Prec = 0.00001;
-            check(sect.Calc("J"), 0.041);
+            checkResult(sect.Calc("J"), 0.041);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to -0.04", () => {
             // paramCnl.v.Prec = 0.00001;
-            check(sect.Calc("I-J"), -0.04);
+            checkResult(sect.Calc("I-J"), -0.04);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 57848", () => {
-            check(sect.Calc("Imp"), 57848);
+            checkResult(sect.Calc("Imp"), 57848);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 194.718", () => {
-            check(sect.Calc("Tau0"), 194.718);
+            checkResult(sect.Calc("Tau0"), 194.718);
         });
     });
 });
diff --git a/spec/section_param/section_param_trapez_fluvial.spec.ts b/spec/section_param/section_param_trapez_fluvial.spec.ts
index f2095057df8ce5a062b30602b27789004ce266a0..6d3a35f72b6a155ce0c852abd930d07923b5861b 100644
--- a/spec/section_param/section_param_trapez_fluvial.spec.ts
+++ b/spec/section_param/section_param_trapez_fluvial.spec.ts
@@ -1,6 +1,6 @@
-import { Result } from "../../src/util/result";
 import { cSnTrapez, ParamsSectionTrapez } from "../../src/section/section_trapez";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramSection: ParamsSectionTrapez;
 let sect: cSnTrapez;
@@ -33,10 +33,6 @@ function createSectionDebordement(prec: number): cSnTrapez {
     return new cSnTrapez(paramSection);
 }
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée trapèze : ", () => {
     beforeEach(() => {
         sect = createSection(precDist);
@@ -45,88 +41,88 @@ describe("Section paramétrée trapèze : ", () => {
     describe("fluvial / pas de débordement :", () => {
         // charge spécifique
         it("Hs should equal to 0.813", () => {
-            check(sect.Calc("Hs"), 0.813);
+            checkResult(sect.Calc("Hs"), 0.813);
         });
 
         // charge critique
         it("Hsc should equal to 0.413", () => {
-            check(sect.Calc("Hsc"), 0.413);
+            checkResult(sect.Calc("Hsc"), 0.413);
         });
 
         // largeur au miroir
         it("B should equal to 3.396", () => {
-            check(sect.Calc("B"), 3.396);
+            checkResult(sect.Calc("B"), 3.396);
         });
 
         // périmètre mouillé
         it("P should equal to 4.334", () => {
-            check(sect.Calc("P"), 4.334);
+            checkResult(sect.Calc("P"), 4.334);
         });
 
         // surface mouillée
         it("S should equal to 2.358", () => {
-            check(sect.Calc("S"), 2.358);
+            checkResult(sect.Calc("S"), 2.358);
         });
 
         // rayon hydraulique
         it("R should equal to 0.544", () => {
-            check(sect.Calc("R"), 0.544);
+            checkResult(sect.Calc("R"), 0.544);
         });
 
         // vitesse moyenne
         it("V should equal to 0.509", () => {
-            check(sect.Calc("V"), 0.509);
+            checkResult(sect.Calc("V"), 0.509);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.195", () => {
-            check(sect.Calc("Fr"), 0.195);
+            checkResult(sect.Calc("Fr"), 0.195);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.28", () => {
-            check(sect.Calc("Yc"), 0.28);
+            checkResult(sect.Calc("Yc"), 0.28);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.587", () => {
-            check(sect.Calc("Yn"), 0.587);
+            checkResult(sect.Calc("Yn"), 0.587);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 0.8", () => {
-            check(sect.Calc("Yf"), 0.8);
+            checkResult(sect.Calc("Yf"), 0.8);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.127", () => {
-            check(sect.Calc("Yt"), 0.127);
+            checkResult(sect.Calc("Yt"), 0.127);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.061", () => {
-            check(sect.Calc("Yco"), 0.061);
+            checkResult(sect.Calc("Yco"), 0.061);
         });
 
         // perte de charge
         it("J should equal to 0.00036", () => {
             let sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.00036);
+            checkResult(sect.Calc("J"), 0.00036);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.001", () => {
-            check(sect.Calc("I-J"), 0.001);
+            checkResult(sect.Calc("I-J"), 0.001);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 9396.158", () => {
-            check(sect.Calc("Imp"), 9396.158);
+            checkResult(sect.Calc("Imp"), 9396.158);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 1.944", () => {
-            check(sect.Calc("Tau0"), 1.944);
+            checkResult(sect.Calc("Tau0"), 1.944);
         });
     });
 });
@@ -140,88 +136,88 @@ describe("Section paramétrée trapèze : ", () => {
     describe("fluvial / débordement :", () => {
         // charge spécifique
         it("Hs should equal to 2.002", () => {
-            check(sect.Calc("Hs"), 2.002);
+            checkResult(sect.Calc("Hs"), 2.002);
         });
 
         // charge critique
         it("Hsc should equal to 0.413", () => {
-            check(sect.Calc("Hsc"), 0.413);
+            checkResult(sect.Calc("Hsc"), 0.413);
         });
 
         // largeur au miroir
         it("B should equal to 3.62", () => {
-            check(sect.Calc("B"), 3.62);
+            checkResult(sect.Calc("B"), 3.62);
         });
 
         // périmètre mouillé
         it("P should equal to 6.792", () => {
-            check(sect.Calc("P"), 6.792);
+            checkResult(sect.Calc("P"), 6.792);
         });
 
         // surface mouillée
         it("S should equal to 6.68", () => {
-            check(sect.Calc("S"), 6.68);
+            checkResult(sect.Calc("S"), 6.68);
         });
 
         // rayon hydraulique
         it("R should equal to 0.983", () => {
-            check(sect.Calc("R"), 0.983);
+            checkResult(sect.Calc("R"), 0.983);
         });
 
         // vitesse moyenne
         it("V should equal to 0.18", () => {
-            check(sect.Calc("V"), 0.18);
+            checkResult(sect.Calc("V"), 0.18);
         });
 
         // nombre de Froude
         it("Fr should equal to 0.042", () => {
-            check(sect.Calc("Fr"), 0.042);
+            checkResult(sect.Calc("Fr"), 0.042);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 0.28", () => {
-            check(sect.Calc("Yc"), 0.28);
+            checkResult(sect.Calc("Yc"), 0.28);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 0.587", () => {
-            check(sect.Calc("Yn"), 0.587);
+            checkResult(sect.Calc("Yn"), 0.587);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 2", () => {
-            check(sect.Calc("Yf"), 2);
+            checkResult(sect.Calc("Yf"), 2);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.077", () => {
-            check(sect.Calc("Yt"), 0.077);
+            checkResult(sect.Calc("Yt"), 0.077);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 0.009", () => {
-            check(sect.Calc("Yco"), 0.009);
+            checkResult(sect.Calc("Yco"), 0.009);
         });
 
         // perte de charge
         it("J should equal to 0.00002", () => {
             let sect = createSection(0.00001);
-            check(sect.Calc("J"), 0.00002);
+            checkResult(sect.Calc("J"), 0.00002);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to 0.001", () => {
-            check(sect.Calc("I-J"), 0.001);
+            checkResult(sect.Calc("I-J"), 0.001);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 63915.169", () => {
-            check(sect.Calc("Imp"), 63915.169);
+            checkResult(sect.Calc("Imp"), 63915.169);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 0.199", () => {
-            check(sect.Calc("Tau0"), 0.199);
+            checkResult(sect.Calc("Tau0"), 0.199);
         });
     });
 });
diff --git a/spec/section_param/section_param_trapez_torrentiel.spec.ts b/spec/section_param/section_param_trapez_torrentiel.spec.ts
index 2b03327234fb8c9ba651cca021b7a495d069494f..a0e8c4ceba5f7608ee3128d36019c5114ebddc44 100644
--- a/spec/section_param/section_param_trapez_torrentiel.spec.ts
+++ b/spec/section_param/section_param_trapez_torrentiel.spec.ts
@@ -1,14 +1,10 @@
-import { Result } from "../../src/util/result";
 import { cSnTrapez, ParamsSectionTrapez } from "../../src/section/section_trapez";
-import { equalEpsilon, precDist } from "../nubtest";
+import { precDist } from "../test_config";
+import { checkResult } from "../test_func";
 
 let paramCnl: ParamsSectionTrapez;
 let sect: cSnTrapez;
 
-function check(val1: number, val2: number) {
-    expect(equalEpsilon(val1, val2)).toBeTruthy("expected " + val2 + ", got " + val1);
-}
-
 describe("Section paramétrée trapèze :", () => {
     beforeEach(() => {
         paramCnl = new ParamsSectionTrapez(2.5, // largeur de fond
@@ -27,88 +23,88 @@ describe("Section paramétrée trapèze :", () => {
     describe("torrentiel :", () => {
         // charge spécifique
         it("Hs should equal to 1.716", () => {
-            check(sect.Calc("Hs"), 1.716);
+            checkResult(sect.Calc("Hs"), 1.716);
         });
 
         // charge critique
         it("Hsc should equal to 1.534", () => {
-            check(sect.Calc("Hsc"), 1.534);
+            checkResult(sect.Calc("Hsc"), 1.534);
         });
 
         // largeur au miroir
         it("B should equal to 3.396", () => {
-            check(sect.Calc("B"), 3.396);
+            checkResult(sect.Calc("B"), 3.396);
         });
 
         // périmètre mouillé
         it("P should equal to 4.334", () => {
-            check(sect.Calc("P"), 4.334);
+            checkResult(sect.Calc("P"), 4.334);
         });
 
         // surface mouillée
         it("S should equal to 2.358", () => {
-            check(sect.Calc("S"), 2.358);
+            checkResult(sect.Calc("S"), 2.358);
         });
 
         // rayon hydraulique
         it("R should equal to 0.544", () => {
-            check(sect.Calc("R"), 0.544);
+            checkResult(sect.Calc("R"), 0.544);
         });
 
         // vitesse moyenne
         it("V should equal to 4.24", () => {
-            check(sect.Calc("V"), 4.24);
+            checkResult(sect.Calc("V"), 4.24);
         });
 
         // nombre de Froude
         it("Fr should equal to 1.625", () => {
-            check(sect.Calc("Fr"), 1.625);
+            checkResult(sect.Calc("Fr"), 1.625);
         });
 
         // tirant d'eau critique
         it("Yc should equal to 1.074", () => {
-            check(sect.Calc("Yc"), 1.074);
+            checkResult(sect.Calc("Yc"), 1.074);
         });
 
         // tirant d'eau normal
         it("Yn should equal to 2.275", () => {
-            check(sect.Calc("Yn"), 2.275);
+            checkResult(sect.Calc("Yn"), 2.275);
         });
 
         // tirant d'eau fluvial
         it("Yf should equal to 1.502", () => {
-            check(sect.Calc("Yf"), 1.502);
+            checkResult(sect.Calc("Yf"), 1.502);
         });
 
         // tirant d'eau torrentiel
         it("Yt should equal to 0.8", () => {
-            check(sect.Calc("Yt"), 0.8);
+            checkResult(sect.Calc("Yt"), 0.8);
         });
 
         // tirant d'eau conjugué
         it("Yco should equal to 1.398", () => {
-            check(sect.Calc("Yco"), 1.398);
+            checkResult(sect.Calc("Yco"), 1.398);
         });
 
         // perte de charge
         it("J should equal to 0.025", () => {
             // paramCnl.v.Prec = 0.00001;
-            check(sect.Calc("J"), 0.025);
+            checkResult(sect.Calc("J"), 0.025);
         });
 
         // Variation linéaire de l'énergie spécifique
         it("I-J should equal to -0.024", () => {
-            check(sect.Calc("I-J"), -0.024);
+            checkResult(sect.Calc("I-J"), -0.024);
         });
 
         // impulsion hydraulique
         it("Imp should equal to 51187.203", () => {
-            check(sect.Calc("Imp"), 51187.203);
+            checkResult(sect.Calc("Imp"), 51187.203);
         });
 
         // force tractrice (contrainte de cisaillement)
         it("Tau0 should equal to 135.020", () => {
-            check(sect.Calc("Tau0"), 135.020);
+            checkResult(sect.Calc("Tau0"), 135.020);
         });
     });
 });
diff --git a/spec/structure/parallel_structure.spec.ts b/spec/structure/parallel_structure.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4efe1a4e7b52e9cc5825cd95fc619f76d85635f6
--- /dev/null
+++ b/spec/structure/parallel_structure.spec.ts
@@ -0,0 +1,93 @@
+/**
+ * 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 { ParamCalculability, ParamDefinition, ParamsEquation } from "../../src/param";
+import { CreateStructure, StructureType } from "../../src/structure/factory_structure";
+import { ParallelStructure } from "../../src/structure/parallel_structure";
+import { ParallelStructureParams } from "../../src/structure/parallel_structure_params";
+import { Structure } from "../../src/structure/structure";
+import { Describer } from "../../src/util/describer";
+import { EnumEx } from "../../src/util/enum";
+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
+);
+
+/*
+ * Tests 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);
+    });
+});
+
+/**
+ * Test sur ParallelStructure
+ * @param sVarCalc Variable à calculer
+ * @param rVcalc Valeur de référence à retrouver
+ * @param Q Débit de chacune des structures (pour structures identiques uniquement)
+ */
+function itParallelStructure(sVarCalc: string, rVcalc: number, Q?: number) {
+    it(`${sVarCalc} should be ${rVcalc}`, () => {
+        const res: Result = pstruct.Calc(sVarCalc);
+        checkResult(res, rVcalc);
+        if (Q !== undefined) {
+            for (let i = 1 ; i < res.nbResults ; i++) {
+                checkResult(res.extractResult(i), Q);
+            }
+        }
+    });
+}
+
+/*
+ * Tests avec toutes les équations et toutes les variables (cf. jalhyd#38)
+ */
+
+const ps2: ParallelStructure = new ParallelStructure(
+    new ParallelStructureParams(0, 102, 101.5), // Q = 0, Z1 = 102, Z2 = 101.5
+    false // debug
+);
+
+// Ajout d'une structure de chaque type dans ParallelStructure
+for (const i of EnumEx.getValues(StructureType)) {
+    ps2.addStructure(CreateStructure(i));
+}
+
+ps2.prms.Q.v = ps2.Calc("Q").vCalc;
+
+// tslint:disable-next-line:prefer-for-of
+describe("Class ParallelStructure: ", () => {
+    for (let i = 0 ; i < ps2.structures.length ; i++) {
+        const st: Structure = ps2.structures[i];
+        describe(`this.structures[${i}]: Structure${StructureType[i]}: `, () => {
+            // tslint:disable-next-line:forin
+            for (const prm of st.prms) {
+                if (prm.calculability === ParamCalculability.DICHO &&
+                    prm.symbol !== "Z1" && prm.symbol !== "Z2") {
+                    const ref: number = prm.v;
+                    const res: Result = ps2.Calc(i + "." + prm.symbol);
+                    prm.v = ref; // Go back to initial value for following tests
+                    it(`Calc(${prm.symbol}) should return ${ref}`, () => {
+                        checkResult(res, ref);
+                    });
+                }
+            }
+        });
+    }
+});
diff --git a/spec/structure/rectangular_structure.ts b/spec/structure/rectangular_structure.ts
index deee528562ccb15569b504fa57592847b9813da4..8895e09c1200f0101ebfbb1b63e4633494615069 100644
--- a/spec/structure/rectangular_structure.ts
+++ b/spec/structure/rectangular_structure.ts
@@ -1,50 +1,39 @@
-// 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.
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructure } from "../../src/structure/rectangular_structure";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
-import { precDigits } from "../nubtest";
-
-/**
- * Récupération du nom de la classe
- * https://www.stevefenton.co.uk/2013/04/Obtaining-A-Class-Name-At-Runtime-In-TypeScript/
- */
-export class Describer {
-    /**
-     * Récupère le nom de la classe d'un objet
-     * @param inputClass Objet à tester
-     */
-    public static getName(inputClass: any) {
-        const funcNameRegex = /function (.{1,})\(/;
-        const results = (funcNameRegex).exec((inputClass as any).constructor.toString());
-        return (results && results.length > 1) ? results[1] : "";
-    }
-}
+import { Describer } from "../../src/util/describer";
+import { Result } from "../../src/util/result";
+import { precDigits } from "../test_config";
 
 export function itCalcQ(
-    struct: RectangularStructure, h1: number, W: number, Q: number,
+    struct: RectangularStructure, Z1: number, W: number, Q: number,
     mode?: StructureFlowMode, regime?: StructureFlowRegime) {
 
-    struct.debug("itCalQ " + Describer.getName(struct) + " h1=" + h1 + " W=" + W + " Q=" + Q);
+    struct.debug("itCalQ " + Describer.getName(struct) + " Z1=" + Z1 + " W=" + W + " Q=" + Q);
 
-    struct.prms.h1.v = h1;
+    struct.prms.Z1.v = Z1;
     struct.prms.W.v = W;
     const res: Result = struct.Calc("Q");
     struct.debug("struct.Calc(Q)=" + res.vCalc);
 
-    it("Q(h1=" + h1 + ",W=" + W + ") should be " + Q, () => {
+    it("Q(Z1=" + Z1 + ",W=" + W + ") should be " + Q, () => {
         struct.debug("struct.Calc(Q)=" + res.vCalc);
         expect(res.vCalc).toBeCloseTo(Q, precDigits);
     });
     if (mode !== undefined) {
-        it("Q(h1=" + h1 + ",W=" + W + ") Mode should be " + mode, () => {
-            expect(res.extraVar.Mode).toBe(mode);
-       });
+        it("Q(Z1=" + Z1 + ",W=" + W + ") Mode should be " + mode, () => {
+            expect(res.extraResults.Mode).toBe(mode);
+        });
     }
     if (regime !== undefined) {
-        it("Q(h1=" + h1 + ",W=" + W + ") Regime should be " + regime, () => {
-            expect(res.extraVar.Regime).toBe(regime);
+        it("Q(Z1=" + Z1 + ",W=" + W + ") Regime should be " + regime, () => {
+            expect(res.extraResults.Regime).toBe(regime);
         });
     }
 }
diff --git a/spec/structure/structure.spec.ts b/spec/structure/structure.spec.ts
index 575f95863f8dafa798a91e82e49b7463bf9a9c16..f1c23d0a8339db96b1e55bcffe6c0f9ee313de5e 100644
--- a/spec/structure/structure.spec.ts
+++ b/spec/structure/structure.spec.ts
@@ -1,50 +1,14 @@
-// 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 { Structure, StructureFlowMode, StructureFlowRegime, StructureParams } from "../../src/structure/structure";
-import { equalEpsilon } from "../nubtest";
-
-function check(val1: Result, val2: number) {
-    expect(equalEpsilon(val1.vCalc, val2)).toBe(true);
-}
-
-class StructureTest extends Structure {
-
-    constructor(prms: StructureParams, dbg: boolean = false) {
-        super(prms, dbg);
-    }
-
-    /**
-     * Test of getFlowMode
-     */
-    public testGetFlowMode() {
-        return this.getFlowMode();
-    }
-
-    /**
-     * Test of getFlowRegime
-     */
-    public testGetFlowRegime() {
-        return this.getFlowRegime();
-    }
-
-    public Equation(sVarCalc: string): Result {
-        let v: number;
-        switch (sVarCalc) {
-            case "Q":
-                v = this.prms.h1.v - this.prms.h2.v;
-                break;
-            default:
-                throw new Error("StructureTest.Equation() : invalid parameter name " + sVarCalc);
-        }
-        return new Result(v);
-    }
-
-}
-
-const structTestPrm: StructureParams = new StructureParams(1, 30, 15);
-const structTest: StructureTest = new StructureTest(structTestPrm, false);
+import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
+import { checkResult } from "../test_func";
+import { structTest } from "./structure_test";
 
 describe("Class Structure: ", () => {
 
@@ -64,47 +28,47 @@ describe("Class Structure: ", () => {
             expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.FREE);
         });
         it("Flow Regime should be SUBMERGED (WEIR)", () => {
-            structTest.prms.h2.v = 21;
+            structTest.prms.Z2.v = 21;
             expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.SUBMERGED);
         });
         it("Flow Regime should be PARTIAL (ORIFICE)", () => {
-            structTest.prms.h2.v = 21;
+            structTest.prms.Z2.v = 21;
             structTest.prms.W.v = 15;
             expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.PARTIAL);
         });
         it("Flow Regime should be SUBMERGED (ORIFICE)", () => {
-            structTest.prms.h2.v = 25;
+            structTest.prms.Z2.v = 25;
             structTest.prms.W.v = 15;
             expect(structTest.testGetFlowRegime()).toBe(StructureFlowRegime.SUBMERGED);
         });
-        structTest.prms.h2.v = 15;
+        structTest.prms.Z2.v = 15;
         structTest.prms.W.v = Infinity;
     });
 
     describe("Calc()", () => {
-        const flagsNull = {Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL};
-        it("h1=h2 => Q=0", () => {
-            structTest.prms.h2.v = structTest.prms.h1.v;
-            check(structTest.Calc("Q"), 0);
-            expect(structTest.Calc("Q").extraVar).toEqual(flagsNull);
-            structTest.prms.h2.v = 15;
+        const flagsNull = { Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL };
+        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);
+            structTest.prms.Z2.v = 15;
         });
         it("W=0 => Q=0", () => {
             structTest.prms.W.v = 0;
-            check(structTest.Calc("Q"), 0);
-            expect(structTest.Calc("Q").extraVar).toEqual(flagsNull);
+            checkResult(structTest.Calc("Q"), 0);
+            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;
-            check(structTest.Calc("h1"), structTest.prms.h2.v);
-            expect(structTest.Calc("h1").extraVar).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", () => {
             structTest.prms.Q.v = 0;
-            check(structTest.Calc("W"), 0);
-            expect(structTest.Calc("W").extraVar).toEqual(flagsNull);
+            checkResult(structTest.Calc("W"), 0);
+            expect(structTest.Calc("W").extraResults).toEqual(flagsNull);
             structTest.prms.Q.v = 1;
         });
         // TODO Test inversion de débit
diff --git a/spec/structure/structure_cem88d.spec.ts b/spec/structure/structure_cem88d.spec.ts
index bae6c610ac9b8b9234bab8f31a0f8b22f61e1229..42521b8d504b04cc5149adef88d7e86e4e575de7 100644
--- a/spec/structure/structure_cem88d.spec.ts
+++ b/spec/structure/structure_cem88d.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureCem88d } from "../../src/structure/structure_cem88d";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureCem88d = new StructureCem88d(structPrm, false);
 
 describe("Class StructureCem88d: ", () => {
@@ -19,7 +24,7 @@ describe("Class StructureCem88d: ", () => {
         const Q: number[] = [0.000000, 0.617586, 1.235173, 1.852759, 2.470345, 3.087931,
             3.705518, 4.296608, 4.831177, 5.302464, 5.700445, 6.007777, 6.175863, 6.175863];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -32,7 +37,7 @@ describe("Class StructureCem88d: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.PARTIAL, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -45,7 +50,7 @@ describe("Class StructureCem88d: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
diff --git a/spec/structure/structure_cem88v.spec.ts b/spec/structure/structure_cem88v.spec.ts
index 0ab80754a6f4085eea91813080934d6b857665ee..fe40920cfa0a6637ecb83faf2ac32e0946b5e277 100644
--- a/spec/structure/structure_cem88v.spec.ts
+++ b/spec/structure/structure_cem88v.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureCem88v } from "../../src/structure/structure_cem88v";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureCem88v = new StructureCem88v(structPrm, false);
 
 describe("Class StructureCem88v: ", () => {
@@ -18,7 +23,7 @@ describe("Class StructureCem88v: ", () => {
         const Q: number[] = [.000000, 0.328260, 0.641822, 0.823867, 1.117381, 1.720738,
             2.225472, 2.575336, 2.873893, 3.113250, 3.280545, 3.349403, 3.149324, 3.149324];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -31,7 +36,7 @@ describe("Class StructureCem88v: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.PARTIAL, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -44,7 +49,7 @@ describe("Class StructureCem88v: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
diff --git a/spec/structure/structure_cunge80.spec.ts b/spec/structure/structure_cunge80.spec.ts
index 8e4bc0324455f3819d7c5a2676b1d86e945705a2..0940fce515add3c730bd89b412ca0485aae88bf6 100644
--- a/spec/structure/structure_cunge80.spec.ts
+++ b/spec/structure/structure_cunge80.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureCunge80 } from "../../src/structure/structure_cunge80";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureCunge80 = new StructureCunge80(structPrm, false);
 
 describe("Class StructureCunge80: ", () => {
@@ -19,7 +24,7 @@ describe("Class StructureCunge80: ", () => {
         const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545,
             1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.377091, 2.377091, 2.377091];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -32,7 +37,7 @@ describe("Class StructureCunge80: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -45,7 +50,7 @@ describe("Class StructureCunge80: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
diff --git a/spec/structure/structure_orifice_free.spec.ts b/spec/structure/structure_orifice_free.spec.ts
index 44e1a7c3cefdb0aae57af592417e42a2d3e348a8..0cefcda138e7e9ce69e938888858c6b059b26fae 100644
--- a/spec/structure/structure_orifice_free.spec.ts
+++ b/spec/structure/structure_orifice_free.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureOrificeFree } from "../../src/structure/structure_orifice_free";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureOrificeFree = new StructureOrificeFree(structPrm, false);
 
 describe("Class StructureOrificeFree: ", () => {
@@ -19,7 +24,7 @@ describe("Class StructureOrificeFree: ", () => {
         const Q: number[] = [0.000000, 0.582266, 1.164532, 1.746798, 2.329064, 2.911330,
             3.493596, 4.075861, 4.658127, 5.240393, 5.822659, 6.404925, 6.987191, 6.987191];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -32,7 +37,7 @@ describe("Class StructureOrificeFree: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.FREE, StructureFlowRegime.FREE, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -45,7 +50,7 @@ describe("Class StructureOrificeFree: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.FREE, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
diff --git a/spec/structure/structure_orifice_submerged.spec.ts b/spec/structure/structure_orifice_submerged.spec.ts
index bf4cd9e8a5e710e013fc69cf1356701eac7b4107..37537f16f9708a8d3739e40e4f2fd984d5fd48b9 100644
--- a/spec/structure/structure_orifice_submerged.spec.ts
+++ b/spec/structure/structure_orifice_submerged.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureOrificeSubmerged } from "../../src/structure/structure_orifice_submerged";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureOrificeSubmerged = new StructureOrificeSubmerged(structPrm, false);
 
 describe("Class StructureOrificeSubmerged: ", () => {
@@ -19,7 +24,7 @@ describe("Class StructureOrificeSubmerged: ", () => {
         const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545,
             1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.614800, 2.852509, 2.852509];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -32,7 +37,7 @@ describe("Class StructureOrificeSubmerged: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -45,7 +50,7 @@ describe("Class StructureOrificeSubmerged: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
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/spec/structure/structure_weir_free.spec.ts b/spec/structure/structure_weir_free.spec.ts
index 1aa66d3a3dd4a6fc2efc17c93c2281d2474ae889..6b04ce6a65737f30b8e687bbeb1aba08ba68f4be 100644
--- a/spec/structure/structure_weir_free.spec.ts
+++ b/spec/structure/structure_weir_free.spec.ts
@@ -1,13 +1,18 @@
-// 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 rectangular_structure.ts
+ */
+// import { describe, expect, it, xdescribe } from "../mock_jasmine";
 
-import { Result } from "../../src/util/result";
 import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
 import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
 import { StructureWeirFree } from "../../src/structure/structure_weir_free";
+import { Result } from "../../src/util/result";
 import { itCalcQ } from "./rectangular_structure";
 
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
+const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 0, 1, 1, 2, 0.6, 0);
 const structTest: StructureWeirFree = new StructureWeirFree(structPrm, false);
 
 describe("Class StructureWeirFree: ", () => {
@@ -19,7 +24,7 @@ describe("Class StructureWeirFree: ", () => {
         const Q: number[] = [0.000000, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191,
             6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191, 6.987191];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1, W[i], Q[i]);
         }
     });
@@ -32,7 +37,7 @@ describe("Class StructureWeirFree: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.FREE, StructureFlowRegime.FREE, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
@@ -45,7 +50,7 @@ describe("Class StructureWeirFree: ", () => {
         const regime: StructureFlowRegime[] = [
             StructureFlowRegime.FREE, StructureFlowRegime.FREE];
 
-        for (let i = 0; i < Q.length; i++ ) {
+        for (let i = 0; i < Q.length; i++) {
             itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
         }
     });
diff --git a/spec/structure/test_rectangular_structure.ts b/spec/structure/test_rectangular_structure.ts
deleted file mode 100644
index 118442634104b6ebc154721d692be1205d3b56fd..0000000000000000000000000000000000000000
--- a/spec/structure/test_rectangular_structure.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Result } from "../../src/util/result";
-import { RectangularStructure } from "../../src/structure/rectangular_structure";
-import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
-import { expect, it } from "../mock_jasmine";
-import { precDigits } from "../nubtest";
-import { Describer } from "./rectangular_structure";
-
-export function itCalcQ(
-    struct: RectangularStructure, h1: number, W: number, Q: number,
-    mode?: StructureFlowMode, regime?: StructureFlowRegime) {
-
-    struct.debug("itCalQ " + Describer.getName(struct) + " h1=" + h1 + " W=" + W + " Q=" + Q);
-
-    struct.prms.h1.v = h1;
-    struct.prms.W.v = W;
-    const res: Result = struct.Calc("Q");
-    struct.debug("struct.Calc(Q)=" + res.vCalc);
-
-    it("Q(h1=" + h1 + ",W=" + W + ") should be " + Q, () => {
-        struct.debug("struct.Calc(Q)=" + res.vCalc);
-        expect(res.vCalc).toBeCloseTo(Q, precDigits);
-    });
-    if (mode !== undefined) {
-        it("Q(h1=" + h1 + ",W=" + W + ") Mode should be " + mode, () => {
-            expect(res.extraVar.Mode).toBe(mode);
-       });
-    }
-    if (regime !== undefined) {
-        it("Q(h1=" + h1 + ",W=" + W + ") Regime should be " + regime, () => {
-            expect(res.extraVar.Regime).toBe(regime);
-        });
-    }
-}
diff --git a/spec/structure/test_structure_cem88d.ts b/spec/structure/test_structure_cem88d.ts
deleted file mode 100644
index 0e00540709e76a6062e40cf4f27fdb8d2b78439c..0000000000000000000000000000000000000000
--- a/spec/structure/test_structure_cem88d.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Result } from "../../src/util/result";
-import { RectangularStructureParams, StructureCem88d } from "../../src/structure/structure_cem88d";
-import { describe, xdescribe } from "../mock_jasmine";
-import { precDigits } from "../nubtest";
-import { itCalcQ } from "./test_rectangular_structure";
-
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
-const structTest: StructureCem88d = new StructureCem88d(structPrm, true);
-
-describe("Class StructureCem88d: ", () => {
-
-    describe("Calcul Q avec W croissant: ", () => {
-        const W: number[] = [0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000,
-            0.600000, 0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000];
-        const h1: number = 1.200000;
-        const Q: number[] = [0.000000, 0.617586, 1.235173, 1.852759, 2.470345, 3.087931, 3.705518,
-            4.296608, 4.831177, 5.302464, 5.700445, 6.007777, 6.175863, 6.175863];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1, W[i], Q[i]);
-        }
-    });
-    describe("Calcul Q en charge avec h1 croissant: ", () => {
-        const W: number = 0.8;
-        const h1: number[] = [1.050000, 1.300000, 1.500000];
-        const Q: number[] = [2.470345, 5.684601, 6.651906];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i]);
-        }
-    });
-    describe("Calcul Q a surface libre avec h1 croissant: ", () => {
-        const W: number = Infinity;
-        const h1: number[] = [1.100000, 1.500000];
-        const Q: number[] = [4.366994, 9.764896];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i]);
-        }
-    });
-});
diff --git a/spec/structure/test_structure_cem88v.ts b/spec/structure/test_structure_cem88v.ts
deleted file mode 100644
index c1be649b6d7927e23fca0d4cec6d1b0cfab11728..0000000000000000000000000000000000000000
--- a/spec/structure/test_structure_cem88v.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Result } from "../../src/util/result";
-import { RectangularStructureParams, StructureCem88v } from "../../src/structure/structure_cem88v";
-import { describe, xdescribe } from "../mock_jasmine";
-import { precDigits } from "../nubtest";
-import { itCalcQ } from "./test_rectangular_structure";
-
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
-const structTest: StructureCem88v = new StructureCem88v(structPrm, true);
-
-describe("Class StructureCem88v: ", () => {
-    describe("Calcul Q avec W croissant: ", () => {
-        const W: number[] = [0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000,
-            0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000];
-        const h1: number = 1.200000;
-        const Q: number[] = [.000000, 0.328260, 0.641822, 0.823867, 1.117381, 1.720738,
-            2.225472, 2.575336, 2.873893, 3.113250, 3.280545, 3.349403, 3.149324, 3.149324];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1, W[i], Q[i]);
-        }
-    });
-    xdescribe("Calcul Q en charge avec h1 croissant: ", () => {
-        const W: number = 0.8;
-        const h1: number[] = [1.05, 1.3, 1.5];
-        const Q: number[] = [1.365897, 3.623277, 4.214572];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i]);
-        }
-    });
-    xdescribe("Calcul Q a surface libre avec h1 croissant: ", () => {
-        const W: number = Infinity;
-        const h1: number[] = [1.100000, 1.500000];
-        const Q: number[] = [2.086781, 5.207945];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i]);
-        }
-    });
-});
diff --git a/spec/structure/test_structure_cunge80.ts b/spec/structure/test_structure_cunge80.ts
deleted file mode 100644
index 60d794187f28671e8c6135946d09b535338a6584..0000000000000000000000000000000000000000
--- a/spec/structure/test_structure_cunge80.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Result } from "../../src/util/result";
-import { RectangularStructureParams } from "../../src/structure/rectangular_structure_params";
-import { StructureFlowMode, StructureFlowRegime } from "../../src/structure/structure";
-import { StructureCunge80 } from "../../src/structure/structure_cunge80";
-import { describe, xdescribe } from "../mock_jasmine";
-import { itCalcQ } from "./test_rectangular_structure";
-
-const structPrm: RectangularStructureParams = new RectangularStructureParams(1, 1, 1, 2, 0.6, 0);
-const structTest: StructureCunge80 = new StructureCunge80(structPrm, true);
-
-describe("Class StructureCunge80: ", () => {
-    describe("Calcul Q avec W croissant: ", () => {
-        const W: number[] = [
-            0.000000, 0.100000, 0.200000, 0.300000, 0.400000, 0.500000, 0.600000,
-            0.700000, 0.800000, 0.900000, 1.000000, 1.100000, 1.200000, 1.300000];
-        const h1: number = 1.200000;
-        const Q: number[] = [0.000000, 0.237709, 0.475418, 0.713127, 0.950836, 1.188545,
-            1.426254, 1.663963, 1.901673, 2.139382, 2.377091, 2.377091, 2.377091, 2.377091];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1, W[i], Q[i]);
-        }
-    });
-    describe("Calcul Q en charge avec h1 croissant: ", () => {
-        const W: number = 0.8;
-        const h1: number[] = [1.050000, 1.300000, 1.500000];
-        const Q: number[] = [0.950836, 2.329064, 3.557704];
-        const mode: StructureFlowMode[] = [
-            StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE, StructureFlowMode.ORIFICE];
-        const regime: StructureFlowRegime[] = [
-            StructureFlowRegime.SUBMERGED, StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
-        }
-    });
-    describe("Calcul Q a surface libre avec h1 croissant: ", () => {
-        const W: number = Infinity;
-        const h1: number[] = [1.100000, 1.500000];
-        const Q: number[] = [1.680857, 3.758510];
-        const mode: StructureFlowMode[] = [
-            StructureFlowMode.WEIR, StructureFlowMode.WEIR];
-        const regime: StructureFlowRegime[] = [
-            StructureFlowRegime.SUBMERGED, StructureFlowRegime.FREE];
-
-        for (let i = 0; i < Q.length; i++ ) {
-            itCalcQ(structTest, h1[i], W, Q[i], mode[i], regime[i]);
-        }
-    });
-});
diff --git a/spec/test_config.ts b/spec/test_config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..51ce698d48f90c4654848d5ad8cf2c12e5ff7d16
--- /dev/null
+++ b/spec/test_config.ts
@@ -0,0 +1,9 @@
+/**
+ * précision de calcul (nombre de décimales)
+ */
+export let precDigits = 3;
+
+/**
+ * précision de calcul (max de abs(v-v'))
+ */
+export let precDist: number = Math.pow(10, -precDigits);
diff --git a/spec/test_func.ts b/spec/test_func.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dbf9a5aff6f4e278a637280856dd477cbf636a84
--- /dev/null
+++ b/spec/test_func.ts
@@ -0,0 +1,204 @@
+/**
+ * IMPORTANT !
+ * décommenter la ligne suivante (import { expect } from "./mock_jasmine") dans le cas d'une fonction
+ * qui utilise la fonction expect() de Jasmine mais qui doit être exécutée en dehors de tests Jasmine
+ */
+// import { describe, expect, it, xdescribe } from "./mock_jasmine";
+
+import { cLog } from "../src/util/log";
+import { Message, MessageCode } from "../src/util/message";
+import { Result } from "../src/util/result";
+import { precDist } from "./test_config";
+import { precDigits } from "./test_config";
+
+/**
+ * Compare deux valeurs réelles à un epsilon près
+ * @param val1 Première valeur à comparer
+ * @param val2 Deuxième valeur à comparer
+ * @param epsilon Erreur de comparaison acceptable
+ * @return Vrai si les valeurs sont égales, faux sinon
+ */
+export function equalEpsilon(val1: number, val2: number, epsilon: number = precDist) {
+    return Math.abs(val1 - val2) < epsilon;
+}
+
+/**
+ * compare 2 objets
+ * @param s message
+ * @param objTest objet à tester
+ * @param objValid objet de référence
+ * @param epsilon tolérance pour les comparaisons de nombres
+ */
+export function compareObject(
+    s: string,
+    objTest: { [key: number]: number },
+    objValid: { [key: number]: number },
+    epsilon: number,
+) {
+    const n1 = Object.keys(objTest).length;
+    const n2 = Object.keys(objValid).length;
+    let b: boolean = n1 === n2;
+    expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
+    if (!b) { return; }
+
+    for (let i = 0; i < n1; i++) {
+        const v1: number = objTest[+Object.keys(objTest)[i]];
+        const v2: number = objValid[+Object.keys(objValid)[i]];
+        b = equalEpsilon(v1, v2, epsilon);
+        expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
+        if (!b) { return; }
+    }
+}
+
+/**
+ * compare 2 tableaux
+ * @param s message
+ * @param arrTest tableau à tester
+ * @param arrValid tableau de référence
+ * @return false en cas d'échec
+ */
+export function compareArray(s: string, arrTest: number[], arrValid: number[]): boolean {
+    const n1 = arrTest.length;
+    const n2 = arrValid.length;
+    let b: boolean = n1 === n2;
+    expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
+    if (!b) { return false; }
+
+    for (let i = 0; i < arrTest.length; i++) {
+        const v1: number = arrTest[i];
+        const v2: number = arrValid[i];
+        b = equalEpsilon(v1, v2);
+        expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
+        if (!b) { return false; }
+    }
+
+    return true;
+}
+// export function compareArray2(s: string, arrTest: string[], arrValid: string[]): boolean {
+//     const n1 = arrTest.length;
+//     const n2 = arrValid.length;
+//     let b: boolean = n1 === n2;
+//     expect(b).toBeTruthy(s + ": longueur incorrecte " + n1 + ", devrait etre " + n2);
+//     if (!b) { return false; }
+
+//     for (let i = 0; i < arrTest.length; i++) {
+//         const v1: number = +arrTest[i];
+//         const v2: number = +arrValid[i];
+//         b = equalEpsilon(v1, v2);
+//         expect(b).toBeTruthy(s + " : " + i + "ieme valeur incorrecte " + v1 + ", devrait etre " + v2);
+//         if (!b) { return false; }
+//     }
+
+//     return true;
+// }
+
+/**
+ * compare 2 journaux
+ */
+export function compareLog(logTest: cLog, logValid: cLog) {
+    // console.log(JSON.stringify(logTest));
+    // console.log("journal :\n" + logTest.toString());
+
+    // taille
+
+    const n1 = logTest.messages.length;
+    const n2 = logValid.messages.length;
+    let b: boolean = n1 === n2;
+    expect(b).toBeTruthy("journal : nombre de messages incorrect (" + n1 + "), devrait etre " + n2);
+    if (!b) { return; }
+
+    // codes
+
+    for (let i = 0; i < n1; i++) {
+        const m1: Message = logTest.messages[i];
+        const m2: Message = logValid.messages[i];
+        b = m1.code === m2.code;
+        expect(b).toBeTruthy(
+            "journal : message n°" + i + ", code " + MessageCode[m1.code]
+            + " incorrect, devrait être " + MessageCode[m2.code],
+        );
+        if (!b) { return; }
+    }
+
+    // données
+
+    for (let i = 0; i < n1; i++) {
+        const m1: Message = logTest.messages[i];
+        const m2: Message = logValid.messages[i];
+        const code1 = MessageCode[m1.code];
+
+        // taille des données
+
+        const nd1 = Object.keys(m1.extraVar).length;
+        const nd2 = Object.keys(m2.extraVar).length;
+        b = nd1 === nd2;
+        expect(b).toBeTruthy(
+            "journal : message n°" + i + ", code " + code1 + " : nombre de données incorrect "
+            + nd1 + ", devrait etre " + nd2,
+        );
+        if (!b) { return; }
+
+        // clés des données
+
+        for (let j = 0; j < m1.extraVar.length; j++) {
+            b = m2.extraVar[j] !== undefined;
+            expect(b).toBeTruthy(
+                "journal : message n°" + i + ", code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
+                + " ne devrait pas être présente");
+            // if (!b) return;
+        }
+
+        for (let j = 0; j < m2.extraVar.length; j++) {
+            b = m1.extraVar[j] !== undefined;
+            expect(b).toBeTruthy(
+                "journal : message n°" + i + ", code " + code1 + " : la donnée " + j + "=" + m2.extraVar[j]
+                + " devrait être présente");
+            // if (!b) return;
+        }
+
+        // type des données
+
+        for (let j = 0; j < m1.extraVar.length; j++) {
+            b = typeof m1.extraVar[j] === typeof m2.extraVar[j];
+            expect(b).toBeTruthy(
+                "journal : " + i + "ieme message, code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
+                + " a un type " + (typeof m1.extraVar[j]) + " incorrect, devrait être du type "
+                + (typeof m2.extraVar[j]));
+            if (!b) { return; }
+        }
+
+        // valeur des données
+
+        for (let j = 0; j < m1.extraVar.length; j++) {
+            const d: any = m1.extraVar[j];
+            if (typeof d === "number") {
+                b = equalEpsilon(d, m2.extraVar[j]);
+            } else {
+                b = d === m2.extraVar[j];
+            }
+            expect(b).toBeTruthy(
+                "journal : " + i + "ieme message, code " + code1 + " : la donnée " + j + "=" + m1.extraVar[j]
+                + " a une valeur incorrecte, devrait être " + m2.extraVar[j]);
+            if (!b) { return; }
+        }
+    }
+}
+
+export function checkResult(val1: Result, val2: number, prec?: number) {
+    expect(val1.ok).toBeTruthy("Result : computation error on Result " + val1.toString());
+    if (val1.ok) {
+        /*
+         * on demande une précision de vérification inférieure à la précision de calcul
+         * pour ne pas échouer sur un arrondi sur le dernier chiffre
+         * par ex :
+         *   précision demandée 0.001
+         *   valeur attendue 1.301
+         *   valeur calculée 1.3016, arrondie à 1.302, faisant échouer le test
+         */
+        if (prec === undefined) {
+            prec = Math.max(0, precDigits - 1);
+        }
+
+        expect(val1.vCalc).toBeCloseTo(val2, prec);
+    }
+}
diff --git a/spec/tsconfig.spec.json b/spec/tsconfig.spec.json
index 86e4fca2e4fc36961b7a48563ddcb38ce153c982..4ad9f932db919296038ef06a0f8dee00c062686d 100644
--- a/spec/tsconfig.spec.json
+++ b/spec/tsconfig.spec.json
@@ -5,6 +5,8 @@
     "../spec/**/*.ts"
   ],
   "exclude": [
-    "../spec/test-remous-fenetre.ts"
+    "../spec/test-remous-fenetre.ts",
+    "../spec/test.ts",
+    "../spec/test_func.ts"
   ]
 }
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/cond_distri.ts b/src/cond_distri.ts
index 6ab4a1f2e70c35754daa5d98aff9f45f907ed0e6..e4ebdbfef33486495a1a2010d0dce0147e3b930f 100644
--- a/src/cond_distri.ts
+++ b/src/cond_distri.ts
@@ -69,7 +69,6 @@ export class ConduiteDistrib extends Nub {
      * @return valeur calculée
      */
     Equation(sVarCalc: string): Result {
-        let res: Result;
         let v: number;
 
         let K = 0.3164 * Math.pow(4, 1.75) / (5.5 * 9.81 * Math.pow(3.1415, 1.75)); // Constante de la formule
diff --git a/src/dichotomie.ts b/src/dichotomie.ts
index 93c6676aecd1c5af0224dab85c608fc0c5bd5b67..063c301a0af11ba741d71bbab35fd6682ae0a203 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.Calc(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,74 +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);
-        intMax.checkValue(rInit);
+        const intMax: Interval = new Interval(min, max);
+        try {
+            intMax.checkValue(rInit);
+        } 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;
 
@@ -298,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 };
@@ -333,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/index.ts b/src/index.ts
index 059f59cb3bc43bec06e548a7f378e07bb373398d..f0a9323bd637fece6aebfb8ceafe81c1df534db1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,23 +1,26 @@
-export * from './base';
-export * from './param';
-export * from './parameters';
-export * from './nub';
-export * from './cond_distri';
-export * from './dichotomie';
-export * from './lechaptcalmon';
-export * from './regime_uniforme';
-export * from './remous';
-export * from './section/section_type';
-export * from './section/section_trapez';
-export * from './section/section_rectang';
-export * from './section/section_circulaire';
-export * from './section/section_puissance';
-export * from './util/definedvalue';
-export * from './util/numericalstring';
-export * from './util/message';
-export * from './util/log';
-export * from './util/result';
-export * from './util/pair';
-export * from './util/interval';
-export * from './pab/pab_dimension';
-export * from './pab/pab_puissance';
+export * from "./base";
+export * from "./param";
+export * from "./parameters";
+export * from "./nub";
+export * from "./cond_distri";
+export * from "./dichotomie";
+export * from "./lechaptcalmon";
+export * from "./regime_uniforme";
+export * from "./remous";
+export * from "./section/section_type";
+export * from "./section/section_trapez";
+export * from "./section/section_rectang";
+export * from "./section/section_circulaire";
+export * from "./section/section_puissance";
+export * from "./util/definedvalue";
+export * from "./util/numericalstring";
+export * from "./util/message";
+export * from "./util/log";
+export * from "./util/result";
+export * from "./util/resultelement";
+export * from "./util/pair";
+export * from "./util/interval";
+export * from "./pab/pab_dimension";
+export * from "./pab/pab_puissance";
+export * from "./util/iterator";
+export * from "./util/enum";
diff --git a/src/nub.ts b/src/nub.ts
index d3822c3ab8c3d24aabe033a8a341c5b483683da4..cb434afd5a582309ddb79582381d8af34b1fbdc5 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,61 @@ 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, rPrec: number = 0.001): Result {
+        if (rInit === undefined) {
+            rInit = this._prms.map[sVarCalc].v;
+        }
+        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/pab/pab_dimension.ts b/src/pab/pab_dimension.ts
index d95c0e45e08bdea1f01db1b4bdd1a143827202bd..5c84d9fea338d98e12d7a6d180efa30d64ce7800 100644
--- a/src/pab/pab_dimension.ts
+++ b/src/pab/pab_dimension.ts
@@ -1,6 +1,6 @@
 import { Result } from "../util/result";
 import { ComputeNodeType, ParamDefinition, ParamDomain, ParamDomainValue, ParamCalculability, ParamsEquation } from "../param";
-import { NumericalString } from "../index";
+import { NumericalString } from "../util/numericalstring";
 import { Nub } from "../nub";
 
 export class PabDimensionParams extends ParamsEquation {
diff --git a/src/pab/pab_puissance.ts b/src/pab/pab_puissance.ts
index 4ee44dade1fefea24c8177bcdc69445ca050c996..df65b5086619ca734b95f790505ccbe2468dc19e 100644
--- a/src/pab/pab_puissance.ts
+++ b/src/pab/pab_puissance.ts
@@ -1,6 +1,6 @@
 import { Result } from "../util/result";
 import { ComputeNodeType, ParamDefinition, ParamDomain, ParamDomainValue, ParamCalculability, ParamsEquation } from "../param";
-import { NumericalString } from "../index";
+import { NumericalString } from "../util/numericalstring";
 import { Nub } from "../nub";
 
 export class PabPuissanceParams extends ParamsEquation {
diff --git a/src/param.ts b/src/param.ts
index d8aa8ee04f8ff60a352471ec7c15fd86e6efcd7f..77a641c1fa70aa771cfdc1990efbd4b8be9e866e 100644
--- a/src/param.ts
+++ b/src/param.ts
@@ -1,8 +1,9 @@
 // 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';
+import { MapIterator } from "./util/iterator";
 
 /**
  * domaine de définition du paramètre
@@ -18,7 +19,6 @@ export enum ParamDomainValue {
      */
     POS_NULL,
 
-
     /**
      * > 0
      */
@@ -36,13 +36,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 +75,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 +100,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 +168,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 +180,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 +197,7 @@ export class BaseParam extends DefinedNumber {
         return this._symbol;
     }
 
-    getDomain(): ParamDomain {
+    public getDomain(): ParamDomain {
         return this._domain;
     }
 
@@ -202,22 +205,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 +227,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 +235,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 +284,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 +294,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 +323,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 +338,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 +358,60 @@ 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
  */
-export abstract class ParamsEquation {
+// 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))
+        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,45 +421,26 @@ 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;
+        if (res.length > 0) {
+            throw new Error("Calculability of parameter(s) " + res.toString() + " has not been defined");
         }
-
-        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;
-        }
-
-        throw 'ParamsEquation.getParameter() : invalid parameter name ' + name;
+    [Symbol.iterator](): Iterator<ParamDefinition> {
+        return this.iterator;
     }
 
-    public getFirstAnalyticalParameter(): ParamDefinition {
-        for (let ps in this._paramMap) {
-            let p: ParamDefinition = this._paramMap[ps];
-            if (p.isAnalytical())
-                return p;
-        }
-        return undefined;
+    public get iterator() {
+        return new MapIterator(this._paramMap);
     }
 }
 
@@ -446,11 +463,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 +480,7 @@ export abstract class ComputeNode extends Debug {
     public getFirstAnalyticalParameter(): ParamDefinition {
         return this._prms.getFirstAnalyticalParameter();
     }
+
+    protected abstract setParametersCalculability(): void;
+
 }
diff --git a/src/regime_uniforme.ts b/src/regime_uniforme.ts
index 5582c5e6366611fc27e0aee48c263695078593c9..d1bd51e9734161f8c967e26736195968ec980e6f 100644
--- a/src/regime_uniforme.ts
+++ b/src/regime_uniforme.ts
@@ -24,34 +24,40 @@ export class RegimeUniforme extends Nub {
    * Calcul du débit en régime uniforme.
    * @return Débit en régime uniforme
    */
-    Calc_Qn(): number {
+    Calc_Qn(): Result {
         this.Sn.Reset(true);
         if (this.Sn.prms.If.v <= 0)
-            return 0;
+            return new Result(0);
 
         // this.debug("RU: Calc_Qn : ");
         // this.debug(this.Sn.prms);
 
-        return this.Sn.prms.Ks.v * Math.pow(this.Sn.Calc("R", this.Sn.prms.Y.v), 2 / 3) * this.Sn.Calc("S", this.Sn.prms.Y.v) * Math.sqrt(this.Sn.prms.If.v);
+        // return this.Sn.prms.Ks.v * Math.pow(this.Sn.Calc("R", this.Sn.prms.Y.v), 2 / 3) * this.Sn.Calc("S", this.Sn.prms.Y.v) * Math.sqrt(this.Sn.prms.If.v);
+
+        const rR: Result = this.Sn.Calc("R", this.Sn.prms.Y.v);
+        if (!rR)
+            return rR;
+
+        const rS: Result = this.Sn.Calc("S", this.Sn.prms.Y.v)
+        if (!rS)
+            return rS;
+
+        const v = this.Sn.prms.Ks.v * Math.pow(rR.vCalc, 2 / 3) * rS.vCalc * Math.sqrt(this.Sn.prms.If.v);
+        return new Result(v);
     }
 
     Equation(sVarCalc: string): Result {
         this.debug("RU: Equation(" + sVarCalc + ")")
-        let v: number;
 
         switch (sVarCalc) {
             case 'Y':
-                v = this.Sn.Calc("Yn");
-                break;
+                return this.Sn.Calc("Yn");
 
             case 'Q':
-                v = this.Calc_Qn();
-                break;
+                return this.Calc_Qn();
 
             default:
                 throw "RegimeUniforme.Equation() : invalid variable name " + sVarCalc;
         }
-
-        return new Result(v);
     }
 }
diff --git a/src/remous.ts b/src/remous.ts
index ff305273c1259a3c3a02145ae9c5161cb943e736..76b6ea4f72b572cb77ca882272aebd089a946a39 100644
--- a/src/remous.ts
+++ b/src/remous.ts
@@ -1,5 +1,6 @@
 import { ParamsSection, acSection } from "./section/section_type";
 import { XOR, round } from "./base";
+import { ResultElement } from "./util/resultelement";
 import { Result } from "./util/result";
 import { ParamsEquation, ParamDefinition, ParamCalculability, ComputeNodeType, ParamDomainValue } from "./param";
 import { Dichotomie } from "./dichotomie";
@@ -104,7 +105,7 @@ export class CourbeRemous extends Nub {
 	/**
 	 * Journal de calcul
 	 */
-	private _log: cLog;
+	//private _log: cLog;
 
 	private prmSect: ParamsSection;
 
@@ -115,14 +116,14 @@ export class CourbeRemous extends Nub {
 
 	constructor(crp: CourbeRemousParams, dbg: boolean = false) {
 		super(crp, dbg);
-		this._log = crp.Sn.log;
+		// this._log = crp.Sn.log;
 		this.prmSect = crp.Sn.prms;
 		this.Sn.Calc("Yc");
 	}
 
-	public get log() {
-		return this._log;
-	}
+	// public get log() {
+	// 	return this._log;
+	// }
 
 	private get Sn(): acSection {
 		return this.prms.Sn;
@@ -143,9 +144,19 @@ export class CourbeRemous extends Nub {
 	public Equation(sVarCalc: string): Result {
 		if (sVarCalc == "Hs") {
 			// Equation de l'intégration par la méthode des trapèzes
-			// let res: number = this.Sn.Calc('Hs', this.VarCal) - this.Sn.Calc('J', this.VarCal) / 2 * this.Dx;
 			this.Sn.Reset();  // pour forcer le calcul avec la nouvelle valeur de prmSect.Y
-			let res: number = this.Sn.Calc('Hs') - this.Sn.Calc('J') / 2 * this.Dx;
+
+			// let res: number = this.Sn.Calc('Hs') - this.Sn.Calc('J') / 2 * this.Dx;
+
+			const rHS = this.Sn.Calc('Hs');
+			if (!rHS.ok)
+				return rHS;
+
+			const rJ = this.Sn.Calc('J');
+			if (!rJ.ok)
+				return rJ;
+
+			const res: number = rHS.vCalc - rJ.vCalc / 2 * this.Dx;
 			return new Result(res);
 		}
 
@@ -156,9 +167,20 @@ export class CourbeRemous extends Nub {
 	 * Calcul de dy/dx (utilisé par Euler explicite et Runge-Kutta 4)
 	 * @param Y Tirant d'eau initial
 	 */
-	private Calc_dYdX(Y: number): number {
+	private Calc_dYdX(Y: number): Result {
 		// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
-		return - (this.prmSect.If.v - this.Sn.Calc('J', Y)) / (1 - Math.pow(this.Sn.Calc('Fr', Y), 2));
+		// return - (this.prmSect.If.v - this.Sn.Calc('J', Y)) / (1 - Math.pow(this.Sn.Calc('Fr', Y), 2));
+
+		const rJ = this.Sn.Calc('J', Y);
+		if (!rJ.ok)
+			return rJ;
+
+		const rFR = this.Sn.Calc('Fr', Y);
+		if (!rFR.ok)
+			return rFR;
+
+		const v = - (this.prmSect.If.v - rJ.vCalc) / (1 - Math.pow(rFR.vCalc, 2));
+		return new Result(v);
 	}
 
 	/**
@@ -167,10 +189,20 @@ export class CourbeRemous extends Nub {
 	 * @return Tirant d'eau
 	 */
 	private Calc_Y_EulerExplicite(Y: number): Result {
+		if (!this.Sn.HautCritique.ok)
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
+
 		// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
-		let Y2 = Y + this.Dx * this.Calc_dYdX(Y);
-		if (XOR(this.Dx > 0, !(Y2 < this.Sn.HautCritique))) {
-			return new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+
+		const rDXDY = this.Calc_dYdX(Y);
+		if (!rDXDY.ok)
+			return rDXDY;
+
+		// let Y2 = Y + this.Dx * this.Calc_dYdX(Y);
+		const Y2 = Y + this.Dx * rDXDY.vCalc;
+
+		if (XOR(this.Dx > 0, !(Y2 < this.Sn.HautCritique.vCalc))) {
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
 		return new Result(Y2);
@@ -182,44 +214,55 @@ export class CourbeRemous extends Nub {
 	 * @return Tirant d'eau
 	 */
 	private Calc_Y_RK4(Y: number): Result {
+		if (!this.Sn.HautCritique.ok)
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
+
 		// L'appel à Calc('J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
-		//$rDx = $this ->rDx;
 		let Dx = this.Dx;
-		//$rk1 = $this ->Calc_dYdX($Y);
-		let k1 = this.Calc_dYdX(Y);
 
-		let hc = this.Sn.HautCritique;
+		// let k1 = this.Calc_dYdX(Y);
+		const rDXDY: Result = this.Calc_dYdX(Y);
+		if (!rDXDY.ok)
+			return rDXDY;
+		const k1 = rDXDY.vCalc;
+
+		let hc = this.Sn.HautCritique.vCalc;
 
-		//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk1 < $this ->oSect ->rHautCritique)) { return false; }
 		if (XOR(Dx > 0, !(Y + Dx / 2 * k1 < hc))) {
-			return new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
-		//$rk2 = $this ->Calc_dYdX($Y + $rDx / 2 * $rk1);
-		let k2 = this.Calc_dYdX(Y + Dx / 2 * k1);
+		// let k2 = this.Calc_dYdX(Y + Dx / 2 * k1);
+		const rDXDY2: Result = this.Calc_dYdX(Y + Dx / 2 * k1);
+		if (!rDXDY2.ok)
+			return rDXDY2;
+		const k2 = rDXDY2.vCalc;
 
-		//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk2 < $this ->oSect ->rHautCritique)) { return false; }
 		if (XOR(Dx > 0, !(Y + Dx / 2 * k2 < hc))) {
-			return new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
-		//$rk3 = $this ->Calc_dYdX($Y + $rDx / 2 * $rk2);
-		let k3 = this.Calc_dYdX(Y + Dx / 2 * k2);
+		// let k3 = this.Calc_dYdX(Y + Dx / 2 * k2);
+		const rDXDY3: Result = this.Calc_dYdX(Y + Dx / 2 * k2);
+		if (!rDXDY3.ok)
+			return rDXDY3;
+		const k3 = rDXDY3.vCalc;
 
-		//if ($this ->rDx > 0 xor !($Y + $rDx / 2 * $rk3 < $this ->oSect ->rHautCritique)) { return false; }
 		if (XOR(Dx > 0, !(Y + Dx / 2 * k3 < hc))) {
-			return new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
-		//$rk4 = $this ->Calc_dYdX($Y + $rDx * $rk3);
-		let k4 = this.Calc_dYdX(Y + Dx * k3);
+		// let k4 = this.Calc_dYdX(Y + Dx * k3);
+		const rDXDY4: Result = this.Calc_dYdX(Y + Dx * k3);
+		if (!rDXDY4.ok)
+			return rDXDY4;
+		const k4 = rDXDY4.vCalc;
 
-		//$Yout = $Y + $rDx / 6 * ($rk1 + 2 * ($rk2 + $rk3) + $rk4);
 		let Yout = Y + Dx / 6 * (k1 + 2 * (k2 + k3) + k4);
 
 		//if ($this ->rDx > 0 xor !($Yout < $this ->oSect ->rHautCritique)) { return false; }
 		if (XOR(Dx > 0, !(Yout < hc))) {
-			let res = new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+			let res = new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
 		return new Result(Yout);
@@ -239,37 +282,36 @@ export class CourbeRemous extends Nub {
 	 * @return Tirant d'eau
 	 */
 	private Calc_Y_Trapez(Y: number): Result {
-		//include_spip('hyd_inc/dichotomie.class');
-		//$this ->VarCal = &$Y;
-		// this.VarCal = Y;
+		if (!this.Sn.HautCritique.ok)
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 
-		// $oDicho = new cDichotomie($this ->oLog, $this, 'Calc_Y_Trapez_Fn', false);
 		let Dicho = new Dichotomie(this, "Y", this._debugDicho, "Hs");
 
 		// Calcul de H + J * \Delta x / 2
-		// $Trapez_Fn = $this ->oSect ->Calc('Hs', $this ->VarCal) + $this ->oSect ->Calc('J', $this ->VarCal) / 2 * $this ->rDx;
-		// let Trapez_Fn = this.Sn.Calc('Hs', this.VarCal) + this.Sn.Calc('J', this.VarCal) / 2 * this.Dx
-		let Trapez_Fn = this.Sn.Calc('Hs', Y) + this.Sn.Calc('J', Y) / 2 * this.Dx
+		// let Trapez_Fn = this.Sn.Calc('Hs', Y) + this.Sn.Calc('J', Y) / 2 * this.Dx
+		const rHS: Result = this.Sn.Calc('Hs', Y);
+		if (!rHS.ok)
+			return rHS;
+
+		const rJ: Result = this.Sn.Calc('J', Y)
+		if (!rJ.ok)
+			return rJ;
+
+		let Trapez_Fn = rHS.vCalc + rJ.vCalc / 2 * this.Dx
 
 		// H est la charge totale. On se place dans le référentiel ou Zf de la section à calculer = 0
-		// $Trapez_Fn = $Trapez_Fn - $this ->rDx * $this ->oP ->rIf;
 		Trapez_Fn -= this.Dx * this.prmSect.If.v;
 
-		// list($Y2, $flag) = $oDicho ->calculer($Trapez_Fn, $this ->oP ->rPrec, $this ->oSect ->rHautCritique);
-		// let r: Result = Dicho.Dichotomie(Trapez_Fn, this.prmSect.Prec.v, this.Sn.HautCritique);
 		let r: Result = Dicho.Dichotomie(Trapez_Fn, this.prmSect.Prec.v, Y);
-
-		// if ($flag < 0) {
 		if (!r.ok)
 			return r;
 
-		let Y2 = r.vCalc;
-		// } elseif($this ->rDx > 0 xor !($Y2 < $this ->oSect ->rHautCritique)) {
-		if (XOR(this.Dx > 0, !(Y2 < this.Sn.HautCritique))) {
-			return new Result(new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE));
+		if (XOR(this.Dx > 0, !(r.vCalc < this.Sn.HautCritique.vCalc))) {
+			return new Result(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 		}
 
-		return new Result(Y2);
+		// return new Result(Y2);
+		return r;
 	}
 
 	/**
@@ -317,8 +359,11 @@ export class CourbeRemous extends Nub {
 	 * Calcul d'une courbe de remous en fluvial ou torrentiel
 	 * @param YCL Condition limite amont (torrentiel) ou aval (fluvial)
 	 */
-	private calcul(YCL: number): { [key: number]: number } {
+	private calcul(YCL: number): ResultElement
+	// { [key: number]: number } 
+	{
 		let trY: { [key: number]: number; } = {};
+		const res = new ResultElement();
 
 		if (this.Dx > 0) {
 			// Calcul depuis l'aval
@@ -354,30 +399,34 @@ export class CourbeRemous extends Nub {
 
 					let m: Message = new Message(MessageCode.ERROR_REMOUS_PENTE_FORTE);
 					m.extraVar["x"] = x;
-					this._log.add(m);
+					// this._log.add(m);
+					res.addMessage(m);
 				}
 
 				trY[round(x, this.prmSect.iPrec.v)] = rY.vCalc;
 			} else {
-				let m = new Message(MessageCode.ERROR_REMOUS_ARRET_CRITIQUE);
+				let m = new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE);
 				m.extraVar["x"] = x;
-				this._log.add(m);
+				// this._log.add(m);
+				res.addMessage(m);
 				this.debug("Arrêt du calcul : Hauteur critique atteinte à l'abscisse " + x + " m");
 				break;
 			}
 			lastY = rY.vCalc;
 		}
 
-		return trY;
+		//return trY;
+		res.addExtraResult("trY", trY);
+		return res;
 	}
 
-	private logArray(a: string[]) {
+	private logArray(a: any[]) {
 		let s = "[";
 		let first = true;
 		for (let e of a) {
 			if (!first)
 				s += ",";
-			s += +e;
+			s += String(e);
 			first = false;
 		}
 		s += "]";
@@ -402,20 +451,24 @@ export class CourbeRemous extends Nub {
 	/**
 	 * calcul de la ligne fluviale depuis l'aval (si possible)
 	 */
-	public calculFluvial() {
-		let res: { [key: number]: number; } = {};
+	public calculFluvial(): ResultElement {
+		if (!this.Sn.HautCritique.ok)
+			return new ResultElement(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 
 		// Calcul depuis l'aval
-		if (this.Sn.HautCritique <= this.prms.Yaval.v) {
-			this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
+		if (this.Sn.HautCritique.vCalc <= this.prms.Yaval.v) {
+			// this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_FLUVIAL));
 
 			this.debug("Condition limite aval (" + this.prms.Yaval.v + ") >= Hauteur critique (" + this.Sn.HautCritique + ") : calcul de la partie fluviale à partir de l'aval");
 			this.Dx = this.prms.Dx.v;
-			res = this.calcul(this.prms.Yaval.v);
+			var res = this.calcul(this.prms.Yaval.v);
+			res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_FLUVIAL));
 		}
 		else {
 			this.debug("Condition limite aval (" + this.prms.Yaval.v + ") < Hauteur critique (" + this.Sn.HautCritique + ") : pas de calcul possible depuis l'aval");
-			this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
+			// this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
+			res = new ResultElement();
+			res.addMessage(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AVAL));
 		}
 
 		return res;
@@ -424,20 +477,24 @@ export class CourbeRemous extends Nub {
 	/**
 	 * calcul de la ligne torrentielle depuis l'amont (si possible)
 	 */
-	public calculTorrentiel() {
-		let res: { [key: number]: number; } = {};
+	public calculTorrentiel(): ResultElement {
+		if (!this.Sn.HautCritique.ok)
+			return new ResultElement(new Message(MessageCode.WARNING_REMOUS_ARRET_CRITIQUE));
 
 		// Calcul depuis l'amont
-		if (this.Sn.HautCritique >= this.prms.Yamont.v) {
-			this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
+		if (this.Sn.HautCritique.vCalc >= this.prms.Yamont.v) {
+			// this._log.add(new Message(MessageCode.ERROR_REMOUS_CALCUL_TORRENTIEL));
 
 			this.debug("Condition limite amont (" + this.prms.Yamont.v + ") <= Hauteur critique (" + this.Sn.HautCritique + ") : calcul de la partie torrentielle à partir de l'amont");
 			this.Dx = -this.prms.Dx.v;
-			res = this.calcul(this.prms.Yamont.v);
+			var res = this.calcul(this.prms.Yamont.v);
+			res.insertMessage(new Message(MessageCode.INFO_REMOUS_CALCUL_TORRENTIEL));
 		}
 		else {
-			this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
+			// this._log.add(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 			this.debug("Condition limite amont (" + this.prms.Yamont.v + ") > Hauteur critique (" + this.Sn.HautCritique + ") : pas de calcul possible depuis l'amont");
+			res = new ResultElement();
+			res.addMessage(new Message(MessageCode.ERROR_REMOUS_PAS_CALCUL_DEPUIS_AMONT));
 		}
 
 		return res;
@@ -446,35 +503,83 @@ export class CourbeRemous extends Nub {
 	/**
 	 * @param val_a_cal nom de la variable à calculer
 	 */
-	public calculRemous(val_a_cal: string): {
-		"flu": { [key: number]: number; },
-		"tor": { [key: number]: number; },
-		"trX": string[],
-		"tRes": { [key: number]: number }
-	} {
-		let Yc: number = this.Sn.Calc("Yc");
-
-		let m: Message = new Message(MessageCode.ERROR_REMOUS_LARGEUR_BERGE);
-		m.extraVar["B"] = this.Sn.Calc("B", this.Sn.prms.YB.v);
-		this._log.add(m);
-
-		m = new Message(MessageCode.ERROR_REMOUS_H_CRITIQUE);
+	public calculRemous(val_a_cal: string):
+		// {
+		// "flu": { [key: number]: number; },
+		// "tor": { [key: number]: number; },
+		// "trX": string[],
+		// "tRes": { [key: number]: number }
+		// }
+		Result {
+		const res = new Result();
+
+		// let Yc: number = this.Sn.Calc("Yc");
+		const rYC = this.Sn.Calc("Yc");
+		if (!rYC.ok) {
+			res.addLog(rYC.log);
+			return res;
+		}
+		const Yc: number = rYC.vCalc;
+
+		const rB: Result = this.Sn.Calc("B", this.Sn.prms.YB.v)
+		if (!rB.ok) {
+			res.addLog(rB.log);
+			return res;
+		}
+
+		let m: Message = new Message(MessageCode.INFO_REMOUS_LARGEUR_BERGE);
+		// m.extraVar["B"] = this.Sn.Calc("B", this.Sn.prms.YB.v);
+		m.extraVar["B"] = rB.vCalc;
+		// this._log.add(m);
+		res.addMessage(m);
+
+		m = new Message(MessageCode.INFO_REMOUS_H_CRITIQUE);
 		m.extraVar["Yc"] = Yc;
-		this._log.add(m);
+		// this._log.add(m);
+		res.addMessage(m);
+
+		const rYN = this.Sn.Calc("Yn");
+		if (!rYN.ok) {
+			res.addLog(rYN.log);
+			return res;
+		}
 
-		let Yn = this.Sn.Calc("Yn");
-		m = new Message(MessageCode.ERROR_REMOUS_H_NORMALE);
+		const Yn = rYN.vCalc;
+		m = new Message(MessageCode.INFO_REMOUS_H_NORMALE);
 		m.extraVar["Yn"] = Yn;
-		this._log.add(m);
+		// this._log.add(m);
+		res.addMessage(m);
 
-		this.debug("largeur berge " + this.Sn.Calc("B"));
-		this.debug("hauteur critique " + Yc);
-		this.Sn.HautNormale = this.Sn.Calc("Yn");
-		this.debug("hauteur normale " + this.Sn.HautNormale);
+		// this.debug("largeur berge " + this.Sn.Calc("B"));
+		// const rB2: Result = this.Sn.Calc("B")
+		// this.debug("largeur berge " + rB2.vCalc);
+		// this.debug("hauteur critique " + Yc);
+		// this.Sn.HautNormale = this.Sn.Calc("Yn");
+		// this.debug("hauteur normale " + this.Sn.HautNormale);
+		// this.debug("hauteur normale " + Yn);
 
 		// Calcul des courbes de remous
-		let crbFlu: { [key: number]: number; } = this.calculFluvial();
-		let crbTor: { [key: number]: number; } = this.calculTorrentiel();
+
+		// let crbFlu: { [key: number]: number; } = this.calculFluvial();
+		let rCourbeFlu: ResultElement = this.calculFluvial();
+		// if (!rCourbeFlu.ok) {
+		res.addLog(rCourbeFlu.log);
+		// 	return res;
+		// }
+
+		// let crbTor: { [key: number]: number; } = this.calculTorrentiel();
+		let rCourbeTor: ResultElement = this.calculTorrentiel();
+		// if (!rCourbeTor.ok) {
+		res.addLog(rCourbeTor.log);
+		// 	return res;
+		// }
+
+		let crbFlu = rCourbeFlu.getExtraResult("trY");
+		if (crbFlu == undefined)
+			crbFlu = {};
+		let crbTor = rCourbeTor.getExtraResult("trY");
+		if (crbTor == undefined)
+			crbTor = {};
 
 		//this.debug("HautCritique ", this.Sn.HautCritique);
 
@@ -488,17 +593,17 @@ export class CourbeRemous extends Nub {
 
 		for (let xflu in crbFlu) {
 			let yflu = crbFlu[xflu];
-			this.debug("imp x " + xflu + " flu " + this.Sn.Calc('Imp', yflu));
+			// this.debug("imp x " + xflu + " flu " + this.Sn.Calc('Imp', yflu));
 		}
 
 		for (let xtor in crbTor) {
 			let ytor = crbTor[xtor];
-			this.debug("imp x " + xtor + " tor " + this.Sn.Calc('Imp', ytor));
+			// this.debug("imp x " + xtor + " tor " + this.Sn.Calc('Imp', ytor));
 		}
 
 		// Détection du ressaut hydraulique
-		let nFlu: number = this.size(crbFlu);
-		let nTor: number = this.size(crbTor);
+		const nFlu: number = this.size(crbFlu);
+		const nTor: number = this.size(crbTor);
 		if (nFlu != 0 && nTor != 0) {
 			let firstYFlu = crbFlu[0];
 			let lastYTor = this.last(crbTor);
@@ -554,7 +659,7 @@ export class CourbeRemous extends Nub {
 			// this.debug(trX);
 
 			let bRessaut = false;
-			let Dx = this.prms.Dx.v;
+			const Dx = this.prms.Dx.v;
 
 			for (let irX = 0; irX < trX.length; irX++) {
 				let rX: number = +trX[irX];
@@ -563,10 +668,15 @@ export class CourbeRemous extends Nub {
 				// this.debug("partielle[" + rX + "]=" + crbPartielle[rX]);
 
 				// Calcul de l'abscisse de la section dans l'autre régime
-				let Yco = this.Sn.Calc('Yco', crbPartielle[rX]); // Y conjugué
+				const rYCO = this.Sn.Calc('Yco', crbPartielle[rX]); // Y conjugué
+				if (!rYCO.ok) {
+					res.addLog(rYCO.log);
+					return res;
+				}
+				const Yco = rYCO.vCalc;
 				// this.debug("rX=" + rX + " Yco(Ypartiel=" + crbPartielle[rX] + ")=" + Yco);
 
-				let rLongRst = 5 * Math.abs(crbPartielle[rX] - Yco); // Longueur du ressaut
+				const rLongRst = 5 * Math.abs(crbPartielle[rX] - Yco); // Longueur du ressaut
 				// this.debug("longueur ressaut=" + rLongRst);
 
 				let xRst = rX + Math.round(iSens * rLongRst / Dx) * Dx; // Abscisse où comparer Yconj et Y
@@ -579,6 +689,10 @@ export class CourbeRemous extends Nub {
 
 				let impYpartielle = this.Sn.Calc('Imp', crbPartielle[rX]);
 				// this.debug("imp(Ypartiel[rX=" + rX + "]=" + crbPartielle[rX] + ")=" + impYpartielle);
+				if (!impYpartielle.ok) {
+					res.addLog(impYpartielle.log);
+					return res;
+				}
 
 				if (crbComplete[xRst] != undefined) {
 					// Hauteur décalée de la longueur du ressaut (il faut gérer la pente du fond)
@@ -586,13 +700,18 @@ export class CourbeRemous extends Nub {
 					// this.debug("Ydec=" + Ydec);
 					let impYcomplete = this.Sn.Calc('Imp', crbComplete[xRst]);
 					// this.debug("imp(Ycomplet[xRst=" + xRst + "]=" + crbComplete[xRst] + ")=" + impYcomplete);
+					if (!impYcomplete.ok) {
+						res.addLog(impYcomplete.log);
+						return res;
+					}
 
-					if (impYpartielle > impYcomplete) {
+					if (impYpartielle.vCalc > impYcomplete.vCalc) {
 						this.debug("Ressaut hydraulique détecté entre les abscisses " + Math.min(rX, xRst) + " et " + Math.max(rX, xRst));
-						m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_HYDRO);
+						m = new Message(MessageCode.INFO_REMOUS_RESSAUT_HYDRO);
 						m.extraVar["xmin"] = Math.min(rX, xRst);
 						m.extraVar["xmax"] = Math.max(rX, xRst);
-						this._log.add(m);
+						// this._log.add(m);
+						res.addMessage(m);
 						// this.debug("rX=" + rX + " xRst=" + xRst);
 
 						// Modification de la ligne d'eau complète
@@ -621,10 +740,11 @@ export class CourbeRemous extends Nub {
 			}
 			if (!bRessaut) {
 				// Le ressaut est en dehors du canal
-				let m = new Message(MessageCode.ERROR_REMOUS_RESSAUT_DEHORS);
+				let m = new Message(MessageCode.INFO_REMOUS_RESSAUT_DEHORS);
 				m.extraVar["sens"] = sSens;
 				m.extraVar["x"] = +this.last(trX);
-				this._log.add(m);
+				//  this._log.add(m);
+				res.addMessage(m);
 
 				this.debug("Ressaut hydraulique détecté à l'" + sSens + " de l'abscisse " + this.last(trX));
 				if (iSens == 1)
@@ -643,18 +763,20 @@ export class CourbeRemous extends Nub {
 		this.debug(JSON.stringify(crbPartielle));
 
 		// Définition des abscisses
-		let trX: string[] = [];
+		let trX: number[] = [];
 
 		if (nFlu != 0)
-			trX = Object.keys(crbFlu);
+			trX = Object.keys(crbFlu).map(k => +k);
 
-		if (nTor != 0)
-			trX = trX.concat(Object.keys(crbTor));
+		if (nTor != 0) {
+			const kTor = Object.keys(crbTor).map(k => +k);
+			trX = trX.concat(kTor);
+		}
 		// this.debug("trX=" + trX);
 
 		trX.sort((a, b) => {
-			if (+a > +b) return 1;
-			if (+a < +b) return -1;
+			if (a > b) return 1;
+			if (a < b) return -1;
 			return 0;
 		});
 		// this.debug("trX tri=" + trX);
@@ -674,19 +796,25 @@ export class CourbeRemous extends Nub {
 		if (val_a_cal != undefined && (nFlu != 0 || nTor != 0)) {
 			for (let rX of trX) {
 				let rY = undefined;
-				let hasFlu: boolean = crbFlu[+rX] != undefined;
-				let hasTor: boolean = crbTor[+rX] != undefined;
+				let hasFlu: boolean = crbFlu[rX] != undefined;
+				let hasTor: boolean = crbTor[rX] != undefined;
 
 				if (hasFlu && !hasTor)
-					rY = crbFlu[+rX];
+					rY = crbFlu[rX];
 
 				if (hasTor)
-					if (!hasFlu || (hasFlu && crbFlu[+rX] == crbTor[+rX]))
-						rY = crbTor[+rX];
+					if (!hasFlu || (hasFlu && crbFlu[rX] == crbTor[rX]))
+						rY = crbTor[rX];
 
 				if (rY != undefined) {
-					tRes[+rX] = this.Sn.Calc(val_a_cal, rY);
-					this.debug('X=' + rX + ' Calc(' + val_a_cal + ', Y=' + rY + ')=' + tRes[+rX]);
+					// tRes[+rX] = this.Sn.Calc(val_a_cal, rY);
+					const rVar = this.Sn.Calc(val_a_cal, rY);
+					if (!rVar.ok) {
+						res.addLog(rVar.log);
+						return res;
+					}
+					tRes[rX] = rVar.vCalc;
+					this.debug('X=' + rX + ' Calc(' + val_a_cal + ', Y=' + rY + ')=' + tRes[rX]);
 				}
 			}
 
@@ -694,6 +822,23 @@ export class CourbeRemous extends Nub {
 			this.logObject(tRes);
 		}
 
-		return { "flu": crbFlu, "tor": crbTor, "trX": trX, "tRes": tRes };
+		//return { "flu": crbFlu, "tor": crbTor, "trX": trX, "tRes": tRes };
+		const rFlu = new ResultElement();
+		rFlu.addExtraResult("flu", crbFlu);
+		res.addResult(rFlu);
+
+		const rTor = new ResultElement();
+		rTor.addExtraResult("tor", crbTor);
+		res.addResult(rTor);
+
+		const rX = new ResultElement();
+		rX.addExtraResult("trX", trX);
+		res.addResult(rX);
+
+		const rVar = new ResultElement();
+		rVar.addExtraResult("tRes", tRes);
+		res.addResult(rVar);
+
+		return res;
 	}
 }
diff --git a/src/section/hauteur.ts b/src/section/hauteur.ts
index 9a3faa0eac9f8eb35aa251a768a78a89d12a0f85..cb2cbae3bef69740cc2a5c0492fdbeb17c91b021 100644
--- a/src/section/hauteur.ts
+++ b/src/section/hauteur.ts
@@ -1,6 +1,8 @@
 import { Debug } from "../base"
 import { acSection, cParamsCanal } from "./section_type";
 import { acNewton } from "./newton";
+import { Result } from "../util/result";
+import { MessageCode, Message } from "../util/message";
 
 /**
  * Calcul de la hauteur critique
@@ -24,28 +26,63 @@ export class cHautCritique extends acNewton {
          * Calcul de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcFn(rX: number) {
+        CalcFn(rX: number): Result {
+                const rS: Result = this.Sn.Calc("S", rX);
+                if (!rS.ok)
+                        return rS;
+
                 // Calcul de la fonction
-                if (this.Sn.Calc("S", rX) != 0)
-                        return (Math.pow(this.Sn.prms.Q.v, 2) * this.Sn.Calc("B", rX) / Math.pow(this.Sn.Calc("S", rX), 3) / cParamsCanal.G - 1);
+                // if (this.Sn.Calc("S", rX) != 0)
+                if (rS.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_SURFACE_NULLE));
+
+                // return (Math.pow(this.Sn.prms.Q.v, 2) * this.Sn.Calc("B", rX) / Math.pow(this.Sn.Calc("S", rX), 3) / cParamsCanal.G - 1);
+                const rB: Result = this.Sn.Calc("B", rX);
+                if (!rB.ok)
+                        return rB;
+
+                const rS2: Result = this.Sn.Calc("S", rX);
+                if (!rS2.ok)
+                        return rS2;
+
+                const v = (Math.pow(this.Sn.prms.Q.v, 2) * rB.vCalc / Math.pow(rS2.vCalc, 3) / cParamsCanal.G - 1);
+                return new Result(v);
 
-                return Infinity;
+                // return Infinity;
         }
 
         /**
          * Calcul analytique de la dérivée de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcDer(rX: number) {
-                let S = this.Sn.Calc("S");
-                if (S != 0) {
-                        let B = this.Sn.Calc("B");
-                        // L'initialisation à partir de rX a été faite lors de l'appel à CalcFn
-                        let Der = (this.Sn.Calc("dB") * S - 3 * B * B);
-                        return Math.pow(this.Sn.prms.Q.v, 2) / cParamsCanal.G * Der / Math.pow(S, 4);
-                }
+        CalcDer(rX: number): Result {
+                // let S = this.Sn.Calc("S");
+                const rS: Result = this.Sn.Calc("S");
+                if (!rS.ok)
+                        return rS;
+                const S = rS.vCalc;
+                // if (S != 0) {
+                if (S == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_SURFACE_NULLE));
+
+                // let B = this.Sn.Calc("B");
+                const rB: Result = this.Sn.Calc("B");
+                if (!rB.ok)
+                        return rB;
+                const B = rB.vCalc;
+
+                const rDB: Result = this.Sn.Calc("dB");
+                if (!rDB.ok)
+                        return rDB;
 
-                return Infinity;
+                // L'initialisation à partir de rX a été faite lors de l'appel à CalcFn
+                // let Der = (this.Sn.Calc("dB") * S - 3 * B * B);
+                let Der = (rDB.vCalc * S - 3 * B * B);
+                const v = Math.pow(this.Sn.prms.Q.v, 2) / cParamsCanal.G * Der / Math.pow(S, 4);
+                return new Result(v);
+                // }
+
+                // return Infinity;
         }
 }
 
@@ -89,21 +126,56 @@ export class cHautNormale extends acNewton {
          * Calcul de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcFn(rX: number) {
+        CalcFn(rX: number): Result {
                 // Calcul de la fonction
-                return (this.Q - this.Ks * Math.pow(this.Sn.Calc("R", rX), 2 / 3) * this.Sn.Calc("S", rX) * Math.sqrt(this.If));
+                // return (this.Q - this.Ks * Math.pow(this.Sn.Calc("R", rX), 2 / 3) * this.Sn.Calc("S", rX) * Math.sqrt(this.If));
+                const rR: Result = this.Sn.Calc("R", rX);
+                if (!rR.ok)
+                        return rR;
+
+                const rS: Result = this.Sn.Calc("S", rX);
+                if (!rS.ok)
+                        return rS;
+
+                const v = (this.Q - this.Ks * Math.pow(rR.vCalc, 2 / 3) * rS.vCalc * Math.sqrt(this.If));
+                return new Result(v);
         }
 
         /**
          * Calcul analytique de la dérivée de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcDer(rX: number) {
+        CalcDer(rX: number): Result {
+                const rDR: Result = this.Sn.Calc("dR");
+                if (!rDR.ok)
+                        return rDR;
+
+                const rR: Result = this.Sn.Calc("R");
+                if (!rR.ok)
+                        return rR;
+
+                const rS: Result = this.Sn.Calc("S");
+                if (!rS.ok)
+                        return rS;
+
                 // L'initialisation a été faite lors de l'appel à CalcFn
-                let Der = 2 / 3 * this.Sn.Calc("dR") * Math.pow(this.Sn.Calc("R"), -1 / 3) * this.Sn.Calc("S");
-                Der = Der + Math.pow(this.Sn.Calc("R"), 2 / 3) * this.Sn.Calc("B");
+
+                // let Der = 2 / 3 * this.Sn.Calc("dR") * Math.pow(this.Sn.Calc("R"), -1 / 3) * this.Sn.Calc("S");
+                let Der = 2 / 3 * rDR.vCalc * Math.pow(rR.vCalc, -1 / 3) * rS.vCalc;
+
+                const rR2: Result = this.Sn.Calc("R");
+                if (!rR2.ok)
+                        return rR2;
+
+                const rB: Result = this.Sn.Calc("B");
+                if (!rB.ok)
+                        return rB;
+
+                // Der = Der + Math.pow(this.Sn.Calc("R"), 2 / 3) * this.Sn.Calc("B");
+                Der = Der + Math.pow(rR2.vCalc, 2 / 3) * rB.vCalc;
+
                 Der = Der * -this.Ks * Math.sqrt(this.If);
-                return Der;
+                return new Result(Der);
         }
 }
 
@@ -119,7 +191,7 @@ export class cHautCorrespondante extends acNewton {
         /** 
          * 1/S^2 associé au tirant d'eau connu
          */
-        private rS2: number;
+        private _rS2: Result;
 
         /**
          * Section contenant les données de la section avec la hauteur à calculer
@@ -138,31 +210,68 @@ export class cHautCorrespondante extends acNewton {
         constructor(Sn: acSection, maxIter: number, dbg: boolean = false) {
                 super(Sn.prms, maxIter, dbg);
                 this.Y = Sn.prms.Y.v;
-                this.rS2 = Math.pow(Sn.Calc("S"), -2);
+                //                this.rS2 = Math.pow(Sn.Calc("S"), -2);
                 this.Sn = Sn;
+                this.rS2;  // pour initialiser la valeur
                 this.rQ2G = Math.pow(Sn.prms.Q.v, 2) / (2 * cParamsCanal.G);
         }
 
+        private get rS2(): Result {
+                if (this._rS2 == undefined) {
+                        const rS = this.Sn.Calc("S");
+                        if (rS.ok) {
+                                const v = Math.pow(rS.vCalc, -2);
+                                this._rS2 = new Result(v);
+                        }
+                        else
+                                this._rS2 = rS;
+                }
+                return this._rS2;
+        }
+
         /**
          * Calcul de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcFn(rX: number) {
+        CalcFn(rX: number): Result {
+                if (!this.rS2.ok)
+                        return this.rS2;
+
+                const rS: Result = this.Sn.Calc("S", rX);
+                if (!rS.ok)
+                        return rS;
+
                 // Calcul de la fonction
-                return this.Y - rX + (this.rS2 - Math.pow(this.Sn.Calc("S", rX), -2)) * this.rQ2G;
+                // return this.Y - rX + (this.rS2 - Math.pow(this.Sn.Calc("S", rX), -2)) * this.rQ2G;
+                const v = this.Y - rX + (this.rS2.vCalc - Math.pow(rS.vCalc, -2)) * this.rQ2G;
+                return new Result(v);
         }
 
         /**
          * Calcul analytique de la dérivée de la fonction dont on protected function cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcDer(rX: number) {
-                let S = this.Sn.Calc("S");
+        CalcDer(rX: number): Result {
+                // let S = this.Sn.Calc("S");
+                const rS: Result = this.Sn.Calc("S");
+                if (!rS.ok)
+                        return rS;
+                const S = rS.vCalc;
+
                 // L'initialisation a été faite lors de l'appel à CalcFn
-                if (S != 0)
-                        return -1 + 2 * this.rQ2G * this.Sn.Calc("B") / Math.pow(S, 3);
+                // if (S != 0)
+                if (S == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_SURFACE_NULLE));
+
+                const rB: Result = this.Sn.Calc("B");
+                if (!rB.ok)
+                        return rB;
 
-                return Infinity;
+                // return -1 + 2 * this.rQ2G * this.Sn.Calc("B") / Math.pow(S, 3);
+                const v = -1 + 2 * this.rQ2G * rB.vCalc / Math.pow(S, 3);
+                return new Result(v);
+
+                // return Infinity;
         }
 }
 
@@ -177,10 +286,10 @@ export class cHautConjuguee extends acNewton {
         private rQ2: number;
 
         /** Surface hydraulique associée au tirant d'eau connu */
-        private rS: number;
+        private rS: Result;
 
         /** SYg associée au tirant d'eau connu */
-        private rSYg: number;
+        private rSYg: Result;
 
         /**
          * Constructeur de la classe
@@ -199,27 +308,73 @@ export class cHautConjuguee extends acNewton {
          * @param rX Variable dont dépend la fonction
          */
         CalcFn(rX: number) {
-                // Réinitialisation des paramètres hydrauliques de oSn avec l'appel this->oSn->Calc("S',rX)
-                if (this.rS > 0 && this.Sn.Calc("S", rX) > 0) {
-                        let Fn = this.rQ2 * (1 / this.rS - 1 / this.Sn.Calc("S"));
-                        return Fn + cParamsCanal.G * (this.rSYg - this.Sn.Calc("SYg"));
+                if (!this.rS.ok)
+                        return this.rS;
+
+                if (!this.rSYg.ok)
+                        return this.rSYg;
+
+                const rS2: Result = this.Sn.Calc("S", rX);
+                if (!rS2.ok)
+                        return rS2;
+
+                // Réinitialisation des paramètres hydrauliques de this.Sn avec l'appel this.Sn.Calc("S',rX)
+                // if (this.rS > 0 && this.Sn.Calc("S", rX) > 0) {
+                if (this.rS.vCalc > 0 && rS2.vCalc > 0) {
+                        // let Fn = this.rQ2 * (1 / this.rS - 1 / this.Sn.Calc("S"));
+                        const rS3: Result = this.Sn.Calc("S");
+                        if (!rS3.ok)
+                                return rS3;
+
+                        let Fn = this.rQ2 * (1 / this.rS.vCalc - 1 / rS3.vCalc);
+
+                        let rSYg = this.Sn.Calc("SYg");
+                        if (!rSYg.ok)
+                                return rSYg;
+
+                        // return Fn + cParamsCanal.G * (this.rSYg - this.Sn.Calc("SYg"));
+                        const v = Fn + cParamsCanal.G * (this.rSYg.vCalc - rSYg.vCalc);
+                        return new Result(v);
                 }
 
-                return -Infinity;
+                return new Result(new Message(MessageCode.ERROR_SECTION_PERIMETRE_NUL));
+                // return -Infinity;
         }
 
         /**
          * Calcul analytique de la dérivée de la fonction dont on cherche le zéro
          * @param rX Variable dont dépend la fonction
          */
-        CalcDer(rX: number) {
-                let S = this.Sn.Calc("S");
+        CalcDer(rX: number): Result {
+                if (!this.rS.ok)
+                        return this.rS;
+
+                //                let S = this.Sn.Calc("S");
+                const rS2: Result = this.Sn.Calc("S");
+                if (!rS2.ok)
+                        return rS2;
+                const S = rS2.vCalc;
+
                 // L'initialisation a été faite lors de l'appel à CalcFn
-                if (this.rS > 0 && S > 0) {
-                        let Der = this.rQ2 * this.Sn.Calc("dS") * Math.pow(S, -2);
-                        return Der - cParamsCanal.G * this.Sn.Calc("dSYg", rX);
+                // if (this.rS > 0 && S > 0) {
+                if (this.rS.vCalc > 0 && S > 0) {
+                        const rDS: Result = this.Sn.Calc("dS");
+                        if (!rDS.ok)
+                                return rDS;
+
+                        // let Der = this.rQ2 * this.Sn.Calc("dS") * Math.pow(S, -2);
+                        let Der = this.rQ2 * rDS.vCalc * Math.pow(S, -2);
+
+                        const rDYG: Result = this.Sn.Calc("dSYg", rX);
+                        if (!rDYG.ok)
+                                return rDYG;
+
+                        // return Der - cParamsCanal.G * this.Sn.Calc("dSYg", rX);
+                        const v = Der - cParamsCanal.G * rDYG.vCalc;
+                        return new Result(v);
                 }
 
-                return -Infinity;
+                return new Result(new Message(MessageCode.ERROR_SECTION_PERIMETRE_NUL));
+                // return -Infinity;
         }
 }
diff --git a/src/section/newton.ts b/src/section/newton.ts
index f3b76d66cac86dd9b5af65076b95d3497f23d211..78ddacb264669d027edab9e04e4f15ab394ff294 100644
--- a/src/section/newton.ts
+++ b/src/section/newton.ts
@@ -1,10 +1,13 @@
 import { XOR, Debug } from "../base"
 import { cParamsCanal } from "./section_type"
+import { Result } from "../util/result";
+import { Message, MessageCode } from "../util/message";
+import { ResultElement } from "../util/resultelement";
 
 export abstract class acNewton extends Debug {
         protected rTol: number;
         protected Dx: number;
-        private iCpt: number = 0;
+        private iCpt: number;
         private iCptMax: number;
         private rRelax = 1; /// Coefficient de relaxation
         private rFnPrec = 0; /// Mémorisation du Fn précédent pour détecter le changement de signe
@@ -26,15 +29,25 @@ export abstract class acNewton extends Debug {
          * @param rX x
          * @return Calcul de la fonction
          */
-        abstract CalcFn(rX: number): number;
+        abstract CalcFn(rX: number): Result;
 
         /**
          * Calcul de la dérivée f'(x) (peut être redéfini pour calcul analytique)
          * @param rX x
          * @return Calcul de la fonction
          */
-        protected CalcDer(x: number) {
-                return (this.CalcFn(x + this.Dx) - this.CalcFn(x - this.Dx)) / (2 * this.Dx);
+        protected CalcDer(x: number): Result {
+                const rFN1 = this.CalcFn(x - this.Dx)
+                if (!rFN1.ok)
+                        return rFN1;
+
+                const rFN2 = this.CalcFn(x + this.Dx);
+                if (!rFN2.ok)
+                        return rFN2;
+
+                // return (this.CalcFn(x + this.Dx) - this.CalcFn(x - this.Dx)) / (2 * this.Dx);
+                const v = (rFN2.vCalc - rFN1.vCalc) / (2 * this.Dx);
+                return new Result(v);
         }
 
         /**
@@ -42,23 +55,40 @@ export abstract class acNewton extends Debug {
          * @param rFn x
          * @return True si égal, False sinon
          */
-        private FuzzyEqual(rFn: number) {
+        private FuzzyEqual(rFn: number): boolean {
                 return (Math.abs(rFn) < this.rTol);
         }
 
-
         /**
          * Fonction récursive de calcul de la suite du Newton
          * @param rX x
          * @return Solution du zéro de la fonction
          */
-        public Newton(rX: number): number {
+        private doNewton(rX: number): Result {
                 this.iCpt++;
-                var rFn = this.CalcFn(rX);
-                if (this.FuzzyEqual(rFn) || this.iCpt >= this.iCptMax)
-                        return rX;
+                const rFN = this.CalcFn(rX);
+                if (!rFN.ok)
+                        return rFN;
+
+                const rFn = rFN.vCalc;
+                // if (this.FuzzyEqual(rFn) || this.iCpt >= this.iCptMax)
+                //         return new Result(rX);
+
+                if (this.FuzzyEqual(rFn))  // convergence
+                        return new Result(rX);
 
-                var rDer = this.CalcDer(rX);
+                if (this.iCpt >= this.iCptMax) {  // non convergence
+                        const m = new Message(MessageCode.ERROR_NEWTON_NON_CONVERGENCE);
+                        const res = new ResultElement(m);
+                        res.addExtraResult("res", rX);
+                        return new Result(res);
+                }
+
+                const rDER = this.CalcDer(rX);
+                if (!rDER.ok)
+                        return rDER;
+
+                const rDer = rDER.vCalc;
                 if (rDer != 0) {
                         if (XOR(rFn < 0, this.rFnPrec < 0)) {
                                 this.iOscil++;
@@ -73,32 +103,31 @@ export abstract class acNewton extends Debug {
                                 }
                         }
                         this.rFnPrec = rFn;
-                        var Delta = rFn / rDer;
+                        const Delta = rFn / rDer;
                         //2^8 = 2E8 ?
                         while (Math.abs(Delta * this.rRelax) < this.rTol && rFn > 10 * this.rTol && this.rRelax < 2E8) {
                                 // On augmente le coefficicient de relaxation s'il est trop petit
                                 this.rRelax = this.rRelax * 2;
                         }
-                        var rRelax = this.rRelax;
+                        let rRelax = this.rRelax;
                         while (rX - Delta * rRelax <= 0 && rRelax > 1E-4) {
-                                // On diminue le coeficient de relaxation si on passe en négatif
+                                // On diminue le coefficient de relaxation si on passe en négatif
                                 rRelax = rRelax * 0.5; // Mais on ne le mémorise pas pour les itérations suivantes
                         }
                         rX = rX - Delta * rRelax;
                         //this.rDelta = Delta; ???
                         if (rX < 0) { rX = this.rTol; } // Aucune valeur recherchée ne peut être négative ou nulle
-                        return this.Newton(rX);
+                        return this.doNewton(rX);
                 }
 
                 // Echec de la résolution
-                return undefined;
+                // return undefined;
+                const m = new Message(MessageCode.ERROR_NEWTON_DERIVEE_NULLE);
+                return new Result(m);
         }
 
-        /**
-	 * Pour savoir si le Newton a convergé
-	 * @return true si oui, false sinon
-	 */
-        public hasConverged(): boolean {
-                return this.iCpt < this.iCptMax;
+        public Newton(rX: number): Result {
+                this.iCpt = 0;
+                return this.doNewton(rX);
         }
-}
\ No newline at end of file
+}
diff --git a/src/section/section_circulaire.ts b/src/section/section_circulaire.ts
index a9814d6d64abd5ad3a15f3dad804523791786223..942dc121bace709f1c1c86fccb8877428e2a6398 100644
--- a/src/section/section_circulaire.ts
+++ b/src/section/section_circulaire.ts
@@ -1,7 +1,8 @@
 import { ComputeNodeType, ParamDefinition, ParamDomainValue, ParamCalculability } from "../param";
 import { acSection, ParamsSection } from "./section_type";
-import { cLog } from "../util/log";
 import { Message, MessageCode } from "../util/message";
+import { Result } from "../util/result";
+import { randomBytes } from "crypto";
 
 export class ParamsSectionCirc extends ParamsSection {
         private _D: ParamDefinition;          // Diamètre du cercle
@@ -73,20 +74,20 @@ export class cSnCirc extends acSection {
          * Calcul de l'angle Alpha de la surface libre par rapport au fond.
          * @return Alpha
          */
-        private Calc_AlphaY(Y: number, D: number) {
+        private Calc_AlphaY(Y: number, D: number): Result {
                 let alpha = Math.acos(1. - Y / (D / 2.));
-                return Math.min(alpha, Math.PI);
+                return new Result(Math.min(alpha, Math.PI));
         }
 
-        protected Calc_Alpha() {
+        protected Calc_Alpha(): Result {
                 this.debug("Calc_Alpha : bSnFermee " + this.bSnFermee);
 
                 if (this.prms.Y.v <= 0)
-                        return 0;
+                        return new Result(0);
 
                 if (this.isDebordement()) {
                         if (this.bSnFermee)
-                                return Math.PI;
+                                return new Result(Math.PI);
                         return this.Calc_AlphaY(this.prms.YB.v, this.prms.D.v);
                 }
 
@@ -97,51 +98,48 @@ export class cSnCirc extends acSection {
          * Calcul de dérivée de l'angle Alpha de la surface libre par rapport au fond.
          * @return dAlpha
          */
-        protected Calc_dAlpha() {
+        protected Calc_dAlpha(): Result {
                 if (this.prms.Y.v <= 0 || this.isDebordement())
-                        return 0;
+                        return new Result(0);
 
-                return 2. / this.prms.D.v / Math.sqrt(1. - Math.pow(1. - 2. * this.prms.Y.v / this.prms.D.v, 2));
+                const v = 2. / this.prms.D.v / Math.sqrt(1. - Math.pow(1. - 2. * this.prms.Y.v / this.prms.D.v, 2));
+                return new Result(v);
         }
 
-        private Calc_LargeurBerge() {
-                // let d = this.prms.D.v;
-                // let yb = this.prms.YB.v;
-                // if (yb >= d)
-                //         return 0;
-                // return d * Math.sin(this.Calc_AlphaY(yb, d));
+        private Calc_LargeurBerge(): Result {
+
                 let d = this.prms.D.v;
                 let yb = Math.min(this.prms.YB.v, d);
-                // return d * Math.sin(this.Calc_AlphaY(yb, d));
-                let res = d * Math.sin(this.Calc_AlphaY(yb, d));
-                this.debug("Calc_LargeurBerge res=" + res);
-                return res;
+
+                const rAY = this.Calc_AlphaY(yb, d);
+                if (!rAY.ok)
+                        return rAY;
+
+                // let res = d * Math.sin(this.Calc_AlphaY(yb, d));
+                let res = d * Math.sin(rAY.vCalc);
+
+                return new Result(res);
         }
 
         /**
          * Calcul de la largeur au miroir.
          * @return B
          */
-        protected Calc_B() {
-                this.debug("circ.Calc_B() : LargeurBerge " + this.prms.LargeurBerge.toString());
-                this.debug("circ.Calc_B() : D " + this.prms.D.toString());
-                this.debug("circ.Calc_B() : Y " + this.prms.Y.toString());
-
+        protected Calc_B(): Result {
                 if (this.isDebordement()) {
-                        this.debug("circ.Calc_B() : débordement");
-                        //if (!this.prms.LargeurBerge.isDefined())
-                        //      this.prms.LargeurBerge.v = this.Calc_LargeurBerge();
-                        // return super.Calc_B_Debordement();
-
                         return this.Calc_LargeurBerge();
                 }
 
                 this.debug("circ.Calc_B() : PAS débordement");
                 if (this.prms.D.isDefined && this.prms.Y.isDefined) {
-                        //return this.prms.D.v * Math.sin(this.Calc("Alpha"));
-                        let res = this.prms.D.v * Math.sin(this.Calc("Alpha"));
+                        const rAlpha: Result = this.Calc("Alpha");
+                        if (!rAlpha.ok)
+                                return rAlpha;
+
+                        // let res = this.prms.D.v * Math.sin(this.Calc("Alpha"));
+                        let res = this.prms.D.v * Math.sin(rAlpha.vCalc);
                         this.debug("circ.Calc_B() : res=" + res);
-                        return res;
+                        return new Result(res);
                 }
 
                 let e: Message = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
@@ -154,24 +152,59 @@ export class cSnCirc extends acSection {
          * Calcul du périmètre mouillé.
          * @return B
          */
-        protected Calc_P() {
-                if (!this.bSnFermee && this.isDebordement())
+        protected Calc_P(): Result {
+                if (!this.bSnFermee && this.isDebordement()) {
                         // On n'ajoute pas le périmètre dans le cas d'une fente de Preissmann
-                        return this.CalcGeo("P") + super.Calc_P_Debordement(this.valeurYDebordement());
+                        // return this.CalcGeo("P") + super.Calc_P_Debordement(this.valeurYDebordement());
+
+                        const rGeoP: Result = this.CalcGeo("P");
+                        if (!rGeoP.ok)
+                                return rGeoP;
+
+                        const rPDeb: Result = super.Calc_P_Debordement(this.valeurYDebordement());
+                        if (!rPDeb.ok)
+                                return rPDeb;
+
+                        const v = rGeoP.vCalc + rPDeb.vCalc;
+                        return new Result(v);
+                }
+
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
 
-                return this.prms.D.v * this.Calc("Alpha");
+                // return this.prms.D.v * this.Calc("Alpha");
+                const v = this.prms.D.v * rAlpha.vCalc;
+                return new Result(v);
         }
 
         /**
          * Calcul de la surface mouillée.
          * @return S
          */
-        protected Calc_S() {
-                if (!this.bSnFermee && this.isDebordement())
-                        return this.CalcGeo("S") + super.Calc_S_Debordement(this.valeurYDebordement());
+        protected Calc_S(): Result {
+                if (!this.bSnFermee && this.isDebordement()) {
+                        // return this.CalcGeo("S") + super.Calc_S_Debordement(this.valeurYDebordement());
+                        const rGeoS: Result = this.CalcGeo("S");
+                        if (!rGeoS.ok)
+                                return rGeoS;
+
+                        const rSDeb: Result = super.Calc_S_Debordement(this.valeurYDebordement());
+                        if (!rSDeb.ok)
+                                return rSDeb;
+
+                        const v = rGeoS.vCalc + rSDeb.vCalc;
+                        return new Result(v);
+                }
 
-                let alpha = this.Calc("Alpha");
-                return Math.pow(this.prms.D.v, 2) / 4 * (alpha - Math.sin(alpha) * Math.cos(alpha));
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                // return Math.pow(this.prms.D.v, 2) / 4 * (alpha - Math.sin(alpha) * Math.cos(alpha));
+                const alpha = rAlpha.vCalc;
+                const v = Math.pow(this.prms.D.v, 2) / 4 * (alpha - Math.sin(alpha) * Math.cos(alpha));
+                return new Result(v);
         }
 
 
@@ -179,22 +212,38 @@ export class cSnCirc extends acSection {
          * Calcul de dérivée du périmètre hydraulique par rapport au tirant d'eau.
          * @return dP
          */
-        protected Calc_dP() {
+        protected Calc_dP(): Result {
                 if (!this.bSnFermee && this.isDebordement())
                         return super.Calc_dP_Debordement();
 
-                return this.prms.D.v * this.Calc("dAlpha");
+                const rDAlpha: Result = this.Calc("dAlpha");
+                if (!rDAlpha.ok)
+                        return rDAlpha;
+
+                // return this.prms.D.v * this.Calc("dAlpha");
+                const v = this.prms.D.v * rDAlpha.vCalc;
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée de la largeur au miroir par rapport au tirant d'eau.
          * @return dB
          */
-        protected Calc_dB() {
+        protected Calc_dB(): Result {
                 if (this.isDebordement())
                         return super.Calc_dB_Debordement();
 
-                return this.prms.D.v * this.Calc("dAlpha") * Math.cos(this.Calc("Alpha"));
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                const rDAlpha: Result = this.Calc("dAlpha");
+                if (!rDAlpha.ok)
+                        return rDAlpha;
+
+                // return this.prms.D.v * this.Calc("dAlpha") * Math.cos(this.Calc("Alpha"));
+                const v = this.prms.D.v * rDAlpha.vCalc * Math.cos(rAlpha.vCalc);
+                return new Result(v);
         }
 
         /**
@@ -202,11 +251,18 @@ export class cSnCirc extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_SYg(): number {
-                let alpha = this.Calc("Alpha");
+        protected Calc_SYg(): Result {
+                // let alpha = this.Calc("Alpha");
+
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                const alpha = rAlpha.vCalc;
+
                 let SYg = Math.sin(alpha) - Math.pow(Math.sin(alpha), 3) / 3 - alpha * Math.cos(alpha);
                 SYg = Math.pow(this.prms.D.v, 3) / 8 * SYg;
-                return SYg;
+                return new Result(SYg);
         }
 
         /**
@@ -214,15 +270,27 @@ export class cSnCirc extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_dSYg() {
-                let alpha = this.Calc("Alpha");
-                let dAlpha = this.Calc("dAlpha");
+        protected Calc_dSYg(): Result {
+                // let alpha = this.Calc("Alpha");
+                // let dAlpha = this.Calc("dAlpha");
+
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                const rDAlpha: Result = this.Calc("dAlpha");
+                if (!rDAlpha.ok)
+                        return rDAlpha;
+
+                const alpha = rAlpha.vCalc;
+                const dAlpha = rDAlpha.vCalc;
+
                 var cos = Math.cos(alpha);
                 var sin = Math.sin(alpha);
                 var SYg = dAlpha * cos;
                 SYg += - dAlpha * cos * Math.pow(sin, 2);
                 SYg += - dAlpha * cos + alpha * dAlpha * sin;
                 SYg = 3 * Math.pow(this.prms.D.v, 3) / 8 * SYg;
-                return SYg;
+                return new Result(SYg);
         }
 }
\ No newline at end of file
diff --git a/src/section/section_puissance.ts b/src/section/section_puissance.ts
index 8105e14f5fe185e205e0ad743d768e62a6ce4e2c..5179b9db26c148a4ab8e4ec3841925bffe6bf1c4 100644
--- a/src/section/section_puissance.ts
+++ b/src/section/section_puissance.ts
@@ -1,5 +1,6 @@
 import { ComputeNodeType, ParamDefinition, ParamDomain, ParamDomainValue, ParamCalculability } from "../param";
 import { acSection, ParamsSection } from "./section_type";
+import { Result } from "../util/result";
 
 /**
  * Paramètres de la section parabolique ou "puissance"
@@ -47,28 +48,40 @@ export class cSnPuiss extends acSection {
          * Calcul de Lambda (mais on garde la routine Alpha commune avec la section circulaire)
          * @return Lambda
          */
-        protected Calc_Alpha(): number {
-                return this.prms.LargeurBerge.v / Math.pow(this.prms.YB.v, this.prms.k.v);
+        protected Calc_Alpha(): Result {
+                const v = this.prms.LargeurBerge.v / Math.pow(this.prms.YB.v, this.prms.k.v);
+                return new Result(v);
         }
 
         /**
          * Calcul de la largeur au miroir.
          * @return B
          */
-        protected Calc_B(): number {
+        protected Calc_B(): Result {
                 if (this.prms.Y.v >= this.prms.YB.v)
-                        return this.prms.LargeurBerge.v;
+                        return new Result(this.prms.LargeurBerge.v);
 
-                return this.Calc("Alpha") * Math.pow(this.prms.Y.v, this.prms.k.v);
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                // return this.Calc("Alpha") * Math.pow(this.prms.Y.v, this.prms.k.v);
+                const v = rAlpha.vCalc * Math.pow(this.prms.Y.v, this.prms.k.v);
+                return new Result(v);
         }
 
         /**
          * Calcul du périmètre mouillé.
          * @return B
          */
-        protected Calc_P(): number {
+        protected Calc_P(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
                 var n = 100; /// Le nombre de partie pour le calcul de l'intégrale
-                var Lambda2 = Math.pow(this.Calc("Alpha"), 2);
+                // var Lambda2 = Math.pow(this.Calc("Alpha"), 2);
+                var Lambda2 = Math.pow(rAlpha.vCalc, 2);
                 var P = 0; /// Le périmètre à calculer
                 var Previous = 0;
                 for (var i = 1; i <= n; i++) {
@@ -77,34 +90,51 @@ export class cSnPuiss extends acSection {
                         Previous = Current;
                 }
                 P *= 2;
-                return P;
+                return new Result(P);
         }
 
         /**
          * Calcul de la surface mouillée.
          * @return S
          */
-        protected Calc_S(): number {
+        protected Calc_S(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
                 let k = this.prms.k.v;
-                return this.Calc("Alpha") * Math.pow(this.prms.Y.v, k + 1) / (k + 1);
+                const v = rAlpha.vCalc * Math.pow(this.prms.Y.v, k + 1) / (k + 1);
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée du périmètre hydraulique par rapport au tirant d'eau.
          * @return dP
          */
-        protected Calc_dP(): number {
+        protected Calc_dP(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
                 let k = this.prms.k.v;
-                return 2 * Math.sqrt(1 + Math.pow(k * this.Calc("Alpha") / 2, 2) * Math.pow(this.prms.Y.v, 2 * (k - 1)));
+                // return 2 * Math.sqrt(1 + Math.pow(k * this.Calc("Alpha") / 2, 2) * Math.pow(this.prms.Y.v, 2 * (k - 1)));
+                const v = 2 * Math.sqrt(1 + Math.pow(k * rAlpha.vCalc / 2, 2) * Math.pow(this.prms.Y.v, 2 * (k - 1)));
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée de la largeur au miroir par rapport au tirant d'eau.
          * @return dB
          */
-        protected Calc_dB(): number {
+        protected Calc_dB(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
                 let k = this.prms.k.v;
-                return this.Calc("Alpha") * k * Math.pow(this.prms.Y.v, k - 1);
+                // return this.Calc("Alpha") * k * Math.pow(this.prms.Y.v, k - 1);
+                const v = rAlpha.vCalc * k * Math.pow(this.prms.Y.v, k - 1);
+                return new Result(v);
         }
 
         /**
@@ -112,9 +142,15 @@ export class cSnPuiss extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_SYg(): number {
+        protected Calc_SYg(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
                 let k = this.prms.k.v;
-                return this.Calc("Alpha") * Math.pow(this.prms.Y.v, k + 2) / ((k + 1) * (k + 2));
+                // return this.Calc("Alpha") * Math.pow(this.prms.Y.v, k + 2) / ((k + 1) * (k + 2));
+                const v = rAlpha.vCalc * Math.pow(this.prms.Y.v, k + 2) / ((k + 1) * (k + 2));
+                return new Result(v);
         }
 
         /**
@@ -122,10 +158,20 @@ export class cSnPuiss extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_dSYg(): number {
+        protected Calc_dSYg(): Result {
+                const rAlpha: Result = this.Calc("Alpha");
+                if (!rAlpha.ok)
+                        return rAlpha;
+
+                const rDAlpha: Result = this.Calc("dAlpha");
+                if (!rDAlpha.ok)
+                        return rDAlpha;
+
                 let k = this.prms.k.v;
                 let Y = this.prms.Y.v;
-                let SYg = this.Calc("dAlpha") * Math.pow(Y, k + 2) + this.Calc("Alpha") * Math.pow(Y, k + 1) * (k + 2);
-                return SYg / ((k + 1) * (k + 2));
+                // let SYg = this.Calc("dAlpha") * Math.pow(Y, k + 2) + this.Calc("Alpha") * Math.pow(Y, k + 1) * (k + 2);
+                let SYg = rDAlpha.vCalc * Math.pow(Y, k + 2) + rAlpha.vCalc * Math.pow(Y, k + 1) * (k + 2);
+                const v = SYg / ((k + 1) * (k + 2));
+                return new Result(v);
         }
 }
\ No newline at end of file
diff --git a/src/section/section_rectang.ts b/src/section/section_rectang.ts
index 67299a61ad8b4aa6d34a3e7a5212fe3e488a99a0..b566b23b545b0aadcef8716fd4d9bda6c7d4076c 100644
--- a/src/section/section_rectang.ts
+++ b/src/section/section_rectang.ts
@@ -1,6 +1,6 @@
 import { acSection, ParamsSection } from "./section_type";
 import { ComputeNodeType } from "../param";
-import { cLog } from "../util/log";
+import { Result } from "../util/result";
 
 export class ParamsSectionRectang extends ParamsSection {
         constructor(rY: number, rLargeurFond: number, rKs: number, rQ: number, rIf: number, rPrec: number, rYB: number,
@@ -27,23 +27,29 @@ export class cSnRectang extends acSection {
          * Calcul du périmètre mouillé
          * @return Périmètre mouillé (m)
          */
-        protected Calc_P(): number {
-                return this.prms.LargeurBerge.v + super.Calc_P_Debordement(this.prms.Y.v);
+        protected Calc_P(): Result {
+                // return this.prms.LargeurBerge.v + super.Calc_P_Debordement(this.prms.Y.v);
+                const rPDeb: Result = super.Calc_P_Debordement(this.prms.Y.v);
+                if (!rPDeb.ok)
+                        return rPDeb;
+
+                const v = this.prms.LargeurBerge.v + rPDeb.vCalc;
+                return new Result(v);
         }
 
-        protected Calc_dP(): number {
+        protected Calc_dP(): Result {
                 return super.Calc_dP_Debordement();
         }
 
-        protected Calc_B(): number {
+        protected Calc_B(): Result {
                 return super.Calc_B_Debordement();
         }
 
-        protected Calc_dB(): number {
+        protected Calc_dB(): Result {
                 return super.Calc_dB_Debordement();
         }
 
-        protected Calc_S(): number {
+        protected Calc_S(): Result {
                 return super.Calc_S_Debordement(this.prms.Y.v);
         }
 
@@ -51,7 +57,14 @@ export class cSnRectang extends acSection {
          * Calcul du tirant d'eau conjugué avec la formule analytique pour la section rectangulaire
          * @return tirant d'eau conjugué
          */
-        protected CalcYco(): number {
-                return this.prms.Y.v * (Math.sqrt(1 + 8 * Math.pow(this.Calc("Fr"), 2)) - 1) / 2;
+        protected CalcYco(): Result {
+                // return this.prms.Y.v * (Math.sqrt(1 + 8 * Math.pow(this.Calc("Fr"), 2)) - 1) / 2;
+
+                const rFR: Result = this.Calc("Fr");
+                if (!rFR.ok)
+                        return rFR;
+
+                const v = this.prms.Y.v * (Math.sqrt(1 + 8 * Math.pow(rFR.vCalc, 2)) - 1) / 2;
+                return new Result(v);
         }
 }
\ No newline at end of file
diff --git a/src/section/section_trapez.ts b/src/section/section_trapez.ts
index 4bf29e2ad2a460edbb987d954fefa481fa9f6da7..f415776cb960cf1e5384e4ce6d3c9efcd23237a4 100644
--- a/src/section/section_trapez.ts
+++ b/src/section/section_trapez.ts
@@ -1,7 +1,6 @@
 import { ComputeNodeType, ParamDefinition, ParamDomainValue, ParamCalculability } from "../param";
 import { acSection, ParamsSection } from "./section_type";
-import { cLog } from "../util/log";
-
+import { Result } from "../util/result";
 
 export class ParamsSectionTrapez extends ParamsSection {
         private _LargeurFond: ParamDefinition; // Largeur au fond
@@ -56,69 +55,97 @@ export class cSnTrapez extends acSection {
                 return this.prms.Y.v > this.prms.YB.v;
         }
 
-        // Calc_B(bBerge = false): number {
-        protected Calc_B(): number {
-                // if (!bBerge && this.isDebordement())
-                if (this.isDebordement())
-                        //return this.prms.LargeurBerge.v;
-                        return this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.YB.v;
+        protected Calc_B(): Result {
+                if (this.isDebordement()) {
+                        const v = this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.YB.v;
+                        return new Result(v);
+                }
 
-                return this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.Y.v;
+                const v = this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.Y.v;
+                return new Result(v);
         }
 
         /**
          * Calcul du périmètre mouillé
          * @return Périmètre mouillé (m)
          */
-        protected Calc_P(): number {
-                if (this.isDebordement())
-                        return this.CalcGeo("P") + super.Calc_P_Debordement(this.prms.Y.v - this.prms.YB.v);
+        protected Calc_P(): Result {
+                if (this.isDebordement()) {
+                        // return this.CalcGeo("P") + super.Calc_P_Debordement(this.prms.Y.v - this.prms.YB.v);
+
+                        const rGeoP: Result = this.CalcGeo("P");
+                        if (!rGeoP.ok)
+                                return rGeoP;
 
-                return this.prms.LargeurFond.v + 2 * Math.sqrt(1 + Math.pow(this.prms.Fruit.v, 2)) * this.prms.Y.v;
+                        const rPDeb: Result = super.Calc_P_Debordement(this.prms.Y.v - this.prms.YB.v);
+                        if (!rPDeb.ok)
+                                return rPDeb;
+
+                        const v = rGeoP.vCalc + rPDeb.vCalc;
+                        return new Result(v);
+                }
+
+                const v = this.prms.LargeurFond.v + 2 * Math.sqrt(1 + Math.pow(this.prms.Fruit.v, 2)) * this.prms.Y.v;
+                return new Result(v);
         }
 
         /**
          * Calcul de la surface mouillée
          * @return Surface mouillée (m2)
          */
-        protected Calc_S(): number {
-                if (this.isDebordement())
-                        return this.CalcGeo("S") + super.Calc_S_Debordement(this.prms.Y.v - this.prms.YB.v);
-
-                return this.prms.Y.v * (this.prms.LargeurFond.v + this.prms.Fruit.v * this.prms.Y.v);
+        protected Calc_S(): Result {
+                if (this.isDebordement()) {
+                        // return this.CalcGeo("S") + super.Calc_S_Debordement(this.prms.Y.v - this.prms.YB.v);
+                        const rGeoS: Result = this.CalcGeo("S");
+                        if (!rGeoS.ok)
+                                return rGeoS;
+
+                        const rSDeb: Result = super.Calc_S_Debordement(this.prms.Y.v - this.prms.YB.v);
+                        if (!rSDeb.ok)
+                                return rSDeb;
+
+                        const v = rGeoS.vCalc + rSDeb.vCalc;
+                        return new Result(v);
+                }
+
+                const v = this.prms.Y.v * (this.prms.LargeurFond.v + this.prms.Fruit.v * this.prms.Y.v);
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée de la surface hydraulique par rapport au tirant d'eau.
          * @return dS
          */
-        protected Calc_dS(): number {
+        protected Calc_dS(): Result {
                 if (this.isDebordement())
                         return super.Calc_dS();
 
-                return this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.Y.v;
+                const v = this.prms.LargeurFond.v + 2 * this.prms.Fruit.v * this.prms.Y.v;
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée du périmètre hydraulique par rapport au tirant d'eau.
          * @return dP
          */
-        protected Calc_dP(): number {
+        protected Calc_dP(): Result {
                 if (this.isDebordement())
                         return super.Calc_dP_Debordement();
 
-                return 2 * Math.sqrt(1 + this.prms.Fruit.v * this.prms.Fruit.v);
+                const v = 2 * Math.sqrt(1 + this.prms.Fruit.v * this.prms.Fruit.v);
+                return new Result(v);
         }
 
         /**
          * Calcul de dérivée de la largeur au miroir par rapport au tirant d'eau.
          * @return dB
          */
-        protected Calc_dB(): number {
+        protected Calc_dB(): Result {
                 if (this.isDebordement())
                         return super.Calc_dB_Debordement();
 
-                return 2 * this.prms.LargeurFond.v * this.prms.Fruit.v;
+                const v = 2 * this.prms.LargeurFond.v * this.prms.Fruit.v;
+                return new Result(v);
         }
 
         /**
@@ -126,8 +153,9 @@ export class cSnTrapez extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_SYg(): number {
-                return (this.prms.LargeurFond.v / 2 + this.prms.Fruit.v * this.prms.Y.v / 3) * Math.pow(this.prms.Y.v, 2);
+        protected Calc_SYg(): Result {
+                const v = (this.prms.LargeurFond.v / 2 + this.prms.Fruit.v * this.prms.Y.v / 3) * Math.pow(this.prms.Y.v, 2);
+                return new Result(v);
         }
 
         /**
@@ -135,9 +163,9 @@ export class cSnTrapez extends acSection {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_dSYg(): number {
+        protected Calc_dSYg(): Result {
                 var SYg = this.prms.Fruit.v / 3 * Math.pow(this.prms.Y.v, 2);
                 SYg += (this.prms.LargeurFond.v / 2 + this.prms.Fruit.v * this.prms.Y.v / 3) * 2 * this.prms.Y.v;
-                return SYg;
+                return new Result(SYg);
         }
 }
\ No newline at end of file
diff --git a/src/section/section_type.ts b/src/section/section_type.ts
index 25b540edb6ab5b11a78520405956e876f54f2a87..1e910e39e41c2237ee4fac5f05150342d85eb76f 100644
--- a/src/section/section_type.ts
+++ b/src/section/section_type.ts
@@ -1,8 +1,7 @@
-import { XOR } from "../base";
-import { cLog } from "../util/log";
 import { MessageCode, Message } from "../util/message";
 import { ComputeNodeType, ComputeNode, ParamDefinition, ParamDomainValue, ParamCalculability, ParamsEquation } from "../param";
 import { cHautCritique, cHautNormale, cHautCorrespondante, cHautConjuguee } from "./hauteur";
+import { Result } from "../util/result";
 
 /**
  * Gestion des Paramètres du canal (hors section)
@@ -21,7 +20,7 @@ export abstract class cParamsCanal extends ParamsEquation {
                 super();
                 this._Ks = new ParamDefinition(nodeType, 'Ks', ParamDomainValue.POS, rKs);
                 this._Q = new ParamDefinition(nodeType, 'Q', ParamDomainValue.POS_NULL, rQ);
-                this._If = new ParamDefinition(nodeType, 'If', ParamDomainValue.POS, rIf);
+                this._If = new ParamDefinition(nodeType, 'If', ParamDomainValue.ANY, rIf);
                 this._Prec = new ParamDefinition(nodeType, 'Prec', ParamDomainValue.POS, rPrec);
                 this._iPrec = new ParamDefinition(nodeType, 'iPrec', ParamDomainValue.ANY, Math.round(-Math.log(rPrec) / Math.log(10)));
                 this._YB = new ParamDefinition(nodeType, 'YB', ParamDomainValue.POS, rYB);
@@ -75,13 +74,6 @@ export abstract class cParamsCanal extends ParamsEquation {
         get YB(): ParamDefinition {
                 return this._YB;
         }
-
-        // /**
-        //  * Longueur du bief
-        //  */
-        // get Long() {
-        //         return this._Long;
-        // }
 }
 
 
@@ -121,9 +113,7 @@ export abstract class ParamsSection extends cParamsCanal {
 export abstract class acSection extends ComputeNode {
         [key: string]: any; // pour pouvoir faire this['methode]();
 
-        public HautCritique: number;  /// Tirant d'eau critique
-        public HautNormale: number;   /// Tirant d'eau normal
-        protected oLog: cLog; /// Pour l'affichage du journal de calcul
+        private _hautCritique: Result;  // Tirant d'eau critique
 
         /**
          * true si la section est fermée (on considère alors qu'il existe une fente de Preissmann)
@@ -154,19 +144,27 @@ export abstract class acSection extends ComputeNode {
          */
         private _newtonMaxIter: number = 50;
 
+        /**
+         * flag de débuggage pour Newton
+         */
+        private _newtonDbg: boolean;
+
+        private _indentCalc: number = -1;
+
         /**
          * Construction de la classe.
          * Calcul des hauteurs normale et critique
          */
         constructor(prms: ParamsSection, dbg: boolean = false) {
                 super(prms, dbg);
-                this.oLog = new cLog();
 
                 // this._v = oP.v;  // copie la référence au tableau
                 // this.prms.Y.v = 0;
                 // this.prms.LargeurBerge.v = 0;
 
                 // this.CalcGeo("B");  // à ce point, il manque des paramètres pour certaines sections (ex : fruit pour trapèze)
+
+                this._newtonDbg = dbg;
         }
 
         protected setParametersCalculability() {
@@ -192,8 +190,8 @@ export abstract class acSection extends ComputeNode {
                 this._newtonMaxIter = n;
         }
 
-        public get log(): cLog {
-                return this.oLog;
+        public get HautCritique() {
+                return this._hautCritique;
         }
 
         /**
@@ -204,14 +202,9 @@ export abstract class acSection extends ComputeNode {
                 this.debug("reset(" + bGeo + ")");
                 this.arCalc = {};
                 if (bGeo) {
-                        // this.debug("reset Geo");
                         this.arCalcGeo = {};
                         this.bSnFermee = false;
                 }
-                // this.debug("reset arCalc :");
-                // this.debug(this.arCalc);
-                // this.debug("reset arCalcGeo :");
-                // this.debug(this.arCalcGeo);
         }
 
         /**
@@ -232,13 +225,25 @@ export abstract class acSection extends ComputeNode {
                 }
         }
 
+        private calcIndent(): string {
+                let res = "";
+                for (let i = 0; i < this._indentCalc; i++)
+                        res += "  ";
+                return res;
+        }
+
+        public debug(m: string) {
+                super.debug(this.calcIndent() + m);
+        }
+
         /**
          * Calcul des données à la section
          * @param sDonnee Clé de la donnée à calculer (voir this->arCalc)
          * @param rY valeur de Y à utiliser
          * @return la donnée calculée
          */
-        public Calc(sDonnee: string, rY: number = undefined): number {
+        public Calc(sDonnee: string, rY: number = undefined): Result {
+                this._indentCalc++;
                 this.debug("in Calc(" + sDonnee + ", rY=" + rY + ") old " + sDonnee + "=" + this.arCalc[sDonnee]);
                 this.debug("this.Y=" + this.prms.Y.toString());
 
@@ -251,7 +256,14 @@ export abstract class acSection extends ComputeNode {
                         // La donnée a besoin d'être calculée
                         switch (sDonnee) {
                                 case 'I-J': // Variation linéaire de l'énergie spécifique (I-J) en m/m
-                                        this.arCalc[sDonnee] = this.prms.If.v - this.Calc("J");
+                                        // this.arCalc[sDonnee] = this.prms.If.v - this.Calc("J");
+                                        var rJ: Result = this.Calc("J");
+                                        if (rJ.ok) {
+                                                this.arCalc[sDonnee] = this.prms.If.v - rJ.vCalc;
+                                                var res = new Result(this.arCalc[sDonnee]);
+                                        }
+                                        else
+                                                res = rJ;
                                         break;
 
                                 default:
@@ -263,18 +275,23 @@ export abstract class acSection extends ComputeNode {
                                            une valeur bien définie
                                            !!!!!
                                          */
-                                        let res: number = this[methode]();
-                                        this.arCalc[sDonnee] = res;
+                                        res = this[methode]();
+                                        if (res.ok)
+                                                this.arCalc[sDonnee] = res.vCalc;
                                         break;
                         }
                         this.debug("Calc(" + sDonnee + ") resultat -> " + this.arCalc[sDonnee]);
                 }
-                else
+                else {
                         this.debug("Calc(" + sDonnee + ") cache= " + this.arCalc[sDonnee]);
+                        res = new Result(this.arCalc[sDonnee]);
+                }
+                this._indentCalc--;
 
                 this.debug('this.Y=' + this.prms.Y.toString());
 
-                return this.arCalc[sDonnee];
+                // return this.arCalc[sDonnee];
+                return res;
         }
 
         /**
@@ -282,7 +299,8 @@ export abstract class acSection extends ComputeNode {
          * @param sDonnee Clé de la donnée à calculer (voir this->arCalcGeo)
          * @return la donnée calculée
          */
-        protected CalcGeo(sDonnee: string): number {
+        protected CalcGeo(sDonnee: string): Result {
+                this._indentCalc++;
                 this.debug("in CalcGeo(" + sDonnee + ") old " + sDonnee + "=" + this.arCalcGeo[sDonnee]);
                 this.debug("this.Y=" + this.prms.Y.toString());
 
@@ -297,62 +315,74 @@ export abstract class acSection extends ComputeNode {
                         this.prms.Y.v = this.prms.YB.v;
                         switch (sDonnee) {
                                 case "B": // Largeur aux berges
-                                        this.arCalcGeo[sDonnee] = this.Calc_B();
-                                        if (this.arCalcGeo[sDonnee] < this.prms.YB.v / 100) {
-                                                // Section fermée
-                                                this.bSnFermee = true;
-                                                // On propose une fente de Preissmann égale à 1/100 de la hauteur des berges
-                                                this.arCalcGeo[sDonnee] = this.prms.YB.v / 100;
+                                        // this.arCalcGeo[sDonnee] = this.Calc_B();
+                                        var res: Result = this.Calc_B();
+                                        if (res.ok) {
+                                                this.arCalcGeo[sDonnee] = res.vCalc;
+                                                if (this.arCalcGeo[sDonnee] < this.prms.YB.v / 100) {
+                                                        // Section fermée
+                                                        this.bSnFermee = true;
+                                                        // On propose une fente de Preissmann égale à 1/100 de la hauteur des berges
+                                                        this.arCalcGeo[sDonnee] = this.prms.YB.v / 100;
+                                                }
+                                                this.prms.LargeurBerge.v = this.arCalcGeo[sDonnee];
                                         }
-                                        this.prms.LargeurBerge.v = this.arCalcGeo[sDonnee];
                                         break;
 
                                 default:
                                         let methode = "Calc_" + sDonnee;
                                         // this.arCalcGeo[sDonnee] = this[methode]();
-                                        let res = this[methode]();
-                                        this.arCalcGeo[sDonnee] = res;
+                                        res = this[methode]();
+                                        if (res.ok)
+                                                this.arCalcGeo[sDonnee] = res.vCalc;
                                         break;
                         }
                         this.Swap(false); // On restitue les données hydrauliques en cours
                         this.debug("CalcGeo(" + sDonnee + ") resultat -> " + this.arCalcGeo[sDonnee]);
                 }
-                else
+                else {
                         this.debug("CalcGeo(" + sDonnee + ") cache= " + this.arCalcGeo[sDonnee]);
+                        res = new Result(this.arCalcGeo[sDonnee]);
+                }
 
-                this.debug('this.Y=' + this.prms.Y.toString());
+                // this.debug('this.Y=' + this.prms.Y.toString());
 
-                return this.arCalcGeo[sDonnee];
+                this._indentCalc--;
+
+                // return this.arCalcGeo[sDonnee];
+                return res;
         }
 
         /**
          * Calcul de la surface hydraulique.
          * @return La surface hydraulique
          */
-        protected abstract Calc_S(): number;
+        protected abstract Calc_S(): Result;
 
 
-        protected Calc_dS(): number {
+        protected Calc_dS(): Result {
                 return this.Calc("B"); // largeur au miroir
         }
 
         /**
-         *  calcul de la surface hydraulique en cas de débordement
-         * @param Y hauteur d'eau au dela de la berge
+         * Calcul de la surface hydraulique en cas de débordement
+         * @param Y hauteur d'eau au delà de la berge
          **/
-        protected Calc_S_Debordement(Y: number): number {
-                // this.debug('section->CalcS(rY=' + Y + ') LargeurBerge=' + this.prms.LargeurBerge);
+        protected Calc_S_Debordement(Y: number): Result {
                 this.debug('section->CalcS(rY=' + Y + ') LargeurBerge=' + this.CalcGeo("B"));
-                // return Y * this.prms.LargeurBerge.v;
-                return Y * this.CalcGeo("B");
+                // return Y * this.CalcGeo("B");
+                let rB: Result = this.CalcGeo("B");
+                if (!rB.ok)
+                        return rB;
+
+                return new Result(Y * rB.vCalc);
         }
 
         /**
          * Calcul de la dérivée surface hydraulique en cas de débordement
          * @return La dérivée de la surface hydraulique en cas de débordement
          */
-        private Calc_dS_Debordement(): number {
-                // return this.prms.LargeurBerge.v;
+        private Calc_dS_Debordement(): Result {
                 return this.CalcGeo("B");
         }
 
@@ -360,253 +390,412 @@ export abstract class acSection extends ComputeNode {
          * Calcul du périmètre hydraulique.
          * @return Le périmètre hydraulique
          */
-        protected abstract Calc_P(): number;
+        protected abstract Calc_P(): Result;
 
         /**
          * Calcul du périmètre hydraulique en cas de débordement
          * @param Y hauteur d'eau au dela de la berge
          */
-        protected Calc_P_Debordement(Y: number): number {
-                return 2 * Y;
+        protected Calc_P_Debordement(Y: number): Result {
+                return new Result(2 * Y);
         }
 
         /**
          * Calcul de dérivée du périmètre hydraulique par rapport au tirant d'eau.
          * @return dP
          */
-        protected abstract Calc_dP(): number;
+        protected abstract Calc_dP(): Result;
 
         /**
          * Calcul de dérivée du périmètre hydraulique par rapport au tirant d'eau en cas de débordement
          * @return la dérivée du périmètre hydraulique par rapport au tirant d'eau en cas de débordement
          */
-        protected Calc_dP_Debordement(): number {
-                return 2;
+        protected Calc_dP_Debordement(): Result {
+                return new Result(2);
         }
 
         /**
          * Calcul du rayon hydraulique.
          * @return Le rayon hydraulique
          */
-        private Calc_R(): number {
-                let P = this.Calc("P");
-                if (P != 0)
-                        return this.Calc("S") / P;
+        private Calc_R(): Result {
+                // let P = this.Calc("P");
+                let rP: Result = this.Calc("P");
+                if (!rP.ok)
+                        return rP;
 
-                return Infinity;
+                // if (P != 0)
+                if (rP.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_PERIMETRE_NUL));
+                // return this.Calc("S") / P;
+
+                let rS = this.Calc("S");
+                if (!rS.ok)
+                        return rS;
+
+                return new Result(rS.vCalc / rP.vCalc);
+
+                // return Infinity;
         }
 
         /**
          * Calcul de dérivée du rayon hydraulique par rapport au tirant d'eau.
          * @return dR
          */
-        private Calc_dR(): number {
-                let P = this.Calc("P");
-                if (P != 0)
-                        return ((this.Calc("B") * P - this.Calc("S") * this.Calc("dP")) / Math.pow(P, 2));
+        private Calc_dR(): Result {
+                // let P = this.Calc("P");
+                const rP: Result = this.Calc("P");
+
+                if (!rP.ok)
+                        return rP;
+
+                // if (P != 0)
+                if (rP.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_PERIMETRE_NUL));
 
-                return 0;
+                //return ((this.Calc("B") * P - this.Calc("S") * this.Calc("dP")) / Math.pow(P, 2));
+                const rB: Result = this.Calc("B");
+                if (!rB.ok)
+                        return rB;
+
+                const rS: Result = this.Calc("S");
+                if (!rS.ok)
+                        return rS;
+
+                const rDP: Result = this.Calc("dP");
+                if (!rDP.ok)
+                        return rDP;
+
+                const v = ((rB.vCalc * rP.vCalc - rS.vCalc * rDP.vCalc) / Math.pow(rP.vCalc, 2));
+                return new Result(v);
+
+                // return 0;
         }
 
         /**
          * Calcul de la largeur au miroir.
          * @return La largeur au miroir
          */
-        protected abstract Calc_B(): number;
+        protected abstract Calc_B(): Result;
 
 
         /**
            * Calcul de la largeur au miroir en cas de débordement
            * @return La largeur au miroir en cas de débordement
            */
-        protected Calc_B_Debordement(): number {
-                return this.prms.LargeurBerge.v;
-                // return this.CalcGeo("B");
+        protected Calc_B_Debordement(): Result {
+                // return this.prms.LargeurBerge.v;
+                return new Result(this.prms.LargeurBerge.v);
         }
 
         /**
           * Calcul de dérivée de la largeur au miroir par rapport au tirant d'eau.
           * @return dB
           */
-        protected abstract Calc_dB(): number;
+        protected abstract Calc_dB(): Result;
 
         /**
          * Calcul de dérivée de la largeur au miroir par rapport au tirant d'eau en cas de débordement
          * @return la dérivée de la largeur au miroir par rapport au tirant d'eau en cas de débordement
          */
-        protected Calc_dB_Debordement(): number {
-                return 0;
+        protected Calc_dB_Debordement(): Result {
+                return new Result(0);
         }
 
         /**
          * Calcul de la perte de charge par la formule de Manning-Strickler.
          * @return La perte de charge
          */
-        private Calc_J(): number {
-                let R = this.Calc("R");
-                if (R != 0)
-                        return Math.pow(this.Calc("V") / this.prms.Ks.v, 2) / Math.pow(R, 4 / 3);
+        private Calc_J(): Result {
+                // let R = this.Calc("R");
+                let rR: Result = this.Calc("R");
+                if (!rR.ok)
+                        return rR;
 
-                return Infinity;
+                // if (R != 0)
+                if (rR.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_RAYON_NUL));
+
+                // return Math.pow(this.Calc("V") / this.prms.Ks.v, 2) / Math.pow(R, 4 / 3);
+                const rV: Result = this.Calc("V");
+                if (!rV.ok)
+                        return rV;
+
+                const v = Math.pow(rV.vCalc / this.prms.Ks.v, 2) / Math.pow(rR.vCalc, 4 / 3);
+                return new Result(v);
+                //                return Infinity;
         }
 
         /**
          * Calcul du nombre de Froude.
          * @return Le nombre de Froude
          */
-        private Calc_Fr(): number {
-                let S = this.Calc("S");
-                if (S != 0)
-                        return this.prms.Q.v / S * Math.sqrt(this.Calc("B") / S / cParamsCanal.G);
+        private Calc_Fr(): Result {
+                // let S = this.Calc("S");
+                const rS: Result = this.Calc("S");
+
+                if (!rS.ok)
+                        return rS;
+
+                // if (S != 0)
+                if (rS.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_SURFACE_NULLE));
+
+                const rB: Result = this.Calc("B");
+                if (!rB.ok)
+                        return rB;
 
-                return Infinity;
+                // return this.prms.Q.v / S * Math.sqrt(this.Calc("B") / S / cParamsCanal.G);
+                const v = this.prms.Q.v / rS.vCalc * Math.sqrt(rB.vCalc / rS.vCalc / cParamsCanal.G);
+                return new Result(v);
+
+                // return Infinity;
         }
 
         /**
          * Calcul de dy/dx
          */
-        private Calc_dYdX(Y: number): number {
+        private Calc_dYdX(Y: number): Result {
                 // L'appel à Calc("J') avec Y en paramètre réinitialise toutes les données dépendantes de la ligne d'eau
-                return - (this.prms.If.v - this.Calc("J", Y) / (1 - Math.pow(this.Calc("Fr", Y), 2)));
+
+                // return - (this.prms.If.v - this.Calc("J", Y) / (1 - Math.pow(this.Calc("Fr", Y), 2)));
+                const rJ: Result = this.Calc("J", Y);
+                if (!rJ.ok)
+                        return rJ;
+
+                const rFR: Result = this.Calc("Fr", Y);
+                if (!rFR.ok)
+                        return rFR;
+
+                const v = - (this.prms.If.v - rJ.vCalc / (1 - Math.pow(rFR.vCalc, 2)));
+                return new Result(v);
         }
 
         /**
          * Calcul de la vitesse moyenne.
          * @return Vitesse moyenne
          */
-        private Calc_V(): number {
-                let S = this.Calc("S");
-                if (S != 0)
-                        return this.prms.Q.v / S;
+        private Calc_V(): Result {
+                // let S = this.Calc("S");
+                let rS: Result = this.Calc("S");
+                if (!rS.ok)
+                        return rS;
+
+                // if (S != 0)
+                if (rS.vCalc == 0)
+                        return new Result(new Message(MessageCode.ERROR_SECTION_SURFACE_NULLE));
 
-                return Infinity;
+                // return this.prms.Q.v / S;
+                const v = this.prms.Q.v / rS.vCalc;
+                return new Result(v);
+
+                // return Infinity;
         }
 
         /**
          * Calcul de la charge spécifique.
          * @return Charge spécifique
          */
-        private Calc_Hs(): number {
-                return this.prms.Y.v + Math.pow(this.Calc("V"), 2) / (2 * cParamsCanal.G);
+        private Calc_Hs(): Result {
+                // return this.prms.Y.v + Math.pow(this.Calc("V"), 2) / (2 * cParamsCanal.G);
+
+                let rV: Result = this.Calc("V");
+                if (!rV.ok)
+                        return rV;
+
+                const v = this.prms.Y.v + Math.pow(rV.vCalc, 2) / (2 * cParamsCanal.G);
+                return new Result(v);
         }
 
         /**
          * Calcul de la charge spécifique critique.
          * @return Charge spécifique critique
          */
-        private Calc_Hsc(): number {
+        private Calc_Hsc(): Result {
+                let res: Result;
+
                 this.Swap(true); // On mémorise les données hydrauliques en cours
+
                 // On calcule la charge avec la hauteur critique
-                var Hsc = this.Calc("Hs", this.CalcGeo("Yc"));
+                // var Hsc = this.Calc("Hs", this.CalcGeo("Yc"));
+                const rYC: Result = this.CalcGeo("Yc");
+                if (!rYC.ok)
+                        res = rYC;
+                else
+                        res = this.Calc("Hs", rYC.vCalc);
+
                 // On restitue les données initiales
                 this.Swap(false);
-                return Hsc;
+
+                // return Hsc;
+                return res;
         }
 
         /**
          * Calcul du tirant d'eau critique.
          * @return tirant d'eau critique
          */
-        private Calc_Yc(): number {
-                let hautCritique = new cHautCritique(this, this._newtonMaxIter, this.DBG);
-                this.HautCritique = hautCritique.Newton(this.prms.YB.v);
-                if (this.HautCritique == undefined || !hautCritique.hasConverged()) {
+        private Calc_Yc(): Result {
+                let hautCritique = new cHautCritique(this, this._newtonMaxIter, this.newtonDbg);
+                this._hautCritique = hautCritique.Newton(this.prms.YB.v);
+
+                //                if (this.HautCritique == undefined || !hautCritique.hasConverged()) {
+                if (!this._hautCritique.ok) {
                         let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCRITIQUE);
-                        this.oLog.add(m);
+                        // this.oLog.add(m);
+                        this._hautCritique = new Result(m);
                 }
-                return this.HautCritique;
+                return this._hautCritique;
         }
 
         /**
          * Calcul du tirant d'eau normal.
          * @return tirant d'eau normal
          */
-        private Calc_Yn(): number {
-                this.debug("in calc_Yn");
+        private Calc_Yn(): Result {
                 if (this.prms.If.v <= 0) {
                         let m = new Message(MessageCode.ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF);
-                        this.oLog.add(m);
-                        return undefined;
+                        // this.oLog.add(m);
+                        // return undefined;
+                        return new Result(m);
                 }
 
-                let oHautNormale = new cHautNormale(this, this._newtonMaxIter, this.DBG);
-                let res = oHautNormale.Newton(this.CalcGeo("Yc"));
-                if (res == undefined || !oHautNormale.hasConverged()) {
+                const rYC: Result = this.CalcGeo("Yc");
+                if (!rYC.ok)
+                        return rYC;
+
+                let oHautNormale = new cHautNormale(this, this._newtonMaxIter, this._newtonDbg);
+                // let res = oHautNormale.Newton(this.CalcGeo("Yc"));
+                let rYN = oHautNormale.Newton(rYC.vCalc);
+
+                // if (res == undefined || !oHautNormale.hasConverged()) {
+                if (!rYN.ok) {
                         let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HNORMALE);
-                        this.oLog.add(m);
+                        // this.oLog.add(m);
+                        rYN = new Result(m);
                 }
 
-                return res;
+                return rYN;
         }
 
         /**
          * Calcul du tirant d'eau fluvial.
          * @return tirant d'eau fluvial
          */
-        private Calc_Yf(): number {
-                if (this.prms.Y.v > this.CalcGeo("Yc"))
-                        return this.prms.Y.v;
+        private Calc_Yf(): Result {
+                const rGeoYC: Result = this.CalcGeo("Yc");
+                if (!rGeoYC.ok)
+                        return rGeoYC;
+
+                // if (this.prms.Y.v > this.CalcGeo("Yc"))
+                if (this.prms.Y.v > rGeoYC.vCalc)
+                        return new Result(this.prms.Y.v);
+
+                const oHautCorrespondante = new cHautCorrespondante(this, this._newtonMaxIter, this._newtonDbg);
 
-                var oHautCorrespondante = new cHautCorrespondante(this, this._newtonMaxIter, this.DBG);
-                let res = oHautCorrespondante.Newton(this.Calc("Yc") * 2);
-                if (res == undefined || !oHautCorrespondante.hasConverged()) {
+                const rYC: Result = this.Calc("Yc");
+                if (!rYC.ok)
+                        return rYC;
+                // let res = oHautCorrespondante.Newton(this.Calc("Yc") * 2);
+                let rYF = oHautCorrespondante.Newton(rYC.vCalc * 2);
+
+                // if (res == undefined || !oHautCorrespondante.hasConverged()) {
+                if (!rYF.ok) {
                         let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HFLU);
-                        this.oLog.add(m);
+                        // this.oLog.add(m);
+                        rYF = new Result(m);
                 }
 
-                return res;
+                return rYF;
         }
 
         /**
          * Calcul du tirant d'eau torrentiel.
          * @return tirant d'eau torrentiel
          */
-        private Calc_Yt(): number {
-                if (this.prms.Y.v < this.CalcGeo("Yc"))
-                        return this.prms.Y.v;
+        private Calc_Yt(): Result {
+                const rGeoYC: Result = this.CalcGeo("Yc");
+                if (!rGeoYC.ok)
+                        return rGeoYC;
+
+                // if (this.prms.Y.v < this.CalcGeo("Yc"))
+                if (this.prms.Y.v < rGeoYC.vCalc)
+                        return new Result(this.prms.Y.v);
 
-                var oHautCorrespondante = new cHautCorrespondante(this, this._newtonMaxIter, this.DBG);
-                let res = oHautCorrespondante.Newton(this.CalcGeo("Yc") / 2);
-                if (res == undefined || !oHautCorrespondante.hasConverged()) {
+                var oHautCorrespondante = new cHautCorrespondante(this, this._newtonMaxIter, this._newtonDbg);
+                // let res = oHautCorrespondante.Newton(this.CalcGeo("Yc") / 2);
+                let rYT = oHautCorrespondante.Newton(rGeoYC.vCalc / 2);
+                // if (res == undefined || !oHautCorrespondante.hasConverged()) {
+                if (!rYT.ok) {
                         let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HTOR);
-                        this.oLog.add(m);
+                        // this.oLog.add(m);
+                        rYT = new Result(m);
                 }
 
-                return res;
+                return rYT;
         }
 
         /**
          * Calcul du tirant d'eau conjugué.
          * @return tirant d'eau conjugué
          */
-        private Calc_Yco(): number {
+        private Calc_Yco(): Result {
+                let res: Result;
+
                 this.Swap(true);
-                var oHautConj = new cHautConjuguee(this, this._newtonMaxIter, this.DBG);
-                // Choisir une valeur initiale du bon côté de la courbe
-                if (this.Calc("Fr") < 1) {
-                        // Ecoulement fluvial, on cherche la conjuguée à partir du tirant d'eau torrentiel
-                        var Y0 = this.Calc("Yt");
-                }
+
+                const oHautConj = new cHautConjuguee(this, this._newtonMaxIter, this._newtonDbg);
+
+                const rFR: Result = this.Calc("Fr");
+                if (!rFR.ok)
+                        res = rFR;
                 else {
-                        // Ecoulement torrentiel, on cherche la conjuguée à partir du tirant d'eau fluvial
-                        Y0 = this.Calc("Yf");
-                }
-                let Yco = oHautConj.Newton(Y0);
-                if (Yco == undefined || !oHautConj.hasConverged()) {
-                        let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
-                        this.oLog.add(m);
+                        // Choisir une valeur initiale du bon côté de la courbe
+                        // if (this.Calc("Fr") < 1) {
+                        if (rFR.vCalc < 1) {
+                                // Ecoulement fluvial, on cherche la conjuguée à partir du tirant d'eau torrentiel
+                                var Y0: Result = this.Calc("Yt");
+                        }
+                        else {
+                                // Ecoulement torrentiel, on cherche la conjuguée à partir du tirant d'eau fluvial
+                                Y0 = this.Calc("Yf");
+                        }
+                        if (!Y0.ok)
+                                res = Y0;
+                        else {
+                                // let Yco = oHautConj.Newton(Y0);
+                                const Yco: Result = oHautConj.Newton(Y0.vCalc);
+
+                                // if (Yco == undefined || !oHautConj.hasConverged()) {
+                                if (!Yco.ok) {
+                                        let m = new Message(MessageCode.ERROR_SECTION_NON_CONVERGENCE_NEWTON_HCONJUG);
+                                        // this.oLog.add(m);
+                                        res = new Result(m);
+                                }
+                                else
+                                        res = Yco;
+                        }
                 }
 
                 this.Swap(false);
-                return Yco;
+                return res;
         }
 
         /**
          * Calcul de la contrainte de cisaillement.
          * @return contrainte de cisaillement
          */
-        private Calc_Tau0(): number {
-                return 1000 * cParamsCanal.G * this.Calc("R") * this.Calc("J");
+        private Calc_Tau0(): Result {
+                const rR: Result = this.Calc("R");
+                if (!rR.ok)
+                        return rR;
+
+                const rJ: Result = this.Calc("J");
+                if (!rJ.ok)
+                        return rJ;
+
+                // return 1000 * cParamsCanal.G * this.Calc("R") * this.Calc("J");
+                return new Result(1000 * cParamsCanal.G * rR.vCalc * rJ.vCalc);
         }
 
         /**
@@ -614,9 +803,16 @@ export abstract class acSection extends ComputeNode {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_SYg(): number {
-                // return Math.pow(this.prms.Y.v, 2) * this.prms.LargeurBerge.v / 2;
-                return Math.pow(this.prms.Y.v, 2) * this.CalcGeo("B") / 2;
+        protected Calc_SYg(): Result {
+                // return Math.pow(this.prms.Y.v, 2) * this.CalcGeo("B") / 2;
+
+                const rGeoB: Result = this.CalcGeo("B");
+                if (!rGeoB.ok)
+                        return rGeoB;
+
+                // return Math.pow(this.prms.Y.v, 2) * this.CalcGeo("B") / 2;
+                const v = Math.pow(this.prms.Y.v, 2) * rGeoB.vCalc / 2;
+                return new Result(v);
         }
 
         /**
@@ -624,32 +820,47 @@ export abstract class acSection extends ComputeNode {
          * multiplié par la surface hydraulique
          * @return S x Yg
          */
-        protected Calc_dSYg(): number {
-                // return this.prms.Y.v * this.prms.LargeurBerge.v;
-                return this.prms.Y.v * this.CalcGeo("B");
+        protected Calc_dSYg(): Result {
+                const rGeoB: Result = this.CalcGeo("B");
+                if (!rGeoB.ok)
+                        return rGeoB;
+
+                // return this.prms.Y.v * this.CalcGeo("B");
+                const v = this.prms.Y.v * rGeoB.vCalc;
+                return new Result(v);
         }
 
         /**
          * Calcul de l'impulsion hydraulique.
          * @return Impulsion hydraulique
          */
-        private Calc_Imp(): number {
-                return 1000 * (this.prms.Q.v * this.Calc("V") + cParamsCanal.G * this.Calc("SYg"));
+        private Calc_Imp(): Result {
+                const rV: Result = this.Calc("V");
+                if (!rV.ok)
+                        return rV;
+
+                const rSYG: Result = this.Calc("SYg");
+                if (!rSYG.ok)
+                        return rSYG;
+
+                // return 1000 * (this.prms.Q.v * this.Calc("V") + cParamsCanal.G * this.Calc("SYg"));
+                const v = 1000 * (this.prms.Q.v * rV.vCalc + cParamsCanal.G * rSYG.vCalc);
+                return new Result(v);
         }
 
         /**
          * Calcul de l'angle Alpha entre la surface libre et le fond pour les sections circulaires.
          * @return Angle Alpha pour une section circulaire, 0 sinon.
          */
-        protected Calc_Alpha(): number {
-                return 0;
+        protected Calc_Alpha(): Result {
+                return new Result(0);
         }
 
         /**
          * Calcul de la dérivée de l'angle Alpha entre la surface libre et le fond pour les sections circulaires.
          * @return Dérivée de l'angle Alpha pour une section circulaire, 0 sinon.
          */
-        protected Calc_dAlpha(): number {
-                return 0;
+        protected Calc_dAlpha(): Result {
+                return new Result(0);
         }
 }
diff --git a/src/structure/factory_structure.ts b/src/structure/factory_structure.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3acb5d4a9b8b24ed4a1f06cd9a8aad889dec355d
--- /dev/null
+++ b/src/structure/factory_structure.ts
@@ -0,0 +1,45 @@
+import { RectangularStructureParams } from "./rectangular_structure_params";
+import { Structure } from "./structure";
+import { StructureCem88d } from "./structure_cem88d";
+import { StructureCem88v } from "./structure_cem88v";
+import { StructureCunge80 } from "./structure_cunge80";
+import { StructureOrificeFree } from "./structure_orifice_free";
+import { StructureOrificeSubmerged } from "./structure_orifice_submerged";
+import { StructureWeirFree } from "./structure_weir_free";
+
+export enum StructureType {
+    Cem88d,
+    Cem88v,
+    Cunge80,
+    OrificeFree,
+    OrificeSubmerged,
+    WeirFree
+}
+
+export function CreateStructure(structureType: StructureType): Structure {
+    const structPrms: RectangularStructureParams = new RectangularStructureParams(
+        0,  // Q
+        100,        // ZDV
+        102,        // Z1
+        101.5,      // Z2
+        2,          // L
+        0.6,        // Cd
+        0.5         // W
+    );
+    switch (structureType) {
+        case StructureType.Cem88d:
+            return new StructureCem88d(structPrms);
+        case StructureType.Cem88v:
+            return new StructureCem88v(structPrms);
+        case StructureType.Cunge80:
+            return new StructureCunge80(structPrms);
+        case StructureType.OrificeFree:
+            return new StructureOrificeFree(structPrms);
+        case StructureType.OrificeSubmerged:
+            return new StructureOrificeSubmerged(structPrms);
+        case StructureType.WeirFree:
+            const st: StructureWeirFree = new StructureWeirFree(structPrms);
+            st.prms.Cd.v = 0.4;
+            return st;
+    }
+}
diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6489a87c45ae886eead0d6b6dc69be3fdbdd1024
--- /dev/null
+++ b/src/structure/parallel_structure.ts
@@ -0,0 +1,151 @@
+import { Nub } from "../nub";
+import { ParamCalculability } from "../param";
+import { Message } from "../util/message";
+import { Result } from "../util/result";
+import { ParallelStructureParams } from "./parallel_structure_params";
+import { Structure } from "./structure";
+
+/**
+ * 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, 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, 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 :
+        this.structures[index].prms.Q.v = 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 edd24882d4056e5269a8d5361f6cb193c92fb18c..485d540bdfa2b17d1d4363d1edcac93da1be0ff4 100644
--- a/src/structure/rectangular_structure_params.ts
+++ b/src/structure/rectangular_structure_params.ts
@@ -10,10 +10,21 @@ export class RectangularStructureParams extends StructureParams {
     public L: ParamDefinition;
 
     /** Discharge coefficient */
+    // tslint:disable-next-line:variable-name
     public Cd: ParamDefinition;
 
-    constructor(rQ: number, rh1: number, rh2: number, rL: number, rCd: number, rW: number = Infinity) {
-        super(rQ, rh1, rh2, rW);
+    /**
+     * Constructeur d'une structure rectangulaire
+     * @param rQ    Débit (m3/s)
+     * @param rZDV  Cote de la crête du déversoir ou du radier de la vanne (m)
+     * @param rZ1   Cote de l'eau amont (m)
+     * @param rZ2   Cote de l'eau aval (m)
+     * @param rL    Largeur de la vanne ou du déversoir (m)
+     * @param rCd   Coefficient de débit (-)
+     * @param rW    Ouverture de la vanne (m) (Valeur par défaut +infinity pour les déversoirs)
+     */
+    constructor(rQ: number, rZDV: number, rZ1: number, rZ2: number, rL: number, rCd: number, rW: number = Infinity) {
+        super(rQ, rZDV, rZ1, rZ2, rW);
         this.L = new ParamDefinition(ComputeNodeType.CondDistri, "L", ParamDomainValue.POS, rL);
         this.addParamDefinition(this.L);
         this.Cd = new ParamDefinition(ComputeNodeType.CondDistri, "Cd", ParamDomainValue.POS, rCd);
diff --git a/src/structure/structure.ts b/src/structure/structure.ts
index c9f43ae1a0e69ad7595bf9b4b3ab1dd7d93a07dc..0ed0b4ad5a65cf5065a800a0307cb56892adcf93 100644
--- a/src/structure/structure.ts
+++ b/src/structure/structure.ts
@@ -1,7 +1,7 @@
-import { Result } from "../util/result";
 import { Nub } from "../nub";
 import { ParamCalculability } from "../param";
 import { Message } from "../util/message";
+import { Result } from "../util/result";
 
 import { StructureParams } from "./structure_params";
 
@@ -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,18 +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;
-
-    protected defaultResultData() {
-        return {
-            Mode: this.getFlowMode(),
-            Regime: this.getFlowRegime()
-        };
-    }
-
     /**
      * Calcul d'une équation quelque soit l'inconnue à calculer.
      * Gestion du débit nul et de l'inversion de débit
@@ -71,9 +66,12 @@ export abstract class Structure extends Nub {
      * @param rInit valeur initiale de la variable à calculer dans le cas de la dichotomie
      * @param rPrec précision de calcul
      */
-    public Calc(sVarCalc: string, rInit: number = 0, rPrec: number = 0.001): Result {
-        const flagsNull = {Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL};
+    public Calc(sVarCalc: string, rInit?: number, rPrec: number = 0.001): Result {
+        // Mise à jour de h1 et h2
+        this.prms.update_h1h2();
+
         // Gestion du débit nul
+        const flagsNull = {Mode: StructureFlowMode.NULL, Regime: StructureFlowRegime.NULL};
         if (sVarCalc === "Q") {
             if (this.prms.h1.v === this.prms.h2.v || this.prms.W.v <= 0) {
                 return new Result(0, flagsNull);
@@ -81,29 +79,55 @@ 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;
         }
 
+        // Calcul normal hors débit nul et inversion de débit
         return super.Calc(sVarCalc, rInit, rPrec);
+    }
 
+    protected getResultData() {
+        return {
+            Mode: this.getFlowMode(),
+            Regime: this.getFlowRegime(),
+        };
     }
 
     /**
@@ -111,8 +135,11 @@ export abstract class Structure extends Nub {
      */
     protected setParametersCalculability() {
         this.prms.Q.calculability = ParamCalculability.EQUATION;
-        this.prms.h1.calculability = ParamCalculability.DICHO;
-        this.prms.h2.calculability = ParamCalculability.DICHO;
+        this.prms.ZDV.calculability = ParamCalculability.DICHO;
+        this.prms.Z1.calculability = ParamCalculability.DICHO;
+        this.prms.Z2.calculability = ParamCalculability.DICHO;
+        this.prms.h1.calculability = ParamCalculability.FREE;
+        this.prms.h2.calculability = ParamCalculability.FREE;
         this.prms.W.calculability = ParamCalculability.DICHO;
     }
 
@@ -158,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 539047181ae3b3e4971914c9a2f535b19f3bc33e..468fd6a43cb48b9e032dcdb416ea052a0723e533 100644
--- a/src/structure/structure_params.ts
+++ b/src/structure/structure_params.ts
@@ -1,19 +1,26 @@
-import { Result } from "../util/result";
 import { Nub } from "../nub";
-import { ComputeNodeType, ParamDefinition, ParamDomain, ParamDomainValue, ParamsEquation } from "../param";
-import { Message } from "../util/message";
+import { ComputeNodeType, ParamDefinition, ParamDomainValue, ParamsEquation } from "../param";
 
 /**
  * Common parameters of hydraulic structure equations
  */
 export class StructureParams extends ParamsEquation {
-    /** Débit */
+    /** Débit (m3/s) */
     public Q: ParamDefinition;
 
-    /** Tirant d'eau amont */
+    /** Cote de la crête du déversoir ou du radier de la vanne (m) */
+    public ZDV: ParamDefinition;
+
+    /** Cote de l'eau amont (m) */
+    public Z1: ParamDefinition;
+
+    /** Cote de l'eau aval (m) */
+    public Z2: ParamDefinition;
+
+    /** Tirant d'eau amont (m) */
     public h1: ParamDefinition;
 
-    /** Tirant d'eau aval */
+    /** Tirant d'eau aval (m) */
     public h2: ParamDefinition;
 
     /** Ouverture de la vanne
@@ -24,19 +31,34 @@ export class StructureParams extends ParamsEquation {
     /**
      * Paramètres communs à toutes les équations de structure
      * @param rQ Débit (m3/s)
-     * @param rh1 Hauteur amont au dessus de la crête (m)
-     * @param rh2 Hauteur aval au dessus de la crête (m)
+     * @param rZDV Cote de la crête du déversoir ou du radier de la vanne (m)
+     * @param rZ1 Cote de l'eau amont (m)
+     * @param rZ2 Cote de l'eau aval (m)
      * @param rW Ouverture de vanne (m) (infinity pour un seuil)
      */
-    constructor(rQ: number, rh1: number, rh2: number, rW: number = Infinity ) {
+    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.h1 = new ParamDefinition(ComputeNodeType.CondDistri, "h1", ParamDomainValue.POS_NULL, rh1);
+        this.ZDV = new ParamDefinition(ComputeNodeType.CondDistri, "ZDV", ParamDomainValue.ANY, rZDV);
+        this.addParamDefinition(this.ZDV);
+        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);
+        this.h1 = new ParamDefinition(ComputeNodeType.CondDistri, "h1", ParamDomainValue.POS_NULL,
+            Math.max(0, this.Z1.v - this.ZDV.v));
         this.addParamDefinition(this.h1);
-        this.h2 = new ParamDefinition(ComputeNodeType.CondDistri, "h2", ParamDomainValue.POS_NULL, rh2);
+        this.h2 = new ParamDefinition(ComputeNodeType.CondDistri, "h2", ParamDomainValue.POS_NULL,
+            Math.max(0, this.Z2.v - this.ZDV.v));
         this.addParamDefinition(this.h2);
         this.W = new ParamDefinition(ComputeNodeType.CondDistri, "W", ParamDomainValue.POS_NULL, rW);
         this.addParamDefinition(this.W);
     }
+
+    /** Mise à jour des paramètres h1 et h2 à partir de Z1, Z2 et ZDV */
+    public update_h1h2() {
+        this.h1.v = Math.max(0, this.Z1.v - this.ZDV.v);
+        this.h2.v = Math.max(0, this.Z2.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/describer.ts b/src/util/describer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5786fb812d7b54be12cf58ad50c35ec08fdfb40a
--- /dev/null
+++ b/src/util/describer.ts
@@ -0,0 +1,15 @@
+/**
+ * Récupération du nom de la classe
+ * https://www.stevefenton.co.uk/2013/04/Obtaining-A-Class-Name-At-Runtime-In-TypeScript/
+ */
+export class Describer {
+    /**
+     * Récupère le nom de la classe d'un objet
+     * @param inputClass Objet à tester
+     */
+    public static getName(inputClass: any) {
+        const funcNameRegex = /function (.{1,})\(/;
+        const results = (funcNameRegex).exec((inputClass as any).constructor.toString());
+        return (results && results.length > 1) ? results[1] : "";
+    }
+}
diff --git a/src/util/enum.ts b/src/util/enum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8c0186b4c1dd946353bbeebd804795f94580c321
--- /dev/null
+++ b/src/util/enum.ts
@@ -0,0 +1,45 @@
+/**
+ * classe d'itérateurs pour les enums
+ * cf. https://stackoverflow.com/questions/21293063/how-to-programmatically-enumerate-an-enum-type-in-typescript-0-9-5#21294925
+ 
+   utilisation : 
+
+    for (const v of EnumEx.getValues(MonTypeEnum)) {
+       console.log(v);
+    }
+
+    for (const n of EnumEx.getNames(MonTypeEnum)) {
+       console.log(n);
+    }
+
+    for (const c of EnumEx.getNamesAndValues(MonTypeEnum)) {
+       console.log(c.name);
+       console.log(c.value);
+    }
+ */
+export class EnumEx {
+    /**
+     * retourne les noms et les valeurs d'un enum
+     */
+    static getNamesAndValues<T extends number>(e: any) {
+        return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as T }));
+    }
+
+    /**
+     * retourne les noms d'un enum
+     */
+    static getNames(e: any) {
+        return EnumEx.getObjValues(e).filter(v => typeof v === "string") as string[];
+    }
+
+    /**
+     * retourne les valeurs d'un enum
+     */
+    static getValues<T extends number>(e: any) {
+        return EnumEx.getObjValues(e).filter(v => typeof v === "number") as T[];
+    }
+
+    private static getObjValues(e: any): (number | string)[] {
+        return Object.keys(e).map(k => e[k]);
+    }
+}
diff --git a/src/util/iterator.ts b/src/util/iterator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..31a4b942c704ffb378a44806a7009a02982d4272
--- /dev/null
+++ b/src/util/iterator.ts
@@ -0,0 +1,100 @@
+/**
+ * itérateur sur un tableau dans le sens inverse (depuis la fin)
+ * 
+ * utilisation :
+     let arr = [1,2,3];
+     const it = new ArrayReverseIterator<Result>(arr);
+     for (let r of it)
+       console.log( r );   // 3 2 1
+ */
+export class ArrayReverseIterator<T> implements IterableIterator<T> {
+    private _index: number;
+
+    constructor(private _arr: any[]) {
+        this._index = this._arr == undefined ? 0 : this._arr.length - 1;
+    }
+
+    public next(): IteratorResult<T> {
+        if (this._arr != undefined && this._index >= 0) {
+            return {
+                done: false,
+                value: this._arr[this._index--]
+            }
+        } else {
+            return {
+                done: true,
+                value: null
+            }
+        }
+    }
+
+    [Symbol.iterator](): IterableIterator<T> {
+        return this;
+    }
+}
+
+/**
+ * itérateur sur un map string<->any
+   
+   utilisation :
+
+   class MaClasseAIterer implements Iterable<Machin> {
+       private _machinMap: { [key: string]: Machin } = {};
+
+       [Symbol.iterator](): Iterator<Machin> {
+          return new MapIterator(this._machinMap);
+       }
+   }
+
+   const mc = new MaClasseAIterer();
+   for ( const m of mc ) {
+     ...
+   }
+ */
+export class MapIterator<T> implements Iterator<T> {
+    private _map: { [key: string]: T } = {};
+
+    private _keys: string[];
+
+    private _lastIndex: number = -1; // index of last element returned; -1 if no such
+
+    private _index: number = 0;
+
+    private _currentKey: string;
+
+    constructor(m: { [key: string]: T }) {
+        this._map = m;
+        if (this._map != undefined)
+            this._keys = Object.keys(this._map);
+        else
+            this._keys = [];
+    }
+
+    public next(): IteratorResult<T> {
+        const i = this._index;
+        if (this._index < this._keys.length) {
+            this._currentKey = this._keys[this._index++];
+            this._index = i + 1;
+            this._lastIndex = i;
+            return {
+                done: this._index >= this._keys.length,
+                value: this._map[this._currentKey]
+            }
+        } else {
+            this._currentKey = undefined;
+            this._lastIndex = undefined;
+            return {
+                done: true,
+                value: undefined
+            }
+        }
+    }
+
+    public get index() {
+        return this._lastIndex;
+    }
+
+    public get key(): string {
+        return this._currentKey;
+    }
+}
diff --git a/src/util/log.ts b/src/util/log.ts
index 401fbc9c9dbcdfe364ee600a4994eab1e1cbce0e..6770d31341730508c2dc93539bd8f5a33ef88b76 100644
--- a/src/util/log.ts
+++ b/src/util/log.ts
@@ -7,6 +7,19 @@ export class cLog {
         this._messages.push(m);
     }
 
+    public addLog(l: cLog) {
+        for (let m of l._messages)
+            this._messages.push(m);
+    }
+
+    /**
+    * insert un message en début de liste
+    */
+    public insert(m: Message) {
+        //arr.splice(index, 0, item); will insert item into arr at the specified index (deleting 0 items first, that is, it's just an insert).
+        this._messages.splice(0, 0, m);
+    }
+
     public get messages() {
         return this._messages;
     }
diff --git a/src/util/message.ts b/src/util/message.ts
index a4ee532a837b1b54450f50e938a7ec690bd44021..6f0cd183be78235b869a14aa2dbacbe581874a91 100644
--- a/src/util/message.ts
+++ b/src/util/message.ts
@@ -106,42 +106,42 @@ export enum MessageCode {
     /**
      * courbes de remous : Arrêt du calcul : hauteur critique atteinte à l'abscisse x
      */
-    ERROR_REMOUS_ARRET_CRITIQUE = -500,
+    WARNING_REMOUS_ARRET_CRITIQUE = -500,
 
     /**
      * courbe de remous : Condition limite aval >= Hauteur critique : calcul de la partie fluviale à partir de l'aval
      */
-    ERROR_REMOUS_CALCUL_FLUVIAL = -501,
+    INFO_REMOUS_CALCUL_FLUVIAL = -501,
 
     /**
      * courbe de remous : Condition limite amont <= Hauteur critique : calcul de la partie torrentielle à partir de l'amont
      */
-    ERROR_REMOUS_CALCUL_TORRENTIEL = -502,
+    INFO_REMOUS_CALCUL_TORRENTIEL = -502,
 
     /**
      * courbe de remous : ressaut hydraulique détecté à l'amont/aval de l'abscisse x
      */
-    ERROR_REMOUS_RESSAUT_DEHORS = -503,
+    INFO_REMOUS_RESSAUT_DEHORS = -503,
 
     /**
      * courbe de remous : Largeur au niveau des berges
      */
-    ERROR_REMOUS_LARGEUR_BERGE = -504,
+    INFO_REMOUS_LARGEUR_BERGE = -504,
 
     /**
      * courbe de remous : Tirant d'eau critique
      */
-    ERROR_REMOUS_H_CRITIQUE = -505,
+    INFO_REMOUS_H_CRITIQUE = -505,
 
     /**
      * courbe de remous : Tirant d'eau normal
      */
-    ERROR_REMOUS_H_NORMALE = -506,
+    INFO_REMOUS_H_NORMALE = -506,
 
     /**
      * courbe de remous : Ressaut hydraulique détecté entre les abscisses Xmin et Xmax m
      */
-    ERROR_REMOUS_RESSAUT_HYDRO = -507,
+    INFO_REMOUS_RESSAUT_HYDRO = -507,
 
     /**
      * courbe de remous : La pente de la ligne d'eau est trop forte à l'abscisse x m
@@ -187,6 +187,31 @@ export enum MessageCode {
      * section : La pente est négative ou nulle, la hauteur normale est infinie
      */
     ERROR_SECTION_PENTE_NEG_NULLE_HNORMALE_INF = -605,
+
+    /**
+     * section : calcul impossible à cause d'un périmètre nul
+     */
+    ERROR_SECTION_PERIMETRE_NUL = -606,
+
+    /**
+     * section : calcul impossible à cause d'un rayon nul
+     */
+    ERROR_SECTION_RAYON_NUL = -607,
+
+    /**
+     * section : calcul impossible à cause d'une surface nulle
+     */
+    ERROR_SECTION_SURFACE_NULLE = -608,
+
+    /**
+     * newton : pas de convergence
+     */
+    ERROR_NEWTON_NON_CONVERGENCE = -700,
+
+    /**
+     * newton : dérivée nulle
+     */
+    ERROR_NEWTON_DERIVEE_NULLE = -701,
 }
 
 /**
@@ -211,7 +236,7 @@ export class Message {
     constructor(c: MessageCode) {
         this._code = c;
         this.extraVar = {}
-    };
+    }
 
     get code() { return this._code; }
 
diff --git a/src/util/result.ts b/src/util/result.ts
index 1456888a9f224f429b49f43c7489a2d55f90ac1c..22f51be55091a226dccb01ec937c06fadef3166b 100644
--- a/src/util/result.ts
+++ b/src/util/result.ts
@@ -1,62 +1,232 @@
 import { cLog } from "./log";
-import { Message, MessageCode } from "./message";
+import { Message, MessageCode, MessageSeverity } from "./message";
+import { ResultElement } from "./resultelement";
 
 /**
- * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
+ * Résultat global d'un calcul
+ * Peut comporter un ou plusieurs Result.
  */
+// tslint:disable-next-line:max-classes-per-file
 export class Result {
-    /** Valeur calculée */
-    private _vCalc: number;
+    /**
+     * Messages (erreurs, infos, ...)
+     */
+    private _globalLog: cLog;
 
-    private _log: cLog;
+    private _results: ResultElement[];
 
-    constructor(v: number | Message, d: {} = undefined) {
-        this._log = new cLog();
-        if (typeof v == "number") {
-            this._vCalc = v;
-            const m = new Message(MessageCode.ERROR_OK);
-            m.extraVar = d;
-            this._log.add(m);
+    constructor(v?: number | Message | ResultElement, d?: any) {
+        this._globalLog = new cLog();
+        this._results = [];
+        if (typeof (v) === "number" || v instanceof Message) {
+            this._results.push(new ResultElement(v));
+        } else if (v instanceof ResultElement) {
+            this._results.push(v);
         }
-        else {
-            if (d != undefined)
-                throw new Error("appel à Result.constructor() invalide");
-            this._log.add(v);
+
+        if (d !== undefined) {
+            this.result.extraResults = d;
+        }
+    }
+
+    /**
+     * retourne le journal de la calculette
+     */
+    public get globalLog() {
+        return this._globalLog;
+    }
+
+    /**
+     * 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];
+    }
+
+    /**
+     * @return true si il existe au moins 1 ResultElement dans le tableau
+     */
+    get hasResults(): boolean {
+        return this._results.length > 0;
+    }
+
+    /**
+     * @return le résultat de calcul du 1er ResultElement
+     */
+    get vCalc(): number {
+        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
+     */
+    public get log() {
+        // return this._globalLog;
+        return this.result.log;
+    }
+
+    /**
+     * retourne le code du 1er ResultElement
+     */
+    public get code(): MessageCode {
+        return this.result.code;
+    }
+
+    /**
+     * 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]);
+    }
+
+    /**
+     * Renvoie le nombre de résultats dans le tableau de résultats
+     */
+    public get nbResults(): number {
+        return this._results.length;
+    }
 
-    get vCalc() { return this._vCalc; }
+    /**
+     * Ajoute un ResultElement au tableau
+     * @param r ResultElement à ajouter
+     */
+    public addResult(r: ResultElement) {
+        this._results.push(r);
+    }
 
-    get code(): MessageCode {
-        if (this.messageCount != 1)
-            throw new Error("appel à Result.code invalide, il n'y pas exactement un message de log");
-        return this._log.messages[0].code;
+    /**
+     * Insert result r at index i
+     * @param r Result to insert
+     * @param i Index position
+     */
+    public insertResult(r: ResultElement, i: number) {
+        this._results.splice(i, 0, r);
     }
 
-    get extraVar() {
-        if (this.messageCount != 1)
-            throw new Error("appel à Result.extraVar invalide, il n'y pas exactement un message de log");
-        return this._log.messages[0].extraVar;
+    /**
+     * @param name nom du résultat complémentaire
+     * @returns le nombre la taille d'un résultat complémentaire
+     */
+    public extraResultLength(name: string): number {
+        const r = this.getExtraResult(name);
+        if (r === undefined) {
+            return 0;
+        }
+        return Object.keys(r).length;
+    }
+
+    public getExtraResult(name: string): any {
+        const res = [];
+        for (const r of this._results) {
+            const er = r.getExtraResult(name);
+            if (er !== undefined) {
+                res.push(er);
+            }
+        }
+
+        switch (res.length) {
+            case 0:
+                return undefined;
+
+            case 1:
+                return res[0];
+
+            default:
+                throw new Error(
+                    "Result.getExtraResult() : il existe plusieurs ResultElement avec" +
+                    " un extratresult dont le nom est '" + name + "'",
+                );
+        }
     }
 
+    // protected get messageCount(): number {
+    //     return this._globalLog.messages.length;
+    // }
+
+    /**
+     * ajoute un message au journal
+     */
     public addMessage(m: Message) {
-        this._log.add(m);
+        this._globalLog.add(m);
     }
 
-    public get log(): cLog {
-        return this._log;
+    /**
+     * ajoute tous les messages d'un journal au journal
+     */
+    public addLog(l: cLog) {
+        this._globalLog.addLog(l);
     }
 
-    private get messageCount(): number {
-        return this._log.messages.length;
+    /**
+     * insert un message en début de liste
+     */
+    public insertMessage(m: Message) {
+        this._globalLog.insert(m);
     }
 
+    /**
+     * Teste si tous les résultats + complémentaires sont valides et journal sans erreur
+     * @returns true si le test est valide
+     */
     public get ok(): boolean {
-        if (this._vCalc == undefined)
+        return this.resultsOk && !this.hasErrorMessages;
+    }
+
+    /**
+     * Teste si tous les résultats + complémentaires sont valides
+     * @returns true si le test est valide
+     */
+    public get resultsOk(): boolean {
+        if (this._results.length === 0) {
             return false;
-        for (let m of this._log.messages)
-            if (m.code != MessageCode.ERROR_OK)
+        }
+        for (const r of this._results) {
+            if (!r.resultsOk) {
                 return false;
+            }
+        }
         return true;
     }
+
+    /**
+     * @returns true si au moins un message de log comporte un code d'erreur
+     */
+    public get hasErrorMessages(): boolean {
+        // 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;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/src/util/resultelement.ts b/src/util/resultelement.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dc301486fdeeabcfc22d9e77a3a37418139c546f
--- /dev/null
+++ b/src/util/resultelement.ts
@@ -0,0 +1,133 @@
+import { cLog } from "./log";
+import { Message, MessageCode, MessageSeverity } from "./message";
+
+/**
+ * Résultat de calcul comprenant la valeur du résultat et des calculs annexes (flag, calculs intermédiaires...)
+ * Représente une valeur unique
+ */
+// tslint:disable-next-line:max-classes-per-file
+export class ResultElement {
+    /**
+     * Valeur calculée
+     */
+    private _vCalc: number;
+
+    /**
+     * Messages (erreurs, infos, ...)
+     */
+    private _log: cLog;
+
+    /**
+     * résultats complémentaires
+     */
+    private _extraResults: { [key: string]: any };
+
+    constructor(v?: number | Message) {
+        this._log = new cLog();
+        if (typeof v === "number") {
+            this._vCalc = v;
+        } else if (v instanceof Message) {
+            this.addMessage(v);
+        }
+        this._extraResults = {};
+    }
+
+    get vCalc() { return this._vCalc; }
+
+    set vCalc(r: number) {
+        this._vCalc = r;
+    }
+
+    public get log() {
+        return this._log;
+    }
+
+    get code(): MessageCode {
+        if (this.messageCount !== 1) {
+            throw new Error("appel à Result.code invalide, il n'y pas exactement un message de log");
+        }
+        return this._log.messages[0].code;
+    }
+
+    get extraVar() {
+        if (this.messageCount !== 1) {
+            throw new Error("appel à Result.extraVar invalide, il n'y pas exactement un message de log");
+        }
+        return this._log.messages[0].extraVar;
+    }
+
+    private get hasExtraResults(): boolean {
+        return Object.keys(this._extraResults).length > 0;
+    }
+
+    public get resultsOk(): boolean {
+        return this._vCalc !== undefined || this.hasExtraResults;
+    }
+
+    private get messageCount(): number {
+        return this._log.messages.length;
+    }
+
+    public get hasErrorMessages(): boolean {
+        for (const m of this._log.messages) {
+            if (m.code !== MessageCode.ERROR_OK && m.getSeverity() === MessageSeverity.ERROR) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public get ok(): boolean {
+        return this.resultsOk && !this.hasErrorMessages;
+    }
+
+    /**
+     * ajoute un message au journal
+     */
+    public addMessage(m: Message) {
+        this._log.add(m);
+    }
+
+    /**
+     * insert un message en début de liste
+     */
+    public insertMessage(m: Message) {
+        this._log.insert(m);
+    }
+
+    /**
+     * résultats complémentaires
+     */
+
+    get extraResults() {
+        return this._extraResults;
+    }
+
+    set extraResults(d: { [key: string]: any }) {
+        this._extraResults = d;
+    }
+
+    public addExtraResult(name: string, value: any) {
+        this._extraResults[name] = value;
+    }
+
+    /**
+     * @param name nom du résultat complémentaire à retourner
+     * @returns un résultat complémentaire par son nom
+     */
+    public getExtraResult(name: string): any {
+        for (const n in this._extraResults) {
+            if (n === name) {
+                return this._extraResults[n];
+            }
+        }
+        return undefined;
+    }
+
+    public toString(): string {
+        if (this._vCalc !== undefined) {
+            return String(this._vCalc);
+        }
+        return JSON.stringify(this);
+    }
+}
diff --git a/tsconfig.json b/tsconfig.json
index e5b0503469e05cc0e822ab774c1c6588fe2ed880..c345304ba5072030805570231b733fcf0c9e0745 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
 {
   "compilerOptions": {
-    "target": "es5",
+    "target": "es6",
     "module": "commonjs",
     "outDir": "./build",
     "noImplicitAny": true,
@@ -12,4 +12,4 @@
   "exclude": [
     "node_modules"
   ]
-}
+}
\ No newline at end of file
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