FISP: a 1D Fast Ion Spectra Propagator for solid cold targets.
Project description
FISP is a 1D simulation code for the interaction of ion beams with cold solid targets. It should be seen as a less precise but much faster alternative to Monte-Carlo simulations: both types of simulations can complement each other.
Peer-reviewed paper to be published.
Features
- Runs on a personnal computer with short running times (seconds to minutes depending on the simulation)
- User friendly: install as any other python package and easy to use
- Multi-layer targets of any solid cold materials of known composition
- Propagating single or multiple spectra of any ion
- Reactions between any two nuclei (user provides cross-section data)
- Front and rear exiting spectra calculation
- local Energy deposition calculation
- local Number of reactions calculation
User guide
Setting-up the simulation
In FISP, everything has to be manually declared. This includes atomic/ion species, materials, nuclear reactions and ion spectra.
Ion species
Any atomic/ion species involved in a FISP simulation (in the composition of a material layer or as the product of a nuclear reaction for example) must be declared before anything else. This is done using the Ion
class, for example let's declare an alpha particle (4He nucleus):
import fisp
Z = 2 # Atomic number
A = 4 # Mass number
mass = 3727.37941 # Ion mass energy in MeV
I = 41.8e-6 # Optionnal: mean excitation potential in MeV. Can be specified
# in the `Material` class instead. Less user-friendly.
ionization_energy = 0 # Optionnal: ionization energy in MeV. Useful for some simulations
# (see nuclear reactions part)
name = 'alpha' # Optionnal: chose a name for plots
propagate = True # Optionnal: tells FISP to propagate this type of ions. Setting
# this to False speeds up the calculation (especially with
# neutrons and thick targets), but obviously prevents FISP
# from calculating relating things such as energy deposition
# contribution from this ion type or output spectra for this
# ion type: any ion that is not propagated is forgotten as
# soon as it is created, only counting in the created ions numbers.
He4 = fisp.Ion(Z, A, mass, I=I, ionization_energy=ionization_energy, name=name, propagate=propagate)
Materials
Once your ions are declared, you can add them to a material type using the Material
class, for example with natural boron:
composition = {B10:.199, B11:.801} # 19.9% of boron 10 and 80.1% of boron 11, previously
# declared using the Ion class
density = 2370 # Density in kg/m^3
molar_mass = .0108135 # Molar mass in kg/mol
I = 76e-6 # Optionnal: mean excitation potential in MeV. Default
# is the average for the components of the materials.
name = 'boron' # Optionnal: chose a name for plots.
disable_warnings = True # Optionnal: FISP will warn the user if there seems to
# be a unit mistake on the values given for materials.
# If you know better, you can disable these warnings here.
boron = fisp.Material(composition, density, molar_mass, mean_excitation_potential=I, name=name, disable_warnings=disable_warnings)
Nuclear reactions
Binary nuclear reactions
Nuclear reactions that involve two nuclei turning into two other nuclei can be expressed as follows:
target (projectile, ejectile) product
They can be declared easily using the BinaryReaction
subclass of the main Reaction
class, that is introduced in the next paragraph.
target = B11 # Boron 11, previously declared using the Ion class
projectile = H1 # proton (hydrogen 1)
ejectile = n # neutron
product = C11 # carbon 11
data = mydata # cross-section data. Expected format is (xdata, ydata), with xdata
# being the projectile energies in the lab frame, and ydata being
# the corresponding cross-sections in m². Yes, square meters.
name = 'p+B11->n+C11' # Optionnal: chose a name for plots.
pb11_nC11 = fisp.BinaryReaction(B11, H1, n, C11, data)
Non binary nuclear reactions
Other reactions can be declared using the Reaction
class, which involves much more work from the user. For example with the reaction p + 11B -> 3a (here, skipping analytical calculations):
projectile = H1
target = B11
output_ions = [(He4, .5, func1), (He4, .5, func2), (He4, .5, func3), (He4, .5, func4), (He4, .5, func5), (He4, .5, func6)]
# Here: - He4 is the previously declared Ion object for alpha particles
# - .5 stands for the number of alpha particles with a given speed.
# Indeed, the reaction emits 3 alpha particles and each of these
# alpha particles has a probability of one half to go forward and
# one half to go backward*. At the macroscopic scale of our
# simulations, large numbers law applies: it can be considered that
# for each reaction, half a particle is emited in both direction.
# *simplification were done here, the point is to understand. This
# result is still correct though.
# - func1 to func6 are user-provided functions taking as input a numpy
# array containing the projectile (in our case, protons) energies.
# The function must then return the *speed* of the particles created.
# These speeds must be calculated in c units and in the lab frame,
# with positive values indicating forward direction and negative
# values indicating backward direction.
data = mydata # cross-section data. Expected format is (xdata, ydata), with xdata
# being the projectile energies in the lab frame, and ydata being
# the corresponding cross-sections in m². Yes, square meters.
name = 'p+B11->3a' # Optionnal: chose a name for plots.
pb11_3a = fisp.Reaction(projectile, target, output_ions, data, name=name)
Note: only reactions between two atoms/ions are supported.
Target layers
Now that materials and reactions have been declared, one can construct the target geometry using the Layer
class. Indeed, FISP supports multi-layer target, each layer being a different material.
material = boron # the Material object previously declared composing the layer
thickness = 100e-6 # the thickness of the layer in m
reactions = pb11_C11, pb11_3a # the previously declared nuclear reactions occuring within the layer
outer_step_size = 1e-8 # the step size of the code on the layer's borders in m
max_inner_step_size = 1e-6 # the maximum allowed step size of the code within the layer in m
step_factor = 1.01 # the ratio between the sizes of two consecutive steps. Indeed, as
# inner steps have less influence on the calculation's results, the
# code makes them larger to speed up the calculation.
fisp.Layer(material, thickness, reactions, outer_step_size, max, inner_step_size, step_factor)
One additionnal layer is added to the simulation each time the Layer
class is called. The order the the layers in the simulated target is the order in which the user declares the layers.
The reset the layers, see the reset
function below.
Ion beam
An ion beam (spectrum) can be added anywhere inside the target using the input_spectrum
function:
ions_type = H1 # Previously declared nature type of ions
position = 0. # Start position of the spectrum in m
direction = 'back' # Propagation direction of the spectrum ('front'/'back' is
# towards the front/back of the target)
energy_data = mydataE # the spectrum energy bins values in MeV
population_data = lydataP # corresponding ion populations in /MeV
fisp.input_spectrum(ions_type, position, direction, energy_data, population_data)
Additional parameters and functions
Set energy bins
The set_energy_bins
function can be used to tune the parameters of the simulation regarding the energy bins: the number of bins, their distribution and the resizing trigger.
import numpy as np
# These are the defaults values
number = 10000
distribution = np.linspace
resize_trigger = 100
fisp.set_energy_bins(number, distribution, resize_trigger)
Set simulation
The set_simulation
function tells FISP wether to calculate the location of energy deposit and stopped particles within the target.
# These are the default values
calculate_energy_deposit = True
calculate_particles_stopping = True
fisp.set_simulation(calculate_energy_deposit, calculate_particles_stopping)
If both calculations are turned off, the simulation speed is greatly increased in most cases.
Calling the run function
At this point, the simulation parameters and input are completely done. The run function should be called.
fisp.run()
Setting-up the post-processing
FISP embarks tools for prost-processing the simulations. They should be placed under the run
function in the user's python file.
For more information about a function listed here, please consult its docstring.
Plotting functions
FISP includes several plotting functions: plot_energy_deposition
, plot_nuclear_reactions
, plot_range
, plot_stopped_ions
, plot_stopping_power
, plot_target
.
The Spectrum
class has it own plotting method: plot
. The Reaction
class also has its own plotting method: plot_cross_section
.
Printing function
FISP includes one printing function: `print_created_ions'.
Data Saving
FISP includes functions to save data as csv files: save_energy_deposition
, save_created_ions
, save_nuclear_reactions
, save_range
, save_stopped_ions
, save_stopping_power
and the Spectrum
class method save
.
Data extraction
For more flexibility, it is possible to access data from FISP inside Python:
- Data:
range_tables
,reactions_list
,front_spectra
, 'rear_spectra` - Functions: 'extract_created_ions', 'extract_energy_deposition', 'extract_nuclear_reations', 'extract_stopped_ions'
Resetting
At the end of the Python file, the reset
function should be called. If not done, parametric studies or any following simulations in the same console will yield nonsensic results.
Parametric studies
The original purpose of FISP is to perform parametric studies. Thus, a function to run parametric studies is included. It works by running multiple Python interpeters at the same time with different parameters. Thus, the user needs to provide a functionning FISP namelist. In this namelist must be the flag $parametric$
for the value to replace, for example:
my_thickness = $parametric$
This flag will be replaced by a value of the parametric study for each simulation. To run a parametric study, user has to execute a separate python file:
import fisp
values = [1e-3, 2e-3, 3e-3] # Values of the parametric study that replace the $parametric$ flag
namelist = 'namelist_parallel.py' # Name of the namelist file to run (the one with the $parametric$ flag)
output = 'test' # Optionnal: output directory. Default is current working directory.
cpu = 1 # Optionnal: number of CPU cores to use. Note: as FISP is high-demanding
# on memory bandwidth, using a lot of core does not scale well.
ignore_overwrite = True # Tells wether to delete past simulations if they exist in the same directory.
fisp.prun(values, namelist, output_directory=output, workers=cpu, ignore_overwrite=ignore_overwrite)
Graphs will not be displayed and prints will not be printed during parametric studies: everything has to be saved from the namelist file.
Changelog
Version 0.3.0
Updated documentation (run
function and parametric studies).
Improvement of non-binary reactions automatic naming.
New feature: propagate
parameter allows the user to select which ions the code should propagate, allowing for more optimization of each simulation and for future features.
Version 0.2.0
Added documentation.
Changed default nuclear reactions names.
Not necessary anymore to save the output from fisp.run
and search though it to find exiting spectra: just read from fisp.front_spectra
and fisp.rear_spectra
.
Spectrum
class method save_csv
method is now named save
.
Version 0.1.1
Overwriting files at the end of simulations now works.
Version 0.1
Initial release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.