1- // Copyright (C) 2020-2021 Jack S. Hale and Michal Habera.
1+ // Copyright (C) 2020-2025 Jack S. Hale, Michal Habera and Garth N. Wells
22//
33// This file is part of DOLFINx (https://www.fenicsproject.org)
44//
88
99#include " Constant.h"
1010#include " Function.h"
11- #include " pack.h"
12- #include " utils.h"
1311#include < algorithm>
1412#include < array>
1513#include < concepts>
1614#include < dolfinx/common/types.h>
1715#include < dolfinx/mesh/Mesh.h>
1816#include < functional>
17+ #include < memory>
1918#include < span>
2019#include < utility>
2120#include < vector>
2221
2322namespace dolfinx ::fem
2423{
25- // / @brief Represents a mathematical expression evaluated at a
26- // / pre-defined set of points on the reference cell.
24+ template <dolfinx::scalar T, std::floating_point U>
25+ class Function ;
26+
27+ // / @brief An Expression represents a mathematical expression evaluated
28+ // / at a pre-defined points on a reference cell.
2729// /
28- // // This class closely follows the concept of a UFC Expression .
30+ // / An Expression can be evaluated using ::tabulate_expression .
2931// /
30- // / The functionality can be used to evaluate a gradient of a Function
31- // / at quadrature points in all cells. This evaluated gradient can then
32- // / be used as input in to a non-FEniCS function that calculates a
32+ // / An example of Expression use is to evaluate the gradient of a
33+ // / Function at quadrature points in cells. The evaluated gradient can
34+ // / then be used as input in to a non-FEniCS function that evaluates a
3335// / material constitutive model.
3436// /
35- // / @tparam T The scalar type
36- // / @tparam U The mesh geometry scalar type
37+ // / @tparam T The scalar type.
38+ // / @tparam U The mesh geometry scalar type.
3739template <dolfinx::scalar T,
3840 std::floating_point U = dolfinx::scalar_value_type_t <T>>
3941class Expression
@@ -50,18 +52,21 @@ class Expression
5052
5153 // / @brief Create an Expression.
5254 // /
53- // / @note Users should prefer the @ref create_expression factory
54- // / functions.
55+ // / @note Users should prefer the fem:: create_expression factory
56+ // / functions for creating an Expression .
5557 // /
5658 // / @param[in] coefficients Coefficients in the Expression.
57- // / @param[in] constants Constants in the Expression
59+ // / @param[in] constants Constants in the Expression.
5860 // / @param[in] X Points on the reference cell, `shape=(number of
5961 // / points, tdim)` and storage is row-major.
6062 // / @param[in] Xshape Shape of `X`.
6163 // / @param[in] fn Function for tabulating the Expression.
6264 // / @param[in] value_shape Shape of Expression evaluated at single
6365 // / point.
64- // / @param[in] argument_function_space Function space for Argument.
66+ // / @param[in] argument_space Function space for Argument. Used to
67+ // / computed a 1-form expression, e.g. can be used to create a matrix
68+ // / that when applied to a degree-of-freedom vector gives the
69+ // / expression values at the evaluation points.
6570 Expression (
6671 const std::vector<std::shared_ptr<
6772 const Function<scalar_type, geometry_type>>>& coefficients,
@@ -72,13 +77,11 @@ class Expression
7277 const geometry_type*, const int *, const uint8_t *, void *)>
7378 fn,
7479 const std::vector<std::size_t >& value_shape,
75- std::shared_ptr<const FunctionSpace<geometry_type>>
76- argument_function_space
80+ std::shared_ptr<const FunctionSpace<geometry_type>> argument_space
7781 = nullptr )
7882 : _coefficients(coefficients), _constants(constants),
7983 _x_ref (std::vector<geometry_type>(X.begin(), X.end()), Xshape), _fn(fn),
80- _value_shape(value_shape),
81- _argument_function_space(argument_function_space)
84+ _value_shape(value_shape), _argument_space(argument_space)
8285 {
8386 for (auto & c : _coefficients)
8487 {
@@ -97,28 +100,25 @@ class Expression
97100 // / Destructor
98101 virtual ~Expression () = default ;
99102
100- // / @brief Get argument function space.
101- // / @return The argument function space, nullptr if there is no
102- // / argument.
103- std::shared_ptr<const FunctionSpace<geometry_type>>
104- argument_function_space () const
103+ // / @brief Argument function space.
104+ // / @return Argument function space, nullptr if there is no argument.
105+ std::shared_ptr<const FunctionSpace<geometry_type>> argument_space () const
105106 {
106- return _argument_function_space ;
107+ return _argument_space ;
107108 };
108109
109- // / @brief Get coefficients.
110- // / @return Vector of attached coefficients.
110+ // / @brief Expression coefficients.
111+ // / @return List of attached coefficients.
111112 const std::vector<
112113 std::shared_ptr<const Function<scalar_type, geometry_type>>>&
113114 coefficients () const
114115 {
115116 return _coefficients;
116117 }
117118
118- // / @brief Get constants.
119- // / @return Vector of attached constants with their names. Names are
120- // / used to set constants in user's c++ code. Index in the vector is
121- // / the position of the constant in the original (nonsimplified) form.
119+ // / @brief Expression constants.
120+ // /
121+ // / @return List of attached constants.
122122 const std::vector<std::shared_ptr<const Constant<scalar_type>>>&
123123 constants () const
124124 {
@@ -127,7 +127,7 @@ class Expression
127127
128128 // / @brief Offset for each coefficient expansion array on a cell.
129129 // /
130- // / Used to pack data for multiple coefficients in a flat array. The
130+ // / Used to pack data for multiple coefficients into a flat array. The
131131 // / last entry is the size required to store all coefficients.
132132 // / @return The offsets.
133133 std::vector<int > coefficient_offsets () const
@@ -142,157 +142,33 @@ class Expression
142142 return n;
143143 }
144144
145- // / @brief Evaluate Expression on cells or facets.
146- // /
147- // / @param[in] mesh Cells on which to evaluate the Expression.
148- // / @param[in] entities List of entities to evaluate the expression
149- // / on. This could be either a list of cells or a list of (cell, local
150- // / @param[out] values A 2D array to store the result. Caller is
151- // / responsible for correct sizing which should be `(num_cells,
152- // / num_points * value_size * num_all_argument_dofs columns)`.
153- // / facet index) tuples. Array is flattened per entity.
154- // / @param[in] vshape The shape of `values` (row-major storage).
155- void eval (const mesh::Mesh<geometry_type>& mesh,
156- std::span<const std::int32_t > entities,
157- std::span<scalar_type> values,
158- std::array<std::size_t , 2 > vshape) const
159- {
160- std::size_t estride;
161- if (mesh.topology ()->dim () == _x_ref.second [1 ])
162- estride = 1 ;
163- else if (mesh.topology ()->dim () == _x_ref.second [1 ] + 1 )
164- estride = 2 ;
165- else
166- throw std::runtime_error (" Invalid dimension of evaluation points." );
167-
168- // Prepare coefficients and constants
169- std::vector<T> coeffs ((entities.size () / estride)
170- * this ->coefficient_offsets ().back ());
171- int cstride = this ->coefficient_offsets ().back ();
172- {
173- std::vector<
174- std::reference_wrapper<const Function<scalar_type, geometry_type>>>
175- c;
176- std::ranges::transform (this ->coefficients (), std::back_inserter (c),
177- [](auto c) -> const Function<T, U>&
178- { return *c; });
179- fem::pack_coefficients (c, this ->coefficient_offsets (), entities, estride,
180- std::span (coeffs));
181- }
182- std::vector<scalar_type> constant_data = fem::pack_constants (*this );
183-
184- auto fn = this ->get_tabulate_expression ();
185-
186- // Prepare cell geometry
187- auto x_dofmap = mesh.geometry ().dofmap ();
188-
189- // Get geometry data
190- auto & cmap = mesh.geometry ().cmap ();
191-
192- std::size_t num_dofs_g = cmap.dim ();
193- auto x_g = mesh.geometry ().x ();
194-
195- // Create data structures used in evaluation
196- std::vector<geometry_type> coord_dofs (3 * num_dofs_g);
197-
198- int num_argument_dofs = 1 ;
199- std::span<const std::uint32_t > cell_info;
200- std::function<void (std::span<scalar_type>, std::span<const std::uint32_t >,
201- std::int32_t , int )>
202- post_dof_transform
203- = [](std::span<scalar_type>, std::span<const std::uint32_t >,
204- std::int32_t , int )
205- {
206- // Do nothing
207- };
208-
209- if (_argument_function_space)
210- {
211- num_argument_dofs
212- = _argument_function_space->dofmap ()->element_dof_layout ().num_dofs ();
213- auto element = _argument_function_space->element ();
214- num_argument_dofs *= _argument_function_space->dofmap ()->bs ();
215- assert (element);
216- if (element->needs_dof_transformations ())
217- {
218- mesh.topology_mutable ()->create_entity_permutations ();
219- cell_info = std::span (mesh.topology ()->get_cell_permutation_info ());
220- post_dof_transform
221- = element->template dof_transformation_right_fn <scalar_type>(
222- doftransform::transpose);
223- }
224- }
225-
226- // Create get entity index function
227- std::function<const std::int32_t *(std::span<const std::int32_t >,
228- std::size_t )>
229- get_entity_index
230- = []([[maybe_unused]] std::span<const std::int32_t > entities,
231- [[maybe_unused]] std::size_t idx) { return nullptr ; };
232- if (estride == 2 )
233- {
234- get_entity_index
235- = [](std::span<const std::int32_t > entities, std::size_t idx)
236- { return entities.data () + 2 * idx + 1 ; };
237- }
238-
239- // Iterate over cells and 'assemble' into values
240- int size0 = _x_ref.second [0 ] * value_size ();
241- std::vector<scalar_type> values_local (size0 * num_argument_dofs, 0 );
242- for (std::size_t e = 0 ; e < entities.size () / estride; ++e)
243- {
244- std::int32_t entity = entities[e * estride];
245- auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::submdspan (
246- x_dofmap, entity, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
247- for (std::size_t i = 0 ; i < x_dofs.size (); ++i)
248- {
249- std::copy_n (std::next (x_g.begin (), 3 * x_dofs[i]), 3 ,
250- std::next (coord_dofs.begin (), 3 * i));
251- }
252-
253- const scalar_type* coeff_cell = coeffs.data () + e * cstride;
254- const int * entity_index = get_entity_index (entities, e);
255-
256- std::ranges::fill (values_local, 0 );
257- _fn (values_local.data (), coeff_cell, constant_data.data (),
258- coord_dofs.data (), entity_index, nullptr , nullptr );
259- post_dof_transform (values_local, cell_info, e, size0);
260- for (std::size_t j = 0 ; j < values_local.size (); ++j)
261- values[e * vshape[1 ] + j] = values_local[j];
262- }
263- }
264-
265- // / @brief Get function for tabulate_expression.
266- // / @return fn Function to tabulate expression.
145+ // / @brief Function for tabulating the Expression.
267146 const std::function<void (scalar_type*, const scalar_type*, const scalar_type*,
268147 const geometry_type*, const int *, const uint8_t *, void *)>&
269- get_tabulate_expression () const
148+ kernel () const
270149 {
271150 return _fn;
272151 }
273152
274- // / @brief Get value size
275- // / @return The value size.
153+ // / @brief Value size of the Expression result.
276154 int value_size () const
277155 {
278156 return std::reduce (_value_shape.begin (), _value_shape.end (), 1 ,
279157 std::multiplies{});
280158 }
281159
282- // / @brief Get value shape.
283- // / @return The value shape.
160+ // / @brief Value shape of of Expression result (at a point),
284161 const std::vector<std::size_t >& value_shape () const { return _value_shape; }
285162
286- // / @brief Evaluation points on the reference cell.
287- // / @return Evaluation points.
163+ // / @brief Evaluation point coordinates on the reference cell.
288164 std::pair<std::vector<geometry_type>, std::array<std::size_t , 2 >> X () const
289165 {
290166 return _x_ref;
291167 }
292168
293169private:
294170 // Function space for Argument
295- std::shared_ptr<const FunctionSpace<geometry_type>> _argument_function_space ;
171+ std::shared_ptr<const FunctionSpace<geometry_type>> _argument_space ;
296172
297173 // Coefficients associated with the Expression
298174 std::vector<std::shared_ptr<const Function<scalar_type, geometry_type>>>
@@ -306,11 +182,10 @@ class Expression
306182 const geometry_type*, const int *, const uint8_t *, void *)>
307183 _fn;
308184
309- // Shape of the evaluated expression
185+ // Shape of the evaluated Expression
310186 std::vector<std::size_t > _value_shape;
311187
312- // Evaluation points on reference cell. Synonymous with X in public
313- // interface.
188+ // Evaluation points on reference cell
314189 std::pair<std::vector<geometry_type>, std::array<std::size_t , 2 >> _x_ref;
315190};
316191} // namespace dolfinx::fem
0 commit comments