Antiscalant Dosing: Optimizer Example | Vose Software

ModelRisk Optimizer example · Energy and utilities

Desalination Plant: Antiscalant Dosing

How much antiscalant should each reverse-osmosis train receive when feed salinity is uncertain?

  • Complexity: ★★★★★
  • Free Excel workbook
  • Needs ModelRisk with the Optimizer

The optimisation problem

Lowest mean daily cost

Decide
6 antiscalant doses, 0 to 8
Goal
Lowest mean daily cost
Limit
95th-percentile brine toxicity no more than 34
Engine
Vertex Detector

What the Optimizer found

Starting planOptimizer’s plan
Train 131
Train 231
Train 332
Train 432
Train 531
Train 632
Goal: Mean total cost ($/day)2,5201,682
Limit: 95th percentile of brine toxicity index, at most 3423.8 met14.8 met

ModelRisk Optimizer run on 13 Oct 2026: the Vertex Detector engine, with Turbo simulation, tried 296 plans, each simulated with 10,000 samples, in 3 seconds. Both plans above were then simulated again with the same 10,000 samples.

What the workbook models

A seawater RO plant runs 6 membrane trains. Antiscalant suppresses mineral scaling but is costly and loads the brine discharge with toxicity. Feed salinity varies day to day (lognormal), so whether a train fouls — and needs an expensive clean-in-place — is uncertain. You choose an integer dose 0 to 8 per train.

Decision, objective and constraint

Decision variables
6 integer antiscalant doses (Model!B15:B20), each 0 to 8
Objective
Minimise the Mean of total daily cost (antiscalant + expected clean-in-place), Model!C25
Hard constraint
95th-percentile brine toxicity index ≤ 34 (Model!C26) — a service-level / discharge-permit limit

Why the Vertex Detector

The percentile (chance) constraint makes the feasible region a thin, noisy boundary walled by an infinite penalty: any dose vector that violates the 95% toxicity limit is infeasible, so finite-difference gradient engines see a flat wall and stall. Method = Auto routes this integer + percentile-constrained model to the Vertex Detector, which samples vertices and walks the feasible edge to the least-cost dose plan.

The model

Set the antiscalant dose on each RO train to minimise expected cost while holding a 95% brine-toxicity limit.

InputDecision (the Optimizer changes it)Calculated or uncertain (sampled each iteration)Objective

Plant parameters

Scaling decay per dose unit k0.28
Fouling threshold (scaling index)1.05
Antiscalant cost per dose unit ($/day)140
Membrane clean-in-place cost if fouled ($)2,600
Brine toxicity per dose unit (index)1.00
95%-tile toxicity limit34.00

Membrane trains (decision = integer dose 0 to 8)

TrainDose (0-8)Feed salinity ×Scaling indexFouled clean $Toxicity
Train 13uncertaincalculatedcalculateduncertain
Train 23uncertaincalculatedcalculateduncertain
Train 33uncertaincalculatedcalculateduncertain
Train 43uncertaincalculatedcalculateduncertain
Train 53uncertaincalculatedcalculateduncertain
Train 63uncertaincalculatedcalculateduncertain

Results

Antiscalant cost ($/day)calculated
Expected clean cost ($/day)calculated
TOTAL cost ($/day): objectivecalculated
Brine toxicity index: constraintcalculated

Decision cells hold starting values: the workbook opens at the starting plan above, and the Optimizer finds its plan when you run it. The figures are illustrative.

Run it yourself. Open the workbook with ModelRisk, open the Optimizer from the ribbon (the saved task opens with it) and press Start.

How to run it

  1. ModelRisk ribbon then Optimizer (the saved task opens automatically).
  2. Press Start Optimization.
  3. Read the optimal doses in B15:B20 and the cost in C25.
  4. Simulation: 1000 Monte-Carlo iterations per trial (needed for a stable 95th percentile).

Glossary

Antiscalant
chemical that keeps dissolved minerals from precipitating on the membrane
Clean-in-place
chemical wash of a fouled membrane train; costly and interrupts production
95th percentile
the value the toxicity index stays below on 95% of simulated days

Find similar models