Nektar++
SparseDiagBlkMatrix.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: SparseDiagBlkMatrix.cpp
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
32 // sparse storage format
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <algorithm>
37 #include <fstream>
38 #include <map>
39 #include <utility>
40 #include <vector>
41 
47 
48 namespace Nektar
49 {
50 
51 template <typename SparseStorageType>
53  const SparseStorageSharedPtrVector &sparseStoragePtrVector)
54  : m_rows(0), m_cols(0), m_rowoffset(sparseStoragePtrVector.size() + 1, 0.0),
55  m_mulCallsCounter(0),
56  m_submatrix(sparseStoragePtrVector.size(), sparseStoragePtrVector)
57 {
58  for (int i = 0; i < sparseStoragePtrVector.size(); i++)
59  {
60  const IndexType rows = sparseStoragePtrVector[i]->GetRows();
61  m_rows += rows;
62  m_cols += sparseStoragePtrVector[i]->GetColumns();
63  m_rowoffset[i + 1] = m_rowoffset[i] + rows;
64  }
65 }
66 
67 template <typename SparseStorageType>
69  const NekSparseDiagBlkMatrix &src)
70  : m_rows(src.m_rows), m_cols(src.m_cols), m_rowoffset(src.m_rowoffset),
71  m_mulCallsCounter(src.m_mulCallsCounter), m_submatrix(src.m_submatrix)
72 {
73 }
74 
75 template <typename SparseStorageType>
77 {
78 }
79 
80 template <typename SparseStorageType>
82 {
83  return m_rows;
84 }
85 
86 template <typename SparseStorageType>
88 {
89  return m_cols;
90 }
91 
92 /// number of rows at i-th submatrix
93 template <typename SparseStorageType>
95 {
96  return m_submatrix[i]->GetRows();
97 }
98 
99 /// number of columns at i-th submatrix
100 template <typename SparseStorageType>
102 {
103  return m_submatrix[i]->GetColumns();
104 }
105 
106 template <typename SparseStorageType>
108  const
109 {
110  return m_submatrix.size();
111 }
112 
113 template <typename SparseStorageType>
115 {
116  IndexType nnz = 0;
117  for (int i = 0; i < m_submatrix.size(); i++)
118  {
119  nnz += m_submatrix[i]->GetNumNonZeroEntries();
120  }
121  return nnz;
122 }
123 
124 // nnz of i-th CSR matrix
125 template <typename SparseStorageType>
127  int i) const
128 {
129  return m_submatrix[i]->GetNumNonZeroEntries();
130 }
131 
132 template <typename SparseStorageType>
134  SparseStorageType>::GetFillInRatio(int i) const
135 {
136  return m_submatrix[i]->GetFillInRatio();
137 }
138 
139 template <typename SparseStorageType>
141  SparseStorageType>::GetFillInRatio() const
142 {
143  IndexType stored = 0;
144  IndexType nnz = 0;
145  for (int i = 0; i < m_submatrix.size(); i++)
146  {
147  stored += m_submatrix[i]->GetNumStoredDoubles();
148  nnz += m_submatrix[i]->GetNumNonZeroEntries();
149  }
150  return (DataType)stored / (DataType)nnz;
151 }
152 
153 template <typename SparseStorageType>
154 typename boost::call_traits<
155  typename SparseStorageType::DataType>::const_reference
157  IndexType block, IndexType loc_row, IndexType loc_column) const
158 {
159  return m_submatrix[block]->GetValue(loc_row, loc_column);
160 }
161 
162 template <typename SparseStorageType>
163 typename boost::call_traits<
164  typename SparseStorageType::DataType>::const_reference
166  IndexType glob_row, IndexType glob_column) const
167 {
168  IndexType i = 0;
169  static DataType defaultReturnValue = 0;
170 
171  signed int local_row = glob_row;
172  signed int local_col = glob_column;
173 
174  while ((local_row >= m_submatrix[i]->GetRows()) && (local_col >= 0))
175  {
176  local_row -= m_submatrix[i]->GetRows();
177  local_col -= m_submatrix[i]->GetColumns();
178  i++;
179  }
180  /// \todo double check, might be a bug when local_col > local column
181  if (local_col < 0)
182  return defaultReturnValue;
183 
184  return m_submatrix[i]->GetValue(local_row, local_col);
185 }
186 
187 template <typename SparseStorageType>
189  const DataVectorType &in, DataVectorType &out)
190 {
191  for (int i = 0; i < m_submatrix.size(); ++i)
192  {
193  m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
194  }
195  m_mulCallsCounter++;
196 }
197 
198 template <typename SparseStorageType>
200  DataType *out)
201 {
202  for (int i = 0; i < m_submatrix.size(); ++i)
203  {
204  m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
205  }
206  m_mulCallsCounter++;
207 }
208 
209 template <typename SparseStorageType>
211  const IndexType blockNum, DataType *in, DataType *out)
212 {
213  m_submatrix[blockNum]->Multiply(in + m_rowoffset[blockNum],
214  out + m_rowoffset[blockNum]);
215  // m_mulCallsCounter++;
216 }
217 
218 template <typename SparseStorageType>
220 {
221  size_t bytes = sizeof(IndexType) * 2 + // sizes
222  sizeof(unsigned long) + // mulCallsCounter
223  sizeof(IndexVector) +
224  sizeof(IndexType) * m_rowoffset.capacity() +
226  sizeof(SparseStorageSharedPtr) * m_submatrix.capacity();
227  for (int i = 0; i < m_submatrix.size(); i++)
228  {
229  bytes += m_submatrix[i]->GetMemoryUsage();
230  }
231  return bytes;
232 }
233 
234 template <typename SparseStorageType>
236  IndexType i) const
237 {
238  return m_submatrix[i]->GetMemoryUsage();
239 }
240 
241 template <typename SparseStorageType>
243  const
244 {
245  return m_mulCallsCounter;
246 }
247 
248 template <typename SparseStorageType>
249 typename SparseStorageType::DataType NekSparseDiagBlkMatrix<
250  SparseStorageType>::GetAvgRowDensity()
251 {
252  DataType avgRowDensity = 0.0;
253  for (int i = 0; i < m_submatrix.size(); i++)
254  {
255  avgRowDensity += (DataType)m_submatrix[i]->GetNumNonZeroEntries() /
256  (DataType)m_submatrix[i]->GetRows();
257  }
258  return avgRowDensity / m_submatrix.size();
259 }
260 
261 template <typename SparseStorageType>
262 typename SparseStorageType::DataType NekSparseDiagBlkMatrix<
263  SparseStorageType>::GetAvgRowDensity(IndexType i) const
264 {
265  return (DataType)m_submatrix[i]->GetNumNonZeroEntries() /
266  (DataType)m_submatrix[i]->GetRows();
267 }
268 
269 template <typename SparseStorageType>
271 {
272  IndexType bandwidth = 0;
273  for (int i = 0; i < m_submatrix.size(); i++)
274  {
275  typename SparseStorageType::const_iterator entry =
276  m_submatrix[i]->begin();
277  for (; entry != m_submatrix[i]->end(); ++entry)
278  {
279  bandwidth =
280  (std::max)(static_cast<int>(bandwidth),
281  2 * abs(static_cast<int>(entry->first.first -
282  entry->first.second) +
283  1));
284  }
285  }
286  return bandwidth;
287 }
288 
289 template <typename SparseStorageType>
291 {
292  IndexType bandwidth = 0;
293  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
294  for (; entry != m_submatrix[i]->end(); ++entry)
295  {
296  bandwidth = (std::max)(
297  static_cast<int>(bandwidth),
298  2 * abs(static_cast<int>(entry->first.first - entry->first.second) +
299  1));
300  }
301  return bandwidth;
302 }
303 
304 template <typename SparseStorageType>
306  IndexType i)
307 {
308  COOMatTypeSharedPtr coo(new COOMatType());
309  typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
310  for (; entry != m_submatrix[i]->end(); entry++)
311  {
312  IndexType loc_row = entry->first.first;
313  IndexType loc_col = entry->first.second;
314  (*coo)[std::make_pair(loc_row, loc_col)] = entry->second;
315  }
316  return coo;
317 }
318 
319 template <typename SparseStorageType>
321 {
322  COOMatTypeSharedPtr coo(new COOMatType());
323  IndexType row_offset = 0;
324  IndexType col_offset = 0;
325  for (IndexType i = 0; i < m_submatrix.size(); i++)
326  {
327  typename SparseStorageType::const_iterator entry =
328  m_submatrix[i]->begin();
329  for (; entry != m_submatrix[i]->end(); entry++)
330  {
331  IndexType loc_row = entry->first.first;
332  IndexType loc_col = entry->first.second;
333  (*coo)[std::make_pair(loc_row + row_offset, loc_col + col_offset)] =
334  entry->second;
335  }
336  row_offset += m_submatrix[i]->GetRows();
337  col_offset += m_submatrix[i]->GetColumns();
338  }
339  return coo;
340 }
341 
342 // Generates a matrix each element of which is a number of
343 // nonzero entries to block-matrix associated with *this object.
344 // E.g. for unit 6x6 matrix and block size = 2 it will generate
345 // 3x3 matrix with elements 2 along the diagonal.
346 //
347 // The output can be visualised with Python's matplotlib's spy().
348 //
349 template <typename SparseStorageType>
351  std::ostream &out, const IndexType subMatrixIdx, const IndexType blockSize)
352 {
353  const int matRows = m_submatrix[subMatrixIdx]->GetRows();
354  const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
355  const int gridCols = gridRows;
356 
357  std::vector<std::vector<int>> grid(gridRows);
358  for (int row = 0; row < gridRows; row++)
359  {
360  grid[row].resize(gridCols, 0.0);
361  }
362 
363  typename SparseStorageType::const_iterator entry =
364  m_submatrix[subMatrixIdx]->begin();
365  typename SparseStorageType::const_iterator stop =
366  m_submatrix[subMatrixIdx]->end();
367  for (; entry != stop; ++entry)
368  {
369  const IndexType row = entry->first.first;
370  const IndexType col = entry->first.second;
371  const int gridRow = row / blockSize;
372  const int gridCol = col / blockSize;
373  grid[gridRow][gridCol]++;
374  }
375 
376  for (int row = 0; row < gridRows; row++)
377  {
378  for (int col = 0; col < gridCols; col++)
379  {
380  out << grid[row][col] << " ";
381  }
382  out << std::endl;
383  }
384 }
385 
386 template <typename SparseStorageType>
388  std::ostream &out, const IndexType blockSize)
389 {
390  const int matRows = GetRows();
391  const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
392  const int gridCols = gridRows;
393 
394  std::vector<std::vector<int>> grid(gridRows);
395  for (int row = 0; row < gridRows; row++)
396  {
397  grid[row].resize(gridCols, 0.0);
398  }
399 
400  IndexType row_offset = 0;
401  IndexType col_offset = 0;
402  for (int i = 0; i < m_submatrix.size(); i++)
403  {
404  typename SparseStorageType::const_iterator entry =
405  m_submatrix[i]->begin();
406  typename SparseStorageType::const_iterator stop = m_submatrix[i]->end();
407  for (; entry != stop; ++entry)
408  {
409  const IndexType row = entry->first.first + row_offset;
410  const IndexType col = entry->first.second + col_offset;
411  const int gridRow = row / blockSize;
412  const int gridCol = col / blockSize;
413  grid[gridRow][gridCol]++;
414  }
415  row_offset += m_submatrix[i]->GetRows();
416  col_offset += m_submatrix[i]->GetColumns();
417  }
418 
419  for (int row = 0; row < gridRows; row++)
420  {
421  for (int col = 0; col < gridCols; col++)
422  {
423  out << grid[row][col] << " ";
424  }
425  out << std::endl;
426  }
427 }
428 
429 /// Complementary routine to the previous. It generates
430 /// exact non-zero pattern of a given block matrix entry
431 /// to *this object. E.g., for a 6x6 matrix defined as
432 /// A(i,i):=i, A(i,j):=0, block size = 2 and
433 /// blk_row=blk_col=2 it produces 2x2 matrix with 5 and 6
434 /// along the diagonal.
435 template <typename SparseStorageType>
437  writeSubmatrixBlockSparsityPatternTo(std::ostream &out,
438  const IndexType subMatrixIdx,
439  const IndexType blk_row,
440  const IndexType blk_col,
441  IndexType blockSize)
442 {
443  blockSize = (std::min)(blockSize, m_submatrix[subMatrixIdx]->GetRows());
444  std::vector<std::vector<int>> grid(blockSize);
445  for (int row = 0; row < blockSize; row++)
446  {
447  grid[row].resize(blockSize, 0.0);
448  }
449 
450  typename SparseStorageType::const_iterator entry =
451  m_submatrix[subMatrixIdx]->begin();
452  typename SparseStorageType::const_iterator stop =
453  m_submatrix[subMatrixIdx]->end();
454  for (; entry != stop; ++entry)
455  {
456  const IndexType row = entry->first.first;
457  const IndexType col = entry->first.second;
458 
459  if (blk_row != row / blockSize)
460  continue;
461  if (blk_col != col / blockSize)
462  continue;
463  grid[row % blockSize][col % blockSize]++;
464  }
465 
466  for (int row = 0; row < blockSize; row++)
467  {
468  for (int col = 0; col < blockSize; col++)
469  {
470  out << grid[row][col] << " ";
471  }
472  out << std::endl;
473  }
474 }
475 
476 template <typename SparseStorageType>
478  std::ostream &out, const IndexType blk_row, const IndexType blk_col,
479  IndexType blockSize)
480 {
481  blockSize = (std::min)(blockSize, GetRows());
482  std::vector<std::vector<int>> grid(blockSize);
483  for (int row = 0; row < blockSize; row++)
484  {
485  grid[row].resize(blockSize, 0.0);
486  }
487 
488  IndexType row_offset = 0;
489  IndexType col_offset = 0;
490  for (int i = 0; i < m_submatrix.size(); i++)
491  {
492  typename SparseStorageType::const_iterator entry =
493  m_submatrix[i]->begin();
494  typename SparseStorageType::const_iterator stop = m_submatrix[i]->end();
495  for (; entry != stop; ++entry)
496  {
497  const IndexType row = entry->first.first + row_offset;
498  const IndexType col = entry->first.second + col_offset;
499 
500  if (blk_row != row / blockSize)
501  continue;
502  if (blk_col != col / blockSize)
503  continue;
504  grid[row % blockSize][col % blockSize]++;
505  }
506  row_offset += m_submatrix[i]->GetRows();
507  col_offset += m_submatrix[i]->GetColumns();
508  }
509 
510  for (int row = 0; row < blockSize; row++)
511  {
512  for (int col = 0; col < blockSize; col++)
513  {
514  out << grid[row][col] << " ";
515  }
516  out << std::endl;
517  }
518 }
519 
520 // explicit instantiation
522 
523 } // namespace Nektar
SparseStorageType::DataType DataType
boost::call_traits< DataType >::const_reference operator()(const IndexType row, const IndexType column) const
std::shared_ptr< SparseStorageType > SparseStorageSharedPtr
void MultiplySubMatrix(const IndexType blockNum, DataType *in, DataType *out)
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...
unsigned long GetMulCallsCounter() const
void writeSubmatrixSparsityPatternTo(std::ostream &out, const IndexType subMatrixIdx, IndexType blockSize=64)
void writeSparsityPatternTo(std::ostream &out, IndexType blockSize=64)
void Multiply(const DataVectorType &in, DataVectorType &out)
void writeBlockSparsityPatternTo(std::ostream &out, const IndexType blk_row=0, const IndexType blk_col=0, IndexType blockSize=64)
NekSparseDiagBlkMatrix(const SparseStorageSharedPtrVector &sparseStoragePtrVector)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
Array< OneD, IndexType > IndexVector
std::shared_ptr< COOMatType > COOMatTypeSharedPtr
unsigned int IndexType
std::map< CoordType, NekDouble > COOMatType
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298