API reference¶
Auto-generated from the source docstrings.
Indices¶
cooling_tower_chem.indices ¶
Water-stability and corrosion indices for cooling-tower and process water.
All indices use the classical water-chemistry conventions:
- Calcium hardness and total alkalinity are expressed in mg/L as CaCO3.
- Total dissolved solids (TDS) is in mg/L.
- Temperature is in degrees Celsius.
- Chloride and sulfate are in mg/L (as the ion).
The saturation pH (ph_of_saturation) uses 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)
References
- Langelier, W. F. (1936). "The Analytical Control of Anti-Corrosion Water Treatment." J. AWWA 28(10), 1500-1521.
- Ryznar, J. W. (1944). "A New Index for Determining Amount of Calcium Carbonate Scale Formed by a Water." J. AWWA 36(4), 472-483.
- Puckorius, P. R. & Brooke, J. M. (1991). "A New Practical Index for Calcium Carbonate Scale Prediction in Cooling Tower Systems." Corrosion 47(4).
- Larson, T. E. & Skold, R. V. (1958). "Laboratory Studies Relating Mineral Quality of Water to Corrosion of Steel and Cast Iron." Corrosion 14(6).
ph_of_saturation ¶
ph_of_saturation(temperature_c: float, tds: float, calcium_hardness: float, total_alkalinity: float) -> float
Return the pH of calcium-carbonate saturation (pHs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
temperature_c
|
float
|
Water temperature in degrees Celsius. |
required |
tds
|
float
|
Total dissolved solids in mg/L. If you only have conductivity, convert
it first with :func: |
required |
calcium_hardness
|
float
|
Calcium hardness in mg/L as CaCO3. |
required |
total_alkalinity
|
float
|
Total alkalinity in mg/L as CaCO3. |
required |
Returns:
| Type | Description |
|---|---|
float
|
The saturation pH. |
Source code in src/cooling_tower_chem/indices.py
langelier_saturation_index ¶
langelier_saturation_index(ph: float, temperature_c: float, tds: float, calcium_hardness: float, total_alkalinity: float) -> float
Langelier Saturation Index (LSI): pH - pHs.
LSI > 0— water is supersaturated; calcium carbonate tends to precipitate (scaling).LSI = 0— water is at equilibrium.LSI < 0— water is undersaturated; it tends to dissolve calcium carbonate (corrosive / aggressive).
For most cooling-tower programs a small positive LSI (roughly 0 to
+1) is targeted to lay a thin protective scale without fouling.
Source code in src/cooling_tower_chem/indices.py
ryznar_stability_index ¶
ryznar_stability_index(ph: float, temperature_c: float, tds: float, calcium_hardness: float, total_alkalinity: float) -> float
Ryznar Stability Index (RSI): 2*pHs - pH.
The RSI is always positive and is read on an empirical scale:
RSI < 6— scale-forming;6 <= RSI <= 7— approximately balanced;RSI > 7— corrosive (increasingly so above ~8).
Source code in src/cooling_tower_chem/indices.py
puckorius_scaling_index ¶
puckorius_scaling_index(temperature_c: float, tds: float, calcium_hardness: float, total_alkalinity: float) -> float
Puckorius (Practical) Scaling Index (PSI): 2*pHs - pH_eq.
The PSI replaces the measured pH of the RSI with an equilibrium pH driven
only by alkalinity, pH_eq = 1.465 * log10(total_alkalinity) + 4.54. This
makes it a better predictor than LSI/RSI for the highly buffered,
recirculating water typical of cooling towers, where measured pH can swing
without changing scaling potential.
Interpreted on the same empirical scale as the RSI (< 6 scaling,
6-7 balanced, > 7 corrosive). Note the PSI does not take a measured
pH argument by design.
Source code in src/cooling_tower_chem/indices.py
larson_skold_index ¶
Larson-Skold index: corrosivity of water toward mild steel.
Defined as the equivalents ratio
(Cl- + SO4(2-)) / (HCO3- + CO3(2-)). Alkalinity is supplied here as
mg/L as CaCO3 and converted to equivalents internally.
< 0.8— chlorides and sulfates are unlikely to interfere with a protective film;0.8 - 1.2— chlorides and sulfates may increase corrosion rates;> 1.2— high corrosion rates on mild steel are expected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chloride
|
float
|
Concentrations in mg/L (as the ion). |
required |
sulfate
|
float
|
Concentrations in mg/L (as the ion). |
required |
total_alkalinity
|
float
|
Total alkalinity in mg/L as CaCO3 (must be > 0). |
required |
Source code in src/cooling_tower_chem/indices.py
stiff_davis_ph_of_saturation ¶
stiff_davis_ph_of_saturation(temperature_c: float, calcium_hardness: float, total_alkalinity: float, ionic_strength: float) -> float
Stiff-Davis pH of saturation: pHs = pCa + pAlk + K.
pCa and pAlk are molar negative logs, derived from the CaCO3-basis
inputs ([Ca] = hardness / 100086.9 mol/L, [Alk] = alkalinity / 50043.45
eq/L). K comes from :func:_stiff_davis_k.
Source code in src/cooling_tower_chem/indices.py
stiff_davis_index ¶
stiff_davis_index(ph: float, temperature_c: float, calcium_hardness: float, total_alkalinity: float, tds: float | None = None, ionic_strength: float | None = None) -> float
Stiff-Davis Stability Index (S&DSI): pH - pHs, for high-salinity water.
The Langelier/Ryznar indices lose accuracy at high ionic strength (brines,
seawater, concentrated blowdown). The Stiff-Davis index corrects for this by
replacing the LSI temperature/TDS terms with an ionic-strength-dependent
constant K. Read like the LSI: > 0 scale-forming, < 0 corrosive.
Provide the ionic strength directly (mol/L), or tds (mg/L) to estimate it
via I = 2.5e-5 * TDS. Hardness and alkalinity are mg/L as CaCO3.
.. note::
S&DSI is intended for the high-salinity regime (roughly TDS > 10,000 mg/L,
ionic strength >= ~0.05 mol/L). The K curve fit is unreliable at very
low ionic strength; use :func:langelier_saturation_index for
low-salinity water instead.
References: Stiff & Davis (1952); ASTM D4582; USBR (2013).
Source code in src/cooling_tower_chem/indices.py
aggressiveness_index ¶
AWWA Aggressiveness Index (AI): pH + log10(calcium_hardness * alkalinity).
Originally standardized (AWWA C400) for asbestos-cement pipe, the AI is a simplified, temperature-independent corrosivity screen:
AI >= 12— non-aggressive;10 <= AI < 12— moderately aggressive;AI < 10— highly aggressive.
Hardness and alkalinity are in mg/L as CaCO3.
Source code in src/cooling_tower_chem/indices.py
CCPP (advanced)¶
cooling_tower_chem.advanced ¶
Quantitative closed-system carbonate chemistry: the CaCO3 precipitation potential.
The saturation indices in :mod:cooling_tower_chem.indices (LSI, RSI, S&DSI, ...)
report a direction — whether water tends to scale or corrode — but not how
much calcium carbonate is involved. The Calcium Carbonate Precipitation
Potential (CCPP) closes that gap: it is the mass of CaCO3, in mg/L as CaCO3,
that must precipitate (positive) or dissolve (negative) to bring the water to
exact calcite saturation (saturation index SI = 0).
Method
There is no closed form in the general case, so the equilibrium is solved
iteratively. The water is treated as a closed system: as CaCO3 is deposited
or dissolved the total (carbonate) alkalinity and the CO2-acidity are held
conservative. Removing one mole of CaCO3 removes one mole of calcium, one mole
of total carbonate, and two equivalents of alkalinity; the CO2-acidity
2*CT - Alk is therefore unchanged. The equilibrium calcium, carbonate and
pH that satisfy [Ca][CO3] = Ksp are found by a bracketed root search, and
CCPP (mg/L as CaCO3) = x * 100086.9 (x = mol/L of CaCO3 exchanged)
Thermodynamic equilibrium constants are the Plummer & Busenberg (1982) fits
(T in kelvin); at 25 C they give pK1 = 6.352, pK2 = 10.329,
pK_sp(calcite) = 8.480 and log Kw = -13.995. They are converted to
conditional (concentration) constants with single-ion activity coefficients from
the Davies equation, log gamma = -A z^2 (sqrt(I)/(1 + sqrt(I)) - 0.3 I) with
A = 0.509 (its 25 C value), valid to an ionic strength of about 0.5 mol/L.
References
- Plummer, L. N. & Busenberg, E. (1982). "The solubilities of calcite, aragonite and vaterite in CO2-H2O solutions between 0 and 90 C." Geochim. Cosmochim. Acta 46(6), 1011-1040.
- Wojtowicz, J. A. (2001). "The Calcium Carbonate Precipitation Potential (CCPP) and its Use in Pool Water Balance." J. Swimming Pool & Spa Industry 2(2), 23-29.
- Rossum, J. R. & Merrill, D. T. (1983). "An Evaluation of the Calcium Carbonate Saturation Indexes." J. AWWA 75(1), 95-100.
- Standard Methods for the Examination of Water and Wastewater, Method 2330 (Calcium Carbonate Saturation).
- Tang, C. et al. (2021). "Prediction of Calcium Carbonate Precipitation Potential." Water 13(1), 42.
calcium_carbonate_precipitation_potential ¶
calcium_carbonate_precipitation_potential(ph: float, temperature_c: float, calcium_hardness: float, total_alkalinity: float, tds: float | None = None, ionic_strength: float | None = None) -> float
Calcium Carbonate Precipitation Potential (CCPP), in mg/L as CaCO3.
The signed mass of calcium carbonate that must precipitate (positive) or
dissolve (negative) to bring the water to exact calcite saturation
(SI = 0), computed for a closed system in which the total alkalinity and
CO2-acidity are conserved as CaCO3 is exchanged (see the module docstring for
the method and the Plummer & Busenberg / Wojtowicz references).
Provide the ionic strength directly (ionic_strength, mol/L) or a tds
(mg/L) from which it is estimated as I = 2.5e-5 * TDS via
:func:cooling_tower_chem.balance.ionic_strength_from_tds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ph
|
float
|
Measured pH of the water (treated as |
required |
temperature_c
|
float
|
Water temperature in degrees Celsius. |
required |
calcium_hardness
|
float
|
Calcium hardness in mg/L as CaCO3 (must be > 0). |
required |
total_alkalinity
|
float
|
Total (carbonate) alkalinity in mg/L as CaCO3 (must be > 0). |
required |
tds
|
float | None
|
Total dissolved solids in mg/L, used to estimate ionic strength when
|
None
|
ionic_strength
|
float | None
|
Ionic strength in mol/L. Takes precedence over |
None
|
Returns:
| Type | Description |
|---|---|
float
|
CCPP in mg/L as CaCO3: |
Notes
This is a screening estimate, not a substitute for a full speciation model.
Its magnitude is dominated by the activity correction, so it is sensitive to
the ionic strength: the I = 2.5e-5 * TDS estimate is rough, and the
dependency-free Davies model carries no ion pairing (e.g. CaHCO3+, CaCO3-aq),
so it tends to over-predict precipitation for hard, high-TDS water relative to
an ion-pairing model such as PHREEQC. Supply a measured or model-derived
ionic_strength when accuracy matters. The Davies A is held at its
25 C value (0.509); the closed-system assumption (no CO2 exchange with the
atmosphere) suits a snapshot of a recirculating loop rather than an aerated
basin.
Raises:
| Type | Description |
|---|---|
ValueError
|
If an input is non-finite or non-physical, or if neither |
Source code in src/cooling_tower_chem/advanced.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
Water balance¶
cooling_tower_chem.balance ¶
Cooling-tower water balance: cycles of concentration and evaporation/blowdown.
These helpers relate the four water streams of an evaporative cooling tower:
- Evaporation (E) — pure water lost to the air; it concentrates dissolved solids in the remaining water.
- Drift / windage (D) — liquid droplets carried out in the air stream.
- Blowdown / bleed (B) — water deliberately discharged to cap the dissolved solids concentration.
- Makeup (M) — fresh water added to replace all losses:
M = E + B + D.
Cycles of concentration (CoC) is the ratio of a conservative species'
concentration in the recirculating water to its concentration in the makeup
water, and equals M / (B + D).
All flow rates share whatever volumetric unit you pass in (e.g. m3/h or gpm); the functions only take ratios and sums, so the result carries the same unit.
tds_from_conductivity ¶
Estimate TDS (mg/L) from electrical conductivity (uS/cm).
TDS ~= factor * conductivity. The factor depends on the ionic makeup of
the water and typically ranges 0.55-0.70 for cooling-tower water; 0.65 is a
common default. Calibrate against a lab TDS when accuracy matters.
Source code in src/cooling_tower_chem/balance.py
conductivity_from_tds ¶
Inverse of :func:tds_from_conductivity: estimate uS/cm from mg/L TDS.
Source code in src/cooling_tower_chem/balance.py
ionic_strength_from_tds ¶
Estimate ionic strength (mol/L) from TDS (mg/L).
Uses the standard approximation I = 2.5e-5 * TDS (Langelier, 1936;
reproduced in Snoeyink & Jenkins and APHA Standard Methods). If you have a
full ion analysis, computing I = 0.5 * sum(c_i * z_i^2) directly is more
accurate. Ionic strength feeds the Stiff-Davis index
(:func:cooling_tower_chem.indices.stiff_davis_index).
Source code in src/cooling_tower_chem/balance.py
cycles_of_concentration ¶
Cycles of concentration from a conservative-species ratio.
Pass the concentration of a species that leaves only via blowdown/drift
(conductivity, chloride, or silica are common choices) in the recirculating
water and in the makeup water. CoC = circulating / makeup.
Source code in src/cooling_tower_chem/balance.py
evaporation_loss ¶
evaporation_loss(circulation_rate: float, delta_t_c: float, latent_heat_kj_per_kg: float | None = None, specific_heat_kj_per_kg_c: float = 4.186) -> float
Evaporation rate from a first-principles energy balance.
E = circulation_rate * cp * delta_t / latent_heat. Roughly 1% of the
circulating flow evaporates per ~5.5 C (10 F) of cooling range, which this
energy balance reproduces.
Note this assumes all rejected heat leaves as latent heat of
vaporization, so it returns the theoretical maximum evaporation. Real
towers also reject some sensible/convective heat, so field evaporation is
typically ~75-90% of this value; apply a heat-rejection factor if you need
the practical estimate, or pass a temperature-appropriate latent_heat.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
circulation_rate
|
float
|
Recirculating water flow (any volumetric unit; the result is returned in the same unit). |
required |
delta_t_c
|
float
|
Cooling range: the temperature drop across the tower, in C. |
required |
latent_heat_kj_per_kg
|
float | None
|
Latent heat of vaporization. If omitted, a temperature-independent 2450 kJ/kg (typical near 30-35 C) is used. |
None
|
specific_heat_kj_per_kg_c
|
float
|
Specific heat of water, default 4.186 kJ/(kg.C). |
4.186
|
Source code in src/cooling_tower_chem/balance.py
drift_loss ¶
Drift (windage) loss as a fraction of circulation.
Modern drift eliminators achieve 0.001%-0.02% of circulating flow; the default 0.0002 (0.02%) is a conservative upper estimate for a tower with good eliminators.
Source code in src/cooling_tower_chem/balance.py
blowdown_loss ¶
Required blowdown to hold a target cycles of concentration.
From the dissolved-solids mass balance, B = E / (CoC - 1) - D. The
result is clamped at zero (if drift alone already exceeds the solids budget,
no blowdown is needed).
Source code in src/cooling_tower_chem/balance.py
makeup_water ¶
Makeup water required: M = E + B + D.
Source code in src/cooling_tower_chem/balance.py
cycles_from_flows ¶
Cycles of concentration from the water streams: CoC = M / (B + D).
Source code in src/cooling_tower_chem/balance.py
water_saved_by_increasing_cycles ¶
water_saved_by_increasing_cycles(evaporation: float, cycles_low: float, cycles_high: float, drift: float = 0.0) -> float
Makeup water saved per unit time by raising cycles of concentration.
Increasing CoC reduces blowdown (and therefore makeup) for the same
evaporative duty. Returns makeup(cycles_low) - makeup(cycles_high) in the
same flow unit as evaporation. A positive result is water saved; raising
cycles from, say, 3 to 6 typically cuts makeup noticeably.
Source code in src/cooling_tower_chem/balance.py
Interpretation¶
cooling_tower_chem.interpret ¶
Human-readable interpretation of the water-chemistry indices.
Each interpret_* function maps a numeric index to a :class:Tendency
(a coarse scaling/corrosion classification) and a short sentence. Thresholds
follow the conventional bands cited in the index references; they are screening
guides, not a substitute for site-specific engineering judgment.
Band edges vary between published sources (for example, some Ryznar tables put the balanced/corrosive boundary at 6.8 rather than 7.0). This module uses the common "RSI 6-7 balanced" convention; treat values near a boundary as borderline rather than decisive.
Tendency ¶
Bases: str, Enum
Coarse classification shared by the interpretation helpers.
Source code in src/cooling_tower_chem/interpret.py
interpret_lsi ¶
Interpret a Langelier Saturation Index value.
Source code in src/cooling_tower_chem/interpret.py
interpret_rsi ¶
Interpret a Ryznar Stability Index value.
Source code in src/cooling_tower_chem/interpret.py
interpret_psi ¶
Interpret a Puckorius Scaling Index value (same bands as the RSI).
interpret_stiff_davis ¶
Interpret a Stiff-Davis Stability Index (same directional bands as the LSI).
interpret_larson_skold ¶
Interpret a Larson-Skold index (corrosivity toward mild steel).
Source code in src/cooling_tower_chem/interpret.py
interpret_aggressiveness ¶
Interpret an AWWA Aggressiveness Index value.
Source code in src/cooling_tower_chem/interpret.py
WaterSample¶
cooling_tower_chem.sample ¶
A convenience WaterSample that computes every index from one input.
Example:
from cooling_tower_chem import WaterSample
s = WaterSample(ph=8.2, temperature_c=32, calcium_hardness=450,
total_alkalinity=250, conductivity_us_cm=2400,
chloride=180, sulfate=120)
s.lsi() # 1.38
s.report()["lsi"]["tendency"] # 'scale_forming'
WaterSample
dataclass
¶
A single water analysis, with lazy accessors for every index.
Required fields: ph, temperature_c, calcium_hardness and
total_alkalinity (hardness and alkalinity in mg/L as CaCO3).
tds may be given directly (mg/L) or derived from conductivity_us_cm.
chloride and sulfate (mg/L) are only needed for the Larson-Skold
index.
Source code in src/cooling_tower_chem/sample.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | |
from_us_units
classmethod
¶
from_us_units(ph: float, temperature_f: float, calcium_hardness_gpg: float, total_alkalinity_gpg: float, tds: float | None = None, conductivity_us_cm: float | None = None, chloride: float | None = None, sulfate: float | None = None, tds_factor: float = balance.DEFAULT_TDS_FACTOR) -> WaterSample
Build a :class:WaterSample from customary US units.
Many US practitioners report temperature in degrees Fahrenheit and
calcium hardness / total alkalinity in grains per US gallon (as CaCO3).
This constructor accepts those units and converts them to the SI
conventions the indices expect, via
:func:cooling_tower_chem.convert.fahrenheit_to_celsius and
:func:cooling_tower_chem.convert.grains_per_gallon_to_mg_l
(1 grain/gal = 17.118 mg/L as CaCO3). The signature is otherwise
parallel to :class:WaterSample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ph
|
float
|
Water pH (dimensionless), unchanged. |
required |
temperature_f
|
float
|
Water temperature in degrees Fahrenheit. |
required |
calcium_hardness_gpg
|
float
|
Calcium hardness in grains per US gallon as CaCO3. |
required |
total_alkalinity_gpg
|
float
|
Total alkalinity in grains per US gallon as CaCO3. |
required |
tds
|
float | None
|
Total dissolved solids in mg/L (its usual unit), or |
None
|
conductivity_us_cm
|
float | None
|
Conductivity in microsiemens/cm (its usual unit); used to derive
TDS when |
None
|
chloride
|
float | None
|
Concentrations in mg/L as the ion (their usual units), for the Larson-Skold index. |
None
|
sulfate
|
float | None
|
Concentrations in mg/L as the ion (their usual units), for the Larson-Skold index. |
None
|
tds_factor
|
float
|
TDS-from-conductivity factor (mg/L per uS/cm), same as
:class: |
DEFAULT_TDS_FACTOR
|
Returns:
| Type | Description |
|---|---|
WaterSample
|
An instance whose fields are all in SI units, so every index method behaves identically to one built with the primary constructor. |
Example
Source code in src/cooling_tower_chem/sample.py
effective_tds ¶
TDS in mg/L, using the measured value or deriving it from conductivity.
Source code in src/cooling_tower_chem/sample.py
stiff_davis_index ¶
Stiff-Davis Stability Index, with ionic strength estimated from TDS.
For high-salinity water only (see
:func:cooling_tower_chem.indices.stiff_davis_index). Not included in
:meth:report, which targets ordinary cooling-tower water.
Source code in src/cooling_tower_chem/sample.py
ccpp ¶
Calcium Carbonate Precipitation Potential, mg/L as CaCO3 (signed).
Positive means calcite tends to precipitate (scaling); negative means it
tends to dissolve (aggressive). By default the ionic strength is estimated
from TDS; pass ionic_strength (mol/L) to supply a measured or
model-derived value, which the result is sensitive to (see
:func:cooling_tower_chem.advanced.calcium_carbonate_precipitation_potential).
Not included in :meth:report.
Source code in src/cooling_tower_chem/sample.py
larson_skold_index ¶
Larson-Skold index, or None if chloride/sulfate were not provided.
Source code in src/cooling_tower_chem/sample.py
report ¶
Return every available index with its interpretation as a plain dict.
Keys are index names; each value has value, tendency and
description. Larson-Skold is included only when chloride and sulfate
are present. The result is JSON-serializable.
Source code in src/cooling_tower_chem/sample.py
CoolingTower¶
cooling_tower_chem.tower ¶
A :class:CoolingTower convenience object over the water-balance functions.
Give it a circulating flow, a cooling range, and a target cycles of concentration; read back the evaporation, drift, blowdown and makeup streams, and project how the recirculating water concentrates relative to the makeup.
CoolingTower
dataclass
¶
Steady-state water balance for an evaporative cooling tower.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
circulation_rate
|
float
|
Recirculating water flow in any consistent volumetric unit (e.g. m3/h). Every returned stream is in the same unit. |
required |
delta_t_c
|
float
|
Cooling range (temperature drop across the tower) in degrees C. |
required |
cycles
|
float | None
|
Target cycles of concentration. Required to compute blowdown/makeup. |
None
|
drift_fraction
|
float
|
Drift (windage) as a fraction of circulation. Default 0.0002 (0.02%). |
0.0002
|
latent_heat_kj_per_kg
|
float | None
|
Optional override for the latent heat used by the evaporation estimate. |
None
|
Source code in src/cooling_tower_chem/tower.py
water_balance ¶
All four streams (and cycles) as a JSON-serializable dict.
Source code in src/cooling_tower_chem/tower.py
concentrated ¶
Project recirculating-water chemistry from the makeup analysis.
Conservative species (hardness, alkalinity, TDS, chloride, sulfate, conductivity) concentrate by the cycles of concentration; pH and temperature are not scaled (they are governed by equilibria and the process, not by a mass balance) and are carried through unchanged. Use the result to estimate the LSI/RSI of the water actually in the basin.
Source code in src/cooling_tower_chem/tower.py
Unit conversions¶
cooling_tower_chem.convert ¶
Unit conversions for water-chemistry work.
Water-treatment data arrives in inconsistent units: an ion may be reported as
mg/L of the ion itself or "as CaCO3", hardness may be in grains per gallon, and
US sources use Fahrenheit. These helpers convert between the conventions the
indices in :mod:cooling_tower_chem.indices expect (mg/L as CaCO3, degrees C).
"As CaCO3" expresses a concentration in terms of an equivalent amount of calcium
carbonate: mg/L as CaCO3 = mg/L of ion x (50.04 / equivalent_weight_of_ion),
where 50.04 mg/meq is the equivalent weight of CaCO3.
as_caco3 ¶
Convert a concentration in mg/L of an ion to mg/L as CaCO3.
Pass the ion's equivalent weight (mg/meq); several are in
:data:EQUIVALENT_WEIGHTS.
Source code in src/cooling_tower_chem/convert.py
caco3_to_ion ¶
Inverse of :func:as_caco3: mg/L as CaCO3 back to mg/L of the ion.
Source code in src/cooling_tower_chem/convert.py
calcium_as_caco3 ¶
magnesium_as_caco3 ¶
bicarbonate_as_caco3 ¶
Convert mg/L of HCO3(-) alkalinity to mg/L as CaCO3 (x ~0.820).
mg_l_to_grains_per_gallon ¶
grains_per_gallon_to_mg_l ¶
Convert grains per US gallon to mg/L (as CaCO3).
celsius_to_fahrenheit ¶
Convert degrees Celsius to Fahrenheit.
Source code in src/cooling_tower_chem/convert.py
fahrenheit_to_celsius ¶
Convert degrees Fahrenheit to Celsius.