diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 8509d10d659747afc9c1163d6986006598ee6060..15ede0e0912e30acb3ce2d1644734dd059cb6b76 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -100,6 +100,7 @@ import { DialogEditPabComponent } from "./components/dialog-edit-pab/dialog-edit
 import { DialogEditParamComputedComponent } from "./components/dialog-edit-param-computed/dialog-edit-param-computed.component";
 import { DialogEditParamValuesComponent } from "./components/dialog-edit-param-values/dialog-edit-param-values.component";
 import { DialogGeneratePABComponent } from "./components/dialog-generate-pab/dialog-generate-pab.component";
+import { DialogGeneratePARSimulationComponent } from "./components/dialog-generate-par-simulation/dialog-generate-par-simulation.component";
 import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component";
 import { DialogLogEntriesDetailsComponent } from "./components/dialog-log-entries-details/dialog-log-entries-details.component";
 import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component";
@@ -189,6 +190,7 @@ const appRoutes: Routes = [
     DialogEditParamComputedComponent,
     DialogEditParamValuesComponent,
     DialogGeneratePABComponent,
+    DialogGeneratePARSimulationComponent,
     DialogLoadSessionComponent,
     DialogLogEntriesDetailsComponent,
     DialogSaveSessionComponent,
@@ -240,6 +242,7 @@ const appRoutes: Routes = [
     DialogEditParamComputedComponent,
     DialogEditParamValuesComponent,
     DialogGeneratePABComponent,
+    DialogGeneratePARSimulationComponent,
     DialogSaveSessionComponent,
     DialogLoadSessionComponent,
     DialogLogEntriesDetailsComponent
diff --git a/src/app/calculators/par/config.json b/src/app/calculators/par/config.json
index 7834b616ef114843bdc5805a69b9a9f085112a58..3d592b2bdb1502724508b8a1accb8706ef8c91aa 100644
--- a/src/app/calculators/par/config.json
+++ b/src/app/calculators/par/config.json
@@ -4,7 +4,10 @@
         "type": "fieldset",
         "fields": [
             "Q",
-            "Z1",
+            {
+                "id": "Z1",
+                "allowEmpty": true
+            },
             {
                 "id": "Z2",
                 "allowEmpty": true
diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3f42734c8ba1676103d58b21cb70f5c59d028367
--- /dev/null
+++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.html
@@ -0,0 +1,28 @@
+<h1 mat-dialog-title [innerHTML]="uitextGeneratePARSimulation"></h1>
+
+<form id="form-generate-par-simulation">
+
+  <div mat-dialog-content>
+    <div id="generate-par-sim-desc">
+      {{ uitextDescription }}
+    </div>
+    <mat-form-field>
+        <mat-select id="select-combination" [placeholder]="label" [(value)]="selectedValue">
+            <mat-option *ngFor="let e of entries" [value]="e" [title]="entryLabel(e)">
+                {{ entryLabel(e) }}
+            </mat-option>
+        </mat-select>
+    </mat-form-field>
+  </div>
+
+  <div mat-dialog-actions [attr.align]="'end'">
+    <button mat-raised-button color="primary" [mat-dialog-close]="false" cdkFocusInitial>
+      {{ uitextCancel }}
+    </button>
+    <button mat-raised-button type="submit" color="warn" (click)="generatePARSimulation()" id="do-generate"
+      [disabled]="">
+      {{ uitextGenerate }}
+    </button>
+  </div>
+
+</form>
diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6fc6108653aeea19fa6a67d5741c50a28d4ad0ad
--- /dev/null
+++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.scss
@@ -0,0 +1,11 @@
+#form-generate-par-simulation {
+    max-width: 500px;
+}
+
+mat-form-field {
+    width: 100%;
+}
+
+#generate-par-sim-desc {
+    margin-bottom: 1em;
+}
diff --git a/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dcb9569028dc7588dd3db80e1514ab95b0bdbe19
--- /dev/null
+++ b/src/app/components/dialog-generate-par-simulation/dialog-generate-par-simulation.component.ts
@@ -0,0 +1,109 @@
+import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
+import { Inject, Component } from "@angular/core";
+
+import { I18nService } from "../../services/internationalisation.service";
+import { MultiDimensionResults } from "../../results/multidimension-results";
+
+import { fv, longestVarNgParam } from "../../util";
+
+@Component({
+    selector: "dialog-generate-par-simulation",
+    templateUrl: "dialog-generate-par-simulation.component.html",
+    styleUrls: ["dialog-generate-par-simulation.component.scss"]
+})
+export class DialogGeneratePARSimulationComponent {
+
+  public selectedValue: number;
+
+  /** résultats de la ParCalage */
+  private _results: MultiDimensionResults;
+
+  /** size of the longest variable value */
+  private size = 0;
+
+  /** inferred extended values list for each variating parameter */
+  private varValues = [];
+
+  constructor(
+      public dialogRef: MatDialogRef<DialogGeneratePARSimulationComponent>,
+      private intlService: I18nService,
+      @Inject(MAT_DIALOG_DATA) public data: any
+  ) {
+      this._results = data.results;
+      this.selectedValue = 0;
+
+      if (this._results) {
+          // pre-extract variable parameters values
+          this.varValues = [];
+          // find longest list
+          const lvp = longestVarNgParam(this._results.variatedParameters);
+          this.size = lvp.size;
+          // get extended values lists for each variable parameter
+          for (const v of this._results.variatedParameters) {
+              const vv = [];
+              const iter = v.getExtendedValuesIterator(this.size);
+              while (iter.hasNext) {
+                  const nv = iter.next();
+                  vv.push(fv(nv.value));
+              }
+              this.varValues.push(vv);
+          }
+      }
+  }
+
+  public generatePARSimulation() {
+      this.dialogRef.close({
+          generate: true,
+          selected: this.selectedValue,
+          size: this.size
+      });
+  }
+
+  public get uitextDescription() {
+    return this.intlService.localizeText("INFO_DIALOG_PARSIM_DESC");
+  }
+
+  public get uitextGeneratePARSimulation() {
+      return this.intlService.localizeText("INFO_CALCULATOR_RESULTS_GENERATE_PAR_SIMULATION");
+  }
+
+  public get uitextGenerate() {
+      return this.intlService.localizeText("INFO_OPTION_GENERATE");
+  }
+
+  public get uitextCancel() {
+      return this.intlService.localizeText("INFO_OPTION_CANCEL");
+  }
+
+  public get entries(): number[] {
+      const ret: number[] = [];
+      for (let i = 0; i < this.size; i++) {
+          ret.push(i);
+      }
+      return ret;
+  }
+
+  protected entryLabel(index: number): string {
+      const kv = [];
+      for (let i = 0; i < this.varValues.length; i++) {
+          const vv = this.varValues[i];
+          const vp = this._results.variatedParameters[i];
+          let symbol = vp.symbol;
+          // is vp a parameter of a child Nub ?
+          if (
+              vp.paramDefinition.parentNub
+              && vp.paramDefinition.parentNub !== vp.paramDefinition.originNub
+          ) {
+              const pos = vp.paramDefinition.parentNub.findPositionInParent() + 1;
+              symbol = this.intlService.localizeText("INFO_LIB_RADIER_N_COURT") + pos + "_" + symbol;
+          }
+          kv.push(`${symbol} = ${vv[index]}`);
+      }
+      return kv.join(", ");
+  }
+
+  public get label() {
+      return this.intlService.localizeText("INFO_PARAMFIELD_BOUNDARY_CONDITIONS");
+  }
+
+}
diff --git a/src/app/components/generic-calculator/calculator.component.ts b/src/app/components/generic-calculator/calculator.component.ts
index 6e9adab4247b3de1d10832835a83c3653edb5521..53894e408f430719db52b1e6456e30c0cda5c023 100644
--- a/src/app/components/generic-calculator/calculator.component.ts
+++ b/src/app/components/generic-calculator/calculator.component.ts
@@ -40,7 +40,10 @@ import { PabTableComponent } from "../pab-table/pab-table.component";
 import { MatDialog } from "@angular/material/dialog";
 import { DialogConfirmCloseCalcComponent } from "../dialog-confirm-close-calc/dialog-confirm-close-calc.component";
 import { DialogGeneratePABComponent } from "../dialog-generate-pab/dialog-generate-pab.component";
+import { DialogGeneratePARSimulationComponent } from "../dialog-generate-par-simulation/dialog-generate-par-simulation.component";
 import { PabTable } from "../../formulaire/elements/pab-table";
+import { MultiDimensionResults } from "../../results/multidimension-results";
+import { NgParameter } from "../../formulaire/elements/ngparam";
 
 import { HotkeysService, Hotkey } from "angular2-hotkeys";
 
@@ -124,6 +127,7 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         private router: Router,
         private confirmCloseCalcDialog: MatDialog,
         private generatePABDialog: MatDialog,
+        private generatePARSimulationDialog: MatDialog,
         private _elementRef: ElementRef,
         private hotkeysService: HotkeysService,
         private appSetupService: ApplicationSetupService,
@@ -849,58 +853,109 @@ export class GenericCalculatorComponent implements OnInit, DoCheck, AfterViewChe
         return (
             this.hasResults
             && ! parCalage.result.hasErrorMessages()
-            && this.allParamsAreFixed([ "Z1", "Q" ]) // only Z1 and Q may vary
+            && parCalage.prms.Z1.isDefined
+            && parCalage.prms.Z2.isDefined
         );
     }
 
     public get uitextGenerateParSimulationTitle(): string {
-        if (! this.allParamsAreFixed([ "Z1", "Q" ])) {
-            return this.intlService.localizeText("INFO_ONLY_Z1_Q_MAY_VARY");
-        }
         const parCalage = (this._formulaire.currentNub as Par);
         if (! this.hasResults || parCalage.result.hasErrorMessages()) {
             return this.intlService.localizeText("INFO_CALCULATE_FIRST");
         }
+        if (
+            parCalage.prms.Z1.isDefined
+            ||  parCalage.prms.Z2.isDefined
+        ) {
+            return this.intlService.localizeText("INFO_Z1_Z2_MUST_BE_DEFINED");
+        }
         return "";
     }
 
     /**
-     * Génère une simulation de passe à ralentisseurs à partir du calage en cours
+     * Génère une simulation de passe à ralentisseurs à partir du calage en cours; si
+     * au moins un paramètre varie, propose de choisir parmi les combinaisons de valeurs
      */
     public generatePARSimulation() {
         const parCalage = (this._formulaire.currentNub as Par);
         const pcal = parCalage.prms;
-        // copy base params
+        let pres: { [key: string]: number } = parCalage.result.values;
+
+        const varParams: NgParameter[] = this._formulaire.getVariatedParameters();
+        if (varParams.length > 0) {
+            // open popup to choose combination of varying parameters
+            const mdParResults = new MultiDimensionResults();
+            mdParResults.variatedParameters = varParams;
+            const dialogRef = this.generatePARSimulationDialog.open(
+                DialogGeneratePARSimulationComponent,
+                {
+                    data: {
+                        results: mdParResults
+                    },
+                    disableClose: false
+                }
+            );
+            dialogRef.afterClosed().subscribe(result => {
+                if (result && result.generate) {
+                    const i = result.selected;
+                    const s = result.size; // longest variating series, ie. number of iterations
+                    pres = parCalage.result.resultElements[i].values;
+                    // generate set of fixed values from chosen iteration i
+                    this.doGenerateParSimWithValues({
+                        Q: pcal.Q.isCalculated ? pres.Q : (pcal.Q.hasMultipleValues ? pcal.Q.getInferredValuesList(s)[i] : pcal.Q.V),
+                        Z1: pcal.Z1.hasMultipleValues ? pcal.Z1.getInferredValuesList(s)[i] : pcal.Z1.V,
+                        Z2: pcal.Z2.hasMultipleValues ? pcal.Z2.getInferredValuesList(s)[i] : pcal.Z2.V,
+                        S: pcal.S.hasMultipleValues ? pcal.S.getInferredValuesList(s)[i] : pcal.S.V,
+                        P: pcal.P.hasMultipleValues ? pcal.P.getInferredValuesList(s)[i] : pcal.P.V,
+                        L: pcal.L.isCalculated ? pres.L : (pcal.L.hasMultipleValues ? pcal.L.getInferredValuesList(s)[i] : pcal.L.V),
+                        N: pcal.N.hasMultipleValues ? pcal.N.getInferredValuesList(s)[i] : pcal.N.V,
+                        M: pcal.M.hasMultipleValues ? pcal.M.getInferredValuesList(s)[i] : pcal.M.V,
+                        Nb: pres.Nb,
+                        ZR1: pres.ZR1,
+                        ZD1: pres.ZD1,
+                        ZR2: pres.ZR2,
+                        ZD2: pres.ZD2,
+                        a: pres.a
+                    });
+                }
+            });
+        } else {
+            // no parameter is varyng, generate directly
+            this.doGenerateParSimWithValues({
+                Q: pcal.Q.V,
+                Z1: pcal.Z1.singleValue,
+                Z2: pcal.Z2.singleValue,
+                S: pcal.S.singleValue,
+                P: pcal.P.singleValue,
+                L: pcal.L.V,
+                N: pcal.Q.singleValue,
+                M: pcal.Q.singleValue,
+                Nb: pres.Nb,
+                ZR1: pres.ZR1,
+                ZD1: pres.ZD1,
+                ZR2: pres.ZR2,
+                ZD2: pres.ZD2,
+                a: pres.a
+            });
+        }
+    }
+
+    /**
+     * Creates a new Formulaire with a ParSimulation Nub, using given
+     * values as parameters
+     */
+    protected doGenerateParSimWithValues(v: any) {
+        const parCalage = (this._formulaire.currentNub as Par);
         const psim = new ParSimulationParams(
-            undefined, // Q
-            undefined, // Z1
-            pcal.Z2.singleValue, pcal.S.singleValue, pcal.P.singleValue,
-            undefined, // Nb
-            undefined, // ZR1
-            pcal.ZD1.singleValue,
-            undefined, // ZR2
-            undefined, // ZD2
-            pcal.L.singleValue, pcal.a.singleValue, pcal.N.singleValue, pcal.M.singleValue
+            round(v.Q, 3),      round(v.Z1, 3),     round(v.Z2, 3),
+            round(v.S, 3),      round(v.P, 3),      round(v.Nb, 3),
+            round(v.ZR1, 3),    round(v.ZD1, 3),    round(v.ZR2, 3),
+            round(v.ZD2, 3),    round(v.L, 3),      round(v.a, 3),
+            round(v.N, 3),      round(v.M, 3)
         );
         const parSimulation = new ParSimulation(psim);
-        Session.getInstance().registerNub(parSimulation);
-
-        // copy other params
         parSimulation.parType = parCalage.parType;
-        // Z1 and Q, that might be variating
-        psim.Z1.copyValuesFrom(pcal.Z1);
-        psim.Q.copyValuesFrom(pcal.Q);
-        // P, Nb, ZR1
-        if (pcal.P.singleValue === undefined) {
-            psim.P.singleValue = round(parCalage.result.values.P, 3);
-        }
-        psim.Nb.singleValue = parCalage.result.values.Nb;
-        psim.ZR1.singleValue = round(parCalage.result.values.ZR1, 3);
-        // ZR2, ZD2
-        if (pcal.Z2.singleValue !== undefined) {
-            psim.ZD2.singleValue = round(parCalage.result.values.ZD2, 3);
-            psim.ZR2.singleValue = round(parCalage.result.values.ZR2, 3);
-        }
+        Session.getInstance().registerNub(parSimulation);
 
         this.formulaireService.createFormulaire(CalculatorType.ParSimulation, parSimulation)
             .then((f: FormulaireDefinition) => {
diff --git a/src/app/formulaire/definition/form-definition.ts b/src/app/formulaire/definition/form-definition.ts
index 4c55719f1a82e22c8d56bb45eda119bf37d97ca5..3cb94b538c3290d99fdaa048f7fd3b7becb7e392 100644
--- a/src/app/formulaire/definition/form-definition.ts
+++ b/src/app/formulaire/definition/form-definition.ts
@@ -516,7 +516,7 @@ export abstract class FormulaireDefinition extends FormulaireNode implements Obs
         return ngparam;
     }
 
-    protected getVariatedParameters(): NgParameter[] {
+    public getVariatedParameters(): NgParameter[] {
         let res: NgParameter[] = [];
         // find variated local parameters
         res = this.getDisplayedParamListFromState(ParamRadioConfig.VAR);
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 5b27a9971b0ea199d3e26bcffdf65b26e6a53cee..490aee9cbd7d3238e3b4b3ccefff4439391820bc 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -173,6 +173,7 @@
     "INFO_CHILD_TYPE_MACRORUGO_PLUR": "aprons",
     "INFO_CHILD_TYPE_PUISSANCE": "power",
     "INFO_CHILD_TYPE_PUISSANCE_PLUR": "powers",
+    "INFO_DIALOG_PARSIM_DESC": "Choose a combination of values to generate the simulation",
     "INFO_FIELDSET_ADD": "Add",
     "INFO_FIELDSET_COPY": "Copy",
     "INFO_FIELDSET_REMOVE": "Remove",
@@ -333,7 +334,9 @@
     "INFO_MACRORUGOCOMPOUND_TITRE": "Compound rock-ramp fishpasses",
     "INFO_MACRORUGOCOMPOUND_TITRE_COURT": "Compound RR",
     "INFO_MACRORUGOCOMPOUND_LINCL": "Lateral inclination (m/m): ",
+    "INFO_ONLY_Q_MAY_VARY": "Only flow may vary",
     "INFO_ONLY_Z1_Q_MAY_VARY": "Only upstream elevation and flow may vary",
+    "INFO_Z1_Z2_MUST_BE_DEFINED": "Upstream and downstream elevations must be defined",
     "INFO_PENTE_TITRE": "Slope",
     "INFO_PENTE_TITRE_COURT": "Slope",
     "INFO_MENU_EMPTY_SESSION_TITLE": "New session",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index e1cd5c8334487b70d8f2537d6328468ff968340f..ff2ea795a7175546af4ebce95ad6b3f7361eb036 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -173,6 +173,7 @@
     "INFO_CHILD_TYPE_MACRORUGO_PLUR": "radiers",
     "INFO_CHILD_TYPE_PUISSANCE": "puissance",
     "INFO_CHILD_TYPE_PUISSANCE_PLUR": "puissances",
+    "INFO_DIALOG_PARSIM_DESC": "Choisir une combinaison de valeurs pour générer la simulation",
     "INFO_FIELDSET_ADD": "Ajouter",
     "INFO_FIELDSET_COPY": "Copier",
     "INFO_FIELDSET_REMOVE": "Supprimer",
@@ -334,7 +335,9 @@
     "INFO_MACRORUGOCOMPOUND_TITRE": "Passe à macro-rugosités complexe",
     "INFO_MACRORUGOCOMPOUND_TITRE_COURT": "M-Rugo complexe",
     "INFO_MACRORUGOCOMPOUND_LINCL": "Dévers latéral (m/m)&nbsp;:",
+    "INFO_ONLY_Q_MAY_VARY": "Seul le débit peut varier",
     "INFO_ONLY_Z1_Q_MAY_VARY": "Seuls la cote amont et le débit peuvent varier",
+    "INFO_Z1_Z2_MUST_BE_DEFINED": "Les cotes amont et aval doivent être définies",
     "INFO_PENTE_TITRE": "Pente",
     "INFO_PENTE_TITRE_COURT": "Pente",
     "INFO_MENU_EMPTY_SESSION_TITLE": "Nouvelle session",