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 
53 #include "Xpetra_Map.hpp"
54 #include "Xpetra_MapUtils.hpp"
55 #include "Xpetra_StridedMap.hpp"
56 #include "Xpetra_MapFactory.hpp"
57 #include "Xpetra_MapExtractor.hpp"
59 #include "Xpetra_Matrix.hpp"
60 #include "Xpetra_MatrixFactory.hpp"
62 #include "Xpetra_MatrixMatrix.hpp"
63 
64 namespace Xpetra {
65 
75 template <class Scalar,
76  class LocalOrdinal,
77  class GlobalOrdinal,
78  class Node>
79 class MatrixUtils {
80 #undef XPETRA_MATRIXUTILS_SHORT
81 #include "Xpetra_UseShortNames.hpp"
82 
83 public:
84 
90  RCP<const Map> map = MapUtils::shrinkMapGIDs(*(input.getMap()),*(input.getMap()));
92  for (size_t c = 0; c < input.getNumVectors(); c++) {
94  for (size_t r = 0; r < input.getLocalLength(); r++) {
95  ret->replaceLocalValue(Teuchos::as<LocalOrdinal>(r), c, data[r]);
96  }
97  }
98 
99  return ret;
100  }
101 
105 
106  RCP< const Teuchos::Comm<int> > comm = input.getRowMap()->getComm();
107 
108  // build an overlapping version of mySpecialMap
109  Teuchos::Array<GlobalOrdinal> ovlUnknownStatusGids;
110  Teuchos::Array<GlobalOrdinal> ovlFoundStatusGids;
111 
112  // loop over global column map of A and find all GIDs where it is not sure, whether they are special or not
113  for(size_t i = 0; i<input.getColMap()->getNodeNumElements(); i++) {
114  GlobalOrdinal gcid = input.getColMap()->getGlobalElement(i);
115  if(domainMap.isNodeGlobalElement(gcid) == false) {
116  ovlUnknownStatusGids.push_back(gcid);
117  }
118  }
119 
120  // We need a locally replicated list of all DOF gids of the (non-overlapping) range map of A10
121  // Communicate the number of DOFs on each processor
122  std::vector<int> myUnknownDofGIDs(comm->getSize(),0);
123  std::vector<int> numUnknownDofGIDs(comm->getSize(),0);
124  myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.size();
125  Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myUnknownDofGIDs[0],&numUnknownDofGIDs[0]);
126 
127  // create array containing all DOF GIDs
128  size_t cntUnknownDofGIDs = 0;
129  for(int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
130  std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs,-1); // local version to be filled
131  std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs,-1); // global version after communication
132  // calculate the offset and fill chunk of memory with local data on each processor
133  size_t cntUnknownOffset = 0;
134  for(int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
135  for(size_t k=0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
136  lUnknownDofGIDs[k+cntUnknownOffset] = ovlUnknownStatusGids[k];
137  }
138  if(cntUnknownDofGIDs > 0)
139  Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntUnknownDofGIDs),&lUnknownDofGIDs[0],&gUnknownDofGIDs[0]);
140  std::sort(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end());
141  gUnknownDofGIDs.erase(std::unique(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end()), gUnknownDofGIDs.end());
142 
143  // loop through all GIDs with unknown status
144  for(size_t k=0; k < gUnknownDofGIDs.size(); k++) {
145  GlobalOrdinal curgid = gUnknownDofGIDs[k];
146  if(domainMap.isNodeGlobalElement(curgid)) {
147  ovlFoundStatusGids.push_back(curgid); // curgid is in special map (on this processor)
148  }
149  }
150 
151  std::vector<int> myFoundDofGIDs(comm->getSize(),0);
152  std::vector<int> numFoundDofGIDs(comm->getSize(),0);
153  myFoundDofGIDs[comm->getRank()] = ovlFoundStatusGids.size();
154  Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myFoundDofGIDs[0],&numFoundDofGIDs[0]);
155 
156  // create array containing all DOF GIDs
157  size_t cntFoundDofGIDs = 0;
158  for(int p = 0; p < comm->getSize(); p++) cntFoundDofGIDs += numFoundDofGIDs[p];
159  std::vector<GlobalOrdinal> lFoundDofGIDs(cntFoundDofGIDs,-1); // local version to be filled
160  std::vector<GlobalOrdinal> gFoundDofGIDs(cntFoundDofGIDs,-1); // global version after communication
161  // calculate the offset and fill chunk of memory with local data on each processor
162  size_t cntFoundOffset = 0;
163  for(int p = 0; p < comm->getRank(); p++) cntFoundOffset += numFoundDofGIDs[p];
164  for(size_t k=0; k < Teuchos::as<size_t>(ovlFoundStatusGids.size()); k++) {
165  lFoundDofGIDs[k+cntFoundOffset] = ovlFoundStatusGids[k];
166  }
167  if(cntFoundDofGIDs > 0)
168  Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntFoundDofGIDs),&lFoundDofGIDs[0],&gFoundDofGIDs[0]);
169 
170  Teuchos::Array<GlobalOrdinal> ovlDomainMapArray;
171  for(size_t i = 0; i<input.getColMap()->getNodeNumElements(); i++) {
172  GlobalOrdinal gcid = input.getColMap()->getGlobalElement(i);
173  if(domainMap.isNodeGlobalElement(gcid) == true ||
174  std::find(gFoundDofGIDs.begin(), gFoundDofGIDs.end(), gcid) != gFoundDofGIDs.end()) {
175  ovlDomainMapArray.push_back(gcid);
176  }
177  }
178  RCP<Map> ovlDomainMap = MapFactory::Build (domainMap.lib(),Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(),ovlDomainMapArray(),0,comm);
179  return ovlDomainMap;
180  }
181 
194  Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > columnMapExtractor = Teuchos::null,
195  bool bThyraMode = false) {
200 
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->getNodeNumElements() != input.getRowMap()->getNodeNumElements(), 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->getNodeNumElements() != input.getRangeMap()->getNodeNumElements(), 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->getNodeNumElements() != input.getDomainMap()->getNodeNumElements(), 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]->getNodeNumElements() != rMap->getNodeNumElements(), 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]->getNodeNumElements() != colMap->getNodeNumElements(), Xpetra::Exceptions::Incompatible, "Xpetra::MatrixUtils::Split: Thyra-style column map extractor contains faulty data.")
294  TEUCHOS_TEST_FOR_EXCEPTION(thyDoMapExtractorMaps[c]->getNodeNumElements() != cMap->getNodeNumElements(), 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.getNodeMaxNumRowEntries());
310  else
311  subMatrices[r*numCols+c] = MatrixFactory::Build (rangeMapExtractor->getMap(r),input.getNodeMaxNumRowEntries());
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()->getNodeNumElements(); 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()->getNodeNumElements(); rr++) {
354 
355  // global row id to extract data from global monolithic matrix
356  GlobalOrdinal growid = input.getRowMap()->getGlobalElement(rr); // LID -> GID (column)
357 
358  // Find the block id in range map extractor that belongs to same global row id.
359  // We assume the global ids to be unique in the map extractor
360  // The MapExtractor objects may be constructed using the thyra mode. However, we use
361  // global GID ids (as we have a single input matrix). The only problematic thing could
362  // be that the GIDs of the input matrix are inconsistent with the GIDs in the map extractor.
363  // Note, that for the Thyra mode the GIDs in the map extractor are generated using the ordering
364  // of the blocks.
365  size_t rowBlockId = rangeMapExtractor->getMapIndexForGID(growid);
366 
367  // global row id used for subblocks to insert information
368  GlobalOrdinal subblock_growid = growid; // for Xpetra-style numbering the global row ids are not changing
369  if(bThyraMode == true) {
370  // find local row id associated with growid in the corresponding subblock
371  LocalOrdinal lrowid = rangeMapExtractor->getMap(rowBlockId)->getLocalElement(growid);
372  // translate back local row id to global row id for the subblock
373  subblock_growid = thyRangeMapExtractor->getMap(rowBlockId,true)->getGlobalElement(lrowid);
374  }
375 
376  // extract matrix entries from input matrix
377  // we use global ids since we have to determine the corresponding
378  // block column ids using the global ids anyway
381  input.getLocalRowView(rr, indices, vals);
382 
383  std::vector<Teuchos::Array<GlobalOrdinal> > blockColIdx (numCols, Teuchos::Array<GlobalOrdinal>());
384  std::vector<Teuchos::Array<Scalar> > blockColVals(numCols, Teuchos::Array<Scalar>());
385 
386  for(size_t i=0; i<(size_t)indices.size(); i++) {
387  // gobal column id to extract data from full monolithic matrix
388  GlobalOrdinal gcolid = input.getColMap()->getGlobalElement(indices[i]);
389 
390  size_t colBlockId = myColumnMapExtractor->getMapIndexForGID(gcolid); // old buggy thing
391  //size_t colBlockId = Teuchos::as<size_t>(coCheckData[indices[i]]);
392 
393  // global column id used for subblocks to insert information
394  GlobalOrdinal subblock_gcolid = gcolid; // for Xpetra-style numbering the global col ids are not changing
395  if(bThyraMode == true) {
396  // find local col id associated with gcolid in the corresponding subblock
397  LocalOrdinal lcolid = myColumnMapExtractor->getMap(colBlockId)->getLocalElement(gcolid);
398  // translate back local col id to global col id for the subblock
399  subblock_gcolid = thyColMapExtractor->getMap(colBlockId,true)->getGlobalElement(lcolid);
400  }
401  blockColIdx [colBlockId].push_back(subblock_gcolid);
402  blockColVals[colBlockId].push_back(vals[i]);
403  }
404 
405  for (size_t c = 0; c < numCols; c++) {
406  subMatrices[rowBlockId*numCols+c]->insertGlobalValues(subblock_growid,blockColIdx[c].view(0,blockColIdx[c].size()),blockColVals[c].view(0,blockColVals[c].size()));
407  }
408 
409  }
410 
411  // call fill complete on subblocks and create BlockedCrsOperator
412  RCP<BlockedCrsMatrix> bA = Teuchos::null;
413  if(bThyraMode == true) {
414  for (size_t r = 0; r < numRows; r++) {
415  for (size_t c = 0; c < numCols; c++) {
416  subMatrices[r*numCols+c]->fillComplete(thyDomainMapExtractor->getMap(c,true), thyRangeMapExtractor->getMap(r,true));
417  }
418  }
419  bA = Teuchos::rcp(new BlockedCrsMatrix(thyRangeMapExtractor, thyDomainMapExtractor, 10 /*input.getRowMap()->getNodeMaxNumRowEntries()*/));
420  } else {
421  for (size_t r = 0; r < numRows; r++) {
422  for (size_t c = 0; c < numCols; c++) {
423  subMatrices[r*numCols+c]->fillComplete(domainMapExtractor->getMap(c), rangeMapExtractor->getMap(r));
424  }
425  }
426  bA = Teuchos::rcp(new BlockedCrsMatrix(rangeMapExtractor, domainMapExtractor, 10 /*input.getRowMap()->getNodeMaxNumRowEntries()*/));
427  }
428 
429  for (size_t r = 0; r < numRows; r++) {
430  for (size_t c = 0; c < numCols; c++) {
431  bA->setMatrix(r,c,subMatrices[r*numCols+c]);
432  }
433  }
434  return bA;
435  }
436 
440  bool const &repairZeroDiagonals, Teuchos::FancyOStream &fos)
441  {
442 
444 
446  p->set("DoOptimizeStorage", true);
447 
448  RCP<const Map> rowMap = Ac->getRowMap();
449  RCP<Vector> diagVec = VectorFactory::Build(rowMap);
450  Ac->getLocalDiagCopy(*diagVec);
451 
452  LocalOrdinal lZeroDiags = 0;
453  Teuchos::ArrayRCP< Scalar > diagVal = diagVec->getDataNonConst(0);
454 
455  for (size_t i = 0; i < rowMap->getNodeNumElements(); i++) {
456  if (diagVal[i] == zero) {
457  lZeroDiags++;
458  }
459  }
460  GlobalOrdinal gZeroDiags;
461  Teuchos::reduceAll(*(rowMap->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
462  Teuchos::outArg(gZeroDiags));
463 
464  if (repairZeroDiagonals && gZeroDiags > 0) {
465  /*
466  TAW: If Ac has empty rows, put a 1 on the diagonal of Ac. Be aware that Ac might have empty rows AND
467  columns. The columns might not exist in the column map at all. It would be nice to add the entries
468  to the original matrix Ac. But then we would have to use insertLocalValues. However we cannot add
469  new entries for local column indices that do not exist in the column map of Ac (at least Epetra is
470  not able to do this). With Tpetra it is also not possible to add new entries after the FillComplete
471  call with a static map, since the column map already exists and the diagonal entries are completely
472  missing. Here we build a diagonal matrix with zeros on the diagonal and ones on the diagonal for
473  the rows where Ac has empty rows We have to build a new matrix to be able to use insertGlobalValues.
474  Then we add the original matrix Ac to our new block diagonal matrix and use the result as new
475  (non-singular) matrix Ac. This is very inefficient.
476 
477  If you know something better, please let me know.
478  */
479  RCP<Matrix> fixDiagMatrix = MatrixFactory::Build(rowMap, 1);
481  Teuchos::Array<Scalar> valout(1);
482  for (size_t r = 0; r < rowMap->getNodeNumElements(); r++) {
483  if (diagVal[r] == zero) {
484  GlobalOrdinal grid = rowMap->getGlobalElement(r);
485  indout[0] = grid;
486  valout[0] = one;
487  fixDiagMatrix->insertGlobalValues(grid,indout(), valout());
488  }
489  }
490  {
491  Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer("CheckRepairMainDiagonal: fillComplete1"));
492  fixDiagMatrix->fillComplete(Ac->getDomainMap(),Ac->getRangeMap());
493  }
494 
495  RCP<Matrix> newAc;
496  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*Ac, false, 1.0, *fixDiagMatrix, false, 1.0, newAc, fos);
497  if (Ac->IsView("stridedMaps"))
498  newAc->CreateView("stridedMaps", Ac);
499 
500  Ac = Teuchos::null; // free singular matrix
501  fixDiagMatrix = Teuchos::null;
502  Ac = newAc; // set fixed non-singular matrix
503 
504  // call fillComplete with optimized storage option set to true
505  // This is necessary for new faster Epetra MM kernels.
506  {
507  Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer("CheckRepairMainDiagonal: fillComplete2"));
508  Ac->fillComplete(p);
509  }
510  } // end repair
511 
512 
513 
514  // print some output
515  fos << "CheckRepairMainDiagonal: " << (repairZeroDiagonals ? "repaired " : "found ")
516  << gZeroDiags << " zeros on main diagonal of Ac." << std::endl;
517 
518 #ifdef HAVE_XPETRA_DEBUG // only for debugging
519  // check whether Ac has been repaired...
520  Ac->getLocalDiagCopy(*diagVec);
521  Teuchos::ArrayRCP< Scalar > diagVal2 = diagVec->getDataNonConst(0);
522  for (size_t r = 0; r < Ac->getRowMap()->getNodeNumElements(); r++) {
523  if (diagVal2[r] == zero) {
524  fos << "Error: there are zeros left on diagonal after repair..." << std::endl;
525  break;
526  }
527  }
528 #endif
529  } //CheckRepairMainDiagonal
530 
531 };
532 
533 } // end namespace Xpetra
534 
535 #define XPETRA_MATRIXUTILS_SHORT
536 
537 #endif // PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
Xpetra::MatrixFactory::Build
static RCP< Matrix > Build(const RCP< const Map > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Constructor specifying the number of non-zeros for all rows.
Definition: Xpetra_MatrixFactory.hpp:235
Xpetra::MultiVector::getLocalLength
virtual size_t getLocalLength() const =0
Local number of rows on the calling process.
Xpetra::MatrixMatrix::TwoMatrixAdd
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
Definition: Xpetra_MatrixMatrix.hpp:519
Teuchos::TimeMonitor::getNewTimer
static RCP< Time > getNewTimer(const std::string &name)
Xpetra::MapUtils
Xpetra utility class for common map-related routines.
Definition: Xpetra_MapUtils_fwd.hpp:51
Xpetra
Xpetra namespace
Definition: Xpetra_BlockedCrsMatrix.hpp:86
Xpetra::MapExtractorFactory
Definition: Xpetra_MapExtractorFactory.hpp:61
Xpetra::MultiVectorFactory::Build
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.
Definition: Xpetra_MultiVectorFactory.hpp:90
Teuchos::Array::size
size_type size() const
Xpetra::Matrix::getColMap
virtual const RCP< const Map > & getColMap() const
Returns the Map that describes the column distribution in this matrix. This might be null until fillC...
Definition: Xpetra_Matrix.hpp:330
Xpetra::MultiVector
Definition: Xpetra_MultiVector.hpp:76
Teuchos::ScalarTraits::magnitude
static magnitudeType magnitude(T a)
Teuchos::ScalarTraits::zero
static T zero()
Xpetra::ImportFactory::Build
static RCP< Import< LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &source, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &target)
Constructor specifying the number of non-zeros for all rows.
Definition: Xpetra_ImportFactory.hpp:75
Xpetra_MapExtractorFactory.hpp
Xpetra::Map::isNodeGlobalElement
virtual bool isNodeGlobalElement(GlobalOrdinal globalIndex) const =0
Whether the given global index is valid for this Map on this process.
Teuchos::Array::push_back
void push_back(const value_type &x)
Xpetra::MultiVectorFactory
Definition: Xpetra_MultiVectorFactory.hpp:81
Xpetra_UseShortNames.hpp
Teuchos::rcp
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Xpetra::MultiVector::getNumVectors
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
Xpetra::MultiVector::getData
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
Const view of the local values in a particular vector of this multivector.
Xpetra::Operator::getRangeMap
virtual Teuchos::RCP< const Map > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y....
Xpetra::MatrixUtils::findColumnSubMap
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > findColumnSubMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &domainMap)
Definition: Xpetra_MatrixUtils.hpp:102
Teuchos::ArrayView
Xpetra::Map
Definition: Xpetra_Map.hpp:90
Xpetra::Import
Definition: Xpetra_Import.hpp:62
Teuchos::RCP
Xpetra::MapUtils::shrinkMapGIDs
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.
Definition: Xpetra_MapUtils.hpp:127
Xpetra::MatrixUtils::SplitMatrix
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)
Definition: Xpetra_MatrixUtils.hpp:190
Xpetra_StridedMap.hpp
Xpetra::StridedMap
Class that stores a strided map.
Definition: Xpetra_StridedMap_fwd.hpp:51
Teuchos::Array
Teuchos::ParameterList::set
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Xpetra::MatrixUtils::CheckRepairMainDiagonal
static void CheckRepairMainDiagonal(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &Ac, bool const &repairZeroDiagonals, Teuchos::FancyOStream &fos)
Definition: Xpetra_MatrixUtils.hpp:439
Xpetra::Matrix
Xpetra-specific matrix class.
Definition: Xpetra_Matrix_fwd.hpp:51
Xpetra::Operator::getDomainMap
virtual Teuchos::RCP< const Map > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X....
Xpetra::Vector
Definition: Xpetra_Vector_fwd.hpp:51
Teuchos::ArrayRCP
Teuchos::TimeMonitor
Xpetra::MapFactory::Build
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 > &=Teuchos::null)
Map constructor with Xpetra-defined contiguous uniform distribution.
Definition: Xpetra_MapFactory.hpp:81
Xpetra::Exceptions::RuntimeError
Exception throws to report errors in the internal logical of the program.
Definition: Xpetra_Exceptions.hpp:101
Teuchos::basic_FancyOStream
Teuchos::ScalarTraits::one
static T one()
Teuchos::ArrayView::size
size_type size() const
Xpetra::INSERT
Definition: Xpetra_ConfigDefs.hpp:216
Xpetra::MapExtractorFactory::Build
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)
Constructor specifying the Maps.
Definition: Xpetra_MapExtractorFactory.hpp:75
Xpetra_BlockedCrsMatrix.hpp
Xpetra::BlockedCrsMatrix
Definition: Xpetra_BlockedCrsMatrix.hpp:94
Xpetra::Map::lib
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
Xpetra::ImportFactory
Definition: Xpetra_ImportFactory.hpp:67
Xpetra::DistObject< Scalar, LocalOrdinal, GlobalOrdinal, Node >::getMap
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const=0
The Map describing the parallel distribution of this object.
Teuchos::reduceAll
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
Xpetra_MapUtils.hpp
Xpetra_ConfigDefs.hpp
Xpetra_MatrixFactory.hpp
Xpetra::Exceptions::Incompatible
Exception throws to report incompatible objects (like maps).
Definition: Xpetra_Exceptions.hpp:108
Xpetra::Matrix::getNodeMaxNumRowEntries
virtual size_t getNodeMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
Xpetra::ADD
Definition: Xpetra_ConfigDefs.hpp:215
Xpetra::Matrix::getLocalRowView
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.
Xpetra::Matrix::getRowMap
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
Definition: Xpetra_Matrix.hpp:320
Xpetra::MapUtils::concatenateMaps
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.
Definition: Xpetra_MapUtils.hpp:92
Xpetra::VectorFactory::Build
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
Definition: Xpetra_VectorFactory.hpp:81
Teuchos::OrdinalTraits::invalid
static T invalid()
Xpetra::MapExtractor
Definition: Xpetra_MapExtractor.hpp:78
Xpetra_MapExtractor.hpp
Xpetra_MapFactory.hpp
Teuchos::ParameterList
Xpetra::VectorFactory
Definition: Xpetra_VectorFactory_fwd.hpp:51
Xpetra::MatrixUtils
Xpetra utility class for common matrix-related routines.
Definition: Xpetra_MatrixUtils_fwd.hpp:51
TEUCHOS_TEST_FOR_EXCEPTION
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Xpetra_Matrix.hpp
Xpetra_MatrixMatrix.hpp
Xpetra_Map.hpp
Xpetra::MatrixUtils::xpetraGidNumbering2ThyraGidNumbering
static Teuchos::RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > xpetraGidNumbering2ThyraGidNumbering(const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input)
Definition: Xpetra_MatrixUtils.hpp:85