diff --git a/src/compute-node.ts b/src/compute-node.ts
index 15b0402cd61879f221f3ec4ea036b329e5f2186e..20710d10885f10af36455b5e5bd65a64b3dbb8ef 100644
--- a/src/compute-node.ts
+++ b/src/compute-node.ts
@@ -66,11 +66,6 @@ export abstract class ComputeNode extends JalhydObject implements IDebug {
      */
     protected _resultsFamilies: any;
 
-    /**
-     * { symbol => string } map that defines units for extra results
-     */
-    protected _resultsUnits: any;
-
     private _debug: Debug;
 
     constructor(prms: ParamsEquation, dbg: boolean = false) {
@@ -83,7 +78,6 @@ export abstract class ComputeNode extends JalhydObject implements IDebug {
         this._prms.parent = this;
 
         this.setParametersCalculability();
-        this.setResultsUnits();
         this.exposeResults();
     }
 
@@ -146,12 +140,8 @@ export abstract class ComputeNode extends JalhydObject implements IDebug {
         return this._resultsFamilies;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {};
-    }
-
-    public get resultsUnits() {
-        return this._resultsUnits;
+    public static resultsUnits(): any {
+        return {};
     }
 
     protected abstract setParametersCalculability(): void;
diff --git a/src/devalaison/grille.ts b/src/devalaison/grille.ts
index 1b5ea89734685bdb0e48041f36e8969476e96d4d..adf140b643dc5b117425afac7fbe7b2acf0b6598 100644
--- a/src/devalaison/grille.ts
+++ b/src/devalaison/grille.ts
@@ -21,6 +21,36 @@ export enum GrilleType {
 
 export class Grille extends Nub implements Observer {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        H: "m",
+        HG: "m",
+        S: "m²",
+        SPDG: "m²",
+        VA: "m/s",
+        VAPDG: "m/s",
+        LG: "m",
+        D: "m",
+        DG: "m",
+        SG: "m²",
+        VN: "m/s",
+        DH00: "cm",
+        DH05: "cm",
+        DH10: "cm",
+        DH15: "cm",
+        DH20: "cm",
+        DH25: "cm",
+        DH30: "cm",
+        DH35: "cm",
+        DH40: "cm",
+        DH45: "cm",
+        DH50: "cm",
+        DH55: "cm",
+        DH60: "cm"
+    }
+
     constructor(prms: GrilleParams, dbg: boolean = false) {
         super(prms, dbg);
         this.setCalculatorType(CalculatorType.Grille);
@@ -291,33 +321,8 @@ export class Grille extends Nub implements Observer {
         this.prms.cIncl.calculability = ParamCalculability.FIXED;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            H: "m",
-            HG: "m",
-            S: "m²",
-            SPDG: "m²",
-            VA: "m/s",
-            VAPDG: "m/s",
-            LG: "m",
-            D: "m",
-            DG: "m",
-            SG: "m²",
-            VN: "m/s",
-            DH00: "cm",
-            DH05: "cm",
-            DH10: "cm",
-            DH15: "cm",
-            DH20: "cm",
-            DH25: "cm",
-            DH30: "cm",
-            DH35: "cm",
-            DH40: "cm",
-            DH45: "cm",
-            DH50: "cm",
-            DH55: "cm",
-            DH60: "cm"
-        }
+    public static override resultsUnits() {
+        return Grille._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/devalaison/jet.ts b/src/devalaison/jet.ts
index a46556bdadd2acebc0fc62a2c614a8babe5f7040..63989c173d8b46c3ba1a26edb759843e8e136db2 100644
--- a/src/devalaison/jet.ts
+++ b/src/devalaison/jet.ts
@@ -8,6 +8,18 @@ import { JetParams } from "../internal_modules";
 
 export class Jet extends Nub {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        H: "m",
+        Y: "m",
+        t: "s",
+        Vx: "m/s",
+        Vz: "m/s",
+        Vt: "m/s"
+    };
+
     /** steps for generating the trajectory */
     protected precision = 50;
 
@@ -259,15 +271,8 @@ export class Jet extends Nub {
         this.prms.D.calculability = ParamCalculability.EQUATION;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            H: "m",
-            Y: "m",
-            t: "s",
-            Vx: "m/s",
-            Vz: "m/s",
-            Vt: "m/s"
-        }
+    public static override resultsUnits() {
+        return Jet._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/index.ts b/src/index.ts
index 88adf8802d3021d363fb1bfd8274bba2ac421792..5b315a80c2b33fc880947344d0928c377cc30bbc 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -102,3 +102,4 @@ export * from "./prebarrage/pre_barrage_params";
 export * from "./prebarrage/pb_cloison";
 export * from "./prebarrage/pb_bassin";
 export * from "./prebarrage/pb_bassin_params";
+export * from "./units";
diff --git a/src/macrorugo/concentration_blocs.ts b/src/macrorugo/concentration_blocs.ts
index 36937b11a1218abdca5b2bf88550d41b6a24de7e..3f9f97a73f558172a24f3f88878c1ee797d742a0 100644
--- a/src/macrorugo/concentration_blocs.ts
+++ b/src/macrorugo/concentration_blocs.ts
@@ -8,6 +8,16 @@ import { ConcentrationBlocsParams } from "../internal_modules";
 
 export class ConcentrationBlocs extends Nub {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        ax: "m",
+        R: "m",
+        AXB: "m",
+        AXH: "m"
+    };
+
     constructor(prms: ConcentrationBlocsParams, dbg: boolean = false) {
         super(prms, dbg);
         this.setCalculatorType(CalculatorType.ConcentrationBlocs);
@@ -129,13 +139,8 @@ export class ConcentrationBlocs extends Nub {
         this.prms.D.calculability = ParamCalculability.EQUATION;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            ax: "m",
-            R: "m",
-            AXB: "m",
-            AXH: "m"
-        }
+    public static override resultsUnits() {
+        return ConcentrationBlocs._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/macrorugo/macrorugo.ts b/src/macrorugo/macrorugo.ts
index 2c9c95a2c8443f02f524b00d202a00ebc5c9b416..196fbe4187b60ff8fbc6c7c51e8ba63f7f8ebcf7 100644
--- a/src/macrorugo/macrorugo.ts
+++ b/src/macrorugo/macrorugo.ts
@@ -54,6 +54,18 @@ export class MacroRugo extends FishPass {
     /** true: Cd0 * min(3, fh), false : min(6, Cd0 * fh) */
     private paramCdNewVersion: boolean = true;
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        PV: "W/m³",
+        Vdeb: "m/s",
+        Vmax: "m/s",
+        Vg: "m/s",
+        ZF2: "m",
+        Strickler: "SI"
+    };
+
     constructor(prms: MacrorugoParams, dbg: boolean = false) {
         super(prms, dbg);
         this._cache = {};
@@ -187,15 +199,8 @@ export class MacroRugo extends FishPass {
         this.prms.Cd0.calculability = ParamCalculability.FREE;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            PV: "W/m³",
-            Vdeb: "m/s",
-            Vmax: "m/s",
-            Vg: "m/s",
-            ZF2: "m",
-            Strickler: "SI"
-        }
+    public static override resultsUnits() {
+        return MacroRugo._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/nub.ts b/src/nub.ts
index f3412228a348752517d7f9cc0440dc105dc2ff78..fe913bdaf00358a14d90de0b123639342a4d31ba 100644
--- a/src/nub.ts
+++ b/src/nub.ts
@@ -1681,8 +1681,8 @@ export abstract class Nub extends ComputeNode implements IObservable {
             return p.unit;
         }
         // is it a result ?
-        if (symbol in this.resultsUnits) {
-            return this.resultsUnits[symbol]; // might be undefined
+        if (symbol in Nub.resultsUnits()) {
+            return Nub.resultsUnits()[symbol]; // might be undefined
         }
         // give up
         return undefined;
diff --git a/src/open-channel/regime_uniforme.ts b/src/open-channel/regime_uniforme.ts
index ce690dd3ee2667868c3ee811d2e2728b82ca39f3..3437cb832f4189fa141abbad4cc54d99e3baab46 100644
--- a/src/open-channel/regime_uniforme.ts
+++ b/src/open-channel/regime_uniforme.ts
@@ -10,6 +10,13 @@ import { isGreaterThan } from "../internal_modules";
 
 export class RegimeUniforme extends SectionNub {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        V: "m/s"
+    };
+
     constructor(s: acSection, dbg: boolean = false) {
         super(new SectionParams(), dbg);
         this.setCalculatorType(CalculatorType.RegimeUniforme);
@@ -95,10 +102,8 @@ export class RegimeUniforme extends SectionNub {
         this.section.prms.YB.calculability = ParamCalculability.FREE;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            V: "m/s"
-        }
+    public static override resultsUnits() {
+        return RegimeUniforme._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/pab/cloisons.ts b/src/pab/cloisons.ts
index f2787ab2fa067dc02261f04b3c744676ee993596..f113d453571277d5e6aa5596d37890a56303845b 100644
--- a/src/pab/cloisons.ts
+++ b/src/pab/cloisons.ts
@@ -10,6 +10,15 @@ import { CloisonsParams } from "../internal_modules";
 
 export class Cloisons extends ParallelStructure {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        PV: "W/m³",
+        ZRAM: "m",
+        ZRMB: "m"
+    };
+
     constructor(prms: CloisonsParams, dbg: boolean = false) {
         super(prms, dbg);
         this.setCalculatorType(CalculatorType.Cloisons);
@@ -134,12 +143,8 @@ export class Cloisons extends ParallelStructure {
         this.prms.QA.calculability = ParamCalculability.FREE;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            PV: "W/m³",
-            ZRAM: "m",
-            ZRMB: "m"
-        }
+    public static override resultsUnits() {
+        return Cloisons._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/pab/pab_nombre.ts b/src/pab/pab_nombre.ts
index 1eb540f66a6f01cc97991c7005a4f08777e810a8..4ccf9cdb80fb75f77a92f9ccd88b10be5ffe750b 100644
--- a/src/pab/pab_nombre.ts
+++ b/src/pab/pab_nombre.ts
@@ -7,6 +7,16 @@ import { Result } from "../internal_modules";
 import { PabNombreParams } from "../internal_modules";
 
 export class PabNombre extends Nub {
+
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        DHR: "m",
+        DHB: "m",
+        DHH: "m"
+    }
+
     constructor(prms: PabNombreParams, dbg: boolean = false) {
         super(prms, dbg);
         this.setCalculatorType(CalculatorType.PabNombre);
@@ -101,12 +111,8 @@ export class PabNombre extends Nub {
         this.prms.DH.calculability = ParamCalculability.EQUATION;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            DHR: "m",
-            DHB: "m",
-            DHH: "m"
-        }
+    public static override resultsUnits() {
+        return PabNombre._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/par/par.ts b/src/par/par.ts
index 8793ad2c0071e10bcadc1030c5211b473fddf2bb..509575092e1b23454bc4a88e3547b81d298c203c 100644
--- a/src/par/par.ts
+++ b/src/par/par.ts
@@ -23,6 +23,28 @@ export enum ParType {
 
 export class Par extends FishPass implements Observer {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        h: "m",
+        qStar: "m³/s",
+        V: "m/s",
+        ZD1: "m",
+        ZR1: "m",
+        ZD2: "m",
+        ZR2: "m",
+        ZM: "m",
+        LPI: "m",
+        LPH: "m",
+        B: "m",
+        C: "m",
+        D: "m",
+        H: "m",
+        Hmin: "m",
+        Hmax: "m"
+    };
+
     protected parCalc: ParTypeAbstract;
 
     constructor(prms: ParParams, dbg: boolean = false) {
@@ -212,25 +234,8 @@ export class Par extends FishPass implements Observer {
         this.prms.ha.calculability = ParamCalculability.EQUATION;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            h: "m",
-            qStar: "m³/s",
-            V: "m/s",
-            ZD1: "m",
-            ZR1: "m",
-            ZD2: "m",
-            ZR2: "m",
-            ZM: "m",
-            LPI: "m",
-            LPH: "m",
-            B: "m",
-            C: "m",
-            D: "m",
-            H: "m",
-            Hmin: "m",
-            Hmax: "m"
-        }
+    public static override resultsUnits() {
+        return Par._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/structure/dever.ts b/src/structure/dever.ts
index 3c092857f384868e46dd7d72419654e055ccd76e..f627c9ff78d84067716a6252b2e25b08101cc59a 100644
--- a/src/structure/dever.ts
+++ b/src/structure/dever.ts
@@ -9,6 +9,14 @@ import { loiAdmissiblesDever, LoiDebit } from "../internal_modules";
 
 export class Dever extends ParallelStructure {
 
+    /**
+     * { symbol => string } map that defines units for extra results
+     */
+    private static _resultsUnits = {
+        Ec: "m",
+        V: "m/s"
+    };
+
     private bQcorrected: boolean;
     private bZcorrected: boolean;
 
@@ -121,11 +129,8 @@ export class Dever extends ParallelStructure {
         this.prms.Z2.visible = false;
     }
 
-    protected setResultsUnits() {
-        this._resultsUnits = {
-            Ec: "m",
-            V: "m/s"
-        }
+    public static override resultsUnits() {
+        return Dever._resultsUnits;
     }
 
     protected exposeResults() {
diff --git a/src/units.ts b/src/units.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b1538784ef270bc180e2a2317f893762d01baf65
--- /dev/null
+++ b/src/units.ts
@@ -0,0 +1,33 @@
+import { CalculatorType } from "./compute-node";
+import { Cloisons, ConcentrationBlocs, Dever, Grille, Jet, MacroRugo, PabNombre, Par, RegimeUniforme } from "./index";
+
+/**
+ * correspondance type de calculette - classe de Nub
+ */
+const nubClasses = new Map<CalculatorType, any>([
+    [CalculatorType.Grille, Grille],
+    [CalculatorType.ConcentrationBlocs, ConcentrationBlocs],
+    [CalculatorType.Jet, Jet],
+    [CalculatorType.MacroRugo, MacroRugo],
+    [CalculatorType.RegimeUniforme, RegimeUniforme],
+    [CalculatorType.Cloisons, Cloisons],
+    [CalculatorType.PabNombre, PabNombre],
+    [CalculatorType.Par, Par],
+    [CalculatorType.Dever, Dever]
+]);
+
+/**
+ * détermine l'unité d'un paramètre de résultat
+ * @param nubType Nub contenant le paramètre de résultat
+ * @param symbol symbole du paramètre
+ * @returns unité du paramètre
+ */
+export function getNubResultUnit(nubType: CalculatorType, symbol: string) {
+    const cl = nubClasses.get(nubType);
+    if (cl !== undefined && "resultsUnits" in cl) {
+        const f = cl.resultsUnits;
+        const units = f();
+        return units[symbol];
+    }
+    return {};
+}