Xpetra_MapExtractor.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 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef XPETRA_MAPEXTRACTOR_HPP_
47 #define XPETRA_MAPEXTRACTOR_HPP_
48 
49 #include <map>
50 
51 #include <iostream>
52 
53 #include <Teuchos_RCP.hpp>
54 #include <Teuchos_Describable.hpp>
55 #include <Xpetra_Import.hpp>
56 #include <Xpetra_Map.hpp>
57 
58 #include <Xpetra_Import.hpp>
59 #include <Xpetra_ImportFactory.hpp>
60 #include <Xpetra_MapFactory.hpp>
61 #include <Xpetra_MapUtils.hpp>
62 #include <Xpetra_MultiVector.hpp>
64 #include <Xpetra_Vector.hpp>
65 #include <Xpetra_VectorFactory.hpp>
66 
67 namespace Xpetra {
68 
69 #ifndef DOXYGEN_SHOULD_SKIP_THIS
70  // forward declaration of BlockedMultiVector, needed to prevent circular inclusions
71  template<class S, class LO, class GO, class N> class BlockedMultiVector;
72 #endif
73 
74  template <class Scalar,
75  class LocalOrdinal,
76  class GlobalOrdinal,
77  class Node>
78  class MapExtractor : public Teuchos::Describable {
79  public:
80  typedef Scalar scalar_type;
81  typedef LocalOrdinal local_ordinal_type;
82  typedef GlobalOrdinal global_ordinal_type;
83  typedef Node node_type;
84 
85  private:
86 #undef XPETRA_MAPEXTRACTOR_SHORT
87 #include "Xpetra_UseShortNames.hpp"
88 
89  public:
90 
103  MapExtractor(const RCP<const Map>& fullmap, const std::vector<RCP<const Map> >& maps, bool bThyraMode = false) {
104  bThyraMode_ = bThyraMode;
105 
106  if(bThyraMode == false) {
107  // use Xpetra-style numbering for sub-block maps
108  // That is, all sub-block maps have unique GIDs which may not be contiguous and start with GIDs different than zero.
109 
110  // plausibility check
111  size_t numAllElements = 0;
112  for(size_t v = 0; v < maps.size(); ++v) {
113  numAllElements += maps[v]->getGlobalNumElements();
114  }
115  TEUCHOS_TEST_FOR_EXCEPTION(fullmap->getGlobalNumElements() != numAllElements, std::logic_error,
116  "logic error. full map and sub maps have not same number of elements. We cannot build MapExtractor with Xpetra-style numbering. Please make sure that you want Xpetra-style numbering instead of Thyra-style numbering.");
117 
118  fullmap_ = fullmap;
119  maps_ = maps;
120  } else {
121  //std::cout << "Create Map Extractor in Thyra Mode!!! " << std::endl;
122  // use Thyra-style numbering for sub-block maps
123  // That is, all sub-block maps start with zero as GID and are contiguous
124 
125  // plausibility check
126  for(size_t v = 0; v < maps.size(); ++v) {
127  TEUCHOS_TEST_FOR_EXCEPTION(maps[v]->getMinAllGlobalIndex() != 0, std::logic_error,
128  "logic error. When using Thyra-style numbering all sub-block maps must start with zero as GID. Map block " << v << " starts with GID " << maps[v]->getMinAllGlobalIndex());
129  }
130 
131  // store submaps in Thyra-style ordering
132  thyraMaps_ = maps;
133 
134  // get offsets
135  std::vector<GlobalOrdinal> gidOffsets(maps.size(),0);
136  for(size_t v = 1; v < maps.size(); ++v) {
137  gidOffsets[v] = maps[v-1]->getMaxAllGlobalIndex() + gidOffsets[v-1] + 1;
138  }
139 
140  // build submaps
141  maps_.resize(maps.size());
142  std::vector<GlobalOrdinal> fullMapGids;
143  const GO INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
144  for(size_t v = 0; v < maps.size(); ++v) {
145  std::vector<GlobalOrdinal> subMapGids(maps[v]->getNodeNumElements(),0);
146  for (LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(maps[v]->getNodeNumElements()); ++l) {
147  GlobalOrdinal myGid = maps[v]->getGlobalElement(l);
148  subMapGids[l] = myGid + gidOffsets[v];
149  fullMapGids.push_back(myGid + gidOffsets[v]);
150  }
151  //std::sort(subMapGids.begin(), subMapGids.end());
152  //subMapGids.erase(std::unique(subMapGids.begin(), subMapGids.end()), subMapGids.end());
153 
154  Teuchos::ArrayView<GlobalOrdinal> subMapGidsView(&subMapGids[0], subMapGids.size());
155  Teuchos::RCP<Map> mySubMap = Xpetra::MapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(maps[v]->lib(), INVALID, subMapGidsView, maps[v]->getIndexBase(), maps[v]->getComm());
156  maps_[v] = mySubMap;
157  }
158 
159  //const GO INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
160  //std::sort(coarseMapGids.begin(), coarseMapGids.end());
161  //coarseMapGids.erase(std::unique(coarseMapGids.begin(), coarseMapGids.end()), coarseMapGids.end());
162  //Teuchos::ArrayView<GO> coarseMapGidsView(&coarseMapGids[0], coarseMapGids.size());
163  //std::sort(fullMapGids.begin(), fullMapGids.end());
164  //fullMapGids.erase(std::unique(fullMapGids.begin(), fullMapGids.end()), fullMapGids.end());
165 
166  Teuchos::ArrayView<GlobalOrdinal> fullMapGidsView(&fullMapGids[0], fullMapGids.size());
167  fullmap_ = MapFactory::Build(fullmap->lib(), INVALID, fullMapGidsView, fullmap->getIndexBase(), fullmap->getComm());
168 
169  // plausibility check
170  size_t numAllElements = 0;
171  for(size_t v = 0; v < maps_.size(); ++v) {
172  numAllElements += maps_[v]->getGlobalNumElements();
173  }
174  TEUCHOS_TEST_FOR_EXCEPTION(fullmap_->getGlobalNumElements() != numAllElements, std::logic_error,
175  "logic error. full map and sub maps have not same number of elements. This cannot be. Please report the bug to the Xpetra developers!");
176  }
177 
178  // build importers for sub maps
179  importers_.resize(maps_.size());
180  for (unsigned i = 0; i < maps_.size(); ++i)
181  if (maps[i] != null)
183  TEUCHOS_TEST_FOR_EXCEPTION(CheckConsistency() == false, std::logic_error,
184  "logic error. full map and sub maps are inconsistently distributed over the processors.");
185 
186  }
187 
189  MapExtractor(const std::vector<RCP<const Map> >& maps, const std::vector<RCP<const Map> >& thyramaps) {
190  bThyraMode_ = true;
191 
192 
193  // plausibility check
194  TEUCHOS_TEST_FOR_EXCEPTION(thyramaps.size() != maps.size(), std::logic_error, "logic error. The number of submaps must be identical!");
195  for(size_t v = 0; v < thyramaps.size(); ++v) {
196  TEUCHOS_TEST_FOR_EXCEPTION(thyramaps[v]->getMinAllGlobalIndex() != 0, std::logic_error,
197  "logic error. When using Thyra-style numbering all sub-block maps must start with zero as GID.");
198  TEUCHOS_TEST_FOR_EXCEPTION(thyramaps[v]->getNodeNumElements() != maps[v]->getNodeNumElements(), std::logic_error,
199  "logic error. The size of the submaps must be identical (same distribution, just different GIDs)");
200  }
201 
202  // store user-provided maps and thyramaps
203  thyraMaps_ = thyramaps;
204  maps_ = maps;
205 
207 
208  // plausibility check
209  size_t numAllElements = 0;
210  for(size_t v = 0; v < maps_.size(); ++v) {
211  numAllElements += maps_[v]->getGlobalNumElements();
212  }
213  TEUCHOS_TEST_FOR_EXCEPTION(fullmap_->getGlobalNumElements() != numAllElements, std::logic_error,
214  "logic error. full map and sub maps have not same number of elements. This cannot be. Please report the bug to the Xpetra developers!");
215 
216  // build importers for sub maps
217  importers_.resize(maps_.size());
218  for (unsigned i = 0; i < maps_.size(); ++i)
219  if (maps[i] != null)
221  TEUCHOS_TEST_FOR_EXCEPTION(CheckConsistency() == false, std::logic_error,
222  "logic error. full map and sub maps are inconsistently distributed over the processors.");
223  }
224 
226  MapExtractor(const MapExtractor& input) {
227  bThyraMode_ = input.getThyraMode();
228 
229  fullmap_ = MapFactory::Build(input.getFullMap(),1);
230 
231  maps_.resize(input.NumMaps(), Teuchos::null);
232  if(bThyraMode_ == true)
233  thyraMaps_.resize(input.NumMaps(), Teuchos::null);
234  for(size_t i = 0; i < input.NumMaps(); ++i) {
235  maps_[i] = MapFactory::Build(input.getMap(i,false),1);
236  if(bThyraMode_ == true)
237  thyraMaps_[i] = MapFactory::Build(input.getMap(i,true),1);
238  }
239 
240  // plausibility check
241  size_t numAllElements = 0;
242  for(size_t v = 0; v < maps_.size(); ++v) {
243  numAllElements += maps_[v]->getGlobalNumElements();
244  }
245  TEUCHOS_TEST_FOR_EXCEPTION(fullmap_->getGlobalNumElements() != numAllElements, std::logic_error,
246  "logic error. full map and sub maps have not same number of elements. This cannot be. Please report the bug to the Xpetra developers!");
247 
248  // build importers for sub maps
249  importers_.resize(maps_.size());
250  for (unsigned i = 0; i < maps_.size(); ++i)
251  if (maps_[i] != null)
253  TEUCHOS_TEST_FOR_EXCEPTION(CheckConsistency() == false, std::logic_error,
254  "logic error. full map and sub maps are inconsistently distributed over the processors.");
255  }
256 
259  void ExtractVector(const Vector& full, size_t block, Vector& partial) const {
260  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
262  "ExtractVector: maps_[" << block << "] is null");
263 
264  partial.doImport(full, *importers_[block], Xpetra::INSERT);
265  }
266  void ExtractVector(const MultiVector& full, size_t block, MultiVector& partial) const {
267  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
269  "ExtractVector: maps_[" << block << "] is null");
270  partial.doImport(full, *importers_[block], Xpetra::INSERT);
271  }
272  void ExtractVector(RCP<const Vector>& full, size_t block, RCP< Vector>& partial) const { ExtractVector(*full, block, *partial); }
273  void ExtractVector(RCP< Vector>& full, size_t block, RCP< Vector>& partial) const { ExtractVector(*full, block, *partial); }
274  void ExtractVector(RCP<const MultiVector>& full, size_t block, RCP<MultiVector>& partial) const { ExtractVector(*full, block, *partial); }
275  void ExtractVector(RCP< MultiVector>& full, size_t block, RCP<MultiVector>& partial) const { ExtractVector(*full, block, *partial); }
276 
277  RCP< Vector> ExtractVector(RCP<const Vector>& full, size_t block, bool bThyraMode = false) const {
278  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
280  "ExtractVector: maps_[" << block << "] is null");
281  // first extract partial vector from full vector (using xpetra style GIDs)
282  const RCP<Vector> vv = VectorFactory::Build(getMap(block,false), false);
283  ExtractVector(*full, block, *vv);
284  if(bThyraMode == false) return vv;
285  TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
286  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
287 #if 1
288  vv->replaceMap(getMap(block,true)); // switch to Thyra-style map
289  return vv;
290 #else
291  const RCP<Vector> thyraVec = VectorFactory::Build(getMap(block,true), true);
292  // TODO introduce Kokkos version of this.
293  Teuchos::ArrayRCP<Scalar> thyraVecData = thyraVec->getDataNonConst(0);
294  Teuchos::ArrayRCP<const Scalar> xpetraVecData = vv->getData(0);
295 
296  for(size_t i=0; i < vv->getLocalLength(); i++) {
297  thyraVecData[i] = xpetraVecData[i];
298  }
299  return thyraVec;
300 #endif
301  }
302  RCP< Vector> ExtractVector(RCP< Vector>& full, size_t block, bool bThyraMode = false) const {
303  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
305  "ExtractVector: maps_[" << block << "] is null");
306  // first extract partial vector from full vector (using xpetra style GIDs)
307  const RCP<Vector> vv = VectorFactory::Build(getMap(block,false), false);
308  ExtractVector(*full, block, *vv);
309  if(bThyraMode == false) return vv;
310  TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
311  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
312 #if 1
313  vv->replaceMap(getMap(block,true)); // switch to Thyra-style map
314  return vv;
315 #else
316  const RCP<Vector> thyraVec = VectorFactory::Build(getMap(block,true), true);
317  // TODO introduce Kokkos version of this.
318  Teuchos::ArrayRCP<Scalar> thyraVecData = thyraVec->getDataNonConst(0);
319  Teuchos::ArrayRCP<const Scalar> xpetraVecData = vv->getData(0);
320 
321  for(size_t i=0; i < vv->getLocalLength(); i++) {
322  thyraVecData[i] = xpetraVecData[i];
323  }
324  return thyraVec;
325 #endif
326  }
327  RCP<MultiVector> ExtractVector(RCP<const MultiVector>& full, size_t block, bool bThyraMode = false) const {
328  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
330  "ExtractVector: maps_[" << block << "] is null");
331  // first extract partial vector from full vector (using xpetra style GIDs)
332  const RCP<MultiVector> vv = MultiVectorFactory::Build(getMap(block,false), full->getNumVectors(), false);
333  ExtractVector(*full, block, *vv);
334  if(bThyraMode == false) return vv;
335  TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
336  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
337 #if 1
338  vv->replaceMap(getMap(block,true)); // switch to Thyra-style map
339  return vv;
340 #else
341  const RCP<MultiVector> thyraVec = MultiVectorFactory::Build(getMap(block,true), vv->getNumVectors(), true);
342  // TODO introduce Kokkos version of this.
343  for(size_t k=0; k < vv->getNumVectors(); k++) {
344  Teuchos::ArrayRCP<Scalar> thyraVecData = thyraVec->getDataNonConst(k);
345  Teuchos::ArrayRCP<const Scalar> xpetraVecData = vv->getData(k);
346  for(size_t i=0; i < vv->getLocalLength(); i++) {
347  thyraVecData[i] = xpetraVecData[i];
348  }
349  }
350  return thyraVec;
351 #endif
352  }
353  RCP<MultiVector> ExtractVector(RCP< MultiVector>& full, size_t block, bool bThyraMode = false) const {
354  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
356  "ExtractVector: maps_[" << block << "] is null");
357  // first extract partial vector from full vector (using xpetra style GIDs)
358  const RCP<MultiVector> vv = MultiVectorFactory::Build(getMap(block,false), full->getNumVectors(), false);
359  ExtractVector(*full, block, *vv);
360  if(bThyraMode == false) return vv;
361  TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
362  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
363 #if 1
364  vv->replaceMap(getMap(block,true)); // switch to Thyra-style map
365  return vv;
366 #else
367  const RCP<MultiVector> thyraVec = MultiVectorFactory::Build(getMap(block,true), vv->getNumVectors(), true);
368  // TODO introduce Kokkos version of this.
369  for(size_t k=0; k < vv->getNumVectors(); k++) {
370  Teuchos::ArrayRCP<Scalar> thyraVecData = thyraVec->getDataNonConst(k);
371  Teuchos::ArrayRCP<const Scalar> xpetraVecData = vv->getData(k);
372  for(size_t i=0; i < vv->getLocalLength(); i++) {
373  thyraVecData[i] = xpetraVecData[i];
374  }
375  }
376  return thyraVec;
377 #endif
378  }
379  RCP<MultiVector> ExtractVector(RCP<const BlockedMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& full, size_t block, bool bThyraMode = false) const {
380  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
382  "ExtractVector: maps_[" << block << "] is null");
383  XPETRA_TEST_FOR_EXCEPTION(NumMaps() != full->getMapExtractor()->NumMaps(), Xpetra::Exceptions::RuntimeError,
384  "ExtractVector: Number of blocks in map extractor is " << NumMaps() << " but should be " << full->getMapExtractor()->NumMaps() << " (number of blocks in BlockedMultiVector)");
385  Teuchos::RCP<MultiVector> vv = full->getMultiVector(block,bThyraMode);
386  return vv;
387  }
388  RCP<MultiVector> ExtractVector(RCP< Xpetra::BlockedMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& full, size_t block, bool bThyraMode = false) const {
389  XPETRA_TEST_FOR_EXCEPTION(block >= maps_.size(), std::out_of_range, "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << maps_.size() << " partial blocks.");
391  "ExtractVector: maps_[" << block << "] is null");
392  XPETRA_TEST_FOR_EXCEPTION(NumMaps() != full->getMapExtractor()->NumMaps(), Xpetra::Exceptions::RuntimeError,
393  "ExtractVector: Number of blocks in map extractor is " << NumMaps() << " but should be " << full->getMapExtractor()->NumMaps() << " (number of blocks in BlockedMultiVector)");
394  Teuchos::RCP<MultiVector> vv = full->getMultiVector(block,bThyraMode);
395  return vv;
396  }
398 
401  void InsertVector(const Vector& partial, size_t block, Vector& full, bool bThyraMode = false) const {
403  "InsertVector: maps_[" << block << "] is null");
405  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
406  if(bThyraMode) {
407 #if 1
408  // Temporarily replace underlying map.
409  // Since the partial vector is given by reference we have to switch back to the original map
410  RCP<const MultiVector> rcpPartial = Teuchos::rcpFromRef(partial);
411  RCP<MultiVector> rcpNonConstPartial = Teuchos::rcp_const_cast<MultiVector>(rcpPartial);
412  RCP<const Map> oldMap = rcpNonConstPartial->getMap(); // temporarely store map of partial
413  rcpNonConstPartial->replaceMap(getMap(block,false)); // temporarely switch to xpetra-style map
414  full.doExport(*rcpNonConstPartial, *importers_[block], Xpetra::INSERT);
415  rcpNonConstPartial->replaceMap(oldMap); // change map back to original map
416 #else
417  const RCP<Vector> xpetraVec = VectorFactory::Build(getMap(block,false), true); // get sub vector in xpetra-style numbering
418  // TODO introduce Kokkos version of this.
419  Teuchos::ArrayRCP<const Scalar> thyraVecData = partial.getData(0);
420  Teuchos::ArrayRCP<Scalar> xpetraVecData = xpetraVec->getDataNonConst(0);
421  for(size_t i=0; i < xpetraVec->getLocalLength(); i++) {
422  xpetraVecData[i] = thyraVecData[i];
423  }
424  full.doExport(*xpetraVec, *importers_[block], Xpetra::INSERT);
425 #endif
426  } else {
427  // Xpetra style numbering
428  full.doExport(partial, *importers_[block], Xpetra::INSERT);
429  }
430  }
431  void InsertVector(const MultiVector& partial, size_t block, MultiVector& full, bool bThyraMode = false) const {
433  "InsertVector: maps_[" << block << "] is null");
435  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
436  if(bThyraMode) {
437 #if 1
438  // Temporarily replace underlying map.
439  // Since the partial vector is given by reference we have to switch back to the original map
440  RCP<const MultiVector> rcpPartial = Teuchos::rcpFromRef(partial);
441  RCP<MultiVector> rcpNonConstPartial = Teuchos::rcp_const_cast<MultiVector>(rcpPartial);
442  RCP<const Map> oldMap = rcpNonConstPartial->getMap(); // temporarely store map of partial
443  rcpNonConstPartial->replaceMap(getMap(block,false)); // temporarely switch to xpetra-style map
444  full.doExport(*rcpNonConstPartial, *importers_[block], Xpetra::INSERT);
445  rcpNonConstPartial->replaceMap(oldMap); // change map back to original map
446 #else
447  const RCP<MultiVector> xpetraVec = MultiVectorFactory::Build(getMap(block,false), partial.getNumVectors(), true); // get sub vector in xpetra-style numbering
448  // TODO introduce Kokkos version of this.
449  for(size_t k=0; k < partial.getNumVectors(); k++) {
450  Teuchos::ArrayRCP<const Scalar> thyraVecData = partial.getData(k);
451  Teuchos::ArrayRCP<Scalar> xpetraVecData = xpetraVec->getDataNonConst(k);
452  for(size_t i=0; i < xpetraVec->getLocalLength(); i++) {
453  xpetraVecData[i] = thyraVecData[i];
454  }
455  }
456  full.doExport(*xpetraVec, *importers_[block], Xpetra::INSERT);
457 #endif
458  } else {
459  // Xpetra style numbering
460  full.doExport(partial, *importers_[block], Xpetra::INSERT);
461  }
462  }
463 
464  void InsertVector(RCP<const Vector> partial, size_t block, RCP< Vector> full, bool bThyraMode = false) const { InsertVector(*partial, block, *full, bThyraMode); }
465  void InsertVector(RCP< Vector> partial, size_t block, RCP< Vector> full, bool bThyraMode = false) const { InsertVector(*partial, block, *full, bThyraMode); }
466  void InsertVector(RCP<const MultiVector> partial, size_t block, RCP<MultiVector> full, bool bThyraMode = false) const { InsertVector(*partial, block, *full, bThyraMode); }
467  void InsertVector(RCP< MultiVector> partial, size_t block, RCP<MultiVector> full, bool bThyraMode = false) const { InsertVector(*partial, block, *full, bThyraMode); }
468 
469  void InsertVector(RCP<const MultiVector> partial, size_t block, RCP<Xpetra::BlockedMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > full, bool bThyraMode = false) const {
471  "InsertVector: maps_[" << block << "] is null");
472  /*TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
473  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");*/
474  full->setMultiVector(block, partial, bThyraMode);
475  }
476  void InsertVector(RCP< MultiVector> partial, size_t block, RCP<Xpetra::BlockedMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > full, bool bThyraMode = false) const {
478  "InsertVector: maps_[" << block << "] is null");
479  /*TEUCHOS_TEST_FOR_EXCEPTION(bThyraMode_ == false && bThyraMode == true, Xpetra::Exceptions::RuntimeError,
480  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");*/
481  full->setMultiVector(block, partial, bThyraMode);
482  }
483 
485 
486  RCP< Vector> getVector(size_t i, bool bThyraMode = false, bool bZero = true) const {
488  "MapExtractor::getVector: getVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
489  return VectorFactory::Build(getMap(i, bThyraMode), bZero);
490  }
491  RCP<MultiVector> getVector(size_t i, size_t numvec, bool bThyraMode = false, bool bZero = true) const {
493  "MapExtractor::getVector: getVector in Thyra-style numbering only possible if MapExtractor has been created using Thyra-style numbered submaps.");
494  return MultiVectorFactory::Build(getMap(i, bThyraMode), numvec, bZero);
495  }
496 
498  bool getThyraMode() const { return bThyraMode_; }
499 
502 
504  size_t NumMaps() const { return maps_.size(); }
505 
510  const RCP<const Map> getMap(size_t i, bool bThyraMode = false) const {
511  XPETRA_TEST_FOR_EXCEPTION( i >= NumMaps(), Xpetra::Exceptions::RuntimeError, "MapExtractor::getMap: tried to access block " << i << ", but MapExtractor has only " << NumMaps() << " blocks! Block indices must be between 0 and " << NumMaps() - 1 << ".");
512  if(bThyraMode_ == true && bThyraMode == true)
513  return thyraMaps_[i];
515  "MapExtractor::getMap: cannot return sub map in Thyra-style numbering if MapExtractor object is not created using Thyra-style numbered submaps.");
516  return maps_[i];
517  }
518 
520  const RCP<const Map> getFullMap() const { return fullmap_; }
521 
523  size_t getMapIndexForGID(GlobalOrdinal gid) const {
524  for (size_t i = 0; i < NumMaps(); i++)
525  if (getMap(i)->isNodeGlobalElement(gid) == true)
526  return i;
527 
528  TEUCHOS_TEST_FOR_EXCEPTION(false, Xpetra::Exceptions::RuntimeError,
529  "getMapIndexForGID: GID " << gid << " is not contained by a map in mapextractor." );
530  return 0;
531  }
532 
534 
535  private:
536  bool CheckConsistency() const {
537  const RCP<const Map> fullMap = getFullMap();
538 
539  for (size_t i = 0; i < NumMaps(); i++) {
540  const RCP<const Map> map = getMap(i);
541 
542  ArrayView<const GlobalOrdinal> mapGids = map->getNodeElementList();
543  for (typename ArrayView< const GlobalOrdinal >::const_iterator it = mapGids.begin(); it != mapGids.end(); it++)
544  if (fullMap->isNodeGlobalElement(*it) == false)
545  return false; // Global ID (*it) not found locally on this proc in fullMap -> error
546  }
547  return true;
548  }
549 
550  private:
551  RCP<const Map > fullmap_;
552  std::vector<RCP<const Map> > maps_;
553  std::vector<RCP<Import > > importers_;
554  bool bThyraMode_; //< boolean flag: use Thyra numbering for local sub-block maps. default = false (for Xpetra mode)
555  std::vector<RCP<const Map> > thyraMaps_; //< store Thyra-style numbering maps here in Thyra mode. In Xpetra mode this vector is empty.
556  };
557 }
558 
559 #define XPETRA_MAPEXTRACTOR_SHORT
560 #endif /* XPETRA_MAPEXTRACTOR_HPP_ */
GlobalOrdinal global_ordinal_type
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.
void InsertVector(const Vector &partial, size_t block, Vector &full, bool bThyraMode=false) const
void InsertVector(RCP< MultiVector > partial, size_t block, RCP< MultiVector > full, bool bThyraMode=false) const
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, LocalGlobal lg=Xpetra::GloballyDistributed, const Teuchos::RCP< Node > &node=defaultArgNode())
Map constructor with Xpetra-defined contiguous uniform distribution.
MapExtractor(const MapExtractor &input)
copy constructor
void ExtractVector(RCP< const Vector > &full, size_t block, RCP< Vector > &partial) const
virtual void doExport(const DistObject< Packet, LocalOrdinal, GlobalOrdinal, Node > &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, CombineMode CM)=0
Export data into this object using an Export object ("forward mode").
std::vector< RCP< const Map > > maps_
RCP< MultiVector > ExtractVector(RCP< const MultiVector > &full, size_t block, bool bThyraMode=false) const
GlobalOrdinal GO
void InsertVector(RCP< const MultiVector > partial, size_t block, RCP< Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > full, bool bThyraMode=false) const
void InsertVector(RCP< MultiVector > partial, size_t block, RCP< Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > full, bool bThyraMode=false) const
RCP< MultiVector > ExtractVector(RCP< Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &full, size_t block, bool bThyraMode=false) const
RCP< MultiVector > ExtractVector(RCP< MultiVector > &full, size_t block, bool bThyraMode=false) const
Xpetra namespace
void InsertVector(const MultiVector &partial, size_t block, MultiVector &full, bool bThyraMode=false) const
Exception throws to report errors in the internal logical of the program.
void InsertVector(RCP< Vector > partial, size_t block, RCP< Vector > full, bool bThyraMode=false) const
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.
void ExtractVector(RCP< MultiVector > &full, size_t block, RCP< MultiVector > &partial) const
virtual void doImport(const DistObject< Packet, LocalOrdinal, GlobalOrdinal, Node > &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, CombineMode CM)=0
Import data into this object using an Import object ("forward mode").
RCP< Vector > ExtractVector(RCP< const Vector > &full, size_t block, bool bThyraMode=false) const
void ExtractVector(const Vector &full, size_t block, Vector &partial) const
const RCP< const Map > getFullMap() const
the full map
void InsertVector(RCP< const Vector > partial, size_t block, RCP< Vector > full, bool bThyraMode=false) const
size_t NumMaps() const
number of partial maps
RCP< MultiVector > getVector(size_t i, size_t numvec, bool bThyraMode=false, bool bZero=true) const
void InsertVector(RCP< const MultiVector > partial, size_t block, RCP< MultiVector > full, bool bThyraMode=false) const
bool getThyraMode() const
returns true, if sub maps are stored in Thyra-style numbering
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
MapExtractor(const RCP< const Map > &fullmap, const std::vector< RCP< const Map > > &maps, bool bThyraMode=false)
RCP< MultiVector > ExtractVector(RCP< const BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &full, size_t block, bool bThyraMode=false) const
void ExtractVector(const MultiVector &full, size_t block, MultiVector &partial) const
std::vector< RCP< Import > > importers_
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
void ExtractVector(RCP< Vector > &full, size_t block, RCP< Vector > &partial) const
std::vector< RCP< const Map > > thyraMaps_
void ExtractVector(RCP< const MultiVector > &full, size_t block, RCP< MultiVector > &partial) const
size_t getMapIndexForGID(GlobalOrdinal gid) const
returns map index in map extractor which contains GID
#define XPETRA_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
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.
MapExtractor(const std::vector< RCP< const Map > > &maps, const std::vector< RCP< const Map > > &thyramaps)
Expert constructor for Thyra maps.
const RCP< const Map > getMap(size_t i, bool bThyraMode=false) const
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
RCP< Vector > getVector(size_t i, bool bThyraMode=false, bool bZero=true) const
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
Const view of the local values in a particular vector of this multivector.
RCP< Vector > ExtractVector(RCP< Vector > &full, size_t block, bool bThyraMode=false) const