40 #ifndef TPETRA_BLOCKCRSMATRIX_HELPERS_DEF_HPP
41 #define TPETRA_BLOCKCRSMATRIX_HELPERS_DEF_HPP
45 #include "Tpetra_BlockCrsMatrix.hpp"
46 #include "Tpetra_CrsMatrix.hpp"
47 #include "Tpetra_HashTable.hpp"
48 #include "Tpetra_Import.hpp"
49 #include "Tpetra_Map.hpp"
50 #include "Tpetra_MultiVector.hpp"
51 #include "Teuchos_ParameterList.hpp"
52 #include "Teuchos_ScalarTraits.hpp"
58 template<
class Scalar,
class LO,
class GO,
class Node>
60 Teuchos::ParameterList pl;
62 out.open(fileName.c_str());
66 template<
class Scalar,
class LO,
class GO,
class Node>
69 out.open(fileName.c_str());
73 template<
class Scalar,
class LO,
class GO,
class Node>
75 Teuchos::ParameterList pl;
79 template<
class Scalar,
class LO,
class GO,
class Node>
85 typedef Teuchos::OrdinalTraits<GO> TOT;
92 RCP<const map_type>
const rowMap = A.
getRowMap();
93 RCP<const Teuchos::Comm<int> > comm = rowMap->getComm();
94 const int myRank = comm->getRank();
95 const size_t numProcs = comm->getSize();
98 bool alwaysUseParallelAlgorithm =
false;
99 if (params.isParameter(
"always use parallel algorithm"))
100 alwaysUseParallelAlgorithm = params.get<
bool>(
"always use parallel algorithm");
101 bool printMatrixMarketHeader =
true;
102 if (params.isParameter(
"print MatrixMarket header"))
103 printMatrixMarketHeader = params.get<
bool>(
"print MatrixMarket header");
105 if (printMatrixMarketHeader && myRank==0) {
106 std::time_t now = std::time(NULL);
108 const std::string dataTypeStr =
109 Teuchos::ScalarTraits<Scalar>::isComplex ?
"complex" :
"real";
119 os <<
"%%MatrixMarket matrix coordinate " << dataTypeStr <<
" general" << std::endl;
120 os <<
"% time stamp: " << ctime(&now);
121 os <<
"% written from " << numProcs <<
" processes" << std::endl;
122 os <<
"% point representation of Tpetra::BlockCrsMatrix" << std::endl;
125 os <<
"% " << numRows <<
" block rows, " << numCols <<
" block columns" << std::endl;
127 os <<
"% block size " << blockSize << std::endl;
128 os << numRows*blockSize <<
" " << numCols*blockSize <<
" " << A.
getGlobalNumEntries()*blockSize*blockSize << std::endl;
131 if (numProcs==1 && !alwaysUseParallelAlgorithm) {
134 size_t numRows = rowMap->getNodeNumElements();
137 RCP<const map_type> allMeshGidsMap = rcp(
new map_type(TOT::invalid(), numRows, A.
getIndexBase(), comm));
140 mv_type allMeshGids(allMeshGidsMap,1);
141 Teuchos::ArrayRCP<GO> allMeshGidsData = allMeshGids.getDataNonConst(0);
143 for (
size_t i=0; i<numRows; i++)
144 allMeshGidsData[i] = rowMap->getGlobalElement(i);
145 allMeshGidsData = Teuchos::null;
148 size_t stripSize = allMeshGids.getGlobalLength() / numProcs;
149 size_t remainder = allMeshGids.getGlobalLength() % numProcs;
151 size_t curStripSize = 0;
152 Teuchos::Array<GO> importMeshGidList;
153 for (
size_t i=0; i<numProcs; i++) {
155 curStripSize = stripSize;
156 if (i<remainder) curStripSize++;
157 importMeshGidList.resize(curStripSize);
158 for (
size_t j=0; j<curStripSize; j++) importMeshGidList[j] = j + curStart + A.
getIndexBase();
159 curStart += curStripSize;
162 TEUCHOS_TEST_FOR_EXCEPTION(myRank>0 && curStripSize!=0,
163 std::runtime_error,
"Tpetra::blockCrsMatrixWriter: (pid "
164 << myRank <<
") map size should be zero, but is " << curStripSize);
165 RCP<map_type> importMeshGidMap = rcp(
new map_type(TOT::invalid(), importMeshGidList(), A.
getIndexBase(), comm));
166 import_type gidImporter(allMeshGidsMap, importMeshGidMap);
167 mv_type importMeshGids(importMeshGidMap, 1);
168 importMeshGids.doImport(allMeshGids, gidImporter,
INSERT);
174 Teuchos::ArrayRCP<const GO> importMeshGidsData = importMeshGids.getData(0);
175 Teuchos::Array<GO> importMeshGidsGO;
176 importMeshGidsGO.reserve(importMeshGidsData.size());
177 for (
typename Teuchos::ArrayRCP<const GO>::size_type j=0; j<importMeshGidsData.size(); ++j)
178 importMeshGidsGO.push_back(importMeshGidsData[j]);
179 RCP<const map_type> importMap = rcp(
new map_type(TOT::invalid(), importMeshGidsGO(), rowMap->getIndexBase(), comm) );
181 import_type importer(rowMap,importMap );
183 RCP<crs_graph_type> graph =
createCrsGraph(importMap,numEntriesPerRow);
184 RCP<const map_type> domainMap = A.getCrsGraph().
getDomainMap();
185 graph->doImport(A.getCrsGraph(), importer,
INSERT);
186 graph->fillComplete(domainMap, importMap);
188 block_crs_matrix_type importA(*graph, A.
getBlockSize());
189 importA.doImport(A, importer,
INSERT);
197 template<
class Scalar,
class LO,
class GO,
class Node>
203 RCP<const map_type> rowMap = A.
getRowMap();
204 RCP<const map_type> colMap = A.
getColMap();
205 RCP<const Teuchos::Comm<int> > comm = rowMap->getComm();
206 const int myRank = comm->getRank();
208 const size_t meshRowOffset = rowMap->getIndexBase();
209 const size_t meshColOffset = colMap->getIndexBase();
210 TEUCHOS_TEST_FOR_EXCEPTION(meshRowOffset != meshColOffset,
211 std::runtime_error,
"Tpetra::writeMatrixStrip: "
212 "mesh row index base != mesh column index base");
217 std::runtime_error,
"Tpetra::writeMatrixStrip: pid "
218 << myRank <<
" should have 0 rows but has " << A.
getNodeNumRows());
220 std::runtime_error,
"Tpetra::writeMatrixStrip: pid "
221 << myRank <<
" should have 0 columns but has " << A.
getNodeNumCols());
226 std::runtime_error,
"Tpetra::writeMatrixStrip: "
227 "number of rows on pid 0 does not match global number of rows");
233 bool precisionChanged=
false;
234 int oldPrecision = 0;
235 if (params.isParameter(
"precision")) {
236 oldPrecision = os.precision(params.get<
int>(
"precision"));
237 precisionChanged=
true;
240 if (params.isParameter(
"zero-based indexing")) {
241 if (params.get<
bool>(
"zero-based indexing") ==
true)
246 for (localRowInd = 0; localRowInd < numLocalRows; ++localRowInd) {
249 const LO* localColInds;
255 GO globalMeshRowID = rowMap->getGlobalElement(localRowInd) - meshRowOffset;
257 for (LO k = 0; k < numEntries; ++k) {
258 GO globalMeshColID = colMap->getGlobalElement(localColInds[k]) - meshColOffset;
259 Scalar*
const curBlock = vals + blockSize * blockSize * k;
261 for (LO j = 0; j < blockSize; ++j) {
262 GO globalPointRowID = globalMeshRowID * blockSize + j + pointOffset;
263 for (LO i = 0; i < blockSize; ++i) {
264 GO globalPointColID = globalMeshColID * blockSize + i + pointOffset;
265 const Scalar curVal = curBlock[i + j * blockSize];
267 os << globalPointRowID <<
" " << globalPointColID <<
" ";
268 if (Teuchos::ScalarTraits<Scalar>::isComplex) {
271 os << Teuchos::ScalarTraits<Scalar>::real (curVal) <<
" "
272 << Teuchos::ScalarTraits<Scalar>::imag (curVal);
282 if (precisionChanged)
283 os.precision(oldPrecision);
284 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
285 std::runtime_error,
"Tpetra::writeMatrixStrip: "
286 "error getting view of local row " << localRowInd);
292 template<
class Scalar,
class LO,
class GO,
class Node>
293 Teuchos::RCP<BlockCrsMatrix<Scalar, LO, GO, Node> >
305 using Teuchos::Array;
306 using Teuchos::ArrayView;
313 const map_type &pointRowMap = *(pointMatrix.
getRowMap());
314 RCP<const map_type> meshRowMap = createMeshMap<LO,GO,Node>(blockSize, pointRowMap);
316 const map_type &pointColMap = *(pointMatrix.
getColMap());
317 RCP<const map_type> meshColMap = createMeshMap<LO,GO,Node>(blockSize, pointColMap);
319 const map_type &pointDomainMap = *(pointMatrix.
getDomainMap());
320 RCP<const map_type> meshDomainMap = createMeshMap<LO,GO,Node>(blockSize, pointDomainMap);
322 const map_type &pointRangeMap = *(pointMatrix.
getRangeMap());
323 RCP<const map_type> meshRangeMap = createMeshMap<LO,GO,Node>(blockSize, pointRangeMap);
328 RCP<crs_graph_type> meshCrsGraph = rcp(
new crs_graph_type(meshRowMap, meshColMap,
334 ArrayView<const LO> pointColInds;
335 ArrayView<const Scalar> pointVals;
336 Array<GO> meshColGids;
341 for (
int j=0; j<blockSize; ++j) {
342 LO rowLid = i*blockSize+j;
345 for (
int k=0; k<pointColInds.size(); ++k) {
346 GO meshColInd = pointColMap.getGlobalElement(pointColInds[k]) / blockSize;
347 meshColGids.push_back(meshColInd);
352 std::sort(meshColGids.begin(), meshColGids.end());
353 meshColGids.erase( std::unique(meshColGids.begin(), meshColGids.end()), meshColGids.end() );
354 meshCrsGraph->insertGlobalIndices(meshRowMap->getGlobalElement(i), meshColGids());
357 meshCrsGraph->fillComplete(meshDomainMap,meshRangeMap);
360 RCP<block_crs_matrix_type> blockMatrix = rcp(
new block_crs_matrix_type(*meshCrsGraph, blockSize));
363 int maxBlockEntries = blockMatrix->getNodeMaxNumRowEntries();
364 Array<Array<Scalar>> blocks(maxBlockEntries);
365 for (
int i=0; i<maxBlockEntries; ++i)
366 blocks[i].reserve(blockSize*blockSize);
367 std::map<int,int> bcol2bentry;
368 std::map<int,int>::iterator iter;
378 for (
int j=0; j<blockSize; ++j) {
379 LO rowLid = i*blockSize+j;
381 for (
int k=0; k<pointColInds.size(); ++k) {
383 LO meshColInd = pointColInds[k] / blockSize;
384 iter = bcol2bentry.find(meshColInd);
385 if (iter == bcol2bentry.end()) {
387 bcol2bentry[meshColInd] = blkCnt;
388 blocks[blkCnt].push_back(pointVals[k]);
392 int littleBlock = iter->second;
393 blocks[littleBlock].push_back(pointVals[k]);
399 for (iter=bcol2bentry.begin(); iter != bcol2bentry.end(); ++iter) {
400 LO localBlockCol = iter->first;
401 Scalar *vals = (blocks[iter->second]).getRawPtr();
402 blockMatrix->replaceLocalValues(i, &localBlockCol, vals, 1);
406 for (
int j=0; j<maxBlockEntries; ++j)
416 template<
class LO,
class GO,
class Node>
417 Teuchos::RCP<const Tpetra::Map<LO,GO,Node> >
420 typedef Teuchos::OrdinalTraits<Tpetra::global_size_t> TOT;
425 Teuchos::Array<GO> meshGids;
431 meshGids.reserve(pointGids.size());
433 for (
int i=0; i<pointGids.size(); ++i) {
434 GO meshGid = (pointGids[i]-indexBase) / blockSize + indexBase;
435 if (hashTable.
get(meshGid) == -1) {
436 hashTable.
add(meshGid,1);
437 meshGids.push_back(meshGid);
441 Teuchos::RCP<const map_type> meshMap = Teuchos::rcp(
new map_type(TOT::invalid(), meshGids(), 0, pointMap.
getComm()) );
454 #define TPETRA_BLOCKCRSMATRIX_HELPERS_INSTANT(S,LO,GO,NODE) \
455 template void blockCrsMatrixWriter(BlockCrsMatrix<S,LO,GO,NODE> const &A, std::string const &fileName); \
456 template void blockCrsMatrixWriter(BlockCrsMatrix<S,LO,GO,NODE> const &A, std::string const &fileName, Teuchos::ParameterList const ¶ms); \
457 template void blockCrsMatrixWriter(BlockCrsMatrix<S,LO,GO,NODE> const &A, std::ostream &os); \
458 template void blockCrsMatrixWriter(BlockCrsMatrix<S,LO,GO,NODE> const &A, std::ostream &os, Teuchos::ParameterList const ¶ms); \
459 template void writeMatrixStrip(BlockCrsMatrix<S,LO,GO,NODE> const &A, std::ostream &os, Teuchos::ParameterList const ¶ms); \
460 template Teuchos::RCP<BlockCrsMatrix<S, LO, GO, NODE> > convertToBlockCrsMatrix(const CrsMatrix<S, LO, GO, NODE>& pointMatrix, const LO &blockSize);
465 #define TPETRA_CREATEMESHMAP_INSTANT(LO,GO,NODE) \
466 template Teuchos::RCP<const Map<LO,GO,NODE> > createMeshMap (const LO& blockSize, const Map<LO,GO,NODE>& pointMap);
Sparse matrix whose entries are small dense square blocks, all of the same dimensions.
Teuchos::RCP< const map_type > getColMap() const
get the (mesh) map for the columns of this block matrix.
Teuchos::RCP< const map_type > getRowMap() const
get the (mesh) map for the rows of this block matrix.
size_t getNodeNumRows() const
get the local number of block rows
global_size_t getGlobalNumRows() const
get the global number of block rows
LO getLocalRowView(const LO localRowInd, const LO *&colInds, Scalar *&vals, LO &numInds) const
Get a view of the (mesh, i.e., block) row, using local (mesh, i.e., block) indices.
virtual global_size_t getGlobalNumEntries() const
The global number of stored (structurally nonzero) entries.
virtual global_size_t getGlobalNumCols() const
The global number of columns of this matrix.
virtual GO getIndexBase() const
The index base for global indices in this matrix.
virtual size_t getNodeNumCols() const
The number of columns needed to apply the forward operator on this node.
LO getBlockSize() const
The number of degrees of freedom per mesh point.
A distributed graph accessed by rows (adjacency lists) and stored sparsely.
Teuchos::RCP< const map_type > getDomainMap() const override
Returns the Map associated with the domain of this graph.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the graph, over all processes in the graph's communicator.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries.
size_t getNodeNumRows() const override
The number of matrix rows owned by the calling process.
size_t getGlobalMaxNumRowEntries() const override
Maximum number of entries in any row of the matrix, over all processes in the matrix's communicator.
void getLocalRowView(LocalOrdinal LocalRow, Teuchos::ArrayView< const LocalOrdinal > &indices, Teuchos::ArrayView< const Scalar > &values) const override
Get a constant, nonpersisting view of a row of this matrix, using local row and column indices.
Teuchos::RCP< const map_type > getDomainMap() const override
The domain Map of this matrix.
Teuchos::RCP< const map_type > getRangeMap() const override
The range Map of this matrix.
Teuchos::RCP< const map_type > getColMap() const override
The Map that describes the column distribution in this matrix.
Teuchos::RCP< const map_type > getRowMap() const override
The Map that describes the row distribution in this matrix.
ValueType get(const KeyType key)
Get the value corresponding to the given key.
void add(const KeyType key, const ValueType value)
Add a key and its value to the hash table.
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Teuchos::ArrayView< const global_ordinal_type > getNodeElementList() const
Return a NONOWNING view of the global indices owned by this process.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Accessors for the Teuchos::Comm and Kokkos Node objects.
global_ordinal_type getIndexBase() const
The index base for this Map.
One or more distributed dense vectors.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void writeMatrixStrip(BlockCrsMatrix< Scalar, LO, GO, Node > const &A, std::ostream &os, Teuchos::ParameterList const ¶ms)
Helper function called by blockCrsMatrixWriter.
Teuchos::RCP< CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > createCrsGraph(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t maxNumEntriesPerRow=0, const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
Nonmember function to create an empty CrsGraph given a row Map and the max number of entries allowed ...
Teuchos::RCP< BlockCrsMatrix< Scalar, LO, GO, Node > > convertToBlockCrsMatrix(const Tpetra::CrsMatrix< Scalar, LO, GO, Node > &pointMatrix, const LO &blockSize)
Non-member constructor that creates a BlockCrsMatrix from an existing point CrsMatrix.
void blockCrsMatrixWriter(BlockCrsMatrix< Scalar, LO, GO, Node > const &A, std::string const &fileName)
Helper function to write a BlockCrsMatrix. Calls the 3-argument version.
@ INSERT
Insert new values that don't currently exist.
Teuchos::RCP< const Tpetra::Map< LO, GO, Node > > createMeshMap(LO const &blockSize, const Tpetra::Map< LO, GO, Node > &pointMap)
Helper function to generate a mesh map from a point map. Important! It's assumed that point GIDs asso...