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