10 #include <dolfinx/common/IndexMap.h>
11 #include <dolfinx/fem/DofMap.h>
12 #include <dolfinx/fem/FunctionSpace.h>
13 #include <dolfinx/la/SparsityPattern.h>
14 #include <dolfinx/mesh/Mesh.h>
17 #include <xtl/xspan.hpp>
63 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
64 const std::int32_t*,
const T*)>& mat_set,
68 using namespace dolfinx;
71 const std::function<
int(std::int32_t,
const std::int32_t*, std::int32_t,
72 const std::int32_t*,
const T*)>& mat_set,
76 std::shared_ptr<const mesh::Mesh> mesh = V0.
mesh();
81 if (mesh != V1.
mesh())
83 throw std::runtime_error(
"Compute discrete gradient operator. Function "
84 "spaces do not share the same mesh");
88 mesh->topology_mutable().create_entities(1);
89 std::int64_t num_edges_global = mesh->topology().index_map(1)->size_global();
90 const std::int64_t V0dim
91 = V0.
dofmap()->index_map->size_global() * V0.
dofmap()->index_map_bs();
92 if (V0dim != num_edges_global)
94 throw std::runtime_error(
95 "Cannot compute discrete gradient operator. Function "
96 "spaces is not a lowest-order edge space");
100 const std::int64_t num_vertices_global
101 = mesh->topology().index_map(0)->size_global();
102 const std::int64_t V1dim
103 = V1.
dofmap()->index_map->size_global() * V1.
dofmap()->index_map_bs();
104 if (V1dim != num_vertices_global)
106 throw std::runtime_error(
107 "Cannot compute discrete gradient operator. Function "
108 "space is not a linear nodal function space");
112 std::shared_ptr<const dolfinx::fem::ElementDofLayout> layout0
113 = V0.
dofmap()->element_dof_layout;
114 std::shared_ptr<const dolfinx::fem::ElementDofLayout> layout1
115 = V1.
dofmap()->element_dof_layout;
118 std::array<std::shared_ptr<const common::IndexMap>, 2> index_maps
120 std::array<int, 2> block_sizes
121 = {V0.
dofmap()->index_map_bs(), V1.
dofmap()->index_map_bs()};
122 std::vector<std::array<std::int64_t, 2>> local_range
123 = {index_maps[0]->local_range(), index_maps[1]->local_range()};
124 assert(block_sizes[0] == block_sizes[1]);
127 const int tdim = mesh->topology().dim();
128 mesh->topology_mutable().create_connectivity(1, 0);
129 auto e_to_v = mesh->topology().connectivity(1, 0);
130 mesh->topology_mutable().create_connectivity(tdim, 1);
131 auto c_to_e = mesh->topology().connectivity(tdim, 1);
132 mesh->topology_mutable().create_connectivity(1, tdim);
133 auto e_to_c = mesh->topology().connectivity(1, tdim);
134 mesh->topology_mutable().create_connectivity(tdim, 0);
135 auto c_to_v = mesh->topology().connectivity(tdim, 0);
138 const std::int32_t num_edges = mesh->topology().index_map(1)->size_local()
139 + mesh->topology().index_map(1)->num_ghosts();
140 const std::shared_ptr<const fem::DofMap> dofmap0 = V0.
dofmap();
143 const int num_edges_per_cell
145 std::map<std::int32_t, std::vector<std::int32_t>> local_edge_dofs;
146 for (std::int32_t i = 0; i < num_edges_per_cell; ++i)
147 local_edge_dofs[i] = layout0->entity_dofs(1, i);
149 const int num_vertices_per_cell
151 std::map<std::int32_t, std::vector<std::int32_t>> local_vertex_dofs;
152 for (std::int32_t i = 0; i < num_vertices_per_cell; ++i)
153 local_vertex_dofs[i] = layout1->entity_dofs(0, i);
156 const std::shared_ptr<const fem::DofMap> dofmap1 = V1.
dofmap();
158 const std::vector<std::int64_t>& global_indices
159 = mesh->topology().index_map(0)->global_indices();
161 for (std::int32_t e = 0; e < num_edges; ++e)
164 xtl::span<const std::int32_t> cells = e_to_c->links(e);
165 assert(cells.size() > 0);
166 const std::int32_t cell = cells[0];
167 xtl::span<const std::int32_t> edges = c_to_e->links(cell);
168 const auto it = std::find(edges.begin(), edges.end(), e);
169 assert(it != edges.end());
170 const int local_edge = std::distance(edges.begin(), it);
173 xtl::span<const std::int32_t> dofs0 = dofmap0->cell_dofs(cell);
174 std::vector<std::int32_t>& local_dofs = local_edge_dofs[local_edge];
175 assert(local_dofs.size() == 1);
176 const std::int32_t row = dofs0[local_dofs[0]];
178 xtl::span<const std::int32_t> vertices = e_to_v->links(e);
179 assert(vertices.size() == 2);
180 xtl::span<const std::int32_t> cell_vertices = c_to_v->links(cell);
183 std::array<std::int32_t, 2> cols;
184 xtl::span<const std::int32_t> dofs1 = dofmap1->cell_dofs(cell);
185 for (std::int32_t i = 0; i < 2; ++i)
188 = std::find(cell_vertices.begin(), cell_vertices.end(), vertices[i]);
189 assert(it != cell_vertices.end());
190 const int local_vertex = std::distance(cell_vertices.begin(), it);
192 std::vector<std::int32_t>& local_v_dofs = local_vertex_dofs[local_vertex];
193 assert(local_v_dofs.size() == 1);
194 cols[i] = dofs1[local_v_dofs[0]];
197 if (global_indices[vertices[1]] < global_indices[vertices[0]])
202 mat_set(1, &row, 2, cols.data(), Ae.data());
This class represents a finite element function space defined by a mesh, a finite element,...
Definition: FunctionSpace.h:31
std::shared_ptr< const fem::DofMap > dofmap() const
The dofmap.
Definition: FunctionSpace.cpp:225
std::shared_ptr< const mesh::Mesh > mesh() const
The mesh.
Definition: FunctionSpace.cpp:218
This class provides a sparsity pattern data structure that can be used to initialize sparse matrices.
Definition: SparsityPattern.h:33
Finite element method functionality.
Definition: assemble_matrix_impl.h:23
void assemble_discrete_gradient(const std::function< int(std::int32_t, const std::int32_t *, std::int32_t, const std::int32_t *, const T *)> &mat_set, const fem::FunctionSpace &V0, const fem::FunctionSpace &V1)
Definition: discreteoperators.h:70
la::SparsityPattern create_sparsity_discrete_gradient(const fem::FunctionSpace &V0, const fem::FunctionSpace &V1)
Definition: discreteoperators.cpp:13
int cell_num_entities(mesh::CellType type, int dim)
Number of entities of dimension dim.
Definition: cell_types.cpp:183