Xpetra Version of the Day
Loading...
Searching...
No Matches
Xpetra_ReorderedBlockedCrsMatrix.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Xpetra: A linear algebra interface package
4//
5// Copyright 2012 NTESS and the Xpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP
11#define XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP
12
13#include <Tpetra_KokkosCompat_DefaultNode.hpp>
14
15#include "Xpetra_ConfigDefs.hpp"
16#include "Xpetra_Exceptions.hpp"
17
18#include "Xpetra_MapUtils.hpp"
19
20#include "Xpetra_BlockedMultiVector.hpp"
22#include "Xpetra_CrsMatrixWrap.hpp"
23#include "Xpetra_BlockedCrsMatrix.hpp"
24
29namespace Xpetra {
30
31typedef std::string viewLabel_t;
32
33template <class Scalar,
34 class LocalOrdinal,
35 class GlobalOrdinal,
36 class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
37class ReorderedBlockedCrsMatrix : public BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
38 public:
39 typedef Scalar scalar_type;
40 typedef LocalOrdinal local_ordinal_type;
41 typedef GlobalOrdinal global_ordinal_type;
42 typedef Node node_type;
43
44 private:
45#undef XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
47
48 public:
50
51
53
62 size_t npr,
65 : Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>(rangeMaps, domainMaps, npr) {
66 brm_ = brm;
67 fullOp_ = bmat;
68 }
69
70 // protected:
71
74
76
77 private:
79 RCP<const MapExtractor> fullRangeMapExtractor = fullOp_->getRangeMapExtractor();
80
81 // number of sub blocks
82 size_t numBlocks = brm->GetNumBlocks();
83
84 Teuchos::RCP<const Map> map = Teuchos::null;
85
86 if (numBlocks == 0) {
87 // it is a leaf node
88 Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
89
90 // never extract Thyra style maps (since we have to merge them)
91 map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), false);
92 } else {
93 // initialize vector for sub maps
94 std::vector<Teuchos::RCP<const Map>> subMaps(numBlocks, Teuchos::null);
95
96 for (size_t i = 0; i < numBlocks; i++) {
97 Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
98 subMaps[i] = mergeSubBlockMaps(blkMgr);
99 TEUCHOS_ASSERT(subMaps[i].is_null() == false);
100 }
101
102 map = MapUtils::concatenateMaps(subMaps);
103 }
104 TEUCHOS_ASSERT(map.is_null() == false);
105 return map;
106 }
107
108 public:
110
111
113 virtual void apply(const MultiVector& X, MultiVector& Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues,
114 const RCP<Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>>& regionInterfaceImporter,
115 const Teuchos::ArrayRCP<LocalOrdinal>& regionInterfaceLIDs) const {}
117
120 virtual void apply(const MultiVector& X, MultiVector& Y,
122 Scalar alpha = ScalarTraits<Scalar>::one(),
123 Scalar beta = ScalarTraits<Scalar>::zero()) const {
124 // Nested sub-operators should just use the provided X and B vectors
125 if (fullOp_->getLocalNumRows() != this->getLocalNumRows()) {
127 return;
128 }
129
130 // Special handling for the top level of the nested operator
131
132 // check whether input parameters are blocked or not
133 RCP<const MultiVector> refX = rcpFromRef(X);
134 RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
135 RCP<MultiVector> tmpY = rcpFromRef(Y);
136 RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
137
138 bool bCopyResultX = false;
139 bool bCopyResultY = false;
140
141 // TODO create a nested ReorderedBlockedMultiVector out of a nested BlockedMultiVector!
142 // probably not necessary, is it?
143 // check whether X and B are blocked but not ReorderedBlocked operators
144 /*if (refbX != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
145 RCP<const ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<const ReorderedBlockedMultiVector>(refbX);
146 if(rbCheck == Teuchos::null) {
147 RCP<const BlockedMultiVector> bX =
148 Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, refbX));
149 TEUCHOS_ASSERT(bX.is_null()==false);
150 refbX.swap(bX);
151 }
152 }
153 if (tmpbY != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
154 RCP<ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<ReorderedBlockedMultiVector>(tmpbY);
155 if(rbCheck == Teuchos::null) {
156 RCP<BlockedMultiVector> bY =
157 Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbY));
158 TEUCHOS_ASSERT(bY.is_null()==false);
159 tmpbY.swap(bY);
160 }
161 }*/
162
163 // if X and B are not blocked, create a blocked version here and use the blocked vectors
164 // for the internal (nested) apply call.
165
166 // Check whether "this" operator is the reordered variant of the underlying fullOp_.
167 // Note, that nested ReorderedBlockedCrsMatrices always have the same full operator "fullOp_"
168 // stored underneath for being able to "translate" the block ids.
169 if (refbX == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
170 // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
171 RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
172 TEUCHOS_ASSERT(blkRgMap.is_null() == false);
174 TEUCHOS_ASSERT(bXtemp.is_null() == false);
176 Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, bXtemp));
177 TEUCHOS_ASSERT(bX.is_null() == false);
178 refbX.swap(bX);
179 bCopyResultX = true;
180 }
181
182 if (tmpbY == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
183 // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
184 RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
185 TEUCHOS_ASSERT(blkRgMap.is_null() == false);
186 RCP<BlockedMultiVector> tmpbYtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, tmpY));
187 TEUCHOS_ASSERT(tmpbYtemp.is_null() == false);
189 Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbYtemp));
190 TEUCHOS_ASSERT(bY.is_null() == false);
191 tmpbY.swap(bY);
192 bCopyResultY = true;
193 }
194
195 TEUCHOS_ASSERT(refbX.is_null() == false);
196 TEUCHOS_ASSERT(tmpbY.is_null() == false);
197
199
200 if (bCopyResultX == true) {
201 RCP<const MultiVector> Xmerged = refbX->Merge();
202 RCP<MultiVector> nonconstX = Teuchos::rcp_const_cast<MultiVector>(refX);
204 }
205 if (bCopyResultY == true) {
206 RCP<MultiVector> Ymerged = tmpbY->Merge();
208 }
209 }
210
211 // @}
212
214
215
218
221
222 // @}
223
225
226
228 std::string description() const { return "ReorderedBlockedCrsMatrix"; }
229
232 out << "Xpetra::ReorderedBlockedCrsMatrix: " << BlockedCrsMatrix::Rows() << " x " << BlockedCrsMatrix::Cols() << std::endl;
233
235 out << "ReorderedBlockMatrix is fillComplete" << std::endl;
236
237 out << "fullRowMap" << std::endl;
238 BlockedCrsMatrix::getRangeMap(0, false)->describe(out, verbLevel);
239
240 // out << "fullColMap" << std::endl;
241 // fullcolmap_->describe(out,verbLevel);
242
243 } else {
244 out << "Xpetra::ReorderedBlockedCrsMatrix is NOT fillComplete" << std::endl;
245 }
246
247 for (size_t r = 0; r < BlockedCrsMatrix::Rows(); ++r)
248 for (size_t c = 0; c < BlockedCrsMatrix::Cols(); ++c) {
249 out << "Block(" << r << "," << c << ")" << std::endl;
250 BlockedCrsMatrix::getMatrix(r, c)->describe(out, verbLevel);
251 }
252 }
253
255
256 private:
259};
260
261template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
264
265 // TODO distinguish between range and domain map extractor! provide MapExtractor as parameter!
266 RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullRangeMapExtractor = bmat->getRangeMapExtractor();
267
268 // number of sub blocks
269 size_t numBlocks = brm->GetNumBlocks();
270
272
273 if (numBlocks == 0) {
274 // it is a leaf node
275 Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
276
277 map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), bThyraMode);
278 } else {
279 // initialize vector for sub maps
280 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>> subMaps(numBlocks, Teuchos::null);
281
282 for (size_t i = 0; i < numBlocks; i++) {
283 Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
284 subMaps[i] = mergeSubBlockMaps(blkMgr, bmat, bThyraMode);
285 TEUCHOS_ASSERT(subMaps[i].is_null() == false);
286 }
287
288#if 1
289 // concatenate submaps
290 // for Thyra mode this map isn't important
292
293 // create new BlockedMap (either in Thyra Mode or Xpetra mode)
294 map = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(fullMap, subMaps, bThyraMode));
295#else
296 // TAW: 11/27/16 we just concatenate the submaps to one monolithic Map object.
297 // Alternatively, we could create a new BlockedMap using the concatenated map and the submaps
298 // However, the block smoothers only need the concatenated map for creating MultiVectors...
299 // But for the Thyra mode version concatenating would not be ok for the whole map
300 map = MapUtils::concatenateMaps(subMaps);
301#endif
302 }
303 TEUCHOS_ASSERT(map.is_null() == false);
304 return map;
305}
306
307template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
315
316 // number of sub blocks
317 size_t rowSz = rowMgr->GetNumBlocks();
318 size_t colSz = colMgr->GetNumBlocks();
319
320 Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
321
322 if (rowSz == 0 && colSz == 0) {
323 // it is a leaf node
324 Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
325 Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
326
327 // extract leaf node
328 Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
329
330 if (mat == Teuchos::null) return Teuchos::null;
331
332 // check, whether leaf node is of type Xpetra::CrsMatrixWrap
333 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
334 if (matwrap != Teuchos::null) {
335 // If the leaf node is of type Xpetra::CrsMatrixWrap wrap it into a 1x1 ReorderedBlockMatrix
336 // with the corresponding MapExtractors for translating Thyra to Xpetra GIDs if necessary
337 RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
338 Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
339 std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
340 Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
341
342 RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
343 Teuchos::RCP<const Map> submap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
344 std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap2);
345 Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(submap2, colSubMaps, false));
346
347 rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
348 rbmat->setMatrix(0, 0, mat);
349 } else {
350 // If leaf node is already wrapped into a blocked matrix do not wrap it again.
351 rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
352 TEUCHOS_ASSERT(rbmat != Teuchos::null);
353 }
354 TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
355 } else {
356 // create the map extractors
357 // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
358 Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
359 if (rowSz > 0) {
360 std::vector<Teuchos::RCP<const Map>> rowSubMaps(rowSz, Teuchos::null);
361 for (size_t i = 0; i < rowSz; i++) {
362 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
363 rowSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false /*xpetra*/);
364 TEUCHOS_ASSERT(rowSubMaps[i].is_null() == false);
365 }
366 Teuchos::RCP<const Map> rgMergedSubMaps = MapUtils::concatenateMaps(rowSubMaps);
367 rgMapExtractor = Teuchos::rcp(new MapExtractor(rgMergedSubMaps, rowSubMaps, false));
368 } else {
369 Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
370 RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
371 // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
372 // The GIDs might not start with 0 and may not be consecutive!
373 Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
374 std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
375 rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
376 }
377
378 Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
379 if (colSz > 0) {
380 std::vector<Teuchos::RCP<const Map>> colSubMaps(colSz, Teuchos::null);
381 for (size_t j = 0; j < colSz; j++) {
382 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
383 colSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false /*xpetra*/);
384 TEUCHOS_ASSERT(colSubMaps[j].is_null() == false);
385 }
386 Teuchos::RCP<const Map> doMergedSubMaps = MapUtils::concatenateMaps(colSubMaps);
387 doMapExtractor = Teuchos::rcp(new MapExtractor(doMergedSubMaps, colSubMaps, false));
388 } else {
389 Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
390 RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
391 // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
392 // The GIDs might not start with 0 and may not be consecutive!
393 Teuchos::RCP<const Map> submap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
394 std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap);
395 doMapExtractor = Teuchos::rcp(new MapExtractor(submap, colSubMaps, false));
396 }
397
398 rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
399
400 size_t cntNNZ = 0;
401
402 if (rowSz == 0 && colSz > 0) {
403 for (size_t j = 0; j < colSz; j++) {
404 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
405 Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowMgr, colSubMgr, bmat);
406 rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
407 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
408 }
409 } else if (rowSz > 0 && colSz == 0) {
410 for (size_t i = 0; i < rowSz; i++) {
411 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
412 Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colMgr, bmat);
413 rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
414 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
415 }
416 } else {
417 for (size_t i = 0; i < rowSz; i++) {
418 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
419 for (size_t j = 0; j < colSz; j++) {
420 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
421 Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colSubMgr, bmat);
422 rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
423 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
424 }
425 }
426 }
427 TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
428 }
429 rbmat->fillComplete();
430 return rbmat;
431}
432
433// MapExtractor(const std::vector<RCP<const Map> >& maps, const std::vector<RCP<const Map> >& thyramaps);
434
435template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
442
443 TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == true);
444 TEUCHOS_ASSERT(bmat->getDomainMapExtractor()->getThyraMode() == true);
445
446 // number of sub blocks
447 size_t rowSz = rowMgr->GetNumBlocks();
448 size_t colSz = colMgr->GetNumBlocks();
449
450 Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
451
452 if (rowSz == 0 && colSz == 0) {
453 // it is a leaf node
454 Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
455 Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
456
457 // this matrix uses Thyra style GIDs as global row, range, domain and column indices
458 Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
459
460 if (mat == Teuchos::null) return Teuchos::null; // std::cout << "Block " << rowleaf->GetIndex() << "," << colleaf->GetIndex() << " is zero" << std::endl;
461
462 // check, whether leaf node is of type Xpetra::CrsMatrixWrap
463 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
464 if (matwrap != Teuchos::null) {
466 // build map extractors
467 RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
468 // extract Xpetra and Thyra based GIDs
469 Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
470 Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
471 std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
472 std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
473 // use expert constructor
474 Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
475
476 RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
477 // extract Xpetra and Thyra based GIDs
478 Teuchos::RCP<const Map> xpsubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
479 Teuchos::RCP<const Map> tysubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
480 std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap2);
481 std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap2);
482 // use expert constructor
483 Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
484
486 // build reordered block operator
487 rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
488 rbmat->setMatrix(0, 0, mat);
489 } else {
490 // If leaf node is already wrapped into a blocked matrix do not wrap it again.
491 rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
492 TEUCHOS_ASSERT(rbmat != Teuchos::null);
493 }
494 TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
495 } else {
496 // create the map extractors
497 // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
498 Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
499 if (rowSz > 0) {
500 std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(rowSz, Teuchos::null);
501 std::vector<Teuchos::RCP<const Map>> rowTySubMaps(rowSz, Teuchos::null);
502 for (size_t i = 0; i < rowSz; i++) {
503 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
504 // extract Xpetra and Thyra based merged GIDs
505 rowXpSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false);
506 rowTySubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, true);
507 TEUCHOS_ASSERT(rowXpSubMaps[i].is_null() == false);
508 TEUCHOS_ASSERT(rowTySubMaps[i].is_null() == false);
509 }
510 // use expert constructor
511 rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
512 } else {
513 Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
514 RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
515 // extract Xpetra and Thyra based GIDs
516 Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
517 Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
518 std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
519 std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
520 // use expert constructor
521 rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
522 }
523
524 Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
525 if (colSz > 0) {
526 std::vector<Teuchos::RCP<const Map>> colXpSubMaps(colSz, Teuchos::null);
527 std::vector<Teuchos::RCP<const Map>> colTySubMaps(colSz, Teuchos::null);
528 for (size_t j = 0; j < colSz; j++) {
529 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
530 // extract Xpetra and Thyra based merged GIDs
531 colXpSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false);
532 colTySubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, true);
533 TEUCHOS_ASSERT(colXpSubMaps[j].is_null() == false);
534 TEUCHOS_ASSERT(colTySubMaps[j].is_null() == false);
535 }
536 // use expert constructor
537 doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
538 } else {
539 Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
540 RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
541 // extract Xpetra and Thyra based GIDs
542 Teuchos::RCP<const Map> xpsubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
543 Teuchos::RCP<const Map> tysubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
544 std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap);
545 std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap);
546 // use expert constructor
547 doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
548 }
549
550 // TODO matrix should have both rowMgr and colMgr??
551 rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
552
553 size_t cntNNZ = 0;
554
555 if (rowSz == 0 && colSz > 0) {
556 for (size_t j = 0; j < colSz; j++) {
557 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
558 Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowMgr, colSubMgr, bmat);
559 rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
560 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
561 }
562 } else if (rowSz > 0 && colSz == 0) {
563 for (size_t i = 0; i < rowSz; i++) {
564 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
565 Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colMgr, bmat);
566 rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
567 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
568 }
569 } else {
570 for (size_t i = 0; i < rowSz; i++) {
571 Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
572 for (size_t j = 0; j < colSz; j++) {
573 Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
574 Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colSubMgr, bmat);
575 rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
576 if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
577 }
578 }
579 }
580 TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
581 }
582
583 rbmat->fillComplete();
584 return rbmat;
585}
586
587template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
589 TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == bmat->getDomainMapExtractor()->getThyraMode());
591 if (bmat->getRangeMapExtractor()->getThyraMode() == false) {
592 rbmat = mergeSubBlocks(brm, brm, bmat);
593 } else {
594 rbmat = mergeSubBlocksThyra(brm, brm, bmat);
595 }
596
597 // TAW, 6/7/2016: rbmat might be Teuchos::null for empty blocks!
598 return rbmat;
599}
600
601} // namespace Xpetra
602
603#define XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
604#endif /* XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP */
static const EVerbosityLevel verbLevel_default
void swap(RCP< T > &r_ptr)
bool is_null() const
virtual size_t Cols() const
number of column blocks
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode.
virtual size_t Rows() const
number of row blocks
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues, const RCP< Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node > > &regionInterfaceImporter, const Teuchos::ArrayRCP< LocalOrdinal > &regionInterfaceLIDs) const
sparse matrix-multivector multiplication for the region layout matrices (currently no blocked impleme...
Xpetra utility class for common map-related routines.
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.
Xpetra-specific matrix class.
virtual void update(const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta)=0
Update multi-vector values with scaled values of A, this = beta*this + alpha*A.
Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > fullOp_
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues, const RCP< Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node > > &regionInterfaceImporter, const Teuchos::ArrayRCP< LocalOrdinal > &regionInterfaceLIDs) const
sparse matrix-multivector multiplication for the region layout matrices (currently no blocked impleme...
std::string description() const
Return a simple one-line description of this object.
Teuchos::RCP< const Xpetra::BlockReorderManager > brm_
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.
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Computes the sparse matrix-multivector multiplication.
ReorderedBlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMaps, Teuchos::RCP< const MapExtractor > &domainMaps, size_t npr, Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bmat)
Constructor.
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm)
Teuchos::RCP< const Xpetra::BlockReorderManager > getBlockReorderManager()
Returns internal BlockReorderManager object.
Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getBlockedCrsMatrix()
Returns internal unmodified BlockedCrsMatrix object.
#define TEUCHOS_ASSERT(assertion_test)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bmat, bool bThyraMode)
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > buildReorderedBlockedCrsMatrix(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bmat)
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlocks(Teuchos::RCP< const Xpetra::BlockReorderManager > rowMgr, Teuchos::RCP< const Xpetra::BlockReorderManager > colMgr, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bmat)
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlocksThyra(Teuchos::RCP< const Xpetra::BlockReorderManager > rowMgr, Teuchos::RCP< const Xpetra::BlockReorderManager > colMgr, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bmat)
Teuchos::RCP< const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > buildReorderedBlockedMultiVector(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bvec)