Repository navigation
pyop3 - #3318
Merged
Merged
pyop3#3318
Conversation
- bddc.py: dof_dset no longer exists on FunctionSpace; use the new V.lgmap()/V.template_vec accessors instead of V.dof_dset.lgmap and V.dof_dset.layout_vec. - fdm.py broken_function(): op2 is no longer imported in this file (only pyop3), switch to READ/WRITE from firedrake.parloops. Also fix the manual loopy kernel to use 2D (dof, component) indexing, which par_loop now requires unconditionally, and pass dtype=val.dtype to Function() since make_dat now asserts on dtype mismatches (this function is routinely called with integer index/lgmap arrays). - Re-enable tests/firedrake/regression/test_bddc.py (was fully module-skipped with "pyop3 TODO"). Verified serially: BDDCPC solves, test_create_matis (4/4), test_vertex_dofs (8/8 @ nprocs=3), test_bddc_cellwise_fdm (12/12 @ nprocs=1, including condense=True since that config uses fdm_pc_use_amat=False and so never reaches FDMPC.condense()). Still broken/out of scope of this commit: - FDMPC.condense() (matrix-free static condensation, fdm_pc_use_amat=True) was never ported to pyop3 and still raises NotImplementedError. - assemble(..., mat_type="is") + DirichletBC fails in parallel (nprocs>1) with "Matrix is missing diagonal entry" from MatZeroRowsColumnsLocal. This is a core assemble.py bug unrelated to preconditioners.
* Do not bind MPI jobs so full utilisation achieved - don't run jobs on the same cores * Try to kill subprocesses upon SIGINT * Don't error if errcode files don't exist
Assembly is not automatically flushed.
Uncovered a serious and subtle parallel bug.
The previous method didn't work for restricted function spaces.
Needed to fix mixed field_ises and local_ises as they were putting the restricted DoFs in the wrong place. Same fix needed for _restricted_section (which is a sucky hack).
Need to adopt a singleton pattern for frozenrecords because I spawn so many of them. Currently cleaning up the record_setup/record_id bits.
* Only check for equivalence if debug checks are enabled * Fast determination of slice vs index array
* Avoid using ISes as they are much slower than numpy arrays * Use Axis.as_tree() to take advantage of caching
dham
previously approved these changes
Oct 20, 2026
Contributor
|
@connorjward this is what Claude Code came up with for the pyop3 memory growth in #5534: #5538 |
* Have to skip a UID test. I cannot solve it for the life of me and my machine has somehow STOPPED reproducing it. * Avoid caching issue with loopy translation units.
connorjward
commented
Oct 21, 2026
connorjward
commented
Oct 21, 2026
connorjward
commented
Oct 21, 2026
connorjward
commented
Oct 21, 2026
Co-authored-by: Connor Ward <c.ward20@imperial.ac.uk>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR entirely replaces PyOP2 with pyop3. It represents the culmination of 5 years of work.
Motivation
The Firedrake team is in the business of designing software abstractions. For many years now it has been clear that the design of PyOP2 isn't quite right. In PyOP2's view of the world there is no such thing as a mesh (or anything that looks remotely like one) and whole bunch of assumptions are baked right into the abstraction: no loop nesting allowed, no (proper) map composition allowed, only specific types of indirection maps are permitted, that are near impossible to work around once encountered. pyop3 is a fundamental and complete rewrite of PyOP2 to address all of these issues.
pyop3 can be thought of as 2 major pieces:
This is very abstract and so I like to describe pyop3 in an alternative way: pyop3 is like numpy but for unstructured mesh data.
To learn more about pyop3 my thesis is the canonical reference.
Benefits
Replacing PyOP2 with pyop3 will enable a broad swathe of new research to occur because some operations should now become so much easier to express and experiment with. A non-exhaustive list may be found here.
In addition to enabling lots of new technologies, another very significant benefit to integrating pyop3 is the reduction in technical debt and code complexity. Many complex pieces of preexisting Firedrake code have been simplified and/or centralised into very few functions. For example, extruded meshes are now just the same as regular meshes. These changes reduce special-casing throughout Firedrake, making everything more composable!
Further, the current work on GPU support in Firedrake and FUSE both depend on pyop3.
Key changes
PyOP2 is gone
Obviously. Anywhere that you explicitly use the PyOP2 API (i.e.
from pyop2 import op2) will have to be replaced with pyop3 (import pyop3 as op3). If you use PyOP2 indirectly (e.g.function.dat.data,mesh.cell_set,V.dof_dset) then some things will be expected to work (e.g.function.dat.data) but others have no equivalent pyop3 object and thus no longer exist.Extruded meshes are now DMPlexs
Extruded meshes are now fully fledged PETSc DMPlex objects, instead of hybrid objects where only Firedrake knew about the extrusion. This simplifies an awful lot of code and will enable things like submeshing extruded meshes.
Breaking API changes
mesh.interior_facetsandmesh.exterior_facetsare nowAxisTrees, not_FacetsInstead of
mesh.exterior_facets.unique_markersandmesh.interior_facets.unique_markersyou should usemesh.facet_markers.Other attributes of
_Facetsare also available via the mesh with new names.function_space.cell_node_mapis now a pyop3Mapinstead of a PyOP2 oneThis means that it will not work as expected. In particular
V.cell_node_map()will now raise an error because pyop3 maps expect arguments.It is common practice for downstream packages to inspect
function_space.cell_node_map().values. Instead you should simply dofunction_space.cell_node_list.Support for variable layer extruded meshes is dropped
The functionality appeared not to be used by the community (e.g. thetisproject/thetis#405) and porting the functionality would have been a large amount of work. Eventually the functionality will be recoverable via
Submesh.API deprecations
.sub()expects a tuple instead of integer for tensor spaces.For example, to get the
(1, 1)component of a 2x2 tensor function space one should now passf.sub((1, 1))instead off.sub(3). The latter will continue to work for now but a warning is raised.ASMExtrudedStarPCis being deprecatedNow that extruded meshes are just meshes, you should just use
ASMStarPC. To manage the fact that until nowASMStarPCon an extruded mesh would give column patches, a newcolumnoption has been added.Known issues
There are a number of things that are known to be currently broken with pyop3 and we hope to fix them in due course.
ASMExtrudedStarPCdoes not work in 3D (see https://gitlab.com/petsc/petsc/-/work_items/1946)Disabled tests
The tests that are disabled in this PR and that will need subsequent fixing are:
regression/test_moore_spence.py(in complex mode)regression/test_bddc.pyregression/test_fdm.py(only some)regression/test_assemble.py::test_matis(only some)regression/test_mass_lumping.py(4D extrusion test case)regression/test_adjoint_operators.py::test_init_constant_diff_meshexternal_operators/test_jax_operator.py::test_mixed_space_bcsexternal_operators/test_pytorch_operator.py::test_mixed_space_bcs