Skip to content

Install petsc from PyPI, build basix from source, and check the install in CI - #13

Merged
shimwell merged 7 commits into
mainfrom
petsc-from-pypi
Sep 2, 2026
Merged

shimwell merged 7 commits into
mainfrom
petsc-from-pypi

Conversation

@shimwell

@shimwell shimwell commented Sep 2, 2026 •

Copy link
Copy Markdown
Member

petsc 3.25.5 landed on PyPI on 2026-08-30 and is the first release to include
petsc merge request 9488,
which keeps the pkg-config files in the wheel and rewrites prefix to
${pcfiledir}/../.. so they work wherever the wheel is unpacked. That was the
only reason the script cloned the release branch, so PETSc now comes from PyPI.

Before After
petsc git clone --branch release --depth 1 https://gitlab.com/petsc/petsc.git
pip install ./petsc
pip install "petsc==3.25.5"
petsc4py pip install setuptools wheel cython
pip install --no-build-isolation ./petsc/src/binding/petsc4py
pip install "petsc4py==3.25.5"

That drops a roughly 1 GB clone. Build time is unchanged, PyPI ships PETSc as
an sdist so pip still compiles it. Build isolation is fine for petsc4py now
because its setup.cfg has petsc_dir = $PETSC_DIR, which the script exports
from site-packages just above. Pinning petsc4py to the petsc version keeps the
two in step, which is what building both from one clone used to do.

basix goes back to a source build

c8e0902 swapped the basix source build for the fenics-basix wheel, and CI
shows that does not work. The wheel is built with -Cwheel.py-api=cp312, so it
is a Py_LIMITED_API build, and nanobind folds that into its ABI tag:

// Can have limited and non-limited-API extensions in the same process.
// Nanobind data structures will differ, so these can't talk to each other
#if defined(Py_LIMITED_API)
#  define NB_STABLE_ABI "_stable"

The dolfinx bindings built here are not limited API, so the two extensions get
separate type registries and fem.functionspace fails with "incompatible
function arguments". No nanobind version pin fixes it, only building both the
same way. Reported upstream on FEniCS/dolfinx#3064.

CI

A new workflow runs the script on a clean runner and then the whole pipeline:
openmc_data_downloader fetches H1 and Fe56, the first script tallies the
heating, the second solves the heat equation. 22 minutes, green.

The job pins ubuntu-26.04 rather than ubuntu-latest, which is still 24.04
and carries scotch 7.0.4 with no SCOTCHConfig.cmake, so the dolfinx configure
fails there with "No graph partitioner found". The README now says the pip
route requires 26.04.

Nothing in the repo said where the nuclear data comes from beyond "set
OPENMC_CROSS_SECTIONS", so openmc-data-downloader is part of the install
and the README gives the same two commands CI uses.

cad-to-dagmc-mesher is held below 0.3.0, which panics on this geometry with
orient_3d_sos: all projections degenerate. There is a TODO on the bound and
an upstream issue at fusion-energy/cad-to-dagmc-mesher#157.

petsc 3.25.5 is the first release on PyPI to keep the pkg-config files in
the wheel (petsc merge request 9488), and that is how dolfinx finds petsc,
so the clone of the release branch is no longer needed. petsc4py is pinned
to the same version to keep the two in step, and it no longer needs
--no-build-isolation because it takes PETSC_DIR from the environment, which
is already exported from site-packages.

The libpetsc.so symlink stays. dolfinx pull request 4468 fixes that on the
dolfinx side but is only on main, not in 0.11.
Runs installation-with-pip.sh on a clean ubuntu runner, then solves the heat
equation on the heating field committed to the repo. That covers the parts of
the install that an import check does not: dolfinx.fem.petsc has to dlopen
libpetsc.so, the solve goes through petsc4py, and the mesh comes from the 0.11
vtkhdf reader.

The cad and neutronics script is left out because it needs nuclear data.
The first run failed in the dolfinx configure with "No graph partitioner
found". ubuntu-latest is still 24.04, which carries scotch 7.0.4 and ships no
SCOTCHConfig.cmake, and dolfinx looks for SCOTCH in CONFIG mode. 26.04 has
7.0.11, which does ship it, so the job pins ubuntu-26.04.

CI now runs 1-make-cad-get-neutron-heating.py as well, so the openmc, cadquery,
cad_to_dagmc and moab half of the install is exercised rather than just
imported. The example only needs H1 and Fe56, so openmc_data_downloader fetches
those two from FENDL rather than a whole library.

Nothing told a user where to get the nuclear data beyond "set
OPENMC_CROSS_SECTIONS", so openmc-data-downloader is now part of the pip
install and the README gives the same two commands CI uses.
0.3.0 panics on this geometry in the volume mesh with

  pyo3_runtime.PanicException: orient_3d_sos: all projections degenerate
  => duplicate vertex (ids 5017,289,289,5002)

Reproduced twice with identical vertex ids, so it is deterministic rather than a
race in the mesher thread pool. 0.2.0 meshes the same assembly and writes both
dagmc.h5m and umesh.vtk. The mesher comes in as a dependency, so it needs an
explicit bound in both install scripts.
Both install scripts now take whatever is newest. The mesher upper bound was
holding it at 0.2.x because 0.3.0 panics on this geometry, so CI will fail in
1-make-cad-get-neutron-heating.py until that is fixed upstream.
The solve failed with

  TypeError: __init__(): incompatible function arguments
  Invoked with types: dolfinx.cpp.fem.FiniteElement_float64,
  basix._basixcpp.FiniteElement_float64, NoneType, bool

even though the basix element passed is the type the overload asks for. Both
extensions are nanobind, and nanobind shares its type registry only between
extensions built with the same internal ABI version. The install picked up
nanobind 3.0.1 (ABI 22) for the dolfinx build, while the prebuilt fenics-basix
0.11.0 wheel predates nanobind 3.0.0 by two months, so basix elements were
invisible to dolfinx. Both basix and dolfinx only ask for nanobind>=2.5.0, so
nothing upstream prevents this.

The solve step also now runs even when the tally step failed, so a broken
mesher does not hide whether the dolfinx and petsc side works.
c8e0902 swapped the basix source build for the fenics-basix wheel, and that has
not been run end to end since: the images in the README predate it. The wheel is
built by cibuildwheel with -Cwheel.py-api=cp312, so it is a Py_LIMITED_API
build, and nanobind folds that into its ABI tag:

  // Can have limited and non-limited-API extensions in the same process.
  // Nanobind data structures will differ, so these can't talk to each other
  #if defined(Py_LIMITED_API)
  #  define NB_STABLE_ABI "_stable"

The dolfinx bindings built here are not Py_LIMITED_API, so the two extensions
get different tags and separate type registries, and passing a basix element
into dolfinx fails with "incompatible function arguments" from
fem.functionspace. No nanobind version pin can fix that, only building both the
same way.

Also puts the cad-to-dagmc-mesher upper bound back so CI can go green, with a
TODO to drop it once fusion-energy/cad-to-dagmc-mesher#157 is fixed.
@shimwell shimwell changed the title Install petsc and petsc4py from PyPI instead of a git clone Install petsc from PyPI, build basix from source, and check the install in CI Sep 2, 2026
@shimwell
shimwell merged commit b63eeab into main Sep 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant