Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_InterlacedTpetra.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include "Teko_InterlacedTpetra.hpp"
48 #include "Tpetra_Import.hpp"
49 
50 #include <vector>
51 
52 using Teuchos::RCP;
53 using Teuchos::rcp;
54 
55 namespace Teko {
56 namespace TpetraHelpers {
57 namespace Strided {
58 
59 // this assumes that there are numGlobals with numVars each interlaced
60 // i.e. for numVars = 2 (u,v) then the vector is
61 // [u_0,v_0,u_1,v_1,u_2,v_2, ..., u_(numGlobals-1),v_(numGlobals-1)]
62 void buildSubMaps(GO numGlobals, int numVars, const Teuchos::Comm<int>& comm,
63  std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps) {
64  std::vector<int> vars;
65 
66  // build vector describing the sub maps
67  for (int i = 0; i < numVars; i++) vars.push_back(1);
68 
69  // build all the submaps
70  buildSubMaps(numGlobals, vars, comm, subMaps);
71 }
72 
73 // build maps to make other conversions
74 void buildSubMaps(const Tpetra::Map<LO, GO, NT>& globalMap, const std::vector<int>& vars,
75  const Teuchos::Comm<int>& comm,
76  std::vector<std::pair<int, Teuchos::RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps) {
77  buildSubMaps(globalMap.getGlobalNumElements(), globalMap.getLocalNumElements(),
78  globalMap.getMinGlobalIndex(), vars, comm, subMaps);
79 }
80 
81 // build maps to make other conversions
82 void buildSubMaps(GO numGlobals, const std::vector<int>& vars, const Teuchos::Comm<int>& comm,
83  std::vector<std::pair<int, Teuchos::RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps) {
84  std::vector<int>::const_iterator varItr;
85 
86  // compute total number of variables
87  int numGlobalVars = 0;
88  for (varItr = vars.begin(); varItr != vars.end(); ++varItr) numGlobalVars += *varItr;
89 
90  // must be an even number of globals
91  TEUCHOS_ASSERT((numGlobals % numGlobalVars) == 0);
92 
93  Tpetra::Map<LO, GO, NT> sampleMap(numGlobals / numGlobalVars, 0, rcpFromRef(comm));
94 
95  buildSubMaps(numGlobals, numGlobalVars * sampleMap.getLocalNumElements(),
96  numGlobalVars * sampleMap.getMinGlobalIndex(), vars, comm, subMaps);
97 }
98 
99 // build maps to make other conversions
100 void buildSubMaps(GO numGlobals, LO numMyElements, GO minMyGID, const std::vector<int>& vars,
101  const Teuchos::Comm<int>& comm,
102  std::vector<std::pair<int, Teuchos::RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps) {
103  std::vector<int>::const_iterator varItr;
104 
105  // compute total number of variables
106  int numGlobalVars = 0;
107  for (varItr = vars.begin(); varItr != vars.end(); ++varItr) numGlobalVars += *varItr;
108 
109  // must be an even number of globals
110  TEUCHOS_ASSERT((numGlobals % numGlobalVars) == 0);
111  TEUCHOS_ASSERT((numMyElements % numGlobalVars) == 0);
112  TEUCHOS_ASSERT((minMyGID % numGlobalVars) == 0);
113 
114  LO numBlocks = numMyElements / numGlobalVars;
115  GO minBlockID = minMyGID / numGlobalVars;
116 
117  subMaps.clear();
118 
119  // index into local block in strided map
120  GO blockOffset = 0;
121  for (varItr = vars.begin(); varItr != vars.end(); ++varItr) {
122  LO numLocalVars = *varItr;
123  GO numAllElmts = numLocalVars * numGlobals / numGlobalVars;
124 #ifndef NDEBUG
125  LO numMyElmts = numLocalVars * numBlocks;
126 #endif
127 
128  // create global arrays describing the as of yet uncreated maps
129  std::vector<GO> subGlobals;
130  std::vector<GO> contigGlobals; // the contiguous globals
131 
132  // loop over each block of variables
133  LO count = 0;
134  for (LO blockNum = 0; blockNum < numBlocks; blockNum++) {
135  // loop over each local variable in the block
136  for (LO local = 0; local < numLocalVars; ++local) {
137  // global block number = minGID+blockNum
138  // block begin global id = numGlobalVars*(minGID+blockNum)
139  // global id block offset = blockOffset+local
140  subGlobals.push_back((minBlockID + blockNum) * numGlobalVars + blockOffset + local);
141 
142  // also build the contiguous IDs
143  contigGlobals.push_back(numLocalVars * minBlockID + count);
144  count++;
145  }
146  }
147 
148  // sanity check
149  assert((size_t)numMyElmts == subGlobals.size());
150 
151  // create the map with contiguous elements and the map with global elements
152  RCP<Tpetra::Map<LO, GO, NT> > subMap = rcp(new Tpetra::Map<LO, GO, NT>(
153  numAllElmts, Teuchos::ArrayView<GO>(subGlobals), 0, rcpFromRef(comm)));
154  RCP<Tpetra::Map<LO, GO, NT> > contigMap = rcp(new Tpetra::Map<LO, GO, NT>(
155  numAllElmts, Teuchos::ArrayView<GO>(contigGlobals), 0, rcpFromRef(comm)));
156 
157  Teuchos::set_extra_data(contigMap, "contigMap", Teuchos::inOutArg(subMap));
158  subMaps.push_back(std::make_pair(numLocalVars, subMap));
159 
160  // update the block offset
161  blockOffset += numLocalVars;
162  }
163 }
164 
165 void buildExportImport(const Tpetra::Map<LO, GO, NT>& baseMap,
166  const std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps,
167  std::vector<RCP<Tpetra::Export<LO, GO, NT> > >& subExport,
168  std::vector<RCP<Tpetra::Import<LO, GO, NT> > >& subImport) {
169  std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >::const_iterator mapItr;
170 
171  // build importers and exporters
172  for (mapItr = subMaps.begin(); mapItr != subMaps.end(); ++mapItr) {
173  // exctract basic map
174  const Tpetra::Map<LO, GO, NT>& map = *(mapItr->second);
175 
176  // add new elements to vectors
177  subImport.push_back(rcp(new Tpetra::Import<LO, GO, NT>(rcpFromRef(baseMap), rcpFromRef(map))));
178  subExport.push_back(rcp(new Tpetra::Export<LO, GO, NT>(rcpFromRef(map), rcpFromRef(baseMap))));
179  }
180 }
181 
182 void buildSubVectors(const std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps,
183  std::vector<RCP<Tpetra::MultiVector<ST, LO, GO, NT> > >& subVectors,
184  int count) {
185  std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >::const_iterator mapItr;
186 
187  // build vectors
188  for (mapItr = subMaps.begin(); mapItr != subMaps.end(); ++mapItr) {
189  // exctract basic map
190  const Tpetra::Map<LO, GO, NT>& map =
191  *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(mapItr->second, "contigMap"));
192 
193  // add new elements to vectors
194  RCP<Tpetra::MultiVector<ST, LO, GO, NT> > mv =
195  rcp(new Tpetra::MultiVector<ST, LO, GO, NT>(rcpFromRef(map), count));
196  Teuchos::set_extra_data(mapItr->second, "globalMap", Teuchos::inOutArg(mv));
197  subVectors.push_back(mv);
198  }
199 }
200 
201 void associateSubVectors(
202  const std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps,
203  std::vector<RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > >& subVectors) {
204  std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >::const_iterator mapItr;
205  std::vector<RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > >::iterator vecItr;
206 
207  TEUCHOS_ASSERT(subMaps.size() == subVectors.size());
208 
209  // associate the sub vectors with the subMaps
210  for (mapItr = subMaps.begin(), vecItr = subVectors.begin(); mapItr != subMaps.end();
211  ++mapItr, ++vecItr)
212  Teuchos::set_extra_data(mapItr->second, "globalMap", Teuchos::inOutArg(*vecItr),
213  Teuchos::POST_DESTROY, false);
214 }
215 
216 // build a single subblock Epetra_CrsMatrix
217 RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > buildSubBlock(
218  int i, int j, const RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> >& A,
219  const std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps) {
220  // get the number of variables families
221  int numVarFamily = subMaps.size();
222 
223  TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
224  TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
225 
226  const Tpetra::Map<LO, GO, NT>& gRowMap = *subMaps[i].second;
227  const Tpetra::Map<LO, GO, NT>& rowMap =
228  *Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(subMaps[i].second, "contigMap");
229  const Tpetra::Map<LO, GO, NT>& colMap =
230  *Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(subMaps[j].second, "contigMap");
231  int colFamilyCnt = subMaps[j].first;
232 
233  // compute the number of global variables
234  // and the row and column block offset
235  GO numGlobalVars = 0;
236  GO rowBlockOffset = 0;
237  GO colBlockOffset = 0;
238  for (int k = 0; k < numVarFamily; k++) {
239  numGlobalVars += subMaps[k].first;
240 
241  // compute block offsets
242  if (k < i) rowBlockOffset += subMaps[k].first;
243  if (k < j) colBlockOffset += subMaps[k].first;
244  }
245 
246  // copy all global rows to here
247  Tpetra::Import<LO, GO, NT> import(A->getRowMap(), rcpFromRef(gRowMap));
248  Tpetra::CrsMatrix<ST, LO, GO, NT> localA(rcpFromRef(gRowMap), 0);
249  localA.doImport(*A, import, Tpetra::INSERT);
250 
251  // get entry information
252  LO numMyRows = rowMap.getLocalNumElements();
253  LO maxNumEntries = A->getGlobalMaxNumRowEntries();
254 
255  // for extraction
256  auto indices = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_global_inds_host_view_type(
257  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), maxNumEntries);
258  auto values = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_values_host_view_type(
259  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), maxNumEntries);
260 
261  // for counting row sizes
262  std::vector<size_t> numEntriesPerRow(numMyRows, 0);
263 
264  const size_t invalid = Teuchos::OrdinalTraits<size_t>::invalid();
265 
266  // Count the sizes of each row, using same logic as insertion below
267  for (LO localRow = 0; localRow < numMyRows; localRow++) {
268  size_t numEntries = invalid;
269  GO globalRow = gRowMap.getGlobalElement(localRow);
270  GO contigRow = rowMap.getGlobalElement(localRow);
271 
272  TEUCHOS_ASSERT(globalRow >= 0);
273  TEUCHOS_ASSERT(contigRow >= 0);
274 
275  // extract a global row copy
276  localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
277  LO numOwnedCols = 0;
278  for (size_t localCol = 0; localCol < numEntries; localCol++) {
279  GO globalCol = indices(localCol);
280 
281  // determinate which block this column ID is in
282  int block = globalCol / numGlobalVars;
283 
284  bool inFamily = true;
285 
286  // test the beginning of the block
287  inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
288  inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
289 
290  // is this column in the variable family
291  if (inFamily) {
292  numOwnedCols++;
293  }
294  }
295  numEntriesPerRow[localRow] += numOwnedCols;
296  }
297 
298  RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > mat = rcp(new Tpetra::CrsMatrix<ST, LO, GO, NT>(
299  rcpFromRef(rowMap), Teuchos::ArrayView<const size_t>(numEntriesPerRow)));
300 
301  // for insertion
302  std::vector<GO> colIndices(maxNumEntries);
303  std::vector<ST> colValues(maxNumEntries);
304 
305  // insert each row into subblock
306  // let FillComplete handle column distribution
307  for (LO localRow = 0; localRow < numMyRows; localRow++) {
308  size_t numEntries = invalid;
309  GO globalRow = gRowMap.getGlobalElement(localRow);
310  GO contigRow = rowMap.getGlobalElement(localRow);
311 
312  TEUCHOS_ASSERT(globalRow >= 0);
313  TEUCHOS_ASSERT(contigRow >= 0);
314 
315  // extract a global row copy
316  localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
317  LO numOwnedCols = 0;
318  for (size_t localCol = 0; localCol < numEntries; localCol++) {
319  GO globalCol = indices(localCol);
320 
321  // determinate which block this column ID is in
322  int block = globalCol / numGlobalVars;
323 
324  bool inFamily = true;
325 
326  // test the beginning of the block
327  inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
328  inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
329 
330  // is this column in the variable family
331  if (inFamily) {
332  GO familyOffset = globalCol - (block * numGlobalVars + colBlockOffset);
333 
334  colIndices[numOwnedCols] = block * colFamilyCnt + familyOffset;
335  colValues[numOwnedCols] = values(localCol);
336 
337  numOwnedCols++;
338  }
339  }
340 
341  // insert it into the new matrix
342  colIndices.resize(numOwnedCols);
343  colValues.resize(numOwnedCols);
344  mat->insertGlobalValues(contigRow, Teuchos::ArrayView<GO>(colIndices),
345  Teuchos::ArrayView<ST>(colValues));
346  colIndices.resize(maxNumEntries);
347  colValues.resize(maxNumEntries);
348  }
349 
350  // fill it and automagically optimize the storage
351  mat->fillComplete(rcpFromRef(colMap), rcpFromRef(rowMap));
352 
353  return mat;
354 }
355 
356 // rebuild a single subblock Epetra_CrsMatrix
357 void rebuildSubBlock(int i, int j, const RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> >& A,
358  const std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >& subMaps,
359  Tpetra::CrsMatrix<ST, LO, GO, NT>& mat) {
360  // get the number of variables families
361  int numVarFamily = subMaps.size();
362 
363  TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
364  TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
365  TEUCHOS_ASSERT(mat.isFillComplete());
366 
367  const Tpetra::Map<LO, GO, NT>& gRowMap = *subMaps[i].second;
368  const Tpetra::Map<LO, GO, NT>& rowMap =
369  *Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(subMaps[i].second, "contigMap");
370  const Tpetra::Map<LO, GO, NT>& colMap =
371  *Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(subMaps[j].second, "contigMap");
372  int colFamilyCnt = subMaps[j].first;
373 
374  // compute the number of global variables
375  // and the row and column block offset
376  GO numGlobalVars = 0;
377  GO rowBlockOffset = 0;
378  GO colBlockOffset = 0;
379  for (int k = 0; k < numVarFamily; k++) {
380  numGlobalVars += subMaps[k].first;
381 
382  // compute block offsets
383  if (k < i) rowBlockOffset += subMaps[k].first;
384  if (k < j) colBlockOffset += subMaps[k].first;
385  }
386 
387  // copy all global rows to here
388  Tpetra::Import<LO, GO, NT> import(A->getRowMap(), rcpFromRef(gRowMap));
389  Tpetra::CrsMatrix<ST, LO, GO, NT> localA(rcpFromRef(gRowMap), 0);
390  localA.doImport(*A, import, Tpetra::INSERT);
391 
392  // clear out the old matrix
393  mat.resumeFill();
394  mat.setAllToScalar(0.0);
395 
396  // get entry information
397  LO numMyRows = rowMap.getLocalNumElements();
398  GO maxNumEntries = A->getGlobalMaxNumRowEntries();
399 
400  // for extraction
401  auto indices = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_global_inds_host_view_type(
402  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), maxNumEntries);
403  auto values = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_values_host_view_type(
404  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), maxNumEntries);
405 
406  // for insertion
407  std::vector<GO> colIndices(maxNumEntries);
408  std::vector<ST> colValues(maxNumEntries);
409 
410  const size_t invalid = Teuchos::OrdinalTraits<size_t>::invalid();
411 
412  // insert each row into subblock
413  // let FillComplete handle column distribution
414  for (LO localRow = 0; localRow < numMyRows; localRow++) {
415  size_t numEntries = invalid;
416  GO globalRow = gRowMap.getGlobalElement(localRow);
417  GO contigRow = rowMap.getGlobalElement(localRow);
418 
419  TEUCHOS_ASSERT(globalRow >= 0);
420  TEUCHOS_ASSERT(contigRow >= 0);
421 
422  // extract a global row copy
423  localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
424 
425  LO numOwnedCols = 0;
426  for (size_t localCol = 0; localCol < numEntries; localCol++) {
427  GO globalCol = indices(localCol);
428 
429  // determinate which block this column ID is in
430  int block = globalCol / numGlobalVars;
431 
432  bool inFamily = true;
433 
434  // test the beginning of the block
435  inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
436  inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
437 
438  // is this column in the variable family
439  if (inFamily) {
440  GO familyOffset = globalCol - (block * numGlobalVars + colBlockOffset);
441 
442  colIndices[numOwnedCols] = block * colFamilyCnt + familyOffset;
443  colValues[numOwnedCols] = values(localCol);
444 
445  numOwnedCols++;
446  }
447  }
448 
449  // insert it into the new matrix
450  colIndices.resize(numOwnedCols);
451  colValues.resize(numOwnedCols);
452  mat.sumIntoGlobalValues(contigRow, Teuchos::ArrayView<GO>(colIndices),
453  Teuchos::ArrayView<ST>(colValues));
454  colIndices.resize(maxNumEntries);
455  colValues.resize(maxNumEntries);
456  }
457  mat.fillComplete(rcpFromRef(colMap), rcpFromRef(rowMap));
458 }
459 
460 // collect subvectors into a single global vector
461 void many2one(Tpetra::MultiVector<ST, LO, GO, NT>& one,
462  const std::vector<RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > >& many,
463  const std::vector<RCP<Tpetra::Export<LO, GO, NT> > >& subExport) {
464  // std::vector<RCP<const Epetra_Vector> >::const_iterator vecItr;
465  std::vector<RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > >::const_iterator vecItr;
466  std::vector<RCP<Tpetra::Export<LO, GO, NT> > >::const_iterator expItr;
467 
468  // using Exporters fill the empty vector from the sub-vectors
469  for (vecItr = many.begin(), expItr = subExport.begin(); vecItr != many.end();
470  ++vecItr, ++expItr) {
471  // for ease of access to the source
472  RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > srcVec = *vecItr;
473 
474  // extract the map with global indicies from the current vector
475  const Tpetra::Map<LO, GO, NT>& globalMap =
476  *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(srcVec, "globalMap"));
477 
478  // build the export vector as a view of the destination
479  GO lda = srcVec->getStride();
480  GO srcSize = srcVec->getGlobalLength() * srcVec->getNumVectors();
481  std::vector<ST> srcArray(srcSize);
482  Teuchos::ArrayView<ST> srcVals(srcArray);
483  srcVec->get1dCopy(srcVals, lda);
484  Tpetra::MultiVector<ST, LO, GO, NT> exportVector(rcpFromRef(globalMap), srcVals, lda,
485  srcVec->getNumVectors());
486 
487  // perform the export
488  one.doExport(exportVector, **expItr, Tpetra::INSERT);
489  }
490 }
491 
492 // distribute one global vector into a many subvectors
493 void one2many(std::vector<RCP<Tpetra::MultiVector<ST, LO, GO, NT> > >& many,
494  const Tpetra::MultiVector<ST, LO, GO, NT>& single,
495  const std::vector<RCP<Tpetra::Import<LO, GO, NT> > >& subImport) {
496  // std::vector<RCP<Epetra_Vector> >::const_iterator vecItr;
497  std::vector<RCP<Tpetra::MultiVector<ST, LO, GO, NT> > >::const_iterator vecItr;
498  std::vector<RCP<Tpetra::Import<LO, GO, NT> > >::const_iterator impItr;
499 
500  // using Importers fill the sub vectors from the mama vector
501  for (vecItr = many.begin(), impItr = subImport.begin(); vecItr != many.end();
502  ++vecItr, ++impItr) {
503  // for ease of access to the destination
504  RCP<Tpetra::MultiVector<ST, LO, GO, NT> > destVec = *vecItr;
505 
506  // extract the map with global indicies from the current vector
507  const Tpetra::Map<LO, GO, NT>& globalMap =
508  *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(destVec, "globalMap"));
509 
510  // build the import vector as a view on the destination
511  GO destLDA = destVec->getStride();
512  GO destSize = destVec->getGlobalLength() * destVec->getNumVectors();
513  std::vector<ST> destArray(destSize);
514  Teuchos::ArrayView<ST> destVals(destArray);
515  destVec->get1dCopy(destVals, destLDA);
516  Tpetra::MultiVector<ST, LO, GO, NT> importVector(rcpFromRef(globalMap), destVals, destLDA,
517  destVec->getNumVectors());
518 
519  // perform the import
520  importVector.doImport(single, **impItr, Tpetra::INSERT);
521 
522  Tpetra::Import<LO, GO, NT> importer(destVec->getMap(), destVec->getMap());
523  importVector.replaceMap(destVec->getMap());
524  destVec->doImport(importVector, importer, Tpetra::INSERT);
525  }
526 }
527 
528 } // namespace Strided
529 } // namespace TpetraHelpers
530 } // end namespace Teko