73 xmax_history=None, y_sia100=None):
75 Compute macroscopic quantities from ODE solution.
80 y : ndarray [N_eq, n_t]
81 input_data : InputData
82 rate_eq_obj : RateEquations or BinMomentRateEquations
83 xmax_history: ignored (kept for API compatibility)
89 d = input_data.derived
91 inv_Omega = 1.0 / Omega
92 r0 = (3.0 * Omega / (4.0 * np.pi)) ** (1.0 / 3.0)
100 ns = np.arange(1, I + 1, dtype=float)
101 ms = np.arange(1, V + 1, dtype=float)
104 he_mode = getattr(rate_eq_obj,
'he_mode',
'case2')
105 is_bin = hasattr(rate_eq_obj,
'bins')
106 qss_He = getattr(rate_eq_obj,
'qss_He',
False)
107 C_floor = float(input_data.reactions.get(
'C_floor', 1e-15))
109 i_SIA = getattr(rate_eq_obj,
'i_SIA', 0)
110 i_VAC = getattr(rate_eq_obj,
'i_VAC', I)
111 i_He = getattr(rate_eq_obj,
'i_He',
None)
112 if i_He
is None and not qss_He:
113 i_He = y.shape[0] - 1
116 I_bin = getattr(rate_eq_obj,
'I_bin', getattr(rate_eq_obj,
'K', 0))
118 V_bin = getattr(rate_eq_obj,
'V_bin', getattr(rate_eq_obj,
'K_v', 0))
121 C_SIA_tot = np.zeros(n_t)
122 C_VAC_tot = np.zeros(n_t)
123 C_He_tot = np.zeros(n_t)
124 mean_n_i = np.zeros(n_t)
125 mean_n_v = np.zeros(n_t)
126 swelling = np.zeros(n_t)
127 N_loops = np.zeros(n_t)
128 N_voids = np.zeros(n_t)
131 C_He_free = np.zeros(n_t)
133 delta_FP = np.zeros(n_t)
134 delta_FP_sia = np.zeros(n_t)
135 delta_FP_vac = np.zeros(n_t)
136 delta_He = np.zeros(n_t)
141 rr = getattr(rate_eq_obj,
'rr',
None)
142 v_mobile = d.get(
'v_mobile', d.get(
'm_max_v', 1))
146 cascade = getattr(input_data,
'cascade',
None)
148 from .input_data
import split_physics_option
149 cascade = split_physics_option(input_data.physics_option)[1]
150 eta = input_data.production_fission.get(
'eta', 0.30) \
151 if cascade ==
'fission' \
152 else input_data.production_fusion.get(
'eta', 0.28)
155 vac_mid = getattr(rate_eq_obj,
'vac_mid',
None)
158 yj = np.maximum(y[:, j], 0.0)
161 from .bin_moment_rates
import reconstruct_distribution
162 i_d = getattr(rate_eq_obj,
'i_discrete', 0)
163 v_d = getattr(rate_eq_obj,
'v_discrete', 0)
164 P = getattr(rate_eq_obj,
'n_mom', 2)
165 sf = getattr(rate_eq_obj,
'shape_function',
'linear')
169 ns_disc = np.arange(1, i_d + 1, dtype=float)
170 SIA_content_from_mu1 = np.dot(ns_disc, yj[:i_d])
173 mom = yj[i_d:i_d + P * I_bin]
174 mu0_j = mom[0::P][:I_bin]
176 mu1_j = mom[1::P][:I_bin]
177 SIA_content_from_mu1 += np.sum(mu1_j)
181 for kb, (nlo, nhi)
in enumerate(rate_eq_obj.bins):
182 SIA_content_from_mu1 += mu0_j[kb] * (nlo + nhi - 1) / 2.0
183 mu2_j = mom[2::P][:I_bin]
if P >= 3
else None
185 c_n = reconstruct_distribution(sf, mu0_j, mu1_j, mu2_j,
193 ms_disc = np.arange(1, v_d + 1, dtype=float)
195 c_v[:v_d] = yj[i_VAC:i_VAC + v_d]
196 VAC_content_from_mu1 = np.dot(ms_disc, c_v[:v_d])
198 vac_start = i_VAC + v_d
199 vmom = yj[vac_start:vac_start + P * V_bin]
200 vmu0 = vmom[0::P][:V_bin]
202 vmu1 = vmom[1::P][:V_bin]
203 VAC_content_from_mu1 += np.sum(vmu1)
206 for kb, (mlo, mhi)
in enumerate(rate_eq_obj.vac_bins):
207 VAC_content_from_mu1 += vmu0[kb] * (mlo + mhi - 1) / 2.0
208 vmu2 = vmom[2::P][:V_bin]
if P >= 3
else None
209 c_v_binned = reconstruct_distribution(sf, vmu0, vmu1, vmu2,
210 rate_eq_obj.vac_bins, V)
211 c_v[v_d:] = c_v_binned[v_d:]
213 c_n = yj[i_SIA:i_VAC]
214 c_v = yj[i_VAC:i_VAC + V]
215 SIA_content_from_mu1 =
None
216 VAC_content_from_mu1 =
None
219 if he_mode ==
'case1':
220 i_Q = getattr(rate_eq_obj,
'i_Q', i_VAC + V)
221 n_Q = V_bin
if V_bin > 0
else V
222 Q_m = yj[i_Q:i_Q + n_Q]
225 i_Qtot = getattr(rate_eq_obj,
'i_Qtot', i_VAC + V)
231 c_h = rate_eq_obj.compute_c_h_qss(c_v, Q_tot=Q_tot, Q_m=Q_m)
237 C_SIA_tot[j] = SIA_content_from_mu1
if SIA_content_from_mu1
is not None \
240 C_VAC_tot[j] = VAC_content_from_mu1
if VAC_content_from_mu1
is not None \
242 C_He_tot[j] = c_h + Q_tot
252 disc_i_eff = np.maximum(yj[1:i_d] - C_floor, 0.0)
253 count_i = float(np.sum(disc_i_eff))
254 content_i = float(np.dot(ns_disc[1:], disc_i_eff))
256 for kb, (nlo, nhi)
in enumerate(rate_eq_obj.bins):
258 mu0_j[kb], mu1_j[kb]
if P >= 2
else 0.0,
259 nlo, nhi, C_floor, P)
260 count_i += float(mu0_eff)
261 content_i += float(mu1_eff)
263 mean_n_i[j] = content_i / count_i
if count_i > 0.0
else 0.0
266 disc_v_eff = np.maximum(yj[i_VAC + 1:i_VAC + v_d] - C_floor, 0.0)
267 count_v = float(np.sum(disc_v_eff))
268 content_v = float(np.dot(ms_disc[1:], disc_v_eff))
270 for kb, (mlo, mhi)
in enumerate(rate_eq_obj.vac_bins):
272 vmu0[kb], vmu1[kb]
if P >= 2
else 0.0,
273 mlo, mhi, C_floor, P)
274 count_v += float(mu0_eff)
275 content_v += float(mu1_eff)
277 mean_n_v[j] = content_v / count_v
if count_v > 0.0
else 0.0
279 c_n_eff = np.maximum(c_n[1:] - C_floor, 0.0)
280 sum_cni_eff = np.sum(c_n_eff)
281 mean_n_i[j] = (np.dot(ns[1:], c_n_eff) / sum_cni_eff) \
282 if sum_cni_eff > 0.0
else 0.0
283 c_v_eff = np.maximum(c_v[1:] - C_floor, 0.0)
284 sum_cvi_eff = np.sum(c_v_eff)
285 mean_n_v[j] = (np.dot(ms[1:], c_v_eff) / sum_cvi_eff) \
286 if sum_cvi_eff > 0.0
else 0.0
287 N_loops[j] = np.sum(c_n[1:])
288 N_voids[j] = np.sum(c_v[1:])
293 swelling[j] = C_VAC_tot[j]
310 N_loops_111 = N_loops.copy()
311 N_loops_100 = np.zeros(n_t)
312 mean_n_111 = mean_n_i.copy()
313 mean_n_100 = np.zeros(n_t)
314 f_111_loop = np.ones(n_t)
315 if y_sia100
is not None and np.asarray(y_sia100).size:
322 cont111 = C_SIA_tot.copy()
324 y100 = np.maximum(np.asarray(y_sia100, dtype=float), 0.0)
337 i_d = getattr(rate_eq_obj,
'i_discrete', 0)
338 P = getattr(rate_eq_obj,
'n_mom', 2)
339 bins_ = getattr(rate_eq_obj,
'bins', [])
340 ns_disc = np.arange(1, i_d + 1, dtype=float)
341 disc100 = np.maximum(y100[1:i_d, :] - C_floor, 0.0)
342 N_loops_100 = np.sum(disc100, axis=0)
343 cont100 = ns_disc[1:] @ disc100
344 mom100 = y100[i_d:i_d + P * len(bins_), :]
345 mu0_100 = mom100[0::P, :]
346 mu1_100 = mom100[1::P, :]
if P >= 2
else None
347 for kb, (nlo, nhi)
in enumerate(bins_):
349 mu0_100[kb, :], mu1_100[kb, :]
if P >= 2
else 0.0,
350 nlo, nhi, C_floor, P)
351 N_loops_100 = N_loops_100 + mu0_eff
352 cont100 = cont100 + mu1_eff
354 c100 = np.maximum(y100 - C_floor, 0.0)
356 N_loops_100 = np.sum(c100[1:, :], axis=0)
357 C_SIA_tot = C_SIA_tot + cont100
359 mean_n_100 = np.divide(cont100, cnt100,
360 out=np.zeros(n_t), where=cnt100 > 0)
361 tot = cont111 + cont100
362 f_111_loop = np.divide(cont111, tot,
363 out=np.ones(n_t), where=tot > 0)
364 cnt_tot = cnt111 + cnt100
365 mean_n_i = np.divide(cont111 + cont100, cnt_tot,
366 out=mean_n_i.copy(), where=cnt_tot > 0)
367 N_loops = N_loops_111 + N_loops_100
377 rho_net_val = float(getattr(rr,
'rho_net',
378 input_data.reactions.get(
'rho_net',
379 input_data.reactions.get(
'rho_d', 1.0e14))))
380 rho_net = np.full(n_t, rho_net_val)
393 i_J_SIA_fixed = getattr(rate_eq_obj,
'i_J_SIA_fixed', N_eq - 5)
394 i_J_SIA_mutual = getattr(rate_eq_obj,
'i_J_SIA_mutual', N_eq - 4)
395 i_J_VAC_fixed = getattr(rate_eq_obj,
'i_J_VAC_fixed', N_eq - 3)
396 i_J_VAC_mutual = getattr(rate_eq_obj,
'i_J_VAC_mutual', N_eq - 2)
397 i_J_He_sink = getattr(rate_eq_obj,
'i_J_He_sink', N_eq - 1)
398 J_SIA_fixed = np.maximum(y[i_J_SIA_fixed, :], 0.0)
399 J_SIA_mutual = np.maximum(y[i_J_SIA_mutual, :], 0.0)
400 J_VAC_fixed = np.maximum(y[i_J_VAC_fixed, :], 0.0)
401 J_VAC_mutual = np.maximum(y[i_J_VAC_mutual, :], 0.0)
402 J_He_sink = np.maximum(y[i_J_He_sink, :], 0.0)
414 num = abs(C_VAC_tot[j] - C_SIA_tot[j]
415 - J_SIA_fixed[j] + J_VAC_fixed[j])
416 den = (C_VAC_tot[j] + C_SIA_tot[j]
417 + J_SIA_fixed[j] + J_VAC_fixed[j])
418 delta_FP[j] = num / den
if den > 1e-300
else 0.0
423 prod = eta * G * (t[j] - t[0])
425 sia0 = C_SIA_tot[0] + J_SIA_fixed[0] + J_SIA_mutual[0]
426 vac0 = C_VAC_tot[0] + J_VAC_fixed[0] + J_VAC_mutual[0]
427 delta_FP_sia[j] = abs(
428 prod - (C_SIA_tot[j] + J_SIA_fixed[j] + J_SIA_mutual[j] - sia0)) / prod
429 delta_FP_vac[j] = abs(
430 prod - (C_VAC_tot[j] + J_VAC_fixed[j] + J_VAC_mutual[j] - vac0)) / prod
432 delta_FP_sia[j] = delta_FP_vac[j] = 0.0
455 He_bal = (C_He_tot - C_He_free)
if qss_He
else C_He_tot
456 S_He0 = He_bal[0] + J_He_sink[0]
458 he_prod = G_He * (t[j] - t[0])
459 num = abs(He_bal[j] + J_He_sink[j] - he_prod - S_He0)
460 den = He_bal[j] + J_He_sink[j] + he_prod
461 delta_He[j] = num / den
if den > 1e-300
else 0.0
466 C_SIA_tot *= inv_Omega
467 C_VAC_tot *= inv_Omega
468 C_He_tot *= inv_Omega
469 C_He_free *= inv_Omega
471 N_loops_111 *= inv_Omega
472 N_loops_100 *= inv_Omega
483 conc_names = ([f
'Ci_{n}' for n
in range(1, I + 1)] +
484 [f
'Cv_{m}' for m
in range(1, V + 1)] + [
'C_He'])
492 'C_SIA_tot': C_SIA_tot,
493 'C_VAC_tot': C_VAC_tot,
494 'C_He_tot': C_He_tot,
495 'C_He_free': C_He_free,
496 'mean_n_i': mean_n_i,
497 'mean_n_v': mean_n_v,
499 'N_loops_111': N_loops_111,
500 'N_loops_100': N_loops_100,
501 'mean_n_111': mean_n_111,
502 'mean_n_100': mean_n_100,
503 'f_111_loop': f_111_loop,
505 'swelling': swelling,
508 'delta_FP': delta_FP,
509 'delta_FP_sia': delta_FP_sia,
510 'delta_FP_vac': delta_FP_vac,
511 'delta_He': delta_He,
512 'J_SIA_fixed': J_SIA_fixed,
513 'J_SIA_mutual': J_SIA_mutual,
514 'J_VAC_fixed': J_VAC_fixed,
515 'J_VAC_mutual': J_VAC_mutual,
516 'J_He_sink': J_He_sink,
518 'conc_names': conc_names,
521 '_y_i_He': i_VAC + (getattr(rate_eq_obj,
'v_discrete', 0)
522 + getattr(rate_eq_obj,
'n_mom', 2)
523 * getattr(rate_eq_obj,
'V_bin',
524 getattr(rate_eq_obj,
'K_v', 0))