11 #include <dolfinx/common/IndexMap.h>
12 #include <dolfinx/common/types.h>
13 #include <dolfinx/fem/Constant.h>
14 #include <dolfinx/fem/FunctionSpace.h>
15 #include <dolfinx/mesh/Geometry.h>
16 #include <dolfinx/mesh/Mesh.h>
17 #include <dolfinx/mesh/Topology.h>
21 namespace dolfinx::fem::impl
26 T assemble_cells(
const mesh::Geometry& geometry,
27 const xtl::span<const std::int32_t>& active_cells,
28 const std::function<
void(T*,
const T*,
const T*,
const double*,
29 const int*,
const std::uint8_t*)>& fn,
30 const xtl::span<const T>& constants,
const array2d<T>& coeffs)
33 const graph::AdjacencyList<std::int32_t>& x_dofmap = geometry.dofmap();
36 const std::size_t num_dofs_g = x_dofmap.num_links(0);
37 const xt::xtensor<double, 2>& x_g = geometry.x();
40 std::vector<double> coordinate_dofs(3 * num_dofs_g);
44 for (std::int32_t c : active_cells)
47 auto x_dofs = x_dofmap.links(c);
48 for (std::size_t i = 0; i < x_dofs.size(); ++i)
50 std::copy_n(xt::row(x_g, x_dofs[i]).begin(), 3,
51 std::next(coordinate_dofs.begin(), 3 * i));
54 auto coeff_cell = coeffs.row(c);
55 fn(&value, coeff_cell.data(), constants.data(), coordinate_dofs.data(),
64 T assemble_exterior_facets(
65 const mesh::Mesh& mesh,
const xtl::span<const std::int32_t>& active_facets,
66 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
67 const std::uint8_t*)>& fn,
68 const xtl::span<const T>& constants,
const array2d<T>& coeffs,
69 const xtl::span<const std::uint8_t>& perms)
71 const int tdim = mesh.topology().dim();
74 const graph::AdjacencyList<std::int32_t>& x_dofmap = mesh.geometry().dofmap();
77 const std::size_t num_dofs_g = x_dofmap.num_links(0);
78 const xt::xtensor<double, 2>& x_g = mesh.geometry().x();
81 std::vector<double> coordinate_dofs(3 * num_dofs_g);
83 auto f_to_c = mesh.topology().connectivity(tdim - 1, tdim);
85 auto c_to_f = mesh.topology().connectivity(tdim, tdim - 1);
90 for (std::int32_t facet : active_facets)
93 assert(f_to_c->num_links(facet) == 1);
94 const int cell = f_to_c->links(facet)[0];
97 auto facets = c_to_f->links(cell);
98 auto it = std::find(facets.begin(), facets.end(), facet);
99 assert(it != facets.end());
100 const int local_facet = std::distance(facets.data(), it);
103 auto x_dofs = x_dofmap.links(cell);
104 for (std::size_t i = 0; i < x_dofs.size(); ++i)
106 std::copy_n(xt::row(x_g, x_dofs[i]).begin(), 3,
107 std::next(coordinate_dofs.begin(), 3 * i));
110 auto coeff_cell = coeffs.row(cell);
111 fn(&value, coeff_cell.data(), constants.data(), coordinate_dofs.data(),
112 &local_facet, &perms[cell * facets.size() + local_facet]);
119 template <
typename T>
120 T assemble_interior_facets(
121 const mesh::Mesh& mesh,
const xtl::span<const std::int32_t>& active_facets,
122 const std::function<
void(T*,
const T*,
const T*,
const double*,
const int*,
123 const std::uint8_t*)>& fn,
124 const xtl::span<const T>& constants,
const array2d<T>& coeffs,
125 const xtl::span<const int>& offsets,
126 const xtl::span<const std::uint8_t>& perms)
128 const int tdim = mesh.topology().dim();
131 const graph::AdjacencyList<std::int32_t>& x_dofmap = mesh.geometry().dofmap();
134 const std::size_t num_dofs_g = x_dofmap.num_links(0);
135 const xt::xtensor<double, 2>& x_g = mesh.geometry().x();
138 xt::xtensor<double, 3> coordinate_dofs({2, num_dofs_g, 3});
139 std::vector<T> coeff_array(2 * offsets.back());
140 assert(offsets.back() == coeffs.shape[1]);
142 auto f_to_c = mesh.topology().connectivity(tdim - 1, tdim);
144 auto c_to_f = mesh.topology().connectivity(tdim, tdim - 1);
149 for (std::int32_t f : active_facets)
152 auto cells = f_to_c->links(f);
153 assert(
cells.size() == 2);
155 const int facets_per_cell = c_to_f->num_links(cells[0]);
158 std::array<int, 2> local_facet;
159 for (
int i = 0; i < 2; ++i)
161 auto facets = c_to_f->links(cells[i]);
162 auto it = std::find(facets.begin(), facets.end(), f);
163 assert(it != facets.end());
164 local_facet[i] = std::distance(facets.begin(), it);
168 auto x_dofs0 = x_dofmap.links(cells[0]);
169 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
171 std::copy_n(xt::view(x_g, x_dofs0[i]).begin(), 3,
172 xt::view(coordinate_dofs, 0, i, xt::all()).begin());
174 auto x_dofs1 = x_dofmap.links(cells[1]);
175 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
177 std::copy_n(xt::view(x_g, x_dofs1[i]).begin(), 3,
178 xt::view(coordinate_dofs, 1, i, xt::all()).begin());
183 auto coeff_cell0 = coeffs.row(cells[0]);
184 auto coeff_cell1 = coeffs.row(cells[1]);
187 for (std::size_t i = 0; i < offsets.size() - 1; ++i)
190 const int num_entries = offsets[i + 1] - offsets[i];
191 std::copy_n(coeff_cell0.data() + offsets[i], num_entries,
192 std::next(coeff_array.begin(), 2 * offsets[i]));
193 std::copy_n(coeff_cell1.data() + offsets[i], num_entries,
194 std::next(coeff_array.begin(), offsets[i + 1] + offsets[i]));
197 const std::array perm{perms[
cells[0] * facets_per_cell + local_facet[0]],
198 perms[
cells[1] * facets_per_cell + local_facet[1]]};
199 fn(&value, coeff_array.data(), constants.data(), coordinate_dofs.data(),
200 local_facet.data(), perm.data());
207 template <
typename T>
208 T
assemble_scalar(
const fem::Form<T>& M,
const xtl::span<const T>& constants,
209 const array2d<T>& coeffs)
211 std::shared_ptr<const mesh::Mesh> mesh = M.mesh();
213 const int tdim = mesh->topology().dim();
216 for (
int i : M.integral_ids(IntegralType::cell))
218 const auto& fn = M.kernel(IntegralType::cell, i);
219 const std::vector<std::int32_t>& active_cells
220 = M.domains(IntegralType::cell, i);
221 value += impl::assemble_cells(mesh->geometry(), active_cells, fn, constants,
225 if (M.num_integrals(IntegralType::exterior_facet) > 0
226 or M.num_integrals(IntegralType::interior_facet) > 0)
229 mesh->topology_mutable().create_entities(tdim - 1);
230 mesh->topology_mutable().create_connectivity(tdim - 1, tdim);
231 mesh->topology_mutable().create_entity_permutations();
233 const std::vector<std::uint8_t>& perms
234 = mesh->topology().get_facet_permutations();
236 for (
int i : M.integral_ids(IntegralType::exterior_facet))
238 const auto& fn = M.kernel(IntegralType::exterior_facet, i);
239 const std::vector<std::int32_t>& active_facets
240 = M.domains(IntegralType::exterior_facet, i);
241 value += impl::assemble_exterior_facets(*mesh, active_facets, fn,
242 constants, coeffs, perms);
245 const std::vector<int> c_offsets = M.coefficient_offsets();
246 for (
int i : M.integral_ids(IntegralType::interior_facet))
248 const auto& fn = M.kernel(IntegralType::interior_facet, i);
249 const std::vector<std::int32_t>& active_facets
250 = M.domains(IntegralType::interior_facet, i);
251 value += impl::assemble_interior_facets(
252 *mesh, active_facets, fn, constants, coeffs, c_offsets, perms);
void cells(la::SparsityPattern &pattern, const mesh::Topology &topology, const std::array< const std::reference_wrapper< const fem::DofMap >, 2 > &dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition: sparsitybuild.cpp:18
T assemble_scalar(const Form< T > &M, const xtl::span< const T > &constants, const array2d< T > &coeffs)
Assemble functional into scalar. The caller supplies the form constants and coefficients for this ver...
Definition: assembler.h:36