nain4
is an API and accompanying set of libraries whose aim is to make it
easier to write, test and deploy Geant4
applications.
The documentation for nain4
is gradually being written
here.
Nain4 uses Nix
to manage dependencies, installation and
provision of the development environment. The value proposition is: If you
install nix on
your machine we can provide a zero-effort means of installing Geant4 plus
dependencies and development tools, and making sure that everything has
compatible versions and works together in harmony[^1].
[^1]: Somewhere in the repository, we have provided the means to install nain4
without the use of Nix, but we do not have the resources or the motivation
to maintain this. If something in nain4
is broken when using it via Nix,
then we will aim to fix it; if something is broken when using nain4
without Nix, then we won't be able to help.
For HPC systems on which installing Nix might be problematic:
nain4
Nain4 is a collection of utilities whose aim is to
As a quick taster, here is a translation of the detector geometry from Geant4 example basic/B1
into nain4
:
// Materials
auto water = n4::material("G4_WATER");
auto air = n4::material("G4_AIR");
auto tissue = n4::material("G4_A-150_TISSUE");
auto bone = n4::material("G4_BONE_COMPACT_ICRU");
// Dimensions
// ...
// world_sizeXY = ... unremarkable value settings elided for brevity
// ...
// Volumes
auto world = n4::box ("World" ).xy(world_sizeXY).z(world_sizeZ) .volume(air);
auto envelope = n4::box ("Envelope").xy( env_sizeXY).z( env_sizeZ) .volume(water);
auto trapezoid = n4::trd ("Bone" ).x1(trd_dxa).x2(trd_dxb)
.y1(trd_dya).y2(trd_dyb).z(trd_dz).volume(bone);
// If no handle is needed for a logical volume, it can be placed immediately
n4::cons("Tissue").r1(cone_rmaxa).r2(cone_rmaxb).z(cone_hz).place(tissue).in(envelope).at_yz(2*cm, -7*cm).now();
// Set Trapezoid as scoring volume
this -> fScoringVolume = trapezoid;
// Placement
n4:: place(envelope) .in(world) .now();
n4:: place(trapezoid).in(envelope).at_yz(-1*cm, 7*cm).now();
return n4::place(world) .now();
This is the complete (except for setting of the values like world_sizeXYZ
) nain4
implementation of DetectorConstruction::Construct()
.
These 13 lines of code (without comments or blank lines) correspond to 62 lines in the original example.
In Geant4's interfaces, you have to remember (or look up) the order of the parameters of the shape constructors, and you must provide values for each parameter, even when you want to use an obvious default value (such as inner radius
being zero, or phi
covering 2π
); in nain4
the parameters have clear names and can be provided in any order that you find convenient; obvious default values can be omitted.
Geant4 obliges you to express everything in (frequently annoying) half-lengths; nain4
gives you the choice: .x
vs .half_x
.
The whole[^2] B1 example is translated into nain4 here, and, even though it is written in a style that places almost every argument on a separate line, it fits in a single file in under 150 lines, compared to the 1138 lines spread over 13 files in the original Geant4 rendition.
[^2]: This is not strictly true. The original B1 example caters for multiprocessing. As we actively discourage (TODO link to section in docs) using multiprocessing in Geant4, this translation into nain4 is not exactly equivalent. However, the differences are absolutely minimal.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
Bootstrap a new nain4
project:
nix run github:jacg/nain4#bootstrap-client-project path/to/your-new-project your-project-name "Your project description"
This step will take a while as it downloads and compiles Geant4.
A new directory path/to/your-new-project
will be created. Adapt this path to your needs before executing the command.
Also adapt your-project-name
(used in various identifiers and path components inside your project) and "Your project description"
before executing the command.
cd
into path/to/your-new-project
Type nix develop
[^3]
Start a new bash
shell in which all the required dependencies are
available. Exiting this shell makes these dependencies invisible once more.
Thus, the installation of these dependencies does not interfere with anything
else you may have on your system.
Type just run -g -n 10
.
This step compiles the example application in your new project and runs it in interactive mode. A visualization window should pop up.
[^3]: see the section on direnv for a more ergonomic alternative
If all this worked, hooray! You have a git repository containing a development
environment in which you can use to evolve, test and deploy your nain4
-based
Geant4 application.
If not, read on to see possible problems and fixes.
direnv
As it stands you have to write nix develop
in order to activate the
environment necessary to run and develop this code. What is more, nix develop
places you in a minimal bash shell in which any personal configurations you may
be used to, will be missing.
Both of these problems can be fixed with direnv which:
To use direnv
:
Make sure that it is installed
on your system. If you have got this far, then you have already installed the
Nix package manager on your machine, so you could use it to install direnv
like this:
nix profile install nixpkgs#direnv
Don't forget to hook direnv
into your
shell. Depending on which shell you are using, this will involve adding one
of the following lines to the end of your shell configuration file:
eval "$(direnv hook bash)" # in ~/.bashrc
eval "$(direnv hook zsh)" # in ~/.zshrc
eval `direnv hook tcsh` # in ~/.cshrc
The first time direnv
wants to perform an automatic switch in a new
context (combination of directory + .envrc
contents), it asks you
for permission to do so. You can give it permission by typing direnv allow
in the shell. The message that direnv
gives you at this stage
is pretty clear, but it's usually written in red, thus you might get
the mistaken impression that there is an error.
Linux: This code is developed and tested on Linux. If the above procedure didn't work, it's a bug. Please report it.
Windows: It should work equally well in WSL2 on Windows.
Caveat: if you are going to install Nix in multi-user mode, make sure that systemd
is enabled. In short, this requires you to ensure that the file /etc/wsl.conf
exists in your in-WSL linux and that it contains the lines
[boot]
systemd=true
MacOS: Everything seems to work on macOS, with both Intel processors and Apple Silicon, but it has not been tested as extensively as on Linux.
The interactive mode uses a Qt-based GUI. This requires the correct graphics drivers to be installed in a location known to Nix. This should work out of the box on
On other systems, that is to say non-NixOS Linuxes and WSL2 on Windows, the
environment will try to use nixGL
to
provide the appropriate drivers. WARNING: the first time nixGL
is needed, it
will take a long time to download and compile.