RadCluster
Graph-based cluster dynamics for irradiated materials
Loading...
Searching...
No Matches
test_solver.py
Go to the documentation of this file.
1"""Quick solver test — runs 2 short segments and prints CVODE diagnostics."""
2import sys, os, io
3from pathlib import Path
4
5MODULE_ROOT = Path(__file__).resolve().parent.parent.parent
6REPO_ROOT = MODULE_ROOT.parent
7sys.path.insert(0, str(REPO_ROOT))
8sys.path.insert(0, str(MODULE_ROOT))
9
10import importlib
11import radcluster_code.py_utils.defect_production as _dp
12import radcluster_code.py_utils.binding_energies as _be
13import radcluster_code.py_utils.bin_moment_rates as _bmr
14import radcluster_code.py_utils.input_data as _inp
15import radcluster_code.py_utils.reaction_rates as _rr
16import radcluster_code.py_utils.rate_equations as _re
17import radcluster_code.py_utils.cpp_bridge as _cb
18import radcluster_code.py_utils.post_process as _pp
19import radcluster_code.py_utils.simulation as _sim
20for _m in [_dp, _be, _bmr, _inp, _rr, _re, _cb, _pp, _sim]:
21 importlib.reload(_m)
22from radcluster_code.py_utils.simulation import RadClusterSimulation
23
24# ── Configuration (matches notebook) ──
25I, V = 100_000, 100_000
26i_mobile, v_mobile = 10, 5
27
28_saved = sys.stdout, sys.stderr
29sys.stdout = sys.stderr = io.StringIO()
30try:
31 sim = RadClusterSimulation(
32 I=I, V=V, solver_mode='full_system',
33 physics_option='bin_moment_CD_fission',
34 C_floor=1e-25, he_kinetics='quasi_steady_state',
35 i_mobile=i_mobile, v_mobile=v_mobile)
36finally:
37 sys.stdout, sys.stderr = _saved
38
39# ── Overrides ──
40OVERRIDES = {
41 'eta': 0.3, 'f_cl_i': 0.58, 'f_cl_v': 0.45,
42 'E_m_1D': 0.34, 'i_mobile': i_mobile, 'L_hat': 71.8,
43 'c_C': 1.94e-4, 'E_b_C_SIA': 0.45, 'rho_d': 1e14,
44 'Z_i': 1.1, 'Z_ii': 1.1, 'shape_function': 'lognormal',
45 'i_discrete': i_mobile, 'v_discrete': v_mobile,
46 'I_bin': 30, 'V_bin': 30,
47}
48sys.stdout = sys.stderr = io.StringIO()
49try:
50 inp = sim.input_data
51 for k, v in OVERRIDES.items():
52 placed = False
53 for d in [inp.production_fission, inp.production_fusion,
54 inp.diffusion, inp.reactions, inp.energetics, inp.dissociation]:
55 if k in d:
56 d[k] = v; placed = True
57 if not placed:
58 inp.reactions[k] = v
59 if 'i_mobile' in OVERRIDES:
60 inp.diffusion['i_mobile'] = int(OVERRIDES['i_mobile'])
61 inp.reactions['i_mobile'] = int(OVERRIDES['i_mobile'])
62 inp._calculate_derived()
63 sim.rebuild_rates()
64finally:
65 sys.stdout, sys.stderr = _saved
66
67# ── Run just 2 short segments ──
68SOLVER_CONFIG = {
69 't_span': (1e-6, 3.16), # segments 1-5 time range (up to original failure)
70 'n_points': 50,
71 'log_time': True,
72 'rtol': 1e-6, 'atol': 1e-25,
73 'solver_method': {
74 'linsol': 'gmres',
75 }
76}
77
78print(f'N_eq = {sim.rate_equations.N_eq}')
79print(f'Running t=[{SOLVER_CONFIG["t_span"][0]:.1e}, {SOLVER_CONFIG["t_span"][1]:.1e}]...')
80print('(CVODE diagnostics will appear on stderr)\n', flush=True)
81
82results = sim.run_adaptive(
83 solver_config=SOLVER_CONFIG,
84 save_output=False,
85 boundary_threshold=0.1,
86 max_doublings=0,
87 points_per_segment=10,
88)
89
90if results is not None:
91 print(f'\nDone: {len(results["t"])} time points')
92 print(f't = [{results["t"][0]:.2e}, {results["t"][-1]:.2e}]')
93 print(f'delta_FP = {results["delta_FP"][-1]:.3e}')
94else:
95 print('\nSimulation FAILED')