~corrado-maurini/dolfin/tao

« back to all changes in this revision

Viewing changes to dolfin/la/STLMatrix.cpp

  • Committer: corrado maurini
  • Date: 2012-12-18 12:16:08 UTC
  • mfrom: (6685.78.207 trunk)
  • Revision ID: corrado.maurini@upmc.fr-20121218121608-nk82ly9jgsld9u84
updating with trunk, fix uint in TAO solver and hacking the check for tao FindTAO.cmake

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 
40
40
struct CompareIndex
41
41
{
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; }
45
45
  private:
46
 
    const unsigned int index;
 
46
    const std::size_t index;
47
47
};
48
48
 
49
49
//-----------------------------------------------------------------------------
58
58
  }
59
59
 
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)
63
63
    primary_codim = 0;
64
64
 
65
65
  _local_range = tensor_layout.local_range(primary_dim);
66
66
  num_codim_entities = tensor_layout.size(primary_codim);
67
67
 
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;
69
69
 
70
70
  _values.resize(num_primary_entiries);
71
71
 
77
77
  //}
78
78
}
79
79
//-----------------------------------------------------------------------------
80
 
dolfin::uint STLMatrix::size(uint dim) const
 
80
std::size_t STLMatrix::size(std::size_t dim) const
81
81
{
82
82
  if (dim > 1)
83
83
  {
102
102
  }
103
103
}
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
106
106
{
107
107
  dolfin_assert(dim < 2);
108
108
  if (primary_dim == 0)
123
123
//-----------------------------------------------------------------------------
124
124
void STLMatrix::zero()
125
125
{
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;
131
131
}
132
132
//-----------------------------------------------------------------------------
133
 
void STLMatrix::add(const double* block, uint m, const uint* rows, uint n,
134
 
                    const uint* cols)
 
133
void STLMatrix::add(const double* block, std::size_t m, const DolfinIndex* rows, std::size_t n,
 
134
                    const DolfinIndex* cols)
135
135
{
136
136
  // Perform a simple linear search along each column. Otherwise,
137
137
  // append the value (calling push_back).
138
138
 
139
 
  const uint* primary_slice = rows;
140
 
  const uint* secondary_slice = cols;
 
139
  const DolfinIndex* primary_slice = rows;
 
140
  const DolfinIndex* secondary_slice = cols;
141
141
 
142
 
  uint dim   = m;
143
 
  uint codim = n;
144
 
  uint map0  = 1;
145
 
  uint map1  = n;
 
142
  std::size_t dim   = m;
 
143
  std::size_t codim = n;
 
144
  std::size_t map0  = 1;
 
145
  std::size_t map1  = n;
146
146
  if (primary_dim == 1)
147
147
  {
148
148
    dim = n;
152
152
  }
153
153
 
154
154
  // Iterate over primary dimension
155
 
  for (uint i = 0; i < dim; i++)
 
155
  for (std::size_t i = 0; i < dim; i++)
156
156
  {
157
157
    // Global primary index
158
 
    const uint I = primary_slice[i];
 
158
    const std::size_t I = primary_slice[i];
159
159
 
160
160
    // Check if I is a local row/column
161
161
    if (I < _local_range.second && I >= _local_range.first)
162
162
    {
163
 
      const uint I_local = I - _local_range.first;
 
163
      const std::size_t I_local = I - _local_range.first;
164
164
 
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];
167
167
 
168
168
      // Iterate over co-dimension
169
 
      for (uint j = 0; j < codim; j++)
 
169
      for (std::size_t j = 0; j < codim; j++)
170
170
      {
171
 
        const uint pos = i*map1 + j*map0;
 
171
        const std::size_t pos = i*map1 + j*map0;
172
172
 
173
173
        // Global index
174
 
        const uint J = secondary_slice[j];
 
174
        const std::size_t J = secondary_slice[j];
175
175
 
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];
186
186
    else
187
187
    {
188
188
      // Iterate over columns
189
 
      for (uint j = 0; j < n; j++)
 
189
      for (std::size_t j = 0; j < n; j++)
190
190
      {
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;
196
196
 
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)");
211
211
 
212
212
  // Data to send
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;
215
216
 
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);
218
219
 
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)
222
223
  {
223
 
    const uint global_row = entry->first.first;
 
224
    const std::size_t global_row = entry->first.first;
224
225
 
225
226
    // FIXME: This can be more efficient by storing sparsity pattern,
226
227
    //        or caching owning process for repeated assembly
227
228
 
228
229
    // Get owning process
229
 
    uint owner = 0;
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)
231
232
    {
232
233
      if (global_row < process_ranges[proc].second &&  global_row >= process_ranges[proc].first)
233
234
      {
243
244
  }
244
245
 
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());
254
255
 
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)
257
258
  {
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());
261
262
 
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());
276
277
 
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)
279
280
  {
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;
282
283
  }
283
284
  return std::sqrt(dolfin::MPI::sum(_norm));
284
285
}
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
288
289
{
289
290
  if (primary_dim == 1)
294
295
  }
295
296
 
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)
302
303
  {
303
304
    columns[i] = _values[local_row][i].first;
304
305
    values[i]  = _values[local_row][i].second;
305
306
  }
306
307
}
307
308
//-----------------------------------------------------------------------------
308
 
void STLMatrix::ident(uint m, const uint* rows)
 
309
void STLMatrix::ident(std::size_t m, const DolfinIndex* rows)
309
310
{
310
311
  if (primary_dim == 1)
311
312
  {
314
315
                 "STLMatrix::ident can only be used with row-wise storage.");
315
316
  }
316
317
 
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)
319
320
  {
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)
322
323
    {
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;
327
328
 
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));
332
333
 
340
341
//-----------------------------------------------------------------------------
341
342
const STLMatrix& STLMatrix::operator*= (double a)
342
343
{
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;
368
369
    }
369
370
 
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++)
372
373
    {
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());
376
377
 
377
378
      // Set precision
381
382
 
382
383
      // Format matrix
383
384
      line << "|";
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 << ")";
387
388
      line << " |";
403
404
    return STLFactoryCSC::instance();
404
405
}
405
406
//-----------------------------------------------------------------------------
406
 
dolfin::uint STLMatrix::nnz() const
 
407
std::size_t STLMatrix::nnz() const
407
408
{
408
409
  return dolfin::MPI::sum(local_nnz());
409
410
}
410
411
//-----------------------------------------------------------------------------
411
 
dolfin::uint STLMatrix::local_nnz() const
 
412
std::size_t STLMatrix::local_nnz() const
412
413
{
413
 
  uint _nnz = 0;
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();
416
417
  return _nnz;
417
418
}