47 #include "Teko_InterlacedTpetra.hpp"
48 #include "Tpetra_Import.hpp"
56 namespace TpetraHelpers {
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;
67 for (
int i = 0; i < numVars; i++) vars.push_back(1);
70 buildSubMaps(numGlobals, vars, comm, subMaps);
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);
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;
87 int numGlobalVars = 0;
88 for (varItr = vars.begin(); varItr != vars.end(); ++varItr) numGlobalVars += *varItr;
91 TEUCHOS_ASSERT((numGlobals % numGlobalVars) == 0);
93 Tpetra::Map<LO, GO, NT> sampleMap(numGlobals / numGlobalVars, 0, rcpFromRef(comm));
95 buildSubMaps(numGlobals, numGlobalVars * sampleMap.getLocalNumElements(),
96 numGlobalVars * sampleMap.getMinGlobalIndex(), vars, comm, subMaps);
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;
106 int numGlobalVars = 0;
107 for (varItr = vars.begin(); varItr != vars.end(); ++varItr) numGlobalVars += *varItr;
110 TEUCHOS_ASSERT((numGlobals % numGlobalVars) == 0);
111 TEUCHOS_ASSERT((numMyElements % numGlobalVars) == 0);
112 TEUCHOS_ASSERT((minMyGID % numGlobalVars) == 0);
114 LO numBlocks = numMyElements / numGlobalVars;
115 GO minBlockID = minMyGID / numGlobalVars;
121 for (varItr = vars.begin(); varItr != vars.end(); ++varItr) {
122 LO numLocalVars = *varItr;
123 GO numAllElmts = numLocalVars * numGlobals / numGlobalVars;
125 LO numMyElmts = numLocalVars * numBlocks;
129 std::vector<GO> subGlobals;
130 std::vector<GO> contigGlobals;
134 for (LO blockNum = 0; blockNum < numBlocks; blockNum++) {
136 for (LO local = 0; local < numLocalVars; ++local) {
140 subGlobals.push_back((minBlockID + blockNum) * numGlobalVars + blockOffset + local);
143 contigGlobals.push_back(numLocalVars * minBlockID + count);
149 assert((
size_t)numMyElmts == subGlobals.size());
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)));
157 Teuchos::set_extra_data(contigMap,
"contigMap", Teuchos::inOutArg(subMap));
158 subMaps.push_back(std::make_pair(numLocalVars, subMap));
161 blockOffset += numLocalVars;
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;
172 for (mapItr = subMaps.begin(); mapItr != subMaps.end(); ++mapItr) {
174 const Tpetra::Map<LO, GO, NT>& map = *(mapItr->second);
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))));
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,
185 std::vector<std::pair<int, RCP<Tpetra::Map<LO, GO, NT> > > >::const_iterator mapItr;
188 for (mapItr = subMaps.begin(); mapItr != subMaps.end(); ++mapItr) {
190 const Tpetra::Map<LO, GO, NT>& map =
191 *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(mapItr->second,
"contigMap"));
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);
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;
207 TEUCHOS_ASSERT(subMaps.size() == subVectors.size());
210 for (mapItr = subMaps.begin(), vecItr = subVectors.begin(); mapItr != subMaps.end();
212 Teuchos::set_extra_data(mapItr->second,
"globalMap", Teuchos::inOutArg(*vecItr),
213 Teuchos::POST_DESTROY,
false);
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) {
221 int numVarFamily = subMaps.size();
223 TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
224 TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
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;
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;
242 if (k < i) rowBlockOffset += subMaps[k].first;
243 if (k < j) colBlockOffset += subMaps[k].first;
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);
252 LO numMyRows = rowMap.getLocalNumElements();
253 LO maxNumEntries = A->getGlobalMaxNumRowEntries();
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);
262 std::vector<size_t> numEntriesPerRow(numMyRows, 0);
264 const size_t invalid = Teuchos::OrdinalTraits<size_t>::invalid();
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);
272 TEUCHOS_ASSERT(globalRow >= 0);
273 TEUCHOS_ASSERT(contigRow >= 0);
276 localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
278 for (
size_t localCol = 0; localCol < numEntries; localCol++) {
279 GO globalCol = indices(localCol);
282 int block = globalCol / numGlobalVars;
284 bool inFamily =
true;
287 inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
288 inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
295 numEntriesPerRow[localRow] += numOwnedCols;
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)));
302 std::vector<GO> colIndices(maxNumEntries);
303 std::vector<ST> colValues(maxNumEntries);
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);
312 TEUCHOS_ASSERT(globalRow >= 0);
313 TEUCHOS_ASSERT(contigRow >= 0);
316 localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
318 for (
size_t localCol = 0; localCol < numEntries; localCol++) {
319 GO globalCol = indices(localCol);
322 int block = globalCol / numGlobalVars;
324 bool inFamily =
true;
327 inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
328 inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
332 GO familyOffset = globalCol - (block * numGlobalVars + colBlockOffset);
334 colIndices[numOwnedCols] = block * colFamilyCnt + familyOffset;
335 colValues[numOwnedCols] = values(localCol);
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);
351 mat->fillComplete(rcpFromRef(colMap), rcpFromRef(rowMap));
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) {
361 int numVarFamily = subMaps.size();
363 TEUCHOS_ASSERT(i >= 0 && i < numVarFamily);
364 TEUCHOS_ASSERT(j >= 0 && j < numVarFamily);
365 TEUCHOS_ASSERT(mat.isFillComplete());
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;
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;
383 if (k < i) rowBlockOffset += subMaps[k].first;
384 if (k < j) colBlockOffset += subMaps[k].first;
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);
394 mat.setAllToScalar(0.0);
397 LO numMyRows = rowMap.getLocalNumElements();
398 GO maxNumEntries = A->getGlobalMaxNumRowEntries();
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);
407 std::vector<GO> colIndices(maxNumEntries);
408 std::vector<ST> colValues(maxNumEntries);
410 const size_t invalid = Teuchos::OrdinalTraits<size_t>::invalid();
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);
419 TEUCHOS_ASSERT(globalRow >= 0);
420 TEUCHOS_ASSERT(contigRow >= 0);
423 localA.getGlobalRowCopy(globalRow, indices, values, numEntries);
426 for (
size_t localCol = 0; localCol < numEntries; localCol++) {
427 GO globalCol = indices(localCol);
430 int block = globalCol / numGlobalVars;
432 bool inFamily =
true;
435 inFamily &= (block * numGlobalVars + colBlockOffset <= globalCol);
436 inFamily &= ((block * numGlobalVars + colBlockOffset + colFamilyCnt) > globalCol);
440 GO familyOffset = globalCol - (block * numGlobalVars + colBlockOffset);
442 colIndices[numOwnedCols] = block * colFamilyCnt + familyOffset;
443 colValues[numOwnedCols] = values(localCol);
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);
457 mat.fillComplete(rcpFromRef(colMap), rcpFromRef(rowMap));
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) {
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;
469 for (vecItr = many.begin(), expItr = subExport.begin(); vecItr != many.end();
470 ++vecItr, ++expItr) {
472 RCP<const Tpetra::MultiVector<ST, LO, GO, NT> > srcVec = *vecItr;
475 const Tpetra::Map<LO, GO, NT>& globalMap =
476 *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(srcVec,
"globalMap"));
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());
488 one.doExport(exportVector, **expItr, Tpetra::INSERT);
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) {
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;
501 for (vecItr = many.begin(), impItr = subImport.begin(); vecItr != many.end();
502 ++vecItr, ++impItr) {
504 RCP<Tpetra::MultiVector<ST, LO, GO, NT> > destVec = *vecItr;
507 const Tpetra::Map<LO, GO, NT>& globalMap =
508 *(Teuchos::get_extra_data<RCP<Tpetra::Map<LO, GO, NT> > >(destVec,
"globalMap"));
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());
520 importVector.doImport(single, **impItr, Tpetra::INSERT);
522 Tpetra::Import<LO, GO, NT> importer(destVec->getMap(), destVec->getMap());
523 importVector.replaceMap(destVec->getMap());
524 destVec->doImport(importVector, importer, Tpetra::INSERT);