diff --git a/spec/axb.ts b/spec/axb.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ef2b82d1b35b20b88200fd5cee7b5ee109e4b257
--- /dev/null
+++ b/spec/axb.ts
@@ -0,0 +1,105 @@
+import { ConduiteDistrib } from "../src/cond_distri";
+import { ConduiteDistribParams } from "../src/cond_distri_params";
+import { checkResult } from "./test_func";
+
+describe("Class ConduiteDistrib: ", () => {
+    // beforeEach(() => {
+    // });
+    // beforeAll(() => {
+    // });
+
+    describe("Calc(): ", () => {
+        it("Q should be 9.393", () => {
+            const prms = new ConduiteDistribParams(undefined, // débit Q
+                1.2, // diamètre D
+                0.6, // perte de charge J
+                100, // Longueur de la conduite Lg
+                1e-6, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+
+            checkResult(nub.Calc("Q", 0), 9.393);
+        });
+    });
+
+    describe("Calc(): ", () => {
+        it("Q should be 152.992", () => {
+            const prms = new ConduiteDistribParams(undefined, // débit Q
+                2, // diamètre D
+                0.7, // perte de charge J
+                10, // Longueur de la conduite Lg
+                1e-6, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+            nub.prms.D.v = 2;
+            nub.prms.J.v = 0.7;
+            nub.prms.Lg.v = 10;
+            nub.prms.Nu.v = 1e-6;
+
+            checkResult(nub.Calc("Q", 0), 152.992);
+        });
+    });
+
+    describe("Calc(): ", () => {
+        it("D should be 2.12847", () => {
+            const prms = new ConduiteDistribParams(3, // débit Q
+                undefined, // diamètre D
+                0.7, // perte de charge J
+                10, // Longueur de la conduite Lg
+                1e-6, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+
+            const r = nub.Calc("D", 0);
+            checkResult(r, 2.12847);
+        });
+    });
+
+    describe("Calc(): ", () => {
+        it("J should be 0.00814", () => {
+            const prms = new ConduiteDistribParams(3, // débit Q
+                1.2, // diamètre D
+                undefined, // perte de charge J
+                10, // Longueur de la conduite Lg
+                1e-6, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+
+            checkResult(nub.Calc("J", 0), 0.00814);
+        });
+    });
+
+    describe("Calc(): ", () => {
+        it("Lg should be 737.021", () => {
+            const prms = new ConduiteDistribParams(3, // débit Q
+                1.2, // diamètre D
+                0.6, // perte de charge J
+                undefined, // Longueur de la conduite Lg
+                1e-6, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+
+            checkResult(nub.Calc("Lg", 0), 737.021);
+        });
+    });
+
+    describe("Calc(): ", () => {
+        it("Nu should be 0.00295", () => {
+            const prms = new ConduiteDistribParams(3, // débit Q
+                1.2, // diamètre D
+                0.6, // perte de charge J
+                100, // Longueur de la conduite Lg
+                undefined, // Viscosité dynamique Nu
+            );
+
+            const nub = new ConduiteDistrib(prms);
+
+            checkResult(nub.Calc("Nu", 0), 0.00295);
+        });
+    });
+});
diff --git a/spec/cond_distri.spec.ts b/spec/cond_distri.spec.ts
index ef2b82d1b35b20b88200fd5cee7b5ee109e4b257..ae619f827680c2f3fdca5f9c38f0bfdde434ddeb 100644
--- a/spec/cond_distri.spec.ts
+++ b/spec/cond_distri.spec.ts
@@ -1,105 +1,53 @@
-import { ConduiteDistrib } from "../src/cond_distri";
-import { ConduiteDistribParams } from "../src/cond_distri_params";
-import { checkResult } from "./test_func";
+import { YAXB } from "../src/axb";
+import { YAXBParams } from "../src/axb_params";
+import { MessageCode } from "../src/index";
 
-describe("Class ConduiteDistrib: ", () => {
-    // beforeEach(() => {
-    // });
-    // beforeAll(() => {
-    // });
+describe("Class YAXB: ", () => {
 
-    describe("Calc(): ", () => {
-        it("Q should be 9.393", () => {
-            const prms = new ConduiteDistribParams(undefined, // débit Q
-                1.2, // diamètre D
-                0.6, // perte de charge J
-                100, // Longueur de la conduite Lg
-                1e-6, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-
-            checkResult(nub.Calc("Q", 0), 9.393);
-        });
+    it("Y should be 10", () => {
+        const nub = new YAXB(new YAXBParams(666, 2, 3, 4));
+        nub.calculatedParam = nub.prms.Y;
+        nub.CalcSerie();
+        expect(nub.result.vCalc).toBe(10);
     });
 
-    describe("Calc(): ", () => {
-        it("Q should be 152.992", () => {
-            const prms = new ConduiteDistribParams(undefined, // débit Q
-                2, // diamètre D
-                0.7, // perte de charge J
-                10, // Longueur de la conduite Lg
-                1e-6, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-            nub.prms.D.v = 2;
-            nub.prms.J.v = 0.7;
-            nub.prms.Lg.v = 10;
-            nub.prms.Nu.v = 1e-6;
-
-            checkResult(nub.Calc("Q", 0), 152.992);
-        });
+    it("A should be 2", () => {
+        const nub = new YAXB(new YAXBParams(10, 666, 3, 4));
+        nub.calculatedParam = nub.prms.A;
+        nub.CalcSerie();
+        expect(nub.result.vCalc).toBe(2);
     });
 
-    describe("Calc(): ", () => {
-        it("D should be 2.12847", () => {
-            const prms = new ConduiteDistribParams(3, // débit Q
-                undefined, // diamètre D
-                0.7, // perte de charge J
-                10, // Longueur de la conduite Lg
-                1e-6, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-
-            const r = nub.Calc("D", 0);
-            checkResult(r, 2.12847);
-        });
+    it("X should be 3", () => {
+        const nub = new YAXB(new YAXBParams(10, 2, 666, 4));
+        nub.calculatedParam = nub.prms.X;
+        nub.CalcSerie();
+        expect(nub.result.vCalc).toBe(3);
     });
 
-    describe("Calc(): ", () => {
-        it("J should be 0.00814", () => {
-            const prms = new ConduiteDistribParams(3, // débit Q
-                1.2, // diamètre D
-                undefined, // perte de charge J
-                10, // Longueur de la conduite Lg
-                1e-6, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-
-            checkResult(nub.Calc("J", 0), 0.00814);
-        });
+    it("B should be 4", () => {
+        const nub = new YAXB(new YAXBParams(10, 2, 3, 666));
+        nub.calculatedParam = nub.prms.B;
+        nub.CalcSerie();
+        expect(nub.result.vCalc).toBe(4);
     });
 
-    describe("Calc(): ", () => {
-        it("Lg should be 737.021", () => {
-            const prms = new ConduiteDistribParams(3, // débit Q
-                1.2, // diamètre D
-                0.6, // perte de charge J
-                undefined, // Longueur de la conduite Lg
-                1e-6, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-
-            checkResult(nub.Calc("Lg", 0), 737.021);
-        });
+    it("calc A with X = 0 should trigger error", () => {
+        const nub = new YAXB(new YAXBParams(10, 666, 0, 4));
+        nub.calculatedParam = nub.prms.A;
+        nub.CalcSerie();
+        expect(nub.result.ok).toBe(false);
+        expect(nub.result.resultElement.log.messages.length).toBe(1);
+        expect(nub.result.resultElement.log.messages[0].code).toBe(MessageCode.ERROR_DIVISION_BY_ZERO);
     });
 
-    describe("Calc(): ", () => {
-        it("Nu should be 0.00295", () => {
-            const prms = new ConduiteDistribParams(3, // débit Q
-                1.2, // diamètre D
-                0.6, // perte de charge J
-                100, // Longueur de la conduite Lg
-                undefined, // Viscosité dynamique Nu
-            );
-
-            const nub = new ConduiteDistrib(prms);
-
-            checkResult(nub.Calc("Nu", 0), 0.00295);
-        });
+    it("calc X with A = 0 should trigger error", () => {
+        const nub = new YAXB(new YAXBParams(10, 0, 666, 4));
+        nub.calculatedParam = nub.prms.X;
+        nub.CalcSerie();
+        expect(nub.result.ok).toBe(false);
+        expect(nub.result.resultElement.log.messages.length).toBe(1);
+        expect(nub.result.resultElement.log.messages[0].code).toBe(MessageCode.ERROR_DIVISION_BY_ZERO);
     });
+
 });
diff --git a/src/axb.ts b/src/axb.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99dc614015e8fe905a08d8b6e07e62a4d1cb98dd
--- /dev/null
+++ b/src/axb.ts
@@ -0,0 +1,70 @@
+import { YAXBParams } from "./axb_params";
+import { CalculatorType } from "./compute-node";
+import { Nub } from "./nub";
+import { ParamCalculability } from "./param/param-definition";
+import { Message, MessageCode } from "./util/message";
+import { Result } from "./util/result";
+
+/**
+ * Y = A.X + B
+ */
+export class YAXB extends Nub {
+
+    constructor(prms: YAXBParams, dbg: boolean = false) {
+        super(prms, dbg);
+        this._calcType = CalculatorType.YAXB;
+        this._defaultCalculatedParam = prms.Y;
+        this.resetDefaultCalculatedParam();
+    }
+
+    /** paramètres castés au bon type */
+    get prms(): YAXBParams {
+        return this._prms as YAXBParams;
+    }
+
+    public Equation(sVarCalc: string): Result {
+        let v: number;
+
+        switch (sVarCalc) {
+            case "Y":
+                v = this.prms.A.v * this.prms.X.v + this.prms.B.v;
+                break;
+
+            case "A":
+                if (this.prms.X.v === 0) {
+                    const m = new Message(MessageCode.ERROR_DIVISION_BY_ZERO);
+                    m.extraVar.symbol = "X";
+                    return new Result(m);
+                }
+                v = (this.prms.Y.v - this.prms.B.v) / this.prms.X.v;
+                break;
+
+            case "X":
+                if (this.prms.A.v === 0) {
+                    const m = new Message(MessageCode.ERROR_DIVISION_BY_ZERO);
+                    m.extraVar.symbol = "A";
+                    return new Result(m);
+                }
+                v = (this.prms.Y.v - this.prms.B.v) / this.prms.A.v;
+                break;
+
+            case "B":
+                v = this.prms.Y.v - (this.prms.A.v * this.prms.X.v);
+                break;
+
+            default:
+                throw new Error("AXB.Equation() : invalid variable name " + sVarCalc);
+        }
+
+        return new Result(v, this);
+    }
+
+    /** paramétrage de la calculabilité des paramètres */
+    protected setParametersCalculability() {
+        this.prms.Y.calculability = ParamCalculability.EQUATION;
+        this.prms.A.calculability = ParamCalculability.EQUATION;
+        this.prms.X.calculability = ParamCalculability.EQUATION;
+        this.prms.B.calculability = ParamCalculability.EQUATION;
+    }
+
+}
diff --git a/src/axb_params.ts b/src/axb_params.ts
new file mode 100644
index 0000000000000000000000000000000000000000..847a09750e911f0023049cc2d73a06c524028c6a
--- /dev/null
+++ b/src/axb_params.ts
@@ -0,0 +1,50 @@
+import { ParamDefinition, ParamFamily } from "./param/param-definition";
+import { ParamDomainValue } from "./param/param-domain";
+import { ParamsEquation } from "./param/params-equation";
+
+/**
+ * Y = A.X + B
+ */
+export class YAXBParams extends ParamsEquation {
+
+    /** Y */
+    private _Y: ParamDefinition;
+
+    /** A */
+    private _A: ParamDefinition;
+
+    /** X */
+    private _X: ParamDefinition;
+
+    /** B */
+    private _B: ParamDefinition;
+
+    constructor(rY: number, rA: number, rX: number, rB: number) {
+        super();
+        this._Y = new ParamDefinition(this, "Y", ParamDomainValue.ANY, undefined, rY, ParamFamily.ANY);
+        this._A = new ParamDefinition(this, "A", ParamDomainValue.ANY, undefined, rA, ParamFamily.ANY);
+        this._X = new ParamDefinition(this, "X", ParamDomainValue.ANY, undefined, rX, ParamFamily.ANY);
+        this._B = new ParamDefinition(this, "B", ParamDomainValue.ANY, undefined, rB, ParamFamily.ANY);
+
+        this.addParamDefinition(this._Y);
+        this.addParamDefinition(this._A);
+        this.addParamDefinition(this._X);
+        this.addParamDefinition(this._B);
+    }
+
+    get Y() {
+        return this._Y;
+    }
+
+    get A() {
+        return this._A;
+    }
+
+    get X() {
+        return this._X;
+    }
+
+    get B() {
+        return this._B;
+    }
+}
diff --git a/src/compute-node.ts b/src/compute-node.ts
index 7797777279e9dd77f7ca2b27c8af3085fa79a1b4..2e40d3e86d24f04f6307a35586f1493842d154a9 100644
--- a/src/compute-node.ts
+++ b/src/compute-node.ts
@@ -30,7 +30,8 @@ export enum CalculatorType {
     Grille,             // Pertes de charge grille de prise d'eau
     Pente,
     Bief,
-    Solveur             // Nub qui résout des chaînes de Nubs par dichotomie
+    Solveur,            // Nub qui résout des chaînes de Nubs par dichotomie
+    YAXB                 // Y = A.X + B
 }
 
 /**
diff --git a/src/param/param-definition.ts b/src/param/param-definition.ts
index 2c6c7adcf49c8e67c1862ad726f51cf9190cd339..58faea27882e6405ff1778eeca41819de65b0de5 100644
--- a/src/param/param-definition.ts
+++ b/src/param/param-definition.ts
@@ -30,6 +30,7 @@ export enum ParamCalculability {
  * Parameter family: defines linkability with other parameters/results
  */
 export enum ParamFamily {
+    ANY, // peut être lié à n'importe quel paramètre
     LENGTHS, // longueur
     WIDTHS, // largeur
     SLOPES, // pente
diff --git a/src/session.ts b/src/session.ts
index 2f2d5d810ce0c63ed6c2b25357656cf51b9fcdee..f4f087d86c94a398fc9ad7c5acce6e4e880f0f6c 100644
--- a/src/session.ts
+++ b/src/session.ts
@@ -8,6 +8,8 @@ import { Props } from "./props";
 import { config } from "./config";
 
 // Calculettes
+import { YAXB } from "./axb";
+import { YAXBParams } from "./axb_params";
 import { ConduiteDistrib } from "./cond_distri";
 import { LechaptCalmon } from "./lechaptcalmon";
 import { MacroRugo } from "./macrorugo/macrorugo";
@@ -20,6 +22,8 @@ import { PabPuissance } from "./pab/pab_puissance";
 import { RegimeUniforme } from "./regime_uniforme";
 import { CourbeRemous } from "./remous/remous";
 import { SectionParametree } from "./section/section_parametree";
+import { Solveur } from "./solveur/solveur";
+import { SolveurParams } from "./solveur/solveur_params";
 
 // Classes relatives aux sections
 import { BiefParams, BiefRegime } from "./remous/bief_params";
@@ -66,8 +70,6 @@ import { JetParams } from "./devalaison/jet_params";
 import { Pente } from "./pente";
 import { PenteParams } from "./pente_params";
 import { Bief } from "./remous/bief";
-import { Solveur } from "./solveur/solveur";
-import { SolveurParams } from "./solveur/solveur_params";
 
 export class Session {
 
@@ -584,6 +586,18 @@ export class Session {
                 );
                 break;
 
+            case CalculatorType.YAXB:
+                nub = new YAXB(
+                    new YAXBParams(
+                        10,     // Y
+                        2,      // A
+                        3,      // X
+                        4       // B
+                    ),
+                    dbg
+                );
+                break;
+
             default:
                 throw new Error(
                     `Session.createNub() : type de module '${CalculatorType[calcType]}' non pris en charge`
diff --git a/src/util/message.ts b/src/util/message.ts
index ae2dc255ce49dd992af035af593a188c90099cc9..c8e36bab25b5ab6f4859e7b95b100fb3ced58d6a 100644
--- a/src/util/message.ts
+++ b/src/util/message.ts
@@ -52,6 +52,11 @@ export enum MessageCode {
      */
     ERROR_DICHO_FUNCTION_VARIATION,
 
+    /**
+     * impossible de résoudre l'équation en raison d'une division par zéro
+     */
+    ERROR_DIVISION_BY_ZERO,
+
     /**
      * la cote amont Z1 est plus basse que la cote aval Z2
      */