11#include "FunctionSpace.h"
15#include <basix/mdspan.hpp>
17#include <dolfinx/common/IndexMap.h>
18#include <dolfinx/mesh/Geometry.h>
19#include <dolfinx/mesh/Mesh.h>
20#include <dolfinx/mesh/Topology.h>
25namespace dolfinx::fem::impl
33template <dolfinx::scalar T, std::
floating_po
int U>
34T assemble_cells(MDSpan2Int32
auto x_dofmap, MDSpan2Floating<U>
auto x,
35 std::span<const std::int32_t> cells,
36 const FEkernel<T, U>
auto& fn, std::span<const T> constants,
37 md::mdspan<
const T, md::dextents<std::size_t, 2>> coeffs,
38 std::span<std::type_identity_t<U>> cdofs_b)
44 assert(cdofs_b.size() >= 3 * x_dofmap.extent(1));
46 const T* coeffs_data = coeffs.data_handle();
47 const std::size_t cstride = coeffs.extent(1);
50 for (std::size_t index = 0; index <
cells.size(); ++index)
52 std::int32_t c =
cells[index];
55 auto x_dofs = md::submdspan(x_dofmap, c, md::full_extent);
56 for (std::size_t i = 0; i < x_dofs.size(); ++i)
57 std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i));
59 fn(&value, coeffs_data + index * cstride, constants.data(), cdofs_b.data(),
60 nullptr,
nullptr,
nullptr);
81template <dolfinx::scalar T, std::
floating_po
int U>
83 MDSpan2Int32
auto x_dofmap, MDSpan2Floating<U>
auto x,
84 md::mdspan<
const std::int32_t,
85 md::extents<std::size_t, md::dynamic_extent, 2>>
87 const FEkernel<T, U>
auto& fn, std::span<const T> constants,
88 md::mdspan<
const T, md::dextents<std::size_t, 2>> coeffs,
89 md::mdspan<
const std::uint8_t, md::dextents<std::size_t, 2>> perms,
90 std::span<std::type_identity_t<U>> cdofs_b)
96 assert(cdofs_b.size() >= 3 * x_dofmap.extent(1));
98 const T* coeffs_data = coeffs.data_handle();
99 const std::size_t cstride = coeffs.extent(1);
102 for (std::size_t f = 0; f < entities.extent(0); ++f)
104 std::int32_t
cell = entities(f, 0);
105 std::int32_t local_entity = entities(f, 1);
108 auto x_dofs = md::submdspan(x_dofmap,
cell, md::full_extent);
109 for (std::size_t i = 0; i < x_dofs.size(); ++i)
110 std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i));
113 std::uint8_t perm = perms.empty() ? 0 : perms(
cell, local_entity);
114 fn(&value, coeffs_data + f * cstride, constants.data(), cdofs_b.data(),
115 &local_entity, &perm,
nullptr);
127template <dolfinx::scalar T, std::
floating_po
int U>
128T assemble_interior_facets(
129 MDSpan2Int32
auto x_dofmap, MDSpan2Floating<U>
auto x,
130 md::mdspan<
const std::int32_t,
131 md::extents<std::size_t, md::dynamic_extent, 2, 2>>
133 const FEkernel<T, U>
auto& fn, std::span<const T> constants,
134 md::mdspan<
const T, md::extents<std::size_t, md::dynamic_extent, 2,
137 md::mdspan<
const std::uint8_t, md::dextents<std::size_t, 2>> perms,
138 std::span<std::type_identity_t<U>> cdofs_b)
145 assert(cdofs_b.size() >= 2 * 3 * x_dofmap.extent(1));
146 auto cdofs0 = cdofs_b.first(3 * x_dofmap.extent(1));
147 auto cdofs1 = cdofs_b.last(3 * x_dofmap.extent(1));
149 const T* coeffs_data = coeffs.data_handle();
150 const std::size_t cstride = 2 * coeffs.extent(2);
153 for (std::size_t f = 0; f < facets.extent(0); ++f)
155 std::array
cells = {facets(f, 0, 0), facets(f, 1, 0)};
156 std::array local_facet = {facets(f, 0, 1), facets(f, 1, 1)};
159 auto x_dofs0 = md::submdspan(x_dofmap, cells[0], md::full_extent);
160 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
161 std::copy_n(&x(x_dofs0[i], 0), 3, std::next(cdofs0.begin(), 3 * i));
162 auto x_dofs1 = md::submdspan(x_dofmap, cells[1], md::full_extent);
163 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
164 std::copy_n(&x(x_dofs1[i], 0), 3, std::next(cdofs1.begin(), 3 * i));
166 std::array perm = perms.empty()
167 ? std::array<std::uint8_t, 2>{0, 0}
168 : std::array{perms(cells[0], local_facet[0]),
169 perms(cells[1], local_facet[1])};
170 fn(&value, coeffs_data + f * cstride, constants.data(), cdofs_b.data(),
171 local_facet.data(), perm.data(),
nullptr);
178template <dolfinx::scalar T, std::
floating_po
int U>
180 const fem::Form<T, U>& M, mdspan2_t x_dofmap,
181 md::mdspan<
const U, md::extents<std::size_t, md::dynamic_extent, 3>> x,
182 std::span<const T> constants,
183 const std::map<std::pair<IntegralType, int>,
184 std::pair<std::span<const T>,
int>>& coefficients,
185 std::size_t cell_type_idx)
187 std::shared_ptr<const mesh::Mesh<U>> mesh = M.mesh();
190 std::vector<U> cdofs_b(2 * 3 * x_dofmap.extent(1));
198 std::span<const std::int32_t>
cells
200 assert(
cells.size() * cstride == coeffs.size());
201 value += impl::assemble_cells<T, U>(
202 x_dofmap, x, cells, fn, constants,
203 md::mdspan(coeffs.data(),
cells.size(), cstride), cdofs_b);
206 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> facet_perms;
207 if (M.needs_facet_permutations())
209 mesh::CellType cell_type = mesh->topology()->cell_types()[cell_type_idx];
210 int num_facets_per_cell
213 mesh->topology_mutable()->create_entity_permutations();
214 const std::vector<std::uint8_t>& p
215 = mesh->topology()->get_facet_permutations();
216 facet_perms = md::mdspan(p.data(), p.size() / num_facets_per_cell,
217 num_facets_per_cell);
225 auto& [coeffs, cstride]
229 constexpr std::size_t num_adjacent_cells = 2;
231 constexpr std::size_t shape1 = 2 * num_adjacent_cells;
233 assert((facets.size() / shape1) * 2 * cstride == coeffs.size());
234 value += impl::assemble_interior_facets<T, U>(
236 md::mdspan<
const std::int32_t,
237 md::extents<std::size_t, md::dynamic_extent, 2, 2>>(
238 facets.data(), facets.size() / shape1, 2, 2),
240 md::mdspan<
const T, md::extents<std::size_t, md::dynamic_extent, 2,
241 md::dynamic_extent>>(
242 coeffs.data(), facets.size() / shape1, 2, cstride),
243 facet_perms, cdofs_b);
249 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms
252 : md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>>{};
254 for (
int i = 0; i < M.num_integrals(itg_type, cell_type_idx); ++i)
256 auto fn = M.kernel(itg_type, i, cell_type_idx);
258 auto& [coeffs, cstride] = coefficients.at({itg_type, i});
260 std::span entities = M.domain(itg_type, i, cell_type_idx);
263 assert((entities.size() / 2) * cstride == coeffs.size());
264 value += impl::assemble_entities<T, U>(
266 md::mdspan<
const std::int32_t,
267 md::extents<std::size_t, md::dynamic_extent, 2>>(
268 entities.data(), entities.size() / 2, 2),
270 md::mdspan(coeffs.data(), entities.size() / 2, cstride), perms,
Functions supporting finite element method operations.
void cells(la::SparsityPattern &pattern, const std::pair< R0, R1 > &cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.h:37
@ vertex
Vertex.
Definition Form.h:45
@ interior_facet
Interior facet.
Definition Form.h:44
@ ridge
Ridge.
Definition Form.h:46
@ cell
Cell.
Definition Form.h:42
@ exterior_facet
Exterior facet.
Definition Form.h:43
CellType
Cell type identifier.
Definition cell_types.h:22
int cell_num_entities(CellType type, int dim)
Number of entities of dimension.
Definition cell_types.cpp:92