38
38
void SparsityPatternBuilder::build(GenericSparsityPattern& sparsity_pattern,
40
40
const std::vector<const GenericDofMap*> dofmaps,
41
const std::vector<std::pair<std::pair<uint, uint>, std::pair<uint, uint> > >& master_slave_dofs,
41
const std::vector<std::pair<std::pair<std::size_t, std::size_t>, std::pair<std::size_t, std::size_t> > >& master_slave_dofs,
42
42
bool cells, bool interior_facets, bool exterior_facets, bool diagonal)
44
const uint rank = dofmaps.size();
44
const std::size_t rank = dofmaps.size();
46
46
// Get global dimensions and local range
47
std::vector<uint> global_dimensions(rank);
48
std::vector<std::pair<uint, uint> > local_range(rank);
49
std::vector<const boost::unordered_map<uint, uint>* > off_process_owner(rank);
50
for (uint i = 0; i < rank; ++i)
47
std::vector<std::size_t> global_dimensions(rank);
48
std::vector<std::pair<std::size_t, std::size_t> > local_range(rank);
49
std::vector<const boost::unordered_map<std::size_t, std::size_t>* > off_process_owner(rank);
50
for (std::size_t i = 0; i < rank; ++i)
52
52
global_dimensions[i] = dofmaps[i]->global_dimension();
53
53
local_range[i] = dofmaps[i]->ownership_range();
65
65
// Create vector to point to dofs
66
std::vector<const std::vector<uint>* > dofs(rank);
66
std::vector<const std::vector<DolfinIndex>* > dofs(rank);
68
// FIXME: We iterate over the entire mesh even if the function space
69
// is restricted. This works out fine since the local dofmap
70
// returned on each cell will be an empty vector, but we might think
71
// about optimizing this further.
68
73
// Build sparsity pattern for cell integrals
72
77
for (CellIterator cell(mesh); !cell.end(); ++cell)
74
79
// Tabulate dofs for each dimension and get local dimensions
75
for (uint i = 0; i < rank; ++i)
80
for (std::size_t i = 0; i < rank; ++i)
76
81
dofs[i] = &dofmaps[i]->cell_dofs(cell->index());
78
83
// Insert non-zeroes in sparsity pattern
85
90
// are included when tabulating dofs on all cells
87
92
// Build sparsity pattern for interior/exterior facet integrals
88
const uint D = mesh.topology().dim();
93
const std::size_t D = mesh.topology().dim();
89
94
if (interior_facets || exterior_facets)
91
96
// Compute facets and facet - cell connectivity if not already computed
102
107
// Vector to store macro-dofs (for interior facets)
103
std::vector<std::vector<uint> > macro_dofs(rank);
108
std::vector<std::vector<DolfinIndex> > macro_dofs(rank);
105
110
Progress p("Building sparsity pattern over interior facets", mesh.num_facets());
106
111
for (FacetIterator facet(mesh); !facet.end(); ++facet)
117
122
Cell cell(mesh, facet->entities(D)[0]);
119
124
// Tabulate dofs for each dimension and get local dimensions
120
for (uint i = 0; i < rank; ++i)
125
for (std::size_t i = 0; i < rank; ++i)
121
126
dofs[i] = &dofmaps[i]->cell_dofs(cell.index());
130
135
Cell cell1(mesh, facet->entities(D)[1]);
132
137
// Tabulate dofs for each dimension on macro element
133
for (uint i = 0; i < rank; i++)
138
for (std::size_t i = 0; i < rank; i++)
135
140
// Get dofs for each cell
136
const std::vector<uint>& cell_dofs0 = dofmaps[i]->cell_dofs(cell0.index());
137
const std::vector<uint>& cell_dofs1 = dofmaps[i]->cell_dofs(cell1.index());
141
const std::vector<DolfinIndex>& cell_dofs0 = dofmaps[i]->cell_dofs(cell0.index());
142
const std::vector<DolfinIndex>& cell_dofs1 = dofmaps[i]->cell_dofs(cell1.index());
139
144
// Create space in macro dof vector
140
145
macro_dofs[i].resize(cell_dofs0.size() + cell_dofs1.size());
160
165
Progress p("Building sparsity pattern over diagonal", local_range[0].second-local_range[0].first);
162
std::vector<uint> diagonal_dof(1, 0);
163
for (uint i = 0; i < rank; ++i)
167
std::vector<DolfinIndex> diagonal_dof(1, 0);
168
for (std::size_t i = 0; i < rank; ++i)
164
169
dofs[i] = &diagonal_dof;
166
for (uint j = local_range[0].first; j < local_range[0].second; j++)
171
for (std::size_t j = local_range[0].first; j < local_range[0].second; j++)
168
173
diagonal_dof[0] = j;
177
182
sparsity_pattern.apply();
179
184
// Add master-slave rows positions for periodic boundary conditions
180
std::vector<std::pair<std::pair<uint, uint>, std::pair<uint, uint> > >::const_iterator master_slave;
185
std::vector<std::pair<std::pair<std::size_t, std::size_t>, std::pair<std::size_t, std::size_t> > >::const_iterator master_slave;
181
186
for (master_slave = master_slave_dofs.begin(); master_slave != master_slave_dofs.end(); ++master_slave)
183
const uint master_dof = master_slave->first.first;
184
const uint slave_dof = master_slave->second.first;
188
const std::size_t master_dof = master_slave->first.first;
189
const std::size_t slave_dof = master_slave->second.first;
186
191
if (master_dof >= local_range[0].first && master_dof < local_range[0].second)
188
193
// Get non-zero columns for master row
189
std::vector<uint> column_indices;
194
std::vector<DolfinIndex> column_indices;
190
195
sparsity_pattern.get_edges(master_dof, column_indices);
191
196
column_indices.push_back(slave_dof);
197
202
if (slave_dof >= local_range[0].first && slave_dof < local_range[0].second)
199
204
// Get non-zero columns for slace row
200
std::vector<uint> column_indices;
205
std::vector<DolfinIndex> column_indices;
201
206
sparsity_pattern.get_edges(slave_dof, column_indices);
202
207
column_indices.push_back(master_dof);