DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
expression_evaluate.h
Go to the documentation of this file.
1// Copyright (C) 2018-2026 Garth N. Wells and Jørgen S. Dokken
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Expression.h"
10#include "FiniteElement.h"
11#include "Function.h"
12#include "FunctionSpace.h"
13#include "assemble_expression_impl.h"
14#include "interpolate.h"
15#include "pack.h"
16#include "traits.h"
17#include <algorithm>
18#include <basix/mdspan.hpp>
19#include <cassert>
20#include <cmath>
21#include <concepts>
22#include <cstddef>
23#include <cstdint>
24#include <dolfinx/common/types.h>
25#include <dolfinx/mesh/Mesh.h>
26#include <dolfinx/mesh/Topology.h>
27#include <functional>
28#include <iterator>
29#include <memory>
30#include <optional>
31#include <ranges>
32#include <span>
33#include <stdexcept>
34#include <utility>
35#include <vector>
36
44
45namespace dolfinx::fem
46{
68template <dolfinx::scalar T, std::floating_point U>
70 std::span<T> values, const fem::Expression<T, U>& e,
71 md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
72 std::span<const T> constants, const mesh::Mesh<U>& mesh,
73 fem::MDSpan2 auto entities,
74 std::optional<
75 std::pair<std::reference_wrapper<const FiniteElement<U>>, std::size_t>>
76 element)
77{
78 // Check that domain is the same as mesh of the expression
79 if (e.coordinate_element_hash() != mesh.geometry().cmaps().front().hash())
80 {
81 throw std::invalid_argument(
82 "Expression was created on a different mesh. Cannot tabulate.");
83 }
84 auto [X, Xshape] = e.X();
85 impl::tabulate_expression(values, e.kernel(), Xshape, e.value_size(), coeffs,
86 constants, mesh, entities, element);
87}
88
105template <dolfinx::scalar T, std::floating_point U>
106void tabulate_expression(std::span<T> values, const fem::Expression<T, U>& e,
107 const mesh::Mesh<U>& mesh, fem::MDSpan2 auto entities)
108{
109 // Check that domain is the same as mesh of the expression
110 if (e.coordinate_element_hash() != mesh.geometry().cmaps().front().hash())
111 {
112 throw std::invalid_argument(
113 "Expression was created on a different mesh. Cannot tabulate.");
114 }
115
116 std::optional<
117 std::pair<std::reference_wrapper<const FiniteElement<U>>, std::size_t>>
118 element = std::nullopt;
119 if (auto V = e.argument_space(); V)
120 {
121 std::size_t num_argument_dofs
122 = V->dofmap()->element_dof_layout().num_dofs() * V->dofmap()->bs();
123 assert(V->element());
124 element = {std::cref(*V->element()), num_argument_dofs};
125 }
126
127 std::vector<int> coffsets = e.coefficient_offsets();
128 const std::vector<std::shared_ptr<const Function<T, U>>>& coefficients
129 = e.coefficients();
130 std::vector<T> coeffs(entities.extent(0) * coffsets.back());
131 int cstride = coffsets.back();
132 {
133 std::vector<std::reference_wrapper<const Function<T, U>>> c;
134 std::ranges::transform(coefficients, std::back_inserter(c),
135 [](auto c) -> const Function<T, U>& { return *c; });
136 fem::pack_coefficients(c, mesh, entities, e.entity_maps(), coffsets,
137 std::span(coeffs));
138 }
139 std::vector<T> constants = fem::pack_constants(e);
140
142 values, e,
143 md::mdspan(std::as_const(coeffs).data(), entities.extent(0), cstride),
144 std::span<const T>(constants), mesh, entities, element);
145}
146
164template <dolfinx::scalar T, std::floating_point U>
166 const Expression<T, U>& e0, mesh::CellRange auto&& cells0)
167{
168 // Extract mesh
169 const mesh::Mesh<U>* mesh0 = nullptr;
170 for (auto& c : e0.coefficients())
171 {
172 assert(c);
173 assert(c->function_space());
174 assert(c->function_space()->mesh());
175 if (auto mesh = c->function_space()->mesh().get(); !mesh0)
176 mesh0 = mesh;
177 else if (mesh != mesh0)
178 {
179 throw std::invalid_argument(
180 "Expression coefficient Functions have different meshes.");
181 }
182 }
183
184 // If Expression has no Function coefficients take mesh from `u1`.
185 auto V1 = u1.function_space();
186 assert(V1);
187 assert(V1->mesh());
188 if (!mesh0)
189 mesh0 = V1->mesh().get();
190
191 if (cells0.size() != cells1.size())
192 throw std::invalid_argument("Cell lists have different lengths.");
193
194 // Check that Function and Expression spaces are compatible
195 assert(V1->element());
196 std::size_t value_size = e0.value_size();
197 if (e0.argument_space())
198 throw std::invalid_argument("Cannot interpolate Expression with Argument.");
199
200 if (value_size != (std::size_t)V1->element()->value_size())
201 {
202 throw std::invalid_argument(
203 "Function value size not equal to Expression value size.");
204 }
205
206 // Compatibility check
207 {
208 auto [X0, shape0] = e0.X();
209 auto [X1, shape1] = V1->element()->interpolation_points();
210 if (shape0 != shape1)
211 {
212 throw std::invalid_argument(
213 "Function element interpolation points has different shape to "
214 "Expression interpolation points");
215 }
216
217 for (std::size_t i = 0; i < X0.size(); ++i)
218 {
219 if (std::abs(X0[i] - X1[i]) > 1.0e-10)
220 {
221 throw std::invalid_argument("Function element interpolation points not "
222 "equal to Expression interpolation points");
223 }
224 }
225 }
226
227 // Array to hold evaluated Expression
228 std::size_t num_cells = cells0.size();
229 std::size_t num_points = e0.X().second[0];
230 std::vector<T> fdata(num_cells * num_points * value_size);
231 md::mdspan<const T, md::dextents<std::size_t, 3>> f(fdata.data(), num_cells,
232 num_points, value_size);
233
234 // Evaluate Expression at points
235 std::vector<std::int32_t> _cells0(cells0.begin(), cells0.end());
236 tabulate_expression(std::span(fdata), e0, *mesh0,
237 md::mdspan(_cells0.data(), _cells0.size()));
238
239 // Reshape evaluated data to fit interpolate.
240 // Expression returns matrix of shape (num_cells, num_points *
241 // value_size), i.e. xyzxyz ordering of dof values per cell per
242 // point. The interpolation uses xxyyzz input, ordered for all
243 // points of each cell, i.e. (value_size, num_cells*num_points).
244 std::vector<T> fdata1(num_cells * num_points * value_size);
245 md::mdspan<T, md::dextents<std::size_t, 3>> f1(fdata1.data(), value_size,
246 num_cells, num_points);
247 for (std::size_t i = 0; i < f.extent(0); ++i)
248 for (std::size_t j = 0; j < f.extent(1); ++j)
249 for (std::size_t k = 0; k < f.extent(2); ++k)
250 f1(k, i, j) = f(i, j, k);
251
252 // Interpolate values into appropriate space
253 fem::interpolate<T>(u1, std::span<const T>(fdata1.data(), fdata1.size()),
254 {value_size, num_cells * num_points}, cells1);
255}
256
267template <dolfinx::scalar T, std::floating_point U>
269 mesh::CellRange auto&& cells)
270{
271 interpolate<T, U>(u1, cells, e0, cells);
272}
273
283template <dolfinx::scalar T, std::floating_point U>
285{
286 assert(u1.function_space());
287 assert(u1.function_space()->mesh());
288 int tdim = u1.function_space()->mesh()->topology()->dim();
289 auto map = u1.function_space()->mesh()->topology()->index_map(tdim);
290 assert(map);
292 u1, e0, std::ranges::iota_view(0, map->size_local() + map->num_ghosts()));
293}
294} // namespace dolfinx::fem
An Expression represents a mathematical expression evaluated at a pre-defined points on a reference c...
Definition Expression.h:43
std::pair< std::vector< geometry_type >, std::array< std::size_t, 2 > > X() const
Evaluation point coordinates on the reference cell.
Definition Expression.h:174
const std::vector< std::shared_ptr< const Function< scalar_type, geometry_type > > > & coefficients() const
Expression coefficients.
Definition Expression.h:123
std::shared_ptr< const FunctionSpace< geometry_type > > argument_space() const
Argument function space.
Definition Expression.h:114
std::uint64_t coordinate_element_hash() const
Hash for coordinate element used to create the expression.
Definition Expression.h:187
const std::function< void(scalar_type *, const scalar_type *, const scalar_type *, const geometry_type *, const int *, const uint8_t *, void *)> & kernel() const
Function for tabulating the Expression.
Definition Expression.h:158
std::vector< int > coefficient_offsets() const
Offset for each coefficient expansion array on a cell.
Definition Expression.h:142
int value_size() const
Value size of the Expression result.
Definition Expression.h:164
const std::vector< std::reference_wrapper< const dolfinx::mesh::EntityMap > > & entity_maps() const
Maps between entities of different meshes.
Definition Expression.h:181
Model of a finite element.
Definition FiniteElement.h:199
Definition Function.h:44
std::shared_ptr< const FunctionSpace< geometry_type > > function_space() const
Access the function space.
Definition Function.h:145
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:25
Concept for mdspan of rank 1 or 2.
Definition traits.h:57
Requirement on range of cell indices.
Definition Topology.h:32
Finite element method functionality.
Definition assemble_expression_impl.h:22
void tabulate_expression(std::span< T > values, const fem::Expression< T, U > &e, md::mdspan< const T, md::dextents< std::size_t, 2 > > coeffs, std::span< const T > constants, const mesh::Mesh< U > &mesh, fem::MDSpan2 auto entities, std::optional< std::pair< std::reference_wrapper< const FiniteElement< U > >, std::size_t > > element)
Evaluate an Expression on cells or facets.
Definition expression_evaluate.h:69
void pack_coefficients(const Form< T, U > &form, std::map< std::pair< IntegralType, int >, std::pair< std::vector< T >, int > > &coeffs)
Pack coefficients of a Form.
Definition pack.h:259
std::vector< T > pack_constants(const std::vector< std::reference_wrapper< const fem::Constant< T > > > &c)
Pack constants of an Expression or Form into a single array ready for assembly.
Definition pack.h:573
void interpolate(Function< T, U > &u1, mesh::CellRange auto &&cells1, const Expression< T, U > &e0, mesh::CellRange auto &&cells0)
Interpolate an Expression into a Function over a subset of cells.
Definition expression_evaluate.h:165
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
Functions supporting the packing of coefficient data.