From e77bdd70d8e8d29a23d6819236e20fc586b1cad5 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Mon, 24 Nov 2025 16:18:02 +0000 Subject: [PATCH 01/10] WIP Add Cython bindings for the PETSc API --- petsctools/__init__.pxd | 0 petsctools/cpetsc.pxd | 56 +++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 3 +++ 3 files changed, 59 insertions(+) create mode 100644 petsctools/__init__.pxd create mode 100644 petsctools/cpetsc.pxd diff --git a/petsctools/__init__.pxd b/petsctools/__init__.pxd new file mode 100644 index 0000000..e69de29 diff --git a/petsctools/cpetsc.pxd b/petsctools/cpetsc.pxd new file mode 100644 index 0000000..4693d9a --- /dev/null +++ b/petsctools/cpetsc.pxd @@ -0,0 +1,56 @@ +"""This file basically exposes the PETSc API as a module for use in Cython.""" +from petsc4py cimport PETSc as _PETSc + +# clearer aliases from petsc4py, so the names here match the C API +ctypedef _PETSc.PetscMat Mat +ctypedef _PETSc.Mat Mat_py +ctypedef _PETSc.PetscSF PetscSF +ctypedef _PETSc.SF PetscSF_py +ctypedef _PETSc.PetscSection PetscSection +ctypedef _PETSc.Section PetscSection_py +ctypedef _PETSc.PetscIS IS +ctypedef _PETSc.IS IS_py + +# other PETSc imports +from petsc4py.PETSc cimport ( + CHKERR, + PetscErrorCode, +) + + +cdef extern from "petsc.h": + # fundamental types + ctypedef long PetscInt + ctypedef double PetscReal + ctypedef double PetscScalar + ctypedef enum PetscBool: + PETSC_TRUE + PETSC_FALSE + ctypedef enum InsertMode: + INSERT_VALUES + ADD_VALUES + ctypedef enum PetscCopyMode: + PETSC_COPY_VALUES + PETSC_OWN_POINTER + PETSC_USE_POINTER + + # memory management + PetscErrorCode PetscCalloc1(size_t,void*) + PetscErrorCode PetscMalloc1(size_t,void*) + PetscErrorCode PetscFree(void*) + + # Mat + PetscErrorCode MatSetValue(Mat,PetscInt,PetscInt,const PetscScalar,InsertMode) + PetscErrorCode MatSetValuesBlockedLocal(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode) + + # PetscSF + ctypedef struct PetscSFNode: + pass + + PetscErrorCode PetscSFGetGraph(PetscSF,PetscInt*,PetscInt*,PetscInt**,PetscSFNode**) + PetscErrorCode PetscSFSetGraph(PetscSF,PetscInt,PetscInt,PetscInt*,PetscCopyMode,PetscSFNode*,PetscCopyMode) + + # PetscSection + PetscErrorCode PetscSectionGetDof(PetscSection,PetscInt,PetscInt*) + PetscErrorCode PetscSectionSetDof(PetscSection,PetscInt,PetscInt) + PetscErrorCode PetscSectionGetOffset(PetscSection,PetscInt,PetscInt*) diff --git a/pyproject.toml b/pyproject.toml index 0d155d8..4bc3255 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,9 @@ ci = [ {include-group = "test"}, ] +[tool.setuptools.package-data] +petsctools = ["__init__.pxd", "cpetsc.pxd"] + [tool.ruff] line-length = 79 From b87c05e57d126e1411b51ffec49551fa7eb412a8 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Mon, 24 Nov 2025 16:20:10 +0000 Subject: [PATCH 02/10] fixup --- petsctools/cpetsc.pxd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/petsctools/cpetsc.pxd b/petsctools/cpetsc.pxd index 4693d9a..07567a6 100644 --- a/petsctools/cpetsc.pxd +++ b/petsctools/cpetsc.pxd @@ -1,4 +1,7 @@ """This file basically exposes the PETSc API as a module for use in Cython.""" + +# IMPORTANT: This file cannot be accessed if petsctools is installed in editable mode. + from petsc4py cimport PETSc as _PETSc # clearer aliases from petsc4py, so the names here match the C API From 8a3196faf101a4ae0b59f7e40ffae170b8d417d5 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Mon, 24 Nov 2025 16:41:12 +0000 Subject: [PATCH 03/10] Add demo, will be included in the docs --- .gitignore | 7 ++- docs/source/_static/cython-demo/fast.pyx | 36 ++++++++++++++ docs/source/_static/cython-demo/setup.py | 63 ++++++++++++++++++++++++ docs/source/_static/cython-demo/slow.py | 18 +++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 docs/source/_static/cython-demo/fast.pyx create mode 100644 docs/source/_static/cython-demo/setup.py create mode 100644 docs/source/_static/cython-demo/slow.py diff --git a/.gitignore b/.gitignore index 614fae7..436e9bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,12 @@ petsctools/config.ini -*/__pycache__ +**/__pycache__ *.egg-info docs/build docs/source/generated + +docs/source/_static/cython-demo/build +docs/source/_static/cython-demo/*.c +docs/source/_static/cython-demo/*.so +docs/source/_static/cython-demo/*.html diff --git a/docs/source/_static/cython-demo/fast.pyx b/docs/source/_static/cython-demo/fast.pyx new file mode 100644 index 0000000..fea9f2a --- /dev/null +++ b/docs/source/_static/cython-demo/fast.pyx @@ -0,0 +1,36 @@ +import time + +import cython +from petsc4py import PETSc + +from petsctools cimport cpetsc + + +def medium(): + N: cython.int = int(1e8) + section: PETSc.Section = PETSc.Section().create() + section.setChart(0, N) + + start = time.time() + i: cython.int + for i in range(N): + if i % 2 == 0: + section.setDof(i, 1) + print(f"Time elapsed: {time.time() - start}") + + +def fast(): + N: cython.int = int(1e8) + section: cpetsc.PetscSection_py = PETSc.Section().create() + section.setChart(0, N) + + start = time.time() + i: cython.int + for i in range(N): + if i % 2 == 0: + cpetsc.CHKERR(cpetsc.PetscSectionSetDof(section.sec, i, 1)) + print(f"Time elapsed: {time.time() - start}") + + +medium() +fast() diff --git a/docs/source/_static/cython-demo/setup.py b/docs/source/_static/cython-demo/setup.py new file mode 100644 index 0000000..4e7cbdc --- /dev/null +++ b/docs/source/_static/cython-demo/setup.py @@ -0,0 +1,63 @@ +from Cython.Build import cythonize +from setuptools import setup, Extension + +import petsctools +import os +import petsc4py + + +from dataclasses import dataclass, field + + +@dataclass +class ExternalDependency: + ''' This dataclass stores the relevant information for the compiler as fields + that correspond to the keyword arguments of `Extension`. For convenience it + also implements addition and `**` unpacking. + ''' + include_dirs: list[str] = field(default_factory=list, init=True) + extra_compile_args: list[str] = field(default_factory=list, init=True) + libraries: list[str] = field(default_factory=list, init=True) + library_dirs: list[str] = field(default_factory=list, init=True) + extra_link_args: list[str] = field(default_factory=list, init=True) + runtime_library_dirs: list[str] = field(default_factory=list, init=True) + + def __add__(self, other): + combined = {} + for f in self.__dataclass_fields__.keys(): + combined[f] = getattr(self, f) + getattr(other, f) + return self.__class__(**combined) + + def keys(self): + return self.__dataclass_fields__.keys() + + def __getitem__(self, key): + try: + return getattr(self, key) + except AttributeError: + raise KeyError(f"Key {key} not present") + + + +petsc_dir = petsctools.get_petsc_dir() +petsc_arch = petsctools.get_petsc_arch() +petsc_dirs = [petsc_dir, os.path.join(petsc_dir, petsc_arch)] +petsc_ = ExternalDependency( + libraries=["petsc"], + include_dirs=[petsc4py.get_include()] + [os.path.join(d, "include") for d in petsc_dirs], + library_dirs=[os.path.join(petsc_dirs[-1], "lib")], + runtime_library_dirs=[os.path.join(petsc_dirs[-1], "lib")], +) + +mods = [ + Extension( + name="cython_demo", + language="c", + sources=[os.path.join("cython_demo.pyx")], + **(petsc_), + annotate=True, + ) +] + + +setup(ext_modules=mods) diff --git a/docs/source/_static/cython-demo/slow.py b/docs/source/_static/cython-demo/slow.py new file mode 100644 index 0000000..82acb94 --- /dev/null +++ b/docs/source/_static/cython-demo/slow.py @@ -0,0 +1,18 @@ +import time + +from petsc4py import PETSc + + +def slow(): + N = int(1e8) + section = PETSc.Section().create() + section.setChart(0, N) + + start = time.time() + for i in range(N): + if i % 2 == 0: + section.setDof(i, 1) + print(f"Time elapsed: {time.time() - start}") + + +slow() From 0019c193d5d8dec222715752ef4bb0de43667909 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 26 Nov 2025 15:07:19 +0000 Subject: [PATCH 04/10] PetscSFNode fix --- petsctools/cpetsc.pxd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/petsctools/cpetsc.pxd b/petsctools/cpetsc.pxd index 07567a6..fb55c2c 100644 --- a/petsctools/cpetsc.pxd +++ b/petsctools/cpetsc.pxd @@ -48,9 +48,10 @@ cdef extern from "petsc.h": # PetscSF ctypedef struct PetscSFNode: - pass + PetscInt rank + PetscInt index - PetscErrorCode PetscSFGetGraph(PetscSF,PetscInt*,PetscInt*,PetscInt**,PetscSFNode**) + PetscErrorCode PetscSFGetGraph(PetscSF,PetscInt*,PetscInt*,const PetscInt**,const PetscSFNode**) PetscErrorCode PetscSFSetGraph(PetscSF,PetscInt,PetscInt,PetscInt*,PetscCopyMode,PetscSFNode*,PetscCopyMode) # PetscSection From a73622597f0769175aba238c53d6b29cb5594272 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Tue, 31 Mar 2026 17:59:38 +0100 Subject: [PATCH 05/10] Add webpage and more, almost ready --- .github/workflows/core.yml | 9 +++ .gitignore | 10 ++- docs/source/_static/cython-demo/setup.py | 63 --------------- .../{cython-demo => cython_demo}/fast.pyx | 0 docs/source/_static/cython_demo/setup.py | 18 +++++ .../{cython-demo => cython_demo}/slow.py | 0 docs/source/cython.rst | 76 +++++++++++++++++++ docs/source/index.rst | 1 + petsctools/cpetsc.pxd | 2 +- 9 files changed, 111 insertions(+), 68 deletions(-) delete mode 100644 docs/source/_static/cython-demo/setup.py rename docs/source/_static/{cython-demo => cython_demo}/fast.pyx (100%) create mode 100644 docs/source/_static/cython_demo/setup.py rename docs/source/_static/{cython-demo => cython_demo}/slow.py (100%) create mode 100644 docs/source/cython.rst diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index dfc639a..3f78797 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -130,6 +130,15 @@ jobs: . venv-petsctools/bin/activate pytest petsctools-repo + - name: Run Cython demo + if: success() || steps.install-petsc4py.conclusion == 'success' + run: | + . venv-petsctools/bin/activate + cd docs/source/_static/cython_demo + python setup.py build_ext --inplace + python -c "import slow" + python -c "import fast" + - name: Build documentation id: build_docs if: success() || steps.install.conclusion == 'success' diff --git a/.gitignore b/.gitignore index 436e9bc..3a9e41a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,12 @@ petsctools/config.ini **/__pycache__ *.egg-info +build/ + docs/build docs/source/generated -docs/source/_static/cython-demo/build -docs/source/_static/cython-demo/*.c -docs/source/_static/cython-demo/*.so -docs/source/_static/cython-demo/*.html +docs/source/_static/cython_demo/build +docs/source/_static/cython_demo/*.c +docs/source/_static/cython_demo/*.so +docs/source/_static/cython_demo/*.html diff --git a/docs/source/_static/cython-demo/setup.py b/docs/source/_static/cython-demo/setup.py deleted file mode 100644 index 4e7cbdc..0000000 --- a/docs/source/_static/cython-demo/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -from Cython.Build import cythonize -from setuptools import setup, Extension - -import petsctools -import os -import petsc4py - - -from dataclasses import dataclass, field - - -@dataclass -class ExternalDependency: - ''' This dataclass stores the relevant information for the compiler as fields - that correspond to the keyword arguments of `Extension`. For convenience it - also implements addition and `**` unpacking. - ''' - include_dirs: list[str] = field(default_factory=list, init=True) - extra_compile_args: list[str] = field(default_factory=list, init=True) - libraries: list[str] = field(default_factory=list, init=True) - library_dirs: list[str] = field(default_factory=list, init=True) - extra_link_args: list[str] = field(default_factory=list, init=True) - runtime_library_dirs: list[str] = field(default_factory=list, init=True) - - def __add__(self, other): - combined = {} - for f in self.__dataclass_fields__.keys(): - combined[f] = getattr(self, f) + getattr(other, f) - return self.__class__(**combined) - - def keys(self): - return self.__dataclass_fields__.keys() - - def __getitem__(self, key): - try: - return getattr(self, key) - except AttributeError: - raise KeyError(f"Key {key} not present") - - - -petsc_dir = petsctools.get_petsc_dir() -petsc_arch = petsctools.get_petsc_arch() -petsc_dirs = [petsc_dir, os.path.join(petsc_dir, petsc_arch)] -petsc_ = ExternalDependency( - libraries=["petsc"], - include_dirs=[petsc4py.get_include()] + [os.path.join(d, "include") for d in petsc_dirs], - library_dirs=[os.path.join(petsc_dirs[-1], "lib")], - runtime_library_dirs=[os.path.join(petsc_dirs[-1], "lib")], -) - -mods = [ - Extension( - name="cython_demo", - language="c", - sources=[os.path.join("cython_demo.pyx")], - **(petsc_), - annotate=True, - ) -] - - -setup(ext_modules=mods) diff --git a/docs/source/_static/cython-demo/fast.pyx b/docs/source/_static/cython_demo/fast.pyx similarity index 100% rename from docs/source/_static/cython-demo/fast.pyx rename to docs/source/_static/cython_demo/fast.pyx diff --git a/docs/source/_static/cython_demo/setup.py b/docs/source/_static/cython_demo/setup.py new file mode 100644 index 0000000..f81a846 --- /dev/null +++ b/docs/source/_static/cython_demo/setup.py @@ -0,0 +1,18 @@ +from setuptools import setup, Extension + +import petsc4py +import petsctools + + +extension = Extension( + name="fast", + language="c", + sources=["fast.pyx"], + include_dirs=petsctools.get_petsc_dirs(subdir="include"), + library_dirs=petsctools.get_petsc_dirs(subdir="lib"), + runtime_library_dirs=petsctools.get_petsc_dirs(subdir="lib"), + libraries=["petsc"], + annotate=True, +) + +setup(ext_modules=[extension]) diff --git a/docs/source/_static/cython-demo/slow.py b/docs/source/_static/cython_demo/slow.py similarity index 100% rename from docs/source/_static/cython-demo/slow.py rename to docs/source/_static/cython_demo/slow.py diff --git a/docs/source/cython.rst b/docs/source/cython.rst new file mode 100644 index 0000000..cefbf20 --- /dev/null +++ b/docs/source/cython.rst @@ -0,0 +1,76 @@ +PETSc C bindings +---------------- + +In some circumstances it is desirable to write PETSc C code instead of using +the petsc4py Python bindings. For example: + +* The overhead involved in calling Python bindings may be unacceptable. This + may be the case in very tight loops. +* The desired API functionality is not available in petsc4py. + +To support this, petsctools makes some of PETSc's C API available to use +through Cython. It does this in a similar way to petsc4py but emphasises +readability and faithfulness to the API. Anyone should be able to add +additional bindings to the +`definitions file `_ +without trouble. + +Demo +~~~~ + +To demonstrate this, consider the following simple piece of PETSc code: + +.. literalinclude:: _static/cython_demo/slow.py + :language: python3 + +This code is written in Python and consists of petsc4py API calls. The +Python overhead is therefore maximised. Run on the author's machine this +code takes 4.0s to run to completion. + +Compare this to the examples given in this Cython file: + +.. literalinclude:: _static/cython_demo/fast.pyx + :language: cython + +Here we have two cases. The first (``medium``) is very similar to +``slow`` but is able to partially compile itself because it is +written in Cython. The second (``fast``) avoids petsc4py entirely +and instead uses the PETSc C API directly as exposed through +petsctools. + +Switching to Cython and using the C API directly both lead to +performance improvements. ``medium`` takes 1.8s and ``fast`` +takes 0.78s. + +Compiling Cython code +~~~~~~~~~~~~~~~~~~~~~ + +To compile the Cython code it must be registered as a compiled +extension inside a ``setup.py`` file. A working example for the +extension provided above looks like: + +.. literalinclude:: _static/cython_demo/setup.py + :language: python3 + +This file should be added to your project along with a suitable +``pyproject.toml`` that indicates ``setuptools`` as the +``build-backend``. ``setuptools``, ``cython``, ``petsc4py`` and +``petsctools`` are all necessary build-time dependencies. + +Conventions used +~~~~~~~~~~~~~~~~ + +* All objects are available inside the ``cpetsc`` namespace after + ``cimport``-ing it (e.g. ``cpetsc.PetscSectionSetDof``). + +* petsc4py PETSc objects are renamed to their C API equivalent with + a ``_py`` suffix. For example ``cpetsc.PetscSection`` represents the + C type and ``cpetsc.PetscSection_py`` the Cython type. + +* The C handle of the petsc4py objects are available through a specific + attribute that depends on the type. Examples include: + + * ``cpetsc.Mat_py.mat`` ⟷ ``cpetsc.Mat`` + * ``cpetsc.Vec_py.vec`` ⟷ ``cpetsc.Vec`` + * ``cpetsc.IS_py.iset`` ⟷ ``cpetsc.IS`` + * ``cpetsc.PetscSection_py.sec`` ⟷ ``cpetsc.PetscSection`` diff --git a/docs/source/index.rst b/docs/source/index.rst index 5a7cdd9..978da07 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,4 +8,5 @@ petsctools provides Pythonic extensions for petsc4py and slepc4py. :maxdepth: 2 examples + cython generated/modules diff --git a/petsctools/cpetsc.pxd b/petsctools/cpetsc.pxd index fb55c2c..d04efb1 100644 --- a/petsctools/cpetsc.pxd +++ b/petsctools/cpetsc.pxd @@ -1,4 +1,4 @@ -"""This file basically exposes the PETSc API as a module for use in Cython.""" +"""This file exposes the PETSc API as a module for use in Cython.""" # IMPORTANT: This file cannot be accessed if petsctools is installed in editable mode. From 9113728f97de97b6184f4853023f54e9a6a38cfd Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Tue, 31 Mar 2026 22:32:14 +0100 Subject: [PATCH 06/10] fixup --- docs/source/_static/cython_demo/setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/_static/cython_demo/setup.py b/docs/source/_static/cython_demo/setup.py index f81a846..451474b 100644 --- a/docs/source/_static/cython_demo/setup.py +++ b/docs/source/_static/cython_demo/setup.py @@ -1,6 +1,5 @@ from setuptools import setup, Extension -import petsc4py import petsctools From 51a9cea1759017179809d5cd8451cdff8e4e6b2d Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Tue, 31 Mar 2026 22:47:21 +0100 Subject: [PATCH 07/10] fixup --- .github/workflows/core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 3f78797..7b8d820 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -134,7 +134,7 @@ jobs: if: success() || steps.install-petsc4py.conclusion == 'success' run: | . venv-petsctools/bin/activate - cd docs/source/_static/cython_demo + cd petsctools-repo/docs/source/_static/cython_demo python setup.py build_ext --inplace python -c "import slow" python -c "import fast" From 42111c878d09f7ca0fa2cbb77ce1e9304d22a022 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 1 Apr 2026 11:55:01 +0100 Subject: [PATCH 08/10] Small improvements and tests should pass --- .github/workflows/core.yml | 2 +- docs/source/_static/cython_demo/fast.pyx | 2 +- docs/source/_static/cython_demo/setup.py | 1 - docs/source/cython.rst | 22 ++++++++++++++++------ pyproject.toml | 1 + 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 7b8d820..afd54d4 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -88,7 +88,7 @@ jobs: : # upgrade pip since dependency groups were only introduced in pip 25.1 pip install -U pip - pip install --verbose ./petsctools-repo + pip install --verbose ./petsctools-repo[cython] pip install --group ./petsctools-repo/pyproject.toml:ci pip list diff --git a/docs/source/_static/cython_demo/fast.pyx b/docs/source/_static/cython_demo/fast.pyx index fea9f2a..c2b3dae 100644 --- a/docs/source/_static/cython_demo/fast.pyx +++ b/docs/source/_static/cython_demo/fast.pyx @@ -21,7 +21,7 @@ def medium(): def fast(): N: cython.int = int(1e8) - section: cpetsc.PetscSection_py = PETSc.Section().create() + section: PETSc.Section = PETSc.Section().create() section.setChart(0, N) start = time.time() diff --git a/docs/source/_static/cython_demo/setup.py b/docs/source/_static/cython_demo/setup.py index 451474b..55b127d 100644 --- a/docs/source/_static/cython_demo/setup.py +++ b/docs/source/_static/cython_demo/setup.py @@ -11,7 +11,6 @@ library_dirs=petsctools.get_petsc_dirs(subdir="lib"), runtime_library_dirs=petsctools.get_petsc_dirs(subdir="lib"), libraries=["petsc"], - annotate=True, ) setup(ext_modules=[extension]) diff --git a/docs/source/cython.rst b/docs/source/cython.rst index cefbf20..140f427 100644 --- a/docs/source/cython.rst +++ b/docs/source/cython.rst @@ -9,11 +9,8 @@ the petsc4py Python bindings. For example: * The desired API functionality is not available in petsc4py. To support this, petsctools makes some of PETSc's C API available to use -through Cython. It does this in a similar way to petsc4py but emphasises -readability and faithfulness to the API. Anyone should be able to add -additional bindings to the -`definitions file `_ -without trouble. +through `Cython `_. It does this in a similar way +to petsc4py but emphasises readability and faithfulness to the API. Demo ~~~~ @@ -54,7 +51,7 @@ extension provided above looks like: This file should be added to your project along with a suitable ``pyproject.toml`` that indicates ``setuptools`` as the -``build-backend``. ``setuptools``, ``cython``, ``petsc4py`` and +``build-backend``. ``setuptools``, ``cython`` and ``petsctools`` are all necessary build-time dependencies. Conventions used @@ -74,3 +71,16 @@ Conventions used * ``cpetsc.Vec_py.vec`` ⟷ ``cpetsc.Vec`` * ``cpetsc.IS_py.iset`` ⟷ ``cpetsc.IS`` * ``cpetsc.PetscSection_py.sec`` ⟷ ``cpetsc.PetscSection`` + + For more information you will have to refer to the `petsc4py + source code `__. + +Adding more functions +~~~~~~~~~~~~~~~~~~~~~ + +Adding additional PETSc functions to petsctools is straightforward. You simply +have to add the bindings to the +`definitions file `__ +in a declarative way, just as you would write any other C file. For more +information please refer to the `Cython documentation +`__. diff --git a/pyproject.toml b/pyproject.toml index 4bc3255..3f1ad7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ [project.optional-dependencies] petsc4py = ["petsc4py"] slepc4py = ["slepc4py"] +cython = ["cython"] [project.urls] Repository = "https://github.com/firedrakeproject/petsctools" From 1ec0afe463055bd26c7cddc6cb6f53c6470753b4 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 1 Apr 2026 12:06:28 +0100 Subject: [PATCH 09/10] fixup --- docs/source/_static/cython_demo/fast.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/_static/cython_demo/fast.pyx b/docs/source/_static/cython_demo/fast.pyx index c2b3dae..fea9f2a 100644 --- a/docs/source/_static/cython_demo/fast.pyx +++ b/docs/source/_static/cython_demo/fast.pyx @@ -21,7 +21,7 @@ def medium(): def fast(): N: cython.int = int(1e8) - section: PETSc.Section = PETSc.Section().create() + section: cpetsc.PetscSection_py = PETSc.Section().create() section.setChart(0, N) start = time.time() From 928d7677967d0cf33d6b280ed4cd08350f631b78 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 1 Apr 2026 12:56:51 +0100 Subject: [PATCH 10/10] fixup --- .github/workflows/core.yml | 4 ++-- docs/source/_static/cython_demo/setup.py | 8 ++++++-- docs/source/cython.rst | 15 ++++++++++++++- pyproject.toml | 3 ++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index afd54d4..c6e20a4 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -88,7 +88,7 @@ jobs: : # upgrade pip since dependency groups were only introduced in pip 25.1 pip install -U pip - pip install --verbose ./petsctools-repo[cython] + pip install --verbose ./petsctools-repo pip install --group ./petsctools-repo/pyproject.toml:ci pip list @@ -135,7 +135,7 @@ jobs: run: | . venv-petsctools/bin/activate cd petsctools-repo/docs/source/_static/cython_demo - python setup.py build_ext --inplace + CC=mpicc python setup.py build_ext --inplace python -c "import slow" python -c "import fast" diff --git a/docs/source/_static/cython_demo/setup.py b/docs/source/_static/cython_demo/setup.py index 55b127d..ea2a8be 100644 --- a/docs/source/_static/cython_demo/setup.py +++ b/docs/source/_static/cython_demo/setup.py @@ -1,5 +1,6 @@ from setuptools import setup, Extension +import petsc4py import petsctools @@ -7,10 +8,13 @@ name="fast", language="c", sources=["fast.pyx"], - include_dirs=petsctools.get_petsc_dirs(subdir="include"), + include_dirs=[ + petsc4py.get_include(), + *petsctools.get_petsc_dirs(subdir="include"), + ], library_dirs=petsctools.get_petsc_dirs(subdir="lib"), runtime_library_dirs=petsctools.get_petsc_dirs(subdir="lib"), - libraries=["petsc"], + libraries=["petsc", "mpi"], ) setup(ext_modules=[extension]) diff --git a/docs/source/cython.rst b/docs/source/cython.rst index 140f427..63d8b0a 100644 --- a/docs/source/cython.rst +++ b/docs/source/cython.rst @@ -51,9 +51,22 @@ extension provided above looks like: This file should be added to your project along with a suitable ``pyproject.toml`` that indicates ``setuptools`` as the -``build-backend``. ``setuptools``, ``cython`` and +``build-backend``. ``setuptools``, ``cython``, ``petsc4py`` and ``petsctools`` are all necessary build-time dependencies. +.. note:: + If you encounter errors like:: + + /.../petsc/include/petscsys.h:124:12: fatal error: mpi.h: No such file or directory + 124 | #include + | ^~~~~~~ + compilation terminated. + error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1 + + then this usually means that setuptools cannot find your MPI distribution. + To fix this simply set the environment variable ``CC=mpicc`` and + try again. + Conventions used ~~~~~~~~~~~~~~~~ diff --git a/pyproject.toml b/pyproject.toml index 3f1ad7a..0f9015d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,6 @@ classifiers = [ [project.optional-dependencies] petsc4py = ["petsc4py"] slepc4py = ["slepc4py"] -cython = ["cython"] [project.urls] Repository = "https://github.com/firedrakeproject/petsctools" @@ -40,6 +39,8 @@ ci = [ {include-group = "docs"}, {include-group = "lint"}, {include-group = "test"}, + "cython", + "setuptools", ] [tool.setuptools.package-data]