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 return defaultReturnValue;
182
183 return m_submatrix[i]->GetValue(local_row, local_col);
184}
185
186template <typename SparseStorageType>
188 const DataVectorType &in, DataVectorType &out)
189{
190 for (int i = 0; i < m_submatrix.size(); ++i)
191 {
192 m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
193 }
194 m_mulCallsCounter++;
195}
196
197template <typename SparseStorageType>
199 DataType *out)
200{
201 for (int i = 0; i < m_submatrix.size(); ++i)
202 {
203 m_submatrix[i]->Multiply(&in[m_rowoffset[i]], &out[m_rowoffset[i]]);
204 }
205 m_mulCallsCounter++;
206}
207
208template <typename SparseStorageType>
210 const IndexType blockNum, DataType *in, DataType *out)
211{
212 m_submatrix[blockNum]->Multiply(in + m_rowoffset[blockNum],
213 out + m_rowoffset[blockNum]);
214 // m_mulCallsCounter++;
215}
216
217template <typename SparseStorageType>
219{
220 size_t bytes = sizeof(IndexType) * 2 + // sizes
221 sizeof(unsigned long) + // mulCallsCounter
222 sizeof(IndexVector) +
223 sizeof(IndexType) * m_rowoffset.capacity() +
225 sizeof(SparseStorageSharedPtr) * m_submatrix.capacity();
226 for (int i = 0; i < m_submatrix.size(); i++)
227 {
228 bytes += m_submatrix[i]->GetMemoryUsage();
229 }
230 return bytes;
231}
232
233template <typename SparseStorageType>
235 IndexType i) const
236{
237 return m_submatrix[i]->GetMemoryUsage();
238}
239
240template <typename SparseStorageType>
242 const
243{
244 return m_mulCallsCounter;
245}
246
247template <typename SparseStorageType>
248typename SparseStorageType::DataType NekSparseDiagBlkMatrix<
249 SparseStorageType>::GetAvgRowDensity()
250{
251 DataType avgRowDensity = 0.0;
252 for (int i = 0; i < m_submatrix.size(); i++)
253 {
254 avgRowDensity += (DataType)m_submatrix[i]->GetNumNonZeroEntries() /
255 (DataType)m_submatrix[i]->GetRows();
256 }
257 return avgRowDensity / m_submatrix.size();
258}
259
260template <typename SparseStorageType>
261typename SparseStorageType::DataType NekSparseDiagBlkMatrix<
262 SparseStorageType>::GetAvgRowDensity(IndexType i) const
263{
264 return (DataType)m_submatrix[i]->GetNumNonZeroEntries() /
265 (DataType)m_submatrix[i]->GetRows();
266}
267
268template <typename SparseStorageType>
270{
271 IndexType bandwidth = 0;
272 for (int i = 0; i < m_submatrix.size(); i++)
273 {
274 typename SparseStorageType::const_iterator entry =
275 m_submatrix[i]->begin();
276 for (; entry != m_submatrix[i]->end(); ++entry)
277 {
278 bandwidth =
279 (std::max)(static_cast<int>(bandwidth),
280 2 * abs(static_cast<int>(entry->first.first -
281 entry->first.second) +
282 1));
283 }
284 }
285 return bandwidth;
286}
287
288template <typename SparseStorageType>
290{
291 IndexType bandwidth = 0;
292 typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
293 for (; entry != m_submatrix[i]->end(); ++entry)
294 {
295 bandwidth = (std::max)(
296 static_cast<int>(bandwidth),
297 2 * abs(static_cast<int>(entry->first.first - entry->first.second) +
298 1));
299 }
300 return bandwidth;
301}
302
303template <typename SparseStorageType>
305 IndexType i)
306{
308 typename SparseStorageType::const_iterator entry = m_submatrix[i]->begin();
309 for (; entry != m_submatrix[i]->end(); entry++)
310 {
311 IndexType loc_row = entry->first.first;
312 IndexType loc_col = entry->first.second;
313 (*coo)[std::make_pair(loc_row, loc_col)] = entry->second;
314 }
315 return coo;
316}
317
318template <typename SparseStorageType>
320{
322 IndexType row_offset = 0;
323 IndexType col_offset = 0;
324 for (IndexType i = 0; i < m_submatrix.size(); i++)
325 {
326 typename SparseStorageType::const_iterator entry =
327 m_submatrix[i]->begin();
328 for (; entry != m_submatrix[i]->end(); entry++)
329 {
330 IndexType loc_row = entry->first.first;
331 IndexType loc_col = entry->first.second;
332 (*coo)[std::make_pair(loc_row + row_offset, loc_col + col_offset)] =
333 entry->second;
334 }
335 row_offset += m_submatrix[i]->GetRows();
336 col_offset += m_submatrix[i]->GetColumns();
337 }
338 return coo;
339}
340
341// Generates a matrix each element of which is a number of
342// nonzero entries to block-matrix associated with *this object.
343// E.g. for unit 6x6 matrix and block size = 2 it will generate
344// 3x3 matrix with elements 2 along the diagonal.
345//
346// The output can be visualised with Python's matplotlib's spy().
347//
348template <typename SparseStorageType>
350 std::ostream &out, const IndexType subMatrixIdx, const IndexType blockSize)
351{
352 const int matRows = m_submatrix[subMatrixIdx]->GetRows();
353 const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
354 const int gridCols = gridRows;
355
356 std::vector<std::vector<int>> grid(gridRows);
357 for (int row = 0; row < gridRows; row++)
358 {
359 grid[row].resize(gridCols, 0.0);
360 }
361
362 typename SparseStorageType::const_iterator entry =
363 m_submatrix[subMatrixIdx]->begin();
364 typename SparseStorageType::const_iterator stop =
365 m_submatrix[subMatrixIdx]->end();
366 for (; entry != stop; ++entry)
367 {
368 const IndexType row = entry->first.first;
369 const IndexType col = entry->first.second;
370 const int gridRow = row / blockSize;
371 const int gridCol = col / blockSize;
372 grid[gridRow][gridCol]++;
373 }
374
375 for (int row = 0; row < gridRows; row++)
376 {
377 for (int col = 0; col < gridCols; col++)
378 {
379 out << grid[row][col] << " ";
380 }
381 out << std::endl;
382 }
383}
384
385template <typename SparseStorageType>
387 std::ostream &out, const IndexType blockSize)
388{
389 const int matRows = GetRows();
390 const int gridRows = matRows / blockSize + (matRows % blockSize > 0);
391 const int gridCols = gridRows;
392
393 std::vector<std::vector<int>> grid(gridRows);
394 for (int row = 0; row < gridRows; row++)
395 {
396 grid[row].resize(gridCols, 0.0);
397 }
398
399 IndexType row_offset = 0;
400 IndexType col_offset = 0;
401 for (int i = 0; i < m_submatrix.size(); i++)
402 {
403 typename SparseStorageType::const_iterator entry =
404 m_submatrix[i]->begin();
405 typename SparseStorageType::const_iterator stop = m_submatrix[i]->end();
406 for (; entry != stop; ++entry)
407 {
408 const IndexType row = entry->first.first + row_offset;
409 const IndexType col = entry->first.second + col_offset;
410 const int gridRow = row / blockSize;
411 const int gridCol = col / blockSize;
412 grid[gridRow][gridCol]++;
413 }
414 row_offset += m_submatrix[i]->GetRows();
415 col_offset += m_submatrix[i]->GetColumns();
416 }
417
418 for (int row = 0; row < gridRows; row++)
419 {
420 for (int col = 0; col < gridCols; col++)
421 {
422 out << grid[row][col] << " ";
423 }
424 out << std::endl;
425 }
426}
427
428/// Complementary routine to the previous. It generates
429/// exact non-zero pattern of a given block matrix entry
430/// to *this object. E.g., for a 6x6 matrix defined as
431/// A(i,i):=i, A(i,j):=0, block size = 2 and
432/// blk_row=blk_col=2 it produces 2x2 matrix with 5 and 6
433/// along the diagonal.
434template <typename SparseStorageType>
437 const IndexType subMatrixIdx,
438 const IndexType blk_row,
439 const IndexType blk_col,
440 IndexType blockSize)
441{
442 blockSize = (std::min)(blockSize, m_submatrix[subMatrixIdx]->GetRows());
443 std::vector<std::vector<int>> grid(blockSize);
444 for (int row = 0; row < blockSize; row++)
445 {
446 grid[row].resize(blockSize, 0.0);
447 }
448
449 typename SparseStorageType::const_iterator entry =
450 m_submatrix[subMatrixIdx]->begin();
451 typename SparseStorageType::const_iterator stop =
452 m_submatrix[subMatrixIdx]->end();
453 for (; entry != stop; ++entry)
454 {
455 const IndexType row = entry->first.first;
456 const IndexType col = entry->first.second;
457
458 if (blk_row != row / blockSize)
459 continue;
460 if (blk_col != col / blockSize)
461 continue;
462 grid[row % blockSize][col % blockSize]++;
463 }
464
465 for (int row = 0; row < blockSize; row++)
466 {
467 for (int col = 0; col < blockSize; col++)
468 {
469 out << grid[row][col] << " ";
470 }
471 out << std::endl;
472 }
473}
474
475template <typename SparseStorageType>
477 std::ostream &out, const IndexType blk_row, const IndexType blk_col,
478 IndexType blockSize)
479{
480 blockSize = (std::min)(blockSize, GetRows());
481 std::vector<std::vector<int>> grid(blockSize);
482 for (int row = 0; row < blockSize; row++)
483 {
484 grid[row].resize(blockSize, 0.0);
485 }
486
487 IndexType row_offset = 0;
488 IndexType col_offset = 0;
489 for (int i = 0; i < m_submatrix.size(); i++)
490 {
491 typename SparseStorageType::const_iterator entry =
492 m_submatrix[i]->begin();
493 typename SparseStorageType::const_iterator stop = m_submatrix[i]->end();
494 for (; entry != stop; ++entry)
495 {
496 const IndexType row = entry->first.first + row_offset;
497 const IndexType col = entry->first.second + col_offset;
498
499 if (blk_row != row / blockSize)
500 continue;
501 if (blk_col != col / blockSize)
502 continue;
503 grid[row % blockSize][col % blockSize]++;
504 }
505 row_offset += m_submatrix[i]->GetRows();
506 col_offset += m_submatrix[i]->GetColumns();
507 }
508
509 for (int row = 0; row < blockSize; row++)
510 {
511 for (int col = 0; col < blockSize; col++)
512 {
513 out << grid[row][col] << " ";
514 }
515 out << std::endl;
516 }
517}
518
519// explicit instantiation
521
522} // 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
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