DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
assemble_scalar_impl.h
1// Copyright (C) 2019-2025 Garth N. Wells and Paul T. Kühner
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 "Constant.h"
10#include "Form.h"
11#include "FunctionSpace.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 <type_traits>
21#include <vector>
22
23namespace dolfinx::fem::impl
24{
26template <dolfinx::scalar T, std::floating_point U>
27T assemble_cells(
28 mdspan2_t x_dofmap,
29 md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>> x,
30 std::span<const std::int32_t> cells, FEkernel<T, U> auto fn,
31 std::span<const T> constants,
32 md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
33 std::span<std::type_identity_t<U>> cdofs_b)
34{
35 T value(0);
36 if (cells.empty())
37 return value;
38
39 assert(cdofs_b.size() >= 3 * x_dofmap.extent(1));
40
41 // Iterate over all cells
42 for (std::size_t index = 0; index < cells.size(); ++index)
43 {
44 std::int32_t c = cells[index];
45
46 // Get cell coordinates/geometry
47 auto x_dofs = md::submdspan(x_dofmap, c, md::full_extent);
48 for (std::size_t i = 0; i < x_dofs.size(); ++i)
49 std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i));
50
51 fn(&value, &coeffs(index, 0), constants.data(), cdofs_b.data(), nullptr,
52 nullptr, nullptr);
53 }
54
55 return value;
56}
57
68template <dolfinx::scalar T, std::floating_point U>
69T assemble_entities(
70 mdspan2_t x_dofmap,
71 md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>> x,
72 md::mdspan<const std::int32_t,
73 md::extents<std::size_t, md::dynamic_extent, 2>>
74 entities,
75 FEkernel<T, U> auto fn, std::span<const T> constants,
76 md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
77 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
78 std::span<std::type_identity_t<U>> cdofs_b)
79{
80 T value(0);
81 if (entities.empty())
82 return value;
83
84 assert(cdofs_b.size() >= 3 * x_dofmap.extent(1));
85
86 // Iterate over all facets
87 for (std::size_t f = 0; f < entities.extent(0); ++f)
88 {
89 std::int32_t cell = entities(f, 0);
90 std::int32_t local_entity = entities(f, 1);
91
92 // Get cell coordinates/geometry
93 auto x_dofs = md::submdspan(x_dofmap, cell, md::full_extent);
94 for (std::size_t i = 0; i < x_dofs.size(); ++i)
95 std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i));
96
97 // Permutations
98 std::uint8_t perm = perms.empty() ? 0 : perms(cell, local_entity);
99 fn(&value, &coeffs(f, 0), constants.data(), cdofs_b.data(), &local_entity,
100 &perm, nullptr);
101 }
102
103 return value;
104}
105
107template <dolfinx::scalar T, std::floating_point U>
108T assemble_interior_facets(
109 mdspan2_t x_dofmap,
110 md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>> x,
111 md::mdspan<const std::int32_t,
112 md::extents<std::size_t, md::dynamic_extent, 2, 2>>
113 facets,
114 FEkernel<T, U> auto fn, std::span<const T> constants,
115 md::mdspan<const T, md::extents<std::size_t, md::dynamic_extent, 2,
116 md::dynamic_extent>>
117 coeffs,
118 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
119 std::span<std::type_identity_t<U>> cdofs_b)
120{
121 T value(0);
122 if (facets.empty())
123 return value;
124
125 // Create data structures used in assembly
126 assert(cdofs_b.size() >= 2 * 3 * x_dofmap.extent(1));
127 auto cdofs0 = cdofs_b.first(3 * x_dofmap.extent(1));
128 auto cdofs1 = cdofs_b.last(3 * x_dofmap.extent(1));
129
130 // Iterate over all facets
131 for (std::size_t f = 0; f < facets.extent(0); ++f)
132 {
133 std::array cells = {facets(f, 0, 0), facets(f, 1, 0)};
134 std::array local_facet = {facets(f, 0, 1), facets(f, 1, 1)};
135
136 // Get cell geometry
137 auto x_dofs0 = md::submdspan(x_dofmap, cells[0], md::full_extent);
138 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
139 std::copy_n(&x(x_dofs0[i], 0), 3, std::next(cdofs0.begin(), 3 * i));
140 auto x_dofs1 = md::submdspan(x_dofmap, cells[1], md::full_extent);
141 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
142 std::copy_n(&x(x_dofs1[i], 0), 3, std::next(cdofs1.begin(), 3 * i));
143
144 std::array perm = perms.empty()
145 ? std::array<std::uint8_t, 2>{0, 0}
146 : std::array{perms(cells[0], local_facet[0]),
147 perms(cells[1], local_facet[1])};
148 fn(&value, &coeffs(f, 0, 0), constants.data(), cdofs_b.data(),
149 local_facet.data(), perm.data(), nullptr);
150 }
151
152 return value;
153}
154
156template <dolfinx::scalar T, std::floating_point U>
157T assemble_scalar(
158 const fem::Form<T, U>& M, mdspan2_t x_dofmap,
159 md::mdspan<const U, md::extents<std::size_t, md::dynamic_extent, 3>> x,
160 std::span<const T> constants,
161 const std::map<std::pair<IntegralType, int>,
162 std::pair<std::span<const T>, int>>& coefficients,
163 std::size_t cell_type_idx)
164{
165 std::shared_ptr<const mesh::Mesh<U>> mesh = M.mesh();
166 assert(mesh);
167
168 std::vector<U> cdofs_b(2 * 3 * x_dofmap.extent(1));
169
170 T value = 0;
171 for (int i = 0; i < M.num_integrals(IntegralType::cell, cell_type_idx); ++i)
172 {
173 auto fn = M.kernel(IntegralType::cell, i, cell_type_idx);
174 assert(fn);
175 auto& [coeffs, cstride] = coefficients.at({IntegralType::cell, i});
176 std::span<const std::int32_t> cells
177 = M.domain(IntegralType::cell, i, cell_type_idx);
178 assert(cells.size() * cstride == coeffs.size());
179 value += impl::assemble_cells(
180 x_dofmap, x, cells, fn, constants,
181 md::mdspan(coeffs.data(), cells.size(), cstride), cdofs_b);
182 }
183
184 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> facet_perms;
185 if (M.needs_facet_permutations())
186 {
187 mesh::CellType cell_type = mesh->topology()->cell_types()[cell_type_idx];
188 int num_facets_per_cell
189 = mesh::cell_num_entities(cell_type, mesh->topology()->dim() - 1);
190
191 mesh->topology_mutable()->create_entity_permutations();
192 const std::vector<std::uint8_t>& p
193 = mesh->topology()->get_facet_permutations();
194 facet_perms = md::mdspan(p.data(), p.size() / num_facets_per_cell,
195 num_facets_per_cell);
196 }
197
198 for (int i = 0;
199 i < M.num_integrals(IntegralType::interior_facet, cell_type_idx); ++i)
200 {
201 auto fn = M.kernel(IntegralType::interior_facet, i, cell_type_idx);
202 assert(fn);
203 auto& [coeffs, cstride]
204 = coefficients.at({IntegralType::interior_facet, i});
205 std::span facets = M.domain(IntegralType::interior_facet, i, cell_type_idx);
206
207 constexpr std::size_t num_adjacent_cells = 2;
208 // Two values per each adj. cell (cell index and local facet index).
209 constexpr std::size_t shape1 = 2 * num_adjacent_cells;
210
211 assert((facets.size() / shape1) * 2 * cstride == coeffs.size());
212 value += impl::assemble_interior_facets(
213 x_dofmap, x,
214 md::mdspan<const std::int32_t,
215 md::extents<std::size_t, md::dynamic_extent, 2, 2>>(
216 facets.data(), facets.size() / shape1, 2, 2),
217 fn, constants,
218 md::mdspan<const T, md::extents<std::size_t, md::dynamic_extent, 2,
219 md::dynamic_extent>>(
220 coeffs.data(), facets.size() / shape1, 2, cstride),
221 facet_perms, cdofs_b);
222 }
223
224 for (auto itg_type : {fem::IntegralType::exterior_facet,
226 {
227 md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms
229 ? facet_perms
230 : md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>>{};
231
232 for (int i = 0; i < M.num_integrals(itg_type, cell_type_idx); ++i)
233 {
234 auto fn = M.kernel(itg_type, i, cell_type_idx);
235 assert(fn);
236 auto& [coeffs, cstride] = coefficients.at({itg_type, i});
237
238 std::span entities = M.domain(itg_type, i, cell_type_idx);
239
240 // Two values per each adj. cell (cell index and local entity index).
241 assert((entities.size() / 2) * cstride == coeffs.size());
242 value += impl::assemble_entities(
243 x_dofmap, x,
244 md::mdspan<const std::int32_t,
245 md::extents<std::size_t, md::dynamic_extent, 2>>(
246 entities.data(), entities.size() / 2, 2),
247 fn, constants,
248 md::mdspan(coeffs.data(), entities.size() / 2, cstride), perms,
249 cdofs_b);
250 }
251 }
252
253 return value;
254}
255
256} // namespace dolfinx::fem::impl
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:43
@ interior_facet
Interior facet.
Definition Form.h:42
@ ridge
Ridge.
Definition Form.h:44
@ cell
Cell.
Definition Form.h:40
@ exterior_facet
Exterior facet.
Definition Form.h:41
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