55 """Run the solver at temperature T_C to t_end_s; return modeled f₁₁₁."""
56 _s = sys.stdout, sys.stderr
57 sys.stdout = sys.stderr = io.StringIO()
60 I=I, V=I, solver_mode=
"full_system",
61 physics_option=
"full_CD_fission", C_floor=1e-25,
62 he_kinetics=
"quasi_steady_state", i_mobile=5, v_mobile=2)
64 inp.reactions[
"T"] = T_C + 273.15
65 for k, v
in (overrides
or {}).items():
67 inp._calculate_derived()
69 cfg = {
"t_span": (1e-6, t_end_s),
"n_points": 6,
"log_time":
True,
70 "rtol": 1e-6,
"atol": 1e-26,
71 "solver_method": {
"linsol":
"dense"},
"loop_conversion": 1}
72 r = sim.run_adaptive(solver_config=cfg, save_output=
False)
74 sys.stdout, sys.stderr = _s
75 y = r[
"y"]; y100 = r[
"y_sia100"]; sz = np.arange(1, I + 1)
76 S111 = float(np.dot(sz, np.maximum(y[:I, -1], 0.0)))
77 S100 = float(np.dot(sz, np.maximum(y100[:, -1], 0.0)))
78 return S111 / (S111 + S100)
if (S111 + S100) > 0
else 1.0
83 quick =
"--quick" in sys.argv
84 Tgrid = np.array([250, 300, 350, 400, 450]
if quick
85 else [250, 300, 330, 360, 400, 450, 500], dtype=float)
86 Tstar_candidates = [400.0]
if quick
else [300.0, 350.0, 400.0, 450.0, 500.0]
91 print(f
"Experimental EUROFER points: {len(Texp)} "
92 f
"(T {Texp.min():.0f}-{Texp.max():.0f} C)")
95 order = np.argsort(Texp)
96 fexp_on_grid = np.interp(Tgrid, Texp[order], fexp[order])
99 best = (
None, np.inf,
None)
100 for Tstar
in Tstar_candidates:
102 f111_model(T, t_end, overrides={
"T_star_conv_C": Tstar})
104 loss = float(np.mean((curve - fexp_on_grid) ** 2))
105 results[Tstar] = curve
106 print(f
" T*={Tstar:5.0f} C -> f111(T)="
107 f
"[{', '.join('%.2f' % c for c in curve)}] loss={loss:.4f}")
109 best = (Tstar, loss, curve)
111 print(f
"\nBEST T* = {best[0]:.0f} C (loss={best[1]:.4f})")
116 matplotlib.use(
"Agg")
117 import matplotlib.pyplot
as plt
118 fig, ax = plt.subplots(figsize=(8, 5))
119 ax.scatter(Texp, 100 * fexp, s=80, c=
"k", marker=
"o",
120 edgecolors=
"white", zorder=5, label=
"EUROFER-97 (exp.)")
121 for Tstar, curve
in results.items():
122 lw = 2.5
if Tstar == best[0]
else 1.2
123 ax.plot(Tgrid, 100 * curve,
"-o", lw=lw,
124 label=f
"model T*={Tstar:.0f} C"
125 + (
" (best)" if Tstar == best[0]
else ""))
126 ax.set_xlabel(
"Irradiation temperature (C)")
127 ax.set_ylabel(
"1/2<111> loop fraction (%)")
128 ax.set_title(f
"Loop-conversion calibration ({dose:.0f} dpa)")
129 ax.set_ylim(-5, 105); ax.grid(
True, ls=
":", alpha=0.4)
130 ax.legend(fontsize=9, frameon=
False)
131 out = ROOT /
"output" /
"loop_conversion_calibration.png"
132 out.parent.mkdir(parents=
True, exist_ok=
True)
133 fig.tight_layout(); fig.savefig(out, dpi=150)
134 print(f
"Saved plot: {out}")
135 except Exception
as e:
136 print(f
"(plot skipped: {e})")