Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_MatrixIO_def.hpp
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TPETRA_MATRIX_IO_DEF
11#define TPETRA_MATRIX_IO_DEF
12
13#include "Tpetra_CrsMatrix.hpp"
14#include "Tpetra_MatrixIO.hpp"
15#include <iostream>
16
17namespace Tpetra {
18namespace Utils {
19
20
21template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
22void
23readHBMatrix (const std::string &filename,
24 const Teuchos::RCP<const Teuchos::Comm<int> > &comm,
25 Teuchos::RCP< Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &A,
26 Teuchos::RCP< const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > rowMap,
27 const Teuchos::RCP<Teuchos::ParameterList> &params)
28{
29 typedef Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> map_type;
30
31 const int myRank = comm->getRank();
32 int numRows,numCols,numNZ;
33 Teuchos::ArrayRCP<Scalar> svals;
34 Teuchos::ArrayRCP<GlobalOrdinal> colinds;
35 Teuchos::ArrayRCP<int> rowptrs;
36 Teuchos::ArrayRCP<size_t> nnzPerRow;
37 int fail = 0;
38 if (myRank == 0) {
39 bool isSymmetric=false;
40 Teuchos::ArrayRCP<double> dvals;
41 Teuchos::ArrayRCP<int> colptrs, rowinds;
42 std::string type;
43 Tpetra::Utils::readHBMatDouble(filename,numRows,numCols,numNZ,type,colptrs,rowinds,dvals);
44 TEUCHOS_TEST_FOR_EXCEPT(type.size() != 3);
45 if (type[0] != 'R' && type[0] != 'r') {
46 // only real matrices right now
47 fail = 1;
48 }
49 if (fail == 0 && numNZ > 0) {
50 if (type[1] == 'S' || type[1] == 's') {
51 isSymmetric = true;
52 }
53 else {
54 isSymmetric = false;
55 }
56 }
57 if (fail == 0 && numNZ > 0) {
58 // find num non-zero per row
59 nnzPerRow = Teuchos::arcp<size_t>(numRows);
60 std::fill(nnzPerRow.begin(), nnzPerRow.end(), 0);
61 for (Teuchos::ArrayRCP<int>::const_iterator ri=rowinds.begin(); ri != rowinds.end(); ++ri) {
62 // count each row index towards its row
63 ++nnzPerRow[*ri-1];
64 }
65 if (isSymmetric) {
66 // count each column toward the corresponding row as well
67 for (int c=0; c < numCols; ++c) {
68 // the diagonal was already counted; neglect it, if it exists
69 for (int i=colptrs[c]-1; i != colptrs[c+1]-1; ++i) {
70 if (rowinds[i] != c+1) {
71 ++nnzPerRow[c];
72 ++numNZ;
73 }
74 }
75 }
76 }
77 // allocate/set new matrix data
78 svals = Teuchos::arcp<Scalar>(numNZ);
79 colinds = Teuchos::arcp<GlobalOrdinal>(numNZ);
80 rowptrs = Teuchos::arcp<int>(numRows+1);
81 rowptrs[0] = 0;
82#ifdef HAVE_TPETRA_DEBUG
83 Teuchos::ArrayRCP<size_t> nnzPerRow_debug(nnzPerRow.size());
84 std::copy(nnzPerRow.begin(), nnzPerRow.end(), nnzPerRow_debug.begin());
85#endif
86 for (int j=1; j <= numRows; ++j) {
87 rowptrs[j] = rowptrs[j-1] + nnzPerRow[j-1];
88 nnzPerRow[j-1] = 0;
89 }
90 // translate from column-oriented to row-oriented
91 for (int col=0; col<numCols; ++col) {
92 for (int i=colptrs[col]-1; i != colptrs[col+1]-1; ++i) {
93 const int row = rowinds[i]-1;
94 // add entry to (row,col), with value dvals[i]
95 const size_t entry = rowptrs[row] + nnzPerRow[row];
96 svals[entry] = Teuchos::as<Scalar>(dvals[i]);
97 colinds[entry] = Teuchos::as<GlobalOrdinal>(col);
98 ++nnzPerRow[row];
99 if (isSymmetric && row != col) {
100 // add entry to (col,row), with value dvals[i]
101 const size_t symentry = rowptrs[col] + nnzPerRow[col];
102 svals[symentry] = Teuchos::as<Scalar>(dvals[i]);
103 colinds[symentry] = Teuchos::as<GlobalOrdinal>(row);
104 ++nnzPerRow[col];
105 }
106 }
107 }
108#ifdef HAVE_TPETRA_DEBUG
109 {
110 bool isequal = true;
111 typename Teuchos::ArrayRCP<size_t>::const_iterator it1, it2;
112 for (it1 = nnzPerRow.begin(), it2 = nnzPerRow_debug.begin(); it1 != nnzPerRow.end(); ++it1, ++it2) {
113 if (*it1 != *it2) {
114 isequal = false;
115 break;
116 }
117 }
118 TEUCHOS_TEST_FOR_EXCEPTION(!isequal || nnzPerRow.size() != nnzPerRow_debug.size(), std::logic_error,
119 "Tpetra::Utils::readHBMatrix(): Logic error.");
120 }
121#endif
122 }
123 // std::cout << "Matrix " << filename << " of type " << type << ": " << numRows << " by " << numCols << ", " << numNZ << " nonzeros" << std::endl;
124 }
125 // check for read errors
126 broadcast(*comm,0,&fail);
127 TEUCHOS_TEST_FOR_EXCEPTION(fail == 1, std::runtime_error, "Tpetra::Utils::readHBMatrix() can only read Real matrices.");
128 // distribute global matrix info
129 broadcast(*comm,0,&numRows);
130 broadcast(*comm,0,&numCols);
131 // create map with uniform partitioning
132 if (rowMap == Teuchos::null) {
133 rowMap = Teuchos::rcp (new map_type (static_cast<global_size_t> (numRows),
134 static_cast<GlobalOrdinal> (0),
135 comm, GloballyDistributed));
136 }
137 else {
138 TEUCHOS_TEST_FOR_EXCEPTION( rowMap->getGlobalNumElements() != (global_size_t)numRows, std::runtime_error,
139 "Tpetra::Utils::readHBMatrix(): specified map has incorrect number of elements.");
140 TEUCHOS_TEST_FOR_EXCEPTION( rowMap->isDistributed() == false && comm->getSize() > 1, std::runtime_error,
141 "Tpetra::Utils::readHBMatrix(): specified map is not distributed.");
142 }
143 Teuchos::Array<size_t> myNNZ (rowMap->getLocalNumElements ());
144 if (myRank == 0) {
145 LocalOrdinal numRowsAlreadyDistributed = rowMap->getLocalNumElements();
146 std::copy(nnzPerRow.begin(), nnzPerRow.begin()+numRowsAlreadyDistributed, myNNZ.begin());
147 for (int p=1; p < Teuchos::size(*comm); ++p) {
148 size_t numRowsForP;
149 Teuchos::receive(*comm,p,&numRowsForP);
150 if (numRowsForP) {
151 Teuchos::send<int,size_t>(*comm,numRowsForP,nnzPerRow(numRowsAlreadyDistributed,numRowsForP).getRawPtr(),p);
152 numRowsAlreadyDistributed += numRowsForP;
153 }
154 }
155 }
156 else {
157 const size_t numMyRows = rowMap->getLocalNumElements();
158 Teuchos::send(*comm,numMyRows,0);
159 if (numMyRows) {
160 Teuchos::receive<int,size_t>(*comm,0,numMyRows,myNNZ(0,numMyRows).getRawPtr());
161 }
162 }
163 nnzPerRow = Teuchos::null;
164 // create column map
165 Teuchos::RCP<const map_type> domMap;
166 if (numRows == numCols) {
167 domMap = rowMap;
168 }
169 else {
171 }
172 A = rcp(new Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(rowMap, myNNZ ()));
173 // free this locally, A will keep it allocated as long as it is needed by A (up until allocation of nonzeros)
174 {
175 // Classic idiom for freeing an std::vector; resize doesn't
176 // promise deallocation.
177 Teuchos::Array<size_t> empty;
178 std::swap (myNNZ, empty);
179 }
180 if (myRank == 0 && numNZ > 0) {
181 for (int r=0; r < numRows; ++r) {
182 const LocalOrdinal nnz = rowptrs[r+1] - rowptrs[r];
183 if (nnz > 0) {
184 Teuchos::ArrayView<const GlobalOrdinal> inds = colinds(rowptrs[r],nnz);
185 Teuchos::ArrayView<const Scalar> vals = svals( rowptrs[r],nnz);
186 A->insertGlobalValues(r, inds, vals);
187 }
188 }
189 }
190 // don't need these anymore
191 colinds = Teuchos::null;
192 svals = Teuchos::null;
193 rowptrs = Teuchos::null;
194 A->fillComplete(domMap,rowMap,params);
195}
196
197
198} // namespace Utils
199} // namespace Tpetra
200
201//
202// Explicit instantiation macro
203//
204// Must be expanded from within the Tpetra::Utils namespace!
205//
206
207
208#define TPETRA_MATRIXIO_INSTANT(SCALAR,LO,GO,NODE) \
209 template void \
210 readHBMatrix< SCALAR, LO, GO, NODE > (const std::string&, \
211 const Teuchos::RCP<const Teuchos::Comm<int> > &, \
212 Teuchos::RCP<CrsMatrix< SCALAR, LO, GO, NODE > >&, \
213 Teuchos::RCP<const Tpetra::Map< LO, GO, NODE> >, \
214 const Teuchos::RCP<Teuchos::ParameterList>& );
215
216
217
218#endif
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > createUniformContigMapWithNode(const global_size_t numElements, const Teuchos::RCP< const Teuchos::Comm< int > > &comm)
Non-member constructor for a uniformly distributed, contiguous Map with a user-specified Kokkos Node.
size_t global_size_t
Global size_t object.