12 #include <dolfinx/fem/FunctionSpace.h>
13 #include <dolfinx/graph/AdjacencyList.h>
14 #include <dolfinx/la/utils.h>
15 #include <dolfinx/mesh/Geometry.h>
16 #include <dolfinx/mesh/Mesh.h>
17 #include <dolfinx/mesh/Topology.h>
22 namespace dolfinx::fem::impl
33 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
34 const std::int32_t*,
const T*)>& mat_set_values,
35 const Form<T>& a,
const std::vector<bool>& bc0,
36 const std::vector<bool>& bc1);
41 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
42 const std::int32_t*,
const T*)>& mat_set_values,
44 const std::vector<std::int32_t>& active_cells,
47 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
48 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
49 const std::uint8_t*,
const std::uint32_t)>& kernel,
50 const array2d<T>& coeffs,
const std::vector<T>& constants,
51 const std::vector<std::uint32_t>& cell_info);
55 void assemble_exterior_facets(
56 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
57 const std::int32_t*,
const T*)>& mat_set_values,
58 const mesh::Mesh& mesh,
const std::vector<std::int32_t>& active_facets,
61 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
62 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
63 const std::uint8_t*,
const std::uint32_t)>& fn,
64 const array2d<T>& coeffs,
const std::vector<T>& constants,
65 const std::vector<std::uint32_t>& cell_info,
66 const std::vector<std::uint8_t>& perms);
70 void assemble_interior_facets(
71 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
72 const std::int32_t*,
const T*)>& mat_set_values,
73 const mesh::Mesh& mesh,
const std::vector<std::int32_t>& active_facets,
74 const DofMap& dofmap0,
int bs0,
const DofMap& dofmap1,
int bs1,
75 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
76 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
77 const std::uint8_t*,
const std::uint32_t)>& kernel,
78 const array2d<T>& coeffs,
const std::vector<int>& offsets,
79 const std::vector<T>& constants,
80 const std::vector<std::uint32_t>& cell_info,
81 const std::vector<std::uint8_t>& perms);
86 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
87 const std::int32_t*,
const T*)>& mat_set_values,
88 const Form<T>& a,
const std::vector<bool>& bc0,
89 const std::vector<bool>& bc1)
91 std::shared_ptr<const mesh::Mesh> mesh = a.
mesh();
93 const int tdim = mesh->topology().dim();
94 const std::int32_t num_cells
95 = mesh->topology().connectivity(tdim, 0)->num_nodes();
98 std::shared_ptr<const fem::DofMap> dofmap0
100 std::shared_ptr<const fem::DofMap> dofmap1
105 const int bs0 = dofmap0->bs();
107 const int bs1 = dofmap1->bs();
116 if (needs_permutation_data)
117 mesh->topology_mutable().create_entity_permutations();
118 const std::vector<std::uint32_t>& cell_info
119 = needs_permutation_data ? mesh->topology().get_cell_permutation_info()
120 : std::vector<std::uint32_t>(num_cells);
124 const auto& fn = a.
kernel(IntegralType::cell, i);
125 const std::vector<std::int32_t>& active_cells
126 = a.
domains(IntegralType::cell, i);
127 impl::assemble_cells<T>(mat_set_values, mesh->geometry(), active_cells,
128 dofs0, bs0, dofs1, bs1, bc0, bc1, fn, coeffs,
129 constants, cell_info);
135 mesh->topology_mutable().create_connectivity(tdim - 1, tdim);
136 mesh->topology_mutable().create_entity_permutations();
138 const std::vector<std::uint8_t>& perms
139 = mesh->topology().get_facet_permutations();
141 for (
int i : a.
integral_ids(IntegralType::exterior_facet))
143 const auto& fn = a.
kernel(IntegralType::exterior_facet, i);
144 const std::vector<std::int32_t>& active_facets
145 = a.
domains(IntegralType::exterior_facet, i);
146 impl::assemble_exterior_facets<T>(mat_set_values, *mesh, active_facets,
147 dofs0, bs0, dofs1, bs1, bc0, bc1, fn,
148 coeffs, constants, cell_info, perms);
152 for (
int i : a.
integral_ids(IntegralType::interior_facet))
154 const auto& fn = a.
kernel(IntegralType::interior_facet, i);
155 const std::vector<std::int32_t>& active_facets
156 = a.
domains(IntegralType::interior_facet, i);
157 impl::assemble_interior_facets<T>(
158 mat_set_values, *mesh, active_facets, *dofmap0, bs0, *dofmap1, bs1,
159 bc0, bc1, fn, coeffs, c_offsets, constants, cell_info, perms);
164 template <
typename T>
166 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
167 const std::int32_t*,
const T*)>& mat_set,
169 const std::vector<std::int32_t>& active_cells,
172 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
173 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
174 const std::uint8_t*,
const std::uint32_t)>& kernel,
175 const array2d<T>& coeffs,
const std::vector<T>& constants,
176 const std::vector<std::uint32_t>& cell_info)
178 const std::size_t gdim = geometry.
dim();
184 const std::size_t num_dofs_g = x_dofmap.
num_links(0);
185 const xt::xtensor<double, 2>& x_g = geometry.
x();
188 const int num_dofs0 = dofmap0.
links(0).size();
189 const int num_dofs1 = dofmap1.
links(0).size();
190 const int ndim0 = bs0 * num_dofs0;
191 const int ndim1 = bs1 * num_dofs1;
192 std::vector<T> Ae(ndim0 * ndim1);
193 std::vector<double> coordinate_dofs(num_dofs_g * gdim);
194 for (std::int32_t c : active_cells)
197 auto x_dofs = x_dofmap.
links(c);
198 for (std::size_t i = 0; i < x_dofs.size(); ++i)
200 std::copy_n(xt::row(x_g, x_dofs[i]).begin(), gdim,
201 std::next(coordinate_dofs.begin(), i * gdim));
205 std::fill(Ae.begin(), Ae.end(), 0);
206 kernel(Ae.data(), coeffs.
row(c).data(), constants.data(),
207 coordinate_dofs.data(),
nullptr,
nullptr, cell_info[c]);
210 auto dofs0 = dofmap0.
links(c);
211 auto dofs1 = dofmap1.
links(c);
214 for (
int i = 0; i < num_dofs0; ++i)
216 for (
int k = 0; k < bs0; ++k)
218 if (bc0[bs0 * dofs0[i] + k])
221 const int row = bs0 * i + k;
222 std::fill_n(std::next(Ae.begin(), ndim1 * row), ndim1, 0.0);
230 for (
int j = 0; j < num_dofs1; ++j)
232 for (
int k = 0; k < bs1; ++k)
234 if (bc1[bs1 * dofs1[j] + k])
237 const int col = bs1 * j + k;
238 for (
int row = 0; row < ndim0; ++row)
239 Ae[row * ndim1 + col] = 0.0;
245 mat_set(dofs0.size(), dofs0.data(), dofs1.size(), dofs1.data(), Ae.data());
249 template <
typename T>
250 void assemble_exterior_facets(
251 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
252 const std::int32_t*,
const T*)>& mat_set_values,
253 const mesh::Mesh& mesh,
const std::vector<std::int32_t>& active_facets,
256 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
257 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
258 const std::uint8_t*,
const std::uint32_t)>& kernel,
259 const array2d<T>& coeffs,
const std::vector<T>& constants,
260 const std::vector<std::uint32_t>& cell_info,
261 const std::vector<std::uint8_t>& perms)
270 const std::size_t num_dofs_g = x_dofmap.
num_links(0);
271 const xt::xtensor<double, 2>& x_g = mesh.
geometry().
x();
274 std::vector<double> coordinate_dofs(num_dofs_g * gdim);
275 const int num_dofs0 = dofmap0.
links(0).size();
276 const int num_dofs1 = dofmap1.
links(0).size();
277 const int ndim0 = bs0 * num_dofs0;
278 const int ndim1 = bs1 * num_dofs1;
279 std::vector<T> Ae(ndim0 * ndim1);
286 for (std::int32_t f : active_facets)
288 auto cells = f_to_c->links(f);
289 assert(cells.size() == 1);
292 auto facets = c_to_f->links(cells[0]);
293 auto it = std::find(facets.begin(), facets.end(), f);
294 assert(it != facets.end());
295 const int local_facet = std::distance(facets.begin(), it);
298 auto x_dofs = x_dofmap.
links(cells[0]);
299 for (std::size_t i = 0; i < x_dofs.size(); ++i)
301 std::copy_n(xt::row(x_g, x_dofs[i]).begin(), gdim,
302 std::next(coordinate_dofs.begin(), i * gdim));
306 std::fill(Ae.begin(), Ae.end(), 0);
307 kernel(Ae.data(), coeffs.
row(cells[0]).data(), constants.data(),
308 coordinate_dofs.data(), &local_facet,
309 &perms[cells[0] * facets.size() + local_facet], cell_info[cells[0]]);
312 auto dofs0 = dofmap0.
links(cells[0]);
313 auto dofs1 = dofmap1.
links(cells[0]);
316 for (
int i = 0; i < num_dofs0; ++i)
318 for (
int k = 0; k < bs0; ++k)
320 if (bc0[bs0 * dofs0[i] + k])
323 const int row = bs0 * i + k;
324 std::fill_n(std::next(Ae.begin(), ndim1 * row), ndim1, 0.0);
331 for (
int j = 0; j < num_dofs1; ++j)
333 for (
int k = 0; k < bs1; ++k)
335 if (bc1[bs1 * dofs1[j] + k])
338 const int col = bs1 * j + k;
339 for (
int row = 0; row < ndim0; ++row)
340 Ae[row * ndim1 + col] = 0.0;
346 mat_set_values(dofs0.size(), dofs0.data(), dofs1.size(), dofs1.data(),
351 template <
typename T>
352 void assemble_interior_facets(
353 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
354 const std::int32_t*,
const T*)>& mat_set_values,
355 const mesh::Mesh& mesh,
const std::vector<std::int32_t>& active_facets,
356 const DofMap& dofmap0,
int bs0,
const DofMap& dofmap1,
int bs1,
357 const std::vector<bool>& bc0,
const std::vector<bool>& bc1,
358 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
359 const std::uint8_t*,
const std::uint32_t)>& fn,
360 const array2d<T>& coeffs,
const std::vector<int>& offsets,
361 const std::vector<T>& constants,
362 const std::vector<std::uint32_t>& cell_info,
363 const std::vector<std::uint8_t>& perms)
372 const std::size_t num_dofs_g = x_dofmap.
num_links(0);
373 const xt::xtensor<double, 2>& x_g = mesh.
geometry().
x();
376 xt::xtensor<double, 3> coordinate_dofs({2, num_dofs_g, gdim});
377 std::vector<T> Ae, be;
378 std::vector<T> coeff_array(2 * offsets.back());
379 assert(offsets.back() == coeffs.
shape[1]);
382 std::vector<std::int32_t> dmapjoint0, dmapjoint1;
389 for (std::int32_t facet_index : active_facets)
392 auto cells = c->links(facet_index);
393 assert(cells.size() == 2);
396 auto facets0 = c_to_f->links(cells[0]);
397 const auto* it0 = std::find(facets0.begin(), facets0.end(), facet_index);
398 assert(it0 != facets0.end());
399 const int local_facet0 = std::distance(facets0.begin(), it0);
400 auto facets1 = c_to_f->links(cells[1]);
401 const auto* it1 = std::find(facets1.begin(), facets1.end(), facet_index);
402 assert(it1 != facets1.end());
403 const int local_facet1 = std::distance(facets1.begin(), it1);
405 const std::array local_facet{local_facet0, local_facet1};
408 auto x_dofs0 = x_dofmap.
links(cells[0]);
409 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
411 std::copy_n(xt::view(x_g, x_dofs0[i]).begin(), gdim,
412 xt::view(coordinate_dofs, 0, i, xt::all()).begin());
414 auto x_dofs1 = x_dofmap.
links(cells[1]);
415 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
417 std::copy_n(xt::view(x_g, x_dofs1[i]).begin(), gdim,
418 xt::view(coordinate_dofs, 1, i, xt::all()).begin());
422 xtl::span<const std::int32_t> dmap0_cell0 = dofmap0.
cell_dofs(cells[0]);
423 xtl::span<const std::int32_t> dmap0_cell1 = dofmap0.
cell_dofs(cells[1]);
424 dmapjoint0.resize(dmap0_cell0.size() + dmap0_cell1.size());
425 std::copy(dmap0_cell0.begin(), dmap0_cell0.end(), dmapjoint0.begin());
426 std::copy(dmap0_cell1.begin(), dmap0_cell1.end(),
427 std::next(dmapjoint0.begin(), dmap0_cell0.size()));
429 xtl::span<const std::int32_t> dmap1_cell0 = dofmap1.
cell_dofs(cells[0]);
430 xtl::span<const std::int32_t> dmap1_cell1 = dofmap1.
cell_dofs(cells[1]);
431 dmapjoint1.resize(dmap1_cell0.size() + dmap1_cell1.size());
432 std::copy(dmap1_cell0.begin(), dmap1_cell0.end(), dmapjoint1.begin());
433 std::copy(dmap1_cell1.begin(), dmap1_cell1.end(),
434 std::next(dmapjoint1.begin(), dmap1_cell0.size()));
438 auto coeff_cell0 = coeffs.
row(cells[0]);
439 auto coeff_cell1 = coeffs.
row(cells[1]);
442 for (std::size_t i = 0; i < offsets.size() - 1; ++i)
445 const int num_entries = offsets[i + 1] - offsets[i];
446 std::copy_n(coeff_cell0.data() + offsets[i], num_entries,
447 std::next(coeff_array.begin(), 2 * offsets[i]));
448 std::copy_n(coeff_cell1.data() + offsets[i], num_entries,
449 std::next(coeff_array.begin(), offsets[i + 1] + offsets[i]));
452 const int num_rows = bs0 * dmapjoint0.size();
453 const int num_cols = bs1 * dmapjoint1.size();
456 Ae.resize(num_rows * num_cols);
457 std::fill(Ae.begin(), Ae.end(), 0);
459 const int facets_per_cell = facets0.size();
460 const std::array perm{perms[cells[0] * facets_per_cell + local_facet[0]],
461 perms[cells[1] * facets_per_cell + local_facet[1]]};
462 fn(Ae.data(), coeff_array.data(), constants.data(), coordinate_dofs.data(),
463 local_facet.data(), perm.data(), cell_info[cells[0]]);
468 for (std::size_t i = 0; i < dmapjoint0.size(); ++i)
470 for (
int k = 0; k < bs0; ++k)
472 if (bc0[bs0 * dmapjoint0[i] + k])
475 std::fill_n(std::next(Ae.begin(), num_cols * (bs0 * i + k)),
483 for (std::size_t j = 0; j < dmapjoint1.size(); ++j)
485 for (
int k = 0; k < bs1; ++k)
487 if (bc1[bs1 * dmapjoint1[j] + k])
490 for (
int m = 0; m < num_rows; ++m)
491 Ae[m * num_cols + bs1 * j + k] = 0.0;
497 mat_set_values(dmapjoint0.size(), dmapjoint0.data(), dmapjoint1.size(),
498 dmapjoint1.data(), Ae.data());