diff --git a/spec/devalaison/jet.spec.ts b/spec/devalaison/jet.spec.ts
index 383f06fa77b9ebdf8ea41aa11affe06cbaad77de..e82443f6c04220165770006d7eac6b2c6c2015fb 100644
--- a/spec/devalaison/jet.spec.ts
+++ b/spec/devalaison/jet.spec.ts
@@ -1,9 +1,10 @@
 import { Jet } from "../../src/devalaison/jet";
 import { JetParams } from "../../src/devalaison/jet_params";
+import { MessageCode, ParamCalculability } from "../../src/index";
 
 function newJet(): Jet {
     return new Jet(
-        new JetParams(5, 0.3, 72.48, 19.0788),
+        new JetParams(5, 0.3, 77.48, 5, 3.42, 19.0788),
         false
     );
 }
@@ -15,16 +16,18 @@ describe("Class Jet − ", () => {
         jet = newJet();
     });
     for (const p of jet.parameterIterator) {
-        it(`Calc(${p.symbol}) should return ${p.currentValue}`, () => {
-            jet.calculatedParam = jet.getParameter(p.symbol);
-            const ref: number = p.currentValue;
-            jet.calculatedParam.singleValue = jet.calculatedParam.singleValue / 2;
-            expect(jet.CalcSerie().vCalc).toBeCloseTo(ref, 3);
-            expect(jet.result.values.t).toBeCloseTo(4, 3);
-            expect(jet.result.values.Vx).toBeCloseTo(4.7697, 3);
-            expect(jet.result.values.Vz).toBeCloseTo(-37.74, 3);
-            expect(jet.result.values.Vt).toBeCloseTo(38.0402, 3);
-        });
+        if ([ ParamCalculability.EQUATION, ParamCalculability.DICHO ].includes(p.calculability)) {
+            it(`Calc(${p.symbol}) should return ${p.currentValue}`, () => {
+                jet.calculatedParam = jet.getParameter(p.symbol);
+                const ref: number = p.currentValue;
+                jet.calculatedParam.singleValue = jet.calculatedParam.singleValue / 2;
+                expect(jet.CalcSerie().vCalc).toBeCloseTo(ref, 3);
+                expect(jet.result.values.t).toBeCloseTo(4, 3);
+                expect(jet.result.values.Vx).toBeCloseTo(4.770, 3);
+                expect(jet.result.values.Vz).toBeCloseTo(-37.74, 3);
+                expect(jet.result.values.Vt).toBeCloseTo(38.04, 3);
+            });
+        }
     }
 
     describe("initial slope − ", () => {
@@ -43,4 +46,93 @@ describe("Class Jet − ", () => {
         });
     });
 
+    describe("trajectory − ", () => {
+        it("changing jet start elevation should change Y of the first point", () => {
+            jet.calculatedParam = jet.prms.D;
+            // ZJ = 30
+            jet.prms.ZJ.singleValue = 30;
+            jet.CalcSerie();
+            const traj30 = jet.generateTrajectories()[0];
+            // ZJ = 25
+            jet.prms.ZJ.singleValue = 25;
+            jet.CalcSerie();
+            const traj25 = jet.generateTrajectories()[0];
+            // check
+            expect(traj30[0][1]).toBe(30);
+            expect(traj25[0][1]).toBe(25);
+        });
+    });
+
+    describe("errors and warnings − ", () => {
+        it("water underground (fixed), there should be a warning", () => {
+            jet.prms.ZJ.singleValue = 30;
+            jet.prms.ZW.singleValue = 28.2;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.calculatedParam = jet.prms.D;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(1);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND);
+        });
+        it("water underground (calculated), there should be a warning", () => {
+            jet.prms.ZJ.singleValue = 30;
+            jet.prms.D.singleValue = 3.709;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.calculatedParam = jet.prms.ZW;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(1);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND);
+        });
+        it("jet underground (fixed), there should be two warnings", () => {
+            jet.prms.ZJ.singleValue = 28;
+            jet.prms.ZW.singleValue = 27;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.calculatedParam = jet.prms.D;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(2);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND);
+            expect(res.log.messages[1].code).toBe(MessageCode.WARNING_JET_START_ELEVATION_UNDERGROUND);
+        });
+        it("jet underground (calculated), there should be two warnings", () => {
+            jet.prms.D.singleValue = 3.003;
+            jet.prms.ZW.singleValue = 27;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.calculatedParam = jet.prms.ZJ;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(2);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND);
+            expect(res.log.messages[1].code).toBe(MessageCode.WARNING_JET_START_ELEVATION_UNDERGROUND);
+        });
+        it("jet submerged (fixed) with solution, there should be a warning", () => {
+            jet.prms.ZJ.singleValue = 29.1;
+            jet.prms.ZW.singleValue = 29.2;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.prms.S.singleValue = 0.9;
+            jet.calculatedParam = jet.prms.D;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(1);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_START_SUBMERGED);
+        });
+        it("jet submerged (calculated) with solution, there should be a warning", () => {
+            jet.prms.D.singleValue = 0.950;
+            jet.prms.ZW.singleValue = 29.2;
+            jet.prms.ZF.singleValue = 24.5;
+            jet.prms.S.singleValue = 0.9;
+            jet.calculatedParam = jet.prms.ZJ;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(1);
+            expect(res.log.messages[0].code).toBe(MessageCode.WARNING_JET_START_SUBMERGED);
+        });
+        it("jet submerged without solution, there should be an error and a warning", () => {
+            jet.prms.ZJ.singleValue = 29.1;
+            jet.prms.ZW.singleValue = 29.2;
+            jet.prms.ZF.singleValue = 28.5;
+            jet.prms.S.singleValue = 0;
+            jet.calculatedParam = jet.prms.D;
+            const res = jet.CalcSerie();
+            expect(res.log.messages.length).toBe(2);
+            expect(res.log.messages[0].code).toBe(MessageCode.ERROR_JET_SUBMERGED_NO_SOLUTION);
+            expect(res.log.messages[1].code).toBe(MessageCode.WARNING_JET_START_SUBMERGED);
+        });
+    });
+
 });
diff --git a/src/devalaison/jet.ts b/src/devalaison/jet.ts
index 5b143409cb0332f2f2657e7966a7f2e746199b49..b60e484ae890aeb1ea50f8720e2d985903ce986b 100644
--- a/src/devalaison/jet.ts
+++ b/src/devalaison/jet.ts
@@ -1,7 +1,8 @@
 import { CalculatorType } from "../compute-node";
 import { Nub } from "../nub";
-import { ParamCalculability } from "../param/param-definition";
+import { ParamCalculability, ParamFamily } from "../param/param-definition";
 import { ParamValueMode } from "../param/param-value-mode";
+import { Message, MessageCode } from "../util/message";
 import { Result } from "../util/result";
 import { JetParams } from "./jet_params";
 
@@ -24,38 +25,84 @@ export class Jet extends Nub {
 
     public Calc(sVarCalc: string, rInit?: number): Result {
         this.currentResult = super.Calc(sVarCalc, rInit);
+        // H: chute
+        this.result.resultElement.values.H = this.prms.ZJ.v - this.prms.ZW.v;
+        // Y: profondeur
+        this.result.resultElement.values.Y = this.prms.ZW.v - this.prms.ZF.v;
+        // YH: rapport profondeur/chute
+        this.result.resultElement.values.YH = this.result.resultElement.values.Y / this.result.resultElement.values.H;
+        // t: temps de vol
         this.result.resultElement.values.t = this.prms.D.V / Math.cos(this.alpha) / this.prms.V0.V;
+        // Vx: vitesse horizontale à l'impact
         this.result.resultElement.values.Vx = this.prms.V0.V * Math.cos(this.alpha);
+        // Vz: vitesse verticale à l'impact
         this.result.resultElement.values.Vz =
             this.prms.V0.V * Math.sin(this.alpha) - this.result.resultElement.values.t * 9.81;
+        // Vt: vitesse à l'impact
         this.result.resultElement.values.Vt = Math.sqrt(
             Math.pow(this.result.resultElement.values.Vx, 2)
             + Math.pow(this.result.resultElement.values.Vz, 2)
         );
+
+        let ZF = this.prms.ZF.v;
+        let ZW = this.prms.ZW.v;
+        let ZJ = this.prms.ZJ.v;
+        if (this.calculatedParam === this.prms.ZF) {
+            ZF = this.result.resultElement.vCalc;
+        }
+        if (this.calculatedParam === this.prms.ZW) {
+            ZW = this.result.resultElement.vCalc;
+        }
+        if (this.calculatedParam === this.prms.ZJ) {
+            ZJ = this.result.resultElement.vCalc;
+        }
+        // y a-t-il de l'eau au dessus du sol ?
+        if (ZF > ZW) {
+            this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_WATER_ELEVATION_UNDERGROUND));
+        }
+        // le jet est-il bien au dessus du sol ?
+        if (ZF > ZJ) {
+            this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_START_ELEVATION_UNDERGROUND));
+        }
+        // le jet est-il bien émergé ?
+        if (ZW > ZJ) {
+            this.result.resultElement.log.add(new Message(MessageCode.WARNING_JET_START_SUBMERGED));
+        }
+
         return this.result;
     }
 
     public Equation(sVarCalc: string): Result {
         const g: number = 9.81;
-        let alpha: number;
-        if (sVarCalc !== "S") {
-            // Positive slope for negative angle
-            alpha = this.alpha;
-        }
         let v: number;
+        let h: number;
         switch (sVarCalc) {
-            case ("H"):
-                v = 0.5 * g * Math.pow(this.prms.D.v, 2) / (Math.pow(Math.cos(alpha), 2) * Math.pow(this.prms.V0.v, 2))
-                    - Math.tan(alpha) * this.prms.D.v;
+            case ("ZJ"):
+                h = this.CalcH();
+                v = h + this.prms.ZW.v;
+                break;
+
+            case ("ZW"):
+                h = this.CalcH();
+                v = this.prms.ZJ.v - h;
                 break;
+
             case ("D"):
-                v = this.prms.V0.v / g * Math.cos(alpha)
+                h = (this.prms.ZJ.v - this.prms.ZW.v);
+                const sqrtArg = Math.pow(this.prms.V0.v * Math.sin(this.alpha), 2) + 2 * g * h;
+                if (sqrtArg < 0) {
+                    return new Result(new Message(MessageCode.ERROR_JET_SUBMERGED_NO_SOLUTION));
+                }
+                v = this.prms.V0.v / g * Math.cos(this.alpha)
                     * (
-                        this.prms.V0.v * Math.sin(alpha)
-                        + Math.sqrt(Math.pow(this.prms.V0.v * Math.sin(alpha), 2) + 2 * g * this.prms.H.v)
+                        this.prms.V0.v * Math.sin(this.alpha)
+                        + Math.sqrt(sqrtArg)
                     );
                 break;
 
+            default:
+                throw new Error("Jet.Equation() : invalid variable name " + sVarCalc);
+
         }
         return new Result(v);
     }
@@ -71,12 +118,12 @@ export class Jet extends Nub {
      * for each abscissa (x) between 0 and the impact abscissa (D).
      * A coordinate pair is a list of 2 numbers [ x, y ].
      * If no parameter is varying, result will contain only 1 element.
-     * Trajectory calculation uses a copy of the current Nub to calculate H from D.
+     * Trajectory calculation uses a copy of the current Nub to calculate ZW from D.
      */
     public generateTrajectories(): number[][][] {
         const trajectories: number[][][] = [];
 
-        // clone Nub so that H calculation will not impact current state
+        // clone Nub so that ZW calculation will not impact current state
         const nub = this.clone();
 
         // is anything varying ?
@@ -90,8 +137,8 @@ export class Jet extends Nub {
             nub.prms.D.valueMode = ParamValueMode.SINGLE;
             // H will be calculated
 
-            // 1. find all extended values lists; ignore H (will be calculated) and D (will be reaffected)
-            for (const symbol of [ "S", "V0" ]) {
+            // 1. find all extended values lists; ignore ZW (will be calculated) and D (will be reaffected)
+            for (const symbol of [ "S", "V0", "ZJ" ]) {
                 const p = this.getParameter(symbol);
                 valuesLists[symbol] = [];
                 if (this.calculatedParam.symbol === symbol) { // calculated
@@ -115,9 +162,9 @@ export class Jet extends Nub {
             for (let i = 0; i < length; i++) {
                 // exclude iteration if calculation has failed
                 if (this.result.resultElements[i].ok) {
-                    // set clone params values; ignore H (will be calculated)
+                    // set clone params values; ignore ZW (will be calculated)
                     // and D (will be reaffected by getDAbscissae)
-                    for (const symbol of [ "S", "V0" ]) {
+                    for (const symbol of [ "S", "V0", "ZJ" ]) {
                         const val = valuesLists[symbol][i];
                         nub.getParameter(symbol).v = val;
                     }
@@ -130,7 +177,7 @@ export class Jet extends Nub {
             }
 
         } else { // nothing is varying
-            for (const symbol of [ "S", "V0" ]) {
+            for (const symbol of [ "S", "V0", "ZJ" ]) {
                 // init .v of clone
                 nub.getParameter(symbol).v = nub.getParameter(symbol).singleValue;
             }
@@ -140,6 +187,17 @@ export class Jet extends Nub {
         return trajectories;
     }
 
+    protected CalcH(): number {
+        const g: number = 9.81;
+        return (
+            0.5 * g * Math.pow(this.prms.D.v, 2)
+            / (Math.pow(Math.cos(this.alpha), 2) * Math.pow(this.prms.V0.v, 2)
+        ) - Math.tan(this.alpha) * this.prms.D.v);
+    }
+
+    /**
+     * Build a trajectory data series for a calculation iteration
+     */
     protected buildSeriesForIteration(nub: Jet, i: number): number[][] {
         const traj: number[][] = [];
         const xs = this.getDAbscissae(i);
@@ -147,8 +205,8 @@ export class Jet extends Nub {
             // compute H for D = x
             nub.prms.D.v = x;
             // console.log("__computing H for x =", x, nub.prms.D.v);
-            const h = nub.Calc("H");
-            traj.push([ x, - h.vCalc ]);
+            const h = nub.Calc("ZW");
+            traj.push([ x, h.vCalc ]);
         }
         return traj;
     }
@@ -192,10 +250,19 @@ export class Jet extends Nub {
     protected setParametersCalculability() {
         this.prms.V0.calculability = ParamCalculability.DICHO;
         this.prms.S.calculability = ParamCalculability.DICHO;
-        this.prms.H.calculability = ParamCalculability.EQUATION;
+        this.prms.ZJ.calculability = ParamCalculability.EQUATION;
+        this.prms.ZW.calculability = ParamCalculability.EQUATION;
+        this.prms.ZF.calculability = ParamCalculability.FIXED;
         this.prms.D.calculability = ParamCalculability.EQUATION;
     }
 
+    protected setResultsFamilies() {
+        this._resultsFamilies = {
+            H: ParamFamily.TOTALFALLS,
+            Y: ParamFamily.HEIGHTS
+        };
+    }
+
     private get alpha(): number {
         return Math.asin(this.prms.S.v);
     }
diff --git a/src/devalaison/jet_params.ts b/src/devalaison/jet_params.ts
index 1c928be13b1f1bef4571085c511b31410f756614..f151d3a7f3403b59a4577a64916c6fab782b49b4 100644
--- a/src/devalaison/jet_params.ts
+++ b/src/devalaison/jet_params.ts
@@ -3,8 +3,15 @@ import { ParamDomain, ParamDomainValue } from "../param/param-domain";
 import { ParamsEquation } from "../param/params-equation";
 
 export class JetParams extends ParamsEquation {
-    /** Fall (m) */
-    private _H: ParamDefinition;
+
+    /** Jet start elevation (m) */
+    private _ZJ: ParamDefinition;
+
+    /** Water elevation (m) */
+    private _ZW: ParamDefinition;
+
+    /** Bottom elevation (m) */
+    private _ZF: ParamDefinition;
 
     /** Initial speed */
     private _V0: ParamDefinition;
@@ -15,7 +22,7 @@ export class JetParams extends ParamsEquation {
     /** Impact distance */
     private _D: ParamDefinition;
 
-    constructor(V0: number, S: number, H: number, D: number) {
+    constructor(V0: number, S: number, ZJ: number, ZW: number, ZF: number, D: number) {
         super();
         this._V0 = new ParamDefinition(this, "V0", ParamDomainValue.POS, "m", V0, ParamFamily.SPEEDS);
         this.addParamDefinition(this._V0);
@@ -25,8 +32,12 @@ export class JetParams extends ParamsEquation {
             "m/m", S, ParamFamily.SLOPES
         );
         this.addParamDefinition(this._S);
-        this._H = new ParamDefinition(this, "H", ParamDomainValue.POS_NULL, "m", H, ParamFamily.TOTALFALLS);
-        this.addParamDefinition(this._H);
+        this._ZJ = new ParamDefinition(this, "ZJ", ParamDomainValue.ANY, "m", ZJ, ParamFamily.ELEVATIONS);
+        this.addParamDefinition(this._ZJ);
+        this._ZW = new ParamDefinition(this, "ZW", ParamDomainValue.ANY, "m", ZW, ParamFamily.ELEVATIONS);
+        this.addParamDefinition(this._ZW);
+        this._ZF = new ParamDefinition(this, "ZF", ParamDomainValue.ANY, "m", ZF, ParamFamily.ELEVATIONS);
+        this.addParamDefinition(this._ZF);
         this._D = new ParamDefinition(this, "D", ParamDomainValue.POS_NULL, "m", D, ParamFamily.LENGTHS);
         this.addParamDefinition(this._D);
     }
@@ -39,8 +50,16 @@ export class JetParams extends ParamsEquation {
         return this._S;
     }
 
-    public get H(): ParamDefinition {
-        return this._H;
+    public get ZJ(): ParamDefinition {
+        return this._ZJ;
+    }
+
+    public get ZW(): ParamDefinition {
+        return this._ZW;
+    }
+
+    public get ZF(): ParamDefinition {
+        return this._ZF;
     }
 
     public get D(): ParamDefinition {
diff --git a/src/session.ts b/src/session.ts
index 4afbbcc33cdc23719fe6578432503caf7562e741..0a6909708954f94aa3fc3100d5e66dff5010ca19 100644
--- a/src/session.ts
+++ b/src/session.ts
@@ -540,7 +540,9 @@ export class Session {
                     new JetParams(
                         5,      // V0
                         0.03,   // S
-                        2,      // H
+                        30,     // ZJ
+                        29.2,   // ZW
+                        28.5,   // ZF
                         3       // D
                     )
                 );
diff --git a/src/util/message.ts b/src/util/message.ts
index 6d2f206eb5df32637a9a74d9727911c66f0dc7f2..15319ad0c79ef5107c52c4ce5c9dcb4db4f4cc53 100644
--- a/src/util/message.ts
+++ b/src/util/message.ts
@@ -70,6 +70,9 @@ export enum MessageCode {
      */
     ERROR_IN_CALC_CHAIN,
 
+    /** Jet submergé, pente trop faible: pas de solution pour calculer l'abscisse de l'impact */
+    ERROR_JET_SUBMERGED_NO_SOLUTION,
+
     /**
      * Something failed in certain steps (but not all), when calculating upstream Nubs with varying parameter
      */
@@ -343,6 +346,15 @@ export enum MessageCode {
      */
     WARNING_GRILLE_VN_GREATER_THAN_05,
 
+    /** La cote de départ du jet est plus basse que la code de l'eau */
+    WARNING_JET_START_SUBMERGED,
+
+    /** La cote de départ du jet est plus basse que la code de fond */
+    WARNING_JET_START_ELEVATION_UNDERGROUND,
+
+    /** La cote de l'eau est plus basse ou égale à la cote de fond */
+    WARNING_JET_WATER_ELEVATION_UNDERGROUND,
+
     /** section : le tirant d'eau dépasse la hauteur de berge */
     WARNING_SECTION_OVERFLOW,