Xpetra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Xpetra_MatrixUtils.hpp
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 // Tobias Wiesner (tawiesn@sandia.gov)
43 //
44 // ***********************************************************************
45 //
46 // @HEADER
47 #ifndef PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
48 #define PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
49 
50 #include "Xpetra_ConfigDefs.hpp"
51 
52 #include "Xpetra_Map.hpp"
53 #include "Xpetra_MapUtils.hpp"
54 #include "Xpetra_StridedMap.hpp"
55 #include "Xpetra_MapFactory.hpp"
56 #include "Xpetra_MapExtractor.hpp"
58 #include "Xpetra_Matrix.hpp"
59 #include "Xpetra_MatrixFactory.hpp"
61 #include "Xpetra_MatrixMatrix.hpp"
62 
63 #include "Xpetra_IO.hpp"
64 
65 #ifdef HAVE_XPETRA_TPETRA
66 #include "Xpetra_TpetraMultiVector.hpp"
67 #include <Tpetra_RowMatrixTransposer.hpp>
68 #include <Tpetra_Details_extractBlockDiagonal.hpp>
69 #include <Tpetra_Details_scaleBlockDiagonal.hpp>
70 #endif
71 
72 namespace Xpetra {
73 
83 template <class Scalar,
84  class LocalOrdinal,
85  class GlobalOrdinal,
86  class Node>
87 class MatrixUtils {
88 #undef XPETRA_MATRIXUTILS_SHORT
89 #include "Xpetra_UseShortNames.hpp"
90 
91  public:
92  static Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> xpetraGidNumbering2ThyraGidNumbering(
94  RCP<const Map> map = MapUtils::shrinkMapGIDs(*(input.getMap()), *(input.getMap()));
95  RCP<MultiVector> ret = MultiVectorFactory::Build(map, input.getNumVectors(), true);
96  for (size_t c = 0; c < input.getNumVectors(); c++) {
97  Teuchos::ArrayRCP<const Scalar> data = input.getData(c);
98  for (size_t r = 0; r < input.getLocalLength(); r++) {
99  ret->replaceLocalValue(Teuchos::as<LocalOrdinal>(r), c, data[r]);
100  }
101  }
102 
103  return ret;
104  }
105 
106  static Teuchos::RCP<Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> findColumnSubMap(
109  RCP<const Teuchos::Comm<int>> comm = input.getRowMap()->getComm();
110 
111  // build an overlapping version of mySpecialMap
112  Teuchos::Array<GlobalOrdinal> ovlUnknownStatusGids;
113  Teuchos::Array<GlobalOrdinal> ovlFoundStatusGids;
114 
115  // loop over global column map of A and find all GIDs where it is not sure, whether they are special or not
116  for (size_t i = 0; i < input.getColMap()->getLocalNumElements(); i++) {
117  GlobalOrdinal gcid = input.getColMap()->getGlobalElement(i);
118  if (domainMap.isNodeGlobalElement(gcid) == false) {
119  ovlUnknownStatusGids.push_back(gcid);
120  }
121  }
122 
123  // We need a locally replicated list of all DOF gids of the (non-overlapping) range map of A10
124  // Communicate the number of DOFs on each processor
125  std::vector<int> myUnknownDofGIDs(comm->getSize(), 0);
126  std::vector<int> numUnknownDofGIDs(comm->getSize(), 0);
127  myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.size();
128  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myUnknownDofGIDs[0], &numUnknownDofGIDs[0]);
129 
130  // create array containing all DOF GIDs
131  size_t cntUnknownDofGIDs = 0;
132  for (int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
133  std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs, -1); // local version to be filled
134  std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs, -1); // global version after communication
135  // calculate the offset and fill chunk of memory with local data on each processor
136  size_t cntUnknownOffset = 0;
137  for (int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
138  for (size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
139  lUnknownDofGIDs[k + cntUnknownOffset] = ovlUnknownStatusGids[k];
140  }
141  if (cntUnknownDofGIDs > 0)
142  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lUnknownDofGIDs[0], &gUnknownDofGIDs[0]);
143  std::sort(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end());
144  gUnknownDofGIDs.erase(std::unique(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end()), gUnknownDofGIDs.end());
145 
146  // loop through all GIDs with unknown status
147  for (size_t k = 0; k < gUnknownDofGIDs.size(); k++) {
148  GlobalOrdinal curgid = gUnknownDofGIDs[k];
149  if (domainMap.isNodeGlobalElement(curgid)) {
150  ovlFoundStatusGids.push_back(curgid); // curgid is in special map (on this processor)
151  }
152  }
153 
154  std::vector<int> myFoundDofGIDs(comm->getSize(), 0);
155  std::vector<int> numFoundDofGIDs(comm->getSize(), 0);
156  myFoundDofGIDs[comm->getRank()] = ovlFoundStatusGids.size();
157  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myFoundDofGIDs[0], &numFoundDofGIDs[0]);
158 
159  // create array containing all DOF GIDs
160  size_t cntFoundDofGIDs = 0;
161  for (int p = 0; p < comm->getSize(); p++) cntFoundDofGIDs += numFoundDofGIDs[p];
162  std::vector<GlobalOrdinal> lFoundDofGIDs(cntFoundDofGIDs, -1); // local version to be filled
163  std::vector<GlobalOrdinal> gFoundDofGIDs(cntFoundDofGIDs, -1); // global version after communication
164  // calculate the offset and fill chunk of memory with local data on each processor
165  size_t cntFoundOffset = 0;
166  for (int p = 0; p < comm->getRank(); p++) cntFoundOffset += numFoundDofGIDs[p];
167  for (size_t k = 0; k < Teuchos::as<size_t>(ovlFoundStatusGids.size()); k++) {
168  lFoundDofGIDs[k + cntFoundOffset] = ovlFoundStatusGids[k];
169  }
170  if (cntFoundDofGIDs > 0)
171  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntFoundDofGIDs), &lFoundDofGIDs[0], &gFoundDofGIDs[0]);
172 
173  Teuchos::Array<GlobalOrdinal> ovlDomainMapArray;
174  for (size_t i = 0; i < input.getColMap()->getLocalNumElements(); i++) {
175  GlobalOrdinal gcid = input.getColMap()->getGlobalElement(i);
176  if (domainMap.isNodeGlobalElement(gcid) == true ||
177  std::find(gFoundDofGIDs.begin(), gFoundDofGIDs.end(), gcid) != gFoundDofGIDs.end()) {
178  ovlDomainMapArray.push_back(gcid);
179  }
180  }
181  RCP<Map> ovlDomainMap = MapFactory::Build(domainMap.lib(), Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(), ovlDomainMapArray(), 0, comm);
182  return ovlDomainMap;
183  }
184 
195  static Teuchos::RCP<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> SplitMatrix(
197  Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rangeMapExtractor,
198  Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> domainMapExtractor,
199  Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> columnMapExtractor = Teuchos::null,
200  bool bThyraMode = false) {
201  size_t numRows = rangeMapExtractor->NumMaps();
202  size_t numCols = domainMapExtractor->NumMaps();
203 
204  TEUCHOS_TEST_FOR_EXCEPTION(rangeMapExtractor->getThyraMode() == true, Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor must not use Thyra style numbering of GIDs. The MapExtractor must contain all GIDs of the full range map in order to define a proper splitting.")
205  TEUCHOS_TEST_FOR_EXCEPTION(domainMapExtractor->getThyraMode() == true, Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: DomainMapExtractor must not use Thyra style numbering of GIDs. The MapExtractor must contain all GIDs of the full domain map in order to define a proper splitting.")
206 
207  RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap();
208  RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap();
209 
210  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getMaxAllGlobalIndex() != input.getRowMap()->getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
211  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getGlobalNumElements() != input.getRowMap()->getGlobalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
212  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getLocalNumElements() != input.getRowMap()->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
213  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getMaxAllGlobalIndex() != input.getRangeMap()->getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
214  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getGlobalNumElements() != input.getRangeMap()->getGlobalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
215  TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getLocalNumElements() != input.getRangeMap()->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
216 
217  TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getMaxAllGlobalIndex() != input.getColMap()->getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix. fullDomainMap->getMaxAllGlobalIndex() = " << fullDomainMap->getMaxAllGlobalIndex() << " vs. input.getColMap()->getMaxAllGlobalIndex() = " << input.getColMap()->getMaxAllGlobalIndex())
218  TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getMaxAllGlobalIndex() != input.getDomainMap()->getMaxAllGlobalIndex(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
219  TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getGlobalNumElements() != input.getDomainMap()->getGlobalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
220  TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getLocalNumElements() != input.getDomainMap()->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
221 
222  // check column map extractor
223  Teuchos::RCP<const MapExtractor> myColumnMapExtractor = Teuchos::null;
224  if (columnMapExtractor == Teuchos::null) {
225  TEUCHOS_TEST_FOR_EXCEPTION(domainMapExtractor->getThyraMode() == true, Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: Auto generation of column map extractor not supported for Thyra style numbering.");
226  // This code is always executed, since we always provide map extractors in Xpetra numbering!
227  std::vector<Teuchos::RCP<const Map>> ovlxmaps(numCols, Teuchos::null);
228  for (size_t c = 0; c < numCols; c++) {
229  // TODO: is this routine working correctly?
230  Teuchos::RCP<const Map> colMap = MatrixUtils::findColumnSubMap(input, *(domainMapExtractor->getMap(c)));
231  ovlxmaps[c] = colMap;
232  }
233  RCP<const Map> fullColMap = MapUtils::concatenateMaps(ovlxmaps);
234  // This MapExtractor is always in Xpetra mode!
235  myColumnMapExtractor = MapExtractorFactory::Build(fullColMap, ovlxmaps);
236  } else
237  myColumnMapExtractor = columnMapExtractor; // use user-provided column map extractor.
238 
239  // all above MapExtractors are always in Xpetra mode
240  // build separate ones containing Thyra mode GIDs (if necessary)
241  Teuchos::RCP<const MapExtractor> thyRangeMapExtractor = Teuchos::null;
242  Teuchos::RCP<const MapExtractor> thyDomainMapExtractor = Teuchos::null;
243  Teuchos::RCP<const MapExtractor> thyColMapExtractor = Teuchos::null;
244  if (bThyraMode == true) {
245  // build Thyra-style map extractors
246  std::vector<Teuchos::RCP<const Map>> thyRgMapExtractorMaps(numRows, Teuchos::null);
247  for (size_t r = 0; r < numRows; r++) {
248  RCP<const Map> rMap = rangeMapExtractor->getMap(r);
249  RCP<const Map> shrinkedMap = MapUtils::shrinkMapGIDs(*rMap, *rMap);
250  RCP<const StridedMap> strRangeMap = Teuchos::rcp_dynamic_cast<const StridedMap>(rMap);
251  if (strRangeMap != Teuchos::null) {
252  std::vector<size_t> strInfo = strRangeMap->getStridingData();
253  GlobalOrdinal offset = strRangeMap->getOffset();
254  LocalOrdinal stridedBlockId = strRangeMap->getStridedBlockId();
255  RCP<const StridedMap> strShrinkedMap = Teuchos::rcp(new StridedMap(shrinkedMap, strInfo, shrinkedMap->getIndexBase(), stridedBlockId, offset));
256  thyRgMapExtractorMaps[r] = strShrinkedMap;
257  } else {
258  thyRgMapExtractorMaps[r] = shrinkedMap;
259  }
260  TEUCHOS_TEST_FOR_EXCEPTION(thyRgMapExtractorMaps[r]->getLocalNumElements() != rMap->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: Thyra-style range map extractor contains faulty data.")
261  }
262  RCP<const Map> fullThyRangeMap = MapUtils::concatenateMaps(thyRgMapExtractorMaps);
263  thyRangeMapExtractor = MapExtractorFactory::Build(fullThyRangeMap, thyRgMapExtractorMaps, true);
264  std::vector<Teuchos::RCP<const Map>> thyDoMapExtractorMaps(numCols, Teuchos::null);
265  std::vector<Teuchos::RCP<const Map>> thyColMapExtractorMaps(numCols, Teuchos::null);
266  for (size_t c = 0; c < numCols; c++) {
267  RCP<const Map> cMap = domainMapExtractor->getMap(c);
268 
269  RCP<const Map> shrinkedDomainMap = MapUtils::shrinkMapGIDs(*cMap, *cMap);
270  RCP<const StridedMap> strDomainMap = Teuchos::rcp_dynamic_cast<const StridedMap>(cMap);
271  if (strDomainMap != Teuchos::null) {
272  std::vector<size_t> strInfo = strDomainMap->getStridingData();
273  GlobalOrdinal offset = strDomainMap->getOffset();
274  LocalOrdinal stridedBlockId = strDomainMap->getStridedBlockId();
275  RCP<const StridedMap> strShrinkedDomainMap = Teuchos::rcp(new StridedMap(shrinkedDomainMap, strInfo, shrinkedDomainMap->getIndexBase(), stridedBlockId, offset));
276  thyDoMapExtractorMaps[c] = strShrinkedDomainMap;
277  } else {
278  thyDoMapExtractorMaps[c] = shrinkedDomainMap;
279  }
280  RCP<const Map> colMap = myColumnMapExtractor->getMap(c);
281  RCP<const Map> shrinkedColMap = MapUtils::shrinkMapGIDs(*colMap, *cMap);
282  RCP<const StridedMap> strColMap = Teuchos::rcp_dynamic_cast<const StridedMap>(colMap);
283  if (strColMap != Teuchos::null) {
284  std::vector<size_t> strInfo = strColMap->getStridingData();
285  GlobalOrdinal offset = strColMap->getOffset();
286  LocalOrdinal stridedBlockId = strColMap->getStridedBlockId();
287  RCP<const StridedMap> strShrinkedColMap = Teuchos::rcp(new StridedMap(shrinkedColMap, strInfo, shrinkedColMap->getIndexBase(), stridedBlockId, offset));
288  thyColMapExtractorMaps[c] = strShrinkedColMap;
289  } else {
290  thyColMapExtractorMaps[c] = shrinkedColMap;
291  }
292 
293  TEUCHOS_TEST_FOR_EXCEPTION(thyColMapExtractorMaps[c]->getLocalNumElements() != colMap->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: Thyra-style column map extractor contains faulty data.")
294  TEUCHOS_TEST_FOR_EXCEPTION(thyDoMapExtractorMaps[c]->getLocalNumElements() != cMap->getLocalNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: Thyra-style domain map extractor contains faulty data.")
295  }
296  RCP<const Map> fullThyDomainMap = MapUtils::concatenateMaps(thyDoMapExtractorMaps);
297  RCP<const Map> fullThyColumnMap = MapUtils::concatenateMaps(thyColMapExtractorMaps);
298  thyDomainMapExtractor = MapExtractorFactory::Build(fullThyDomainMap, thyDoMapExtractorMaps, true);
299  thyColMapExtractor = MapExtractorFactory::Build(fullThyColumnMap, thyColMapExtractorMaps, true);
300  }
301  // create submatrices
302  std::vector<Teuchos::RCP<Matrix>> subMatrices(numRows * numCols, Teuchos::null);
303  for (size_t r = 0; r < numRows; r++) {
304  for (size_t c = 0; c < numCols; c++) {
305  // create empty CrsMatrix objects
306  // make sure that the submatrices are defined using the right row maps (either Thyra or xpetra style)
307  // Note: we're reserving a little bit too much memory for the submatrices, but should be still reasonable
308  if (bThyraMode == true)
309  subMatrices[r * numCols + c] = MatrixFactory::Build(thyRangeMapExtractor->getMap(r, true), input.getLocalMaxNumRowEntries());
310  else
311  subMatrices[r * numCols + c] = MatrixFactory::Build(rangeMapExtractor->getMap(r), input.getLocalMaxNumRowEntries());
312  }
313  }
314 
315  // We need a vector which lives on the column map of input and stores the block id that the column belongs to.
316  // create a vector on the domain map. Loop over it and fill in the corresponding block id numbers
317  // create a vector on the column map and import the data
318  // Importer: source map is non-overlapping. Target map is overlapping
319  // call colMap.Import(domMap,Importer,Insert)
320  // do the same with "Add" to make sure only one processor is responsible for the different GIDs!
321 #if 0 // TAW needs to be fixed (does not compile for Scalar=complex)
326 
327  RCP<Vector> doCheck = VectorFactory::Build(input.getDomainMap(), true);
328  doCheck->putScalar(1.0);
329  RCP<Vector> coCheck = VectorFactory::Build(input.getColMap(), true);
330  RCP<Import> imp = ImportFactory::Build(input.getDomainMap(), input.getColMap());
331  coCheck->doImport(*doCheck, *imp, Xpetra::ADD);
332  TEUCHOS_TEST_FOR_EXCEPTION(coCheck->normInf() != Teuchos::ScalarTraits< Scalar >::magnitude(1.0), Xpetra::Exceptions::RuntimeError, "Xpetra::MatrixUtils::SplitMatrix: error when distributing data.");
333 
334  doCheck->putScalar(-1.0);
335  coCheck->putScalar(-1.0);
336 
337  Teuchos::ArrayRCP< Scalar > doCheckData = doCheck->getDataNonConst(0);
338  for (size_t rrr = 0; rrr < input.getDomainMap()->getLocalNumElements(); rrr++) {
339  // global row id to extract data from global monolithic matrix
340  GlobalOrdinal id = input.getDomainMap()->getGlobalElement(rrr); // LID -> GID (column)
341 
342  // Find the block id in range map extractor that belongs to same global id.
343  size_t BlockId = domainMapExtractor->getMapIndexForGID(id);
344 
345  doCheckData[rrr] = Teuchos::as<Scalar>(BlockId);
346  }
347 
348  coCheck->doImport(*doCheck, *imp, Xpetra::INSERT);
349 
350  Teuchos::ArrayRCP< Scalar > coCheckData = coCheck->getDataNonConst(0);
351 #endif
352  // loop over all rows of input matrix
353  for (size_t rr = 0; rr < input.getRowMap()->getLocalNumElements(); rr++) {
354  // global row id to extract data from global monolithic matrix
355  GlobalOrdinal growid = input.getRowMap()->getGlobalElement(rr); // LID -> GID (column)
356 
357  // Find the block id in range map extractor that belongs to same global row id.
358  // We assume the global ids to be unique in the map extractor
359  // The MapExtractor objects may be constructed using the thyra mode. However, we use
360  // global GID ids (as we have a single input matrix). The only problematic thing could
361  // be that the GIDs of the input matrix are inconsistent with the GIDs in the map extractor.
362  // Note, that for the Thyra mode the GIDs in the map extractor are generated using the ordering
363  // of the blocks.
364  size_t rowBlockId = rangeMapExtractor->getMapIndexForGID(growid);
365 
366  // global row id used for subblocks to insert information
367  GlobalOrdinal subblock_growid = growid; // for Xpetra-style numbering the global row ids are not changing
368  if (bThyraMode == true) {
369  // find local row id associated with growid in the corresponding subblock
370  LocalOrdinal lrowid = rangeMapExtractor->getMap(rowBlockId)->getLocalElement(growid);
371  // translate back local row id to global row id for the subblock
372  subblock_growid = thyRangeMapExtractor->getMap(rowBlockId, true)->getGlobalElement(lrowid);
373  }
374 
375  // extract matrix entries from input matrix
376  // we use global ids since we have to determine the corresponding
377  // block column ids using the global ids anyway
378  Teuchos::ArrayView<const LocalOrdinal> indices;
379  Teuchos::ArrayView<const Scalar> vals;
380  input.getLocalRowView(rr, indices, vals);
381 
382  std::vector<Teuchos::Array<GlobalOrdinal>> blockColIdx(numCols, Teuchos::Array<GlobalOrdinal>());
383  std::vector<Teuchos::Array<Scalar>> blockColVals(numCols, Teuchos::Array<Scalar>());
384 
385  for (size_t i = 0; i < (size_t)indices.size(); i++) {
386  // gobal column id to extract data from full monolithic matrix
387  GlobalOrdinal gcolid = input.getColMap()->getGlobalElement(indices[i]);
388 
389  size_t colBlockId = myColumnMapExtractor->getMapIndexForGID(gcolid); // old buggy thing
390  // size_t colBlockId = Teuchos::as<size_t>(coCheckData[indices[i]]);
391 
392  // global column id used for subblocks to insert information
393  GlobalOrdinal subblock_gcolid = gcolid; // for Xpetra-style numbering the global col ids are not changing
394  if (bThyraMode == true) {
395  // find local col id associated with gcolid in the corresponding subblock
396  LocalOrdinal lcolid = myColumnMapExtractor->getMap(colBlockId)->getLocalElement(gcolid);
397  // translate back local col id to global col id for the subblock
398  subblock_gcolid = thyColMapExtractor->getMap(colBlockId, true)->getGlobalElement(lcolid);
399  }
400  blockColIdx[colBlockId].push_back(subblock_gcolid);
401  blockColVals[colBlockId].push_back(vals[i]);
402  }
403 
404  for (size_t c = 0; c < numCols; c++) {
405  subMatrices[rowBlockId * numCols + c]->insertGlobalValues(subblock_growid, blockColIdx[c].view(0, blockColIdx[c].size()), blockColVals[c].view(0, blockColVals[c].size()));
406  }
407  }
408 
409  // call fill complete on subblocks and create BlockedCrsOperator
410  RCP<BlockedCrsMatrix> bA = Teuchos::null;
411  if (bThyraMode == true) {
412  for (size_t r = 0; r < numRows; r++) {
413  for (size_t c = 0; c < numCols; c++) {
414  subMatrices[r * numCols + c]->fillComplete(thyDomainMapExtractor->getMap(c, true), thyRangeMapExtractor->getMap(r, true));
415  }
416  }
417  bA = Teuchos::rcp(new BlockedCrsMatrix(thyRangeMapExtractor, thyDomainMapExtractor, 10 /*input.getRowMap()->getLocalMaxNumRowEntries()*/));
418  } else {
419  for (size_t r = 0; r < numRows; r++) {
420  for (size_t c = 0; c < numCols; c++) {
421  subMatrices[r * numCols + c]->fillComplete(domainMapExtractor->getMap(c), rangeMapExtractor->getMap(r));
422  }
423  }
424  bA = Teuchos::rcp(new BlockedCrsMatrix(rangeMapExtractor, domainMapExtractor, 10 /*input.getRowMap()->getLocalMaxNumRowEntries()*/));
425  }
426 
427  for (size_t r = 0; r < numRows; r++) {
428  for (size_t c = 0; c < numCols; c++) {
429  bA->setMatrix(r, c, subMatrices[r * numCols + c]);
430  }
431  }
432  return bA;
433  } // SplitMatrix
434 
438  bool const& repairZeroDiagonals, Teuchos::FancyOStream& fos,
439  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType threshold = Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::zero(),
440  const Scalar replacementValue = Teuchos::ScalarTraits<Scalar>::one()) {
441  using TST = typename Teuchos::ScalarTraits<Scalar>;
442  using Teuchos::rcp_dynamic_cast;
443 
444  GlobalOrdinal gZeroDiags;
445  bool usedEfficientPath = false;
446 
447 #ifdef HAVE_MUELU_TPETRA
448  RCP<CrsMatrixWrap> crsWrapAc = rcp_dynamic_cast<CrsMatrixWrap>(Ac);
449  RCP<TpetraCrsMatrix> tpCrsAc;
450  if (!crsWrapAc.is_null())
451  tpCrsAc = rcp_dynamic_cast<TpetraCrsMatrix>(crsWrapAc->getCrsMatrix());
452 
453  if (!tpCrsAc.is_null()) {
454  auto tpCrsGraph = tpCrsAc->getTpetra_CrsMatrix()->getCrsGraph();
455  size_t numRows = Ac->getRowMap()->getLocalNumElements();
456  typedef typename Tpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::offset_device_view_type offset_type;
457  using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
458  auto offsets = offset_type(Kokkos::ViewAllocateWithoutInitializing("offsets"), numRows);
459  tpCrsGraph->getLocalDiagOffsets(offsets);
460 
461  const size_t STINV =
462  Tpetra::Details::OrdinalTraits<typename offset_type::value_type>::invalid();
463 
464  if (repairZeroDiagonals) {
465  // Make sure that the matrix has all its diagonal entries, so
466  // we can fix them in-place.
467 
468  LO numMissingDiagonalEntries = 0;
469 
470  Kokkos::parallel_reduce(
471  "countMissingDiagonalEntries",
472  range_type(0, numRows),
473  KOKKOS_LAMBDA(const LO i, LO& missing) {
474  missing += (offsets(i) == STINV);
475  },
476  numMissingDiagonalEntries);
477 
478  GlobalOrdinal gNumMissingDiagonalEntries;
479  Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(numMissingDiagonalEntries),
480  Teuchos::outArg(gNumMissingDiagonalEntries));
481 
482  if (gNumMissingDiagonalEntries == 0) {
483  // Matrix has all diagonal entries, now we fix them
484 
485  auto lclA = tpCrsAc->getTpetra_CrsMatrix()->getLocalMatrixDevice();
486 
487  using ATS = Kokkos::ArithTraits<Scalar>;
488  using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
489 
490  LO lZeroDiags = 0;
491  typename ATS::val_type impl_replacementValue = replacementValue;
492 
493  Kokkos::parallel_reduce(
494  "fixSmallDiagonalEntries",
495  range_type(0, numRows),
496  KOKKOS_LAMBDA(const LO i, LO& fixed) {
497  const auto offset = offsets(i);
498  auto curRow = lclA.row(i);
499  if (impl_ATS::magnitude(curRow.value(offset)) <= threshold) {
500  curRow.value(offset) = impl_replacementValue;
501  fixed += 1;
502  }
503  },
504  lZeroDiags);
505 
506  Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
507  Teuchos::outArg(gZeroDiags));
508 
509  usedEfficientPath = true;
510  }
511  } else {
512  // We only want to count up small diagonal entries, but not
513  // fix them. So missing diagonal entries are not an issue.
514 
515  auto lclA = tpCrsAc->getTpetra_CrsMatrix()->getLocalMatrixDevice();
516 
517  using ATS = Kokkos::ArithTraits<Scalar>;
518  using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
519 
520  LO lZeroDiags = 0;
521 
522  Kokkos::parallel_reduce(
523  "detectSmallDiagonalEntries",
524  range_type(0, numRows),
525  KOKKOS_LAMBDA(const LO i, LO& small) {
526  const auto offset = offsets(i);
527  if (offset == STINV)
528  small += 1;
529  else {
530  auto curRow = lclA.row(i);
531  if (impl_ATS::magnitude(curRow.value(offset)) <= threshold) {
532  small += 1;
533  }
534  }
535  },
536  lZeroDiags);
537 
538  Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
539  Teuchos::outArg(gZeroDiags));
540 
541  usedEfficientPath = true;
542  }
543  }
544 #endif
545 
546  if (!usedEfficientPath) {
547  RCP<const Map> rowMap = Ac->getRowMap();
548  RCP<Vector> diagVec = VectorFactory::Build(rowMap);
549  Ac->getLocalDiagCopy(*diagVec);
550 
551  LocalOrdinal lZeroDiags = 0;
552  Teuchos::ArrayRCP<const Scalar> diagVal = diagVec->getData(0);
553 
554  for (size_t i = 0; i < rowMap->getLocalNumElements(); i++) {
555  if (TST::magnitude(diagVal[i]) <= threshold) {
556  lZeroDiags++;
557  }
558  }
559 
560  Teuchos::reduceAll(*(rowMap->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
561  Teuchos::outArg(gZeroDiags));
562 
563  if (repairZeroDiagonals && gZeroDiags > 0) {
564  /*
565  TAW: If Ac has empty rows, put a 1 on the diagonal of Ac. Be aware that Ac might have empty rows AND
566  columns. The columns might not exist in the column map at all. It would be nice to add the entries
567  to the original matrix Ac. But then we would have to use insertLocalValues. However we cannot add
568  new entries for local column indices that do not exist in the column map of Ac (at least Epetra is
569  not able to do this). With Tpetra it is also not possible to add new entries after the FillComplete
570  call with a static map, since the column map already exists and the diagonal entries are completely
571  missing. Here we build a diagonal matrix with zeros on the diagonal and ones on the diagonal for
572  the rows where Ac has empty rows We have to build a new matrix to be able to use insertGlobalValues.
573  Then we add the original matrix Ac to our new block diagonal matrix and use the result as new
574  (non-singular) matrix Ac. This is very inefficient.
575 
576  If you know something better, please let me know.
577  */
578  RCP<Matrix> fixDiagMatrix = MatrixFactory::Build(rowMap, 1);
579  Teuchos::Array<GlobalOrdinal> indout(1);
580  Teuchos::Array<Scalar> valout(1);
581  for (size_t r = 0; r < rowMap->getLocalNumElements(); r++) {
582  if (TST::magnitude(diagVal[r]) <= threshold) {
583  GlobalOrdinal grid = rowMap->getGlobalElement(r);
584  indout[0] = grid;
585  valout[0] = replacementValue;
586  fixDiagMatrix->insertGlobalValues(grid, indout(), valout());
587  }
588  }
589  {
590  Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer("CheckRepairMainDiagonal: fillComplete1"));
591  fixDiagMatrix->fillComplete(Ac->getDomainMap(), Ac->getRangeMap());
592  }
593 
594  RCP<Matrix> newAc;
595  Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*Ac, false, 1.0, *fixDiagMatrix, false, 1.0, newAc, fos);
596  if (Ac->IsView("stridedMaps"))
597  newAc->CreateView("stridedMaps", Ac);
598 
599  Ac = Teuchos::null; // free singular matrix
600  fixDiagMatrix = Teuchos::null;
601  Ac = newAc; // set fixed non-singular matrix
602 
603  // call fillComplete with optimized storage option set to true
604  // This is necessary for new faster Epetra MM kernels.
605  Teuchos::RCP<Teuchos::ParameterList> p = Teuchos::rcp(new Teuchos::ParameterList());
606  p->set("DoOptimizeStorage", true);
607  {
608  Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer("CheckRepairMainDiagonal: fillComplete2"));
609  Ac->fillComplete(p);
610  }
611  } // end repair
612  }
613 
614  // print some output
615  fos << "CheckRepairMainDiagonal: " << (repairZeroDiagonals ? "repaired " : "found ")
616  << gZeroDiags << " too small entries (threshold = " << threshold << ") on main diagonal of Ac." << std::endl;
617 
618 #ifdef HAVE_XPETRA_DEBUG // only for debugging
619  {
620  // check whether Ac has been repaired...
621  RCP<const Map> rowMap = Ac->getRowMap();
622  RCP<Vector> diagVec = VectorFactory::Build(rowMap);
623  Teuchos::ArrayRCP<const Scalar> diagVal;
624  Ac->getLocalDiagCopy(*diagVec);
625  diagVal = diagVec->getData(0);
626  for (size_t r = 0; r < Ac->getRowMap()->getLocalNumElements(); r++) {
627  if (TST::magnitude(diagVal[r]) <= threshold) {
628  fos << "Error: there are too small entries left on diagonal after repair..." << std::endl;
629  break;
630  }
631  }
632  }
633 #endif
634  } // CheckRepairMainDiagonal
635 
643  const Teuchos::ArrayView<const double>& relativeThreshold, Teuchos::FancyOStream& fos) {
644  Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer("RelativeDiagonalBoost"));
645 
646  TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() != relativeThreshold.size() && relativeThreshold.size() != 1, Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::RelativeDiagonal Boost: Either A->GetFixedBlockSize() != relativeThreshold.size() OR relativeThreshold.size() == 1");
647 
648  LocalOrdinal numPDEs = A->GetFixedBlockSize();
649  typedef typename Teuchos::ScalarTraits<Scalar> TST;
650  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
651  Scalar zero = TST::zero();
652  Scalar one = TST::one();
653 
654  // Get the diagonal
655  RCP<Vector> diag = VectorFactory::Build(A->getRowMap());
656  A->getLocalDiagCopy(*diag);
657  Teuchos::ArrayRCP<const Scalar> dataVal = diag->getData(0);
658  size_t N = A->getRowMap()->getLocalNumElements();
659 
660  // Compute the diagonal maxes for each PDE
661  std::vector<MT> l_diagMax(numPDEs), g_diagMax(numPDEs);
662  for (size_t i = 0; i < N; i++) {
663  int pde = (int)(i % numPDEs);
664  if ((int)i < numPDEs)
665  l_diagMax[pde] = TST::magnitude(dataVal[i]);
666  else
667  l_diagMax[pde] = std::max(l_diagMax[pde], TST::magnitude(dataVal[i]));
668  }
669  Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_MAX, numPDEs, l_diagMax.data(), g_diagMax.data());
670 
671  // Apply the diagonal maxes via matrix-matrix addition
672  RCP<Matrix> boostMatrix = MatrixFactory::Build(A->getRowMap(), 1);
673  Teuchos::Array<GlobalOrdinal> index(1);
674  Teuchos::Array<Scalar> value(1);
675  for (size_t i = 0; i < N; i++) {
676  GlobalOrdinal GRID = A->getRowMap()->getGlobalElement(i);
677  int pde = (int)(i % numPDEs);
678  index[0] = GRID;
679  if (TST::magnitude(dataVal[i]) < relativeThreshold[pde] * g_diagMax[pde])
680  value[0] = relativeThreshold[pde] * g_diagMax[pde] - TST::magnitude(dataVal[i]);
681  else
682  value[0] = zero;
683  boostMatrix->insertGlobalValues(GRID, index(), value());
684  }
685  boostMatrix->fillComplete(A->getDomainMap(), A->getRangeMap());
686 
687  // FIXME: We really need an add that lets you "add into"
688  RCP<Matrix> newA;
689  Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A, false, one, *boostMatrix, false, one, newA, fos);
690  if (A->IsView("stridedMaps"))
691  newA->CreateView("stridedMaps", A);
692  A = newA;
693  A->fillComplete();
694  }
695 
696  // Extracting the block diagonal of a matrix
699  const UnderlyingLib lib = A.getRowMap()->lib();
700 
701  if (lib == Xpetra::UseEpetra) {
702 #if defined(HAVE_XPETRA_EPETRA)
703  throw(Xpetra::Exceptions::RuntimeError("Xpetra::MatrixUtils::extractBlockDiagonal not available for Epetra."));
704 #endif // HAVE_XPETRA_EPETRA
705  } else if (lib == Xpetra::UseTpetra) {
706 #ifdef HAVE_XPETRA_TPETRA
707  const Tpetra::CrsMatrix<SC, LO, GO, NO>& At = Xpetra::Helpers<SC, LO, GO, NO>::Op2TpetraCrs(A);
708  Tpetra::MultiVector<SC, LO, GO, NO>& Dt = Xpetra::toTpetra(diagonal);
709  Tpetra::Details::extractBlockDiagonal(At, Dt);
710 #endif // HAVE_XPETRA_TPETRA
711  }
712  }
713 
714  // Inverse scaling by a block-diagonal matrix
716  bool doTranspose,
718  const UnderlyingLib lib = blockDiagonal.getMap()->lib();
719 
720  if (lib == Xpetra::UseEpetra) {
721 #if defined(HAVE_XPETRA_EPETRA)
722  throw(Xpetra::Exceptions::RuntimeError("Xpetra::MatrixUtils::inverseScaleBlockDiagonal not available for Epetra."));
723 #endif // HAVE_XPETRA_EPETRA
724  } else if (lib == Xpetra::UseTpetra) {
725 #ifdef HAVE_XPETRA_TPETRA
726  Tpetra::MultiVector<SC, LO, GO, NO>& Dt = Xpetra::toTpetra(blockDiagonal);
727  Tpetra::MultiVector<SC, LO, GO, NO>& St = Xpetra::toTpetra(toBeScaled);
728  Tpetra::Details::inverseScaleBlockDiagonal(Dt, doTranspose, St);
729 #endif // HAVE_XPETRA_TPETRA
730  }
731  }
732 
734  RCP<const Map> rowMap = A.getRowMap();
735  RCP<const Map> colMap = A.getColMap();
736  bool fail = false;
737  if (rowMap->lib() == Xpetra::UseTpetra) {
738  auto tpRowMap = Teuchos::rcp_dynamic_cast<const TpetraMap>(rowMap, true)->getTpetra_Map();
739  auto tpColMap = Teuchos::rcp_dynamic_cast<const TpetraMap>(colMap, true)->getTpetra_Map();
740  fail = !tpColMap->isLocallyFitted(*tpRowMap);
741  } else {
742  RCP<const Teuchos::Comm<int>> comm = rowMap->getComm();
743  LO numRows = Teuchos::as<LocalOrdinal>(rowMap->getLocalNumElements());
744 
745  for (LO rowLID = 0; rowLID < numRows; rowLID++) {
746  GO rowGID = rowMap->getGlobalElement(rowLID);
747  LO colGID = colMap->getGlobalElement(rowLID);
748  if (rowGID != colGID) {
749  fail = true;
750  std::cerr << "On rank " << comm->getRank() << ", LID " << rowLID << " is GID " << rowGID << " in the rowmap, but GID " << colGID << " in the column map.\n";
751  }
752  }
753  }
754  TEUCHOS_TEST_FOR_EXCEPTION(fail, Exceptions::RuntimeError,
755  "Local parts of row and column map do not match!");
756  }
757 
767  std::vector<size_t>& rangeStridingInfo, std::vector<size_t>& domainStridingInfo) {
768  RCP<const StridedMap> stridedRowMap = StridedMapFactory::Build(matrix->getRowMap(), rangeStridingInfo, -1, 0);
769  RCP<const StridedMap> stridedColMap = StridedMapFactory::Build(matrix->getColMap(), domainStridingInfo, -1, 0);
770 
771  if (matrix->IsView("stridedMaps") == true) matrix->RemoveView("stridedMaps");
772  matrix->CreateView("stridedMaps", stridedRowMap, stridedColMap);
773  }
774 };
775 
776 } // end namespace Xpetra
777 
778 #define XPETRA_MATRIXUTILS_SHORT
779 
780 #endif // PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > findColumnSubMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &domainMap)
static void checkLocalRowMapMatchesColMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
static void inverseScaleBlockDiagonal(Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &blockDiagonal, bool doTranspose, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &toBeScaled)
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
static Teuchos::RCP< Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > SplitMatrix(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> rangeMapExtractor, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> domainMapExtractor, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> columnMapExtractor=Teuchos::null, bool bThyraMode=false)
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
static Teuchos::RCP< Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map > &fullmap, const std::vector< Teuchos::RCP< const Map >> &maps, bool bThyraMode=false)
Build MapExtrasctor from a given set of partial maps.
static Teuchos::RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node >> &map, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
Exception throws to report errors in the internal logical of the program.
static Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > concatenateMaps(const std::vector< Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > > &subMaps)
Helper function to concatenate several maps.
virtual const RCP< const Map > & getColMap() const
Returns the Map that describes the column distribution in this matrix. This might be null until fillC...
virtual bool isNodeGlobalElement(GlobalOrdinal globalIndex) const =0
Whether the given global index is valid for this Map on this process.
static void convertMatrixToStridedMaps(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> matrix, std::vector< size_t > &rangeStridingInfo, std::vector< size_t > &domainStridingInfo)
virtual void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const =0
Extract a const, non-persisting view of local indices in a specified row of the matrix.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
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)
Map constructor with Xpetra-defined contiguous uniform distribution.
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
Const view of the local values in a particular vector of this multivector.
static void RelativeDiagonalBoost(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const Teuchos::ArrayView< const double > &relativeThreshold, Teuchos::FancyOStream &fos)
RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > toTpetra(const RCP< const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &graph)
virtual const Teuchos::RCP< const map_type > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
virtual size_t getLocalLength() const =0
Local number of rows on the calling process.
RCP< const CrsGraph > getCrsGraph() const
Returns the CrsGraph associated with this matrix.
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > shrinkMapGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput)
Helper function to shrink the GIDs and generate a standard map whith GIDs starting at 0...
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
static Teuchos::RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > xpetraGidNumbering2ThyraGidNumbering(const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input)
std::vector< size_t > getStridingData() const
Exception throws to report incompatible objects (like maps).
static void extractBlockDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &diagonal)
Concrete implementation of Xpetra::Matrix.
virtual const Teuchos::RCP< const map_type > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
virtual size_t getLocalMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
static RCP< Xpetra::StridedMap< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, std::vector< size_t > &stridingInfo, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalOrdinal stridedBlockId=-1, GlobalOrdinal offset=0, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
static void CheckRepairMainDiagonal(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &Ac, bool const &repairZeroDiagonals, Teuchos::FancyOStream &fos, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType threshold=Teuchos::ScalarTraits< typename Teuchos::ScalarTraits< Scalar >::magnitudeType >::zero(), const Scalar replacementValue=Teuchos::ScalarTraits< Scalar >::one())
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
static RCP< Import< LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &source, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &target, const Teuchos::RCP< Teuchos::ParameterList > &plist=Teuchos::null)
Constructor specifying the number of non-zeros for all rows.
Xpetra-specific matrix class.
Class that stores a strided map.