-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_all.py
More file actions
144 lines (119 loc) · 4.41 KB
/
Copy pathrun_all.py
File metadata and controls
144 lines (119 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
"""
Week 9 — Full execution script. Run from repo root.
Usage: python run_all.py
"""
import os
import sys
import time
import numpy as np
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
os.makedirs("assets/figures", exist_ok=True)
os.makedirs("assets/animations", exist_ok=True)
print("=" * 70)
print("INTEGRITY CODE SERIES — Week 9")
print("CUI Thermohygro-Electrochemical Simulation with DFOS Inverse")
print("=" * 70)
# [1] Baseline
print("\n[1/9] Deterministic baseline...")
t0 = time.time()
from src.coupled_solver import run_baseline
result = run_baseline(dt_days=30, n_years=10)
ins_sl = result["mesh"]["ins_slice"]
print(f" wl(t=0)={result['wl'][0]:.4f} mm wl(t=10yr)={result['wl'][-1]:.4f} mm")
print(
f" T_outer={result['T'][-1, -1] - 273.15:.1f} C theta_inner_final={result['theta'][-1, ins_sl.start]:.3f}"
)
print(f" Monotone: {np.all(np.diff(result['wl']) >= -1e-10)}")
# [2] Benchmarks
print("\n[2/9] Validation benchmarks...")
import validation.benchmarks as bm
bm.benchmark_steady_state_T()
bm.benchmark_faraday_mass_balance()
bm.benchmark_butler_volmer_tafel()
bm.benchmark_i0_arrhenius()
bm.benchmark_moisture_diffusion_scaling()
# [3] Monte Carlo
print("\n[3/9] Monte Carlo N=10,000...")
from src.monte_carlo import run_monte_carlo, spearman_sensitivity
mc = run_monte_carlo(n_samples=10_000, n_t=20, seed=42)
p50 = float(np.percentile(mc["wall_loss"], 50))
p95 = float(np.percentile(mc["wall_loss"], 95))
print(f" PoF={mc['pof_final']:.4f} P50={p50:.4f}mm P95={p95:.4f}mm")
print(f" Perforations: {mc['censored'].sum()}")
# [4] Surrogate
print("\n[4/9] GBR surrogate...")
from src.surrogate_gbr import train_surrogate
surr = train_surrogate(mc["params"], mc["wall_loss"])
print(
f" R2_train={surr['r2_train']:.4f} R2_test={surr['r2_test']:.4f} MAE={surr['mae_test']:.4f}mm"
)
# [5] Sensitivity
print("\n[5/9] Spearman sensitivity...")
rho = spearman_sensitivity(mc)
for k, v in rho.items():
print(f" {k:15s}: {v:+.4f}")
# [6] Inverse problem (3 synthetic test cases)
# Search range capped at S_ref=1e-6: above that the partial-holiday BC
# saturates at THETA_SAT, so S is non-identifiable in the plateau region.
print("\n[6/9] DFOS inverse reconstruction...")
from src.geometry import build_mesh
from src.inverse_problem import solve_inverse, synthetic_dfos_observation
mesh_inv = build_mesh(n_r_steel=3, n_r_ins=6, n_r_clad=2)
dt_inv = 60 * 86400
n_inv = 4
inv_results = []
for S_true, seed in [(2e-7, 1), (5e-7, 2), (8e-7, 3)]:
T_obs = synthetic_dfos_observation(mesh_inv, dt_inv, n_inv, S_true, noise_K=0.03, seed=seed)
inv = solve_inverse(T_obs, mesh_inv, dt_inv, n_inv, S_lo=0, S_hi=1e-6, max_iter=30)
inv["S_true"] = S_true
err_pct = abs(inv["S_opt"] - S_true) / S_true * 100 if S_true > 0 else 0
print(f" S_true={S_true:.1e} S_opt={inv['S_opt']:.1e} err={err_pct:.1f}%")
inv_results.append(inv)
# [7] FAD
print("\n[7/9] FAD assessment...")
from src.constants import P_OP_BAR
from src.fad_assessment import fad_trajectory
traj = fad_trajectory(P_OP_BAR, result["wl"])
n_unacceptable = (traj["status"] == "unacceptable").sum()
print(
f" Unacceptable points: {n_unacceptable}/{len(traj['status'])} (all acceptable for 10yr baseline)"
)
# [8] Plots
print("\n[8/9] Generating plots...")
from visualization.plot_fields import plot_field_heatmaps
plot_field_heatmaps(result)
from visualization.plot_mc_dist import plot_mc_distribution
plot_mc_distribution(mc)
from visualization.plot_analysis import (
plot_fad,
plot_inverse,
plot_iso_risk,
plot_sensitivity,
plot_surrogate,
)
plot_sensitivity(rho)
plot_surrogate(surr)
plot_iso_risk(mc)
plot_fad(result)
plot_inverse(inv_results)
# [9] GIF + audit
print("\n[9/9] GIF + audit chain...")
from visualization.generate_gif import generate_gif
generate_gif(result)
from src.audit_chain import get_chain, log_run
log_run(
"baseline_week9",
{"dt_days": 30, "n_years": 10},
{"wl_10yr": float(result["wl"][-1]), "T_outer": float(result["T"][-1, -1])},
)
log_run("mc_10k", {"n_samples": mc["n_samples"]}, {"pof": mc["pof_final"], "p50": p50, "p95": p95})
chain = get_chain()
print(f" Chain valid: {chain.verify_chain()}, entries: {len(chain)}")
with open("assets/audit_chain.json", "w") as f:
f.write(chain.to_json())
print(f"\n{'=' * 70}")
print(f"Complete in {time.time() - t0:.0f}s")
print(
f"Figures: {len(os.listdir('assets/figures'))} | Animations: {len(os.listdir('assets/animations'))}"
)
print(f"{'=' * 70}")