11 #include "FunctionSpace.h"
13 #include <dolfinx/common/utils.h>
14 #include <dolfinx/graph/AdjacencyList.h>
15 #include <dolfinx/la/utils.h>
16 #include <dolfinx/mesh/Geometry.h>
17 #include <dolfinx/mesh/Mesh.h>
18 #include <dolfinx/mesh/Topology.h>
24 namespace dolfinx::fem::impl
32 template <
typename T,
typename U>
34 U mat_set_values,
const Form<T>& a,
const std::span<const T>& constants,
35 const std::map<std::pair<IntegralType, int>,
36 std::pair<std::span<const T>,
int>>& coefficients,
37 const std::span<const std::int8_t>& bc0,
38 const std::span<const std::int8_t>& bc1);
41 template <
typename T,
typename U>
44 const std::span<const std::int32_t>& cells,
45 const std::function<
void(
const std::span<T>&,
46 const std::span<const std::uint32_t>&,
47 std::int32_t,
int)>& dof_transform,
49 const std::function<
void(
const std::span<T>&,
50 const std::span<const std::uint32_t>&,
51 std::int32_t,
int)>& dof_transform_to_transpose,
53 const std::span<const std::int8_t>& bc0,
54 const std::span<const std::int8_t>& bc1,
55 const std::function<
void(T*,
const T*,
const T*,
56 const scalar_value_type_t<T>*,
const int*,
57 const std::uint8_t*)>& kernel,
58 const std::span<const T>& coeffs,
int cstride,
59 const std::span<const T>& constants,
60 const std::span<const std::uint32_t>& cell_info)
67 const std::size_t num_dofs_g = geometry.
cmap().
dim();
68 std::span<const double> x_g = geometry.
x();
71 const int num_dofs0 = dofmap0.
links(0).size();
72 const int num_dofs1 = dofmap1.
links(0).size();
73 const int ndim0 = bs0 * num_dofs0;
74 const int ndim1 = bs1 * num_dofs1;
75 std::vector<T> Ae(ndim0 * ndim1);
76 const std::span<T> _Ae(Ae);
77 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * num_dofs_g);
80 for (std::size_t index = 0; index < cells.size(); ++index)
82 std::int32_t c = cells[index];
85 auto x_dofs = x_dofmap.
links(c);
86 for (std::size_t i = 0; i < x_dofs.size(); ++i)
88 common::impl::copy_N<3>(std::next(x_g.begin(), 3 * x_dofs[i]),
89 std::next(coordinate_dofs.begin(), 3 * i));
93 std::fill(Ae.begin(), Ae.end(), 0);
94 kernel(Ae.data(), coeffs.data() + index * cstride, constants.data(),
95 coordinate_dofs.data(),
nullptr,
nullptr);
97 dof_transform(_Ae, cell_info, c, ndim1);
98 dof_transform_to_transpose(_Ae, cell_info, c, ndim0);
101 auto dofs0 = dofmap0.
links(c);
102 auto dofs1 = dofmap1.
links(c);
105 for (
int i = 0; i < num_dofs0; ++i)
107 for (
int k = 0; k < bs0; ++k)
109 if (bc0[bs0 * dofs0[i] + k])
112 const int row = bs0 * i + k;
113 std::fill_n(std::next(Ae.begin(), ndim1 * row), ndim1, 0.0);
121 for (
int j = 0; j < num_dofs1; ++j)
123 for (
int k = 0; k < bs1; ++k)
125 if (bc1[bs1 * dofs1[j] + k])
128 const int col = bs1 * j + k;
129 for (
int row = 0; row < ndim0; ++row)
130 Ae[row * ndim1 + col] = 0.0;
136 mat_set(dofs0, dofs1, Ae);
141 template <
typename T,
typename U>
142 void assemble_exterior_facets(
144 const std::span<const std::int32_t>& facets,
145 const std::function<
void(
const std::span<T>&,
146 const std::span<const std::uint32_t>&,
147 std::int32_t,
int)>& dof_transform,
149 const std::function<
void(
const std::span<T>&,
150 const std::span<const std::uint32_t>&,
151 std::int32_t,
int)>& dof_transform_to_transpose,
153 const std::span<const std::int8_t>& bc0,
154 const std::span<const std::int8_t>& bc1,
155 const std::function<
void(T*,
const T*,
const T*,
156 const scalar_value_type_t<T>*,
const int*,
157 const std::uint8_t*)>& kernel,
158 const std::span<const T>& coeffs,
int cstride,
159 const std::span<const T>& constants,
160 const std::span<const std::uint32_t>& cell_info)
168 std::span<const double> x_g = mesh.
geometry().
x();
171 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * num_dofs_g);
172 const int num_dofs0 = dofmap0.
links(0).size();
173 const int num_dofs1 = dofmap1.
links(0).size();
174 const int ndim0 = bs0 * num_dofs0;
175 const int ndim1 = bs1 * num_dofs1;
176 std::vector<T> Ae(ndim0 * ndim1);
177 const std::span<T> _Ae(Ae);
178 assert(facets.size() % 2 == 0);
179 for (std::size_t index = 0; index < facets.size(); index += 2)
181 std::int32_t
cell = facets[index];
182 std::int32_t local_facet = facets[index + 1];
186 for (std::size_t i = 0; i < x_dofs.size(); ++i)
188 common::impl::copy_N<3>(std::next(x_g.begin(), 3 * x_dofs[i]),
189 std::next(coordinate_dofs.begin(), 3 * i));
193 std::fill(Ae.begin(), Ae.end(), 0);
194 kernel(Ae.data(), coeffs.data() + index / 2 * cstride, constants.data(),
195 coordinate_dofs.data(), &local_facet,
nullptr);
197 dof_transform(_Ae, cell_info,
cell, ndim1);
198 dof_transform_to_transpose(_Ae, cell_info,
cell, ndim0);
205 for (
int i = 0; i < num_dofs0; ++i)
207 for (
int k = 0; k < bs0; ++k)
209 if (bc0[bs0 * dofs0[i] + k])
212 const int row = bs0 * i + k;
213 std::fill_n(std::next(Ae.begin(), ndim1 * row), ndim1, 0.0);
220 for (
int j = 0; j < num_dofs1; ++j)
222 for (
int k = 0; k < bs1; ++k)
224 if (bc1[bs1 * dofs1[j] + k])
227 const int col = bs1 * j + k;
228 for (
int row = 0; row < ndim0; ++row)
229 Ae[row * ndim1 + col] = 0.0;
235 mat_set(dofs0, dofs1, Ae);
240 template <
typename T,
typename U>
241 void assemble_interior_facets(
243 const std::span<const std::int32_t>& facets,
244 const std::function<
void(
const std::span<T>&,
245 const std::span<const std::uint32_t>&,
246 std::int32_t,
int)>& dof_transform,
247 const DofMap& dofmap0,
int bs0,
248 const std::function<
void(
const std::span<T>&,
249 const std::span<const std::uint32_t>&,
250 std::int32_t,
int)>& dof_transform_to_transpose,
251 const DofMap& dofmap1,
int bs1,
const std::span<const std::int8_t>& bc0,
252 const std::span<const std::int8_t>& bc1,
253 const std::function<
void(T*,
const T*,
const T*,
254 const scalar_value_type_t<T>*,
const int*,
255 const std::uint8_t*)>& kernel,
256 const std::span<const T>& coeffs,
int cstride,
257 const std::span<const int>& offsets,
const std::span<const T>& constants,
258 const std::span<const std::uint32_t>& cell_info,
259 const std::function<std::uint8_t(std::size_t)>& get_perm)
269 std::span<const double> x_g = mesh.
geometry().
x();
272 using X = scalar_value_type_t<T>;
273 std::vector<X> coordinate_dofs(2 * num_dofs_g * 3);
274 std::span<X> cdofs0(coordinate_dofs.data(), num_dofs_g * 3);
275 std::span<X> cdofs1(coordinate_dofs.data() + num_dofs_g * 3, num_dofs_g * 3);
277 std::vector<T> Ae, be;
278 std::vector<T> coeff_array(2 * offsets.back());
279 assert(offsets.back() == cstride);
281 const int num_cell_facets
285 std::vector<std::int32_t> dmapjoint0, dmapjoint1;
286 assert(facets.size() % 4 == 0);
287 for (std::size_t index = 0; index < facets.size(); index += 4)
289 std::array<std::int32_t, 2> cells = {facets[index], facets[index + 2]};
290 std::array<std::int32_t, 2> local_facet
291 = {facets[index + 1], facets[index + 3]};
294 auto x_dofs0 = x_dofmap.
links(cells[0]);
295 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
297 common::impl::copy_N<3>(std::next(x_g.begin(), 3 * x_dofs0[i]),
298 std::next(cdofs0.begin(), 3 * i));
300 auto x_dofs1 = x_dofmap.
links(cells[1]);
301 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
303 common::impl::copy_N<3>(std::next(x_g.begin(), 3 * x_dofs1[i]),
304 std::next(cdofs1.begin(), 3 * i));
308 std::span<const std::int32_t> dmap0_cell0 = dofmap0.cell_dofs(cells[0]);
309 std::span<const std::int32_t> dmap0_cell1 = dofmap0.cell_dofs(cells[1]);
310 dmapjoint0.resize(dmap0_cell0.size() + dmap0_cell1.size());
311 std::copy(dmap0_cell0.begin(), dmap0_cell0.end(), dmapjoint0.begin());
312 std::copy(dmap0_cell1.begin(), dmap0_cell1.end(),
313 std::next(dmapjoint0.begin(), dmap0_cell0.size()));
315 std::span<const std::int32_t> dmap1_cell0 = dofmap1.cell_dofs(cells[0]);
316 std::span<const std::int32_t> dmap1_cell1 = dofmap1.cell_dofs(cells[1]);
317 dmapjoint1.resize(dmap1_cell0.size() + dmap1_cell1.size());
318 std::copy(dmap1_cell0.begin(), dmap1_cell0.end(), dmapjoint1.begin());
319 std::copy(dmap1_cell1.begin(), dmap1_cell1.end(),
320 std::next(dmapjoint1.begin(), dmap1_cell0.size()));
322 const int num_rows = bs0 * dmapjoint0.size();
323 const int num_cols = bs1 * dmapjoint1.size();
326 Ae.resize(num_rows * num_cols);
327 std::fill(Ae.begin(), Ae.end(), 0);
329 const std::array perm{
330 get_perm(cells[0] * num_cell_facets + local_facet[0]),
331 get_perm(cells[1] * num_cell_facets + local_facet[1])};
332 kernel(Ae.data(), coeffs.data() + index / 2 * cstride, constants.data(),
333 coordinate_dofs.data(), local_facet.data(), perm.data());
335 const std::span<T> _Ae(Ae);
337 const std::span<T> sub_Ae0
338 = _Ae.subspan(bs0 * dmap0_cell0.size() * num_cols,
339 bs0 * dmap0_cell1.size() * num_cols);
340 const std::span<T> sub_Ae1
341 = _Ae.subspan(bs1 * dmap1_cell0.size(),
342 num_rows * num_cols - bs1 * dmap1_cell0.size());
349 dof_transform(_Ae, cell_info, cells[0], num_cols);
350 dof_transform(sub_Ae0, cell_info, cells[1], num_cols);
351 dof_transform_to_transpose(_Ae, cell_info, cells[0], num_rows);
352 dof_transform_to_transpose(sub_Ae1, cell_info, cells[1], num_rows);
357 for (std::size_t i = 0; i < dmapjoint0.size(); ++i)
359 for (
int k = 0; k < bs0; ++k)
361 if (bc0[bs0 * dmapjoint0[i] + k])
364 std::fill_n(std::next(Ae.begin(), num_cols * (bs0 * i + k)),
372 for (std::size_t j = 0; j < dmapjoint1.size(); ++j)
374 for (
int k = 0; k < bs1; ++k)
376 if (bc1[bs1 * dmapjoint1[j] + k])
379 for (
int m = 0; m < num_rows; ++m)
380 Ae[m * num_cols + bs1 * j + k] = 0.0;
386 mat_set(dmapjoint0, dmapjoint1, Ae);
390 template <
typename T,
typename U>
392 U mat_set,
const Form<T>& a,
const std::span<const T>& constants,
393 const std::map<std::pair<IntegralType, int>,
394 std::pair<std::span<const T>,
int>>& coefficients,
395 const std::span<const std::int8_t>& bc0,
396 const std::span<const std::int8_t>& bc1)
398 std::shared_ptr<const mesh::Mesh> mesh = a.
mesh();
402 std::shared_ptr<const fem::DofMap> dofmap0
404 std::shared_ptr<const fem::DofMap> dofmap1
409 const int bs0 = dofmap0->bs();
411 const int bs1 = dofmap1->bs();
413 std::shared_ptr<const fem::FiniteElement> element0
415 std::shared_ptr<const fem::FiniteElement> element1
417 const std::function<void(
const std::span<T>&,
418 const std::span<const std::uint32_t>&, std::int32_t,
420 = element0->get_dof_transformation_function<T>();
421 const std::function<void(
const std::span<T>&,
422 const std::span<const std::uint32_t>&, std::int32_t,
423 int)>& dof_transform_to_transpose
424 = element1->get_dof_transformation_to_transpose_function<T>();
426 const bool needs_transformation_data
427 = element0->needs_dof_transformations()
428 or element1->needs_dof_transformations()
430 std::span<const std::uint32_t> cell_info;
431 if (needs_transformation_data)
433 mesh->topology_mutable().create_entity_permutations();
434 cell_info = std::span(mesh->topology().get_cell_permutation_info());
441 const std::vector<std::int32_t>& cells = a.
cell_domains(i);
442 impl::assemble_cells(mat_set, mesh->geometry(), cells, dof_transform, dofs0,
443 bs0, dof_transform_to_transpose, dofs1, bs1, bc0, bc1,
444 fn, coeffs, cstride, constants, cell_info);
450 const auto& [coeffs, cstride]
453 impl::assemble_exterior_facets(mat_set, *mesh, facets, dof_transform, dofs0,
454 bs0, dof_transform_to_transpose, dofs1, bs1,
455 bc0, bc1, fn, coeffs, cstride, constants,
461 std::function<std::uint8_t(std::size_t)> get_perm;
464 mesh->topology_mutable().create_entity_permutations();
465 const std::vector<std::uint8_t>& perms
466 = mesh->topology().get_facet_permutations();
467 get_perm = [&perms](std::size_t i) {
return perms[i]; };
470 get_perm = [](std::size_t) {
return 0; };
476 const auto& [coeffs, cstride]
479 impl::assemble_interior_facets(
480 mat_set, *mesh, facets, dof_transform, *dofmap0, bs0,
481 dof_transform_to_transpose, *dofmap1, bs1, bc0, bc1, fn, coeffs,
482 cstride, c_offsets, constants, cell_info, get_perm);
Degree-of-freedeom map representations ans tools.
int dim() const
The dimension of the geometry element space.
Definition: CoordinateElement.cpp:183
Degree-of-freedom map.
Definition: DofMap.h:71
This class provides a static adjacency list data structure. It is commonly used to store directed gra...
Definition: AdjacencyList.h:26
std::span< T > links(int node)
Get the links (edges) for given node.
Definition: AdjacencyList.h:111
Geometry stores the geometry imposed on a mesh.
Definition: Geometry.h:28
const graph::AdjacencyList< std::int32_t > & dofmap() const
DOF map.
Definition: Geometry.cpp:21
std::span< const double > x() const
Access geometry degrees-of-freedom data (const version).
Definition: Geometry.cpp:33
const fem::CoordinateElement & cmap() const
The element that describes the geometry map.
Definition: Geometry.cpp:35
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition: Mesh.h:33
Geometry & geometry()
Get mesh geometry.
Definition: Mesh.cpp:450
Topology & topology()
Get mesh topology.
Definition: Mesh.cpp:444
int dim() const noexcept
Return the topological dimension of the mesh.
Definition: Topology.cpp:776
CellType cell_type() const noexcept
Cell type.
Definition: Topology.cpp:910
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
void assemble_matrix(U mat_add, const Form< T > &a, const std::span< const T > &constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int >> &coefficients, const std::vector< std::shared_ptr< const DirichletBC< T >>> &bcs)
Assemble bilinear form into a matrix.
Definition: assembler.h:200
int cell_num_entities(CellType type, int dim)
Number of entities of dimension dim.
Definition: cell_types.cpp:182