232 : m_blockSize(other.m_blockSize),
233 m_nRows(other.m_nRows),
234 m_nCols(other.m_nCols),
236 m_maxRowNZ(other.m_maxRowNZ),
237 m_lastRow(other.m_lastRow),
238 m_assembled(other.m_assembled),
239 m_partitioned(other.m_partitioned),
240 m_global_nRows(other.m_global_nRows),
241 m_global_nCols(other.m_global_nCols),
242 m_global_nNZ(other.m_global_nNZ),
243 m_global_maxRowNZ(other.m_global_maxRowNZ),
244 m_global_rowOffset(other.m_global_rowOffset),
245 m_global_colOffset(other.m_global_colOffset),
246 m_pattern(other.m_pattern),
247 m_values (other.m_values)
250 setCommunicator(other.m_communicator);
477 std::string padding(indent,
' ');
481 int nBlockElements = blockSize * blockSize;
483 stream << padding <<
"General information" << std::endl;
484 stream << padding <<
" Block size ............................................ " << blockSize << std::endl;
501 long nNZBlockValues = 0;
502 long nNZElementValues = 0;
503 for (
long k = 0; k < nNZElements; ++k) {
504 double value = m_values[k];
512 if ((k % nBlockElements) == 0) {
513 if (nZeroStreak < nBlockElements) {
521 std::size_t nBlocks = nRows * nCols;
522 std::size_t nElements = nRowElements * nColElements;
524 double blockSparsity =
static_cast<double>(nBlocks - nNZBlocks) / nBlocks;
525 double elementSparsity =
static_cast<double>(nElements - nNZElements) / nElements;
527 double blockValueSparsity =
static_cast<double>(nBlocks - nNZBlockValues) / nBlocks;
528 double elementValueSparsity =
static_cast<double>(nElements - nNZElementValues) / nElements;
531 double valueStorageMemory =
static_cast<double>(nNZElements *
sizeof(
decltype(m_values)::value_type));
534 stream << padding <<
"Local information: " << std::endl;
535 stream << padding <<
" Maximum number of non-zero blocks per row ............. " << maxRowNZBlocks << std::endl;
536 stream << padding <<
" Maximum number of non-zero elements per row ........... " << maxRowNZElements << std::endl;
537 stream << padding <<
" Number of block rows .................................. " << nRows << std::endl;
538 stream << padding <<
" Number of block columns ............................... " << nCols << std::endl;
539 stream << padding <<
" Number of non-zero blocks (pattern) ................... " << nNZBlocks << std::endl;
540 stream << padding <<
" Number of non-zero elements (pattern) ................. " << nNZElements << std::endl;
541 stream << padding <<
" Number of non-zero blocks (non-neglibile values) ...... " << nNZBlockValues << std::endl;
542 stream << padding <<
" Number of non-zero elements (non-neglibile values) .... " << nNZElementValues << std::endl;
543 stream << padding <<
" Sparsity of the blocks (pattern) ...................... " << blockSparsity << std::endl;
544 stream << padding <<
" Sparsity of the elements (pattern) .................... " << elementSparsity << std::endl;
545 stream << padding <<
" Sparsity of the blocks (non-neglibile values) ......... " << blockValueSparsity << std::endl;
546 stream << padding <<
" Sparsity of the elements (non-neglibile values) ....... " << elementValueSparsity << std::endl;
548 stream << padding <<
" Memory used by the value storage ...................... ";
549 if (valueStorageMemory > 1024 * 1024 * 1024) {
550 stream << valueStorageMemory / (1024 * 1024 * 1024) <<
" GB";
551 }
else if (valueStorageMemory > 1024 * 1024) {
552 stream << valueStorageMemory / (1024 * 1024) <<
" MB";
553 }
else if (valueStorageMemory > 1024) {
554 stream << valueStorageMemory / (1024) <<
" KB";
558#if BITPIT_ENABLE_MPI==1
562 MPI_Datatype valueMPIDataType;
563 if (std::is_same<
decltype(m_values)::value_type,
double>::value) {
564 valueMPIDataType = MPI_DOUBLE;
565 }
else if (std::is_same<
decltype(m_values)::value_type,
float>::value) {
566 valueMPIDataType = MPI_FLOAT;
568 throw std::runtime_error(
"Unable to identify the MPI data type of the matrix values.");
581 long maxGlobalRowNZBlocks;
582 long maxGlobalRowNZElements;
583 MPI_Allreduce(&maxRowNZBlocks, &maxGlobalRowNZBlocks, 1, MPI_LONG, MPI_MAX,
getCommunicator());
584 MPI_Allreduce(&maxRowNZElements, &maxGlobalRowNZElements, 1, MPI_LONG, MPI_MAX,
getCommunicator());
587 long nGlobalNZBlockValues;
588 long nGlobalNZElementValues;
589 MPI_Allreduce(&nNZBlockValues, &nGlobalNZBlockValues, 1, MPI_LONG, MPI_SUM,
getCommunicator());
590 MPI_Allreduce(&nNZElementValues, &nGlobalNZElementValues, 1, MPI_LONG, MPI_SUM,
getCommunicator());
593 std::size_t nGlobalBlocks = nGlobalRows * nGlobalCols;
594 std::size_t nGlobalElements = nGlobalRowElements * nGlobalColElements;
596 double globalBlockSparsity =
static_cast<double>(nGlobalBlocks - nGlobalNZBlocks) / nGlobalBlocks;
597 double globalElementSparsity =
static_cast<double>(nGlobalElements - nGlobalNZElements) / nGlobalElements;
599 double globalBlockValueSparsity =
static_cast<double>(nGlobalBlocks - nGlobalNZBlockValues) / nGlobalBlocks;
600 double globalElementValueSparsity =
static_cast<double>(nGlobalElements - nGlobalNZElementValues) / nGlobalElements;
603 double valueStorageGlobalMemory;
604 MPI_Allreduce(&valueStorageMemory, &valueStorageGlobalMemory, 1, valueMPIDataType, MPI_SUM,
getCommunicator());
607 stream << padding <<
"Global information: " << std::endl;
608 stream << padding <<
" Maximum number of non-zero blocks per row ............. " << maxGlobalRowNZBlocks << std::endl;
609 stream << padding <<
" Maximum number of non-zero elements per row ........... " << maxGlobalRowNZElements << std::endl;
610 stream << padding <<
" Number of block columns ............................... " << nGlobalCols << std::endl;
611 stream << padding <<
" Number of block rows .................................. " << nGlobalRows << std::endl;
612 stream << padding <<
" Number of non-zero blocks (pattern) ................... " << nGlobalNZBlocks << std::endl;
613 stream << padding <<
" Number of non-zero elements (pattern) ................. " << nGlobalNZElements << std::endl;
614 stream << padding <<
" Number of non-zero blocks (non-neglibile values) ...... " << nGlobalNZBlockValues << std::endl;
615 stream << padding <<
" Number of non-zero elements (non-neglibile values) .... " << nGlobalNZElementValues << std::endl;
616 stream << padding <<
" Sparsity of the blocks (pattern) ...................... " << globalBlockSparsity << std::endl;
617 stream << padding <<
" Sparsity of the elements (pattern) .................... " << globalElementSparsity << std::endl;
618 stream << padding <<
" Sparsity of the blocks (non-neglibile values) ......... " << globalBlockValueSparsity << std::endl;
619 stream << padding <<
" Sparsity of the elements (non-neglibile values) ....... " << globalElementValueSparsity << std::endl;
621 stream << padding <<
" Memory used by the value storage ...................... ";
622 if (valueStorageGlobalMemory > 1024 * 1024 * 1024) {
623 stream << valueStorageGlobalMemory / (1024 * 1024 * 1024) <<
" GB";
624 }
else if (valueStorageGlobalMemory > 1024 * 1024) {
625 stream << valueStorageGlobalMemory / (1024 * 1024) <<
" MB";
626 }
else if (valueStorageGlobalMemory > 1024) {
627 stream << valueStorageGlobalMemory / (1024) <<
" KB";
634 stream << padding <<
"Display information: " << std::endl;
635 stream << padding <<
" Negligibility threshold ............................... " << negligiblity << std::endl;
1395 std::unique_ptr<SparseMatrix> transpose;
1396#if BITPIT_ENABLE_MPI==1
1397 transpose = std::unique_ptr<SparseMatrix>(
new SparseMatrix(m_communicator, m_partitioned, m_nCols, m_nRows, m_nNZ));
1399 transpose = std::unique_ptr<SparseMatrix>(
new SparseMatrix(m_nCols, m_nRows, m_nNZ));
1403 std::vector<std::size_t> transposeRowSizes(transpose->m_nRows, 0);
1404 for (
int i = 0; i < m_nNZ; ++i) {
1405 long column = *(m_pattern.
data() + i);
1406 ++transposeRowSizes[column];
1409 transpose->m_pattern.initialize(transpose->m_nRows, transposeRowSizes.data(),
static_cast<long>(0));
1412 transpose->m_values.resize(m_blockSize * m_nNZ);
1415 transpose->m_nNZ = m_nNZ;
1417 transpose->m_maxRowNZ = 0;
1418 for (
int i = 0; i < transpose->m_nRows; ++i) {
1419 transpose->m_maxRowNZ = std::max(
static_cast<long>(transposeRowSizes[i]), transpose->m_maxRowNZ);
1423 const std::size_t *rowExtents = m_pattern.
indices();
1424 std::fill(transposeRowSizes.begin(), transposeRowSizes.end(), 0);
1425 for (
long row = 0; row < m_nRows; ++row) {
1426 const std::size_t rowPatternSize = rowExtents[row + 1] - rowExtents[row];
1427 const long *rowPattern = m_pattern.
data() + rowExtents[row];
1428 const double *rowValues = m_values.data() + rowExtents[row];
1429 for (std::size_t k = 0; k < rowPatternSize; ++k) {
1430 long column = rowPattern[k];
1431 const std::size_t transposeRowLastIndex = *(transpose->m_pattern.indices(column)) + transposeRowSizes[column];
1433 long *transposeRowLastPattern = transpose->m_pattern.data() + transposeRowLastIndex;
1434 *transposeRowLastPattern = row;
1436 double *transposeRowLastValue = transpose->m_values.data() + transposeRowLastIndex;
1437 *transposeRowLastValue = rowValues[k];
1439 ++transposeRowSizes[column];
1442 transpose->m_lastRow = transpose->m_nRows - 1;
1445 transpose->assembly();