48 """Run the C++ solver with loop conversion ON and the network-loss channel
49 either OFF (baseline) or ON. Returns the accumulated results dict and the
50 final dynamic network density rho_net."""
51 _s = sys.stdout, sys.stderr
52 sys.stdout = sys.stderr = io.StringIO()
55 I=200, V=200, solver_mode=
"full_system",
56 physics_option=
"full_CD_fission", C_floor=1e-25,
57 he_kinetics=
"quasi_steady_state", i_mobile=5, v_mobile=2)
59 sim.input_data.reactions[
"T"] = 700.0 + 273.15
60 sim.input_data.reactions[
"E_a0_conv"] = 0.8
63 re = sim.input_data.reactions
64 re[
"LOOP_NETWORK_LOSS"] = 1
65 re[
"loop_net_chi"] = 1.0e6
66 re[
"loop_net_w_c"] = 1.0e-3
67 re[
"loop_net_K_rec"] = 1.0e-13
68 re[
"loop_net_n_inc"] = 4
69 sim.input_data._calculate_derived()
73 cfg = {
"t_span": (1e-6, 1e0),
"n_points": 40,
"log_time":
True,
74 "rtol": 1e-7,
"atol": 1e-28,
75 "solver_method": {
"linsol":
"dense"},
77 r = sim.run_adaptive(solver_config=cfg, save_output=
False,
79 lam_max = float(sim.reaction_rates.Lambda_net_111.max())
81 sys.stdout, sys.stderr = _s
86 """Sessile SIA-loop content Σ_{n>=n_inc} n (c_n^{111} + c_n^{100}) at the
87 final time — the population the network-loss channel targets."""
88 I = r[
"y"].shape[0]
if False else 200
89 sz = np.arange(1, I + 1, dtype=float)
91 S = float(np.dot(sz[mask], np.maximum(r[
"y"][:I, -1][mask], 0.0)))
93 S += float(np.dot(sz[mask], np.maximum(r[
"y_sia100"][:, -1][mask], 0.0)))
100 def check(name, cond, *info):
104 print(f
" {'PASS' if cond else 'FAIL'} {name} {info if info else ''}")
106 base, _ =
_run(network_loss=
False)
107 chan, lam_max =
_run(network_loss=
True)
109 tb = np.asarray(base[
"t"]); dfp_b = np.asarray(base[
"delta_FP"])
110 tc = np.asarray(chan[
"t"]); dfp_c = np.asarray(chan[
"delta_FP"])
113 max_off = float(np.max(dfp_b[late_b]))
114 max_on = float(np.max(dfp_c[late_c]))
117 check(
"Lambda_net kernel built non-zero", lam_max > 0.0, lam_max)
122 check(
"channel removes sessile SIA-loop inventory (S_on < S_off)",
123 S_on < S_off * (1.0 - 1e-3), (S_on, S_off, S_on / S_off))
130 check(
"channel does not degrade conservation (max dFP_on <= 1.5x dFP_off)",
131 max_on <= 1.5 * max_off + 1e-9, (max_on, max_off))
132 check(
"final dFP_on within 2x of dFP_off",
133 dfp_c[-1] <= 2.0 * dfp_b[-1] + 1e-9, (float(dfp_c[-1]), float(dfp_b[-1])))
135 print(f
"\n{'ALL PASS' if not fails else str(fails) + ' FAILED'}")
136 print(f
" [info] Lambda_max={lam_max:.2e} sessile S_I: on={S_on:.4e} off={S_off:.4e} "
137 f
"(ratio {S_on/S_off:.4f}) max dFP: on={max_on:.2e} off={max_off:.2e}")
138 return 1
if fails
else 0