• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FEniCS / ffcx / 13926142038

18 Mar 2025 02:45PM UTC coverage: 81.955% (-0.3%) from 82.23%
13926142038

push

github

web-flow
 Add void* to tabulate_tensor kernel (#753)

* add void* to tabulate_tensor

* try to trigger CI

* try to trigger CI

* run ruff

* rename user_data custom_data

* add numba functions to obtain empty void* and conversion of numpy array to void*

* fix ruff check

* add line to remove noqa

* expand comment for numba intrinsic function

* add test to use a struct in C-function similar to tabulate_tensor using void*

* changes to custom data test for CI

* specify void* branch for dolfinx test in github actions

* trying to set dolfinx refs for ffcx testing for pull request

* incorporate review suggestions

* add void* argument to test_ds_prisms

---------

Co-authored-by: Claus Susanne <sclaus@Clauss-MacBook-Pro.local>
Co-authored-by: Matthew Scroggs <matthew.w.scroggs@gmail.com>

7 of 23 new or added lines in 1 file covered. (30.43%)

3547 of 4328 relevant lines covered (81.95%)

0.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.82
/ffcx/codegeneration/utils.py
1
# Copyright (C) 2020-2024 Michal Habera, Chris Richardson and Garth N. Wells
2
#
3
# This file is part of FFCx.(https://www.fenicsproject.org)
4
#
5
# SPDX-License-Identifier:    LGPL-3.0-or-later
6
"""Utilities."""
7

8
import typing
1✔
9

10
import numpy as np
1✔
11
import numpy.typing as npt
1✔
12

13
try:
1✔
14
    import numba
1✔
NEW
15
except ImportError:
×
NEW
16
    numba = None
×
17

18

19
def dtype_to_c_type(dtype: typing.Union[npt.DTypeLike, str]) -> str:
1✔
20
    """For a NumPy dtype, return the corresponding C type.
21

22
    Args:
23
        dtype: Numpy data type,
24

25
    Returns:
26
        Corresponding C type.
27
    """
28
    # Note: Possible aliases, e.g. numpy.longdouble, should test against char ID
29
    if np.dtype(dtype).char == "g":
1✔
30
        return "long double"
×
31
    if np.dtype(dtype) == np.intc:
1✔
32
        return "int"
1✔
33
    elif np.dtype(dtype).char == "f":
1✔
34
        return "float"
1✔
35
    elif np.dtype(dtype).char == "d":
1✔
36
        return "double"
1✔
37
    elif np.dtype(dtype) == np.complex64:
1✔
38
        return "float _Complex"
1✔
39
    elif np.dtype(dtype) == np.complex128:
1✔
40
        return "double _Complex"
1✔
41
    else:
42
        raise RuntimeError(f"Unknown NumPy type for: {dtype}")
×
43

44

45
def dtype_to_scalar_dtype(dtype: typing.Union[npt.DTypeLike, str]) -> np.dtype:
1✔
46
    """For a NumPy dtype, return the corresponding real dtype.
47

48
    Args:
49
        dtype: Numpy data type
50

51
    Returns:
52
        ``numpy.dtype`` for the real component of ``dtype``.
53
    """
54
    if np.issubdtype(dtype, np.floating):
1✔
55
        return np.dtype(dtype)
1✔
56
    elif np.issubdtype(dtype, np.complexfloating):
1✔
57
        return np.dtype(dtype).type(0).real.dtype
1✔
58
    elif np.issubdtype(dtype, np.integer):
1✔
59
        return np.dtype(dtype)
1✔
60
    else:
61
        raise RuntimeError(f"Cannot get value dtype for '{dtype}'. ")
×
62

63

64
def numba_ufcx_kernel_signature(dtype: npt.DTypeLike, xdtype: npt.DTypeLike):
1✔
65
    """Return a Numba C signature for the UFCx ``tabulate_tensor`` interface.
66

67
    Args:
68
        dtype: The scalar type for the finite element data.
69
        xdtype: The geometry float type.
70

71
    Returns:
72
        A Numba signature (``numba.core.typing.templates.Signature``).
73

74
    Raises:
75
        ImportError: If ``numba`` cannot be imported.
76
    """
77
    try:
1✔
78
        import numba.types as types
1✔
79
        from numba import from_dtype
1✔
80

81
        return types.void(
1✔
82
            types.CPointer(from_dtype(dtype)),
83
            types.CPointer(from_dtype(dtype)),
84
            types.CPointer(from_dtype(dtype)),
85
            types.CPointer(from_dtype(xdtype)),
86
            types.CPointer(types.intc),
87
            types.CPointer(types.uint8),
88
            types.CPointer(types.void),
89
        )
90
    except ImportError as e:
×
91
        raise e
×
92

93

94
if numba is not None:
1✔
95

96
    @numba.extending.intrinsic
1✔
97
    def empty_void_pointer(typingctx):
1✔
98
        """Custom intrinsic to return an empty void* pointer.
99

100
        This function creates a void pointer initialized to null (0).
101
        This is used to pass a nullptr to the UFCx tabulate_tensor interface.
102

103
        Args:
104
            typingctx: The typing context.
105

106
        Returns:
107
            A Numba signature and a code generation function that returns a void pointer.
108
        """
109

NEW
110
        def codegen(context, builder, signature, args):
×
NEW
111
            null_ptr = context.get_constant(numba.types.voidptr, 0)
×
NEW
112
            return null_ptr
×
113

NEW
114
        sig = numba.types.voidptr()
×
NEW
115
        return sig, codegen
×
116

117
    @numba.extending.intrinsic
1✔
118
    def get_void_pointer(typingctx, arr):
1✔
119
        """Custom intrinsic to get a void* pointer from a NumPy array.
120

121
        This function takes a NumPy array and returns a void pointer to the array's data.
122
        This is used to pass custom data organised in a NumPy array
123
        to the UFCx tabulate_tensor interface.
124

125
        Args:
126
            typingctx: The typing context.
127
            arr: The NumPy array to get the void pointer to the first element from.
128
            In a multi-dimensional NumPy array, the memory is laid out in a contiguous
129
            block of memory, see
130
            https://numpy.org/doc/stable/reference/arrays.ndarray.html#internal-memory-layout-of-an-ndarray
131

132
        Returns:
133
            sig: A Numba signature, which specifies the numba type (here voidptr),
134
            codegen: A code generation function, which returns the LLVM IR to cast
135
            the raw data pointer to the first element of the of the contiguous block of memory
136
            of the NumPy array to void*.
137
        """
NEW
138
        if not isinstance(arr, numba.types.Array):
×
NEW
139
            raise TypeError("Expected a NumPy array")
×
140

NEW
141
        def codegen(context, builder, signature, args):
×
142
            """Generate LLVM IR code to convert a NumPy array to a void* pointer.
143

144
            This function generates the necessary LLVM IR instructions to:
145
            1. Allocate memory for the array on the stack.
146
            2. Cast the allocated memory to a void* pointer.
147

148
            Args:
149
                context: The LLVM context.
150
                builder: The LLVM IR builder.
151
                signature: The function signature.
152
                args: The input arguments (NumPy array).
153

154
            Returns:
155
                A void* pointer to the array's data.
156
            """
NEW
157
            [arr] = args
×
NEW
158
            raw_ptr = numba.core.cgutils.alloca_once_value(builder, arr)
×
NEW
159
            void_ptr = builder.bitcast(raw_ptr, context.get_value_type(numba.types.voidptr))
×
NEW
160
            return void_ptr
×
161

NEW
162
        sig = numba.types.voidptr(arr)
×
NEW
163
        return sig, codegen
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc