Skip to main content
Glama
puran-water

Corrosion Engineering MCP Server

by puran-water
langelier_index.py6.3 kB
""" Tier 1 Tool: Calculate Langelier Saturation Index (LSI) Simplified wrapper for LSI-only calculation. LSI = pH - pH_s, where pH_s is the pH at calcite saturation. Interpretation: - LSI > 0: Scaling tendency (water can precipitate CaCO₃) - LSI = 0: Equilibrium (water is saturated) - LSI < 0: Corrosive tendency (water can dissolve CaCO₃) Common in cooling tower, boiler, and potable water treatment. Performance: ~1 second Accuracy: ±0.1 LSI units """ from typing import Dict, Optional import json import logging from core.chemistry_backend import PHREEQCBackend, validate_water_chemistry logger = logging.getLogger(__name__) def calculate_langelier_index( ions_json: str, temperature_C: float = 25.0, pH: Optional[float] = None, validate_charge_balance: bool = True, max_imbalance: float = 5.0, ) -> Dict: """ Calculate Langelier Saturation Index (LSI) for calcium carbonate scaling. The LSI is the most widely used index for predicting CaCO₃ scaling tendency in water systems. It is defined as: LSI = pH - pH_s where pH_s is the pH at which water is saturated with calcium carbonate. Args: ions_json: JSON string of ion concentrations in mg/L Must include at least: Ca2+, HCO3- (or CO3-2) Example: '{"Ca2+": 120, "HCO3-": 250, "Cl-": 150, "Na+": 100}' temperature_C: Water temperature in degrees Celsius (default 25.0) pH: Measured pH (if None, uses PHREEQC-calculated pH from charge balance) validate_charge_balance: Check charge balance before running (default True) max_imbalance: Maximum acceptable charge imbalance in % (default 5.0) Returns: Dictionary containing: - lsi: Langelier Saturation Index - pH: Measured or calculated pH - pH_saturation: pH at calcite saturation (pH_s) - si_calcite: Saturation index for calcite mineral - temperature_C: Temperature used in calculation - interpretation: Text summary - action_required: Recommended action based on LSI Example: >>> result = calculate_langelier_index( ... ions_json='{"Ca2+": 120, "HCO3-": 250, "Cl-": 150, "Na+": 100}', ... temperature_C=25.0, ... pH=7.8 ... ) >>> print(result["lsi"]) 0.35 >>> print(result["interpretation"]) "Mild scaling tendency" LSI Interpretation Guide: +2.0 to +3.0: Severe scaling (heavy precipitation) +0.5 to +2.0: Moderate scaling (scale formation likely) +0.0 to +0.5: Mild scaling (slight scale formation) -0.5 to +0.0: Near equilibrium (balanced) -2.0 to -0.5: Corrosive (dissolution of CaCO₃) < -2.0: Severely corrosive (aggressive water) Typical Applications: - Cooling tower water treatment - Boiler feedwater quality assessment - Potable water distribution (Pb/Cu corrosion control) - Reverse osmosis pretreatment - Heat exchanger fouling prediction Raises: ValueError: If charge imbalance exceeds max_imbalance or required ions missing RuntimeError: If PHREEQC calculation fails """ # Parse ion concentrations try: ions = json.loads(ions_json) except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON for ions: {e}") from e if not isinstance(ions, dict): raise ValueError("ions_json must be a JSON object (dictionary)") # Check for required ions if "Ca2+" not in ions and "Ca+2" not in ions: raise ValueError("LSI calculation requires calcium (Ca2+) concentration") if "HCO3-" not in ions and "CO3-2" not in ions: raise ValueError("LSI calculation requires bicarbonate (HCO3-) or carbonate (CO3-2)") # Validate charge balance if requested if validate_charge_balance: try: validate_water_chemistry(ions, max_imbalance=max_imbalance) except ValueError as e: logger.warning(f"Charge balance validation failed: {e}") # Run LSI calculation backend = PHREEQCBackend() lsi = backend.calculate_langelier_index( ions=ions, temperature_C=temperature_C, pH=pH, ) # Get speciation for additional context speciation = backend.run_speciation(ions, temperature_C, pH) si_calcite = speciation.saturation_indices.get("Calcite", 0.0) pH_s = speciation.pH - lsi # Format output output = { "lsi": round(lsi, 3), "pH": round(speciation.pH, 3), "pH_saturation": round(pH_s, 3), "si_calcite": round(si_calcite, 3), "temperature_C": temperature_C, } # Generate interpretation if lsi > 2.0: interpretation = "Severe scaling tendency" action = "Immediate action required: Add acid or increase blowdown. Heavy scale formation expected." elif lsi > 0.5: interpretation = "Moderate scaling tendency" action = "Action recommended: Consider scale inhibitor or pH adjustment. Scale formation likely." elif lsi > 0.0: interpretation = "Mild scaling tendency" action = "Monitor closely. Minor scale formation possible over time." elif lsi > -0.5: interpretation = "Near equilibrium (balanced)" action = "No action required. Water is well-balanced." elif lsi > -2.0: interpretation = "Corrosive tendency" action = "Consider corrosion inhibitor or pH adjustment. May dissolve existing scale." else: interpretation = "Severely corrosive" action = "Immediate action required: Increase pH or add corrosion inhibitor. Aggressive water." output["interpretation"] = interpretation output["action_required"] = action # Add specific notes for cooling towers vs potable water if temperature_C > 30.0: output["note"] = ( "Elevated temperature increases scaling tendency. " "Common in cooling towers - monitor heat exchanger surfaces." ) elif lsi < -1.0 and ("Pb" in ions or "Cu" in ions): output["note"] = ( "Corrosive water with lead/copper present. " "Consider pH adjustment to prevent leaching in distribution system." ) return output

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/puran-water/corrosion-engineering-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server