8 #ifndef MUELU_ALGEBRAICPERMUTATIONSTRATEGY_DEF_HPP_ 9 #define MUELU_ALGEBRAICPERMUTATIONSTRATEGY_DEF_HPP_ 13 #include <Xpetra_MultiVector.hpp> 14 #include <Xpetra_Matrix.hpp> 15 #include <Xpetra_CrsGraph.hpp> 16 #include <Xpetra_Vector.hpp> 17 #include <Xpetra_VectorFactory.hpp> 18 #include <Xpetra_CrsMatrixWrap.hpp> 19 #include <Xpetra_Export.hpp> 20 #include <Xpetra_ExportFactory.hpp> 21 #include <Xpetra_Import.hpp> 22 #include <Xpetra_ImportFactory.hpp> 23 #include <Xpetra_MatrixMatrix.hpp> 25 #include "MueLu_Utilities.hpp" 30 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
32 #ifndef HAVE_MUELU_INST_COMPLEX_INT_INT 34 const Teuchos::RCP< const Teuchos::Comm< int > > comm = A->getRowMap()->getComm();
35 int numProcs = comm->getSize();
36 int myRank = comm->getRank();
42 size_t nDofsPerNode = 1;
43 if (A->IsView(
"stridedMaps")) {
44 Teuchos::RCP<const Map> permRowMapStrided = A->getRowMap(
"stridedMaps");
45 nDofsPerNode = Teuchos::rcp_dynamic_cast<
const StridedMap>(permRowMapStrided)->getFixedBlockSize();
50 std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> > permutedDiagCandidates;
51 std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> > keepDiagonalEntries;
52 std::vector<Scalar> Weights;
56 for (
size_t row = 0; row < A->getRowMap()->getNodeNumElements(); row++) {
57 GlobalOrdinal grow = A->getRowMap()->getGlobalElement(row);
59 if(permRowMap->isNodeGlobalElement(grow) ==
true)
continue;
61 size_t nnz = A->getNumEntriesInLocalRow(row);
64 Teuchos::ArrayView<const LocalOrdinal> indices;
65 Teuchos::ArrayView<const Scalar> vals;
66 A->getLocalRowView(row, indices, vals);
68 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::as<size_t>(indices.size()) != nnz,
Exceptions::RuntimeError,
"MueLu::PermutationFactory::Build: number of nonzeros not equal to number of indices? Error.");
71 GlobalOrdinal gMaxValIdx = 0;
74 for (
size_t j = 0; j < Teuchos::as<size_t>(indices.size()); j++) {
75 norm1 += Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]);
76 if(Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]) > maxVal) {
77 maxVal = Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]);
78 gMaxValIdx = A->getColMap()->getGlobalElement(indices[j]);
82 if(grow == gMaxValIdx)
83 keepDiagonalEntries.push_back(std::make_pair(grow,grow));
88 for (
size_t row = 0; row < permRowMap->getNodeNumElements(); row++) {
89 GlobalOrdinal grow = permRowMap->getGlobalElement(row);
90 LocalOrdinal lArow = A->getRowMap()->getLocalElement(grow);
91 size_t nnz = A->getNumEntriesInLocalRow(lArow);
94 Teuchos::ArrayView<const LocalOrdinal> indices;
95 Teuchos::ArrayView<const Scalar> vals;
96 A->getLocalRowView(lArow, indices, vals);
98 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::as<size_t>(indices.size()) != nnz,
Exceptions::RuntimeError,
"MueLu::PermutationFactory::Build: number of nonzeros not equal to number of indices? Error.");
101 GlobalOrdinal gMaxValIdx = 0;
104 for (
size_t j = 0; j < Teuchos::as<size_t>(indices.size()); j++) {
105 norm1 += Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]);
106 if(Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]) > maxVal) {
107 maxVal = Teuchos::ScalarTraits<Scalar>::magnitude(vals[j]);
108 gMaxValIdx = A->getColMap()->getGlobalElement(indices[j]);
112 if(Teuchos::ScalarTraits<Scalar>::magnitude(maxVal) > 0.0) {
113 permutedDiagCandidates.push_back(std::make_pair(grow,gMaxValIdx));
114 Weights.push_back(maxVal/(norm1*Teuchos::as<Scalar>(nnz)));
116 std::cout <<
"ATTENTION: row " << grow <<
" has only zero entries -> singular matrix!" << std::endl;
122 std::vector<int> permutation;
131 Teuchos::RCP<Vector> gColVec = VectorFactory::Build(A->getColMap());
132 Teuchos::RCP<Vector> gDomVec = VectorFactory::Build(A->getDomainMap());
133 gColVec->putScalar(0.0);
134 gDomVec->putScalar(0.0);
137 for (
typename std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> >::const_iterator p = keepDiagonalEntries.begin(); p != keepDiagonalEntries.end(); ++p) {
138 gColVec->sumIntoGlobalValue((*p).second,1.0);
141 Teuchos::RCP<Export> exporter = ExportFactory::Build(gColVec->getMap(), gDomVec->getMap());
142 gDomVec->doExport(*gColVec,*exporter,Xpetra::ADD);
143 gColVec->doImport(*gDomVec,*exporter,Xpetra::INSERT);
145 std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> > permutedDiagCandidatesFiltered;
146 std::map<GlobalOrdinal, Scalar> gColId2Weight;
148 Teuchos::ArrayRCP< Scalar > ddata = gColVec->getDataNonConst(0);
149 for(
size_t i = 0; i < permutedDiagCandidates.size(); ++i) {
151 std::pair<GlobalOrdinal, GlobalOrdinal> pp = permutedDiagCandidates[permutation[i]];
152 GlobalOrdinal grow = pp.first;
153 GlobalOrdinal gcol = pp.second;
155 LocalOrdinal lcol = A->getColMap()->getLocalElement(gcol);
157 if(ddata[lcol] > 0.0){
164 permutedDiagCandidatesFiltered.push_back(std::make_pair(grow,gcol));
165 gColId2Weight[gcol] = Weights[permutation[i]];
169 gDomVec->doExport(*gColVec,*exporter,Xpetra::ADD);
170 gColVec->doImport(*gDomVec,*exporter,Xpetra::INSERT);
177 std::vector<GlobalOrdinal> multipleColRequests;
181 std::queue<GlobalOrdinal> unusedColIdx;
183 for(
size_t sz = 0; sz<gDomVec->getLocalLength(); ++sz) {
184 Teuchos::ArrayRCP< const Scalar > arrDomVec = gDomVec->getData(0);
185 if(arrDomVec[sz] > 1.0) {
186 multipleColRequests.push_back(gDomVec->getMap()->getGlobalElement(sz));
187 }
else if(arrDomVec[sz] == 0.0) {
188 unusedColIdx.push(gDomVec->getMap()->getGlobalElement(sz));
193 LocalOrdinal localMultColRequests = Teuchos::as<LocalOrdinal>(multipleColRequests.size());
194 LocalOrdinal globalMultColRequests = 0;
197 MueLu_sumAll(gDomVec->getMap()->getComm(), (LocalOrdinal)localMultColRequests, globalMultColRequests);
199 if(globalMultColRequests > 0) {
205 std::vector<GlobalOrdinal> numMyMultColRequests(numProcs,0);
206 std::vector<GlobalOrdinal> numGlobalMultColRequests(numProcs,0);
207 numMyMultColRequests[myRank] = localMultColRequests;
208 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,numProcs,&numMyMultColRequests[0],&numGlobalMultColRequests[0]);
212 for (
int i=0; i<myRank-1; i++)
213 nMyOffset += numGlobalMultColRequests[i];
215 GlobalOrdinal zero=0;
216 std::vector<GlobalOrdinal> procMultRequestedColIds(globalMultColRequests,zero);
217 std::vector<GlobalOrdinal> global_procMultRequestedColIds(globalMultColRequests,zero);
220 for(
size_t i = 0; i < multipleColRequests.size(); i++) {
221 procMultRequestedColIds[nMyOffset + i] = multipleColRequests[i];
225 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(globalMultColRequests), &procMultRequestedColIds[0], &global_procMultRequestedColIds[0]);
228 for (
size_t k = 0; k<global_procMultRequestedColIds.size(); k++) {
229 GlobalOrdinal globColId = global_procMultRequestedColIds[k];
231 std::vector<Scalar> MyWeightForColId(numProcs,0);
232 std::vector<Scalar> GlobalWeightForColId(numProcs,0);
234 if(gColVec->getMap()->isNodeGlobalElement(globColId)) {
235 MyWeightForColId[myRank] = gColId2Weight[globColId];
237 MyWeightForColId[myRank] = 0.0;
240 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numProcs, &MyWeightForColId[0], &GlobalWeightForColId[0]);
242 if(gColVec->getMap()->isNodeGlobalElement(globColId)) {
245 Scalar winnerValue = 0.0;
246 int winnerProcRank = 0;
247 for (
int proc = 0; proc < numProcs; proc++) {
248 if(GlobalWeightForColId[proc] > winnerValue) {
249 winnerValue = GlobalWeightForColId[proc];
250 winnerProcRank = proc;
257 if(myRank != winnerProcRank) {
259 typename std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> >::iterator p = permutedDiagCandidatesFiltered.begin();
260 while(p != permutedDiagCandidatesFiltered.end() )
262 if((*p).second == globColId)
263 p = permutedDiagCandidatesFiltered.erase(p);
275 std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> > RowColPairs;
276 RowColPairs.insert( RowColPairs.end(), keepDiagonalEntries.begin(), keepDiagonalEntries.end());
277 RowColPairs.insert( RowColPairs.end(), permutedDiagCandidatesFiltered.begin(), permutedDiagCandidatesFiltered.end());
282 gColVec->putScalar(0.0);
283 gDomVec->putScalar(0.0);
284 typename std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> >::iterator pl = RowColPairs.begin();
285 while(pl != RowColPairs.end() )
288 GlobalOrdinal jk = (*pl).second;
290 gColVec->sumIntoGlobalValue(jk,1.0);
293 gDomVec->doExport(*gColVec,*exporter,Xpetra::ADD);
294 for(
size_t sz = 0; sz<gDomVec->getLocalLength(); ++sz) {
295 Teuchos::ArrayRCP< const Scalar > arrDomVec = gDomVec->getData(0);
296 if(arrDomVec[sz] > 1.0) {
297 GetOStream(
Runtime0) <<
"RowColPairs has multiple column [" << sz <<
"]=" << arrDomVec[sz] << std::endl;
298 }
else if(arrDomVec[sz] == 0.0) {
299 GetOStream(
Runtime0) <<
"RowColPairs has empty column [" << sz <<
"]=" << arrDomVec[sz] << std::endl;
332 Teuchos::RCP<Vector> Pperm = VectorFactory::Build(A->getRowMap());
333 Teuchos::RCP<Vector> Qperm = VectorFactory::Build(A->getDomainMap());
334 Teuchos::RCP<Vector> lQperm = VectorFactory::Build(A->getColMap());
336 Teuchos::ArrayRCP< Scalar > PpermData = Pperm->getDataNonConst(0);
337 Teuchos::ArrayRCP< Scalar > QpermData = Qperm->getDataNonConst(0);
339 Pperm->putScalar(0.0);
340 Qperm->putScalar(0.0);
341 lQperm->putScalar(0.0);
344 Teuchos::RCP<Export> QpermExporter = ExportFactory::Build(lQperm->getMap(), Qperm->getMap());
346 Teuchos::RCP<Vector> RowIdStatus = VectorFactory::Build(A->getRowMap());
347 Teuchos::RCP<Vector> ColIdStatus = VectorFactory::Build(A->getDomainMap());
348 Teuchos::RCP<Vector> lColIdStatus = VectorFactory::Build(A->getColMap());
349 Teuchos::RCP<Vector> ColIdUsed = VectorFactory::Build(A->getDomainMap());
350 Teuchos::ArrayRCP< Scalar > RowIdStatusArray = RowIdStatus->getDataNonConst(0);
351 Teuchos::ArrayRCP< Scalar > ColIdStatusArray = ColIdStatus->getDataNonConst(0);
352 Teuchos::ArrayRCP< Scalar > lColIdStatusArray = lColIdStatus->getDataNonConst(0);
353 Teuchos::ArrayRCP< Scalar > ColIdUsedArray = ColIdUsed->getDataNonConst(0);
354 RowIdStatus->putScalar(0.0);
355 ColIdStatus->putScalar(0.0);
356 lColIdStatus->putScalar(0.0);
357 ColIdUsed->putScalar(0.0);
362 LocalOrdinal lWideRangeRowPermutations = 0;
363 GlobalOrdinal gWideRangeRowPermutations = 0;
364 LocalOrdinal lWideRangeColPermutations = 0;
365 GlobalOrdinal gWideRangeColPermutations = 0;
368 typename std::vector<std::pair<GlobalOrdinal, GlobalOrdinal> >::iterator p = RowColPairs.begin();
369 while(p != RowColPairs.end() )
371 GlobalOrdinal ik = (*p).first;
372 GlobalOrdinal jk = (*p).second;
374 LocalOrdinal lik = A->getRowMap()->getLocalElement(ik);
375 LocalOrdinal ljk = A->getColMap()->getLocalElement(jk);
377 if(RowIdStatusArray[lik] == 0.0) {
378 RowIdStatusArray[lik] = 1.0;
379 lColIdStatusArray[ljk] = 1.0;
380 Pperm->replaceLocalValue(lik, ik);
381 lQperm->replaceLocalValue(ljk, ik);
382 ColIdUsed->replaceGlobalValue(ik,1.0);
383 p = RowColPairs.erase(p);
386 if(floor(ik/nDofsPerNode) != floor(jk/nDofsPerNode)) {
387 lWideRangeColPermutations++;
395 Qperm->doExport(*lQperm,*QpermExporter,Xpetra::ABSMAX);
396 ColIdStatus->doExport(*lColIdStatus,*QpermExporter,Xpetra::ABSMAX);
399 if(RowColPairs.size()>0) GetOStream(
Warnings0) <<
"MueLu::PermutationFactory: There are Row/Col pairs left!!!" << std::endl;
404 size_t cntFreeRowIdx = 0;
405 std::queue<GlobalOrdinal> qFreeGRowIdx;
406 for (
size_t lik = 0; lik < RowIdStatus->getLocalLength(); ++lik) {
407 if(RowIdStatusArray[lik] == 0.0) {
409 qFreeGRowIdx.push(RowIdStatus->getMap()->getGlobalElement(lik));
414 for (
size_t lik = 0; lik < RowIdStatus->getLocalLength(); ++lik) {
415 if(RowIdStatusArray[lik] == 0.0) {
416 RowIdStatusArray[lik] = 1.0;
417 Pperm->replaceLocalValue(lik, qFreeGRowIdx.front());
419 if(floor(qFreeGRowIdx.front()/nDofsPerNode) != floor(RowIdStatus->getMap()->getGlobalElement(lik)/nDofsPerNode)) {
420 lWideRangeRowPermutations++;
427 size_t cntFreeColIdx = 0;
428 std::queue<GlobalOrdinal> qFreeGColIdx;
429 for (
size_t ljk = 0; ljk < ColIdStatus->getLocalLength(); ++ljk) {
430 if(ColIdStatusArray[ljk] == 0.0) {
432 qFreeGColIdx.push(ColIdStatus->getMap()->getGlobalElement(ljk));
436 size_t cntUnusedColIdx = 0;
437 std::queue<GlobalOrdinal> qUnusedGColIdx;
438 for (
size_t ljk = 0; ljk < ColIdUsed->getLocalLength(); ++ljk) {
439 if(ColIdUsedArray[ljk] == 0.0) {
441 qUnusedGColIdx.push(ColIdUsed->getMap()->getGlobalElement(ljk));
446 for (
size_t ljk = 0; ljk < ColIdStatus->getLocalLength(); ++ljk) {
448 if(cntUnusedColIdx == 0)
break;
450 if(ColIdStatusArray[ljk] == 0.0) {
451 ColIdStatusArray[ljk] = 1.0;
452 Qperm->replaceLocalValue(ljk, qUnusedGColIdx.front());
453 ColIdUsed->replaceGlobalValue(qUnusedGColIdx.front(),1.0);
455 if(floor(qUnusedGColIdx.front()/nDofsPerNode) != floor(ColIdStatus->getMap()->getGlobalElement(ljk)/nDofsPerNode)) {
456 lWideRangeColPermutations++;
458 qUnusedGColIdx.pop();
470 for (
size_t ljk = 0; ljk < ColIdStatus->getLocalLength(); ++ljk) {
471 if(ColIdStatusArray[ljk] == 0.0) {
476 GlobalOrdinal global_cntFreeColIdx = 0;
477 LocalOrdinal local_cntFreeColIdx = cntFreeColIdx;
478 MueLu_sumAll(comm, Teuchos::as<GlobalOrdinal>(local_cntFreeColIdx), global_cntFreeColIdx);
480 std::cout <<
"global # of empty column idx entries in Qperm: " << global_cntFreeColIdx << std::endl;
484 if(global_cntFreeColIdx > 0) {
487 GlobalOrdinal global_cntUnusedColIdx = 0;
488 LocalOrdinal local_cntUnusedColIdx = cntUnusedColIdx;
489 MueLu_sumAll(comm, Teuchos::as<GlobalOrdinal>(local_cntUnusedColIdx), global_cntUnusedColIdx);
491 std::cout <<
"global # of unused column idx: " << global_cntUnusedColIdx << std::endl;
495 std::vector<LocalOrdinal> local_UnusedColIdxOnProc (numProcs);
496 std::vector<LocalOrdinal> global_UnusedColIdxOnProc(numProcs);
497 local_UnusedColIdxOnProc[myRank] = local_cntUnusedColIdx;
498 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numProcs, &local_UnusedColIdxOnProc[0], &global_UnusedColIdxOnProc[0]);
501 std::cout <<
"PROC " << myRank <<
" global num unused indices per proc: ";
502 for (
size_t ljk = 0; ljk < global_UnusedColIdxOnProc.size(); ++ljk) {
503 std::cout <<
" " << global_UnusedColIdxOnProc[ljk];
505 std::cout << std::endl;
509 std::vector<GlobalOrdinal> local_UnusedColIdxVector(Teuchos::as<size_t>(global_cntUnusedColIdx));
510 std::vector<GlobalOrdinal> global_UnusedColIdxVector(Teuchos::as<size_t>(global_cntUnusedColIdx));
511 GlobalOrdinal global_cntUnusedColIdxStartIter = 0;
512 for(
int proc=0; proc<myRank; proc++) {
513 global_cntUnusedColIdxStartIter += global_UnusedColIdxOnProc[proc];
515 for(GlobalOrdinal k = global_cntUnusedColIdxStartIter; k < global_cntUnusedColIdxStartIter+local_cntUnusedColIdx; k++) {
516 local_UnusedColIdxVector[k] = qUnusedGColIdx.front();
517 qUnusedGColIdx.pop();
519 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(global_cntUnusedColIdx), &local_UnusedColIdxVector[0], &global_UnusedColIdxVector[0]);
521 std::cout <<
"PROC " << myRank <<
" global UnusedGColIdx: ";
522 for (
size_t ljk = 0; ljk < global_UnusedColIdxVector.size(); ++ljk) {
523 std::cout <<
" " << global_UnusedColIdxVector[ljk];
525 std::cout << std::endl;
532 std::vector<LocalOrdinal> local_EmptyColIdxOnProc (numProcs);
533 std::vector<LocalOrdinal> global_EmptyColIdxOnProc(numProcs);
534 local_EmptyColIdxOnProc[myRank] = local_cntFreeColIdx;
535 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numProcs, &local_EmptyColIdxOnProc[0], &global_EmptyColIdxOnProc[0]);
538 std::cout <<
"PROC " << myRank <<
" global num of needed column indices: ";
539 for (
size_t ljk = 0; ljk < global_EmptyColIdxOnProc.size(); ++ljk) {
540 std::cout <<
" " << global_EmptyColIdxOnProc[ljk];
542 std::cout << std::endl;
547 GlobalOrdinal global_UnusedColStartIdx = 0;
548 for(
int proc=0; proc<myRank; proc++) {
549 global_UnusedColStartIdx += global_EmptyColIdxOnProc[proc];
553 GetOStream(
Statistics0) <<
"PROC " << myRank <<
" is allowd to use the following column gids: ";
554 for(GlobalOrdinal k = global_UnusedColStartIdx; k < global_UnusedColStartIdx + Teuchos::as<GlobalOrdinal>(cntFreeColIdx); k++) {
555 GetOStream(
Statistics0) << global_UnusedColIdxVector[k] <<
" ";
561 GlobalOrdinal array_iter = 0;
562 for (
size_t ljk = 0; ljk < ColIdStatus->getLocalLength(); ++ljk) {
564 if(ColIdStatusArray[ljk] == 0.0) {
565 ColIdStatusArray[ljk] = 1.0;
566 Qperm->replaceLocalValue(ljk, global_UnusedColIdxVector[global_UnusedColStartIdx + array_iter]);
567 ColIdUsed->replaceGlobalValue(global_UnusedColIdxVector[global_UnusedColStartIdx + array_iter],1.0);
569 if(floor(global_UnusedColIdxVector[global_UnusedColStartIdx + array_iter]/nDofsPerNode) != floor(ColIdStatus->getMap()->getGlobalElement(ljk)/nDofsPerNode)) {
570 lWideRangeColPermutations++;
581 Teuchos::RCP<CrsMatrixWrap> permPTmatrix = Teuchos::rcp(
new CrsMatrixWrap(A->getRowMap(),1,Xpetra::StaticProfile));
582 Teuchos::RCP<CrsMatrixWrap> permQTmatrix = Teuchos::rcp(
new CrsMatrixWrap(A->getRowMap(),1,Xpetra::StaticProfile));
584 for(
size_t row=0; row<A->getNodeNumRows(); row++) {
585 Teuchos::ArrayRCP<GlobalOrdinal> indoutP(1,Teuchos::as<GO>(PpermData[row]));
586 Teuchos::ArrayRCP<GlobalOrdinal> indoutQ(1,Teuchos::as<GO>(QpermData[row]));
587 Teuchos::ArrayRCP<Scalar> valout(1,1.0);
588 permPTmatrix->insertGlobalValues(A->getRowMap()->getGlobalElement(row), indoutP.view(0,indoutP.size()), valout.view(0,valout.size()));
589 permQTmatrix->insertGlobalValues (A->getRowMap()->getGlobalElement(row), indoutQ.view(0,indoutQ.size()), valout.view(0,valout.size()));
592 permPTmatrix->fillComplete();
593 permQTmatrix->fillComplete();
597 for(
size_t row=0; row<permPTmatrix->getNodeNumRows(); row++) {
598 if(permPTmatrix->getNumEntriesInLocalRow(row) != 1)
599 GetOStream(
Warnings0) <<
"#entries in row " << row <<
" of permPTmatrix is " << permPTmatrix->getNumEntriesInLocalRow(row) << std::endl;
600 if(permPmatrix->getNumEntriesInLocalRow(row) != 1)
601 GetOStream(
Warnings0) <<
"#entries in row " << row <<
" of permPmatrix is " << permPmatrix->getNumEntriesInLocalRow(row) << std::endl;
602 if(permQTmatrix->getNumEntriesInLocalRow(row) != 1)
603 GetOStream(
Warnings0) <<
"#entries in row " << row <<
" of permQmatrix is " << permQTmatrix->getNumEntriesInLocalRow(row) << std::endl;
607 Teuchos::RCP<Matrix> ApermQt = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A,
false, *permQTmatrix,
false, GetOStream(
Statistics2));
608 Teuchos::RCP<Matrix> permPApermQt = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*permPmatrix,
false, *ApermQt,
false, GetOStream(
Statistics2));
617 Teuchos::RCP<Vector> diagVec = VectorFactory::Build(permPApermQt->getRowMap(),
true);
618 Teuchos::RCP<Vector> invDiagVec = VectorFactory::Build(permPApermQt->getRowMap(),
true);
619 Teuchos::ArrayRCP< const Scalar > diagVecData = diagVec->getData(0);
620 Teuchos::ArrayRCP< Scalar > invDiagVecData = invDiagVec->getDataNonConst(0);
622 permPApermQt->getLocalDiagCopy(*diagVec);
623 for(
size_t i = 0; i<diagVec->getMap()->getNodeNumElements(); ++i) {
624 if(diagVecData[i] != 0.0)
625 invDiagVecData[i] = 1/diagVecData[i];
627 invDiagVecData[i] = 1.0;
628 GetOStream(
Statistics0) <<
"MueLu::PermutationFactory: found zero on diagonal in row " << i << std::endl;
632 Teuchos::RCP<CrsMatrixWrap> diagScalingOp = Teuchos::rcp(
new CrsMatrixWrap(permPApermQt->getRowMap(),1,Xpetra::StaticProfile));
634 for(
size_t row=0; row<A->getNodeNumRows(); row++) {
635 Teuchos::ArrayRCP<GlobalOrdinal> indout(1,permPApermQt->getRowMap()->getGlobalElement(row));
636 Teuchos::ArrayRCP<Scalar> valout(1,invDiagVecData[row]);
637 diagScalingOp->insertGlobalValues(A->getRowMap()->getGlobalElement(row), indout.view(0,indout.size()), valout.view(0,valout.size()));
639 diagScalingOp->fillComplete();
641 Teuchos::RCP<Matrix> scaledA = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*diagScalingOp,
false, *permPApermQt,
false, GetOStream(
Statistics2));
642 currentLevel.
Set(
"A", Teuchos::rcp_dynamic_cast<Matrix>(scaledA), genFactory);
644 currentLevel.
Set(
"permA", Teuchos::rcp_dynamic_cast<Matrix>(permPApermQt), genFactory);
645 currentLevel.
Set(
"permP", Teuchos::rcp_dynamic_cast<Matrix>(permPmatrix), genFactory);
646 currentLevel.
Set(
"permQT", Teuchos::rcp_dynamic_cast<Matrix>(permQTmatrix), genFactory);
647 currentLevel.
Set(
"permScaling", Teuchos::rcp_dynamic_cast<Matrix>(diagScalingOp), genFactory);
651 Teuchos::RCP<Vector> diagPVec = VectorFactory::Build(permPmatrix->getRowMap(),
true);
652 permPmatrix->getLocalDiagCopy(*diagPVec);
653 Teuchos::ArrayRCP< const Scalar > diagPVecData = diagPVec->getData(0);
654 LocalOrdinal lNumRowPermutations = 0;
655 GlobalOrdinal gNumRowPermutations = 0;
656 for(
size_t i = 0; i<diagPVec->getMap()->getNodeNumElements(); ++i) {
657 if(diagPVecData[i] == 0.0) {
658 lNumRowPermutations++;
663 MueLu_sumAll(diagPVec->getMap()->getComm(), Teuchos::as<GlobalOrdinal>(lNumRowPermutations), gNumRowPermutations);
667 Teuchos::RCP<Vector> diagQTVec = VectorFactory::Build(permQTmatrix->getRowMap(),
true);
668 permQTmatrix->getLocalDiagCopy(*diagQTVec);
669 Teuchos::ArrayRCP< const Scalar > diagQTVecData = diagQTVec->getData(0);
670 LocalOrdinal lNumColPermutations = 0;
671 GlobalOrdinal gNumColPermutations = 0;
672 for(
size_t i = 0; i<diagQTVec->getMap()->getNodeNumElements(); ++i) {
673 if(diagQTVecData[i] == 0.0) {
674 lNumColPermutations++;
679 MueLu_sumAll(diagQTVec->getMap()->getComm(), Teuchos::as<GlobalOrdinal>(lNumColPermutations), gNumColPermutations);
681 currentLevel.
Set(
"#RowPermutations", gNumRowPermutations, genFactory);
682 currentLevel.
Set(
"#ColPermutations", gNumColPermutations, genFactory);
683 currentLevel.
Set(
"#WideRangeRowPermutations", gWideRangeRowPermutations, genFactory);
684 currentLevel.
Set(
"#WideRangeColPermutations", gWideRangeColPermutations, genFactory);
686 GetOStream(
Statistics0) <<
"#Row permutations/max possible permutations: " << gNumRowPermutations <<
"/" << diagPVec->getMap()->getGlobalNumElements() << std::endl;
687 GetOStream(
Statistics0) <<
"#Column permutations/max possible permutations: " << gNumColPermutations <<
"/" << diagQTVec->getMap()->getGlobalNumElements() << std::endl;
688 GetOStream(
Runtime1) <<
"#wide range row permutations: " << gWideRangeRowPermutations <<
" #wide range column permutations: " << gWideRangeColPermutations << std::endl;
690 #endif // #ifndef HAVE_MUELU_INST_COMPLEX_INT_INT Important warning messages (one line)
static RCP< Matrix > Transpose(Matrix &Op, bool optimizeTranspose=false, const std::string &label=std::string())
Transpose a Xpetra::Matrix.
void sortingPermutation(const std::vector< Scalar > &values, std::vector< LocalOrdinal > &v)
One-liner description of what is happening.
Namespace for MueLu classes and methods.
Print even more statistics.
Base class for factories (e.g., R, P, and A_coarse).
Print statistics that do not involve significant additional computation.
#define MueLu_sumAll(rcpComm, in, out)
Class that holds all level-specific information.
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void BuildPermutation(const Teuchos::RCP< Matrix > &A, const Teuchos::RCP< const Map > permRowMap, Level ¤tLevel, const FactoryBase *genFactory) const
build permutation operators
Exception throws to report errors in the internal logical of the program.
Description of what is happening (more verbose)