diff --git a/spec/macrorugo/macrorugo.spec.ts b/spec/macrorugo/macrorugo.spec.ts
index 882c2d461d98ed1dccca593264618932a2295319..3f1de14c2a0e5f34a5b48652d5d7d42ecc820761 100644
--- a/spec/macrorugo/macrorugo.spec.ts
+++ b/spec/macrorugo/macrorugo.spec.ts
@@ -6,7 +6,7 @@
  */
 // import { describe, expect, it, xdescribe, xit } from "../mock_jasmine";
 
-import { ParamCalculability } from "../../src";
+import { ParamCalculability, ParamValueMode } from "../../src";
 import { MacroRugo, MacrorugoParams } from "../../src/macrorugo/macrorugo";
 import { checkResult } from "../test_func";
 
@@ -17,7 +17,7 @@ function macroRugoInstance(): MacroRugo {
             6,      // L
             1,      // B
             0.05,   // If
-            0.5,    // Q
+            9.418,    // Q
             0.6,    // h
             0.01,   // Ks
             0.05,   // C
@@ -28,15 +28,15 @@ function macroRugoInstance(): MacroRugo {
     );
 }
 
-function testMacroRugo(varTest: string) {
+function testMacroRugo(varTest: string, valRef: number) {
     describe("Calc(): ", () => {
-        it("V should be 1", () => {
+        it(`${varTest} should be ${valRef}`, () => {
             const nub = macroRugoInstance();
             nub.prms.Q.v = nub.Calc("Q").vCalc;
-            const res: number = nub.prms[varTest].v;
-            nub.prms[varTest].v = undefined;
-
-            checkResult(nub.Calc(varTest, 0), res);
+            const p = nub.getParameter(varTest);
+            p.v = undefined;
+            p.valueMode = ParamValueMode.CALCUL;
+            checkResult(nub.Calc(varTest, 0.1), valRef);
         });
     });
 }
@@ -48,7 +48,7 @@ describe("Class MacroRugo: ", () => {
 
     for (const prm of nub.prms) {
         if ([ParamCalculability.DICHO, ParamCalculability.EQUATION].includes(prm.calculability)) {
-            testMacroRugo(prm.symbol);
+            testMacroRugo(prm.symbol, prm.v);
         }
     }
 });
diff --git a/spec/test_func.ts b/spec/test_func.ts
index aa4d012028838d680790c2a47e98c47138279e09..742cd8802a24196ca55f238dbc269ee881bb842e 100644
--- a/spec/test_func.ts
+++ b/spec/test_func.ts
@@ -184,7 +184,7 @@ export function compareLog(logTest: cLog, logValid: cLog) {
 }
 
 export function checkResult(val1: Result, val2: number, prec?: number) {
-    expect(val1.ok).toBeTruthy("Result : computation error on Result " + val1.toString());
+    expect(val1.ok).toBeTruthy((!val1.ok) ? "Result: ERROR code=" + MessageCode[val1.code] : "");
     if (val1.ok) {
         /*
          * on demande une précision de vérification inférieure à la précision de calcul
diff --git a/src/macrorugo/macrorugo.ts b/src/macrorugo/macrorugo.ts
index 89571a76f87d4db4b7ff11ddb6f5378763a5304d..a6cf36d89c24de7c8631fe9d4fd52d278b1e8988 100644
--- a/src/macrorugo/macrorugo.ts
+++ b/src/macrorugo/macrorugo.ts
@@ -5,6 +5,12 @@ import { MacrorugoParams } from "./macrorugo_params";
 
 export { MacrorugoParams };
 
+export enum MacroRugoFlowType {
+    EMERGENT,
+    QUASI_EMERGENT,
+    IMMERGE
+}
+
 export class MacroRugo extends Nub {
 
     private static readonly g = 9.81;
@@ -16,6 +22,10 @@ export class MacroRugo extends Nub {
 
     /** Ratio between the lenght (parallel to flow) and the width (perpendicular to flow) of a cell (-) */
     private static readonly fracAyAx = 1;
+
+    /** Limit between emergent and submerged flow */
+    private static readonly limitSubmerg = 1.1;
+
     /** Rugosité de fond (m) */
     private ks: number;
     /** Averaged velocity at the bed (m.s-1) */
@@ -34,17 +44,84 @@ export class MacroRugo extends Nub {
         return this._prms as MacrorugoParams;
     }
 
+    /**
+     * 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 {
+        const r: Result = super.Calc(sVarCalc, rInit, rPrec);
+        // Ajout des résultats complémentaires
+        // Cote de fond aval
+        r.extraResults.ZF2 = this.prms.ZF1.v - this.prms.If.v * this.prms.L.v;
+        // Vitesse débitante
+        r.extraResults.Vdeb = this.V(this.prms.Q) / this.prms.B.v / this.prms.Y.v;
+        // Vitesse maximale
+        r.extraResults.V = r.extraResults.Vdeb * this.calc_fFr(r.extraResults.Vdeb);
+        // Puissance dissipée
+        r.extraResults.P = 1000 * MacroRugo.g * this.V(this.prms.Q) / this.prms.B.v * this.prms.If.v;
+        // Type d'écoulement
+        if (this.prms.Y.v / this.prms.PBH.v < 1) {
+            r.extraResults.FlowType = MacroRugoFlowType.EMERGENT;
+        } else if (this.prms.Y.v / this.prms.PBH.v < 1.1) {
+            r.extraResults.FlowType = MacroRugoFlowType.QUASI_EMERGENT;
+        } else {
+            r.extraResults.FlowType = MacroRugoFlowType.IMMERGE;
+        }
+        // Vitesse et débit du guide technique
+        let cQ: [number, number, number, number];
+        let cV: [number, number, number];
+        if (this.prms.Y.v / this.prms.PBH.v > 1.1) {
+            cQ = [0.955, 2.282, 0.466, -0.23];
+        } else {
+            if (Math.abs(this.prms.Cd0.v - 2) < 0.05) {
+                cQ = [0.648, 1.084, 0.56, -0.456];
+                cV = [3.35, 0.27, 0.53];
+            } else {
+                cQ = [0.815, 1.45, 0.557, -0.456];
+                cV = [4.54, 0.32, 0.56]
+            }
+        }
+        r.extraResults.Q2 = cQ[0] * Math.pow(this.prms.Y.v / this.prms.PBH.v, cQ[1]) *
+            Math.pow(this.prms.If.v, cQ[2]) * Math.pow(this.prms.C.v, cQ[3]) *
+            Math.sqrt(MacroRugo.g * this.prms.PBD.v) * this.prms.PBH.v * this.prms.B.v;
+        if (this.prms.Y.v / this.prms.PBH.v <= 1.1) {
+            r.extraResults.V2 = cV[0] * Math.pow(this.prms.Y.v / this.prms.PBD.v, cV[1]) *
+                Math.pow(this.prms.If.v, cQ[2]) * Math.sqrt(MacroRugo.g * this.prms.PBD.v);
+        }
+        return r;
+    }
+
     public Equation(sVarCalc: string): Result {
-        const Q = uniroot(this.calcQ, this, 0, 1E7);
+        const Q = uniroot(this.calcQ, this, 0, 1E7) * this.prms.B.v;
         return new Result(Q);
     }
 
+    /**
+     * paramétrage de la calculabilité des paramètres
+     */
+    protected setParametersCalculability() {
+        this.prms.ZF1.calculability = ParamCalculability.FREE;
+        this.prms.L.calculability = ParamCalculability.FREE;
+        this.prms.Ks.calculability = ParamCalculability.FREE;
+        this.prms.B.calculability = ParamCalculability.DICHO;
+        this.prms.If.calculability = ParamCalculability.DICHO;
+        this.prms.Q.calculability = ParamCalculability.EQUATION;
+        this.prms.Y.calculability = ParamCalculability.DICHO;
+        this.prms.C.calculability = ParamCalculability.DICHO;
+        this.prms.PBD.calculability = ParamCalculability.DICHO;
+        this.prms.PBH.calculability = ParamCalculability.FREE;
+        this.prms.Cd0.calculability = ParamCalculability.DICHO;
+    }
+
     /**
      * Equation from Cassan, L., Laurens, P., 2016. Design of emergent and submerged rock-ramp fish passes.
      * Knowledge & Management of Aquatic Ecosystems 45.
      * @param sVarCalc Variable à calculer
      */
-    public calcQ(this: MacroRugo, Q: number): number {
+    private calcQ(this: MacroRugo, Q: number): number {
         // Reset cached variables depending on Q (or not...)
         this._cache = {};
         /** Longueur (m) */
@@ -69,13 +146,17 @@ export class MacroRugo extends Nub {
         const g = MacroRugo.g;
         const kappa = 0.41; // von Karman constant
 
+        // u0 = Averaged velocity at the bed (m.s-1)
+        this.u0 = Q / this.prms.L.v / this.prms.Y.v;
+
         /** Calulated average velocity */
         let u: number;
-        if (h / k > 1.1) {
+        if (h / k > MacroRugo.limitSubmerg) {
             // Submerged conditions
 
             /** Velocity at the bed §2.3.2 Cassan et al., 2016 */
-            this.u0 = Math.sqrt(2 * g * S * D * this.R / (Cd0 * C));
+            /** @todo Faut-il un point fixe ici vu que Cd dépend de u0 ?  */
+            this.u0 = Math.sqrt(2 * g * S * D * this.R / (this.calcCd(this.calc_fFr(this.u0)) * C));
             /** turbulent length scale (m) within the blocks layer (alpha_t) */
             const alpha = uniroot(this.calcAlpha_t, this, 0, 100);
             /** averaged velocity at the top of blocks (m.s-1) */
@@ -110,11 +191,8 @@ export class MacroRugo extends Nub {
          } else {
             // Emergent conditions
 
-            // u0 = Averaged velocity at the bed (m.s-1)
-            this.u0 = Q / this.prms.L.v / this.prms.Y.v;
-
             // Resolve equation (4) Cassan et al., 2016
-            u = uniroot(this.calcU0, this, 0, 1E7);
+            u = uniroot(this.resolveU0, this, 0, 1E7);
         }
         return this.u0 - u;
     }
@@ -144,16 +222,16 @@ export class MacroRugo extends Nub {
         if (this._cache.R !== undefined) {
             return this._cache.R;
         }
-        return (1 - this.sigma * this.prms.C.v) * Math.pow(1 - Math.sqrt(this.prms.C.v), 2);
+        return (1 - this.sigma * this.prms.C.v);
     }
 
     /**
      * Bed friction coefficient Equation (3) (Cassan et al., 2016)
      */
-    private get Cf(): number {
+    private calcCf(U0: number): number {
         // Between Eq (8) and (9) (Cassan et al., 2016)
         // tslint:disable-next-line:variable-name
-        const Re = this.u0 * this.prms.Y.v / MacroRugo.nu;
+        const Re = U0 * this.prms.Y.v / MacroRugo.nu;
 
         if (this.prms.Ks.v < 1E-6) {
             return 0.3164 / 4. * Math.pow(Re, -0.25);
@@ -163,23 +241,6 @@ export class MacroRugo extends Nub {
         }
     }
 
-    /**
-     * paramétrage de la calculabilité des paramètres
-     */
-    protected setParametersCalculability() {
-        this.prms.ZF1.calculability = ParamCalculability.FREE;
-        this.prms.L.calculability = ParamCalculability.FREE;
-        this.prms.Ks.calculability = ParamCalculability.FREE;
-        this.prms.B.calculability = ParamCalculability.DICHO;
-        this.prms.If.calculability = ParamCalculability.DICHO;
-        this.prms.Q.calculability = ParamCalculability.EQUATION;
-        this.prms.Y.calculability = ParamCalculability.DICHO;
-        this.prms.C.calculability = ParamCalculability.DICHO;
-        this.prms.PBD.calculability = ParamCalculability.FREE;
-        this.prms.PBH.calculability = ParamCalculability.FREE;
-        this.prms.Cd0.calculability = ParamCalculability.FREE;
-    }
-
     /**
      * Calculation of Cd : drag coefficient of a block under the actual flow conditions
      * @param Cd0
@@ -230,17 +291,17 @@ export class MacroRugo extends Nub {
         return alpha * this.calcUz(alpha) - l0 * this.ustar;
     }
 
-    private calcU0(U01: number) {
+    private resolveU0(U0: number) {
         const g = MacroRugo.g;
 
         const alpha = 1 - (1 * this.prms.C.v);
         // tslint:disable-next-line:variable-name
-        const Cd = this.calcCd(this.calc_fFr(U01));
+        const Cd = this.calcCd(this.calc_fFr(U0));
 
         /** N from Cassan 2016 eq(2) et Cassan 2014 eq(12) */
-        const N = (alpha * this.Cf) / (this.prms.Y.v / this.prms.PBD.v * Cd * this.prms.C.v);
+        const N = (alpha * this.calcCf(U0)) / (this.prms.Y.v / this.prms.PBD.v * Cd * this.prms.C.v);
 
-        return U01 - Math.sqrt(
+        return U0 - Math.sqrt(
             2 * MacroRugo.g * this.prms.If.v * this.prms.PBD.v *
             (1 - this.sigma * this.prms.C.v) / (Cd * this.prms.C.v * (1 + N))
         );
diff --git a/src/nub.ts b/src/nub.ts
index 99e2c66a4b7016ba2870259cca89a9b92d5f34ab..eec9c95409cabc63bffe5a0208b5105261ae7ea0 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -110,8 +110,9 @@ export abstract class Nub extends ComputeNode implements IReferencedNub {
 
                 case ParamValueMode.LINK:
                     const ro = p.referencedObject;
-                    if (ro !== undefined && ro.hasMultipleValues)
+                    if (ro !== undefined && ro.hasMultipleValues) {
                         variatedValues = this.setVariatedValues(p, variatedValues);
+                    }
                     break;
 
                 default:
@@ -161,6 +162,22 @@ export abstract class Nub extends ComputeNode implements IReferencedNub {
         return this._result;
     }
 
+    /**
+     * Renvoie la valeur actuelle d'un paramètre (valeur utilisateur ou résultat)
+     * @param p Paramètre
+     */
+    public V(p: ParamDefinition): number {
+        if (p.valueMode === ParamValueMode.CALCUL) {
+            if (this.result !== undefined) {
+                if (this.result.ok) {
+                    return this.result.vCalc;
+                }
+            }
+            throw new Error(`Attempt to read the result of ${p.symbol} but none found`);
+        }
+        return p.v;
+    }
+
     // interface IReferencedNub
 
     public getReferencedParamValues(desc: string): ParamValues {
@@ -218,7 +235,7 @@ export abstract class Nub extends ComputeNode implements IReferencedNub {
      *                      correspondant à la clé de recherche
      * @returns tableau d'objets de la forme { "name":string, "value":NamedIterableValues, "nub":Nub},
      *   nub=Nub d'origine de la "value"
-     * 
+     *
      *   l'étiquette "name" (cf. INubReference.defineReference) est de la forme <n | ouvrage[n] | N1>[.[N2]]
      *     n : indice de de l'ouvrage dans le cas des ouvrages parallèles
      *     N1 : un nom de paramètre/résultat (dans le cas d'un résultat, il est suivi d'un point)