Skip to content

Replace scifem.compat and scifem.ufl_compat with fenicsx-compat - #267

Open
finsberg wants to merge 10 commits into
mainfrom
finsberg/fenicsx-compat
Open

finsberg wants to merge 10 commits into
mainfrom
finsberg/fenicsx-compat

Conversation

@finsberg

Copy link
Copy Markdown
Member

All cross-version DOLFINx workarounds now come from fenicsx-compat (>=0.2.0), which centralises them for scifem, io4dolfinx and dolfinx-adjoint. scifem keeps no compat layer of its own:

  • scifem.compat and scifem.ufl_compat are removed, along with compat in scifem.all and their API reference section. Their callers use the fenicsx_compat equivalents.
  • Inline duplicates of fenicsx-compat functions are replaced too: facet quadrature permutations, Expression.eval entity shapes, interpolate_f, Expression entity_maps, index map creation and unwrapping, MeshTags.topology, create_sub_index_map, local_range, the gmsh model_to_mesh ghost mode, the ADIOS2 scope and the PETSc lifting helpers.
  • Branches that cannot run on DOLFINx >= 0.10, the floor fenicsx-compat sets, become plain DOLFINx calls: compute_integration_domains, the cpp Topology constructor, pack_constants/pack_coefficients, determine_point_ownership, the *_block PETSc API, and the 0.8/0.9 paths in point_source.py and solvers.py.
  • NewtonSolver arranges its boundary conditions with fenicsx_compat.bcs_by_block, as dolfinx.fem.bcs_by_block cannot be called directly across 0.11 and 0.12 (dolfinx#4342).
  • scifem.petsc.apply_lifting_and_set_bc keeps its single-form calling convention, [form] with [bcs], and passes the form and its boundary conditions on to fenicsx-compat.

The minimum Python version goes from 3.10 to 3.12, as fenicsx-compat requires it, and packaging moves from the runtime dependencies to the test extra, as only the tests still use it.

finsberg and others added 2 commits October 12, 2026 12:17
All cross-version DOLFINx workarounds now come from fenicsx-compat
(>=0.2.0), which centralises them for scifem, io4dolfinx and
dolfinx-adjoint. scifem keeps no compat layer of its own:

- scifem.compat and scifem.ufl_compat are removed, along with
  `compat` in scifem.__all__ and their API reference section. Their
  callers use the fenicsx_compat equivalents.
- Inline duplicates of fenicsx-compat functions are replaced too:
  facet quadrature permutations, Expression.eval entity shapes,
  interpolate_f, Expression entity_maps, index map creation and
  unwrapping, MeshTags.topology, create_sub_index_map, local_range,
  the gmsh model_to_mesh ghost mode, the ADIOS2 scope and the PETSc
  lifting helpers.
- Branches that cannot run on DOLFINx >= 0.10, the floor fenicsx-compat
  sets, become plain DOLFINx calls: compute_integration_domains, the
  cpp Topology constructor, pack_constants/pack_coefficients,
  determine_point_ownership, the *_block PETSc API, and the 0.8/0.9
  paths in point_source.py and solvers.py.
- NewtonSolver arranges its boundary conditions with
  fenicsx_compat.bcs_by_block, as dolfinx.fem.bcs_by_block cannot be
  called directly across 0.11 and 0.12 (dolfinx#4342).
- scifem.petsc.apply_lifting_and_set_bc keeps its single-form calling
  convention, `[form]` with `[bcs]`, and passes the form and its
  boundary conditions on to fenicsx-compat.

The minimum Python version goes from 3.10 to 3.12, as fenicsx-compat
requires it, and `packaging` moves from the runtime dependencies to the
test extra, as only the tests still use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@finsberg
finsberg marked this pull request as ready for review October 12, 2026 19:11
@finsberg
finsberg requested a review from jorgensd October 12, 2026 19:11
@jorgensd

Copy link
Copy Markdown
Member

Do we really want the compat package to depend on PETSc? If we do I think we should aim to make scifem PETSc free over time :)

@finsberg

Copy link
Copy Markdown
Member Author

Do we really want the compat package to depend on PETSc? If we do I think we should aim to make scifem PETSc free over time :)

No, it should not depend strictly on PETSc. Right now it is guarded by an if dolfinx.has_petsc4py , but perhaps we should add a test suite that tests this on dolfinx built without PETSc?

Comment thread src/scifem/periodic/gmsh.py Outdated
Comment thread src/scifem/periodic/gmsh.py Outdated
else:
pairs = PeriodicNodes(0)
mesh_data = model_to_mesh(
mesh = model_to_mesh(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How is this correct?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This was because the helper function (model_to_mesh) inside periodic/gmsh.py returned only the mesh, but this is very confusing with two functions with the same name. Fixed in d6e76e9

Comment thread src/scifem/periodic/mesh.py Outdated
Comment thread src/scifem/periodic/mesh.py Outdated
Comment on lines +382 to +383
ghosting_ranks = np.asarray(ghosting_ranks, dtype=np.int32)
ghosting_offsets = np.asarray(ghosting_offsets, dtype=np.int64)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't this wrapping be done inside fenicsx_compat?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agree! Fixed in 3156f3f

Comment on lines +1323 to +1327
topology = dolfinx.cpp.mesh.Topology(
mesh.topology.cell_type,
mesh.topology.dim,
new_vertex_map,
new_cell_map,
new_c_to_v,
new_v_to_v,
unwrap_index_map(new_vertex_map),
unwrap_index_map(new_cell_map),
new_c_to_v._cpp_object, # type: ignore[arg-type]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't we want a compat topology wrapper here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't know. I think we shouldn't add more compat functions than needed, but if you have strong feelings for adding it we can.

Comment thread src/scifem/geometry.py Outdated
Comment thread src/scifem/mesh.py
if hasattr(dolfinx.mesh, "transfer_meshtags_to_submesh"):
new_et = dolfinx.mesh.transfer_meshtags_to_submesh(
entity_tag, submesh, vertex_to_parent=vertex_map, cell_to_parent=cell_map
try:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems a bit silly to here have a compat function that refers back to the scifem implementation.
Is the reason not for moving it the fact that it requires C++ building, which you have avoided so far in fenicsx_compat?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Totally agree. Perhaps we should just move the whole extract_submesh function to fenicsx-compat, or what do you think?

Comment thread src/scifem/point_source.py Outdated
src_ranks = collision_data.src_owner
else:
raise NotImplementedError(f"Unsupported version of dolfinx: {dolfinx.__version__}")
collision_data = dolfinx.geometry.determine_point_ownership(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is simplified as we support only 0.10 and ownards?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, that is the reason. Are you OK with dropping support for < 0.10?

Comment thread src/scifem/solvers.py
self.x = dolfinx.fem.petsc.create_vector(
dolfinx.fem.extract_function_spaces(self._F), kind="mpi"
)
self.b = dolfinx.fem.petsc.create_vector(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here, is this due to the fact that we now only support 0.10 and onwards?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Exactly

submesh_facets = np.arange(num_facets, dtype=np.int32)
parent_facets = scifem.mesh.get_entity_map(entity_map)[:num_facets]
entities = scifem.compat.compute_integration_domains(
entities = dolfinx.fem.compute_integration_domains(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Dropped because version support is 0.10?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes

@jorgensd jorgensd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some minor things to clarify

finsberg and others added 8 commits October 21, 2026 17:25
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
The wrapper shared its name with dolfinx.io.gmsh.model_to_mesh and
fenicsx_compat.model_to_mesh but, unlike them, returned the mesh rather
than the MeshData. Since this branch it only forwarded to
fenicsx_compat.model_to_mesh, whose defaults (shared_facet ghosting,
max_facet_to_cell_links=2) are the same, so read_periodic_mesh_from_msh
and the tests call that directly and take `.mesh` themselves.

This removes a public function that shipped in v0.26.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
Co-authored-by: Jørgen Schartum Dokken <dokken92@gmail.com>
With a typed DOLFINx installed (0.12.0.dev0), mypy reported 96 errors
in src and tests; the pre-commit hook runs without DOLFINx, so they
never showed there. None changes behaviour:

- Wrong annotations are corrected: NewtonSolver's _F and _J hold a list
  and a list of lists of forms, entity_maps is a sequence of EntityMap
  from DOLFINx 0.10 on, the _EntityMap protocol's members are read-only
  properties, and create_space_of_simple_functions' value_shape is a
  tuple of ints.
- typing.cast where the type is known but not to the stubs, chiefly
  ufl.domain.extract_domains, typed AbstractDomain but a ufl.Mesh here.
- A narrow `# type: ignore[<code>]` with its reason where a stub is
  wrong and the code right: the float32/float64 cpp class picked at
  runtime, a blocked x0 in apply_lifting, numpy index arrays passed to
  petsc4py, and compiled forms passed through dolfinx.fem.form.
- PeriodicNodes(0) becomes PeriodicNodes(): the 0 went into the
  `replaced` array, not num_nodes_global. Harmless, as that branch runs
  only on ranks that never read either.
- KSP.create takes the vector's PETSc communicator directly rather than
  its mpi4py conversion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@finsberg
finsberg added this pull request to stack #270 October 21, 2026 19:38
@finsberg
finsberg removed this pull request from stack #270 October 21, 2026 19:40

This branch has not been deployed

No deployments
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