Moved some diagnostic plots because they were out of range for the boleans to actually catch them, lifted the si time ditehring so that it gets applied everywhere for smootehr time plots. modified: eloss_calculations/Eloss.py introduced a external scaling factr to allow eloss calculations to be paired with the run scripts to figure out the right dEdx scaling modified: run_27Al.sh
103 lines
3.9 KiB
Python
103 lines
3.9 KiB
Python
import pycatima as catima
|
|
import numpy as np
|
|
import os
|
|
|
|
DEDX_SCALE = float(os.environ.get("DEDX_SCALE", "1.0"))
|
|
print(f"Using dEdX scale factor: {DEDX_SCALE}")
|
|
|
|
# --- 1. Constants ---
|
|
P_TORR = 250
|
|
TEMP_K = 293.15
|
|
R = 8.3144
|
|
MEV2U = 1.0 / 931.494
|
|
P_CO2 = 3
|
|
|
|
# Gas Density Calculations
|
|
p_pa = P_TORR * 133.322
|
|
molar_density = p_pa / (R * TEMP_K)
|
|
m_he, m_c, m_o= 4.0026, 12.0000, 15.9949
|
|
m_mix_avg = ((1 - P_CO2 / 100) * m_he) + (P_CO2 / 100 * (m_c + 2*m_o))
|
|
rho_g_cm3 = (molar_density * m_mix_avg) / 1e6
|
|
print(f"Gas density at {P_TORR} Torr: {rho_g_cm3:.6e} g/cm^3")
|
|
|
|
# --- 2. Material & Step Setup ---
|
|
material_def = [(m_he, 2, (1 - P_CO2 / 100)), (m_c, 6, P_CO2 / 100), (m_o, 8, 2*P_CO2 / 100)]
|
|
gas_mix = catima.Material(material_def)
|
|
gas_mix.density(rho_g_cm3)
|
|
|
|
# Thickness step settings
|
|
step_mg_cm2 = 0.001 # 1 ug/cm2 steps as per your example -- kept fine for
|
|
# numerical accuracy of the dedx integration itself.
|
|
step_g_cm2 = step_mg_cm2 / 1000.0
|
|
max_steps = 1000000000 # Adjust based on how far you want to track
|
|
|
|
coarse_step_cm = 0.2 # row spacing over most of the track
|
|
fine_step_cm = 0.03 # row spacing near the Bragg peak
|
|
fine_zone_frac = 0.085 # fraction of the *total* range treated as "near the peak"
|
|
|
|
def generate_lookup(z, mass_u, e_start_mev, label):
|
|
filename = f"/home/vsitaraman/ANASEN_analysis/eloss_calculations/{label}_lookup_{e_start_mev}MeV_{P_TORR}torr_{P_CO2}pc.dat"
|
|
header = f"Energy(MeV) \tmg/cm2 \tcm\nStarting Energy: {e_start_mev} MeV"
|
|
|
|
# Pass 1: integrate at full precision just to find the total range (needed
|
|
# to know where the "last fine_zone_frac" of the track begins).
|
|
projectile = catima.Projectile(mass_u, z)
|
|
e_u = e_start_mev / mass_u
|
|
total_thickness_g_cm2 = 0.0
|
|
while e_u >= 0.0001:
|
|
projectile.T(e_u)
|
|
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
|
|
e_u = (e_u * mass_u - loss_mev) / mass_u
|
|
total_thickness_g_cm2 += step_g_cm2
|
|
total_range_cm = total_thickness_g_cm2 / rho_g_cm3
|
|
fine_zone_start_cm = total_range_cm * (1.0 - fine_zone_frac)
|
|
|
|
projectile = catima.Projectile(mass_u, z)
|
|
current_e_total = e_start_mev
|
|
current_thickness_g_cm2 = 0.0
|
|
next_checkpoint_cm = 0.0
|
|
|
|
output = []
|
|
last_dist_cm = None
|
|
|
|
def append_row(e_total, thickness_g_cm2, dist_cm):
|
|
if last_dist_cm is not None and dist_cm <= last_dist_cm:
|
|
return False
|
|
output.append([e_total, thickness_g_cm2 * 1000.0, dist_cm])
|
|
return True
|
|
|
|
for i in range(max_steps):
|
|
dist_cm = current_thickness_g_cm2 / rho_g_cm3
|
|
if dist_cm >= next_checkpoint_cm:
|
|
if append_row(current_e_total, current_thickness_g_cm2, dist_cm):
|
|
last_dist_cm = dist_cm
|
|
step_cm = fine_step_cm if dist_cm >= fine_zone_start_cm else coarse_step_cm
|
|
next_checkpoint_cm = dist_cm + step_cm
|
|
|
|
e_u = current_e_total / mass_u
|
|
if e_u < 0.0001: # Stop at ATIMA limit
|
|
append_row(current_e_total, current_thickness_g_cm2, dist_cm)
|
|
break
|
|
|
|
projectile.T(e_u)
|
|
# dedx returns MeV / (g/cm2)
|
|
if(mass_u >=10.0):
|
|
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2 * DEDX_SCALE
|
|
else:
|
|
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
|
|
|
|
current_e_total = max(0.0, current_e_total - loss_mev)
|
|
current_thickness_g_cm2 += step_g_cm2
|
|
|
|
np.savetxt(filename, output, fmt='%.6f', delimiter='\t', header=header)
|
|
print(f"Lookup table created: {filename} ({len(output)} rows, "
|
|
f"range {total_range_cm:.2f} cm, fine zone below {fine_zone_start_cm:.2f} cm)")
|
|
|
|
# --- 3. Run ---
|
|
# Format: generate_lookup(Z, mass_u, E_start_MeV, label)
|
|
generate_lookup(1, 1.0078, 30, "proton")
|
|
generate_lookup(1, 2.01355, 30, "deutron")
|
|
generate_lookup(2, 4.0026, 50, "alpha")
|
|
generate_lookup(13,26.9815, 80, "aluminum")
|
|
generate_lookup(9,17.0021, 70, "fluorine")
|
|
generate_lookup(8,15.9949, 70, "oxygen") |