Skip to content

Water Stability Calculator (LSI, RSI, PSI, CCPP)

This is an interactive Langelier Saturation Index calculator that also reports the Ryznar Stability Index (RSI), the Puckorius (Practical) Scaling Index (PSI), and the Calcium Carbonate Precipitation Potential (CCPP) for cooling-tower and process water. Enter a pH, temperature, calcium hardness, total alkalinity, and TDS, and it tells you whether the water tends to scale or corrode — and, via CCPP, roughly how much calcium carbonate is at stake.

The math runs entirely in your browser (nothing is uploaded). Every formula is a faithful port of the cooling-tower-chem Python library, using the same constants and the same interpretation bands, and the numbers are cross-checked against the library on this page. For the full-analysis Python API, the ctchem command line, and the cooling-tower cycles of concentration / blowdown balance, see the rest of the docs.

Water analysis

Results

Running self-test…

How it's computed

Every value above comes from the same formulas the Python library uses, ported unchanged. The shared building block is the pH of saturation (pHs), the standard analytical form of Langelier's equation:

pHs = (9.3 + A + B) - (C + D)
A   = (log10(TDS) - 1) / 10
B   = -13.12 * log10(T_kelvin) + 34.55
C   = log10(calcium_hardness_as_CaCO3) - 0.4
D   = log10(total_alkalinity_as_CaCO3)
Index Formula Source
LSI (Langelier Saturation Index) LSI = pH - pHs Langelier, W. F. (1936), J. AWWA 28(10)
RSI (Ryznar Stability Index) RSI = 2*pHs - pH Ryznar, J. W. (1944), J. AWWA 36(4)
PSI (Puckorius Scaling Index) PSI = 2*pHs - pH_eq, with pH_eq = 1.465*log10(alkalinity) + 4.54 Puckorius & Brooke (1991), Corrosion 47(4)
CCPP (Calcium Carbonate Precipitation Potential) closed-system carbonate equilibrium solved to [Ca][CO3] = Ksp, in mg/L as CaCO₃ Plummer & Busenberg (1982); Wojtowicz (2001)

The PSI deliberately replaces the measured pH with an equilibrium pH driven only by alkalinity, which makes it a better fit for the highly buffered, recirculating water typical of cooling towers. CCPP goes beyond the direction the indices give and estimates the quantity of calcium carbonate that would precipitate (+) or dissolve () to reach calcite saturation; it is solved iteratively with the Plummer & Busenberg equilibrium constants and a Davies activity model (ionic strength estimated as μ ≈ 2.5×10⁻⁵ · TDS).

The interpretation bands (LSI target ≈ 0 to +1; RSI/PSI < 6 scaling, 6–7 balanced, > 7 corrosive) and their wording are ported verbatim from the library's interpret module. For the full derivation, the Stiff-Davis index for high-salinity water, and the cooling-tower water balance, see Indices & the science and CCPP.

Note

These are screening calculations, not a substitute for site-specific engineering judgment or a jar test. Band edges vary between published sources (some Ryznar tables put the balanced/corrosive boundary at 6.8 rather than 7.0), so treat values near a boundary as borderline. CCPP in particular is a semi-quantitative screen: its magnitude is dominated by the ionic-strength (activity) correction, and the dependency-free Davies model carries no ion pairing, so it tends to over-predict precipitation for hard, high-TDS water relative to a full speciation model such as PHREEQC. See the interpretation guidance for details.

Run the same numbers in Python

The calculator is a browser port of cooling-tower-chem. To compute the same indices in a script, notebook, or pipeline — and get input validation, the Stiff-Davis and Larson-Skold indices, unit conversions, and the cooling-tower water balance — install the library:

# From source (the first PyPI release is pending):
pip install git+https://github.com/Madhvansh/cooling-tower-chem
from cooling_tower_chem import WaterSample

# The default inputs of the calculator above (TDS 1560 mg/L).
sample = WaterSample(
    ph=8.2, temperature_c=32,
    calcium_hardness=450, total_alkalinity=250,  # mg/L as CaCO3
    tds=1560,
)
print(round(sample.lsi(), 2))   # 1.38  -> scale-forming
print(round(sample.rsi(), 2))   # 5.44  -> heavy scale
print(round(sample.psi(), 2))   # 5.59
print(round(sample.ccpp(), 1))  # 66.6  mg/L as CaCO3

Installing the package also gives you the ctchem command line, which reproduces the same figures:

$ ctchem report --ph 8.2 --temp 32 --calcium 450 --alkalinity 250 --tds 1560
pH of saturation (pHs): 6.821
LSI: 1.379  [scale_forming]
    LSI +1.38: scale-forming; calcium carbonate will tend to precipitate.
RSI: 5.443  [severely_scale_forming]
    RSI 5.44: heavy scale formation expected.
...

$ ctchem ccpp --ph 8.2 --temp 32 --calcium 450 --alkalinity 250 --tds 1560
CCPP = +66.59 mg/L as CaCO3

See the Command line page for every subcommand and --json output.

Cross-checked against the library

To keep the browser calculator honest, this page runs a self-test on load: it computes four reference cases with the in-page JavaScript and asserts each matches values produced by the cooling-tower-chem Python library (.venv CPython) to within 0.01. The badge under the calculator reports the result; the observed maximum deviation is on the order of 1e-6.

Case Inputs (pH, °C, TDS, Ca, Alk) LSI RSI PSI CCPP (mg/L as CaCO₃)
A 8.2, 32, 1560, 450, 250 +1.38 5.44 5.59 +66.6
B 7.5, 25, 400, 240, 180 +0.19 7.12 6.78 +17.5
C 8.0, 30, 2000, 900, 250 +1.43 5.14 5.08 +88.3
D 7.0, 20, 150, 50, 40 −1.70 10.40 10.51 −17.3

The JavaScript and Python columns agree on all four cases (the table shows the rounded Python values; the self-test compares against the full-precision figures).