jitr quickstart example¶
We will
compile a solver for a particular reaction and kinematics
define a parametric potential and generate samples of the interaction parameters
propagate parameter samples through our compiled solver to generate predictive distributions of reaction observables
To illustrate, we will use the example of \(\alpha\) elastic scattering on \(^{48}\)Ca at 29 MeV, comparing to experimental data from EXFOR.
1import numpy as np
2from matplotlib import pyplot as plt
3from scipy import stats
4from tqdm import tqdm
5
6from jitr.optical_potentials.potential_forms import (
7 coulomb_charged_sphere as coulomb,
8)
9from jitr.optical_potentials.potential_forms import (
10 woods_saxon_safe as ws,
11)
12from jitr.reactions.reaction import Reaction
13from jitr.rmatrix import Solver as SolverKernel
14from jitr.utils import utils
15from jitr.xs import elastic
16
17# define reaction system
18alpha = (4, 2)
19Ca48 = (48, 20)
20reaction = Reaction(target=Ca48, projectile=alpha, process="El")
21
22# calculate kinematics for a given lab energy
23energy_lab = 28.2
24kinematics = reaction.kinematics(energy_lab)
25
26# set the channel radius, number of nodes, and number of partial waves
27interaction_range_fm = 1.2 * (48 ** (1 / 3) + 4 ** (1 / 3)) + 2
28channel_radius_dimensionless = utils.suggested_dimensionless_channel_radius(
29 interaction_range_fm, kinematics.k
30)
31channel_radius = channel_radius_dimensionless / kinematics.k
32N = utils.suggested_basis_size(channel_radius_dimensionless)
33lmax = 180
34
35# build a solver for the system and reaction of interest
36print(f"Compiling solver for {reaction} at {energy_lab} MeV")
37print(f" - channel radius {channel_radius:1.2f} fm")
38print(f" - {N} nodes")
39print(f" - {lmax} partial waves")
40
41solver = elastic.DifferentialWorkspace.build_from_system(
42 reaction=reaction,
43 kinematics=kinematics,
44 channel_radius_fm=channel_radius,
45 solver=SolverKernel(N),
46 lmax=lmax,
47 angles=np.linspace(0.1, np.pi, 180),
48)
49rgrid = solver.radial_grid()
50# jit warmup
51_ = solver.xs(central_potential=np.zeros_like(solver.radial_grid()))
52print("Done!")
Compiling solver for 48-Ca(alpha,el) at 28.2 MeV
- channel radius 11.19 fm
- 40 nodes
- 180 partial waves
Done!
1# define interaction
2def U_central(r, Vv, Wv, Rv, av):
3 fr = ws(r, Rv, av)
4 return -(Vv * fr + 1j * Wv * fr)
5
6
7def V_Coulomb(r, Zz, RC):
8 return coulomb(r, Zz, RC)
9
10
11# define parameter distribution and draw samples
12# just
13param_means = np.array([185, 20, 1.0, 0.6, 1.2])
14param_std_devs = np.array([6, 2, 0.05, 0.05, 0.01])
15num_samples = 1000
16param_draws = stats.multivariate_normal(
17 mean=param_means, cov=np.diag(param_std_devs) ** 2
18).rvs(num_samples)
19
20print(f"Running {num_samples} calculations...")
21prediction_samples = np.zeros((num_samples, solver.angles.size))
22for i in tqdm(range(param_draws.shape[0])):
23 Vv, Wv, rv, av, rC = param_draws[i]
24 A_factor = reaction.target.A ** (1 / 3) + reaction.projectile.A ** (1 / 3)
25 Zz = reaction.target.Z * reaction.projectile.Z
26 xs = solver.xs(
27 central_potential=U_central(
28 rgrid,
29 Vv,
30 Wv,
31 rv * A_factor,
32 av,
33 ),
34 coulomb_potential=V_Coulomb(rgrid, Zz, rC * A_factor),
35 )
36 prediction_samples[i, :] = xs.dsdo / solver.rutherford
37
38print("Done!")
Running 1000 calculations...
100%|██████████████████████████████████████████████████████████| 1000/1000 [00:05<00:00, 168.00it/s]
Done!
We will compare to some experimental data from EXFOR
1import pandas as pd
2
3df = pd.read_csv("./alpha_ca48_ratio_ruth.txt", names=["angle", "xs"], sep=r"\s+")
Plot predictive cross section distribution¶
1plt.figure()
2plt.scatter(df["angle"], df["xs"], color="k", marker=".")
3
4plt.fill_between(
5 np.rad2deg(solver.angles),
6 *np.percentile(prediction_samples, [16, 84], axis=0),
7 alpha=0.5,
8)
9plt.yscale("log")
10plt.xlabel(r"$\theta$ [deg]")
11plt.ylabel(r"$(\frac{d\sigma}{d\Omega}) / (\frac{d\sigma}{d\Omega})_{R}$")
12plt.title(f"${reaction.reaction_latex}$ at {kinematics.Elab:1.0f} MeV")
13plt.tight_layout()
14plt.show()
This looks like a reasonable prior! The next steps would be to use Bayesian calibration to determine a posterior…