Skip to content

Add Cython bindings for the PETSc API#30

Merged
connorjward merged 11 commits intomainfrom
connorjward/cpetsc
Apr 2, 2026
Merged

Add Cython bindings for the PETSc API#30
connorjward merged 11 commits intomainfrom
connorjward/cpetsc

Conversation

@connorjward
Copy link
Copy Markdown
Collaborator

@connorjward connorjward commented Nov 24, 2025

The ultimate aim is to move this file out of Firedrake and make it more widely available.

Why is this useful?

It can be useful to be able to access the C API of PETSc directly (instead of going through petsc4py) in cases where we need to call a function many many times (e.g. inside a loop that is the size of the mesh). I wrote a little demo that shows this:

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()

vs

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)  # small amount of Python
    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))  # entirely C
    print(f"Time elapsed: {time.time() - start}")


medium()
fast()

The former takes 4.0s and the latter takes 1.8s and 0.78s each. The differences are admittedly much smaller than expected but still significant enough to care about.

But petsc4py have Cython headers too, why aren't those sufficient?

Basically 2 reasons:

  • petsc4py is really complex and does not expose this information very clearly. By comparison what I have here is extremely straightforward to read and extend.
  • They make some confusing choices regarding naming. For example the type representing a C Mat is called a PetscMat so all of the C API signatures look a bit odd. Here everything matches exactly, and a petsc4py Python Mat is called Mat_py.
  • They use the older .pxi format (example) which literal-includes the text instead of importing via .pxd.

@connorjward connorjward marked this pull request as ready for review April 1, 2026 10:57
@connorjward connorjward requested a review from JHopeCollins April 1, 2026 10:58
Comment thread .github/workflows/core.yml
@JHopeCollins
Copy link
Copy Markdown
Member

Looks like the cython build isn't finding the mpi compiler wrapper

@connorjward
Copy link
Copy Markdown
Collaborator Author

Looks like the cython build isn't finding the mpi compiler wrapper

Yeah. It passes locally which is strange. I'm investigating.

@connorjward
Copy link
Copy Markdown
Collaborator Author

All fixed now.

Copy link
Copy Markdown
Member

@JHopeCollins JHopeCollins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some naming questions if you're trying to be more consistent

Comment thread petsctools/cpetsc.pxd
Comment thread petsctools/cpetsc.pxd
@connorjward connorjward merged commit 36a830a into main Apr 2, 2026
2 checks 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.

2 participants