Quickstart¶
Install¶
# From PyPI:
pip install cooling-tower-chem
# Or install the latest development version from source:
pip install git+https://github.com/Madhvansh/cooling-tower-chem
No third-party dependencies. Pure standard-library Python, tested on CPython 3.9–3.13.
One sample, every index¶
from cooling_tower_chem import WaterSample
sample = WaterSample(
ph=8.2,
temperature_c=32,
calcium_hardness=450, # mg/L as CaCO3
total_alkalinity=250, # mg/L as CaCO3
conductivity_us_cm=2400, # TDS derived from this if not given
chloride=180, # mg/L (for the Larson-Skold index)
sulfate=120, # mg/L
)
print(sample.lsi()) # 1.38 -> scale-forming
print(sample.rsi()) # 5.44 -> heavy scale
report = sample.report() # JSON-serializable dict of every index + interpretation
Working in US units?¶
If your analysis is in customary US units — temperature in °F and
hardness/alkalinity in grains per gallon (as CaCO₃) — use
WaterSample.from_us_units, which converts them internally and returns an
ordinary WaterSample:
from cooling_tower_chem import WaterSample
sample = WaterSample.from_us_units(
ph=8.2,
temperature_f=90, # °F
calcium_hardness_gpg=26.3, # grains/gallon as CaCO3
total_alkalinity_gpg=14.6, # grains/gallon as CaCO3
conductivity_us_cm=2400, # TDS/conductivity keep their usual units
)
print(round(sample.lsi(), 2)) # identical to the SI constructor
Prefer plain functions?¶
from cooling_tower_chem import (
langelier_saturation_index,
ryznar_stability_index,
puckorius_scaling_index,
larson_skold_index,
)
lsi = langelier_saturation_index(
ph=7.5, temperature_c=25, tds=400,
calcium_hardness=240, total_alkalinity=180,
) # -> +0.19
Cooling-tower water balance¶
The CoolingTower object ties the balance together and projects how makeup water
concentrates in the basin:
from cooling_tower_chem import CoolingTower, WaterSample
tower = CoolingTower(circulation_rate=1000, delta_t_c=6, cycles=5) # m3/h
print(tower.water_balance())
# {'evaporation': 10.2514, 'drift': 0.2, 'blowdown': 2.3629, 'makeup': 12.8143, 'cycles': 5}
makeup = WaterSample(ph=7.8, temperature_c=32, calcium_hardness=90,
total_alkalinity=60, conductivity_us_cm=400)
basin = tower.concentrated(makeup) # conservative species x cycles
print(round(makeup.lsi(), 2), "->", round(basin.lsi(), 2)) # -0.26 -> 1.07
Units & conventions¶
- Calcium hardness and total alkalinity: mg/L as CaCO₃
- TDS and ions (chloride, sulfate): mg/L
- Temperature: °C (use
celsius_to_fahrenheit/fahrenheit_to_celsiusto convert) - Flows: any consistent volumetric unit (m³/h, gpm, …) — results carry the same unit
Inputs that would break a logarithm (non-positive hardness, alkalinity, or TDS)
raise a clear ValueError rather than returning a silent fallback.
See the runnable scripts in
examples/.