Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/ccpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ on:
tags:
- "v*"
pull_request:
branches:
- main
# branches:
# - main
merge_group:
branches:
- main
Expand Down Expand Up @@ -128,9 +128,15 @@ jobs:
run: cmake --build . --target test

- name: Build Python interface
run: |
pip install --check-build-dependencies --no-build-isolation --config-settings=cmake.build-type="Developer" 'python/[test]'
python -c "from mpi4py import MPI; import dolfinx; assert not dolfinx.has_petsc; assert not dolfinx.has_petsc4py; assert dolfinx.has_superlu_dist"
run: >
pip install 'python/[test]'
--check-build-dependencies
--no-build-isolation
--config-settings=cmake.build-type="Developer"
--verbose

- name: Check Python install
run: python -c "from mpi4py import MPI; import dolfinx; assert not dolfinx.has_petsc; assert not dolfinx.has_petsc4py; assert dolfinx.has_superlu_dist"

- name: Run mypy
working-directory: python
Expand Down
39 changes: 39 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,42 @@ endif()
set_target_properties(cpp PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)

install(TARGETS cpp DESTINATION dolfinx)


if (WIN32)
message("Windows..." STATUS FATAL_ERROR)
else()
nanobind_add_stub(
cpp_stub
MODULE cpp
PYTHON_PATH $<TARGET_FILE_DIR:cpp>
DEPENDS cpp
MARKER_FILE cpp/py.typed
VERBOSE
RECURSIVE
# INSTALL_TIME
# OUTPUT_PATH dolfinx
OUTPUT
cpp/fem/__init__.pyi
cpp/fem/petsc.pyi
cpp/la/__init__.pyi
cpp/la/petsc.pyi
cpp/nls/__init__.pyi
cpp/nls/petsc.pyi
cpp/__init__.pyi
cpp/common.pyi
cpp/geometry.pyi
cpp/graph.pyi
cpp/io.pyi
cpp/log.pyi
cpp/mesh.pyi
cpp/refinement.pyi
)

install(TARGETS cpp LIBRARY DESTINATION dolfinx)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cpp
DESTINATION dolfinx
FILES_MATCHING
PATTERN "*.pyi"
PATTERN "*.typed")
endif()
5 changes: 3 additions & 2 deletions python/demo/demo_lagrange_variants.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from mpi4py import MPI

import matplotlib.pylab as plt
import numpy as np

import basix
import basix.ufl
Expand Down Expand Up @@ -142,11 +143,11 @@ def saw_tooth(x):
uh.interpolate(lambda x: saw_tooth(x[0]))
if MPI.COMM_WORLD.size == 1: # Skip this plotting in parallel
pts: list[list[float]] = []
cells: list[int] = []
cells = np.empty((0,), dtype=np.int32)
for cell in range(N):
for i in range(51):
pts.append([cell / N + i / 50 / N, 0, 0])
cells.append(cell)
cells = np.append(cells, [cell])
values = uh.eval(pts, cells)
plt.plot(pts, [saw_tooth(i[0]) for i in pts], "k--")
plt.plot(pts, values, "r-")
Expand Down
21 changes: 12 additions & 9 deletions python/dolfinx/fem/bcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from __future__ import annotations

from collections.abc import Callable, Iterable
from typing import Generic, TypeVar

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -90,7 +91,10 @@ def locate_dofs_topological(
return _cpp.fem.locate_dofs_topological(_V, entity_dim, _entities, remote)


class DirichletBC:
_T = TypeVar("_T", np.float32, np.float64, np.complex64, np.complex128)


class DirichletBC(Generic[_T]):
"""Representation of Dirichlet boundary conditions.

The conditions are imposed on a linear system.
Expand Down Expand Up @@ -119,18 +123,17 @@ class initialiser. This class is combined with different
self._cpp_object = bc

@property
def g(self) -> Function | Constant | np.ndarray:
def g(self) -> Function | Constant:
"""The boundary condition value(s)."""
# TODO: needs to be wrapped into Function or Constant
return self._cpp_object.value

@property
def function_space(self) -> dolfinx.fem.FunctionSpace:
"""Function space on which the boundary condition is defined."""
return self._cpp_object.function_space

def set(
self, x: npt.NDArray, x0: npt.NDArray[np.int32] | None = None, alpha: float = 1
) -> None:
def set(self, x: npt.NDArray[_T], x0: npt.NDArray[_T] | None = None, alpha: float = 1) -> None:
"""Set array entries that are constrained by a Dirichlet condition.

Entries in ``x`` that are constrained by a Dirichlet boundary
Expand Down Expand Up @@ -171,10 +174,10 @@ def dof_indices(self) -> tuple[npt.NDArray[np.int32], int]:


def dirichletbc(
value: Function | Constant | np.ndarray | float | complex,
value: Function | Constant | npt.NDArray[_T] | float | complex,
dofs: npt.NDArray[np.int32],
V: dolfinx.fem.FunctionSpace | None = None,
) -> DirichletBC:
) -> DirichletBC[_T]:
"""Representation of Dirichlet boundary condition.

Args:
Expand Down Expand Up @@ -231,8 +234,8 @@ def dirichletbc(


def bcs_by_block(
spaces: Iterable[FunctionSpace | None], bcs: Iterable[DirichletBC]
) -> list[list[DirichletBC]]:
spaces: Iterable[FunctionSpace | None], bcs: Iterable[DirichletBC[_T]]
) -> list[list[DirichletBC[_T]]]:
"""Arrange boundary conditions by the space that they constrain.

Given a sequence of function spaces ``spaces`` and a sequence of
Expand Down
33 changes: 14 additions & 19 deletions python/dolfinx/fem/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""Finite elements."""

from functools import singledispatch
from typing import Generic, TypeVar

import numpy as np
import numpy.typing as npt
Expand All @@ -14,8 +15,10 @@
import basix.ufl
from dolfinx import cpp as _cpp

_T = TypeVar("_T", np.float32, np.float64)

class CoordinateElement:

class CoordinateElement(Generic[_T]):
"""Coordinate element describing the geometry map for mesh cells."""

_cpp_object: _cpp.fem.CoordinateElement_float32 | _cpp.fem.CoordinateElement_float64
Expand Down Expand Up @@ -60,11 +63,7 @@ def create_dof_layout(self) -> _cpp.fem.ElementDofLayout:
"""Compute and return the dof layout."""
return self._cpp_object.create_dof_layout()

def push_forward(
self,
X: npt.NDArray[np.float32] | npt.NDArray[np.float64],
cell_geometry: npt.NDArray[np.float32] | npt.NDArray[np.float64],
) -> npt.NDArray[np.float32] | npt.NDArray[np.float64]:
def push_forward(self, X: npt.NDArray[_T], cell_geometry: npt.NDArray[_T]) -> npt.NDArray[_T]:
"""Push points on the reference cell forward to the physical cell.

Args:
Expand All @@ -80,11 +79,7 @@ def push_forward(
"""
return self._cpp_object.push_forward(X, cell_geometry)

def pull_back(
self,
x: npt.NDArray[np.float32] | npt.NDArray[np.float64],
cell_geometry: npt.NDArray[np.float32] | npt.NDArray[np.float64],
) -> npt.NDArray[np.float32] | npt.NDArray[np.float64]:
def pull_back(self, x: npt.NDArray[_T], cell_geometry: npt.NDArray[_T]) -> npt.NDArray[_T]:
"""Pull points on the physical cell back to the reference cell.

For non-affine cells, the pull-back is a nonlinear operation.
Expand Down Expand Up @@ -124,7 +119,7 @@ def coordinate_element(
degree: int,
variant=int(basix.LagrangeVariant.unset),
dtype: npt.DTypeLike = np.float64,
):
) -> CoordinateElement:
"""Create a Lagrange CoordinateElement from element metadata.

Coordinate elements are typically used to create meshes.
Expand All @@ -147,7 +142,7 @@ def coordinate_element(


@coordinate_element.register(basix.finite_element.FiniteElement)
def _(e: basix.finite_element.FiniteElement):
def _(e: basix.finite_element.FiniteElement) -> CoordinateElement:
"""Create a Lagrange CoordinateElement from a Basix finite element.

Coordinate elements are typically used when creating meshes.
Expand All @@ -164,7 +159,7 @@ def _(e: basix.finite_element.FiniteElement):
return CoordinateElement(_cpp.fem.CoordinateElement_float64(e._e))


class FiniteElement:
class FiniteElement(Generic[_T]):
"""A finite element."""

_cpp_object: _cpp.fem.FiniteElement_float32 | _cpp.fem.FiniteElement_float64
Expand Down Expand Up @@ -218,7 +213,7 @@ def value_shape(self) -> npt.NDArray[np.integer]:
return self._cpp_object.value_shape

@property
def interpolation_points(self) -> npt.NDArray[np.floating]:
def interpolation_points(self) -> npt.NDArray[_T]:
"""Points at which to evaluate the function to be interpolated.

Interpolation point coordinates on the reference cell, returning
Expand Down Expand Up @@ -276,7 +271,7 @@ def signature(self) -> str:
return self._cpp_object.signature

def T_apply(
self, x: npt.NDArray[np.floating], cell_permutations: npt.NDArray[np.uint32], dim: int
self, x: npt.NDArray[_T], cell_permutations: npt.NDArray[np.uint32], dim: int
) -> None:
"""Transform basis from reference to physical ordering/orientation.

Expand All @@ -299,7 +294,7 @@ def T_apply(
self._cpp_object.T_apply(x, cell_permutations, dim)

def Tt_apply(
self, x: npt.NDArray[np.floating], cell_permutations: npt.NDArray[np.uint32], dim: int
self, x: npt.NDArray[_T], cell_permutations: npt.NDArray[np.uint32], dim: int
) -> None:
"""Apply the transpose of the operator applied by T_apply().

Expand All @@ -313,7 +308,7 @@ def Tt_apply(
self._cpp_object.Tt_apply(x, cell_permutations, dim)

def Tt_inv_apply(
self, x: npt.NDArray[np.floating], cell_permutations: npt.NDArray[np.uint32], dim: int
self, x: npt.NDArray[_T], cell_permutations: npt.NDArray[np.uint32], dim: int
) -> None:
"""Apply the inverse transpose of T_apply().

Expand All @@ -330,7 +325,7 @@ def Tt_inv_apply(
def finiteelement(
cell_type: _cpp.mesh.CellType,
ufl_e: basix.ufl._ElementBase,
FiniteElement_dtype: np.dtype,
FiniteElement_dtype: npt.DTypeLike,
) -> FiniteElement:
"""Create a DOLFINx element from a basix.ufl element.

Expand Down
4 changes: 3 additions & 1 deletion python/dolfinx/fem/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
from dolfinx.mesh import EntityMap as _EntityMap
from dolfinx.mesh import Mesh, MeshTags

_S = typing.TypeVar("_S", np.float32, np.float64, np.complex64, np.complex128) # scalar

class Form:

class Form(typing.Generic[_S]):
"""A finite element form."""

_cpp_object: (
Expand Down
Loading
Loading