Xpetra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Xpetra_BlockedMultiVector_def.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_BLOCKEDMULTIVECTOR_DEF_HPP
11 #define XPETRA_BLOCKEDMULTIVECTOR_DEF_HPP
12 
14 
15 #include "Xpetra_MultiVectorFactory.hpp"
16 #include "Xpetra_BlockedVector.hpp"
17 #include "Xpetra_MapExtractor.hpp"
18 
19 namespace Xpetra {
20 
21 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
24  size_t NumVectors,
25  bool zeroOut)
26  : map_(map) {
27  numVectors_ = NumVectors;
28 
29  vv_.reserve(map->getNumMaps());
30 
31  // add CrsMatrix objects in row,column order
32  for (size_t r = 0; r < map->getNumMaps(); ++r)
33  vv_.push_back(
34  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map->getMap(r, map_->getThyraMode()), NumVectors, zeroOut));
35 }
36 
48 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
49 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
50  BlockedMultiVector(Teuchos::RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>> bmap,
51  Teuchos::RCP<const MultiVector> v) {
52  XPETRA_TEST_FOR_EXCEPTION(bmap->getMap()->getLocalNumElements() != v->getMap()->getLocalNumElements(),
54  "BlockedMultiVector: inconsistent number of local elements of MultiVector and BlockedMap. The BlockedMap has "
55  << bmap->getMap()->getLocalNumElements() << " local elements. The vector has " << v->getMap()->getLocalNumElements()
56  << ".");
57  XPETRA_TEST_FOR_EXCEPTION(bmap->getMap()->getGlobalNumElements() != v->getMap()->getGlobalNumElements(),
59  "BlockedMultiVector: inconsistent number of global elements of MultiVector and BlockedMap. The BlockedMap has "
60  << bmap->getMap()->getGlobalNumElements() << " local elements. The vector has " << v->getMap()->getGlobalNumElements()
61  << ".");
62  // TEUCHOS_TEST_FOR_EXCEPTION(bmap->getFullMap()->getLocalNumElements() != v->getMap()->getLocalNumElements(), Xpetra::Exceptions::RuntimeError,
63  // "BlockedMultiVector: inconsistent number of local elements of MultiVector and BlockedMap. The BlockedMap has " <<
64  // bmap->getFullMap()->getLocalNumElements() << " local elements. The vector has " << v->getMap()->getLocalNumElements() << ".");
65  // TEUCHOS_TEST_FOR_EXCEPTION(bmap->getFullMap()->getGlobalNumElements() != v->getMap()->getGlobalNumElements(), Xpetra::Exceptions::RuntimeError,
66  // "BlockedMultiVector: inconsistent number of global elements of MultiVector and BlockedMap. The BlockedMap has " <<
67  // bmap->getFullMap()->getGlobalNumElements() << " local elements. The vector has " << v->getMap()->getGlobalNumElements() << ".");
68 
69  numVectors_ = v->getNumVectors();
70 
71  map_ = bmap;
72 
73  // Extract vector
74  vv_.reserve(bmap->getNumMaps());
75 
76  // add CrsMatrix objects in row,column order
77  for (size_t r = 0; r < bmap->getNumMaps(); ++r)
78  vv_.push_back(this->ExtractVector(v, r, bmap->getThyraMode()));
79 }
80 
92 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
95  Teuchos::RCP<const MultiVector> v) {
96  numVectors_ = v->getNumVectors();
97 
98  // create blocked map out of MapExtractor
99  std::vector<RCP<const Map>> maps;
100  maps.reserve(mapExtractor->NumMaps());
101  for (size_t r = 0; r < mapExtractor->NumMaps(); ++r)
102  maps.push_back(mapExtractor->getMap(r, mapExtractor->getThyraMode()));
103  map_ = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(mapExtractor->getFullMap(), maps, mapExtractor->getThyraMode()));
104 
105  // Extract vector
106  vv_.reserve(mapExtractor->NumMaps());
107 
108  // add CrsMatrix objects in row,column order
109  for (size_t r = 0; r < mapExtractor->NumMaps(); ++r)
110  vv_.push_back(this->ExtractVector(v, r, mapExtractor->getThyraMode()));
111 }
112 
113 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
115  BlockedMultiVector(const Teuchos::RCP<const BlockedMap>& map,
116  std::vector<Teuchos::RCP<MultiVector>>& vin) {
117  numVectors_ = vin[0]->getNumVectors();
118  map_ = map;
119  vv_.resize(vin.size());
120  for (size_t i = 0; i < vv_.size(); i++)
121  vv_[i] = vin[i];
122 }
123 
124 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
127  for (size_t r = 0; r < vv_.size(); ++r) {
128  vv_[r] = Teuchos::null;
129  }
130 
131  map_ = Teuchos::null;
132  numVectors_ = 0;
133 }
134 
135 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
138 operator=(const MultiVector& rhs) {
139  assign(rhs); // dispatch to protected virtual method
140  return *this;
141 }
142 
143 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
145  replaceGlobalValue(GlobalOrdinal /* globalRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
146  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::replaceGlobalValue: Not (yet) supported by BlockedMultiVector.");
147 }
148 
149 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
151  sumIntoGlobalValue(GlobalOrdinal /* globalRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
152  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::sumIntoGlobalValue: Not (yet) supported by BlockedMultiVector.");
153 }
154 
155 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
157  replaceLocalValue(LocalOrdinal /* myRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
158  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::replaceLocalValue: Not supported by BlockedMultiVector.");
159 }
160 
161 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
163  sumIntoLocalValue(LocalOrdinal /* myRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
164  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::sumIntoLocalValue:Not (yet) supported by BlockedMultiVector.");
165 }
166 
167 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
169  putScalar(const Scalar& value) {
170  XPETRA_MONITOR("BlockedMultiVector::putScalar");
171  for (size_t r = 0; r < map_->getNumMaps(); r++) {
172  getMultiVector(r)->putScalar(value);
173  }
174 }
175 
176 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
177 Teuchos::RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
179  getVector(size_t j) const {
180  RCP<Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> ret =
181  Teuchos::rcp(new Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>(this->getBlockedMap(), false));
182 
183  for (size_t r = 0; r < getBlockedMap()->getNumMaps(); r++) {
184  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> subvec =
185  this->getMultiVector(r, this->getBlockedMap()->getThyraMode())->getVector(j);
186  ret->setMultiVector(r, subvec, this->getBlockedMap()->getThyraMode());
187  }
188  return ret;
189 }
190 
191 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
192 Teuchos::RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
195  RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> ret =
196  Teuchos::rcp_const_cast<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(getVector(j));
197  return ret;
198 }
199 
200 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
201 Teuchos::ArrayRCP<const Scalar>
203  getData(size_t j) const {
204  if (map_->getNumMaps() == 1) {
205  return vv_[0]->getData(j);
206  }
207  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::getData: Not (yet) supported by BlockedMultiVector.");
208  TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
209 }
210 
211 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
212 Teuchos::ArrayRCP<Scalar>
214  getDataNonConst(size_t j) {
215  if (map_->getNumMaps() == 1) {
216  return vv_[0]->getDataNonConst(j);
217  }
218  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::getDataNonConst: Not (yet) supported by BlockedMultiVector.");
219  TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
220 }
221 
222 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
224  dot(const MultiVector& /* A */, const Teuchos::ArrayView<Scalar>& /* dots */) const {
225  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::dot: Not (yet) supported by BlockedMultiVector.");
226 }
227 
228 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
230  abs(const MultiVector& /* A */) {
231  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::abs: Not (yet) supported by BlockedMultiVector.");
232 }
233 
234 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
236  reciprocal(const MultiVector& /* A */) {
237  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::reciprocal: Not (yet) supported by BlockedMultiVector.");
238 }
239 
240 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
242  scale(const Scalar& alpha) {
243  XPETRA_MONITOR("BlockedMultiVector::scale (Scalar)");
244  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
245  if (getMultiVector(r) != Teuchos::null) {
246  getMultiVector(r)->scale(alpha);
247  }
248  }
249 }
250 
251 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
253  scale(Teuchos::ArrayView<const Scalar> alpha) {
254  XPETRA_MONITOR("BlockedMultiVector::scale (Array)");
255  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
256  if (getMultiVector(r) != Teuchos::null) {
257  getMultiVector(r)->scale(alpha);
258  }
259  }
260 }
261 
262 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
264  update(const Scalar& alpha, const MultiVector& A, const Scalar& beta) {
265  XPETRA_MONITOR("BlockedMultiVector::update");
266  Teuchos::RCP<const MultiVector> rcpA = Teuchos::rcpFromRef(A);
267  Teuchos::RCP<const BlockedMultiVector> bA = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpA);
268  TEUCHOS_TEST_FOR_EXCEPTION(numVectors_ != rcpA->getNumVectors(),
270  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector).");
271  if (bA != Teuchos::null) {
272  // A is a BlockedMultiVector (and compatible with this)
273  // Call update recursively on all sub vectors
274  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bA->getBlockedMap()->getThyraMode(),
276  "BlockedMultiVector::update: update with incompatible vector (different thyra mode).");
277  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bA->getBlockedMap()->getNumMaps(),
279  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors).");
280  for (size_t r = 0; r < map_->getNumMaps(); r++) {
281  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getLocalNumElements() != bA->getMultiVector(r)->getMap()->getLocalNumElements(),
283  "BlockedMultiVector::update: in subvector "
284  << r << ": Cannot add a vector of (local) length " << bA->getMultiVector(r)->getMap()->getLocalNumElements()
285  << " to the existing vector with " << getMultiVector(r)->getMap()->getLocalNumElements() << " entries.");
286  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getGlobalNumElements() != bA->getMultiVector(r)->getMap()->getGlobalNumElements(),
288  "BlockedMultiVector::update: in subvector "
289  << r << ": Cannot add a vector of length " << bA->getMultiVector(r)->getMap()->getGlobalNumElements()
290  << " to the existing vector with " << getMultiVector(r)->getMap()->getGlobalNumElements() << " entries.");
291 
292  // TAW: 12/6 We basically want to do something like:
293  // getMultiVector(r)->update(alpha, *(bA->getMultiVector(r)), beta);
294  // But if the left hand side is a standard MultiVector and bA->getMultiVector(r) is
295  // a blocked MultiVector this will not work, as the update implementation of the standard
296  // multivector cannot deal with blocked multivectors.
297  // The only use case where this could happen is, if the rhs vector is a single block multivector
298  Teuchos::RCP<MultiVector> lmv = getMultiVector(r);
299  Teuchos::RCP<MultiVector> rmv = bA->getMultiVector(r);
300 
301  // check whether lmv/rmv are blocked or not
302  Teuchos::RCP<BlockedMultiVector> blmv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(lmv);
303  Teuchos::RCP<BlockedMultiVector> brmv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rmv);
304 
305  if (blmv.is_null() == true && brmv.is_null() == false) {
306  // special case: lmv is standard MultiVector but rmv is BlockedMultiVector
307  TEUCHOS_TEST_FOR_EXCEPTION(brmv->getBlockedMap()->getNumMaps() > 1,
309  "BlockedMultiVector::update: Standard MultiVector object does not accept BlockedMultVector object as "
310  "parameter in update call.");
311  lmv->update(alpha, *(brmv->getMultiVector(0)), beta);
312  } else
313  lmv->update(alpha, *rmv, beta);
314  }
315  } else {
316  // A is a MultiVector
317  // If this is a BlockedMultiVector with only one sub-vector of same length we can just update
318  // Otherwise, A is not compatible with this as BlockedMultiVector and we have to extract the vector data from A
319 
320  if (getBlockedMap()->getNumMaps() == 1) {
321  // Actually call "update" on the underlying MultiVector (Epetra or Tpetra).
322  // The maps have to be compatible.
324  getMultiVector(0)->getMap()->isSameAs(*(rcpA->getMap())) == false,
326  "BlockedMultiVector::update: update with incompatible vector (maps of full vector do not match with map in MapExtractor).");
327  getMultiVector(0)->update(alpha, *rcpA, beta);
328  } else {
329  // general case: A has to be splitted and subparts have to be extracted and stored in this BlockedMultiVector
330  // XPETRA_TEST_FOR_EXCEPTION(map_->getFullMap()->isSameAs(*(rcpA->getMap()))==false, Xpetra::Exceptions::RuntimeError,
331  // "BlockedMultiVector::update: update with incompatible vector (maps of full vector do not match with map in MapExtractor). - Note:
332  // This test might be too strict and can probably be relaxed!");
333  for (size_t r = 0; r < map_->getNumMaps(); r++) {
334  // Call "update" on the subvector. Note, that getMultiVector(r) could return another BlockedMultiVector.
335  // That is, in Thyra mode the maps could differ (local Xpetra versus Thyra style gids)
336  Teuchos::RCP<const MultiVector> part = this->ExtractVector(rcpA, r, map_->getThyraMode());
337  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getLocalNumElements() != part->getMap()->getLocalNumElements(),
339  "BlockedMultiVector::update: in subvector "
340  << r << ": Cannot add a vector of (local) length " << part->getMap()->getLocalNumElements()
341  << " to the existing vector with " << getMultiVector(r)->getMap()->getLocalNumElements() << " entries.");
342  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getGlobalNumElements() != part->getMap()->getGlobalNumElements(),
344  "BlockedMultiVector::update: in subvector "
345  << r << ": Cannot add a vector of length " << part->getMap()->getGlobalNumElements()
346  << " to the existing vector with " << getMultiVector(r)->getMap()->getGlobalNumElements() << " entries.");
347  getMultiVector(r)->update(alpha, *part, beta);
348  }
349  }
350  }
351 }
352 
353 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
355  update(const Scalar& alpha, const MultiVector& A, const Scalar& beta, const MultiVector& B, const Scalar& gamma) {
356  XPETRA_MONITOR("BlockedMultiVector::update2");
357  Teuchos::RCP<const MultiVector> rcpA = Teuchos::rcpFromRef(A);
358  Teuchos::RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
359  Teuchos::RCP<const BlockedMultiVector> bA = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpA);
360  Teuchos::RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
361  if (bA != Teuchos::null && bB != Teuchos::null) {
362  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bA->getBlockedMap()->getThyraMode(),
364  "BlockedMultiVector::update: update with incompatible vector (different thyra mode in vector A).");
365  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bA->getBlockedMap()->getNumMaps(),
367  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors in vector A).");
368  TEUCHOS_TEST_FOR_EXCEPTION(
369  numVectors_ != bA->getNumVectors(),
371  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector in vector A).");
372  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bB->getBlockedMap()->getThyraMode(),
374  "BlockedMultiVector::update: update with incompatible vector (different thyra mode in vector B).");
375  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bB->getBlockedMap()->getNumMaps(),
377  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors in vector B).");
378  TEUCHOS_TEST_FOR_EXCEPTION(
379  numVectors_ != bB->getNumVectors(),
381  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector in vector B).");
382 
383  for (size_t r = 0; r < map_->getNumMaps(); r++) {
384  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->isSameAs(*(bA->getMultiVector(r)->getMap())) == false,
386  "BlockedMultiVector::update: update with incompatible vector (different maps in partial vector " << r << ").");
387  getMultiVector(r)->update(alpha, *(bA->getMultiVector(r)), beta, *(bB->getMultiVector(r)), gamma);
388  }
389  return;
390  }
391  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::update: only supports update with other BlockedMultiVector.");
392 }
393 
394 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
396  norm1(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
397  XPETRA_MONITOR("BlockedMultiVector::norm1");
398  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
399  Array<Magnitude> temp_norms(getNumVectors());
400  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
401  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
402  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
403  if (getMultiVector(r) != Teuchos::null) {
404  getMultiVector(r)->norm1(temp_norms);
405  for (size_t c = 0; c < getNumVectors(); ++c)
406  norms[c] += temp_norms[c];
407  }
408  }
409 }
410 
411 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
413  norm2(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
414  XPETRA_MONITOR("BlockedMultiVector::norm2");
415  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
416  Array<Magnitude> results(getNumVectors());
417  Array<Magnitude> temp_norms(getNumVectors());
418  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
419  std::fill(results.begin(), results.end(), ScalarTraits<Magnitude>::zero());
420  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
421  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
422  if (getMultiVector(r) != Teuchos::null) {
423  getMultiVector(r)->norm2(temp_norms);
424  for (size_t c = 0; c < getNumVectors(); ++c)
425  results[c] += temp_norms[c] * temp_norms[c];
426  }
427  }
428  for (size_t c = 0; c < getNumVectors(); ++c)
429  norms[c] = Teuchos::ScalarTraits<Magnitude>::squareroot(results[c]);
430 }
431 
432 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
434  normInf(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
435  XPETRA_MONITOR("BlockedMultiVector::normInf");
436  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
437  Array<Magnitude> temp_norms(getNumVectors());
438  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
439  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
440  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
441  if (getMultiVector(r) != Teuchos::null) {
442  getMultiVector(r)->normInf(temp_norms);
443  for (size_t c = 0; c < getNumVectors(); ++c)
444  norms[c] = std::max(norms[c], temp_norms[c]);
445  }
446  }
447 }
448 
449 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
451  meanValue(const Teuchos::ArrayView<Scalar>& /* means */) const {
452  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::meanValue: Not (yet) supported by BlockedMultiVector.");
453 }
454 
455 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
457  multiply(Teuchos::ETransp /* transA */,
458  Teuchos::ETransp /* transB */,
459  const Scalar& /* alpha */,
460  const MultiVector& /* A */,
461  const MultiVector& /* B */,
462  const Scalar& /* beta */) {
463  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::multiply: Not (yet) supported by BlockedMultiVector.");
464 }
465 
466 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
468  elementWiseMultiply(Scalar scalarAB,
470  const MultiVector& B,
471  Scalar scalarThis) {
472  XPETRA_MONITOR("BlockedMultiVector::elementWiseMultiply");
473  XPETRA_TEST_FOR_EXCEPTION(B.getMap()->isSameAs(*(this->getMap())) == false,
475  "BlockedMultiVector::elementWiseMultipy: B must have same blocked map than this.");
476  // XPETRA_TEST_FOR_EXCEPTION(A.getMap()->isSameAs(*(this->getMap()))==false, Xpetra::Exceptions::RuntimeError,
477  // "BlockedMultiVector::elementWiseMultipy: A must have same blocked map than this.");
478  TEUCHOS_TEST_FOR_EXCEPTION(A.getMap()->getLocalNumElements() != B.getMap()->getLocalNumElements(),
480  "BlockedMultiVector::elementWiseMultipy: A has " << A.getMap()->getLocalNumElements() << " elements, B has "
481  << B.getMap()->getLocalNumElements() << ".");
482  TEUCHOS_TEST_FOR_EXCEPTION(A.getMap()->getGlobalNumElements() != B.getMap()->getGlobalNumElements(),
484  "BlockedMultiVector::elementWiseMultipy: A has " << A.getMap()->getGlobalNumElements() << " elements, B has "
485  << B.getMap()->getGlobalNumElements() << ".");
486 
487  RCP<const BlockedMap> bmap = getBlockedMap();
488  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rcpA = Teuchos::rcpFromRef(A);
489  RCP<const Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bA =
490  Teuchos::rcp_dynamic_cast<const Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(rcpA);
491 
492  RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
493  RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
494  TEUCHOS_TEST_FOR_EXCEPTION(
495  bB.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::elementWiseMultipy: B must be a BlockedMultiVector.");
496 
497  // RCP<Xpetra::MapExtractor<Scalar,LocalOrdinal,GlobalOrdinal,Node> > me = Teuchos::rcp(new
498  // Xpetra::MapExtractor<Scalar,LocalOrdinal,GlobalOrdinal,Node>(bmap));
499 
500  for (size_t m = 0; m < bmap->getNumMaps(); m++) {
501  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> partA = bA->getMultiVector(m, bmap->getThyraMode())->getVector(0);
502  RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> partB = bB->getMultiVector(m, bmap->getThyraMode());
503  RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> thisPart = this->getMultiVector(m, bmap->getThyraMode());
504 
505  thisPart->elementWiseMultiply(scalarAB, *partA, *partB, scalarThis);
506  }
507 }
508 
509 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
510 size_t
512  getNumVectors() const {
513  return numVectors_;
514 }
515 
516 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
517 size_t
520  XPETRA_MONITOR("BlockedMultiVector::getLocalLength()");
521  return map_->getFullMap()->getLocalNumElements();
522 }
523 
524 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
528  XPETRA_MONITOR("BlockedMultiVector::getGlobalLength()");
529  return map_->getFullMap()->getGlobalNumElements();
530 }
531 
532 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
535  const BlockedMultiVector* Vb = dynamic_cast<const BlockedMultiVector*>(&vec);
536  if (!Vb)
537  return false;
538  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
539  RCP<const MultiVector> a = getMultiVector(r);
540  RCP<const MultiVector> b = Vb->getMultiVector(r);
541  if ((a == Teuchos::null && b != Teuchos::null) || (a != Teuchos::null && b == Teuchos::null))
542  return false;
543  if (a != Teuchos::null && b != Teuchos::null && !a->isSameSize(*b))
544  return false;
545  }
546  return true;
547 }
548 
549 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
550 std::string
552  description() const {
553  return std::string("BlockedMultiVector");
554 }
555 
556 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
558  describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const {
559  out << description() << std::endl;
560  for (size_t r = 0; r < map_->getNumMaps(); r++)
561  getMultiVector(r)->describe(out, verbLevel);
562 }
563 
564 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
566  replaceMap(const RCP<const Map>& map) {
567  XPETRA_MONITOR("BlockedMultiVector::replaceMap");
568  RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
569  if (bmap.is_null() == true) {
570  // if this has more than 1 sub blocks but "map" is not a blocked map, they are very likely not compatible
571  if (this->getBlockedMap()->getNumMaps() > 1) {
573  "BlockedMultiVector::replaceMap: map is not of type BlockedMap. General implementation not available, yet.");
574  TEUCHOS_UNREACHABLE_RETURN();
575  }
576  // special case: this is a blocked map with only one block
577  // TODO add more debug check (especially for Thyra mode)
578  std::vector<Teuchos::RCP<const Map>> subMaps(1, map);
579  map_ = Teuchos::rcp(new BlockedMap(map, subMaps, this->getBlockedMap()->getThyraMode()));
580  this->getMultiVector(0)->replaceMap(map);
581  return;
582  }
583  RCP<const BlockedMap> mybmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map_);
584 
586  mybmap->getThyraMode() != bmap->getThyraMode(), Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::replaceMap: inconsistent Thyra mode");
587  map_ = bmap;
588  for (size_t r = 0; r < map_->getNumMaps(); r++)
589  getMultiVector(r)->replaceMap(bmap->getMap(r, map_->getThyraMode()));
590 }
591 
592 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
595  const Import& /* importer */,
596  CombineMode /* CM */) {
597  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doImport: Not supported by BlockedMultiVector.");
598 }
599 
600 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
603  const Import& /* importer */,
604  CombineMode /* CM */) {
605  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doExport: Not supported by BlockedMultiVector.");
606 }
607 
608 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
611  const Export& /* exporter */,
612  CombineMode /* CM */) {
613  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doImport: Not supported by BlockedMultiVector.");
614 }
615 
616 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
619  const Export& /* exporter */,
620  CombineMode /* CM */) {
621  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doExport: Not supported by BlockedMultiVector.");
622 }
623 
624 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
626  setSeed(unsigned int seed) {
627  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
628  getMultiVector(r)->setSeed(seed);
629  }
630 }
631 
632 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
634  randomize(bool bUseXpetraImplementation) {
635  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
636  getMultiVector(r)->randomize(bUseXpetraImplementation);
637  }
638 }
639 
640 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
642  randomize(const Scalar& minVal, const Scalar& maxVal, bool bUseXpetraImplementation) {
643  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
644  getMultiVector(r)->randomize(minVal, maxVal, bUseXpetraImplementation);
645  }
646 }
647 
648 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
652 }
653 
654 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
656  Xpetra_randomize(const Scalar& minVal, const Scalar& maxVal) {
658 }
659 
660 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
661 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>
663  getMap() const {
664  XPETRA_MONITOR("BlockedMultiVector::getMap");
665  return map_;
666 }
667 
668 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
669 Teuchos::RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>>
671  getBlockedMap() const {
672  XPETRA_MONITOR("BlockedMultiVector::getBlockedMap");
673  return map_;
674 }
675 
676 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
677 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
679  getMultiVector(size_t r) const {
680  XPETRA_MONITOR("BlockedMultiVector::getMultiVector(r)");
681  TEUCHOS_TEST_FOR_EXCEPTION(r > map_->getNumMaps(),
682  std::out_of_range,
683  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
684  << " partial blocks.");
685  return vv_[r];
686 }
687 
688 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
689 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
691  getMultiVector(size_t r, bool bThyraMode) const {
692  XPETRA_MONITOR("BlockedMultiVector::getMultiVector(r,bThyraMode)");
693  TEUCHOS_TEST_FOR_EXCEPTION(r > map_->getNumMaps(),
694  std::out_of_range,
695  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
696  << " partial blocks.");
698  map_->getThyraMode() != bThyraMode, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::getMultiVector: inconsistent Thyra mode");
699  (void)bThyraMode; // avoid unused parameter warning when HAVE_XPETRA_DEBUG isn't defined
700  return vv_[r];
701 }
702 
703 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
707  bool bThyraMode) {
708  // The map of the MultiVector should be the same as the stored submap
709  // In thyra mode the vectors should live on the thyra maps
710  // in xpetra mode the should live in the xpetra maps
711  // that should be also ok in the nested case for thyra (if the vectors are distributed accordingly)
712  XPETRA_MONITOR("BlockedMultiVector::setMultiVector");
713  XPETRA_TEST_FOR_EXCEPTION(r >= map_->getNumMaps(),
714  std::out_of_range,
715  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps() << " partial blocks.");
716  XPETRA_TEST_FOR_EXCEPTION(numVectors_ != v->getNumVectors(),
718  "The BlockedMultiVectors expects " << getNumVectors() << " vectors. The provided partial multivector has "
719  << v->getNumVectors() << " vectors.");
721  map_->getThyraMode() != bThyraMode, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::setMultiVector: inconsistent Thyra mode");
722  (void)bThyraMode; // avoid unused parameter warning when HAVE_XPETRA_DEBUG isn't defined
723  Teuchos::RCP<MultiVector> vv = Teuchos::rcp_const_cast<MultiVector>(v);
724  TEUCHOS_TEST_FOR_EXCEPTION(vv == Teuchos::null, Xpetra::Exceptions::RuntimeError, "Partial vector must not be Teuchos::null");
725  vv_[r] = vv;
726 }
727 
728 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
729 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
731  Merge() const {
732  XPETRA_MONITOR("BlockedMultiVector::Merge");
733  using Teuchos::RCP;
734 
735  RCP<MultiVector> v = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getFullMap(), getNumVectors());
736  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
737  RCP<MultiVector> vi = getMultiVector(r);
738  RCP<BlockedMultiVector> bvi = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vi);
739  if (bvi.is_null() == true) {
740  this->InsertVector(vi, r, v, map_->getThyraMode());
741  } else {
742  RCP<MultiVector> mvi = bvi->Merge();
743  this->InsertVector(mvi, r, v, map_->getThyraMode());
744  }
745  }
746 
747  // TODO plausibility checks
748 
749  return v;
750 }
751 
752 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
755  Teuchos::RCP<const MultiVector> rcpRhs = Teuchos::rcpFromRef(rhs);
756  Teuchos::RCP<const BlockedMultiVector> bRhs = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpRhs);
757  if (bRhs == Teuchos::null)
758  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::assign: argument is not a blocked multi vector.");
759 
760  map_ = Teuchos::rcp(new BlockedMap(*(bRhs->getBlockedMap())));
761  vv_ = std::vector<Teuchos::RCP<MultiVector>>(map_->getNumMaps());
762  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
763  // extract source vector (is of type MultiVector or BlockedMultiVector)
764  RCP<MultiVector> src = bRhs->getMultiVector(r, map_->getThyraMode());
765 
766  // create new (empty) multivector (is of type MultiVector or BlockedMultiVector)
768  map_->getMap(r, bRhs->getBlockedMap()->getThyraMode()), rcpRhs->getNumVectors(), true);
769 
770  // check type of source and target vector
771  RCP<BlockedMultiVector> bsrc = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(src);
772  RCP<BlockedMultiVector> bvv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vv);
773  if (bsrc.is_null() == true && bvv.is_null() == true) {
774  *vv = *src; // deep copy
775  } else if (bsrc.is_null() == true && bvv.is_null() == false) {
776  // special case: source vector is a merged MultiVector but target vector is blocked
777  *vv = *src; // deep copy (is this a problem???)
778  } else if (bsrc.is_null() == false && bvv.is_null() == true) {
779  // special case: source vector is blocked but target vector is a merged MultiVector
780  // This is a problem and only works if bsrc has only one block
781  if (bsrc->getBlockedMap()->getNumMaps() > 1) {
783  "BlockedMultiVector::assign: source vector is of type BlockedMultiVector (with more than "
784  "1 blocks) and target is a MultiVector.");
785  TEUCHOS_UNREACHABLE_RETURN();
786  }
787  RCP<MultiVector> ssrc = bsrc->getMultiVector(0, map_->getThyraMode());
788  XPETRA_TEST_FOR_EXCEPTION(ssrc.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::assign: cannot extract vector");
789  XPETRA_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<BlockedMultiVector>(ssrc) != Teuchos::null,
791  "BlockedMultiVector::assign: sub block must not be of type BlockedMultiVector.");
792  *vv = *ssrc;
793  } else {
794  // this should work (no exception necessary, i guess)
795  XPETRA_TEST_FOR_EXCEPTION(bsrc->getBlockedMap()->getNumMaps() != bvv->getBlockedMap()->getNumMaps(),
797  "BlockedMultiVector::assign: source and target are BlockedMultiVectors with a different number of submaps.");
798  *vv = *src; // deep copy
799  }
800  vv_[r] = vv;
801  }
802  numVectors_ = rcpRhs->getNumVectors();
803 }
804 
805 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
808  size_t block,
810  ExtractVector(*full, block, *partial);
811 }
812 
813 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
814 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
816  size_t block,
818  ExtractVector(*full, block, *partial);
819 }
820 
821 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
822 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
823 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
825  size_t block,
826  bool bThyraMode) const {
827  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
828  std::out_of_range,
829  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
830  << " partial blocks.");
832  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
833  RCP<const BlockedMultiVector> bfull = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(full);
834  if (bfull.is_null() == true) {
835  // standard case: full is not of type BlockedMultiVector
836  // first extract partial vector from full vector (using xpetra style GIDs)
837  const RCP<MultiVector> vv =
838  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getMap(block, false), full->getNumVectors(), false);
839  // if(bThyraMode == false) {
840  // ExtractVector(*full, block, *vv);
841  // return vv;
842  //} else {
843  RCP<const Map> oldThyMapFull = full->getMap(); // temporarely store map of full
844  RCP<MultiVector> rcpNonConstFull = Teuchos::rcp_const_cast<MultiVector>(full);
845  rcpNonConstFull->replaceMap(map_->getImporter(block)->getSourceMap());
846  ExtractVector(*rcpNonConstFull, block, *vv);
847  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
848  Xpetra::Exceptions::RuntimeError,
849  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been "
850  "created using Thyra-style numbered submaps.");
851  if (bThyraMode == true)
852  vv->replaceMap(map_->getMap(block, true)); // switch to Thyra-style map
853  rcpNonConstFull->replaceMap(oldThyMapFull);
854  return vv;
855  //}
856  } else {
857  // special case: full is of type BlockedMultiVector
858  XPETRA_TEST_FOR_EXCEPTION(map_->getNumMaps() != bfull->getBlockedMap()->getNumMaps(),
859  Xpetra::Exceptions::RuntimeError,
860  "ExtractVector: Number of blocks in map extractor is " << map_->getNumMaps() << " but should be "
861  << bfull->getBlockedMap()->getNumMaps()
862  << " (number of blocks in BlockedMultiVector)");
863  return bfull->getMultiVector(block, bThyraMode);
864  }
865 }
866 
867 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
868 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
869 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
871  size_t block,
872  bool bThyraMode) const {
873  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
874  std::out_of_range,
875  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
876  << " partial blocks.");
878  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
879  RCP<BlockedMultiVector> bfull = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(full);
880  if (bfull.is_null() == true) {
881  // standard case: full is not of type BlockedMultiVector
882  // first extract partial vector from full vector (using xpetra style GIDs)
883  const RCP<MultiVector> vv =
884  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getMap(block, false), full->getNumVectors(), false);
885  // if(bThyraMode == false) {
886  // ExtractVector(*full, block, *vv);
887  // return vv;
888  //} else {
889  RCP<const Map> oldThyMapFull = full->getMap(); // temporarely store map of full
890  full->replaceMap(map_->getImporter(block)->getSourceMap());
891  ExtractVector(*full, block, *vv);
892  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
893  Xpetra::Exceptions::RuntimeError,
894  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been "
895  "created using Thyra-style numbered submaps.");
896  if (bThyraMode == true)
897  vv->replaceMap(map_->getMap(block, true)); // switch to Thyra-style map
898  full->replaceMap(oldThyMapFull);
899  return vv;
900  //}
901  } else {
902  // special case: full is of type BlockedMultiVector
903  XPETRA_TEST_FOR_EXCEPTION(map_->getNumMaps() != bfull->getBlockedMap()->getNumMaps(),
904  Xpetra::Exceptions::RuntimeError,
905  "ExtractVector: Number of blocks in map extractor is " << map_->getNumMaps() << " but should be "
906  << bfull->getBlockedMap()->getNumMaps()
907  << " (number of blocks in BlockedMultiVector)");
908  return bfull->getMultiVector(block, bThyraMode);
909  }
910 }
911 
912 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
913 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
915  size_t block,
917  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
918  std::out_of_range,
919  "ExtractVector: Error, block = " << block << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
920  << " partial blocks.");
921  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: maps_[" << block << "] is null");
922  partial.doImport(full, *(map_->getImporter(block)), Xpetra::INSERT);
923 }
924 
925 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
928  size_t block,
930  bool bThyraMode) const {
931  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
932  std::out_of_range,
933  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
934  << " partial blocks.");
936  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
937  XPETRA_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
938  Xpetra::Exceptions::RuntimeError,
939  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created "
940  "using Thyra-style numbered submaps.");
941  if (bThyraMode) {
942  // NOTE: the importer objects in the BlockedMap are always using Xpetra GIDs (or Thyra style Xpetra GIDs)
943  // The source map corresponds to the full map (in Xpetra GIDs) starting with GIDs from zero. The GIDs are consecutive in Thyra mode
944  // The target map is the partial map (in the corresponding Xpetra GIDs)
945 
946  // TODO can we skip the Export call in special cases (i.e. Src = Target map, same length, etc...)
947 
948  // store original GIDs (could be Thyra GIDs)
949  RCP<const MultiVector> rcpPartial = Teuchos::rcpFromRef(partial);
950  RCP<MultiVector> rcpNonConstPartial = Teuchos::rcp_const_cast<MultiVector>(rcpPartial);
951  RCP<const Map> oldThyMapPartial = rcpNonConstPartial->getMap(); // temporarely store map of partial
952  RCP<const Map> oldThyMapFull = full.getMap(); // temporarely store map of full
953 
954  // check whether getMap(block,false) is identical to target map of importer
955  // XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block,false)->isSameAs(*(map_->getImporter(block)->getTargetMap()))==false,
956  // Xpetra::Exceptions::RuntimeError,
957  // "MapExtractor::InsertVector: InsertVector in Thyra-style mode: Xpetra GIDs of partial vector are not identical to target Map
958  // of Importer. This should not be.");
959 
960  // XPETRA_TEST_FOR_EXCEPTION(full.getMap()->isSameAs(*(map_->getImporter(block)->getSourceMap()))==false,
961  // Xpetra::Exceptions::RuntimeError,
962  // "MapExtractor::InsertVector: InsertVector in Thyra-style mode: Xpetra GIDs of full vector are not identical to source Map of
963  // Importer. This should not be.");
964 
965  rcpNonConstPartial->replaceMap(map_->getMap(block, false)); // temporarely switch to xpetra-style map
966  full.replaceMap(map_->getImporter(block)->getSourceMap()); // temporarely switch to Xpetra GIDs
967 
968  // do the Export
969  full.doExport(*rcpNonConstPartial, *(map_->getImporter(block)), Xpetra::INSERT);
970 
971  // switch back to original maps
972  full.replaceMap(oldThyMapFull); // reset original map (Thyra GIDs)
973  rcpNonConstPartial->replaceMap(oldThyMapPartial); // change map back to original map
974  } else {
975  // Xpetra style numbering
976  full.doExport(partial, *(map_->getImporter(block)), Xpetra::INSERT);
977  }
978 }
979 
980 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
983  size_t block,
985  bool bThyraMode) const {
986  RCP<Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bfull =
988  if (bfull.is_null() == true)
989  InsertVector(*partial, block, *full, bThyraMode);
990  else {
991  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "InsertVector: maps_[" << block << "] is null");
992 
993 #if 0
994  // WCMCLEN - ETI: MultiVector doesn't have a setMultiVector method,
995  // WCMCLEN - ETI: but BlockedMultiVector does... should this be bfull->...?
996  full->setMultiVector(block, partial, bThyraMode);
997 #else
998  throw Xpetra::Exceptions::RuntimeError("MultiVector::setMultiVector() is not implemented.");
999 #endif
1000  }
1001 }
1002 
1003 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1004 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1006  size_t block,
1008  bool bThyraMode) const {
1009  RCP<Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bfull =
1011  if (bfull.is_null() == true)
1012  InsertVector(*partial, block, *full, bThyraMode);
1013  else {
1014  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "InsertVector: maps_[" << block << "] is null");
1015  bfull->setMultiVector(block, partial, bThyraMode);
1016  }
1017 }
1018 
1019 } // namespace Xpetra
1020 
1021 #endif // XPETRA_BLOCKEDMULTIVECTOR_DEF_HPP
virtual void replaceMap(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map)=0
virtual void doExport(const DistObject< Scalar, LocalOrdinal, GlobalOrdinal, Node > &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, CombineMode CM)=0
Export data into this object using an Export object (&quot;forward mode&quot;).
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.
BlockedMultiVector(const Teuchos::RCP< const BlockedMap > &map, size_t NumVectors, bool zeroOut=true)
Constructor.
Exception throws to report errors in the internal logical of the program.
virtual void Xpetra_randomize()
Set multi-vector values to random numbers. XPetra implementation.
Factory for any type of Xpetra::MultiVector and its derived classes.
virtual void update(const Scalar &alpha, const MultiVector &A, const Scalar &beta)
Update multi-vector values with scaled values of A, this = beta*this + alpha*A.
virtual void doImport(const DistObject< Scalar, LocalOrdinal, GlobalOrdinal, Node > &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, CombineMode CM)=0
Import data into this object using an Import object (&quot;forward mode&quot;).
Teuchos::RCP< MultiVector > Merge() const
merge BlockedMultiVector blocks to a single MultiVector
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with the given verbosity level to a FancyOStream.
virtual void setSeed(unsigned int seed)
Set seed for Random function.
size_t global_size_t
Global size_t object.
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const
Const view of the local values in a particular vector of this multivector.
Teuchos::RCP< MultiVector > getMultiVector(size_t r) const
return partial multivector associated with block row r
virtual Teuchos::ArrayRCP< Scalar > getDataNonConst(size_t j)
View of the local values in a particular vector of this multivector.
#define XPETRA_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual size_t getNumVectors() const
Number of columns in the multivector.
CombineMode
Xpetra::Combine Mode enumerable type.
#define XPETRA_MONITOR(funcName)
virtual void randomize(bool bUseXpetraImplementation=false)
Set multi-vector values to random numbers.