New package - libconeangle

I’ve written a small Fortran library with a Python interface, libconeangle. It’s based on some learnings from this thread and many others. For me, it’s a first attempt of writing relatively modern Fortran code for easy access via Python (or any other language with a C interface), that is also packaged in an accessible way. Would be curious for feedback both on the Fortran and Python aspects.

The design philosophy is to use an explicit C API to the main subroutine that the library provides, cone_angle. It is then compiled as a shared library which is loaded with ctypes from Python. The heavy lifting with respect to passing arrays is handled via numpy.ctypeslib. The Fortran stdlib is used in many instances, for example for checking near-equivalence of real numbers. The user of the Python package would be completely agnostic of the Fortran backend as everything is wrapped

>>> from libconeangle import cone_angle
>>> coordinates =  np.array([[0.0, 0.0, -0.52], [0.0, 0.0, 1.76], [0.0, 0.0, 2.86]])
>>> radii = np.array([2.1, 1.7, 1.52])
>>> index_metal = 0 # Zero-indexed
>>> c_angle, axis, tangent_atoms = cone_angle(coordinates, radii, index_metal)
>>> c_angle
96.4237340645161
>>> axis
array([0., 0., 1.])
>>> tangent_atoms # Also zero-indexed
[1]

The main challenge has been packaging. The average Python user expects to be able to install via either the pip package installer or conda (usually the conda-forge channel these days) and will not be bothered to compile Fortran code or even installing a Fortran compiler. Packages also need to be available on Windows, MacOS (ARM and Intel) and Linux, and also need to support a number of different Python versions (at least 3.8-3.10). These aspects are particularly relevant for a package like libconeangle which would be used as a dependency in other packages.

In the end I believe that I found a relatively simple system which should require little maintenance (although it was far from simple to get there!). It is based on a combination of CMake and scikit-build, where cibuildwheel is used to build platform-specific wheels on GitHub Actions that are then uploaded to PyPI. Support for conda-forge is also essentially done but needs approval. Here, the package is built directly for Linux and MacOS, while support for Windows is hampered by the lack of a modern Fortran compiler (GFortran 5.3). For Windows, I therefore resort to installing the wheels from PyPI which seems to work OK.

12 Likes

I have also found using CMake with scikit-build is the easiest way to combine Python and Fortran/C/C++.

1 Like

In my experience, the GitHub Windows CI environment has gfortran 10.3 installed, and it’s possible to get 11.2 installed using msys. Also, I’ve had good luck with the installer provided by equation.com.

Yes, I am building Windows wheels on GitHub Actions. You can get the 11.2 just by running choco upgrade mingw. Conda-forge is stuck at 5.3 though.