From 4e990be568fdd3543e96fba11f9e82041f272ef9 Mon Sep 17 00:00:00 2001 From: Felipe Rocha Date: Wed, 1 Jul 2026 16:21:17 -0600 Subject: [PATCH] docs: align Week 9 CUI with Integrity Code Series canonical standard - Standardise the badge row to the 6-badge canonical order (CI, License MIT, Python 3.11+, Tests 154 passing, Code style ruff, DOI) with working hrefs - Correct the tests badge and Quickstart count to the real pytest total (154) - Add docs/equations.html: a MathJax reference rendering only the governing equations already present in the README/source, preserving [ASSUMED] tags - Link docs/equations.html from the Governing Equations section - Resolve the MIT-vs-"research/educational only" contradiction: keep MIT in License, move the usage restriction into a new Disclaimer section - Add Disclaimer (canonical text), Anti-Hallucination Note (T1/T2/T3 tiers) and rename Cybersecurity Summary to Cybersecurity (STRIDE) - Update the series cross-link table: bold Week 9, add Week 11, refresh slugs - Fix Repository Structure: list docs/ and the existing tests/test_extended.py --- README.md | 61 +++++++-- docs/equations.html | 306 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+), 13 deletions(-) create mode 100644 docs/equations.html diff --git a/README.md b/README.md index c385b31..a65a4bc 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # ICS2 Week 9 — CUI Coupled Thermohygro-Electrochemical Simulation -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20172508.svg)](https://doi.org/10.5281/zenodo.20172508) - [![CI](https://github.com/felipearocha/integrity-code-series-week9-cui/actions/workflows/ci.yml/badge.svg)](https://github.com/felipearocha/integrity-code-series-week9-cui/actions/workflows/ci.yml) -[![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/) -[![Tests](https://img.shields.io/badge/tests-151%20passing-brightgreen.svg)](#testing) -[![License](https://img.shields.io/badge/license-Research--Educational-lightgrey.svg)](LICENSE) +[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) +[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/) +[![Tests: 154 passing](https://img.shields.io/badge/tests-154%20passing-brightgreen.svg)](tests) +[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20172508.svg)](https://doi.org/10.5281/zenodo.20172508) Three-way coupled physics-first simulator for **Corrosion Under Insulation (CUI)** on insulated carbon-steel process piping. Simulates moisture ingress through a @@ -21,11 +21,12 @@ Part of an ongoing series of physics-first integrity simulators by Felipe Rocha: | # | Repo | Domain | |---|---|---| | Week 3 | [Integrity-code-series-3](https://github.com/felipearocha/Integrity-code-series-3) | F1 lap simulation (six coupled ODEs) | -| Week 6 | [Integrity-code-series-week6-smartphone-galvanic](https://github.com/felipearocha/Integrity-code-series-week6-smartphone-galvanic) | Smartphone galvanic corrosion (Laplace + Butler-Volmer) | +| Week 6 | [integrity-code-series-week6-smartphone-galvanic](https://github.com/felipearocha/Integrity-code-series-week6-smartphone-galvanic) | Smartphone galvanic corrosion (Laplace + Butler-Volmer) | | Week 7 | [integrity_code_series_week7_h2_lferw](https://github.com/felipearocha/integrity_code_series_week7_h2_lferw) | LF-ERW H2 conversion (B31.12 + NACE TM0316) | | Week 8 | [integrity-code-series-week8-creep-fatigue-heater](https://github.com/felipearocha/integrity-code-series-week8-creep-fatigue-heater) | Creep-fatigue 9Cr-1Mo (Norton/Omega + Coffin-Manson) | -| Week 9 | [integrity-code-series-week9-cui](https://github.com/felipearocha/integrity-code-series-week9-cui) | CUI thermohygro-electrochemical (3 PDEs, Strang) | +| **Week 9** | **[integrity-code-series-week9-cui](https://github.com/felipearocha/integrity-code-series-week9-cui)** | **CUI thermohygro-electrochemical (3 PDEs, Strang) — this repo** | | Week 10 | [integrity-code-series-week-10_nnph_scc](https://github.com/felipearocha/integrity-code-series-week-10_nnph_scc) | NNpHSCC full-physics (Chen-Sutherby-Xing + BS 7910) | +| Week 11 | [integrity-code-series-week11-erosion-corrosion-multiphase](https://github.com/felipearocha/integrity-code-series-week11-erosion-corrosion-multiphase) | Erosion-corrosion multiphase (NORSOK M-506 + DNV-RP-O501 + G119 + API 579) | | Bonus | [Vibration-Accelerated-Corrosion-Coupled-Mechano-Electrochemical-Simulation](https://github.com/felipearocha/Vibration-Accelerated-Corrosion-Coupled-Mechano-Electrochemical-Simulation) | Vibration-accelerated corrosion (SDOF + Butler-Volmer + Archard) | | Bonus | [synthetic-integrity-digital-twin-piml](https://github.com/felipearocha/synthetic-integrity-digital-twin-piml) | Physics-informed neural-network surrogate | | Bonus | [integrity-data-foundation](https://github.com/felipearocha/integrity-data-foundation) | Engineering data validation baseline | @@ -38,7 +39,7 @@ cd REPO python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt python run_all.py # ~70 s on a laptop; produces 7 figures + 1 GIF + audit_chain.json -pytest tests/ -v # 151 tests +pytest tests/ -v # 154 tests python validation/benchmarks.py # 5 analytical benchmarks ``` @@ -60,6 +61,8 @@ locations from outer cladding temperature measurements. ## Governing Equations +Full rendered (MathJax) reference: **[docs/equations.html](docs/equations.html)** — open in any browser. + ### Field 1 — Fourier Heat Conduction (Eq. 1) ``` @@ -167,6 +170,8 @@ integrity_code_series_week9_cui_thermohygro/ │ ├── surrogate_gbr.py GBR surrogate, parity metrics │ ├── fad_assessment.py API 579-1 Level 2 FAD │ └── audit_chain.py SHA-256 hash-linked run log +├── docs/ +│ └── equations.html Rendered (MathJax) governing-equations reference ├── validation/ │ └── benchmarks.py ├── visualization/ @@ -177,6 +182,7 @@ integrity_code_series_week9_cui_thermohygro/ ├── tests/ │ ├── test_geometry_thermal.py │ ├── test_moisture_electrochemistry.py +│ ├── test_extended.py │ └── test_remaining.py ├── assets/figures/ 8 static PNG panels (300 DPI) ├── assets/animations/ cui_moisture_front.gif @@ -214,7 +220,7 @@ integrity_code_series_week9_cui_thermohygro/ --- -## Cybersecurity Summary +## Cybersecurity (STRIDE) STRIDE threat model applied to DFOS sensor network feeding inverse solver: @@ -230,12 +236,41 @@ STRIDE threat model applied to DFOS sensor network feeding inverse solver: --- +## Anti-Hallucination Note + +Every physical parameter carries an explicit provenance tag. Constants read directly from +a standard or the literature are stated as such; parameters anchored to literature but not +calibrated to a specific site are flagged `[ASSUMED]` in `src/constants.py` and collected +in the **[ASSUMED] Parameter Flags** table above. In the Integrity Code Series tiering this +maps to: + +- **T1 [SOURCE]** — values fixed by physics or a cited standard (the API 579-1 Level 2 + Option B FAD curve, Faraday's law, the API RP 583 50-175 C CUI window). +- **T2 [SOURCE]** — quantities derived from T1 inputs (effective insulation properties, the + golden-section Tikhonov recovery restricted to `S ∈ [0, S_ref]`). +- **T3 [ASSUMED]** — practitioner / literature estimates that are not site-calibrated: the + mineral-wool moisture diffusivity `D_theta0` and slope `beta_theta`, the electrolyte + threshold `theta_crit`, the Fe-dissolution `i0_ref` / `E_a` / mixed overpotential, and the + `D_T` coupling form. + +No equation, constant, or citation in this repository or in `docs/equations.html` is +introduced beyond what the model actually implements. + +--- + +## Disclaimer + +Research tool only. Not for design, fitness-for-service, or safety-critical decisions without site-specific calibration and independent PE review. + +Additionally: API RP 583, API 579-1, and PHMSA regulations take precedence over model +output, and `[ASSUMED]` parameters must be validated against site-specific inspection data +before any operational use. + +--- + ## License -Research and educational use only. Not for operational fitness-for-service decisions -without independent engineering review and site-specific validation. -API RP 583, API 579-1, PHMSA regulations take precedence over model output. -[ASSUMED] parameters must be validated against site-specific inspection data. +MIT — Felipe Rocha. See [LICENSE](LICENSE). --- diff --git a/docs/equations.html b/docs/equations.html new file mode 100644 index 0000000..b463626 --- /dev/null +++ b/docs/equations.html @@ -0,0 +1,306 @@ + + + + + Integrity Code Series — Week 9 — Governing Equations + + + + + + + +
+

Integrity Code Series — Week 9

+

CUI Coupled Thermohygro-Electrochemical Simulation — Governing Equations Reference

+

Felipe Rocha

+
+ +
+ Contents +
    +
  1. Fourier Heat Conduction (Eq. 1)
  2. +
  3. Philip-de Vries Hygrothermal Transport (Eq. 2)
  4. +
  5. Butler-Volmer Electrochemical Kinetics (Eq. 3)
  6. +
  7. Wall Loss — Faraday's Law (Eq. 4)
  8. +
  9. Strang Operator Splitting (Eq. 5)
  10. +
  11. Tikhonov Inverse Problem (Eq. 6)
  12. +
  13. Monte Carlo / PoF (Eq. 9-10)
  14. +
  15. FAD — API 579-1 Level 2 Option B (Eq. 12-13)
  16. +
+
+ +
+Every equation below is transcribed from this repository's README. Constants tagged +[ASSUMED] are anchored to literature, not site-calibrated (see +src/constants.py and the [ASSUMED] Parameter Flags +table in the README). No equation, constant, or citation has been added beyond what the +repository already states. +
+ + +

1. Field 1 — Fourier Heat Conduction (Eq. 1)

+ +

1.1 Energy balance across the insulation annulus

+
+$$ +\rho_{\text{eff}}(\theta_w)\,c_{p,\text{eff}}(\theta_w)\,\frac{\partial T}{\partial t} +\;=\; \nabla\!\cdot\!\bigl(\lambda_{\text{eff}}(\theta_w)\,\nabla T\bigr) \;+\; Q_{\text{corr}} +$$ +

SOURCE: Fourier heat conduction; CUI critical window 50–175 °C per API RP 583 (process temperature 120 °C, see src/constants.py → T_PROCESS).

+

Code: src/thermal_field.py → build_thermal_system, thermal_step, lambda_eff, rho_cp_eff.

+
+ +

1.2 Boundary conditions

+
+$$ +T(r_i) = T_{\text{process}} \tag{1a} +$$ +$$ +-\lambda\,\frac{\partial T}{\partial r}\Big|_{\text{outer}} += h_{\text{conv}}\,(T - T_\infty) + \varepsilon\,\sigma\,(T^{4} - T_\infty^{4}) \tag{1b} +$$ +$$ +\frac{\partial T}{\partial z}\Big|_{\text{ends}} = 0 \tag{1c} +$$ +

(1a) inner-wall Dirichlet · (1b) Robin convective + radiative outer cladding · (1c) adiabatic axial ends. Cladding emissivity $\varepsilon$ [ASSUMED], $h_{\text{conv}}$ [ASSUMED].

+

Code: src/thermal_field.py → build_thermal_system.

+
+ + +

2. Field 2 — Philip-de Vries Hygrothermal Moisture Transport (Eq. 2)

+ +

2.1 Coupled moisture and thermal diffusion

+
+$$ +\frac{\partial \theta_w}{\partial t} +\;=\; \nabla\!\cdot\!\bigl(D_\theta(\theta_w)\,\nabla \theta_w\bigr) +\;+\; \nabla\!\cdot\!\bigl(D_T(\theta_w,T)\,\nabla T\bigr) +$$ +

SOURCE: Philip-de Vries hygrothermal moisture transport (name as used in the repository).

+

Code: src/moisture_field.py → moisture_step.

+
+ +

2.2 Constitutive coefficients and boundary conditions

+
+$$ +D_\theta(\theta_w) = D_{\theta 0}\,e^{\,\beta_\theta \theta_w} \tag{2a} +$$ +$$ +D_T(\theta_w, T) = D_{\text{vap,atm}}\,\xi(\theta_w)\,f(\theta_w, T) \tag{2b} +$$ +$$ +\theta_w\big|_{\text{holiday}} = f\,\Theta_{\text{SAT}} + (1-f)\,\Theta_{\text{INIT}}, +\qquad f = \min\!\left(\frac{S_{\text{mag}}}{S_{\text{ref}}},\, 1\right) \tag{2c} +$$ +$$ +J_w\!\cdot\! n\big|_{\text{intact}} = 0 \tag{2d} +$$ +$$ +\theta_w\big|_{t=0} = \Theta_{\text{INIT}} \quad \text{[ASSUMED]} \tag{2e} +$$ +
The partial-holiday BC (2c) models the cladding defect as a fraction $f$ of the outer circumference at saturation; $S_{\text{mag}} = S_{\text{ref}}$ (default $S_{\text{REF}} = 10^{-6}\ \text{m}^3/\text{m}^3/\text{s}$) is a fully wet holiday, $S_{\text{mag}} = 0$ is intact cladding. Above $S_{\text{ref}}$ the BC saturates and $S_{\text{mag}}$ is non-identifiable from $T_{\text{clad}}$ alone, so the inverse problem (Eq. 6) is restricted to $S \in [0, S_{\text{ref}}]$.
+

SOURCE: $D_{\theta 0}$, $\beta_\theta$, and the $D_T$ coupling form are [ASSUMED] (mineral-wool / simplified Philip-de Vries literature, see src/constants.py).

+

Code: src/moisture_field.py → D_theta, D_T_coeff, apply_holiday_bc.

+
+ + +

3. Field 3 — Butler-Volmer Electrochemical Kinetics (Eq. 3)

+ +
+$$ +i_{\text{corr}} = +\begin{cases} +i_0(T)\left[\,e^{\,\alpha_a F \eta /(RT)} - e^{-\alpha_c F \eta /(RT)}\,\right], & \theta_w > \theta_{\text{crit}} \\[4pt] +0, & \theta_w \le \theta_{\text{crit}} +\end{cases} +$$ +$$ +i_0(T) = i_{0,\text{ref}}\,\exp\!\left[-\frac{E_a}{R}\left(\frac{1}{T} - \frac{1}{T_{\text{ref}}}\right)\right] \tag{3a} +$$ +
Corrosion switches on only once the moisture volume fraction exceeds the electrolyte threshold $\theta_{\text{crit}} = 0.05$ ([ASSUMED], API RP 583 qualitative guidance). Transfer coefficients $\alpha_a, \alpha_c$, exchange current density $i_{0,\text{ref}}$, activation energy $E_a$, and mixed overpotential $\eta$ are all [ASSUMED].
+

SOURCE: Butler-Volmer kinetics with Arrhenius exchange-current density; constants [ASSUMED] per src/constants.py.

+

Code: src/electrochemistry.py → i_corr, i0.

+
+ + +

4. Wall Loss — Faraday's Law (Eq. 4)

+ +
+$$ +\frac{dWT}{dt} = -\frac{M_{\text{Fe}}}{n\,F\,\rho_{\text{steel}}}\; i_{\text{corr}}(T, \theta_w) +$$ +

SOURCE: Faraday's law of electrolysis; $M_{\text{Fe}}$, $n$, $F$, $\rho_{\text{steel}}$ from src/constants.py.

+

Code: src/electrochemistry.py → wall_loss_rate, faraday_step.

+
+ + +

5. Strang Operator Splitting (Eq. 5)

+ +
+$$ +u^{\,n+1} = L_{\text{EC}}\!\left(\tfrac{\Delta t}{2}\right) \circ +L_{\text{HY}}\!\left(\tfrac{\Delta t}{2}\right) \circ +L_{\text{TH}}(\Delta t) \circ +L_{\text{HY}}\!\left(\tfrac{\Delta t}{2}\right) \circ +L_{\text{EC}}\!\left(\tfrac{\Delta t}{2}\right)\, u^{\,n} +$$ +

Second-order symmetric splitting of the electrochemistry (EC), hygrothermal (HY), and thermal (TH) sub-operators.

+

SOURCE: Strang symmetric operator splitting.

+

Code: src/coupled_solver.py → run_coupled.

+
+ + +

6. Tikhonov Inverse Problem (Eq. 6)

+ +
+$$ +\min_{S}\; J(S) = \bigl(T_{\text{obs}} - T_{\text{model}}(S)\bigr)^{2} + \lambda_{\text{reg}}\,S^{2}, +\qquad S \in [0, S_{\text{ref}}] +$$ +
Single-parameter 1D inverse for $S_{\text{mag}}$, solved by golden-section line search on $J(S)$. Recovery error is <1% on the identifiable range $S \in [0, S_{\text{ref}}]$ for synthetic DFOS cases with 0.03 K measurement noise. Above $S_{\text{ref}}$ the model BC saturates and the inverse is non-injective by construction; a full adjoint formulation is out of scope.
+

SOURCE: Tikhonov-regularised least-squares inverse.

+

Code: src/inverse_problem.py → solve_inverse, misfit.

+
+ + +

7. Monte Carlo / Probability of Failure (Eq. 9-10)

+ +
+$$ +\xi = \{\, S_{\text{mag}},\, \theta_{\text{crit}},\, i_{0,\text{ref}},\, E_a,\, \lambda_{\text{eff}},\, L_{\text{defect}} \,\}, +\qquad N_{\text{MC}} = 10{,}000\ \text{(LHS)} +$$ +$$ +\mathrm{PoF}(t^{*}) = \frac{1}{N}\sum_{k=1}^{N} +\mathbf{1}\!\left[\, WT_k(t^{*}) > 0.20\, t_{\text{nom}} \,\right] +$$ +

Uncertainty propagation over the six-parameter vector $\xi$ by Latin-hypercube sampling; failure is wall loss exceeding 20% of nominal wall thickness.

+

SOURCE: Latin-hypercube Monte Carlo; failure fraction $0.20$ from src/constants.py → MAX_WL_FRAC.

+

Code: src/monte_carlo.py → run_monte_carlo, latin_hypercube_sample, spearman_sensitivity.

+
+ + +

8. Failure Assessment Diagram — API 579-1 Level 2 Option B (Eq. 12-13)

+ +
+$$ +f(L_r) = \left[\,1 + 0.5\,L_r^{2}\,\right]^{-1/2} +\left[\,0.3 + 0.7\,e^{-0.65\,L_r^{6}}\,\right] +$$ +$$ +L_{r,\max} = 0.5\left(1 + \frac{\text{UTS}}{\text{SMYS}}\right) +$$ +

Level 2 Option B FAD curve with cut-off $L_{r,\max}$; UTS and SMYS for X52 from src/constants.py ($K_{\text{mat}} = 70\ \text{MPa}\sqrt{\text{m}}$ [ASSUMED]).

+

SOURCE: API 579-1/ASME FFS-1 Level 2 Option B FAD.

+

Code: src/fad_assessment.py → fad_curve, Lr_max_value, assessment_point.

+
+ +
+Disclaimer: Research tool only. Not for design, fitness-for-service, or safety-critical decisions without site-specific calibration and independent PE review. Equations and constants are transcribed from this repository's README; parameters not calibrated to a specific site are marked [ASSUMED]. API RP 583, API 579-1, and PHMSA regulations take precedence over model output. Outputs are SHA-256 hash-chained; verify with the audit chain in src/audit_chain.py. +
+ + + + +