WIP: DESIGN Configuring C8 simulations from Python
This is a proof-of-concept Python interface for C8 that is capable of configuring and running an extended air shower (basically a Python version of the existing verticalEAS test) implemented using PyBind11.
This is still very WIP and is intended to start some discussion on whether this is a useful idea to pursue - I only implemented what was necessary to get the vertical air shower example working (using Sibyll and EnergyLoss) and understand how the full Python interface might work.
Currently, a full EAS is configured and run in the test suite and can be seen here.
This interface currently has the following features:
- Our physical units are mapped directly into Python types with all the normal numeric operator overloads - this enables expressions like
1*GeVetc. These are unit-checked (at runtime) and any attempt to pass an invalid unit into a method will result in a TypeError exception.
- Our geometry types (currently Vector, Point) are wrapped and again support the standard vector operators - i.e.
center = Point(cs, 0*m, 1*m, 3*m),
center + center,
(center - Point(cs, 0*m, 0*km, 0*m)) * 1.5
- The Python package hierarchy is a one-to-map of the C8 header structure i.e.
<corsika/geometry/Point.h>is wrapped into
corsika.geometry.Point. Each header file has a corresponding Python implementation file in a matching set of subdirectories (to keep each compilation unit independent where possible).
- Process lists are assembled using the same
<<operator as in C++. Currently, I have hard-coded the supported combination of processes in a ProcessList (since the type must be known as compile-time and I wanted to get something working quickly) but there are a couple of options available to us for easily supporting the full list of processes. This can be discussed in more detail as needed.
Most of the C8 code base is very amenable to exposing into Python - the only part that poses a significant issue is the process sequence (since the exact type is defined at compile-time by the product of
P1 << P2 << ... etc.) I see a couple of ways we can approach this on a larger scale (some of which I have used in other codebases)
- If the number of type permutations is small, some macro+template magic can generate every compile-time permutation of types. A Python factory function then dispatches the Python runtime arguments to the correct type. This could work for our environment hierarchy where we may only have a handful of types.
- For the process sequence (where the number of permutations is too large), we could provide a handful of standard precompiled process lists that could serve the needs of most users. If we add the ability to disable a particular process at runtime into the Process hierarchy, one very detailed process list could be adjusted from Python as needed. There's plenty of ideas to discuss on this front!
This is still very WIP and I have a big list of improvements and TODOs if we decide to continue down this route.
Perhaps we can discuss this at a future meeting...