DOLFINx 0.11.0
DOLFINx C++
Loading...
Searching...
No Matches
assemble_expression_impl.h
1// Copyright (C) 2025 Garth N. Wells
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 "FunctionSpace.h"
11#include "traits.h"
12#include "utils.h"
13#include <algorithm>
14#include <basix/mdspan.hpp>
15#include <dolfinx/common/IndexMap.h>
16#include <dolfinx/mesh/Geometry.h>
17#include <dolfinx/mesh/Mesh.h>
18#include <dolfinx/mesh/Topology.h>
19#include <memory>
20#include <vector>
21
22namespace dolfinx::fem::impl
23{
62template <dolfinx::scalar T, std::floating_point U>
64 std::span<T> values, fem::FEkernel<T> auto fn,
65 std::array<std::size_t, 2> Xshape, std::size_t value_size,
66 std::size_t num_argument_dofs,
67 md::mdspan<const std::int32_t, md::dextents<std::size_t, 2>> x_dofmap,
68 std::span<const scalar_value_t<T>> x,
69 md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
70 std::span<const T> constants, fem::MDSpan2 auto entities,
71 std::span<const std::uint32_t> cell_info,
73 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms)
74{
75 static_assert(entities.rank() == 1 or entities.rank() == 2);
76
77 // Create data structures used in evaluation
78 std::vector<U> coord_dofs(3 * x_dofmap.extent(1));
79
80 // Iterate over cells and 'assemble' into values
81 int size0 = Xshape[0] * value_size;
82 std::vector<T> values_local(size0 * num_argument_dofs, 0);
83 std::size_t offset = values_local.size();
84 for (std::size_t e = 0; e < entities.extent(0); ++e)
85 {
86 std::ranges::fill(values_local, 0);
87 if constexpr (entities.rank() == 1)
88 {
89 std::int32_t entity = entities(e);
90 auto x_dofs = md::submdspan(x_dofmap, entity, md::full_extent);
91 for (std::size_t i = 0; i < x_dofs.size(); ++i)
92 {
93 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
94 std::next(coord_dofs.begin(), 3 * i));
95 }
96 fn(values_local.data(), &coeffs(e, 0), constants.data(),
97 coord_dofs.data(), nullptr, nullptr, nullptr);
98
99 P0(values_local, cell_info, entity, size0);
100 }
101 else
102 {
103 std::int32_t entity = entities(e, 0);
104 std::int32_t local_entity = entities(e, 1);
105 std::uint8_t perm = perms.empty() ? 0 : perms(entity, local_entity);
106 auto x_dofs = md::submdspan(x_dofmap, entity, md::full_extent);
107 for (std::size_t i = 0; i < x_dofs.size(); ++i)
108 {
109 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
110 std::next(coord_dofs.begin(), 3 * i));
111 }
112 fn(values_local.data(), &coeffs(e, 0), constants.data(),
113 coord_dofs.data(), &local_entity, &perm, nullptr);
114 P0(values_local, cell_info, entity, size0);
115 }
116
117 for (std::size_t j = 0; j < values_local.size(); ++j)
118 values[e * offset + j] = values_local[j];
119 }
120}
121
154template <dolfinx::scalar T, std::floating_point U>
156 std::span<T> values, fem::FEkernel<T> auto fn,
157 std::array<std::size_t, 2> Xshape, std::size_t value_size,
158 md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
159 std::span<const T> constants, const mesh::Mesh<U>& mesh,
160 fem::MDSpan2 auto entities,
161 std::optional<
162 std::pair<std::reference_wrapper<const FiniteElement<U>>, std::size_t>>
163 element)
164{
165 std::function<void(std::span<T>, std::span<const std::uint32_t>, std::int32_t,
166 int)>
167 post_dof_transform
168 = [](std::span<T>, std::span<const std::uint32_t>, std::int32_t, int)
169 {
170 // Do nothing
171 };
172
173 std::shared_ptr<const mesh::Topology> topology = mesh.topology();
174 assert(topology);
175 std::size_t num_argument_dofs = 1;
176 std::span<const std::uint32_t> cell_info;
177 if (element)
178 {
179 num_argument_dofs = element->second;
180 if (element->first.get().needs_dof_transformations())
181 {
182 mesh.topology_mutable()->create_entity_permutations();
183 cell_info = std::span(topology->get_cell_permutation_info());
184 post_dof_transform
185 = element->first.get().template dof_transformation_right_fn<T>(
187 }
188 }
189 // An expression has no notion of requiring a facet permutation.
190 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> facet_perms;
191 if constexpr (entities.rank() == 2)
192 {
193 mesh::CellType cell_type = mesh.topology()->cell_types()[0];
194 int num_facets_per_cell
195 = mesh::cell_num_entities(cell_type, mesh.topology()->dim() - 1);
196 mesh.topology_mutable()->create_entity_permutations();
197 const std::vector<std::uint8_t>& p
198 = mesh.topology()->get_facet_permutations();
199 facet_perms = md::mdspan(p.data(), p.size() / num_facets_per_cell,
200 num_facets_per_cell);
201 }
202 tabulate_expression<T, U>(values, fn, Xshape, value_size, num_argument_dofs,
203 mesh.geometry().dofmaps().front(),
204 mesh.geometry().x(), coeffs, constants, entities,
205 cell_info, post_dof_transform, facet_perms);
206}
207} // namespace dolfinx::fem::impl
Model of a finite element.
Definition FiniteElement.h:57
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:23
DOF transform kernel concept.
Definition traits.h:21
Finite element cell kernel concept.
Definition traits.h:30
Concept for mdspan of rank 1 or 2.
Definition traits.h:36
Functions supporting finite element method operations.
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 assembler.h:65
@ transpose
Transpose.
Definition FiniteElement.h:28
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
CellType
Cell type identifier.
Definition cell_types.h:21
int cell_num_entities(CellType type, int dim)
Number of entities of dimension.
Definition cell_types.cpp:90