40
40
struct CompareIndex
42
CompareIndex(unsigned int index) : index(index) {}
43
bool operator()(const std::pair<unsigned int, double>& entry) const
42
CompareIndex(std::size_t index) : index(index) {}
43
bool operator()(const std::pair<std::size_t, double>& entry) const
44
44
{ return index == entry.first; }
46
const unsigned int index;
46
const std::size_t index;
49
49
//-----------------------------------------------------------------------------
60
60
//primary_dim = sparsity_pattern.primary_dim();
61
uint primary_codim = 1;
61
std::size_t primary_codim = 1;
62
62
if (primary_dim == 1)
65
65
_local_range = tensor_layout.local_range(primary_dim);
66
66
num_codim_entities = tensor_layout.size(primary_codim);
68
const uint num_primary_entiries = _local_range.second - _local_range.first;
68
const std::size_t num_primary_entiries = _local_range.second - _local_range.first;
70
70
_values.resize(num_primary_entiries);
104
104
//-----------------------------------------------------------------------------
105
std::pair<dolfin::uint, dolfin::uint> STLMatrix::local_range(uint dim) const
105
std::pair<std::size_t, std::size_t> STLMatrix::local_range(std::size_t dim) const
107
107
dolfin_assert(dim < 2);
108
108
if (primary_dim == 0)
123
123
//-----------------------------------------------------------------------------
124
124
void STLMatrix::zero()
126
std::vector<std::vector<std::pair<uint, double> > >::iterator slice;
127
std::vector<std::pair<uint, double> >::iterator entry;
126
std::vector<std::vector<std::pair<std::size_t, double> > >::iterator slice;
127
std::vector<std::pair<std::size_t, double> >::iterator entry;
128
128
for (slice = _values.begin(); slice != _values.end(); ++slice)
129
129
for (entry = slice->begin(); entry != slice->end(); ++entry)
130
130
entry->second = 0.0;
132
132
//-----------------------------------------------------------------------------
133
void STLMatrix::add(const double* block, uint m, const uint* rows, uint n,
133
void STLMatrix::add(const double* block, std::size_t m, const DolfinIndex* rows, std::size_t n,
134
const DolfinIndex* cols)
136
136
// Perform a simple linear search along each column. Otherwise,
137
137
// append the value (calling push_back).
139
const uint* primary_slice = rows;
140
const uint* secondary_slice = cols;
139
const DolfinIndex* primary_slice = rows;
140
const DolfinIndex* secondary_slice = cols;
143
std::size_t codim = n;
144
std::size_t map0 = 1;
145
std::size_t map1 = n;
146
146
if (primary_dim == 1)
154
154
// Iterate over primary dimension
155
for (uint i = 0; i < dim; i++)
155
for (std::size_t i = 0; i < dim; i++)
157
157
// Global primary index
158
const uint I = primary_slice[i];
158
const std::size_t I = primary_slice[i];
160
160
// Check if I is a local row/column
161
161
if (I < _local_range.second && I >= _local_range.first)
163
const uint I_local = I - _local_range.first;
163
const std::size_t I_local = I - _local_range.first;
165
165
assert(I_local < _values.size());
166
std::vector<std::pair<uint, double> >& slice = _values[I_local];
166
std::vector<std::pair<std::size_t, double> >& slice = _values[I_local];
168
168
// Iterate over co-dimension
169
for (uint j = 0; j < codim; j++)
169
for (std::size_t j = 0; j < codim; j++)
171
const uint pos = i*map1 + j*map0;
171
const std::size_t pos = i*map1 + j*map0;
174
const uint J = secondary_slice[j];
174
const std::size_t J = secondary_slice[j];
176
176
// Check if entry exists and insert
177
//const std::vector<uint>::const_iterator entry = std::find(slice.begin(), slice.end(), J);
178
std::vector<std::pair<uint, double> >::iterator entry
177
//const std::vector<std::size_t>::const_iterator entry = std::find(slice.begin(), slice.end(), J);
178
std::vector<std::pair<std::size_t, double> >::iterator entry
179
179
= std::find_if(slice.begin(), slice.end(), CompareIndex(J));
180
180
if (entry != slice.end())
181
181
entry->second += block[pos];
188
188
// Iterate over columns
189
for (uint j = 0; j < n; j++)
189
for (std::size_t j = 0; j < n; j++)
191
191
// Global column, coordinate
192
const uint J = secondary_slice[j];
193
const std::pair<uint, uint> global_coordinate(I, J);
194
//const uint pos = i*n + j;
195
const uint pos = i*map1 + j*map0;
192
const std::size_t J = secondary_slice[j];
193
const std::pair<std::size_t, std::size_t> global_coordinate(I, J);
194
//const std::size_t pos = i*n + j;
195
const std::size_t pos = i*map1 + j*map0;
197
boost::unordered_map<std::pair<uint, uint>, double>::iterator coord;
197
boost::unordered_map<std::pair<std::size_t, std::size_t>, double>::iterator coord;
198
198
coord = off_processs_data.find(global_coordinate);
199
199
if (coord == off_processs_data.end())
200
200
off_processs_data[global_coordinate] = block[pos];
210
210
Timer("Apply (matrix)");
213
std::vector<uint> send_non_local_rows, send_non_local_cols, destinations;
213
std::vector<std::size_t> send_non_local_rows, send_non_local_cols;
214
std::vector<std::size_t> destinations;
214
215
std::vector<double> send_non_local_vals;
216
std::vector<std::pair<uint, uint> > process_ranges;
217
std::vector<std::pair<std::size_t, std::size_t> > process_ranges;
217
218
dolfin::MPI::all_gather(_local_range, process_ranges);
219
220
// Communicate off-process data
220
boost::unordered_map<std::pair<uint, uint>, double>::const_iterator entry;
221
boost::unordered_map<std::pair<std::size_t, std::size_t>, double>::const_iterator entry;
221
222
for (entry = off_processs_data.begin(); entry != off_processs_data.end(); ++entry)
223
const uint global_row = entry->first.first;
224
const std::size_t global_row = entry->first.first;
225
226
// FIXME: This can be more efficient by storing sparsity pattern,
226
227
// or caching owning process for repeated assembly
228
229
// Get owning process
230
for (uint proc = 0; proc < process_ranges.size(); ++proc)
230
std::size_t owner = 0;
231
for (std::size_t proc = 0; proc < process_ranges.size(); ++proc)
232
233
if (global_row < process_ranges[proc].second && global_row >= process_ranges[proc].first)
245
246
// Send/receive data
246
std::vector<uint> received_non_local_rows, received_non_local_cols;
247
std::vector<std::size_t> received_non_local_rows, received_non_local_cols;
247
248
std::vector<double> received_non_local_vals;
248
249
dolfin::MPI::distribute(send_non_local_rows, destinations, received_non_local_rows);
249
250
dolfin::MPI::distribute(send_non_local_cols, destinations, received_non_local_cols);
253
254
assert(received_non_local_rows.size() == received_non_local_vals.size());
255
256
// Add/insert off-process data
256
for (uint i = 0; i < received_non_local_rows.size(); ++i)
257
for (std::size_t i = 0; i < received_non_local_rows.size(); ++i)
258
259
dolfin_assert(received_non_local_rows[i] < _local_range.second && received_non_local_rows[i] >= _local_range.first);
259
const uint I_local = received_non_local_rows[i] - _local_range.first;
260
const std::size_t I_local = received_non_local_rows[i] - _local_range.first;
260
261
assert(I_local < _values.size());
262
const uint J = received_non_local_cols[i];
263
std::vector<std::pair<uint, double> >::iterator entry
263
const std::size_t J = received_non_local_cols[i];
264
std::vector<std::pair<std::size_t, double> >::iterator entry
264
265
= std::find_if(_values[I_local].begin(), _values[I_local].end(), CompareIndex(J));
265
266
if (entry != _values[I_local].end())
266
267
entry->second += received_non_local_vals[i];
275
276
error("Do not know to comput %s norm for STLMatrix", norm_type.c_str());
277
278
double _norm = 0.0;
278
for (uint i = 0; i < _values.size(); ++i)
279
for (std::size_t i = 0; i < _values.size(); ++i)
280
for (uint j = 0; j < _values[i].size(); ++j)
281
for (std::size_t j = 0; j < _values[i].size(); ++j)
281
282
_norm += _values[i][j].second*_values[i][j].second;
283
284
return std::sqrt(dolfin::MPI::sum(_norm));
285
286
//-----------------------------------------------------------------------------
286
void STLMatrix::getrow(uint row, std::vector<uint>& columns,
287
void STLMatrix::getrow(std::size_t row, std::vector<std::size_t>& columns,
287
288
std::vector<double>& values) const
289
290
if (primary_dim == 1)
296
297
dolfin_assert(row < _local_range.second && row >= _local_range.first);
297
const uint local_row = row - _local_range.first;
298
const std::size_t local_row = row - _local_range.first;
298
299
dolfin_assert(local_row < _values.size());
299
300
columns.resize(_values[local_row].size());
300
301
values.resize(_values[local_row].size());
301
for (uint i = 0; i < _values.size(); ++i)
302
for (std::size_t i = 0; i < _values.size(); ++i)
303
304
columns[i] = _values[local_row][i].first;
304
305
values[i] = _values[local_row][i].second;
307
308
//-----------------------------------------------------------------------------
308
void STLMatrix::ident(uint m, const uint* rows)
309
void STLMatrix::ident(std::size_t m, const DolfinIndex* rows)
310
311
if (primary_dim == 1)
314
315
"STLMatrix::ident can only be used with row-wise storage.");
317
std::pair<uint, uint> row_range = local_range(0);
318
for (uint i = 0; i < m; ++i)
318
std::pair<std::size_t, std::size_t> row_range = local_range(0);
319
for (std::size_t i = 0; i < m; ++i)
320
const uint global_row = rows[i];
321
const std::size_t global_row = rows[i];
321
322
if (global_row >= row_range.first && global_row < row_range.second)
323
const uint local_row = global_row - row_range.first;
324
const std::size_t local_row = global_row - row_range.first;
324
325
dolfin_assert(local_row < _values.size());
325
for (uint i = 0; i < _values[local_row].size(); ++i)
326
for (std::size_t i = 0; i < _values[local_row].size(); ++i)
326
327
_values[local_row][i].second = 0.0;
328
329
// Place one on diagonal
329
std::vector<std::pair<uint, double> >::iterator diagonal
330
std::vector<std::pair<std::size_t, double> >::iterator diagonal
330
331
= std::find_if(_values[local_row].begin(), _values[local_row].end(),
331
332
CompareIndex(global_row));
340
341
//-----------------------------------------------------------------------------
341
342
const STLMatrix& STLMatrix::operator*= (double a)
343
std::vector<std::vector<std::pair<uint, double> > >::iterator row;
344
std::vector<std::pair<uint, double> >::iterator entry;
344
std::vector<std::vector<std::pair<std::size_t, double> > >::iterator row;
345
std::vector<std::pair<std::size_t, double> >::iterator entry;
345
346
for (row = _values.begin(); row != _values.end(); ++row)
346
347
for (entry = row->begin(); entry != row->end(); ++entry)
347
348
entry->second *=a;
370
371
s << str(false) << std::endl << std::endl;
371
for (uint i = 0; i < _local_range.second - _local_range.first; i++)
372
for (std::size_t i = 0; i < _local_range.second - _local_range.first; i++)
373
374
// Sort row data by colmun index
374
std::vector<std::pair<uint, double> > data = _values[i];
375
std::vector<std::pair<std::size_t, double> > data = _values[i];
375
376
std::sort(data.begin(), data.end());
384
std::vector<std::pair<uint, double> >::const_iterator entry;
385
std::vector<std::pair<std::size_t, double> >::const_iterator entry;
385
386
for (entry = data.begin(); entry != data.end(); ++entry)
386
387
line << " (" << i << ", " << entry->first << ", " << entry->second << ")";
403
404
return STLFactoryCSC::instance();
405
406
//-----------------------------------------------------------------------------
406
dolfin::uint STLMatrix::nnz() const
407
std::size_t STLMatrix::nnz() const
408
409
return dolfin::MPI::sum(local_nnz());
410
411
//-----------------------------------------------------------------------------
411
dolfin::uint STLMatrix::local_nnz() const
412
std::size_t STLMatrix::local_nnz() const
414
for (uint i = 0; i < _values.size(); ++i)
414
std::size_t _nnz = 0;
415
for (std::size_t i = 0; i < _values.size(); ++i)
415
416
_nnz += _values[i].size();