Skip to main content
Glama
puran-water

Corrosion Engineering MCP Server

by puran-water
ohio_u_datasets.py7.01 kB
""" Ohio University FREECORP validation dataset. Contains ~700 experimental data points for CO2/H2S corrosion used to develop and validate the FREECORP mechanistic model. Expected Accuracy: - CO2 corrosion: ±factor of 2 for 90% of cases - H2S corrosion: Higher uncertainty due to complex kinetics References: - Nesic et al. (2003-2009): Ohio University ICMT corrosion research - FREECORP software validation reports """ from typing import Dict, List, Any, Optional from dataclasses import dataclass import logging @dataclass class OhioUTestCase: """ Single Ohio U / FREECORP experimental data point. Attributes: case_id: Unique identifier experiment_type: Type (e.g., "rotating_cylinder", "flow_loop") inputs: Experimental conditions measured_rate_mm_per_y: Measured corrosion rate uncertainty_mm_per_y: Measurement uncertainty (if reported) reference: Publication or report reference """ case_id: str experiment_type: str inputs: Dict[str, Any] measured_rate_mm_per_y: float uncertainty_mm_per_y: Optional[float] reference: str class OhioUValidation: """ Ohio University FREECORP validation dataset manager. Provides access to experimental corrosion data from Ohio U's Institute for Corrosion and Multiphase Technology. """ def __init__(self): """Initialize Ohio U validation dataset""" self._logger = logging.getLogger(__name__) self._test_cases = self._load_test_cases() def _load_test_cases(self) -> List[OhioUTestCase]: """ Load Ohio U experimental data. TODO: Load actual FREECORP validation dataset when obtained. Placeholder cases based on published literature. """ placeholder_cases = [ OhioUTestCase( case_id="OHIO_CO2_001", experiment_type="rotating_cylinder", inputs={ "T_C": 25, "pCO2_bar": 0.53, "pH": 5.0, "rotation_rpm": 1000, }, measured_rate_mm_per_y=0.12, uncertainty_mm_per_y=0.02, reference="Nesic & Lee (2003) Corrosion Journal", ), OhioUTestCase( case_id="OHIO_CO2_002", experiment_type="flow_loop", inputs={ "T_C": 60, "pCO2_bar": 1.0, "pH": 6.2, "v_m_s": 2.5, }, measured_rate_mm_per_y=0.35, uncertainty_mm_per_y=0.05, reference="Nesic et al. (2006) NACE Corrosion", ), OhioUTestCase( case_id="OHIO_H2S_001", experiment_type="rotating_cylinder", inputs={ "T_C": 80, "pCO2_bar": 0.3, "pH2S_bar": 0.01, "pH": 5.5, "rotation_rpm": 500, }, measured_rate_mm_per_y=0.18, uncertainty_mm_per_y=0.04, reference="Sun & Nesic (2009) Corrosion Journal", ), ] return placeholder_cases def get_test_case(self, case_id: str) -> Optional[OhioUTestCase]: """Get specific test case by ID""" for case in self._test_cases: if case.case_id == case_id: return case return None def get_all_cases(self) -> List[OhioUTestCase]: """Get all test cases""" return self._test_cases def get_cases_by_type(self, experiment_type: str) -> List[OhioUTestCase]: """Filter cases by experiment type""" return [c for c in self._test_cases if c.experiment_type == experiment_type] def validate_model(self, model_function, tolerance_factor: float = 2.0) -> Dict[str, Any]: """ Validate a corrosion model against Ohio U experimental data. Args: model_function: Function that takes inputs dict and returns predicted rate tolerance_factor: Acceptable factor deviation (default: ±2x) Returns: Validation report dictionary """ results = [] for case in self._test_cases: try: predicted = model_function(case.inputs) # Calculate errors absolute_error = abs(predicted - case.measured_rate_mm_per_y) relative_error = absolute_error / case.measured_rate_mm_per_y factor_error = max(predicted, case.measured_rate_mm_per_y) / min(predicted, case.measured_rate_mm_per_y) # Check if within tolerance passed = factor_error <= tolerance_factor # Check if within measurement uncertainty (if available) within_uncertainty = False if case.uncertainty_mm_per_y: within_uncertainty = absolute_error <= case.uncertainty_mm_per_y results.append({ "case_id": case.case_id, "experiment_type": case.experiment_type, "measured": case.measured_rate_mm_per_y, "predicted": predicted, "absolute_error": absolute_error, "relative_error": relative_error, "factor_error": factor_error, "passed": passed, "within_uncertainty": within_uncertainty, }) except Exception as e: self._logger.error(f"Validation failed for {case.case_id}: {e}") results.append({ "case_id": case.case_id, "experiment_type": case.experiment_type, "measured": case.measured_rate_mm_per_y, "predicted": None, "error": str(e), "passed": False, }) # Statistics valid_results = [r for r in results if r.get("predicted") is not None] passed_count = sum(1 for r in valid_results if r.get("passed", False)) if valid_results: mare = sum(r["relative_error"] for r in valid_results) / len(valid_results) mean_factor_error = sum(r["factor_error"] for r in valid_results) / len(valid_results) else: mare = float('inf') mean_factor_error = float('inf') return { "dataset": "Ohio University FREECORP", "total_cases": len(results), "passed": passed_count, "failed": len(valid_results) - passed_count, "pass_rate": passed_count / len(valid_results) if valid_results else 0.0, "mean_absolute_relative_error": mare, "mean_factor_error": mean_factor_error, "tolerance_factor": tolerance_factor, "details": results, }

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