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 // ***********************************************************************
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 // Tobias Wiesner (tawiesn@sandia.gov)
42 // Ray Tuminaro (rstumin@sandia.gov)
43 //
44 // ***********************************************************************
45 //
46 // @HEADER
47 #ifndef XPETRA_BLOCKEDMULTIVECTOR_DEF_HPP
48 #define XPETRA_BLOCKEDMULTIVECTOR_DEF_HPP
49 
51 
52 #include "Xpetra_MultiVectorFactory.hpp"
53 #include "Xpetra_BlockedVector.hpp"
54 #include "Xpetra_MapExtractor.hpp"
55 
56 namespace Xpetra {
57 
58 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
61  size_t NumVectors,
62  bool zeroOut)
63  : map_(map) {
64  numVectors_ = NumVectors;
65 
66  vv_.reserve(map->getNumMaps());
67 
68  // add CrsMatrix objects in row,column order
69  for (size_t r = 0; r < map->getNumMaps(); ++r)
70  vv_.push_back(
71  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map->getMap(r, map_->getThyraMode()), NumVectors, zeroOut));
72 }
73 
85 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
86 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
87  BlockedMultiVector(Teuchos::RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>> bmap,
88  Teuchos::RCP<const MultiVector> v) {
89  XPETRA_TEST_FOR_EXCEPTION(bmap->getMap()->getLocalNumElements() != v->getMap()->getLocalNumElements(),
91  "BlockedMultiVector: inconsistent number of local elements of MultiVector and BlockedMap. The BlockedMap has "
92  << bmap->getMap()->getLocalNumElements() << " local elements. The vector has " << v->getMap()->getLocalNumElements()
93  << ".");
94  XPETRA_TEST_FOR_EXCEPTION(bmap->getMap()->getGlobalNumElements() != v->getMap()->getGlobalNumElements(),
96  "BlockedMultiVector: inconsistent number of global elements of MultiVector and BlockedMap. The BlockedMap has "
97  << bmap->getMap()->getGlobalNumElements() << " local elements. The vector has " << v->getMap()->getGlobalNumElements()
98  << ".");
99  // TEUCHOS_TEST_FOR_EXCEPTION(bmap->getFullMap()->getLocalNumElements() != v->getMap()->getLocalNumElements(), Xpetra::Exceptions::RuntimeError,
100  // "BlockedMultiVector: inconsistent number of local elements of MultiVector and BlockedMap. The BlockedMap has " <<
101  // bmap->getFullMap()->getLocalNumElements() << " local elements. The vector has " << v->getMap()->getLocalNumElements() << ".");
102  // TEUCHOS_TEST_FOR_EXCEPTION(bmap->getFullMap()->getGlobalNumElements() != v->getMap()->getGlobalNumElements(), Xpetra::Exceptions::RuntimeError,
103  // "BlockedMultiVector: inconsistent number of global elements of MultiVector and BlockedMap. The BlockedMap has " <<
104  // bmap->getFullMap()->getGlobalNumElements() << " local elements. The vector has " << v->getMap()->getGlobalNumElements() << ".");
105 
106  numVectors_ = v->getNumVectors();
107 
108  map_ = bmap;
109 
110  // Extract vector
111  vv_.reserve(bmap->getNumMaps());
112 
113  // add CrsMatrix objects in row,column order
114  for (size_t r = 0; r < bmap->getNumMaps(); ++r)
115  vv_.push_back(this->ExtractVector(v, r, bmap->getThyraMode()));
116 }
117 
129 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
132  Teuchos::RCP<const MultiVector> v) {
133  numVectors_ = v->getNumVectors();
134 
135  // create blocked map out of MapExtractor
136  std::vector<RCP<const Map>> maps;
137  maps.reserve(mapExtractor->NumMaps());
138  for (size_t r = 0; r < mapExtractor->NumMaps(); ++r)
139  maps.push_back(mapExtractor->getMap(r, mapExtractor->getThyraMode()));
140  map_ = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(mapExtractor->getFullMap(), maps, mapExtractor->getThyraMode()));
141 
142  // Extract vector
143  vv_.reserve(mapExtractor->NumMaps());
144 
145  // add CrsMatrix objects in row,column order
146  for (size_t r = 0; r < mapExtractor->NumMaps(); ++r)
147  vv_.push_back(this->ExtractVector(v, r, mapExtractor->getThyraMode()));
148 }
149 
150 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
152  BlockedMultiVector(const Teuchos::RCP<const BlockedMap>& map,
153  std::vector<Teuchos::RCP<MultiVector>>& vin) {
154  numVectors_ = vin[0]->getNumVectors();
155  map_ = map;
156  vv_.resize(vin.size());
157  for (size_t i = 0; i < vv_.size(); i++)
158  vv_[i] = vin[i];
159 }
160 
161 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
164  for (size_t r = 0; r < vv_.size(); ++r) {
165  vv_[r] = Teuchos::null;
166  }
167 
168  map_ = Teuchos::null;
169  numVectors_ = 0;
170 }
171 
172 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
175 operator=(const MultiVector& rhs) {
176  assign(rhs); // dispatch to protected virtual method
177  return *this;
178 }
179 
180 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
182  replaceGlobalValue(GlobalOrdinal /* globalRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
183  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::replaceGlobalValue: Not (yet) supported by BlockedMultiVector.");
184 }
185 
186 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
188  sumIntoGlobalValue(GlobalOrdinal /* globalRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
189  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::sumIntoGlobalValue: Not (yet) supported by BlockedMultiVector.");
190 }
191 
192 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
194  replaceLocalValue(LocalOrdinal /* myRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
195  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::replaceLocalValue: Not supported by BlockedMultiVector.");
196 }
197 
198 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
200  sumIntoLocalValue(LocalOrdinal /* myRow */, size_t /* vectorIndex */, const Scalar& /* value */) {
201  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::sumIntoLocalValue:Not (yet) supported by BlockedMultiVector.");
202 }
203 
204 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
206  putScalar(const Scalar& value) {
207  XPETRA_MONITOR("BlockedMultiVector::putScalar");
208  for (size_t r = 0; r < map_->getNumMaps(); r++) {
209  getMultiVector(r)->putScalar(value);
210  }
211 }
212 
213 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
214 Teuchos::RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
216  getVector(size_t j) const {
217  RCP<Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> ret =
218  Teuchos::rcp(new Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>(this->getBlockedMap(), false));
219 
220  for (size_t r = 0; r < getBlockedMap()->getNumMaps(); r++) {
221  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> subvec =
222  this->getMultiVector(r, this->getBlockedMap()->getThyraMode())->getVector(j);
223  ret->setMultiVector(r, subvec, this->getBlockedMap()->getThyraMode());
224  }
225  return ret;
226 }
227 
228 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
229 Teuchos::RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
232  RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> ret =
233  Teuchos::rcp_const_cast<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(getVector(j));
234  return ret;
235 }
236 
237 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
238 Teuchos::ArrayRCP<const Scalar>
240  getData(size_t j) const {
241  if (map_->getNumMaps() == 1) {
242  return vv_[0]->getData(j);
243  }
244  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::getData: Not (yet) supported by BlockedMultiVector.");
245  TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
246 }
247 
248 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
249 Teuchos::ArrayRCP<Scalar>
251  getDataNonConst(size_t j) {
252  if (map_->getNumMaps() == 1) {
253  return vv_[0]->getDataNonConst(j);
254  }
255  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::getDataNonConst: Not (yet) supported by BlockedMultiVector.");
256  TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
257 }
258 
259 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
261  dot(const MultiVector& /* A */, const Teuchos::ArrayView<Scalar>& /* dots */) const {
262  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::dot: Not (yet) supported by BlockedMultiVector.");
263 }
264 
265 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
267  abs(const MultiVector& /* A */) {
268  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::abs: Not (yet) supported by BlockedMultiVector.");
269 }
270 
271 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
273  reciprocal(const MultiVector& /* A */) {
274  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::reciprocal: Not (yet) supported by BlockedMultiVector.");
275 }
276 
277 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
279  scale(const Scalar& alpha) {
280  XPETRA_MONITOR("BlockedMultiVector::scale (Scalar)");
281  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
282  if (getMultiVector(r) != Teuchos::null) {
283  getMultiVector(r)->scale(alpha);
284  }
285  }
286 }
287 
288 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
290  scale(Teuchos::ArrayView<const Scalar> alpha) {
291  XPETRA_MONITOR("BlockedMultiVector::scale (Array)");
292  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
293  if (getMultiVector(r) != Teuchos::null) {
294  getMultiVector(r)->scale(alpha);
295  }
296  }
297 }
298 
299 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
301  update(const Scalar& alpha, const MultiVector& A, const Scalar& beta) {
302  XPETRA_MONITOR("BlockedMultiVector::update");
303  Teuchos::RCP<const MultiVector> rcpA = Teuchos::rcpFromRef(A);
304  Teuchos::RCP<const BlockedMultiVector> bA = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpA);
305  TEUCHOS_TEST_FOR_EXCEPTION(numVectors_ != rcpA->getNumVectors(),
307  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector).");
308  if (bA != Teuchos::null) {
309  // A is a BlockedMultiVector (and compatible with this)
310  // Call update recursively on all sub vectors
311  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bA->getBlockedMap()->getThyraMode(),
313  "BlockedMultiVector::update: update with incompatible vector (different thyra mode).");
314  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bA->getBlockedMap()->getNumMaps(),
316  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors).");
317  for (size_t r = 0; r < map_->getNumMaps(); r++) {
318  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getLocalNumElements() != bA->getMultiVector(r)->getMap()->getLocalNumElements(),
320  "BlockedMultiVector::update: in subvector "
321  << r << ": Cannot add a vector of (local) length " << bA->getMultiVector(r)->getMap()->getLocalNumElements()
322  << " to the existing vector with " << getMultiVector(r)->getMap()->getLocalNumElements() << " entries.");
323  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getGlobalNumElements() != bA->getMultiVector(r)->getMap()->getGlobalNumElements(),
325  "BlockedMultiVector::update: in subvector "
326  << r << ": Cannot add a vector of length " << bA->getMultiVector(r)->getMap()->getGlobalNumElements()
327  << " to the existing vector with " << getMultiVector(r)->getMap()->getGlobalNumElements() << " entries.");
328 
329  // TAW: 12/6 We basically want to do something like:
330  // getMultiVector(r)->update(alpha, *(bA->getMultiVector(r)), beta);
331  // But if the left hand side is a standard MultiVector and bA->getMultiVector(r) is
332  // a blocked MultiVector this will not work, as the update implementation of the standard
333  // multivector cannot deal with blocked multivectors.
334  // The only use case where this could happen is, if the rhs vector is a single block multivector
335  Teuchos::RCP<MultiVector> lmv = getMultiVector(r);
336  Teuchos::RCP<MultiVector> rmv = bA->getMultiVector(r);
337 
338  // check whether lmv/rmv are blocked or not
339  Teuchos::RCP<BlockedMultiVector> blmv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(lmv);
340  Teuchos::RCP<BlockedMultiVector> brmv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rmv);
341 
342  if (blmv.is_null() == true && brmv.is_null() == false) {
343  // special case: lmv is standard MultiVector but rmv is BlockedMultiVector
344  TEUCHOS_TEST_FOR_EXCEPTION(brmv->getBlockedMap()->getNumMaps() > 1,
346  "BlockedMultiVector::update: Standard MultiVector object does not accept BlockedMultVector object as "
347  "parameter in update call.");
348  lmv->update(alpha, *(brmv->getMultiVector(0)), beta);
349  } else
350  lmv->update(alpha, *rmv, beta);
351  }
352  } else {
353  // A is a MultiVector
354  // If this is a BlockedMultiVector with only one sub-vector of same length we can just update
355  // Otherwise, A is not compatible with this as BlockedMultiVector and we have to extract the vector data from A
356 
357  if (getBlockedMap()->getNumMaps() == 1) {
358  // Actually call "update" on the underlying MultiVector (Epetra or Tpetra).
359  // The maps have to be compatible.
361  getMultiVector(0)->getMap()->isSameAs(*(rcpA->getMap())) == false,
363  "BlockedMultiVector::update: update with incompatible vector (maps of full vector do not match with map in MapExtractor).");
364  getMultiVector(0)->update(alpha, *rcpA, beta);
365  } else {
366  // general case: A has to be splitted and subparts have to be extracted and stored in this BlockedMultiVector
367  // XPETRA_TEST_FOR_EXCEPTION(map_->getFullMap()->isSameAs(*(rcpA->getMap()))==false, Xpetra::Exceptions::RuntimeError,
368  // "BlockedMultiVector::update: update with incompatible vector (maps of full vector do not match with map in MapExtractor). - Note:
369  // This test might be too strict and can probably be relaxed!");
370  for (size_t r = 0; r < map_->getNumMaps(); r++) {
371  // Call "update" on the subvector. Note, that getMultiVector(r) could return another BlockedMultiVector.
372  // That is, in Thyra mode the maps could differ (local Xpetra versus Thyra style gids)
373  Teuchos::RCP<const MultiVector> part = this->ExtractVector(rcpA, r, map_->getThyraMode());
374  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getLocalNumElements() != part->getMap()->getLocalNumElements(),
376  "BlockedMultiVector::update: in subvector "
377  << r << ": Cannot add a vector of (local) length " << part->getMap()->getLocalNumElements()
378  << " to the existing vector with " << getMultiVector(r)->getMap()->getLocalNumElements() << " entries.");
379  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->getGlobalNumElements() != part->getMap()->getGlobalNumElements(),
381  "BlockedMultiVector::update: in subvector "
382  << r << ": Cannot add a vector of length " << part->getMap()->getGlobalNumElements()
383  << " to the existing vector with " << getMultiVector(r)->getMap()->getGlobalNumElements() << " entries.");
384  getMultiVector(r)->update(alpha, *part, beta);
385  }
386  }
387  }
388 }
389 
390 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
392  update(const Scalar& alpha, const MultiVector& A, const Scalar& beta, const MultiVector& B, const Scalar& gamma) {
393  XPETRA_MONITOR("BlockedMultiVector::update2");
394  Teuchos::RCP<const MultiVector> rcpA = Teuchos::rcpFromRef(A);
395  Teuchos::RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
396  Teuchos::RCP<const BlockedMultiVector> bA = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpA);
397  Teuchos::RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
398  if (bA != Teuchos::null && bB != Teuchos::null) {
399  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bA->getBlockedMap()->getThyraMode(),
401  "BlockedMultiVector::update: update with incompatible vector (different thyra mode in vector A).");
402  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bA->getBlockedMap()->getNumMaps(),
404  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors in vector A).");
405  TEUCHOS_TEST_FOR_EXCEPTION(
406  numVectors_ != bA->getNumVectors(),
408  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector in vector A).");
409  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() != bB->getBlockedMap()->getThyraMode(),
411  "BlockedMultiVector::update: update with incompatible vector (different thyra mode in vector B).");
412  TEUCHOS_TEST_FOR_EXCEPTION(map_->getNumMaps() != bB->getBlockedMap()->getNumMaps(),
414  "BlockedMultiVector::update: update with incompatible vector (different number of partial vectors in vector B).");
415  TEUCHOS_TEST_FOR_EXCEPTION(
416  numVectors_ != bB->getNumVectors(),
418  "BlockedMultiVector::update: update with incompatible vector (different number of vectors in multivector in vector B).");
419 
420  for (size_t r = 0; r < map_->getNumMaps(); r++) {
421  XPETRA_TEST_FOR_EXCEPTION(getMultiVector(r)->getMap()->isSameAs(*(bA->getMultiVector(r)->getMap())) == false,
423  "BlockedMultiVector::update: update with incompatible vector (different maps in partial vector " << r << ").");
424  getMultiVector(r)->update(alpha, *(bA->getMultiVector(r)), beta, *(bB->getMultiVector(r)), gamma);
425  }
426  return;
427  }
428  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::update: only supports update with other BlockedMultiVector.");
429 }
430 
431 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
433  norm1(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
434  XPETRA_MONITOR("BlockedMultiVector::norm1");
435  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
436  Array<Magnitude> temp_norms(getNumVectors());
437  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
438  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
439  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
440  if (getMultiVector(r) != Teuchos::null) {
441  getMultiVector(r)->norm1(temp_norms);
442  for (size_t c = 0; c < getNumVectors(); ++c)
443  norms[c] += temp_norms[c];
444  }
445  }
446 }
447 
448 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
450  norm2(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
451  XPETRA_MONITOR("BlockedMultiVector::norm2");
452  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
453  Array<Magnitude> results(getNumVectors());
454  Array<Magnitude> temp_norms(getNumVectors());
455  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
456  std::fill(results.begin(), results.end(), ScalarTraits<Magnitude>::zero());
457  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
458  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
459  if (getMultiVector(r) != Teuchos::null) {
460  getMultiVector(r)->norm2(temp_norms);
461  for (size_t c = 0; c < getNumVectors(); ++c)
462  results[c] += temp_norms[c] * temp_norms[c];
463  }
464  }
465  for (size_t c = 0; c < getNumVectors(); ++c)
466  norms[c] = Teuchos::ScalarTraits<Magnitude>::squareroot(results[c]);
467 }
468 
469 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
471  normInf(const Teuchos::ArrayView<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& norms) const {
472  XPETRA_MONITOR("BlockedMultiVector::normInf");
473  typedef typename ScalarTraits<Scalar>::magnitudeType Magnitude;
474  Array<Magnitude> temp_norms(getNumVectors());
475  std::fill(norms.begin(), norms.end(), ScalarTraits<Magnitude>::zero());
476  std::fill(temp_norms.begin(), temp_norms.end(), ScalarTraits<Magnitude>::zero());
477  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
478  if (getMultiVector(r) != Teuchos::null) {
479  getMultiVector(r)->normInf(temp_norms);
480  for (size_t c = 0; c < getNumVectors(); ++c)
481  norms[c] = std::max(norms[c], temp_norms[c]);
482  }
483  }
484 }
485 
486 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
488  meanValue(const Teuchos::ArrayView<Scalar>& /* means */) const {
489  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::meanValue: Not (yet) supported by BlockedMultiVector.");
490 }
491 
492 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
494  multiply(Teuchos::ETransp /* transA */,
495  Teuchos::ETransp /* transB */,
496  const Scalar& /* alpha */,
497  const MultiVector& /* A */,
498  const MultiVector& /* B */,
499  const Scalar& /* beta */) {
500  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::multiply: Not (yet) supported by BlockedMultiVector.");
501 }
502 
503 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
505  elementWiseMultiply(Scalar scalarAB,
507  const MultiVector& B,
508  Scalar scalarThis) {
509  XPETRA_MONITOR("BlockedMultiVector::elementWiseMultiply");
510  XPETRA_TEST_FOR_EXCEPTION(B.getMap()->isSameAs(*(this->getMap())) == false,
512  "BlockedMultiVector::elementWiseMultipy: B must have same blocked map than this.");
513  // XPETRA_TEST_FOR_EXCEPTION(A.getMap()->isSameAs(*(this->getMap()))==false, Xpetra::Exceptions::RuntimeError,
514  // "BlockedMultiVector::elementWiseMultipy: A must have same blocked map than this.");
515  TEUCHOS_TEST_FOR_EXCEPTION(A.getMap()->getLocalNumElements() != B.getMap()->getLocalNumElements(),
517  "BlockedMultiVector::elementWiseMultipy: A has " << A.getMap()->getLocalNumElements() << " elements, B has "
518  << B.getMap()->getLocalNumElements() << ".");
519  TEUCHOS_TEST_FOR_EXCEPTION(A.getMap()->getGlobalNumElements() != B.getMap()->getGlobalNumElements(),
521  "BlockedMultiVector::elementWiseMultipy: A has " << A.getMap()->getGlobalNumElements() << " elements, B has "
522  << B.getMap()->getGlobalNumElements() << ".");
523 
524  RCP<const BlockedMap> bmap = getBlockedMap();
525  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rcpA = Teuchos::rcpFromRef(A);
526  RCP<const Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bA =
527  Teuchos::rcp_dynamic_cast<const Xpetra::BlockedVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(rcpA);
528 
529  RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
530  RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
531  TEUCHOS_TEST_FOR_EXCEPTION(
532  bB.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::elementWiseMultipy: B must be a BlockedMultiVector.");
533 
534  // RCP<Xpetra::MapExtractor<Scalar,LocalOrdinal,GlobalOrdinal,Node> > me = Teuchos::rcp(new
535  // Xpetra::MapExtractor<Scalar,LocalOrdinal,GlobalOrdinal,Node>(bmap));
536 
537  for (size_t m = 0; m < bmap->getNumMaps(); m++) {
538  RCP<const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> partA = bA->getMultiVector(m, bmap->getThyraMode())->getVector(0);
539  RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> partB = bB->getMultiVector(m, bmap->getThyraMode());
540  RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> thisPart = this->getMultiVector(m, bmap->getThyraMode());
541 
542  thisPart->elementWiseMultiply(scalarAB, *partA, *partB, scalarThis);
543  }
544 }
545 
546 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
547 size_t
549  getNumVectors() const {
550  return numVectors_;
551 }
552 
553 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
554 size_t
557  XPETRA_MONITOR("BlockedMultiVector::getLocalLength()");
558  return map_->getFullMap()->getLocalNumElements();
559 }
560 
561 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
565  XPETRA_MONITOR("BlockedMultiVector::getGlobalLength()");
566  return map_->getFullMap()->getGlobalNumElements();
567 }
568 
569 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
572  const BlockedMultiVector* Vb = dynamic_cast<const BlockedMultiVector*>(&vec);
573  if (!Vb)
574  return false;
575  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
576  RCP<const MultiVector> a = getMultiVector(r);
577  RCP<const MultiVector> b = Vb->getMultiVector(r);
578  if ((a == Teuchos::null && b != Teuchos::null) || (a != Teuchos::null && b == Teuchos::null))
579  return false;
580  if (a != Teuchos::null && b != Teuchos::null && !a->isSameSize(*b))
581  return false;
582  }
583  return true;
584 }
585 
586 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
587 std::string
589  description() const {
590  return std::string("BlockedMultiVector");
591 }
592 
593 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
595  describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const {
596  out << description() << std::endl;
597  for (size_t r = 0; r < map_->getNumMaps(); r++)
598  getMultiVector(r)->describe(out, verbLevel);
599 }
600 
601 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
603  replaceMap(const RCP<const Map>& map) {
604  XPETRA_MONITOR("BlockedMultiVector::replaceMap");
605  RCP<const BlockedMap> bmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map);
606  if (bmap.is_null() == true) {
607  // if this has more than 1 sub blocks but "map" is not a blocked map, they are very likely not compatible
608  if (this->getBlockedMap()->getNumMaps() > 1) {
610  "BlockedMultiVector::replaceMap: map is not of type BlockedMap. General implementation not available, yet.");
611  TEUCHOS_UNREACHABLE_RETURN();
612  }
613  // special case: this is a blocked map with only one block
614  // TODO add more debug check (especially for Thyra mode)
615  std::vector<Teuchos::RCP<const Map>> subMaps(1, map);
616  map_ = Teuchos::rcp(new BlockedMap(map, subMaps, this->getBlockedMap()->getThyraMode()));
617  this->getMultiVector(0)->replaceMap(map);
618  return;
619  }
620  RCP<const BlockedMap> mybmap = Teuchos::rcp_dynamic_cast<const BlockedMap>(map_);
621 
623  mybmap->getThyraMode() != bmap->getThyraMode(), Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::replaceMap: inconsistent Thyra mode");
624  map_ = bmap;
625  for (size_t r = 0; r < map_->getNumMaps(); r++)
626  getMultiVector(r)->replaceMap(bmap->getMap(r, map_->getThyraMode()));
627 }
628 
629 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
632  const Import& /* importer */,
633  CombineMode /* CM */) {
634  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doImport: Not supported by BlockedMultiVector.");
635 }
636 
637 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
640  const Import& /* importer */,
641  CombineMode /* CM */) {
642  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doExport: Not supported by BlockedMultiVector.");
643 }
644 
645 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
648  const Export& /* exporter */,
649  CombineMode /* CM */) {
650  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doImport: Not supported by BlockedMultiVector.");
651 }
652 
653 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
656  const Export& /* exporter */,
657  CombineMode /* CM */) {
658  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::doExport: Not supported by BlockedMultiVector.");
659 }
660 
661 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
663  setSeed(unsigned int seed) {
664  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
665  getMultiVector(r)->setSeed(seed);
666  }
667 }
668 
669 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
671  randomize(bool bUseXpetraImplementation) {
672  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
673  getMultiVector(r)->randomize(bUseXpetraImplementation);
674  }
675 }
676 
677 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
679  randomize(const Scalar& minVal, const Scalar& maxVal, bool bUseXpetraImplementation) {
680  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
681  getMultiVector(r)->randomize(minVal, maxVal, bUseXpetraImplementation);
682  }
683 }
684 
685 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
689 }
690 
691 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
693  Xpetra_randomize(const Scalar& minVal, const Scalar& maxVal) {
695 }
696 
697 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
698 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>
700  getMap() const {
701  XPETRA_MONITOR("BlockedMultiVector::getMap");
702  return map_;
703 }
704 
705 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
706 Teuchos::RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>>
708  getBlockedMap() const {
709  XPETRA_MONITOR("BlockedMultiVector::getBlockedMap");
710  return map_;
711 }
712 
713 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
714 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
716  getMultiVector(size_t r) const {
717  XPETRA_MONITOR("BlockedMultiVector::getMultiVector(r)");
718  TEUCHOS_TEST_FOR_EXCEPTION(r > map_->getNumMaps(),
719  std::out_of_range,
720  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
721  << " partial blocks.");
722  return vv_[r];
723 }
724 
725 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
726 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
728  getMultiVector(size_t r, bool bThyraMode) const {
729  XPETRA_MONITOR("BlockedMultiVector::getMultiVector(r,bThyraMode)");
730  TEUCHOS_TEST_FOR_EXCEPTION(r > map_->getNumMaps(),
731  std::out_of_range,
732  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
733  << " partial blocks.");
735  map_->getThyraMode() != bThyraMode, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::getMultiVector: inconsistent Thyra mode");
736  (void)bThyraMode; // avoid unused parameter warning when HAVE_XPETRA_DEBUG isn't defined
737  return vv_[r];
738 }
739 
740 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
744  bool bThyraMode) {
745  // The map of the MultiVector should be the same as the stored submap
746  // In thyra mode the vectors should live on the thyra maps
747  // in xpetra mode the should live in the xpetra maps
748  // that should be also ok in the nested case for thyra (if the vectors are distributed accordingly)
749  XPETRA_MONITOR("BlockedMultiVector::setMultiVector");
750  XPETRA_TEST_FOR_EXCEPTION(r >= map_->getNumMaps(),
751  std::out_of_range,
752  "Error, r = " << r << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps() << " partial blocks.");
753  XPETRA_TEST_FOR_EXCEPTION(numVectors_ != v->getNumVectors(),
755  "The BlockedMultiVectors expects " << getNumVectors() << " vectors. The provided partial multivector has "
756  << v->getNumVectors() << " vectors.");
758  map_->getThyraMode() != bThyraMode, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::setMultiVector: inconsistent Thyra mode");
759  (void)bThyraMode; // avoid unused parameter warning when HAVE_XPETRA_DEBUG isn't defined
760  Teuchos::RCP<MultiVector> vv = Teuchos::rcp_const_cast<MultiVector>(v);
761  TEUCHOS_TEST_FOR_EXCEPTION(vv == Teuchos::null, Xpetra::Exceptions::RuntimeError, "Partial vector must not be Teuchos::null");
762  vv_[r] = vv;
763 }
764 
765 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
766 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
768  Merge() const {
769  XPETRA_MONITOR("BlockedMultiVector::Merge");
770  using Teuchos::RCP;
771 
772  RCP<MultiVector> v = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getFullMap(), getNumVectors());
773  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
774  RCP<MultiVector> vi = getMultiVector(r);
775  RCP<BlockedMultiVector> bvi = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vi);
776  if (bvi.is_null() == true) {
777  this->InsertVector(vi, r, v, map_->getThyraMode());
778  } else {
779  RCP<MultiVector> mvi = bvi->Merge();
780  this->InsertVector(mvi, r, v, map_->getThyraMode());
781  }
782  }
783 
784  // TODO plausibility checks
785 
786  return v;
787 }
788 
789 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
792  Teuchos::RCP<const MultiVector> rcpRhs = Teuchos::rcpFromRef(rhs);
793  Teuchos::RCP<const BlockedMultiVector> bRhs = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpRhs);
794  if (bRhs == Teuchos::null)
795  throw Xpetra::Exceptions::RuntimeError("BlockedMultiVector::assign: argument is not a blocked multi vector.");
796 
797  map_ = Teuchos::rcp(new BlockedMap(*(bRhs->getBlockedMap())));
798  vv_ = std::vector<Teuchos::RCP<MultiVector>>(map_->getNumMaps());
799  for (size_t r = 0; r < map_->getNumMaps(); ++r) {
800  // extract source vector (is of type MultiVector or BlockedMultiVector)
801  RCP<MultiVector> src = bRhs->getMultiVector(r, map_->getThyraMode());
802 
803  // create new (empty) multivector (is of type MultiVector or BlockedMultiVector)
805  map_->getMap(r, bRhs->getBlockedMap()->getThyraMode()), rcpRhs->getNumVectors(), true);
806 
807  // check type of source and target vector
808  RCP<BlockedMultiVector> bsrc = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(src);
809  RCP<BlockedMultiVector> bvv = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vv);
810  if (bsrc.is_null() == true && bvv.is_null() == true) {
811  *vv = *src; // deep copy
812  } else if (bsrc.is_null() == true && bvv.is_null() == false) {
813  // special case: source vector is a merged MultiVector but target vector is blocked
814  *vv = *src; // deep copy (is this a problem???)
815  } else if (bsrc.is_null() == false && bvv.is_null() == true) {
816  // special case: source vector is blocked but target vector is a merged MultiVector
817  // This is a problem and only works if bsrc has only one block
818  if (bsrc->getBlockedMap()->getNumMaps() > 1) {
820  "BlockedMultiVector::assign: source vector is of type BlockedMultiVector (with more than "
821  "1 blocks) and target is a MultiVector.");
822  TEUCHOS_UNREACHABLE_RETURN();
823  }
824  RCP<MultiVector> ssrc = bsrc->getMultiVector(0, map_->getThyraMode());
825  XPETRA_TEST_FOR_EXCEPTION(ssrc.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedMultiVector::assign: cannot extract vector");
826  XPETRA_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<BlockedMultiVector>(ssrc) != Teuchos::null,
828  "BlockedMultiVector::assign: sub block must not be of type BlockedMultiVector.");
829  *vv = *ssrc;
830  } else {
831  // this should work (no exception necessary, i guess)
832  XPETRA_TEST_FOR_EXCEPTION(bsrc->getBlockedMap()->getNumMaps() != bvv->getBlockedMap()->getNumMaps(),
834  "BlockedMultiVector::assign: source and target are BlockedMultiVectors with a different number of submaps.");
835  *vv = *src; // deep copy
836  }
837  vv_[r] = vv;
838  }
839  numVectors_ = rcpRhs->getNumVectors();
840 }
841 
842 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
845  size_t block,
847  ExtractVector(*full, block, *partial);
848 }
849 
850 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
851 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
853  size_t block,
855  ExtractVector(*full, block, *partial);
856 }
857 
858 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
859 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
860 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
862  size_t block,
863  bool bThyraMode) const {
864  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
865  std::out_of_range,
866  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
867  << " partial blocks.");
869  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
870  RCP<const BlockedMultiVector> bfull = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(full);
871  if (bfull.is_null() == true) {
872  // standard case: full is not of type BlockedMultiVector
873  // first extract partial vector from full vector (using xpetra style GIDs)
874  const RCP<MultiVector> vv =
875  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getMap(block, false), full->getNumVectors(), false);
876  // if(bThyraMode == false) {
877  // ExtractVector(*full, block, *vv);
878  // return vv;
879  //} else {
880  RCP<const Map> oldThyMapFull = full->getMap(); // temporarely store map of full
881  RCP<MultiVector> rcpNonConstFull = Teuchos::rcp_const_cast<MultiVector>(full);
882  rcpNonConstFull->replaceMap(map_->getImporter(block)->getSourceMap());
883  ExtractVector(*rcpNonConstFull, block, *vv);
884  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
885  Xpetra::Exceptions::RuntimeError,
886  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been "
887  "created using Thyra-style numbered submaps.");
888  if (bThyraMode == true)
889  vv->replaceMap(map_->getMap(block, true)); // switch to Thyra-style map
890  rcpNonConstFull->replaceMap(oldThyMapFull);
891  return vv;
892  //}
893  } else {
894  // special case: full is of type BlockedMultiVector
895  XPETRA_TEST_FOR_EXCEPTION(map_->getNumMaps() != bfull->getBlockedMap()->getNumMaps(),
896  Xpetra::Exceptions::RuntimeError,
897  "ExtractVector: Number of blocks in map extractor is " << map_->getNumMaps() << " but should be "
898  << bfull->getBlockedMap()->getNumMaps()
899  << " (number of blocks in BlockedMultiVector)");
900  return bfull->getMultiVector(block, bThyraMode);
901  }
902 }
903 
904 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
905 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
906 BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
908  size_t block,
909  bool bThyraMode) const {
910  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
911  std::out_of_range,
912  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
913  << " partial blocks.");
915  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
916  RCP<BlockedMultiVector> bfull = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(full);
917  if (bfull.is_null() == true) {
918  // standard case: full is not of type BlockedMultiVector
919  // first extract partial vector from full vector (using xpetra style GIDs)
920  const RCP<MultiVector> vv =
921  Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(map_->getMap(block, false), full->getNumVectors(), false);
922  // if(bThyraMode == false) {
923  // ExtractVector(*full, block, *vv);
924  // return vv;
925  //} else {
926  RCP<const Map> oldThyMapFull = full->getMap(); // temporarely store map of full
927  full->replaceMap(map_->getImporter(block)->getSourceMap());
928  ExtractVector(*full, block, *vv);
929  TEUCHOS_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
930  Xpetra::Exceptions::RuntimeError,
931  "MapExtractor::ExtractVector: ExtractVector in Thyra-style numbering only possible if MapExtractor has been "
932  "created using Thyra-style numbered submaps.");
933  if (bThyraMode == true)
934  vv->replaceMap(map_->getMap(block, true)); // switch to Thyra-style map
935  full->replaceMap(oldThyMapFull);
936  return vv;
937  //}
938  } else {
939  // special case: full is of type BlockedMultiVector
940  XPETRA_TEST_FOR_EXCEPTION(map_->getNumMaps() != bfull->getBlockedMap()->getNumMaps(),
941  Xpetra::Exceptions::RuntimeError,
942  "ExtractVector: Number of blocks in map extractor is " << map_->getNumMaps() << " but should be "
943  << bfull->getBlockedMap()->getNumMaps()
944  << " (number of blocks in BlockedMultiVector)");
945  return bfull->getMultiVector(block, bThyraMode);
946  }
947 }
948 
949 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
950 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
952  size_t block,
954  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
955  std::out_of_range,
956  "ExtractVector: Error, block = " << block << " is too big. The BlockedMultiVector only contains " << map_->getNumMaps()
957  << " partial blocks.");
958  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: maps_[" << block << "] is null");
959  partial.doImport(full, *(map_->getImporter(block)), Xpetra::INSERT);
960 }
961 
962 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
965  size_t block,
967  bool bThyraMode) const {
968  XPETRA_TEST_FOR_EXCEPTION(block >= map_->getNumMaps(),
969  std::out_of_range,
970  "ExtractVector: Error, block = " << block << " is too big. The MapExtractor only contains " << map_->getNumMaps()
971  << " partial blocks.");
973  map_->getMap(block, false) == null, Xpetra::Exceptions::RuntimeError, "ExtractVector: map_->getmap(" << block << ",false) is null");
974  XPETRA_TEST_FOR_EXCEPTION(map_->getThyraMode() == false && bThyraMode == true,
975  Xpetra::Exceptions::RuntimeError,
976  "MapExtractor::InsertVector: InsertVector in Thyra-style numbering only possible if MapExtractor has been created "
977  "using Thyra-style numbered submaps.");
978  if (bThyraMode) {
979  // NOTE: the importer objects in the BlockedMap are always using Xpetra GIDs (or Thyra style Xpetra GIDs)
980  // The source map corresponds to the full map (in Xpetra GIDs) starting with GIDs from zero. The GIDs are consecutive in Thyra mode
981  // The target map is the partial map (in the corresponding Xpetra GIDs)
982 
983  // TODO can we skip the Export call in special cases (i.e. Src = Target map, same length, etc...)
984 
985  // store original GIDs (could be Thyra GIDs)
986  RCP<const MultiVector> rcpPartial = Teuchos::rcpFromRef(partial);
987  RCP<MultiVector> rcpNonConstPartial = Teuchos::rcp_const_cast<MultiVector>(rcpPartial);
988  RCP<const Map> oldThyMapPartial = rcpNonConstPartial->getMap(); // temporarely store map of partial
989  RCP<const Map> oldThyMapFull = full.getMap(); // temporarely store map of full
990 
991  // check whether getMap(block,false) is identical to target map of importer
992  // XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block,false)->isSameAs(*(map_->getImporter(block)->getTargetMap()))==false,
993  // Xpetra::Exceptions::RuntimeError,
994  // "MapExtractor::InsertVector: InsertVector in Thyra-style mode: Xpetra GIDs of partial vector are not identical to target Map
995  // of Importer. This should not be.");
996 
997  // XPETRA_TEST_FOR_EXCEPTION(full.getMap()->isSameAs(*(map_->getImporter(block)->getSourceMap()))==false,
998  // Xpetra::Exceptions::RuntimeError,
999  // "MapExtractor::InsertVector: InsertVector in Thyra-style mode: Xpetra GIDs of full vector are not identical to source Map of
1000  // Importer. This should not be.");
1001 
1002  rcpNonConstPartial->replaceMap(map_->getMap(block, false)); // temporarely switch to xpetra-style map
1003  full.replaceMap(map_->getImporter(block)->getSourceMap()); // temporarely switch to Xpetra GIDs
1004 
1005  // do the Export
1006  full.doExport(*rcpNonConstPartial, *(map_->getImporter(block)), Xpetra::INSERT);
1007 
1008  // switch back to original maps
1009  full.replaceMap(oldThyMapFull); // reset original map (Thyra GIDs)
1010  rcpNonConstPartial->replaceMap(oldThyMapPartial); // change map back to original map
1011  } else {
1012  // Xpetra style numbering
1013  full.doExport(partial, *(map_->getImporter(block)), Xpetra::INSERT);
1014  }
1015 }
1016 
1017 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1020  size_t block,
1022  bool bThyraMode) const {
1023  RCP<Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bfull =
1025  if (bfull.is_null() == true)
1026  InsertVector(*partial, block, *full, bThyraMode);
1027  else {
1028  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "InsertVector: maps_[" << block << "] is null");
1029 
1030 #if 0
1031  // WCMCLEN - ETI: MultiVector doesn't have a setMultiVector method,
1032  // WCMCLEN - ETI: but BlockedMultiVector does... should this be bfull->...?
1033  full->setMultiVector(block, partial, bThyraMode);
1034 #else
1035  throw Xpetra::Exceptions::RuntimeError("MultiVector::setMultiVector() is not implemented.");
1036 #endif
1037  }
1038 }
1039 
1040 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1041 void BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1043  size_t block,
1045  bool bThyraMode) const {
1046  RCP<Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bfull =
1048  if (bfull.is_null() == true)
1049  InsertVector(*partial, block, *full, bThyraMode);
1050  else {
1051  XPETRA_TEST_FOR_EXCEPTION(map_->getMap(block) == null, Xpetra::Exceptions::RuntimeError, "InsertVector: maps_[" << block << "] is null");
1052  bfull->setMultiVector(block, partial, bThyraMode);
1053  }
1054 }
1055 
1056 } // namespace Xpetra
1057 
1058 #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.