Xpetra_EpetraCrsMatrix.cpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Xpetra: A linear algebra interface package
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #include <Teuchos_Array.hpp>
48 
49 namespace Xpetra {
50 
51  template<class EpetraGlobalOrdinal>
53  : mtx_(Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(rowMap), maxNumEntriesPerRow, toEpetra(pftype)))), isFillResumed_(false) { }
54 
55  template<class EpetraGlobalOrdinal>
57  : isFillResumed_(false)
58  {
59  Teuchos::Array<int> numEntriesPerRowToAlloc(NumEntriesPerRowToAlloc.begin(), NumEntriesPerRowToAlloc.end()); // convert array of "size_t" to array of "int"
60  mtx_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(rowMap), numEntriesPerRowToAlloc.getRawPtr(), toEpetra(pftype)));
61  }
62 
63  template<class EpetraGlobalOrdinal>
65  : mtx_(Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(rowMap), toEpetra(colMap), maxNumEntriesPerRow, toEpetra(pftype)))), isFillResumed_(false) { }
66 
67  template<class EpetraGlobalOrdinal>
69  : isFillResumed_(false)
70  {
71  Teuchos::Array<int> numEntriesPerRowToAlloc(NumEntriesPerRowToAlloc.begin(), NumEntriesPerRowToAlloc.end()); // convert array of "size_t" to array of "int"
72  mtx_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(rowMap), toEpetra(colMap), numEntriesPerRowToAlloc.getRawPtr(), toEpetra(pftype)));
73  }
74 
75  template<class EpetraGlobalOrdinal>
77  : mtx_(Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(graph)))), isFillResumed_(false) { }
78 
79  template<class EpetraGlobalOrdinal>
81  : mtx_(Teuchos::rcp(new Epetra_CrsMatrix(*(matrix.mtx_)))), isFillResumed_(false) { }
82 
83 
84  template<class EpetraGlobalOrdinal>
87  const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& domainMap,
88  const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rangeMap,
90  isFillResumed_(false)
91  {
92  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, *sourceMatrix, tSourceMatrix, "Xpetra::EpetraCrsMatrixT constructor only accepts Xpetra::EpetraCrsMatrixT as an input argument.");
93  XPETRA_DYNAMIC_CAST(const EpetraImportT<GlobalOrdinal>, importer, tImporter, "Xpetra::EpetraCrsMatrixT constructor only accepts Xpetra::EpetraImportT as an input argument.");
94 
95  const Epetra_Map* myDomainMap = (domainMap!=Teuchos::null)? &toEpetra(domainMap): 0;
96  const Epetra_Map* myRangeMap = (rangeMap !=Teuchos::null)? &toEpetra(rangeMap) : 0;
97 
98  // Follows the Tpetra parameters
99  bool restrictComm=false;
100  if(!params.is_null()) restrictComm = params->get("Restrict Communicator",restrictComm);
101  mtx_ = Teuchos::rcp(new Epetra_CrsMatrix(*tSourceMatrix.getEpetra_CrsMatrix(),*tImporter.getEpetra_Import(),myDomainMap,myRangeMap,restrictComm));
102  if(restrictComm && mtx_->NumMyRows()==0)
103  mtx_=Teuchos::null;
104  }
105 
106  template<class EpetraGlobalOrdinal>
109  const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& domainMap,
110  const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& rangeMap,
112  isFillResumed_(false)
113  {
114  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, *sourceMatrix, tSourceMatrix, "Xpetra::EpetraCrsMatrixT constructor only accepts Xpetra::EpetraCrsMatrixT as an input argument.");
115  XPETRA_DYNAMIC_CAST(const EpetraExportT<GlobalOrdinal>, exporter, tExporter, "Xpetra::EpetraCrsMatrixT constructor only accepts Xpetra::EpetraExportT as an input argument.");
116 
117  const Epetra_Map* myDomainMap = (domainMap!=Teuchos::null)? &toEpetra(domainMap): 0;
118  const Epetra_Map* myRangeMap = (rangeMap !=Teuchos::null)? &toEpetra(rangeMap) : 0;
119 
120  // Follows the Tpetra parameters
121  bool restrictComm=false;
122  if(!params.is_null()) restrictComm = params->get("Restrict Communicator",restrictComm);
123 
124  mtx_ = Teuchos::rcp(new Epetra_CrsMatrix(*tSourceMatrix.getEpetra_CrsMatrix(),*tExporter.getEpetra_Export(),myDomainMap,myRangeMap,restrictComm));
125  }
126 
127 #ifdef HAVE_XPETRA_KOKKOS_REFACTOR
128  template<class EpetraGlobalOrdinal>
131  const local_matrix_type& lclMatrix,
132  const Teuchos::RCP<Teuchos::ParameterList>& params) {
133  // local typedefs from local_matrix_type
134  typedef typename local_matrix_type::size_type size_type;
135  typedef typename local_matrix_type::value_type value_type;
136  typedef typename local_matrix_type::ordinal_type ordinal_type;
137 
138  // The number of rows in the sparse matrix.
139  ordinal_type lclNumRows = lclMatrix.numRows ();
140  ordinal_type lclNumCols = lclMatrix.numCols (); // do we need this?
141 
142  // plausibility checks
143  TEUCHOS_TEST_FOR_EXCEPTION(lclNumRows != Teuchos::as<ordinal_type>(rowMap->getNodeNumElements()), Xpetra::Exceptions::RuntimeError, "Xpetra::EpetraCrsMatrixT: number of rows in local matrix and number of local entries in row map do not match!");
144  TEUCHOS_TEST_FOR_EXCEPTION(lclNumCols != Teuchos::as<ordinal_type>(colMap->getNodeNumElements()), Xpetra::Exceptions::RuntimeError, "Xpetra::EpetraCrsMatrixT: number of columns in local matrix and number of local entries in column map do not match!");
145 
146  std::vector<GlobalOrdinal> domainMapGids; // vector for collecting domain map GIDs
147 
148  Teuchos::ArrayRCP< size_t > NumEntriesPerRowToAlloc(lclNumRows);
149  for (ordinal_type r = 0; r < lclNumRows; ++r) {
150  // extract data from current row r
151  Kokkos::SparseRowView<local_matrix_type,size_type> rowview = lclMatrix.template row<size_type>(r);
152  NumEntriesPerRowToAlloc[r] = rowview.length;
153  }
154 
155  // setup matrix
156  isFillResumed_ = false;
157  Teuchos::Array<int> numEntriesPerRowToAlloc(NumEntriesPerRowToAlloc.begin(), NumEntriesPerRowToAlloc.end()); // convert array of "size_t" to array of "int"
158  mtx_ = Teuchos::rcp(new Epetra_CrsMatrix(Copy, toEpetra(rowMap), toEpetra(colMap), numEntriesPerRowToAlloc.getRawPtr(), toEpetra(DynamicProfile)));
159 
160  // loop over all rows and colums of local matrix and fill matrix
161  for (ordinal_type r = 0; r < lclNumRows; ++r) {
162  // extract data from current row r
163  Kokkos::SparseRowView<local_matrix_type,size_type> rowview = lclMatrix.template row<size_type>(r);
164 
165  // arrays for current row data
168 
169  for(ordinal_type c = 0; c < rowview.length; c++) {
170  value_type value = rowview.value (c);
171  ordinal_type colidx = rowview.colidx (c);
172 
173  TEUCHOS_TEST_FOR_EXCEPTION(colMap->isNodeLocalElement(colidx) == false, Xpetra::Exceptions::RuntimeError, "Xpetra::EpetraCrsMatrixT: local matrix contains column elements which are not in the provided column map!");
174 
175  indout [c] = colidx;
176  valout [c] = value;
177 
178  // collect GIDs for domain map
179  GlobalOrdinal gcid = colMap->getGlobalElement(c);
180  if(rowMap->isNodeGlobalElement(gcid)) domainMapGids.push_back(gcid);
181  }
182  insertLocalValues(r, indout.view(0,indout.size()), valout.view(0,valout.size()));
183  }
184 
185  // sort entries in domainMapGids and remove duplicates
187  std::sort(domainMapGids.begin(), domainMapGids.end());
188  domainMapGids.erase(std::unique(domainMapGids.begin(), domainMapGids.end()), domainMapGids.end());
189  Teuchos::ArrayView<GlobalOrdinal> domainMapGidsView(&domainMapGids[0], domainMapGids.size());
191  Xpetra::MapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(colMap->lib(), INVALID, domainMapGidsView, colMap->getIndexBase(), colMap->getComm());
192 
193  // call fill complete
194  this->fillComplete(domainMap, rowMap, params);
195  }
196 #endif
197 
198  template<class EpetraGlobalOrdinal>
200  XPETRA_MONITOR("EpetraCrsMatrixT::insertGlobalValues");
201  XPETRA_ERR_CHECK(mtx_->InsertGlobalValues(globalRow, vals.size(), vals.getRawPtr(), cols.getRawPtr()));
202  }
203 
204  template<class EpetraGlobalOrdinal>
206  XPETRA_MONITOR("EpetraCrsMatrixT::insertLocalValues");
207  XPETRA_ERR_CHECK(mtx_->InsertMyValues(localRow, vals.size(), vals.getRawPtr(), cols.getRawPtr()));
208  }
209 
210  template<class EpetraGlobalOrdinal>
212  XPETRA_MONITOR("EpetraCrsMatrixT::replaceGlobalValues");
213 
214  {
215  const std::string tfecfFuncName("replaceGlobalValues");
216  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(! isFillActive(), std::runtime_error,
217  ": Fill must be active in order to call this method. If you have already "
218  "called fillComplete(), you need to call resumeFill() before you can "
219  "replace values.");
220 
221  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(values.size() != indices.size(),
222  std::runtime_error, ": values.size() must equal indices.size().");
223  }
224 
225  XPETRA_ERR_CHECK(mtx_->ReplaceGlobalValues(globalRow, indices.size(), values.getRawPtr(), indices.getRawPtr()));
226 
227  }
228 
229  template<class EpetraGlobalOrdinal>
231  XPETRA_MONITOR("EpetraCrsMatrixT::replaceLocalValues");
232 
233  {
234  const std::string tfecfFuncName("replaceLocalValues");
235  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(! isFillActive(), std::runtime_error,
236  ": Fill must be active in order to call this method. If you have already "
237  "called fillComplete(), you need to call resumeFill() before you can "
238  "replace values.");
239 
240  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(values.size() != indices.size(),
241  std::runtime_error, ": values.size() must equal indices.size().");
242  }
243 
244  XPETRA_ERR_CHECK(mtx_->ReplaceMyValues(localRow, indices.size(), values.getRawPtr(), indices.getRawPtr()));
245 
246  }
247 
248  template<class EpetraGlobalOrdinal>
250  XPETRA_MONITOR("EpetraCrsMatrixT::allocateAllValues");
251 
252  // Row offsets
253  // Unfortunately, we cannot do this in the same manner as column indices
254  // and values (see below). The problem is that Tpetra insists on using
255  // size_t, and Epetra uses int internally. So we only resize here, and
256  // will need to copy in setAllValues
257  rowptr.resize(getNodeNumRows()+1);
258 
259  int lowerOffset = 0;
260  bool ownMemory = false;
261 
262  // Column indices
263  // Extract, resize, set colind
264  Epetra_IntSerialDenseVector& myColind = mtx_->ExpertExtractIndices();
265  myColind.Resize(numNonZeros);
266  colind = Teuchos::arcp(myColind.Values(), lowerOffset, numNonZeros, ownMemory);
267 
268  // Values
269  // Extract, reallocate, set values
270  double *& myValues = mtx_->ExpertExtractValues();
271  delete [] myValues;
272  myValues = new double[numNonZeros];
273  values = Teuchos::arcp(myValues,lowerOffset,numNonZeros,ownMemory);
274  }
275 
276  template<class EpetraGlobalOrdinal>
278  XPETRA_MONITOR("EpetraCrsMatrixT::setAllValues");
279 
280  // Check sizes
282  "An exception is thrown to let you know that the size of your rowptr array is incorrect.");
284  "An exception is thrown to let you know that you mismatched your pointers.");
285 
286  // Check pointers
287  if (values.size() > 0) {
288  TEUCHOS_TEST_FOR_EXCEPTION(colind.getRawPtr() != mtx_->ExpertExtractIndices().Values(), Xpetra::Exceptions::RuntimeError,
289  "An exception is thrown to let you know that you mismatched your pointers.");
291  "An exception is thrown to let you know that you mismatched your pointers.");
292  }
293 
294  // We have to make a copy here, it is unavoidable
295  // See comments in allocateAllValues
296  const size_t N = getNodeNumRows();
297 
298  Epetra_IntSerialDenseVector& myRowptr = mtx_->ExpertExtractIndexOffset();
299  myRowptr.Resize(N+1);
300  for (size_t i = 0; i < N+1; i++)
301  myRowptr[i] = Teuchos::as<int>(rowptr[i]);
302  }
303 
304  template<class EpetraGlobalOrdinal>
306  XPETRA_MONITOR("EpetraCrsMatrixT::getAllValues");
307 
308  int lowerOffset = 0;
309  bool ownMemory = false;
310 
311  const size_t n = getNodeNumRows();
312  const size_t nnz = getNodeNumEntries();
313 
314  // Row offsets
315  // We have to make a copy here, it is unavoidable (see comments in allocateAllValues)
316  Epetra_IntSerialDenseVector& myRowptr = mtx_->ExpertExtractIndexOffset();
317  rowptr.resize(n+1);
318  for (size_t i = 0; i < n+1; i++)
319  (*const_cast<size_t*>(&rowptr[i])) = Teuchos::as<size_t>(myRowptr[i]);
320 
321  // Column indices
322  colind = Teuchos::arcp(mtx_->ExpertExtractIndices().Values(), lowerOffset, nnz, ownMemory);
323 
324  // Values
325  values = Teuchos::arcp(mtx_->ExpertExtractValues(), lowerOffset, nnz, ownMemory);
326  }
327 
328  template<class EpetraGlobalOrdinal>
330  XPETRA_MONITOR("EpetraCrsMatrixT::resumeFill");
331 
332  // According to Tpetra documentation, resumeFill() may be called repeatedly.
333  isFillResumed_ = true;
334  }
335 
336  template<class EpetraGlobalOrdinal>
337  bool EpetraCrsMatrixT<EpetraGlobalOrdinal>::isFillComplete() const { XPETRA_MONITOR("EpetraCrsMatrixT::isFillComplete"); if (isFillResumed_) return false; else return mtx_->Filled(); }
338 
339  template<class EpetraGlobalOrdinal>
340  bool EpetraCrsMatrixT<EpetraGlobalOrdinal>::isFillActive() const { XPETRA_MONITOR("EpetraCrsMatrixT::isFillActive"); return !isFillComplete(); }
341 
342  template<class EpetraGlobalOrdinal>
343  bool EpetraCrsMatrixT<EpetraGlobalOrdinal>::supportsRowViews() const { XPETRA_MONITOR("EpetraCrsMatrixT::supportsRowViews"); return true; }
344 
345  //TODO: throw same exception as Tpetra
346  template<class EpetraGlobalOrdinal>
347  void EpetraCrsMatrixT<EpetraGlobalOrdinal>::getLocalRowCopy(LocalOrdinal LocalRow, const ArrayView<LocalOrdinal> &Indices, const ArrayView<Scalar> &Values, size_t &NumEntries) const {
348  XPETRA_MONITOR("EpetraCrsMatrixT::getLocalRowCopy");
349 
350  int numEntries = -1;
351  XPETRA_ERR_CHECK(mtx_->ExtractMyRowCopy(LocalRow, Indices.size(), numEntries, Values.getRawPtr(), Indices.getRawPtr()));
352  NumEntries = numEntries;
353  }
354 
355  template<class EpetraGlobalOrdinal>
356  void EpetraCrsMatrixT<EpetraGlobalOrdinal>::getGlobalRowCopy(GlobalOrdinal GlobalRow, const ArrayView<GlobalOrdinal> &Indices, const ArrayView<Scalar> &Values, size_t &NumEntries) const {
357  XPETRA_MONITOR("EpetraCrsMatrixT::getGlobalRowCopy");
358 
359  int numEntries = -1;
360  XPETRA_ERR_CHECK(mtx_->ExtractGlobalRowCopy(GlobalRow, Indices.size(), numEntries, Values.getRawPtr(), Indices.getRawPtr()));
361  NumEntries = numEntries;
362  }
363 
364  template<class EpetraGlobalOrdinal>
366  XPETRA_MONITOR("EpetraCrsMatrixT::getGlobalRowView");
367 
368  int numEntries;
369  double * eValues;
370  GlobalOrdinal * eIndices;
371 
372  XPETRA_ERR_CHECK(mtx_->ExtractGlobalRowView(GlobalRow, numEntries, eValues, eIndices));
373  if (numEntries == 0) { eValues = NULL; eIndices = NULL; } // Cf. TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 ) in Teuchos ArrayView constructor.
374 
375  indices = ArrayView<const GlobalOrdinal>(eIndices, numEntries);
376  values = ArrayView<const double>(eValues, numEntries);
377  }
378 
379  template<class EpetraGlobalOrdinal>
381  XPETRA_MONITOR("EpetraCrsMatrixT::getLocalRowView");
382 
383  int numEntries;
384  double * eValues;
385  int * eIndices;
386 
387  XPETRA_ERR_CHECK(mtx_->ExtractMyRowView(LocalRow, numEntries, eValues, eIndices));
388  if (numEntries == 0) { eValues = NULL; eIndices = NULL; } // Cf. TEUCHOS_TEST_FOR_EXCEPT( p == 0 && size_in != 0 ) in Teuchos ArrayView constructor.
389 
390  indices = ArrayView<const int>(eIndices, numEntries);
391  values = ArrayView<const double>(eValues, numEntries);
392  }
393 
394  template<class EpetraGlobalOrdinal>
396  XPETRA_MONITOR("EpetraCrsMatrixT::apply");
397 
398  //TEUCHOS_TEST_FOR_EXCEPTION((alpha != 1) || (beta != 0), Xpetra::Exceptions::NotImplemented, "Xpetra::EpetraCrsMatrixT.multiply() only accept alpha==1 and beta==0");
399 
400  XPETRA_DYNAMIC_CAST(const EpetraMultiVectorT<GlobalOrdinal>, X, eX, "Xpetra::EpetraCrsMatrixT->apply() only accept Xpetra::EpetraMultiVectorT as input arguments.");
401  XPETRA_DYNAMIC_CAST( EpetraMultiVectorT<GlobalOrdinal>, Y, eY, "Xpetra::EpetraCrsMatrixT->apply() only accept Xpetra::EpetraMultiVectorT as input arguments.");
402 
403  TEUCHOS_TEST_FOR_EXCEPTION((mode != Teuchos::NO_TRANS) && (mode != Teuchos::TRANS), Xpetra::Exceptions::NotImplemented, "Xpetra::EpetraCrsMatrixT->apply() only accept mode == NO_TRANS or mode == TRANS");
404  bool eTrans = toEpetra(mode);
405 
406  // /!\ UseTranspose value
407  TEUCHOS_TEST_FOR_EXCEPTION(mtx_->UseTranspose(), Xpetra::Exceptions::NotImplemented, "An exception is throw to let you know that Xpetra::EpetraCrsMatrixT->apply() do not take into account the UseTranspose() parameter of Epetra_CrsMatrix.");
408 
409  RCP<Epetra_MultiVector> epY = eY.getEpetra_MultiVector();
410 
411  // helper vector: tmp = A*x
412  RCP<Epetra_MultiVector> tmp = Teuchos::rcp(new Epetra_MultiVector(*epY));
413  tmp->PutScalar(0.0);
414  XPETRA_ERR_CHECK(mtx_->Multiply(eTrans, *eX.getEpetra_MultiVector(), *tmp));
415 
416  // calculate alpha * A * x + beta * y
417  XPETRA_ERR_CHECK(eY.getEpetra_MultiVector()->Update(alpha,*tmp,beta));
418  }
419 
420  template<class EpetraGlobalOrdinal>
422  XPETRA_MONITOR("EpetraCrsMatrixT::description");
423 
424  // This implementation come from Tpetra_CrsMatrix_def.hpp (without modification)
425  std::ostringstream oss;
426  //TODO: oss << DistObject<char, LocalOrdinal,GlobalOrdinal>::description();
427  if (isFillComplete()) {
428  oss << "{status = fill complete"
429  << ", global rows = " << getGlobalNumRows()
430  << ", global cols = " << getGlobalNumCols()
431  << ", global num entries = " << getGlobalNumEntries()
432  << "}";
433  }
434  else {
435  oss << "{status = fill not complete"
436  << ", global rows = " << getGlobalNumRows()
437  << "}";
438  }
439  return oss.str();
440 
441  }
442 
443  template<class EpetraGlobalOrdinal>
445  XPETRA_MONITOR("EpetraCrsMatrixT::describe");
446 
447  // This implementation come from Tpetra_CrsMatrix_def.hpp (without modification)
448  using std::endl;
449  using std::setw;
450  using Teuchos::VERB_DEFAULT;
451  using Teuchos::VERB_NONE;
452  using Teuchos::VERB_LOW;
453  using Teuchos::VERB_MEDIUM;
454  using Teuchos::VERB_HIGH;
455  using Teuchos::VERB_EXTREME;
456  Teuchos::EVerbosityLevel vl = verbLevel;
457  if (vl == VERB_DEFAULT) vl = VERB_LOW;
458  RCP<const Comm<int> > comm = this->getComm();
459  const int myImageID = comm->getRank(),
460  numImages = comm->getSize();
461  size_t width = 1;
462  for (size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
463  ++width;
464  }
465  width = std::max<size_t>(width,11) + 2;
466  Teuchos::OSTab tab(out);
467  // none: print nothing
468  // low: print O(1) info from node 0
469  // medium: print O(P) info, num entries per node
470  // high: print O(N) info, num entries per row
471  // extreme: print O(NNZ) info: print indices and values
472  //
473  // for medium and higher, print constituent objects at specified verbLevel
474  if (vl != VERB_NONE) {
475  if (myImageID == 0) out << this->description() << std::endl;
476  // O(1) globals, minus what was already printed by description()
477  if (isFillComplete() && myImageID == 0) {
478  out << "Global number of diagonals = " << getGlobalNumDiags() << std::endl;
479  out << "Global max number of entries = " << getGlobalMaxNumRowEntries() << std::endl;
480  }
481  // constituent objects
482  if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
483  if (myImageID == 0) out << "\nRow map: " << std::endl;
484  getRowMap()->describe(out,vl);
485  //
486  if (getColMap() != null) {
487  if (getColMap() == getRowMap()) {
488  if (myImageID == 0) out << "\nColumn map is row map.";
489  }
490  else {
491  if (myImageID == 0) out << "\nColumn map: " << std::endl;
492  getColMap()->describe(out,vl);
493  }
494  }
495  if (getDomainMap() != null) {
496  if (getDomainMap() == getRowMap()) {
497  if (myImageID == 0) out << "\nDomain map is row map.";
498  }
499  else if (getDomainMap() == getColMap()) {
500  if (myImageID == 0) out << "\nDomain map is row map.";
501  }
502  else {
503  if (myImageID == 0) out << "\nDomain map: " << std::endl;
504  getDomainMap()->describe(out,vl);
505  }
506  }
507  if (getRangeMap() != null) {
508  if (getRangeMap() == getDomainMap()) {
509  if (myImageID == 0) out << "\nRange map is domain map." << std::endl;
510  }
511  else if (getRangeMap() == getRowMap()) {
512  if (myImageID == 0) out << "\nRange map is row map." << std::endl;
513  }
514  else {
515  if (myImageID == 0) out << "\nRange map: " << std::endl;
516  getRangeMap()->describe(out,vl);
517  }
518  }
519  if (myImageID == 0) out << std::endl;
520  }
521  // O(P) data
522  if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
523  for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
524  if (myImageID == imageCtr) {
525  out << "Node ID = " << imageCtr << std::endl;
526  // TODO: need a graph
527  // if (staticGraph_->indicesAreAllocated() == false) {
528  // out << "Node not allocated" << std::endl;
529  // }
530  // else {
531  // out << "Node number of allocated entries = " << staticGraph_->getNodeAllocationSize() << std::endl;
532  // }
533 
534  // TMP:
535  // const Epetra_CrsGraph & staticGraph_ = mtx_->Graph();
536  // End of TMP
537 
538  out << "Node number of entries = " << getNodeNumEntries() << std::endl;
539  if (isFillComplete()) {
540  out << "Node number of diagonals = " << getNodeNumDiags() << std::endl;
541  }
542  out << "Node max number of entries = " << getNodeMaxNumRowEntries() << std::endl;
543  }
544  comm->barrier();
545  comm->barrier();
546  comm->barrier();
547  }
548  }
549  // O(N) and O(NNZ) data
550  if (vl == VERB_HIGH || vl == VERB_EXTREME) {
551  for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
552  if (myImageID == imageCtr) {
553  out << std::setw(width) << "Node ID"
554  << std::setw(width) << "Global Row"
555  << std::setw(width) << "Num Entries";
556  if (vl == VERB_EXTREME) {
557  out << std::setw(width) << "(Index,Value)";
558  }
559  out << std::endl;
560  for (size_t r=0; r < getNodeNumRows(); ++r) {
561  const size_t nE = getNumEntriesInLocalRow(r);
562  GlobalOrdinal gid = getRowMap()->getGlobalElement(r);
563  out << std::setw(width) << myImageID
564  << std::setw(width) << gid
565  << std::setw(width) << nE;
566  if (vl == VERB_EXTREME) {
567  if (isGloballyIndexed()) {
569  ArrayView<const Scalar> rowvals;
570  getGlobalRowView(gid,rowinds,rowvals);
571  for (size_t j=0; j < nE; ++j) {
572  out << " (" << rowinds[j]
573  << ", " << rowvals[j]
574  << ") ";
575  }
576  }
577  else if (isLocallyIndexed()) {
579  ArrayView<const Scalar> rowvals;
580  getLocalRowView(r,rowinds,rowvals);
581  for (size_t j=0; j < nE; ++j) {
582  out << " (" << getColMap()->getGlobalElement(rowinds[j])
583  << ", " << rowvals[j]
584  << ") ";
585  }
586  }
587  }
588  out << std::endl;
589  }
590  }
591  comm->barrier();
592  comm->barrier();
593  comm->barrier();
594  }
595  }
596  }
597 
598  }
599 
600  // TODO: use toEpetra()
601  template<class EpetraGlobalOrdinal>
604  XPETRA_MONITOR("EpetraCrsMatrixT::doImport");
605 
606  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, source, tSource, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraCrsMatrixT as input arguments.");
607  XPETRA_DYNAMIC_CAST(const EpetraImportT<GlobalOrdinal>, importer, tImporter, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraImportT as input arguments.");
608 
609  RCP<const Epetra_CrsMatrix> v = tSource.getEpetra_CrsMatrix();
610  int err = mtx_->Import(*v, *tImporter.getEpetra_Import(), toEpetra(CM));
611  TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, "Catch error code returned by Epetra.");
612  }
613 
614  template<class EpetraGlobalOrdinal>
617  XPETRA_MONITOR("EpetraCrsMatrixT::doExport");
618 
619  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, dest, tDest, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraCrsMatrixT as input arguments.");
620  XPETRA_DYNAMIC_CAST(const EpetraImportT<GlobalOrdinal>, importer, tImporter, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraImportT as input arguments.");
621 
622  RCP<const Epetra_CrsMatrix> v = tDest.getEpetra_CrsMatrix();
623  int err = mtx_->Export(*v, *tImporter.getEpetra_Import(), toEpetra(CM));
624  TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, "Catch error code returned by Epetra.");
625  }
626 
627  template<class EpetraGlobalOrdinal>
630  XPETRA_MONITOR("EpetraCrsMatrixT::doImport");
631 
632  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, source, tSource, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraCrsMatrixT as input arguments.");
633  XPETRA_DYNAMIC_CAST(const EpetraExportT<GlobalOrdinal>, exporter, tExporter, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraImportT as input arguments.");
634 
635  RCP<const Epetra_CrsMatrix> v = tSource.getEpetra_CrsMatrix();
636  int err = mtx_->Import(*v, *tExporter.getEpetra_Export(), toEpetra(CM));
637  TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, "Catch error code returned by Epetra.");
638 
639  }
640 
641  template<class EpetraGlobalOrdinal>
644  XPETRA_MONITOR("EpetraCrsMatrixT::doExport");
645 
646  XPETRA_DYNAMIC_CAST(const EpetraCrsMatrixT<GlobalOrdinal>, dest, tDest, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraCrsMatrixT as input arguments.");
647  XPETRA_DYNAMIC_CAST(const EpetraExportT<GlobalOrdinal>, exporter, tExporter, "Xpetra::EpetraCrsMatrixT::doImport only accept Xpetra::EpetraImportT as input arguments.");
648 
649  RCP<const Epetra_CrsMatrix> v = tDest.getEpetra_CrsMatrix();
650  int err = mtx_->Export(*v, *tExporter.getEpetra_Export(), toEpetra(CM));
651  TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, "Catch error code returned by Epetra.");
652  }
653 
654  template<class EpetraGlobalOrdinal>
656  const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap,
657  const RCP< ParameterList > &params) {
658  XPETRA_MONITOR("EpetraCrsMatrixT::fillComplete");
659 
660  // For Epetra matrices, resumeFill() is a fictive operation. There is no need for a fillComplete after some resumeFill() operations.
661  if (isFillResumed_ == true) { isFillResumed_ = false; return; }
662 
663  bool doOptimizeStorage = true;
664  if (params != null && params->get("Optimize Storage",true) == false) doOptimizeStorage = false;
665  mtx_->FillComplete(toEpetra(domainMap), toEpetra(rangeMap), doOptimizeStorage);
666  }
667 
668  template<class EpetraGlobalOrdinal>
670  XPETRA_MONITOR("EpetraCrsMatrixT::fillComplete");
671 
672  // For Epetra matrices, resumeFill() is a fictive operation. There is no need for a fillComplete after some resumeFill() operations.
673  if (isFillResumed_ == true) { isFillResumed_ = false; return; }
674 
675  bool doOptimizeStorage = true;
676  if (params != null && params->get("Optimize Storage",true) == false) doOptimizeStorage = false;
677  mtx_->FillComplete(doOptimizeStorage);
678  }
679 
680 
681  template<class EpetraGlobalOrdinal>
683  XPETRA_MONITOR("EpetraCrsMatrixT::replaceDomainMapAndImporter");
684  XPETRA_DYNAMIC_CAST(const EpetraImportT<GlobalOrdinal>, *newImporter, eImporter, "Xpetra::EpetraCrsMatrixT::replaceDomainMapAndImporter only accepts Xpetra::EpetraImportT.");
685 
686  const RCP<const Epetra_Import> & myImport = eImporter.getEpetra_Import();
687  int rv=0;
688  if(myImport==Teuchos::null)
689  rv=mtx_->ReplaceDomainMapAndImporter( toEpetra(newDomainMap),0);
690  else
691  rv=mtx_->ReplaceDomainMapAndImporter( toEpetra(newDomainMap),&*myImport);
692  TEUCHOS_TEST_FOR_EXCEPTION(rv != 0, std::runtime_error, "Xpetra::EpetraCrsMatrixT::replaceDomainMapAndImporter FAILED!");
693  }
694 
695 
696  template<class EpetraGlobalOrdinal>
698  const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & rangeMap,
699  const RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > &importer,
700  const RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > &exporter,
701  const RCP<ParameterList> & params) {
702  XPETRA_MONITOR("EpetraCrsMatrixT::expertStaticFillComplete");
703  int rv=0;
704  const Epetra_Import * myimport =0;
705  const Epetra_Export * myexport =0;
706 
707  if(!importer.is_null()) {
708  XPETRA_DYNAMIC_CAST(const EpetraImportT<GlobalOrdinal>, *importer, eImporter, "Xpetra::EpetraCrsMatrixT::expertStaticFillComplete only accepts Xpetra::EpetraImportT.");
709  myimport = eImporter.getEpetra_Import().getRawPtr();
710  }
711  if(!exporter.is_null()) {
712  XPETRA_DYNAMIC_CAST(const EpetraExportT<GlobalOrdinal>, *exporter, eExporter, "Xpetra::EpetraCrsMatrixT::expertStaticFillComplete only accepts Xpetra::EpetraImportT.");
713  myexport = eExporter.getEpetra_Export().getRawPtr();
714  }
715 
716  rv=mtx_->ExpertStaticFillComplete(toEpetra(domainMap), toEpetra(rangeMap), myimport, myexport);
717 
718  TEUCHOS_TEST_FOR_EXCEPTION(rv != 0, std::runtime_error, "Xpetra::EpetraCrsMatrixT::expertStaticFillComplete FAILED!");
719  }
720 
721 #ifndef XPETRA_EPETRA_NO_32BIT_GLOBAL_INDICES
722 template class EpetraCrsMatrixT<int>;
723 #endif
724 
725 #ifndef XPETRA_EPETRA_NO_64BIT_GLOBAL_INDICES
726 template class EpetraCrsMatrixT<long long>;
727 #endif
728 
729 }
size_t getNodeNumDiags() const
Returns the number of local diagonal entries, based on global row/column index comparisons.
void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of local indices in a specified row of the matrix.
bool supportsRowViews() const
Returns true if getLocalRowView() and getGlobalRowView() are valid for this class.
CrsMatrix< double, int, GlobalOrdinal >::scalar_type Scalar
size_t getGlobalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on all nodes.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, LocalGlobal lg=Xpetra::GloballyDistributed, const Teuchos::RCP< Node > &node=defaultArgNode())
Map constructor with Xpetra-defined contiguous uniform distribution.
void insertLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using local IDs.
const Epetra_CrsGraph & toEpetra(const RCP< const CrsGraph< int, GlobalOrdinal > > &graph)
CrsMatrix< double, int, GlobalOrdinal >::local_ordinal_type LocalOrdinal
global_size_t getGlobalNumDiags() const
Returns the number of global diagonal entries, based on global row/column index comparisons.
T & get(const std::string &name, T def_value)
global_size_t getGlobalNumRows() const
Number of global elements in the row map of this matrix.
#define TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(throw_exception_test, Exception, msg)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Xpetra namespace
T * getRawPtr() const
size_type size() const
RCP< Epetra_CrsMatrix > mtx_
Exception throws to report errors in the internal logical of the program.
size_type size() const
const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getColMap() const
Returns the Map that describes the column distribution in this matrix.
void replaceLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using local IDs.
void doExport(const DistObject< char, LocalOrdinal, GlobalOrdinal, Node > &dest, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, CombineMode CM)
Export.
bool isFillComplete() const
Returns true if the matrix is in compute mode, i.e. if fillComplete() has been called.
void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView< const GlobalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of global indices in a specified row of the matrix.
void resize(const size_type n, const T &val=T())
size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const
Returns the current number of entries on this node in the specified local row.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void getGlobalRowCopy(GlobalOrdinal GlobalRow, const ArrayView< GlobalOrdinal > &Indices, const ArrayView< Scalar > &Values, size_t &NumEntries) const
Extract a list of entries in a specified global row of this matrix. Put into pre-allocated storage...
#define XPETRA_ERR_CHECK(arg)
const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRangeMap() const
Returns the Map associated with the range of this operator, which must be compatible with Y...
void allocateAllValues(size_t numNonZeros, ArrayRCP< size_t > &rowptr, ArrayRCP< LocalOrdinal > &colind, ArrayRCP< Scalar > &values)
Allocates and returns ArrayRCPs of the Crs arrays — This is an Xpetra-only routine.
EpetraCrsMatrixT(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rowMap, size_t maxNumEntriesPerRow, ProfileType pftype=DynamicProfile, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Constructor specifying fixed number of entries for each row.
global_size_t getGlobalNumEntries() const
Returns the global number of entries in this matrix.
std::string description() const
A simple one-line description of this object.
global_size_t getGlobalNumCols() const
Number of global columns in the matrix.
size_t getNodeMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
Exception throws when you call an unimplemented method of Xpetra.
T * getRawPtr() const
bool isLocallyIndexed() const
If matrix indices are in the local range, this function returns true. Otherwise, this function return...
void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using global IDs.
#define XPETRA_DYNAMIC_CAST(type, obj, newObj, exceptionMsg)
bool isGloballyIndexed() const
If matrix indices are in the global range, this function returns true. Otherwise, this function retur...
void apply(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Computes the sparse matrix-multivector multiplication.
void fillComplete(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap, const RCP< ParameterList > &params=null)
Signal that data entry is complete, specifying domain and range maps.
size_t getNodeNumEntries() const
Returns the local number of entries in this matrix.
void doImport(const DistObject< char, LocalOrdinal, GlobalOrdinal, Node > &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, CombineMode CM)
Import.
void expertStaticFillComplete(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap, const RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > &importer=Teuchos::null, const RCP< const Export< LocalOrdinal, GlobalOrdinal, Node > > &exporter=Teuchos::null, const RCP< ParameterList > &params=Teuchos::null)
Expert static fill complete.
const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const
Returns the Map that describes the row distribution in this matrix.
void resumeFill(const RCP< ParameterList > &params=null)
Copy
void replaceGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using global IDs.
CombineMode
Xpetra::Combine Mode enumerable type.
#define XPETRA_MONITOR(funcName)
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
bool isFillActive() const
Returns true if the matrix is in edit mode.
iterator end() const
void replaceDomainMapAndImporter(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &newDomainMap, Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > &newImporter)
Replaces the current domainMap and importer with the user-specified objects.
const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getDomainMap() const
Returns the Map associated with the domain of this operator. This will be null until fillComplete() i...
void getAllValues(ArrayRCP< const size_t > &rowptr, ArrayRCP< const LocalOrdinal > &colind, ArrayRCP< const Scalar > &values) const
Gets the 1D pointer arrays of the graph.
size_t getNodeNumRows() const
Returns the number of matrix rows owned on the calling node.
iterator begin() const
void getLocalRowCopy(LocalOrdinal LocalRow, const ArrayView< LocalOrdinal > &Indices, const ArrayView< Scalar > &Values, size_t &NumEntries) const
Extract a list of entries in a specified local row of the matrix. Put into storage allocated by calli...
const RCP< const Comm< int > > getComm() const
Returns the communicator.
void setAllValues(const ArrayRCP< size_t > &rowptr, const ArrayRCP< LocalOrdinal > &colind, const ArrayRCP< Scalar > &values)
Sets the 1D pointer arrays of the graph.
bool is_null() const
ArrayView< T > view(size_type lowerOffset, size_type size) const