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

FEniCS / ufl / 18629405325

19 Oct 2025 10:56AM UTC coverage: 77.06% (+0.4%) from 76.622%
18629405325

Pull #401

github

schnellerhase
Ruff
Pull Request #401: Removal of custom type system

494 of 533 new or added lines in 41 files covered. (92.68%)

6 existing lines in 2 files now uncovered.

9325 of 12101 relevant lines covered (77.06%)

0.77 hits per line

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

91.82
/ufl/coefficient.py
1
"""This module defines the Coefficient class and a number of related classes, including Constant."""
2

3
# Copyright (C) 2008-2016 Martin Sandve Alnæs
4
#
5
# This file is part of UFL (https://www.fenicsproject.org)
6
#
7
# SPDX-License-Identifier:    LGPL-3.0-or-later
8
#
9
# Modified by Anders Logg, 2008-2009.
10
# Modified by Massimiliano Leoni, 2016.
11
# Modified by Cecile Daversin-Catty, 2018.
12
# Modified by Ignacia Fierro-Piccardo 2023.
13

14
from ufl.argument import Argument
1✔
15
from ufl.core.compute_expr_hash import compute_expr_hash
1✔
16
from ufl.core.terminal import FormArgument
1✔
17
from ufl.core.ufl_type import UFLType, ufl_type
1✔
18
from ufl.duals import is_dual, is_primal
1✔
19
from ufl.form import BaseForm
1✔
20
from ufl.functionspace import AbstractFunctionSpace, MixedFunctionSpace
1✔
21
from ufl.split_functions import split
1✔
22
from ufl.utils.counted import Counted
1✔
23

24
# --- The Coefficient class represents a coefficient in a form ---
25

26

27
class BaseCoefficient(UFLType, Counted):
1✔
28
    """UFL form argument type: Parent Representation of a form coefficient."""
29

30
    # Slots are disabled here because they cause trouble in PyDOLFIN
31
    # multiple inheritance pattern:
32
    # __slots__ = ("_count", "_ufl_function_space", "_repr", "_ufl_shape")
33
    _ufl_noslots_ = True
1✔
34
    __slots__ = ()
1✔
35

36
    def __getnewargs__(self):
1✔
37
        """Get new args."""
38
        return (self._ufl_function_space, self._count)
1✔
39

40
    def __init__(self, function_space, count=None):
1✔
41
        """Initalise."""
42
        Counted.__init__(self, count, Coefficient)
1✔
43

44
        if not isinstance(function_space, AbstractFunctionSpace):
1✔
45
            raise ValueError("Expecting a FunctionSpace.")
×
46

47
        self._ufl_function_space = function_space
1✔
48
        self._ufl_shape = function_space.value_shape
1✔
49

50
        self._repr = f"BaseCoefficient({self._ufl_function_space!r}, {self._count!r})"
1✔
51

52
    @property
1✔
53
    def ufl_shape(self):
1✔
54
        """Return the associated UFL shape."""
55
        return self._ufl_shape
1✔
56

57
    def ufl_function_space(self):
1✔
58
        """Get the function space of this coefficient."""
59
        return self._ufl_function_space
1✔
60

61
    def ufl_domain(self):
1✔
62
        """Shortcut to get the domain of the function space of this coefficient."""
63
        return self._ufl_function_space.ufl_domain()
×
64

65
    def ufl_element(self):
1✔
66
        """Shortcut to get the finite element of the function space of this coefficient."""
67
        return self._ufl_function_space.ufl_element()
1✔
68

69
    def is_cellwise_constant(self):
1✔
70
        """Return whether this expression is spatially constant over each cell."""
71
        return self.ufl_element().is_cellwise_constant()
1✔
72

73
    def ufl_domains(self):
1✔
74
        """Return tuple of domains related to this terminal object."""
75
        return self._ufl_function_space.ufl_domains()
1✔
76

77
    def _ufl_signature_data_(self, renumbering):
1✔
78
        """Signature data.
79

80
        Signature data for form arguments depend on the global numbering
81
        of the form arguments and domains.
82
        """
83
        count = renumbering[self]
1✔
84
        fsdata = self._ufl_function_space._ufl_signature_data_(renumbering)
1✔
85
        return ("Coefficient", count, fsdata)
1✔
86

87
    def __str__(self):
1✔
88
        """Format as a string."""
89
        return f"w_{self._count}"
1✔
90

91
    def __repr__(self):
1✔
92
        """Representation."""
93
        return self._repr
1✔
94

95
    def __eq__(self, other):
1✔
96
        """Check equality."""
97
        if not isinstance(other, BaseCoefficient):
×
98
            return False
×
99
        if self is other:
×
100
            return True
×
101
        return self._count == other._count and self._ufl_function_space == other._ufl_function_space
×
102

103
    def __hash__(self):
1✔
104
        """Return hash."""
NEW
105
        return compute_expr_hash(self)
×
106

107

108
@ufl_type()
1✔
109
class Cofunction(BaseCoefficient, BaseForm):
1✔
110
    """UFL form argument type: Representation of a form coefficient from a dual space."""
111

112
    __slots__ = (
1✔
113
        "_arguments",
114
        "_coefficients",
115
        "_count",
116
        "_counted_class",
117
        "_hash",
118
        "_repr",
119
        "_ufl_function_space",
120
        "_ufl_shape",
121
        "ufl_operands",
122
    )
123
    _primal = False
1✔
124
    _dual = True
1✔
125
    _ufl_is_terminal_ = True
1✔
126

127
    __eq__ = BaseForm.__eq__
1✔
128

129
    def __new__(cls, *args, **kw):
1✔
130
        """Create a new Cofunction."""
131
        if args[0] and is_primal(args[0]):
1✔
132
            raise ValueError(
1✔
133
                "ufl.Cofunction takes in a dual space. If you want to define a coefficient "
134
                "in the primal space you should use ufl.Coefficient."
135
            )
136
        return super().__new__(cls)
1✔
137

138
    def __init__(self, function_space, count=None):
1✔
139
        """Initialise."""
140
        BaseCoefficient.__init__(self, function_space, count)
1✔
141
        BaseForm.__init__(self)
1✔
142

143
        self.ufl_operands = ()
1✔
144
        self._hash = None
1✔
145
        self._repr = f"Cofunction({self._ufl_function_space!r}, {self._count!r})"
1✔
146

147
    def equals(self, other):
1✔
148
        """Check equality."""
149
        if type(other) is not Cofunction:
1✔
150
            return False
1✔
151
        if self is other:
1✔
152
            return True
1✔
153
        return self._count == other._count and self._ufl_function_space == other._ufl_function_space
1✔
154

155
    def __hash__(self):
1✔
156
        """Hash."""
157
        return hash(("Cofunction", hash(self._ufl_function_space), self._count))
1✔
158

159
    def _analyze_form_arguments(self):
1✔
160
        """Analyze which Argument and Coefficient objects can be found in the form."""
161
        # Define canonical numbering of arguments and coefficients
162
        # Cofunctions have one argument in primal space as they map from V to R.
163
        self._arguments = (Argument(self._ufl_function_space.dual(), 0),)
1✔
164
        self._coefficients = (self,)
1✔
165

166

167
@ufl_type()
1✔
168
class Coefficient(FormArgument, BaseCoefficient):
1✔
169
    """UFL form argument type: Representation of a form coefficient."""
170

171
    _ufl_noslots_ = True
1✔
172
    _primal = True
1✔
173
    _dual = False
1✔
174

175
    __getnewargs__ = BaseCoefficient.__getnewargs__
1✔
176
    __str__ = BaseCoefficient.__str__
1✔
177
    _ufl_signature_data_ = BaseCoefficient._ufl_signature_data_
1✔
178

179
    def __new__(cls, *args, **kw):
1✔
180
        """Create a new Coefficient."""
181
        if args[0] and is_dual(args[0]):
1✔
182
            return Cofunction(*args, **kw)
1✔
183
        return super().__new__(cls)
1✔
184

185
    def __init__(self, function_space, count=None):
1✔
186
        """Initialise."""
187
        FormArgument.__init__(self)
1✔
188
        BaseCoefficient.__init__(self, function_space, count)
1✔
189

190
        self._repr = f"Coefficient({self._ufl_function_space!r}, {self._count!r})"
1✔
191

192
    def ufl_domains(self):
1✔
193
        """Get the UFL domains."""
194
        return BaseCoefficient.ufl_domains(self)
1✔
195

196
    def __eq__(self, other):
1✔
197
        """Check equality."""
198
        if not isinstance(other, Coefficient):
1✔
199
            return False
1✔
200
        if self is other:
1✔
201
            return True
1✔
202
        return self._count == other._count and self._ufl_function_space == other._ufl_function_space
1✔
203

204
    def __hash__(self):
1✔
205
        """Return hash."""
206
        return compute_expr_hash(self)
1✔
207

208
    def __repr__(self):
1✔
209
        """Representation."""
210
        return self._repr
1✔
211

212

213
# --- Helper functions for subfunctions on mixed elements ---
214

215

216
def Coefficients(function_space):
1✔
217
    """Create a Coefficient in a mixed space.
218

219
    Returns a tuple with the function components corresponding to the subelements.
220
    """
221
    if isinstance(function_space, MixedFunctionSpace):
1✔
222
        return [
×
223
            Coefficient(fs) if is_primal(fs) else Cofunction(fs)
224
            for fs in function_space.num_sub_spaces()
225
        ]
226
    else:
227
        return split(Coefficient(function_space))
1✔
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

© 2025 Coveralls, Inc