Nektar++
SparseDiagBlkMatrix.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: SparseDiagBlkMatrix.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Diagonal block sparse matrix class templated by underlying sparse
32 // storage format
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <map>
37 #include <vector>
38 #include <utility>
39 #include <algorithm>
40 #include <fstream>
41 
47 
48 namespace Nektar
49 {
50 
51  template<typename SparseStorageType>
54  sparseStoragePtrVector):
55  m_rows(0),
56  m_cols(0),
57  m_rowoffset(sparseStoragePtrVector.num_elements()+1, 0.0),
58  m_mulCallsCounter(0),
59  m_submatrix(sparseStoragePtrVector.num_elements(),sparseStoragePtrVector)
60  {
61  for (int i = 0; i < sparseStoragePtrVector.num_elements(); i++)
62  {
63  const IndexType rows = sparseStoragePtrVector[i]->GetRows();
64  m_rows += rows;
65  m_cols += sparseStoragePtrVector[i]->GetColumns();
66  m_rowoffset[i+1] = m_rowoffset[i] + rows;
67  }
68  }
69 
70  template<typename SparseStorageType>
72  m_rows(src.m_rows),
73  m_cols(src.m_cols),
77  {
78  }
79 
80  template<typename SparseStorageType>
82  {
83  }
84 
85  template<typename SparseStorageType>
87  {
88  return m_rows;
89  }
90 
91  template<typename SparseStorageType>
93  {
94  return m_cols;
95  }
96 
97  /// number of rows at i-th submatrix
98  template<typename SparseStorageType>
100  {
101  return m_submatrix[i]->GetRows();
102  }
103 
104  /// number of columns at i-th submatrix
105  template<typename SparseStorageType>
107  {
108  return m_submatrix[i]->GetColumns();
109  }
110 
111  template<typename SparseStorageType>
113  {
114  return m_submatrix.num_elements();
115  }
116 
117  template<typename SparseStorageType>
119  {
120  IndexType nnz = 0;
121  for (int i = 0; i < m_submatrix.num_elements(); i++)
122  {
123  nnz += m_submatrix[i]->GetNumNonZeroEntries();
124  }
125  return nnz;
126  }
127 
128  // nnz of i-th CSR matrix
129  template<typename SparseStorageType>
131  {
132  return m_submatrix[i]->GetNumNonZeroEntries();
133  }
134 
135  template<typename SparseStorageType>
137  {
138  return m_submatrix[i]->GetFillInRatio();
139  }
140 
141  template<typename SparseStorageType>
143  {
144  IndexType stored = 0;
145  IndexType nnz = 0;
146  for (int i = 0; i < m_submatrix.num_elements(); i++)
147  {
148  stored += m_submatrix[i]->GetNumStoredDoubles();
149  nnz += m_submatrix[i]->GetNumNonZeroEntries();
150  }
151  return (DataType)stored/(DataType)nnz;
152  }
153 
154 
155  template<typename SparseStorageType>
156  typename boost::call_traits<typename SparseStorageType::DataType>::const_reference NekSparseDiagBlkMatrix<SparseStorageType>::operator()(IndexType block, IndexType loc_row, IndexType loc_column) const
157  {
158  return m_submatrix[block]->GetValue(loc_row, loc_column);
159  }
160 
161  template<typename SparseStorageType>
162  typename boost::call_traits<typename SparseStorageType::DataType>::const_reference
164  (IndexType glob_row, IndexType glob_column) const
165  {
166  IndexType i = 0;
167  static DataType defaultReturnValue = 0;
168 
169  signed int local_row = glob_row;
170  signed int local_col = glob_column;
171 
172  while ((local_row >= m_submatrix[i]->GetRows()) &&
173  (local_col >= 0))
174  {
175  local_row -= m_submatrix[i]->GetRows();
176  local_col -= m_submatrix[i]->GetColumns();
177  i++;
178  }
179  /// \todo double check, might be a bug when local_col > local column
180  if (local_col < 0) return defaultReturnValue;
181 
182  return m_submatrix[i]->GetValue(local_row, local_col);
183  }
184 
185 
186  template<typename SparseStorageType>
188  const DataVectorType &in,
189  DataVectorType &out)
190  {
191  for (int i = 0; i < m_submatrix.num_elements(); ++i)
192  {
193  m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
194  }
196  }
197 
198  template<typename SparseStorageType>
200  const DataType* in, DataType* out)
201  {
202  for (int i = 0; i < m_submatrix.num_elements(); ++i)
203  {
204  m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
205  }
207  }
208 
209  template<typename SparseStorageType>
212  DataType* in,
213  DataType* out)
214  {
215  m_submatrix[blockNum]->Multiply(in + m_rowoffset[blockNum], out + m_rowoffset[blockNum]);
216  // m_mulCallsCounter++;
217  }
218 
219  template<typename SparseStorageType>
221  {
222  size_t bytes =
223  sizeof(IndexType)*2 + // sizes
224  sizeof(unsigned long) + // mulCallsCounter
225  sizeof(IndexVector) +
226  sizeof(IndexType)*m_rowoffset.capacity() +
228  sizeof(SparseStorageSharedPtr)*m_submatrix.capacity();
229  for (int i = 0; i < m_submatrix.num_elements(); i++)
230  {
231  bytes += m_submatrix[i]->GetMemoryUsage();
232  }
233  return bytes;
234  }
235 
236  template<typename SparseStorageType>
238  {
239  return m_submatrix[i]->GetMemoryUsage();
240  }
241 
242  template<typename SparseStorageType>
244  {
245  return m_mulCallsCounter;
246  }
247 
248  template<typename SparseStorageType>
249  typename SparseStorageType::DataType NekSparseDiagBlkMatrix<SparseStorageType>::GetAvgRowDensity()
250  {
251  DataType avgRowDensity = 0.0;
252  for (int i = 0; i < m_submatrix.num_elements(); i++)
253  {
254  avgRowDensity += (DataType) m_submatrix[i]->GetNumNonZeroEntries() /
255  (DataType) m_submatrix[i]->GetRows();
256  }
257  return avgRowDensity / m_submatrix.num_elements();
258  }
259 
260  template<typename SparseStorageType>
261  typename SparseStorageType::DataType NekSparseDiagBlkMatrix<SparseStorageType>::GetAvgRowDensity(IndexType i) const
262  {
263  return (DataType) m_submatrix[i]->GetNumNonZeroEntries() /
264  (DataType) m_submatrix[i]->GetRows();
265  }
266 
267  template<typename SparseStorageType>
269  {
270  IndexType bandwidth = 0;
271  for (int i = 0; i < m_submatrix.num_elements(); i++)
272  {
273  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
274  for (; entry != m_submatrix[i]->end(); ++entry)
275  {
276  bandwidth = (std::max)(static_cast<int>(bandwidth),
277  2*abs( static_cast<int>(entry->first.first - entry->first.second)+1));
278  }
279  }
280  return bandwidth;
281  }
282 
283  template<typename SparseStorageType>
285  {
286  IndexType bandwidth = 0;
287  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
288  for (; entry != m_submatrix[i]->end(); ++entry)
289  {
290  bandwidth = (std::max)(static_cast<int>(bandwidth),
291  2*abs( static_cast<int>(entry->first.first - entry->first.second)+1));
292  }
293  return bandwidth;
294  }
295 
296  template<typename SparseStorageType>
298  {
299  COOMatTypeSharedPtr coo (new COOMatType());
300  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
301  for (; entry != m_submatrix[i]->end(); entry++)
302  {
303  IndexType loc_row = entry->first.first;
304  IndexType loc_col = entry->first.second;
305  (*coo)[std::make_pair(loc_row, loc_col) ] = entry->second;
306  }
307  return coo;
308  }
309 
310  template<typename SparseStorageType>
312  {
313  COOMatTypeSharedPtr coo (new COOMatType());
314  IndexType row_offset = 0;
315  IndexType col_offset = 0;
316  for (IndexType i = 0; i < m_submatrix.num_elements(); i++)
317  {
318  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
319  for (; entry != m_submatrix[i]->end(); entry++)
320  {
321  IndexType loc_row = entry->first.first;
322  IndexType loc_col = entry->first.second;
323  (*coo)[std::make_pair(loc_row + row_offset, loc_col + col_offset) ] = entry->second;
324  }
325  row_offset += m_submatrix[i]->GetRows();
326  col_offset += m_submatrix[i]->GetColumns();
327  }
328  return coo;
329  }
330 
331  // Generates a matrix each element of which is a number of
332  // nonzero entries to block-matrix associated with *this object.
333  // E.g. for unit 6x6 matrix and block size = 2 it will generate
334  // 3x3 matrix with elements 2 along the diagonal.
335  //
336  // The output can be visualised with Python's matplotlib's spy().
337  //
338  template<typename SparseStorageType>
341  const IndexType subMatrixIdx,
342  const IndexType blockSize)
343  {
344  const int matRows = m_submatrix[subMatrixIdx]->GetRows();
345  const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
346  const int gridCols = gridRows;
347 
348  std::vector< std::vector<int> > grid (gridRows);
349  for (int row = 0; row < gridRows; row++)
350  {
351  grid[row].resize(gridCols,0.0);
352  }
353 
354  typename SparseStorageType::const_iterator entry =
355  m_submatrix[subMatrixIdx]->begin();
356  typename SparseStorageType::const_iterator stop =
357  m_submatrix[subMatrixIdx]->end();
358  for (; entry != stop; ++entry)
359  {
360  const IndexType row = entry->first.first;
361  const IndexType col = entry->first.second;
362  const int gridRow = row / blockSize;
363  const int gridCol = col / blockSize;
364  grid[gridRow][gridCol]++;
365  }
366 
367  for (int row = 0; row < gridRows; row++)
368  {
369  for (int col = 0; col < gridCols; col++)
370  {
371  out << grid[row][col] << " ";
372  }
373  out << std::endl;
374  }
375  }
376 
377  template<typename SparseStorageType>
379  writeSparsityPatternTo(std::ostream& out,
380  const IndexType blockSize)
381  {
382  const int matRows = GetRows();
383  const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
384  const int gridCols = gridRows;
385 
386  std::vector< std::vector<int> > grid (gridRows);
387  for (int row = 0; row < gridRows; row++)
388  {
389  grid[row].resize(gridCols,0.0);
390  }
391 
392  IndexType row_offset = 0;
393  IndexType col_offset = 0;
394  for (int i = 0; i < m_submatrix.num_elements(); i++)
395  {
396  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
397  typename SparseStorageType::const_iterator stop = m_submatrix[i]->end();
398  for (; entry != stop; ++entry)
399  {
400  const IndexType row = entry->first.first + row_offset;
401  const IndexType col = entry->first.second + col_offset;
402  const int gridRow = row / blockSize;
403  const int gridCol = col / blockSize;
404  grid[gridRow][gridCol]++;
405  }
406  row_offset += m_submatrix[i]->GetRows();
407  col_offset += m_submatrix[i]->GetColumns();
408  }
409 
410  for (int row = 0; row < gridRows; row++)
411  {
412  for (int col = 0; col < gridCols; col++)
413  {
414  out << grid[row][col] << " ";
415  }
416  out << std::endl;
417  }
418  }
419 
420  /// Complementary routine to the previous. It generates
421  /// exact non-zero pattern of a given block matrix entry
422  /// to *this object. E.g., for a 6x6 matrix defined as
423  /// A(i,i):=i, A(i,j):=0, block size = 2 and
424  /// blk_row=blk_col=2 it produces 2x2 matrix with 5 and 6
425  /// along the diagonal.
426  template<typename SparseStorageType>
429  const IndexType subMatrixIdx,
430  const IndexType blk_row,
431  const IndexType blk_col,
432  IndexType blockSize)
433  {
434  blockSize = (std::min)(blockSize, m_submatrix[subMatrixIdx]->GetRows());
435  std::vector< std::vector<int> > grid (blockSize);
436  for (int row = 0; row < blockSize; row++)
437  {
438  grid[row].resize(blockSize,0.0);
439  }
440 
441  typename SparseStorageType::const_iterator entry =
442  m_submatrix[subMatrixIdx]->begin();
443  typename SparseStorageType::const_iterator stop =
444  m_submatrix[subMatrixIdx]->end();
445  for (; entry != stop; ++entry)
446  {
447  const IndexType row = entry->first.first;
448  const IndexType col = entry->first.second;
449 
450  if (blk_row != row / blockSize ) continue;
451  if (blk_col != col / blockSize ) continue;
452  grid[row % blockSize][col % blockSize]++;
453  }
454 
455  for (int row = 0; row < blockSize; row++)
456  {
457  for (int col = 0; col < blockSize; col++)
458  {
459  out << grid[row][col] << " ";
460  }
461  out << std::endl;
462  }
463  }
464 
465  template<typename SparseStorageType>
467  std::ostream& out,
468  const IndexType blk_row,
469  const IndexType blk_col,
470  IndexType blockSize)
471  {
472  blockSize = (std::min)(blockSize, GetRows());
473  std::vector< std::vector<int> > grid (blockSize);
474  for (int row = 0; row < blockSize; row++)
475  {
476  grid[row].resize(blockSize,0.0);
477  }
478 
479  IndexType row_offset = 0;
480  IndexType col_offset = 0;
481  for (int i = 0; i < m_submatrix.num_elements(); i++)
482  {
483  typename SparseStorageType::const_iterator entry =
484  m_submatrix[i]->begin();
485  typename SparseStorageType::const_iterator stop =
486  m_submatrix[i]->end();
487  for (; entry != stop; ++entry)
488  {
489  const IndexType row = entry->first.first + row_offset;
490  const IndexType col = entry->first.second + col_offset;
491 
492  if (blk_row != row / blockSize ) continue;
493  if (blk_col != col / blockSize ) continue;
494  grid[row % blockSize][col % blockSize]++;
495  }
496  row_offset += m_submatrix[i]->GetRows();
497  col_offset += m_submatrix[i]->GetColumns();
498  }
499 
500  for (int row = 0; row < blockSize; row++)
501  {
502  for (int col = 0; col < blockSize; col++)
503  {
504  out << grid[row][col] << " ";
505  }
506  out << std::endl;
507  }
508  }
509 
510 
511 
512  // explicit instantiation
514 
515 
516 } // namespace
517 
std::map< CoordType, NekDouble > COOMatType
SparseStorageSharedPtrVector m_submatrix
Array< OneD, IndexType > IndexVector
boost::call_traits< DataType >::const_reference operator()(const IndexType row, const IndexType column) const
void MultiplySubMatrix(const IndexType blockNum, DataType *in, DataType *out)
SparseStorageType::DataType DataType
unsigned int IndexType
void writeSubmatrixBlockSparsityPatternTo(std::ostream &out, const IndexType subMatrixIdx, const IndexType blk_row=0, const IndexType blk_col=0, IndexType blockSize=64)
Complementary routine to the previous. It generates exact non-zero pattern of a given block matrix en...
void writeBlockSparsityPatternTo(std::ostream &out, const IndexType blk_row=0, const IndexType blk_col=0, IndexType blockSize=64)
void Multiply(const DataVectorType &in, DataVectorType &out)
std::shared_ptr< COOMatType > COOMatTypeSharedPtr
void writeSparsityPatternTo(std::ostream &out, IndexType blockSize=64)
std::shared_ptr< SparseStorageType > SparseStorageSharedPtr
unsigned long GetMulCallsCounter() const
void writeSubmatrixSparsityPatternTo(std::ostream &out, const IndexType subMatrixIdx, IndexType blockSize=64)
Array< OneD, SparseStorageSharedPtr > SparseStorageSharedPtrVector
NekSparseDiagBlkMatrix(const SparseStorageSharedPtrVector &sparseStoragePtrVector)