Skip to content

Commit 508011a

Browse files
Claus SusanneClaus Susanne
authored andcommitted
merge latest changes of main into sclaus branch
2 parents 1f9fe27 + ead49d0 commit 508011a

File tree

15 files changed

+711
-388
lines changed

15 files changed

+711
-388
lines changed

cpp/dolfinx/fem/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ set(HEADERS_fem
1010
${CMAKE_CURRENT_SOURCE_DIR}/Function.h
1111
${CMAKE_CURRENT_SOURCE_DIR}/FunctionSpace.h
1212
${CMAKE_CURRENT_SOURCE_DIR}/assembler.h
13+
${CMAKE_CURRENT_SOURCE_DIR}/assemble_expression_impl.h
1314
${CMAKE_CURRENT_SOURCE_DIR}/assemble_matrix_impl.h
1415
${CMAKE_CURRENT_SOURCE_DIR}/assemble_scalar_impl.h
1516
${CMAKE_CURRENT_SOURCE_DIR}/assemble_vector_impl.h

cpp/dolfinx/fem/Expression.h

Lines changed: 40 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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
//
@@ -8,32 +8,34 @@
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

2322
namespace 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.
3739
template <dolfinx::scalar T,
3840
std::floating_point U = dolfinx::scalar_value_type_t<T>>
3941
class 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

293169
private:
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

cpp/dolfinx/fem/Function.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#include "DofMap.h"
1010
#include "FiniteElement.h"
1111
#include "FunctionSpace.h"
12+
#include "assembler.h"
1213
#include "interpolate.h"
1314
#include <algorithm>
15+
#include <basix/mdspan.hpp>
1416
#include <concepts>
1517
#include <dolfinx/common/IndexMap.h>
1618
#include <dolfinx/common/types.h>
@@ -315,6 +317,8 @@ class Function
315317
std::span<const std::int32_t> cells0,
316318
std::span<const std::int32_t> cells1 = {})
317319
{
320+
namespace md = MDSPAN_IMPL_STANDARD_NAMESPACE;
321+
318322
// Extract mesh
319323
const mesh::Mesh<geometry_type>* mesh0 = nullptr;
320324
for (auto& c : e0.coefficients())
@@ -352,7 +356,7 @@ class Function
352356
// Check that Function and Expression spaces are compatible
353357
assert(_function_space->element());
354358
std::size_t value_size = e0.value_size();
355-
if (e0.argument_function_space())
359+
if (e0.argument_space())
356360
throw std::runtime_error("Cannot interpolate Expression with Argument.");
357361
if (value_size != _function_space->element()->value_size())
358362
{
@@ -391,7 +395,8 @@ class Function
391395
f(fdata.data(), num_cells, num_points, value_size);
392396

393397
// Evaluate Expression at points
394-
e0.eval(*mesh0, cells0, fdata, {num_cells, num_points * value_size});
398+
tabulate_expression(std::span(fdata), e0, *mesh0,
399+
md::mdspan(cells0.data(), cells0.size()));
395400

396401
// Reshape evaluated data to fit interpolate.
397402
// Expression returns matrix of shape (num_cells, num_points *

0 commit comments

Comments
 (0)