diff --git a/spec/structure/parallel_structure.spec.ts b/spec/structure/parallel_structure.spec.ts
index a473e54cfed2ff39ac5cba2a01c7b619ffe90a7e..8a01b1d2014e232fa97f1147a6ae49803962326f 100644
--- a/spec/structure/parallel_structure.spec.ts
+++ b/spec/structure/parallel_structure.spec.ts
@@ -18,35 +18,36 @@ import { checkResult } from "../test_func";
 import { testParallelStructures } from "./functions";
 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
- */
+function createEnv() {
+    const pstruct = new ParallelStructure(
+        new ParallelStructureParams(30, 30, 15), // Q = 30, Z1 = 30, Z2 = 15
+        false // debug
+    );
+    /*
+     * Tests avec deux structures test identiques
+     */
+    pstruct.addChild(structTest);
+    pstruct.addChild(structTest);
+    return pstruct;
+}
 
-pstruct.addChild(structTest);
-pstruct.addChild(structTest);
+let pstruct: ParallelStructure;
 
 describe("Class ParallelStructure: ", () => {
     describe("Calc()", () => {
+        beforeEach(() => {
+            pstruct = createEnv();
+        });
         it("should return 1 result", () => {
-            const res: Result = pstruct.Calc("Q");
-            expect(pstruct.Calc("Q").nbResultElements).toEqual(1);
+            const p1 = createEnv();
+            const res: Result = p1.Calc("Q");
+            expect(p1.Calc("Q").nbResultElements).toEqual(1);
         });
-        itParallelStructure("Q", 30, 15);
-        itParallelStructure("Z1", 30, 15);
-        itParallelStructure("Z2", 15, 15);
-        itParallelStructure({
-            uid: pstruct.structures[0].uid,
-            symbol: "ZDV"
-        }, 0, 15);
-        itParallelStructure({
-            uid: pstruct.structures[1].uid,
-            symbol: "ZDV"
-        }, 0, 15);
+        itParallelStructure(null, "Q", 30, 15);
+        itParallelStructure(null, "Z1", 30, 15);
+        itParallelStructure(null, "Z2", 15, 15);
+        itParallelStructure(0, "ZDV", 0, 15);
+        itParallelStructure(1, "ZDV", 0, 15);
         it("shoud return an error Q too high", () => {
             pstruct.prms.Q.v = 14;
             const res: Result = pstruct.Calc({
@@ -57,6 +58,16 @@ describe("Class ParallelStructure: ", () => {
         });
     });
 });
+function getVarCalc(pstructLoc: ParallelStructure, structIndex: number, sVarCalc: string) : any { 
+    if (structIndex !== null) {
+        return {
+            uid: pstructLoc.structures[structIndex].uid,
+            symbol: sVarCalc
+        };
+    } else {
+        return sVarCalc;
+    }
+}
 
 /**
  * Test sur ParallelStructure
@@ -64,25 +75,30 @@ describe("Class ParallelStructure: ", () => {
  * @param rVcalc Valeur de référence à retrouver
  * @param Q Débit de chacune des structures (pour structures identiques uniquement)
  */
-function itParallelStructure(sVarCalc: any, rVcalc: number, Q?: number) {
+function itParallelStructure(structIndex: number, sVarCalc: string, rVcalc: number, Q?: number) {  
     it(`${sVarCalc} should be ${rVcalc}`, () => {
-        checkResult(pstruct.Calc(sVarCalc), rVcalc);
+        const VC1: any = getVarCalc(pstruct, structIndex, sVarCalc);
+        checkResult(pstruct.Calc(VC1), rVcalc);
     });
     if (Q !== undefined) {
-        for (let i = 0; i < pstruct.structures.length; i++) {
-            it(`ExtraResult[ouvrage[${i}].Q] should be ${Q}`, () => {
+        const pstructLocal = createEnv();
+        for (let i = 0; i < pstructLocal.structures.length; i++) {
+            it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q] should be ${Q}`, () => {
+                const VC2: any = getVarCalc(pstruct, structIndex, sVarCalc);
                 expect(
-                    pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q`]
+                    pstruct.Calc(VC2).resultElement.extraResults[`ouvrage[${i}].Q`]
                 ).toBeCloseTo(Q, Math.max(0, precDigits - 1));
             });
-            it(`ExtraResult[ouvrage[${i}].Q_Mode] should be 0`, () => {
+            it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q_Mode] should be 0`, () => {
+                const VC3 = getVarCalc(pstruct, structIndex, sVarCalc);
                 expect(
-                    pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowMode`]
+                    pstruct.Calc(VC3).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowMode`]
                 ).toEqual(0);
             });
-            it(`ExtraResult[ouvrage[${i}].Q_Regime] should be 0`, () => {
+            it(`Calc(${JSON.stringify(sVarCalc)}) ExtraResult[ouvrage[${i}].Q_Regime] should be 0`, () => {
+                const VC4 = getVarCalc(pstruct, structIndex, sVarCalc);
                 expect(
-                    pstruct.Calc(sVarCalc).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowRegime`]
+                    pstruct.Calc(VC4).resultElement.extraResults[`ouvrage[${i}].Q_ENUM_StructureFlowRegime`]
                 ).toEqual(0);
             });
         }
diff --git a/spec/value_ref/value_ref.spec.ts b/spec/value_ref/value_ref.spec.ts
index c07d15df38100e24403282aca46a88343773331c..c101298864c894401e8b4b5257bdcbbba19af3a5 100644
--- a/spec/value_ref/value_ref.spec.ts
+++ b/spec/value_ref/value_ref.spec.ts
@@ -6,7 +6,7 @@
  */
 // import { describe, expect, it } from "../mock_jasmine";
 
-import { Result, Session } from "../../src/index";
+import { Result, Session, ParamValueMode } from "../../src/index";
 import { NubTest, NubTestParams } from "../nubtest";
 import { precDigits } from "../test_config";
 
@@ -42,15 +42,16 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.A.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1)
+            // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1)
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "A");
 
-            expect(prm1.A.v).toEqual(1);
-            expect(prm1.B.v).toEqual(2);
-            expect(prm1.C.v).toEqual(3);
-            expect(prm2.A.v).toEqual(1);
-            expect(prm2.B.v).toEqual(2);
-            expect(prm2.C.v).toEqual(3);
+            expect(prm1.A.singleValue).toEqual(1);
+            expect(prm1.B.singleValue).toEqual(2);
+            expect(prm1.C.singleValue).toEqual(3);
+            expect(prm2.A.singleValue).toEqual(1);
+            expect(prm2.B.singleValue).toEqual(2);
+            expect(prm2.C.singleValue).toEqual(3);
         });
 
         it("test 2", () => {
@@ -60,15 +61,16 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.B.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.B, normalement 2)
+            // valeur esclave, doit être masquée par la valeur maître (cad prm1.B, normalement 2)
+            prm2.B.singleValue = 0;
             prm2.B.defineReference(nub1, "B");
 
-            expect(prm1.A.v).toEqual(1);
-            expect(prm1.B.v).toEqual(2);
-            expect(prm1.C.v).toEqual(3);
-            expect(prm2.A.v).toEqual(1);
-            expect(prm2.B.v).toEqual(2);
-            expect(prm2.C.v).toEqual(3);
+            expect(prm1.A.singleValue).toEqual(1);
+            expect(prm1.B.singleValue).toEqual(2);
+            expect(prm1.C.singleValue).toEqual(3);
+            expect(prm2.A.singleValue).toEqual(1);
+            expect(prm2.B.singleValue).toEqual(2);
+            expect(prm2.C.singleValue).toEqual(3);
         });
 
         it("test 3", () => {
@@ -78,18 +80,19 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.C.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            prm2.C.singleValue = 0;
             prm2.C.defineReference(nub1, "C");
 
             // as C is a calculated param
             nub2.triggerChainCalculation();
 
-            expect(prm1.A.v).toEqual(1);
-            expect(prm1.B.v).toEqual(2);
-            expect(prm1.C.v).toEqual(3);
-            expect(prm2.A.v).toEqual(1);
-            expect(prm2.B.v).toEqual(2);
-            expect(prm2.C.v).toEqual(3);
+            expect(prm1.A.singleValue).toEqual(1);
+            expect(prm1.B.singleValue).toEqual(2);
+            expect(prm1.C.singleValue).toEqual(3);
+            expect(prm2.A.singleValue).toEqual(1);
+            expect(prm2.B.singleValue).toEqual(2);
+            expect(prm2.C.singleValue).toEqual(3);
         });
 
         it("test 4", () => {
@@ -99,7 +102,8 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.A.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1)
+            // valeur esclave, doit être masquée par la valeur maître (cad prm1.A, normalement 1)
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "A");
 
             expect(nub1.Calc("A").vCalc).toBeCloseTo(1, precDigits);
@@ -118,18 +122,18 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm1.B.v = 3;  // valeur maître
-            prm2.B.v = 0;  // valeur esclave (doit être masquée par la valeur maître)
+            prm1.B.singleValue = 3;  // valeur maître
+            prm2.B.singleValue = 0;  // valeur esclave (doit être masquée par la valeur maître)
             prm2.B.defineReference(nub1, "B");
 
-            expect(nub1.Calc("A").vCalc).toBeCloseTo(0, precDigits);
-            expect(nub1.Calc("B").vCalc).toBeCloseTo(3, precDigits);
-            expect(nub1.Calc("C").vCalc).toBeCloseTo(3, precDigits);
+            expect(nub1.CalcSerie(undefined, "A").vCalc).toBeCloseTo(0, precDigits);
+            expect(nub1.CalcSerie(undefined, "B").vCalc).toBeCloseTo(2, precDigits);
+            expect(nub1.CalcSerie(undefined, "C").vCalc).toBeCloseTo(4, precDigits);
+
+            expect(nub2.CalcSerie(undefined, "A").vCalc).toBeCloseTo(0, precDigits);
+            expect(nub2.CalcSerie(undefined, "B").vCalc).toBeCloseTo(2, precDigits);
+            expect(nub2.CalcSerie(undefined, "C").vCalc).toBeCloseTo(4, precDigits);
 
-            expect(nub2.Calc("A").vCalc).toBeCloseTo(0, precDigits);
-            // tslint:disable-next-line:max-line-length
-            // expect(nub2.Calc("B").vCalc).toBeCloseTo(3, precDigits); // échoue car l'écriture du paramètre esclave (pendant la dichotomie) n'affecte pas la valeur maître; la relecture du paramètre esclave ne reflète pas la valeur écrite
-            expect(nub2.Calc("C").vCalc).toBeCloseTo(3, precDigits);
         });
 
         it("test 6", () => {
@@ -139,7 +143,8 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.C.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            // valeur esclave, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            prm2.C.singleValue = 0;
             prm2.C.defineReference(nub1, "C");
 
             expect(nub1.Calc("A").vCalc).toBeCloseTo(1, precDigits);
@@ -160,15 +165,16 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm1.B.v = 5;
+            prm1.B.singleValue = 5;
             nub1.calculatedParam = prm1.C;
-            prm2.A.v = 0;  // valeur esclave (doit être masquée par la valeur maître, cad prm1.C, normalement 3)
+            // valeur esclave (doit être masquée par la valeur maître, cad prm1.C, normalement 3)
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "C");
 
             // as C is a calculated param
             nub2.triggerChainCalculation();
 
-            expect(prm2.A.v).toBeCloseTo(6, precDigits);
+            expect(prm2.A.singleValue).toBeCloseTo(6, precDigits);
         });
 
         it("test 2", () => {
@@ -178,16 +184,14 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm1.C.v = 0;  // valeur bidon, doit être 3 après calcul
+            prm1.C.singleValue = 0;  // valeur bidon, doit être 3 après calcul
             nub1.calculatedParam = prm1.C;
-            prm2.C.v = 0;  // valeur bidon, doit être 5 après calcul
-            prm2.A.v = 0;  // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            prm2.C.singleValue = 0;  // valeur bidon, doit être 5 après calcul
+            // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.C, normalement 3)
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "C");
 
-            // as C is a calculated param
-            nub2.triggerChainCalculation();
-
-            expect(nub2.Calc("C").vCalc).toBeCloseTo(5, precDigits);
+            expect(nub2.CalcSerie(undefined, "C").vCalc).toBeCloseTo(5, precDigits);
         });
 
         it("test 3", () => {
@@ -204,7 +208,7 @@ describe("référence d'un paramètre à un autre : ", () => {
             prm1.A.setValues(min, max, step);
 
             // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.A, normalement [1,2,3,4,5])
-            prm2.A.v = 0;
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "A");
 
             let n = 0;
@@ -228,9 +232,9 @@ describe("référence d'un paramètre à un autre : ", () => {
             prm1.A.setValues(input);
 
             // valeur esclave bidon, doit être masquée par la valeur maître (cad prm1.A, normalement [2,3,4,5,6])
-            prm2.A.v = 0;
+            prm2.A.singleValue = 0;
             prm2.A.defineReference(nub1, "A");
-            prm2.Pr.v = 0.001;
+            prm2.Pr.singleValue = 0.001;
 
             const r: Result = nub2.CalcSerie(0.1, "C");
 
diff --git a/spec/value_ref/value_ref_indirect.spec.ts b/spec/value_ref/value_ref_indirect.spec.ts
index 9e59d8766dd39005dfd4c3552296be7ae27eb6b2..aca3ba20d54efab48f4e95bc6fe2a572a1bf8212 100644
--- a/spec/value_ref/value_ref_indirect.spec.ts
+++ b/spec/value_ref/value_ref_indirect.spec.ts
@@ -29,14 +29,14 @@ let prm4: DeverParams;
 function createEnv() {
     // Nub 1 : Régime Uniforme
     const paramSect = new ParamsSectionCirc(2, 0.6613, 40, 1.2, 0.001, 1);
-    paramSect.Pr.v = 0.01;
+    paramSect.Pr.singleValue = 0.01;
     const sect = new cSnCirc(paramSect);
     nub1 = new RegimeUniforme(sect);
     prm1 = nub1.section.prms as ParamsSectionCirc;
 
     // Nub 2 : Section Paramétrée
     const prmsS = new ParamsSectionTrapez(1, 0.5, 1, 0.01, 1, 0.01, 2);
-    prmsS.Pr.v = 0.01;
+    prmsS.Pr.singleValue = 0.01;
     nub2 = new SectionParametree(new cSnTrapez(prmsS));
     prm2 = nub2.section.prms as ParamsSectionTrapez; // = prmsS
 
@@ -46,7 +46,7 @@ function createEnv() {
 
     // Nub 4 : Déversoirs Dénoyés
     prm4 = new DeverParams(0.5, 102, 10, 99);
-    prm4.Pr.v = 0.01;
+    prm4.Pr.singleValue = 0.01;
     nub4 = new Dever(prm4);
     nub4.addChild(
         CreateStructure(
@@ -72,7 +72,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm3.Y.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
+        prm3.Y.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
         prm3.Y.defineReference(nub2.section, "Y");
         prm2.Y.defineReference(nub1.section, "Y");
 
@@ -88,7 +88,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm3.Y.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
+        prm3.Y.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
         prm3.Y.defineReference(nub2.section, "Y");
         prm2.Y.defineReference(nub1.section, "Y");
         prm1.Y.setValues(2, 5, 1);
@@ -105,12 +105,11 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm3.Y.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
+        prm3.Y.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
         prm3.Y.defineReference(nub2.section, "Y");
         prm2.Y.defineReference(nub1.section, "Y");
 
-        prm1.LargeurBerge.v = 3.5; // Section Circ !
-        prm1.Ks.v = 42;
+        prm1.Ks.singleValue = 42;
         nub1.calculatedParam = prm1.Y;
 
         nub3.CalcSerie();
@@ -125,12 +124,12 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm3.Y.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
+        prm3.Y.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.Y)
         prm3.Y.defineReference(nub2.section, "Y");
         prm2.Y.defineReference(nub1.section, "Y");
 
         prm1.D.setValues(2.5, 7, 0.5);
-        prm1.Ks.v = 42;
+        prm1.Ks.singleValue = 42;
         nub1.calculatedParam = prm1.Y;
 
         nub3.CalcSerie();
@@ -154,7 +153,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm1.Q.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q)
+        prm1.Q.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q)
         prm1.Q.defineReference(nub2.section, "Q");
         nub1.calculatedParam = prm1.Ks;
         prm2.Q.defineReference(nub4, "CvQT");
@@ -173,7 +172,7 @@ describe("référence indirecte d'un paramètre à un autre : ", () => {
 
         createEnv();
 
-        prm1.Q.v = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q)
+        prm1.Q.singleValue = 0.1;  // valeur esclave, doit être masquée par la valeur maître (cad prm4.Q)
         prm1.Q.defineReference(nub2.section, "Q");
         nub1.calculatedParam = prm1.Ks;
         prm2.Q.defineReference(nub4, "CvQT");
diff --git a/spec/value_ref/value_ref_section.spec.ts b/spec/value_ref/value_ref_section.spec.ts
index 50c1d19e6419ec62779b975ed7799bed2bc2b25c..4dec46b616240f2baf4b5511b19816800cba6f2a 100644
--- a/spec/value_ref/value_ref_section.spec.ts
+++ b/spec/value_ref/value_ref_section.spec.ts
@@ -51,12 +51,12 @@ describe("référence d'un paramètre à un autre : ", () => {
 
             createEnv();
 
-            prm2.Q.v = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.CvQT)
+            prm2.Q.singleValue = 0;  // valeur esclave, doit être masquée par la valeur maître (cad prm1.CvQT)
             prm2.Q.defineReference(nub1, "CvQT");
 
-            nub2.CalcSerie();
+            nub2.CalcSerie(); // triggers chain calculation
 
-            expect(prm2.Q.v).toBeCloseTo(10.106);
+            expect(prm2.Q.singleValue).toBeCloseTo(10.106);
         });
     });
 });
diff --git a/src/dichotomie.ts b/src/dichotomie.ts
index b17acfe1bfd897b7f52ea572e4c3ff058034a1df..21f744078216404a30bf51b7db6b541e18936b13 100644
--- a/src/dichotomie.ts
+++ b/src/dichotomie.ts
@@ -159,7 +159,7 @@ export class Dichotomie extends Debug {
     }
 
     private set vX(vCalc: number) {
-        this._paramX.setValue(vCalc);
+        this._paramX.v = vCalc;
     }
 
     /**
diff --git a/src/linked-value.ts b/src/linked-value.ts
index 9de169224e6fc016b6e4a57478df2163e78100d0..b817cdecded268cd9e929a940317b0faf333c5c1 100644
--- a/src/linked-value.ts
+++ b/src/linked-value.ts
@@ -3,7 +3,6 @@ import { ParamDefinition } from "./param/param-definition";
 import { INamedIterableValues } from "./param/param-value-iterator";
 import { ParamValueMode } from "./param/param-value-mode";
 import { ParamValues } from "./param/param-values";
-import { Message, MessageCode } from "./util/message";
 
 export class LinkedValue {
     /** linked value metadata (ex: calculator title for GUI) */
@@ -134,10 +133,6 @@ export class LinkedValue {
                         if (targetParam.hasMultipleValues) {
                             const multipleRes = this.nub.result.getCalculatedValues();
                             this._paramValues.setValues(multipleRes);
-                            if (this._paramValues.currentValue === undefined) {
-                                // or else isDefined() will return false
-                                this._paramValues.currentValue = multipleRes[0];
-                            }
                         } else {
                             const singleRes = this.nub.result.vCalc;
                             this._paramValues.setValues(singleRes);
@@ -146,9 +141,6 @@ export class LinkedValue {
                     // return local cache
                     ret = this._paramValues;
                 } else {
-                    // else simple parameter proxy (see below)
-                    // @TODO why ? risk of getting obsolete values !
-                    // ret = targetParam.paramValues;
                     throw new Error("LinkedValue.getParamValues() - result not available");
                 }
 
@@ -169,10 +161,6 @@ export class LinkedValue {
                     if (this.nub.resultHasMultipleValues()) {
                         const multipleExtraRes = this.nub.result.getExtraResults(this.symbol);
                         this._paramValues.setValues(multipleExtraRes);
-                        if (this._paramValues.currentValue === undefined) {
-                            // or else isDefined() will return false
-                            this._paramValues.currentValue = multipleExtraRes[0];
-                        }
                     } else {
                         const singleExtraRes = this.nub.result.getExtraResult(this.symbol);
                         this._paramValues.setValues(singleExtraRes);
@@ -192,33 +180,12 @@ export class LinkedValue {
     }
 
     /**
-     * Returns the current value of this.paramValues; triggers a chain computation
-     * if required to obtain ParamValues; throws an error if this.paramValues is
-     * ultimately not defined
+     * Returns the single value of this.paramValues; triggers a chain computation
+     * if required to obtain ParamValues
      */
     public getValue(triggerChainComputation: boolean = false) {
         const pv = this.getParamValues(triggerChainComputation);
-        if (! pv.isDefined) {
-            const e = new Message(MessageCode.ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED);
-            e.extraVar.symbol = this.symbol;
-            throw e;
-        }
-        return pv.currentValue;
-    }
-
-    /**
-     * Returns the current multiple values list of this.paramValues; triggers a
-     * chain computation if required to obtain ParamValues; throws an error if
-     * this.paramValues is ultimately not defined
-     */
-    public getValues(triggerChainComputation: boolean = false): number[] {
-        const pv = this.getParamValues(triggerChainComputation);
-        if (! pv.isDefined) {
-            const e = new Message(MessageCode.ERROR_PARAMDEF_LINKED_VALUE_UNDEFINED);
-            e.extraVar.symbol = this.symbol;
-            throw e;
-        }
-        return pv.valueList;
+        return pv.singleValue;
     }
 
     /**
@@ -236,6 +203,17 @@ export class LinkedValue {
         return false;
     }
 
+    /**
+     * Returns true if target value is available
+     */
+    public isDefined() {
+        if (this.isExtraResult()) {
+            return (this.nub.result !== undefined);
+        } else {
+            return (this.element as ParamDefinition).isDefined;
+        }
+    }
+
     /**
      * When invalidating a Nub's result, parameters pointing to this result should
      * invalidate their proxy paramValues too
@@ -243,4 +221,17 @@ export class LinkedValue {
     public invalidateParamValues() {
         this._paramValues = undefined;
     }
+
+    /**
+     * Calles before calculation: asks target parameter to copy its
+     * single value to its current value so that .v is up to date
+     */
+    public setCurrentValueFromSingleValue() {
+        if (this.isParameter()) {
+            const targetParam = (this.element as ParamDefinition);
+            if (targetParam.valueMode === ParamValueMode.SINGLE) {
+                targetParam.paramValues.currentValue = targetParam.paramValues.singleValue;
+            }
+        }
+    }
 }
diff --git a/src/nub.ts b/src/nub.ts
index f18235deb176287136d9b1d624e95f23e19eda29..4cbca8c0aeb50b5dd41c82e1c1db0936625e5052 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -256,7 +256,7 @@ export abstract class Nub extends ComputeNode implements IObservable {
             return this._result;
         }
         const sAnalyticalPrm: string = this.getFirstAnalyticalParameter().symbol;
-        computedVar.setValue(resSolve.vCalc);
+        computedVar.v = resSolve.vCalc;
         const res: Result = this.Equation(sAnalyticalPrm);
         res.vCalc = resSolve.vCalc;
         this._result = res;
@@ -298,8 +298,10 @@ export abstract class Nub extends ComputeNode implements IObservable {
         this.progress = 0;
         this.triggerChainCalculation();
 
+        this.copySingleValuesToCurrentValues();
+
+        // check which values are variating, if any
         for (const p of this.parameterIterator) {
-            // checks which values are variating, if any
             switch (p.valueMode) {
                 case ParamValueMode.SINGLE:
                 case ParamValueMode.CALCUL:
@@ -360,7 +362,8 @@ export abstract class Nub extends ComputeNode implements IObservable {
 
             variatedValues.initValuesIterator(false);
             while (variatedValues.hasNext) {
-                variatedValues.next();
+                const currentIteratorValue = variatedValues.next();
+                variatedParam.v = currentIteratorValue.value; // copy to local sandbox value
 
                 this.Calc(computedSymbol, rInit);  // résultat dans this._result
                 if (this._result.ok) {
@@ -1019,6 +1022,31 @@ export abstract class Nub extends ComputeNode implements IObservable {
         this._observable.notifyObservers(data, sender);
     }
 
+    /**
+     * For all SINGLE, LINK and CALC parameters, copies singleValue to
+     * currentValue (.v) before calculation
+     */
+    protected copySingleValuesToCurrentValues() {
+        for (const p of this.parameterIterator) {
+            switch (p.valueMode) {
+                case ParamValueMode.SINGLE:
+                case ParamValueMode.CALCUL:
+                    p.v = p.singleValue;
+                    break;
+                case ParamValueMode.LINK:
+                    if (p.referencedValue) {
+                        p.v = p.referencedValue.getValue();
+                    } else {
+                        throw Error("Nub.CalcSerie() : linked value not defined");
+                    }
+                    break;
+                default:
+                    // variable mode, let iterator do the job
+                    p.v = undefined;
+            }
+        }
+    }
+
     /**
      * To call Nub.calc(…) from indirect child
      */
diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts
index 13b100c3b7c605837b1a4c51322a232d588f32c7..fc9b44f5ea2c5b780f66f7046d0e5a3c5f90e3a6 100644
--- a/src/param/param-definition.ts
+++ b/src/param/param-definition.ts
@@ -50,6 +50,9 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     /** le paramètre doit-il être exposé (par ex: affiché par l'interface graphique) ? */
     public visible: boolean = true;
 
+    /** sandbox value used during calculation */
+    public v: number;
+
     /** mode de génération des valeurs : min/max, liste, ... */
     private _valueMode: ParamValueMode;
 
@@ -84,7 +87,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
         this._symbol = symb;
         this._observable = new Observable();
         this._paramValues = new ParamValues();
+
+        // set single value and copy it to currentValue
         this._paramValues.singleValue = val;
+        this.v = val;
+
         this._calc = ParamCalculability.FREE;
         this._family = family;
         this.visible = visible;
@@ -370,74 +377,84 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     }
 
     /**
-     * Proxy to getValue(); never triggers chain computation
+     * Returns true if current value (not singleValue !) is defined
      */
-    get v(): number {
-        return this.getValue();
+    public get hasCurrentValue(): boolean {
+        return (this.v !== undefined);
     }
 
     /**
-     * set value, with calculability control
-     * @TODO move calculability control to setValue() ?
+     * Returns true if held value (not currentValue !) is defined,
+     * depending on the value mode
      */
-    set v(val: number) {
-        if (this.calculability === ParamCalculability.NONE) {
-            const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_FIXED);
-            e.extraVar.symbol = this.symbol;
-            throw e;
-        }
-        this.setValue(val);
-    }
-
     public get isDefined(): boolean {
-        try {
-            return this.paramValues.isDefined;
-        } catch (e) {
-            // unavailable targetted result (pending calculation)
-            return false;
+        let defined = false;
+        switch (this.valueMode) {
+            case ParamValueMode.SINGLE:
+                defined = (this.singleValue !== undefined);
+                break;
+            case ParamValueMode.MINMAX:
+                defined = (
+                    this.paramValues.min !== undefined
+                    && this.paramValues.max !== undefined
+                    && this.paramValues.step !== undefined
+                );
+                break;
+            case ParamValueMode.LISTE:
+                defined = (this.valueList.length > 0 && this.valueList[0] !== undefined);
+                break;
+            case ParamValueMode.CALCUL:
+                if (this.parentNub && this.parentNub.result && this.parentNub.result.nbResultElements > 0) {
+                    const res = this.parentNub.result;
+                    defined = (res.vCalc !== undefined);
+                }
+                break;
+            case ParamValueMode.LINK:
+                defined = this.referencedValue.isDefined();
         }
+        return defined;
     }
 
     // -- values getters / setters; in LINK mode, reads / writes from / to the target values
 
     public get singleValue(): number {
-        this.checkValueMode(ParamValueMode.SINGLE);
+        this.checkValueMode([ParamValueMode.SINGLE, ParamValueMode.CALCUL, ParamValueMode.LINK]);
         return this.paramValues.singleValue;
     }
 
     public set singleValue(v: number) {
-        this.checkValueMode(ParamValueMode.SINGLE);
+        this.checkValueMode([ParamValueMode.SINGLE, ParamValueMode.CALCUL, ParamValueMode.LINK]);
         this.paramValues.singleValue = v;
         this.notifyValueModified(this);
     }
 
     public get min() {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]);
         return this.paramValues.min;
     }
 
     public set min(v: number) {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX]);
         this.paramValues.min = v;
     }
 
     public get max() {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]);
         return this.paramValues.max;
     }
 
     public set max(v: number) {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX]);
         this.paramValues.max = v;
     }
 
     public get step() {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX, ParamValueMode.LINK]);
         return this.paramValues.step;
     }
 
     public set step(v: number) {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX]);
         this.paramValues.step = v;
     }
 
@@ -445,17 +462,17 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
      * Generates a reference step value, given the current (local) values for min / max
      */
     public get stepRefValue(): Interval {
-        this.checkValueMode(ParamValueMode.MINMAX);
+        this.checkValueMode([ParamValueMode.MINMAX]);
         return new Interval(1e-9, this._paramValues.max - this._paramValues.min);
     }
 
     public get valueList() {
-        this.checkValueMode(ParamValueMode.LISTE);
+        this.checkValueMode([ParamValueMode.LISTE, ParamValueMode.LINK]);
         return this.paramValues.valueList;
     }
 
     public set valueList(l: number[]) {
-        this.checkValueMode(ParamValueMode.LISTE);
+        this.checkValueMode([ParamValueMode.LISTE]);
         this.paramValues.valueList = l;
     }
 
@@ -463,23 +480,22 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
         return this.paramValues.valuesIterator.count();
     }
 
-    /**
-     * Get current value (not singleValue !)
-     * Might throw an error if parameter is in LINK mode, and target
-     * value is a result that is not yet computed
-     */
-    public getValue(): number {
-        if (! this.paramValues.isDefined) {
-            const e = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
-            e.extraVar.symbol = this.symbol;
-            throw e;
-        }
+    // for INumberiterator interface
+    public get currentValue(): number {
+        // magically follows links
         return this.paramValues.currentValue;
     }
 
-    // for INumberiterator interface
-    public get currentValue(): number {
-        return this.getValue();
+    public set currentValue(v: number) {
+        // magically follows links
+        this.paramValues.currentValue = v;
+    }
+
+    /**
+     * Get single value
+     */
+    public getValue(): number {
+        return this.paramValues.singleValue;
     }
 
     /**
@@ -507,7 +523,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
      */
     public setValue(val: number, sender?: any) {
         this.checkValueAgainstDomain(val);
-        this.paramValues.currentValue = val;
+        this.paramValues.singleValue = val;
         // this.notifyValueModified(sender); // @TODO why ? currentValue is only used temporarily for calculation
     }
 
@@ -590,11 +606,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
     }
 
     /**
-     * Return true if current value is valid regarding the domain constraints
+     * Return true if single value is valid regarding the domain constraints
      */
     get isValueValid(): boolean {
         try {
-            const v = this.getValue();
+            const v = this.paramValues.singleValue;
             this.checkValueAgainstDomain(v);
             return true;
         } catch (e) {
@@ -760,7 +776,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
         // adjust parameter representation depending on value mode
         switch (this._valueMode) {
             case ParamValueMode.SINGLE:
-                paramRep.value = this.getValue();
+                paramRep.value = this.singleValue;
                 break;
 
             case ParamValueMode.MINMAX:
@@ -1100,9 +1116,11 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
      * In LINK mode, the tested valueMode is the mode of the ultimately targetted
      * set of values (may never be LINK)
      */
-    private checkValueMode(expected: ParamValueMode) {
-        if (this.paramValues.valueMode !== expected) {
-            throw new Error(`ParamValues : mode de valeurs ${ParamValueMode[expected]} incorrect`);
+    private checkValueMode(expected: ParamValueMode[]) {
+        if (! expected.includes(this.valueMode)) {
+            throw new Error(
+                `ParamDefinition : mode de valeurs ${ParamValueMode[this.valueMode]} incorrect`
+            );
         }
     }
 
diff --git a/src/param/param-values.ts b/src/param/param-values.ts
index badb8433f819f721766be6945e081e18fbbf2842..e367f6173174cf6ee1fe1afbac0da1a33ba9a434 100644
--- a/src/param/param-values.ts
+++ b/src/param/param-values.ts
@@ -42,7 +42,6 @@ export class ParamValues implements IterableValues {
 
     public set singleValue(v: number) {
         this._singleValue = v;
-        this.currentValue = v;
     }
 
     public count() {
@@ -54,18 +53,15 @@ export class ParamValues implements IterableValues {
             if (max === undefined) {
                 this.valueMode = ParamValueMode.SINGLE;
                 this.singleValue = o;
-                this.currentValue = o;
             } else {
                 this.valueMode = ParamValueMode.MINMAX;
                 this.min = o;
                 this.max = max;
                 this.step = step;
-                this.currentValue = undefined;
             }
         } else if (Array.isArray(o)) {
             this.valueMode = ParamValueMode.LISTE;
             this.valueList = o;
-            this.currentValue = undefined;
         } else {
             throw new Error(`ParamValues.setValues() :  appel invalide`);
         }
@@ -107,10 +103,6 @@ export class ParamValues implements IterableValues {
         }
     }
 
-    public get isDefined() {
-        return this.currentValue !== undefined;
-    }
-
     // -- iterator-related methods
 
     /**
diff --git a/src/section/section_circulaire.ts b/src/section/section_circulaire.ts
index 4ff68af501fbcdcc70f02a0985eb0d4d341e4d1e..af68e902e0e87710bff49ebcfb450b4a9790135b 100644
--- a/src/section/section_circulaire.ts
+++ b/src/section/section_circulaire.ts
@@ -92,7 +92,7 @@ export class cSnCirc extends acSection {
                 }
 
                 this.debug("circ.Calc_B() : PAS débordement");
-                if (this.prms.D.isDefined && this.prms.Y.isDefined) {
+                if (this.prms.D.hasCurrentValue && this.prms.Y.hasCurrentValue) {
                         const rAlpha: Result = this.calcFromY("Alpha");
                         if (!rAlpha.ok) {
                                 return rAlpha;
@@ -104,8 +104,8 @@ export class cSnCirc extends acSection {
                 }
 
                 const e: Message = new Message(MessageCode.ERROR_PARAMDEF_VALUE_UNDEFINED);
-                e.extraVar.diameterValue = this.prms.D.isDefined ? String(this.prms.D.v) : "undefined";
-                e.extraVar.yValue = this.prms.Y.isDefined ? String(this.prms.Y.v) : "undefined";
+                e.extraVar.diameterValue = this.prms.D.hasCurrentValue ? String(this.prms.D.v) : "undefined";
+                e.extraVar.yValue = this.prms.Y.hasCurrentValue ? String(this.prms.Y.v) : "undefined";
                 throw e;
         }
 
diff --git a/src/structure/cloisons.ts b/src/structure/cloisons.ts
index 5dd0b51964c721398197427a7969dd2e84f07f6e..70c53d652a19b553392cebc59db21dac23327a25 100644
--- a/src/structure/cloisons.ts
+++ b/src/structure/cloisons.ts
@@ -5,7 +5,7 @@ import { ParamCalculability } from "../param/param-definition";
 import { Result } from "../util/result";
 import { CloisonsParams } from "./cloisons_params";
 import { ParallelStructure } from "./parallel_structure";
-import { StructureKivi, StructureKiviParams } from "./structure_kivi";
+import { StructureKiviParams } from "./structure_kivi";
 import { loiAdmissiblesCloisons, LoiDebit } from "./structure_props";
 
 export { CloisonsParams };
@@ -54,7 +54,7 @@ export class Cloisons extends ParallelStructure {
             case "BB":
                 r = this.nubCalc(sVC, rInit);
                 if (r.ok) {
-                    this.getParameter(sVC).setValue(r.vCalc);
+                    this.getParameter(sVC).v = r.vCalc;
                 }
                 break;
             default:
diff --git a/src/structure/dever.ts b/src/structure/dever.ts
index fedcf19599084101a75386072526d3feee0eaba2..368510fea9558dc5a089ccfd74e5ef47e65806c4 100644
--- a/src/structure/dever.ts
+++ b/src/structure/dever.ts
@@ -67,7 +67,7 @@ export class Dever extends ParallelStructure {
             case "ZR":
                 res = this.nubCalc(sVarCalc, rInit);
                 if (res.ok) {
-                    this.getParameter(sVarCalc).setValue(res.vCalc);
+                    this.getParameter(sVarCalc).v = res.vCalc;
                 }
                 break;
             default:
diff --git a/src/structure/factory_structure.ts b/src/structure/factory_structure.ts
index f1f0b7c069d03772125befd1885995c09e1be794..1379b405f308414b607978ff940bef0966d7775d 100644
--- a/src/structure/factory_structure.ts
+++ b/src/structure/factory_structure.ts
@@ -39,7 +39,7 @@ export function CreateStructure(loiDebit: LoiDebit, parentNub?: ParallelStructur
         case LoiDebit.Cunge80:
         case LoiDebit.RectangularOrificeFree:
         case LoiDebit.RectangularOrificeSubmerged:
-            rectStructPrms.W.v = 0.5;
+            rectStructPrms.W.singleValue = 0.5;
             rectStructPrms.Cd.v = oCd.VanneR; // Cd pour une vanne rectangulaire
     }
 
diff --git a/src/structure/parallel_structure.ts b/src/structure/parallel_structure.ts
index 7b589783e9e8a691e86169891de7852f0fc1e564..2f4f8e32a49a17ff2db8ed51f02d1c95173c2730 100644
--- a/src/structure/parallel_structure.ts
+++ b/src/structure/parallel_structure.ts
@@ -105,7 +105,7 @@ export class ParallelStructure extends Nub {
             case "Q":
                 res = super.Calc(sVarCalc, rInit);
                 if (res.ok) {
-                    this.getParameter(sVarCalc).setValue(res.vCalc);
+                    this.getParameter(sVarCalc).v = res.vCalc;
                 }
                 break;
             default:
@@ -118,7 +118,7 @@ export class ParallelStructure extends Nub {
                 // Suppression des extraResults : ils sont complétés plus bas pour chaque ouvrage
                 res.resultElement.extraResults = {};
                 if (res.ok) {
-                    this._children[structureIndex].getParameter(sVarCalc.symbol).setValue(res.vCalc);
+                    this._children[structureIndex].getParameter(sVarCalc.symbol).v = res.vCalc;
                 }
         }
         if (res.ok) {
@@ -179,7 +179,7 @@ export class ParallelStructure extends Nub {
      */
     protected CalcStructPrm(index: number, symbol: string, rInit?: number): Result {
         // Le débit restant sur la structure en calcul est :
-        this.structures[index].prms.Q.setValue(this.prms.Q.v - this.CalcQ(index).vCalc);
+        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(symbol, rInit);
diff --git a/src/structure/structure_cem88d.ts b/src/structure/structure_cem88d.ts
index 8c08a710694713d4cc809de003996e08f22f269d..7d960877c7196de70d66a60fcdee71b7c14a10c6 100644
--- a/src/structure/structure_cem88d.ts
+++ b/src/structure/structure_cem88d.ts
@@ -6,8 +6,6 @@ import { LoiDebit } from "./structure_props";
 
 export { RectangularStructureParams };
 
-
-
 /**
  * Equation CEM88D : déversoir / orifice (pelle importante) Cemagref 1988
  */