It requires Python and git.
Tested on Python 3.10-3.12.
# (Optional) Create and activate a virtual environment:
python -m venv .venv
# Windows (PowerShell):
. .\.venv\Scripts\Activate.ps1
# macOS/Linux:
# source .venv/bin/activate
After cloning the repository:
cd <project-directory>
# Install the package and runtime dependencies:
pip install .
# Or install the editable version (this is also optional):
# pip install -e .[dev]
If not installed dev dependencies yet:
pip install -e .[dev]
# or: pip install -r requirements.txt
# Run all tests
pytest
# Example for running only one test file
pytest tests/test_cli.py
# Example for running a single test function
pytest tests/test_cli.py::test_absorption_only_json_output
Coverage is configured in pytest.ini
, for this reason the command pytest
is enough to also get the coverage report.
After installing the package (with pip install .
), the user can use two console scripts. To see their help:
mctransport -h
;mctransport-graph -h
.
Or via Python:python -m mctransport.cli -h
;python -m mctransport.graph_cli -h
.
This project aims to model transport in a homogeneous isotropic medium.
For now the only physical phenomenon taken into consideration is the pure absorption one without any scattering and sources. In the future these things could be implemented in the program.
A particle (photon, neutron, etc...) travels a random straight free path L
, if d
represents the slab thickness, the particle is transmitted, otherwise it is absorbed.
In a homogeneous isotropic absorbing medium, the transmission probability, that is the probability that a particle travels a distance d without interacting, is defined as:
where d
, as said before, is the distance/thickness of the medium to cross, and λ
is the mean free path (called lam
in the code).
d
and λ
must have the same units.
This expression is also known considering the attenuation coefficient
In the limit cases for T
we have:
The mean free path λ
represents the average distance a particle travels before being absorbed.
It is defined as:
where σ
is the microscopic absorption cross section, and n
is the number density of absorbing particles.
The free path L
follows an exponential distribution with mean λ
:
where the mean and the variance are and
.
With the property:
The simulation considers N
independent particles.
For each particle:
- It samples a free path L from the exponential distribution;
- If
$L \geq d$ , the particle is transmitted; - If
$L < d$ , the particle is absorbed.
It also samples
Since each
is Bernoulli with parameter p = T(d).
The transmission estimator is the sample mean, so:
The number of transmitted particles follows a binomial distribution, for this reason the standard error (SE) of the Monte Carlo result is:
All the modules of the program are inside src/mctransport
:
- RNG Module (
src/mctransport/rng.py
) - Physics Module (
src/mctransport/physics.py
) - Simulation Module (
src/mctransport/simulate.py
) - CLI Module (
src/mctransport/cli.py
) - Graph CLI Module (
src/mctransport/graph_cli.py
)
Some common parameter rules are the following:
n
,n_particles
: strictly positive and finite integer (booleans are rejected);distance
(d
): non-negative and finite;mean_free_path
(λ
): strictly positive and finite;rng
:numpy.random.Generator
.
distance
and mean_free_path
must have the same units.
The src/mctransport/rng.py
module contains a function for random number generation.
sample_free_path(n, mean_free_path, rng)
- It generates
n
free path lengths from an exponential distribution with meanmean_free_path
.
- It generates
The output is a 1D NumPy array of n
free path lengths (non-negative floats).
The src/mctransport/physics.py
module contains a function that computes the transmission probability.
beer_lambert_transmission(distance, mean_free_path)
- It gives the transmission probability: T(d) = exp(-d / λ).
The function returns a float value in [0, 1].
The src/mctransport/simulate.py
module contains a function for running the Monte Carlo transmission simulation using the other two modules together.
-
simulate_absorption_only(n_particles, distance, mean_free_path, rng)
- By creating free paths L from an exponential distribution and by counting particles with
$L \geq d$ , it simulates the transmission.
- By creating free paths L from an exponential distribution and by counting particles with
The output is a float in [0, 1].
The src/mctransport/cli.py
module gives a CLI to run the simulation from the terminal without Python code.
mctransport absorption-only -N <N> -d <distance> -l <mean_free_path> [options]
The required parameters are the following:
-N
or--n-particles
: It must be a positive finite integer. Scientific notation like '1e5' is accepted;-d
or--distance
: non-negative and finite;-l
or--lambda
or--mean-free-path
: strictly positive and finite.
The possible options are:
- Seed:
--seed
: int, RNG seed, if not specified is 'null' as default;
- Verbosity (mutually exclusive):
--verbose
: print parameters + numeric result;--terse
: print only the numeric result;--silent
: no console output.
- Output formats:
--precision
: int, how many decimal digits for the numeric result (default: 6);--json
: print result as JSON (also used for file output, it overrides the verbosity);--output PATH
: write output to file (JSON if --json, otherwise CSV).
mctransport absorption-only -N 1e5 -d 3 -l 2 --seed 42
# Transmission fraction: 0.224480
mctransport absorption-only -N 100000 -d 3.0 -l 2.0 --seed 42 --verbose
# Simulation: absorption-only
# N = 100,000
# d = 3.0
# mean_free_path = 2.0
# seed = 42
# Transmission fraction: 0.224480
# JSON on console and written to result.json in the current directory
mctransport absorption-only -N 1e5 -d 7 -l 2 --seed 24 --json --output result.json
# On console printed:
# Transmission fraction: 0.029110
# On result.json printed:
# {"simulation": "absorption-only", "n_particles": 100000, "distance": 7.0, "mean_free_path": 2.0, "seed": 24, "transmission": 0.02911}
# CSV file and terse on console
mctransport absorption-only -N 50000 -d 1.5 -l 0.8 --seed 123 --terse --precision 5 --output result.csv
# On console printed:
# 0.15318
# On result.csv printed:
# simulation,n_particles,distance,mean_free_path,seed,transmission
# absorption-only,50000,1.5,0.8,123,0.15318
Important: directories for --output
must already exist; the program does not attempt to create missing directories and will exit with error 3 if they do not exist.
The src/mctransport/graph_cli.py
script runs a sweep simulation of distances.
It compares the Monte Carlo transmission with the Beer-Lambert law.
It also writes a CSV with the data and a PNG plot (and it saves them inside ./results/
by default).
It uses independent RNG seeds per point: for each distance point (with index i
), the seed is set to seed + i
so that every row is reproducible with the results obtained with src/mctransport/cli.py
.
Programmatic use (Python):
With this first method the user can modify the parameters in the Python code and directly call run_sweep()
:
# Example of changing parameters
import numpy as np
from mctransport.graph_cli import run_sweep
run_sweep(
N=50_000,
lam=3.0,
seed=5678,
d_vals=np.linspace(0.0, 1.0, 7),
outdir="output_directory",
)
Parameters:
N
: It must be a strictly positive finite integer. Scientific notation is not accepted;lam
: strictly positive and finite;seed
: int, RNG seed is 'seed + i';d_vals
: np.ndarray, non-negative and finite values;outdir
: str or Path, output folder (created if missing).
CLI:
The second method consists in using the CLI:
# Example, if some parameters are not defined it takes the default ones.
mctransport-graph
# Example, all the parameters defined
mctransport-graph --N 200000 --lam 1.5 --seed 7 --dmin 0 --dmax 6 --points 25 --outdir output_directory
This second method builds an equally spaced grid of distances and creates d_vals
as np.linspace(dmin, dmax, points)
.
The script produces two outputs:
- CSV:
results_absorption_sweep.csv
with columns 'distance', 'T_mc', 'T_theory', 'SE'; - PNG:
results_absorption_sweep.png
(MC points with ±2*SE to consider 95% of expected statistical variation; and theoretical curve).
Example of the plot produced by the command:
mctransport-graph --N 200000 --lam 1.5 --seed 7 --dmin 0 --dmax 6 --points 25 --outdir output_directory
The tests for all the modules are located in tests/
.