108 typedef typename Teuchos::ScalarTraits<Scalar>::coordinateType coordinate_type;
109 typedef Xpetra::MultiVector<coordinate_type, LO, GO, NO> RealValuedMultiVector;
110 typedef Xpetra::MultiVectorFactory<coordinate_type, LO, GO, NO> RealValuedMultiVectorFactory;
112 const ParameterList& pL = GetParameterList();
113 std::string nspName =
"Nullspace";
114 if (pL.isParameter(
"Nullspace name")) nspName = pL.get<std::string>(
"Nullspace name");
116 RCP<Matrix> Ptentative;
117 auto A = Get<RCP<Matrix>>(fineLevel,
"A");
118 auto aggregates = Get<RCP<Aggregates>>(fineLevel,
"Aggregates");
121 if (aggregates->GetNumGlobalAggregatesComputeIfNeeded() == 0) {
122 Ptentative = Teuchos::null;
123 Set(coarseLevel,
"P", Ptentative);
127 auto amalgInfo = Get<RCP<AmalgamationInfo>>(fineLevel,
"UnAmalgamationInfo");
128 auto fineNullspace = Get<RCP<MultiVector>>(fineLevel, nspName);
129 auto coarseMap = Get<RCP<const Map>>(fineLevel,
"CoarseMap");
130 RCP<RealValuedMultiVector> fineCoords;
131 if (bTransferCoordinates_) {
132 fineCoords = Get<RCP<RealValuedMultiVector>>(fineLevel,
"Coordinates");
137 RCP<const Teuchos::Comm<int>> nodeComm = Get<RCP<const Teuchos::Comm<int>>>(fineLevel,
"Node Comm");
138 Set<RCP<const Teuchos::Comm<int>>>(coarseLevel,
"Node Comm", nodeComm);
142 TEUCHOS_TEST_FOR_EXCEPTION(A->getDomainMap()->getLocalNumElements() != fineNullspace->getMap()->getLocalNumElements(),
145 RCP<MultiVector> coarseNullspace;
146 RCP<RealValuedMultiVector> coarseCoords;
148 if (bTransferCoordinates_) {
151 ArrayView<const GO> elementAList = coarseMap->getLocalElementList();
153 if (rcp_dynamic_cast<const StridedMap>(coarseMap) != Teuchos::null) {
154 blkSize = rcp_dynamic_cast<const StridedMap>(coarseMap)->getFixedBlockSize();
156 GO indexBase = coarseMap->getIndexBase();
157 LO numCoarseNodes = Teuchos::as<LO>(elementAList.size() / blkSize);
158 Array<GO> nodeList(numCoarseNodes);
159 const int numDimensions = fineCoords->getNumVectors();
161 for (LO i = 0; i < numCoarseNodes; i++) {
162 nodeList[i] = (elementAList[i * blkSize] - indexBase) / blkSize + indexBase;
164 Teuchos::RCP<Teuchos::ParameterList> params = Teuchos::rcp(
new Teuchos::ParameterList());
165 params->set(
"compute global constants",
false);
166 RCP<const Map> coarseCoordsMap = MapFactory::Build(fineCoords->getMap()->lib(),
167 blkSize * coarseMap->getGlobalNumElements(),
170 fineCoords->getMap()->getComm(),
172 coarseCoords = RealValuedMultiVectorFactory::Build(coarseCoordsMap, numDimensions);
175 RCP<RealValuedMultiVector> ghostedCoords;
176 if (aggregates->AggregatesCrossProcessors()) {
177 RCP<const Map> aggMap = aggregates->GetMap();
178 RCP<const Import> importer = ImportFactory::Build(fineCoords->getMap(), aggMap);
180 ghostedCoords = RealValuedMultiVectorFactory::Build(aggMap, numDimensions);
181 ghostedCoords->doImport(*fineCoords, *importer, Xpetra::INSERT);
183 ghostedCoords = fineCoords;
187 int myPID = coarseCoordsMap->getComm()->getRank();
188 LO numAggs = aggregates->GetNumAggregates();
189 ArrayRCP<LO> aggSizes = aggregates->ComputeAggregateSizesArrayRCP();
190 const ArrayRCP<const LO> vertex2AggID = aggregates->GetVertex2AggId()->getData(0);
191 const ArrayRCP<const LO> procWinner = aggregates->GetProcWinner()->getData(0);
194 for (
int dim = 0; dim < numDimensions; ++dim) {
195 ArrayRCP<const coordinate_type> fineCoordsData = ghostedCoords->getData(dim);
196 ArrayRCP<coordinate_type> coarseCoordsData = coarseCoords->getDataNonConst(dim);
198 for (LO lnode = 0; lnode < Teuchos::as<LO>(vertex2AggID.size()); lnode++) {
199 if (procWinner[lnode] == myPID &&
200 lnode < fineCoordsData.size() &&
201 vertex2AggID[lnode] < coarseCoordsData.size() &&
202 Teuchos::ScalarTraits<coordinate_type>::isnaninf(fineCoordsData[lnode]) ==
false) {
203 coarseCoordsData[vertex2AggID[lnode]] += fineCoordsData[lnode];
206 for (LO agg = 0; agg < numAggs; agg++) {
207 coarseCoordsData[agg] /= aggSizes[agg];
212 if (!aggregates->AggregatesCrossProcessors()) {
213 if (Xpetra::Helpers<SC, LO, GO, NO>::isTpetraBlockCrs(A)) {
214 BuildPuncoupledBlockCrs(A, aggregates, amalgInfo, fineNullspace, coarseMap, Ptentative, coarseNullspace, coarseLevel.
GetLevelID());
216 BuildPuncoupled(A, aggregates, amalgInfo, fineNullspace, coarseMap, Ptentative, coarseNullspace, coarseLevel.
GetLevelID());
219 BuildPcoupled(A, aggregates, amalgInfo, fineNullspace, coarseMap, Ptentative, coarseNullspace);
229 if (A->IsView(
"stridedMaps") ==
true)
230 Ptentative->CreateView(
"stridedMaps", A->getRowMap(
"stridedMaps"), coarseMap);
232 if (bTransferCoordinates_) {
233 Set(coarseLevel,
"Coordinates", coarseCoords);
235 Set(coarseLevel,
"Nullspace", coarseNullspace);
236 Set(coarseLevel,
"P", Ptentative);
238 if (pL.get<
bool>(
"sa: keep tentative prolongator")) {
244 RCP<ParameterList> params = rcp(
new ParameterList());
245 params->set(
"printLoadBalancingInfo",
true);
252 BuildPuncoupled(RCP<Matrix> A, RCP<Aggregates> aggregates, RCP<AmalgamationInfo> amalgInfo, RCP<MultiVector> fineNullspace,
253 RCP<const Map> coarseMap, RCP<Matrix>& Ptentative, RCP<MultiVector>& coarseNullspace,
const int levelID)
const {
254 RCP<const Map> rowMap = A->getRowMap();
255 RCP<const Map> colMap = A->getColMap();
256 const size_t numRows = rowMap->getLocalNumElements();
258 typedef Teuchos::ScalarTraits<SC> STS;
259 typedef typename STS::magnitudeType Magnitude;
260 const SC zero = STS::zero();
261 const SC one = STS::one();
262 const LO INVALID = Teuchos::OrdinalTraits<LO>::invalid();
264 const GO numAggs = aggregates->GetNumAggregates();
265 const size_t NSDim = fineNullspace->getNumVectors();
266 ArrayRCP<LO> aggSizes = aggregates->ComputeAggregateSizesArrayRCP();
269 const ParameterList& pL = GetParameterList();
270 const bool& doQRStep = pL.get<
bool>(
"tentative: calculate qr");
271 const bool& constantColSums = pL.get<
bool>(
"tentative: constant column sums");
274 "MueLu::TentativePFactory::MakeTentative: cannot use 'constant column sums' and 'calculate qr' at the same time");
285 ArrayRCP<LO> aggStart;
286 ArrayRCP<LO> aggToRowMapLO;
287 ArrayRCP<GO> aggToRowMapGO;
289 amalgInfo->UnamalgamateAggregatesLO(*aggregates, aggStart, aggToRowMapLO);
290 GetOStream(
Runtime1) <<
"Column map is consistent with the row map, good." << std::endl;
293 amalgInfo->UnamalgamateAggregates(*aggregates, aggStart, aggToRowMapGO);
294 GetOStream(
Warnings0) <<
"Column map is not consistent with the row map\n"
295 <<
"using GO->LO conversion with performance penalty" << std::endl;
297 coarseNullspace = MultiVectorFactory::Build(coarseMap, NSDim);
300 ArrayRCP<ArrayRCP<const SC>> fineNS(NSDim);
301 ArrayRCP<ArrayRCP<SC>> coarseNS(NSDim);
302 for (
size_t i = 0; i < NSDim; i++) {
303 fineNS[i] = fineNullspace->getData(i);
304 if (coarseMap->getLocalNumElements() > 0)
305 coarseNS[i] = coarseNullspace->getDataNonConst(i);
308 size_t nnzEstimate = numRows * NSDim;
311 Ptentative = rcp(
new CrsMatrixWrap(rowMap, coarseMap, 0));
312 RCP<CrsMatrix> PtentCrs = toCrsMatrix(Ptentative);
314 ArrayRCP<size_t> iaPtent;
315 ArrayRCP<LO> jaPtent;
316 ArrayRCP<SC> valPtent;
318 PtentCrs->allocateAllValues(nnzEstimate, iaPtent, jaPtent, valPtent);
320 ArrayView<size_t> ia = iaPtent();
321 ArrayView<LO> ja = jaPtent();
322 ArrayView<SC> val = valPtent();
325 for (
size_t i = 1; i <= numRows; i++)
326 ia[i] = ia[i - 1] + NSDim;
328 for (
size_t j = 0; j < nnzEstimate; j++) {
337 for (GO agg = 0; agg < numAggs; agg++) {
338 LO aggSize = aggStart[agg + 1] - aggStart[agg];
340 Xpetra::global_size_t offset = agg * NSDim;
345 Teuchos::SerialDenseMatrix<LO, SC> localQR(aggSize, NSDim);
347 for (
size_t j = 0; j < NSDim; j++)
348 for (LO k = 0; k < aggSize; k++)
349 localQR(k, j) = fineNS[j][aggToRowMapLO[aggStart[agg] + k]];
351 for (
size_t j = 0; j < NSDim; j++)
352 for (LO k = 0; k < aggSize; k++)
353 localQR(k, j) = fineNS[j][rowMap->getLocalElement(aggToRowMapGO[aggStart[agg] + k])];
357 for (
size_t j = 0; j < NSDim; j++) {
358 bool bIsZeroNSColumn =
true;
360 for (LO k = 0; k < aggSize; k++)
361 if (localQR(k, j) != zero)
362 bIsZeroNSColumn =
false;
365 "MueLu::TentativePFactory::MakeTentative: fine level NS part has a zero column in NS column " << j);
370 if (aggSize >= Teuchos::as<LO>(NSDim)) {
373 Magnitude norm = STS::magnitude(zero);
374 for (
size_t k = 0; k < Teuchos::as<size_t>(aggSize); k++)
375 norm += STS::magnitude(localQR(k, 0) * localQR(k, 0));
376 norm = Teuchos::ScalarTraits<Magnitude>::squareroot(norm);
379 coarseNS[0][offset] = norm;
382 for (LO i = 0; i < aggSize; i++)
383 localQR(i, 0) /= norm;
386 Teuchos::SerialQRDenseSolver<LO, SC> qrSolver;
387 qrSolver.setMatrix(Teuchos::rcp(&localQR,
false));
391 for (
size_t j = 0; j < NSDim; j++)
392 for (
size_t k = 0; k <= j; k++)
393 coarseNS[j][offset + k] = localQR(k, j);
398 Teuchos::RCP<Teuchos::SerialDenseMatrix<LO, SC>> qFactor = qrSolver.getQ();
399 for (
size_t j = 0; j < NSDim; j++)
400 for (
size_t i = 0; i < Teuchos::as<size_t>(aggSize); i++)
401 localQR(i, j) = (*qFactor)(i, j);
432 for (
size_t j = 0; j < NSDim; j++)
433 for (
size_t k = 0; k < NSDim; k++)
434 if (k < as<size_t>(aggSize))
435 coarseNS[j][offset + k] = localQR(k, j);
437 coarseNS[j][offset + k] = (k == j ? one : zero);
440 for (
size_t i = 0; i < as<size_t>(aggSize); i++)
441 for (
size_t j = 0; j < NSDim; j++)
442 localQR(i, j) = (j == i ? one : zero);
447 for (LO j = 0; j < aggSize; j++) {
448 LO localRow = (goodMap ? aggToRowMapLO[aggStart[agg] + j] : rowMap->getLocalElement(aggToRowMapGO[aggStart[agg] + j]));
450 size_t rowStart = ia[localRow];
451 for (
size_t k = 0, lnnz = 0; k < NSDim; k++) {
453 if (localQR(j, k) != zero) {
454 ja[rowStart + lnnz] = offset + k;
455 val[rowStart + lnnz] = localQR(j, k);
463 GetOStream(
Runtime1) <<
"TentativePFactory : bypassing local QR phase" << std::endl;
465 GetOStream(
Warnings0) <<
"TentativePFactory : for nontrivial nullspace, this may degrade performance" << std::endl;
475 for (GO agg = 0; agg < numAggs; agg++) {
476 const LO aggSize = aggStart[agg + 1] - aggStart[agg];
477 Xpetra::global_size_t offset = agg * NSDim;
481 for (LO j = 0; j < aggSize; j++) {
485 const LO localRow = aggToRowMapLO[aggStart[agg] + j];
487 const size_t rowStart = ia[localRow];
489 for (
size_t k = 0, lnnz = 0; k < NSDim; k++) {
491 SC qr_jk = fineNS[k][aggToRowMapLO[aggStart[agg] + j]];
492 if (constantColSums) qr_jk = qr_jk / (Magnitude)aggSizes[agg];
494 ja[rowStart + lnnz] = offset + k;
495 val[rowStart + lnnz] = qr_jk;
500 for (
size_t j = 0; j < NSDim; j++)
501 coarseNS[j][offset + j] = one;
505 for (GO agg = 0; agg < numAggs; agg++) {
506 const LO aggSize = aggStart[agg + 1] - aggStart[agg];
507 Xpetra::global_size_t offset = agg * NSDim;
508 for (LO j = 0; j < aggSize; j++) {
509 const LO localRow = rowMap->getLocalElement(aggToRowMapGO[aggStart[agg] + j]);
511 const size_t rowStart = ia[localRow];
513 for (
size_t k = 0, lnnz = 0; k < NSDim; ++k) {
515 SC qr_jk = fineNS[k][rowMap->getLocalElement(aggToRowMapGO[aggStart[agg] + j])];
516 if (constantColSums) qr_jk = qr_jk / (Magnitude)aggSizes[agg];
518 ja[rowStart + lnnz] = offset + k;
519 val[rowStart + lnnz] = qr_jk;
524 for (
size_t j = 0; j < NSDim; j++)
525 coarseNS[j][offset + j] = one;
534 size_t ia_tmp = 0, nnz = 0;
535 for (
size_t i = 0; i < numRows; i++) {
536 for (
size_t j = ia_tmp; j < ia[i + 1]; j++)
537 if (ja[j] != INVALID) {
545 if (rowMap->lib() == Xpetra::UseTpetra) {
550 valPtent.resize(nnz);
553 GetOStream(
Runtime1) <<
"TentativePFactory : aggregates do not cross process boundaries" << std::endl;
555 PtentCrs->setAllValues(iaPtent, jaPtent, valPtent);
558 RCP<ParameterList> FCparams;
559 if (pL.isSublist(
"matrixmatrix: kernel params"))
560 FCparams = rcp(
new ParameterList(pL.sublist(
"matrixmatrix: kernel params")));
562 FCparams = rcp(
new ParameterList);
564 FCparams->set(
"compute global constants", FCparams->get(
"compute global constants",
false));
565 std::string levelIDs =
toString(levelID);
566 FCparams->set(
"Timer Label", std::string(
"MueLu::TentativeP-") + levelIDs);
567 RCP<const Export> dummy_e;
568 RCP<const Import> dummy_i;
570 PtentCrs->expertStaticFillComplete(coarseMap, A->getDomainMap(), dummy_i, dummy_e, FCparams);
575 BuildPuncoupledBlockCrs(RCP<Matrix> A, RCP<Aggregates> aggregates, RCP<AmalgamationInfo> amalgInfo, RCP<MultiVector> fineNullspace,
576 RCP<const Map> coarsePointMap, RCP<Matrix>& Ptentative, RCP<MultiVector>& coarseNullspace,
const int levelID)
const {
586 RCP<const Map> rowMap = A->getRowMap();
587 RCP<const Map> rangeMap = A->getRangeMap();
588 RCP<const Map> colMap = A->getColMap();
590 const size_t numFineBlockRows = rowMap->getLocalNumElements();
592 typedef Teuchos::ScalarTraits<SC> STS;
594 const SC zero = STS::zero();
595 const SC one = STS::one();
596 const LO INVALID = Teuchos::OrdinalTraits<LO>::invalid();
598 const GO numAggs = aggregates->GetNumAggregates();
599 const size_t NSDim = fineNullspace->getNumVectors();
600 ArrayRCP<LO> aggSizes = aggregates->ComputeAggregateSizesArrayRCP();
606 const size_t numCoarseBlockRows = coarsePointMap->getLocalNumElements() / NSDim;
607 RCP<const Map> coarseBlockMap = MapFactory::Build(coarsePointMap->lib(),
608 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
610 coarsePointMap->getIndexBase(),
611 coarsePointMap->getComm());
613 const ParameterList& pL = GetParameterList();
614 const bool& doQRStep = pL.get<
bool>(
"tentative: calculate qr");
615 const bool& constantColSums = pL.get<
bool>(
"tentative: constant column sums");
618 "MueLu::TentativePFactory::MakeTentative: cannot use 'constant column sums' and 'calculate qr' at the same time");
631 ArrayRCP<LO> aggStart;
632 ArrayRCP<LO> aggToRowMapLO;
633 ArrayRCP<GO> aggToRowMapGO;
635 amalgInfo->UnamalgamateAggregatesLO(*aggregates, aggStart, aggToRowMapLO);
636 GetOStream(
Runtime1) <<
"Column map is consistent with the row map, good." << std::endl;
638 throw std::runtime_error(
"TentativePFactory::PuncoupledBlockCrs: Inconsistent maps not currently supported");
641 coarseNullspace = MultiVectorFactory::Build(coarsePointMap, NSDim);
644 ArrayRCP<ArrayRCP<const SC>> fineNS(NSDim);
645 ArrayRCP<ArrayRCP<SC>> coarseNS(NSDim);
646 for (
size_t i = 0; i < NSDim; i++) {
647 fineNS[i] = fineNullspace->getData(i);
648 if (coarsePointMap->getLocalNumElements() > 0)
649 coarseNS[i] = coarseNullspace->getDataNonConst(i);
655 RCP<CrsGraph> BlockGraph = CrsGraphFactory::Build(rowMap, coarseBlockMap, 0);
656 ArrayRCP<size_t> iaPtent;
657 ArrayRCP<LO> jaPtent;
658 BlockGraph->allocateAllIndices(numFineBlockRows, iaPtent, jaPtent);
659 ArrayView<size_t> ia = iaPtent();
660 ArrayView<LO> ja = jaPtent();
662 for (
size_t i = 0; i < numFineBlockRows; i++) {
666 ia[numCoarseBlockRows] = numCoarseBlockRows;
668 for (GO agg = 0; agg < numAggs; agg++) {
669 LO aggSize = aggStart[agg + 1] - aggStart[agg];
670 Xpetra::global_size_t offset = agg;
672 for (LO j = 0; j < aggSize; j++) {
674 const LO localRow = aggToRowMapLO[aggStart[agg] + j];
675 const size_t rowStart = ia[localRow];
676 ja[rowStart] = offset;
682 size_t ia_tmp = 0, nnz = 0;
683 for (
size_t i = 0; i < numFineBlockRows; i++) {
684 for (
size_t j = ia_tmp; j < ia[i + 1]; j++)
685 if (ja[j] != INVALID) {
693 if (rowMap->lib() == Xpetra::UseTpetra) {
700 GetOStream(
Runtime1) <<
"TentativePFactory : generating block graph" << std::endl;
701 BlockGraph->setAllIndices(iaPtent, jaPtent);
705 RCP<ParameterList> FCparams;
706 if (pL.isSublist(
"matrixmatrix: kernel params"))
707 FCparams = rcp(
new ParameterList(pL.sublist(
"matrixmatrix: kernel params")));
709 FCparams = rcp(
new ParameterList);
712 FCparams->set(
"compute global constants", FCparams->get(
"compute global constants",
true));
713 std::string levelIDs =
toString(levelID);
714 FCparams->set(
"Timer Label", std::string(
"MueLu::TentativeP-") + levelIDs);
715 RCP<const Export> dummy_e;
716 RCP<const Import> dummy_i;
717 BlockGraph->expertStaticFillComplete(coarseBlockMap, rowMap, dummy_i, dummy_e, FCparams);
722 RCP<Xpetra::CrsMatrix<SC, LO, GO, NO>> P_xpetra = Xpetra::CrsMatrixFactory<SC, LO, GO, NO>::BuildBlock(BlockGraph, coarsePointMap, rangeMap, NSDim);
723 RCP<Xpetra::TpetraBlockCrsMatrix<SC, LO, GO, NO>> P_tpetra = rcp_dynamic_cast<Xpetra::TpetraBlockCrsMatrix<SC, LO, GO, NO>>(P_xpetra);
724 if (P_tpetra.is_null())
throw std::runtime_error(
"BuildPUncoupled: Matrix factory did not return a Tpetra::BlockCrsMatrix");
725 RCP<CrsMatrixWrap> P_wrap = rcp(
new CrsMatrixWrap(P_xpetra));
734 Teuchos::Array<Scalar> block(NSDim * NSDim, zero);
735 Teuchos::Array<LO> bcol(1);
737 GetOStream(
Runtime1) <<
"TentativePFactory : bypassing local QR phase" << std::endl;
738 for (LO agg = 0; agg < numAggs; agg++) {
740 const LO aggSize = aggStart[agg + 1] - aggStart[agg];
741 Xpetra::global_size_t offset = agg * NSDim;
745 for (LO j = 0; j < aggSize; j++) {
746 const LO localBlockRow = aggToRowMapLO[aggStart[agg] + j];
748 for (
size_t r = 0; r < NSDim; r++) {
749 LO localPointRow = localBlockRow * NSDim + r;
750 for (
size_t c = 0; c < NSDim; c++)
751 block[r * NSDim + c] = fineNS[c][localPointRow];
754 P_tpetra->replaceLocalValues(localBlockRow, bcol(), block());
758 for (
size_t j = 0; j < NSDim; j++)
759 coarseNS[j][offset + j] = one;
768 BuildPcoupled(RCP<Matrix> A, RCP<Aggregates> aggregates, RCP<AmalgamationInfo> amalgInfo, RCP<MultiVector> fineNullspace,
769 RCP<const Map> coarseMap, RCP<Matrix>& Ptentative, RCP<MultiVector>& coarseNullspace)
const {
770 typedef Teuchos::ScalarTraits<SC> STS;
771 typedef typename STS::magnitudeType Magnitude;
772 const SC zero = STS::zero();
773 const SC one = STS::one();
776 GO numAggs = aggregates->GetNumAggregates();
782 ArrayRCP<LO> aggStart;
783 ArrayRCP<GO> aggToRowMap;
784 amalgInfo->UnamalgamateAggregates(*aggregates, aggStart, aggToRowMap);
788 for (GO i = 0; i < numAggs; ++i) {
789 LO sizeOfThisAgg = aggStart[i + 1] - aggStart[i];
790 if (sizeOfThisAgg > maxAggSize) maxAggSize = sizeOfThisAgg;
794 const size_t NSDim = fineNullspace->getNumVectors();
797 GO indexBase = A->getRowMap()->getIndexBase();
799 const RCP<const Map> nonUniqueMap = amalgInfo->ComputeUnamalgamatedImportDofMap(*aggregates);
800 const RCP<const Map> uniqueMap = A->getDomainMap();
801 RCP<const Import> importer = ImportFactory::Build(uniqueMap, nonUniqueMap);
802 RCP<MultiVector> fineNullspaceWithOverlap = MultiVectorFactory::Build(nonUniqueMap, NSDim);
803 fineNullspaceWithOverlap->doImport(*fineNullspace, *importer, Xpetra::INSERT);
806 ArrayRCP<ArrayRCP<const SC>> fineNS(NSDim);
807 for (
size_t i = 0; i < NSDim; ++i)
808 fineNS[i] = fineNullspaceWithOverlap->getData(i);
811 coarseNullspace = MultiVectorFactory::Build(coarseMap, NSDim);
813 ArrayRCP<ArrayRCP<SC>> coarseNS(NSDim);
814 for (
size_t i = 0; i < NSDim; ++i)
815 if (coarseMap->getLocalNumElements() > 0) coarseNS[i] = coarseNullspace->getDataNonConst(i);
820 RCP<const Map> rowMapForPtent = A->getRowMap();
821 const Map& rowMapForPtentRef = *rowMapForPtent;
825 RCP<const Map> colMap = A->getColMap();
827 RCP<const Map> ghostQMap;
828 RCP<MultiVector> ghostQvalues;
829 Array<RCP<Xpetra::Vector<GO, LO, GO, Node>>> ghostQcolumns;
830 RCP<Xpetra::Vector<GO, LO, GO, Node>> ghostQrowNums;
831 ArrayRCP<ArrayRCP<SC>> ghostQvals;
832 ArrayRCP<ArrayRCP<GO>> ghostQcols;
833 ArrayRCP<GO> ghostQrows;
836 for (LO j = 0; j < numAggs; ++j) {
837 for (LO k = aggStart[j]; k < aggStart[j + 1]; ++k) {
838 if (rowMapForPtentRef.isNodeGlobalElement(aggToRowMap[k]) ==
false) {
839 ghostGIDs.push_back(aggToRowMap[k]);
843 ghostQMap = MapFactory::Build(A->getRowMap()->lib(),
844 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
846 indexBase, A->getRowMap()->getComm());
848 ghostQvalues = MultiVectorFactory::Build(ghostQMap, NSDim);
852 ghostQcolumns.resize(NSDim);
853 for (
size_t i = 0; i < NSDim; ++i)
854 ghostQcolumns[i] = Xpetra::VectorFactory<GO, LO, GO, Node>::Build(ghostQMap);
855 ghostQrowNums = Xpetra::VectorFactory<GO, LO, GO, Node>::Build(ghostQMap);
856 if (ghostQvalues->getLocalLength() > 0) {
857 ghostQvals.resize(NSDim);
858 ghostQcols.resize(NSDim);
859 for (
size_t i = 0; i < NSDim; ++i) {
860 ghostQvals[i] = ghostQvalues->getDataNonConst(i);
861 ghostQcols[i] = ghostQcolumns[i]->getDataNonConst(0);
863 ghostQrows = ghostQrowNums->getDataNonConst(0);
867 importer = ImportFactory::Build(ghostQMap, A->getRowMap());
870 Teuchos::SerialQRDenseSolver<LO, SC> qrSolver;
873 Array<GO> globalColPtr(maxAggSize * NSDim, 0);
874 Array<LO> localColPtr(maxAggSize * NSDim, 0);
875 Array<SC> valPtr(maxAggSize * NSDim, 0.);
878 const Map& coarseMapRef = *coarseMap;
881 ArrayRCP<size_t> ptent_rowptr;
882 ArrayRCP<LO> ptent_colind;
883 ArrayRCP<Scalar> ptent_values;
886 ArrayView<size_t> rowptr_v;
887 ArrayView<LO> colind_v;
888 ArrayView<Scalar> values_v;
891 Array<size_t> rowptr_temp;
892 Array<LO> colind_temp;
893 Array<Scalar> values_temp;
895 RCP<CrsMatrix> PtentCrs;
897 RCP<CrsMatrixWrap> PtentCrsWrap = rcp(
new CrsMatrixWrap(rowMapForPtent, NSDim));
898 PtentCrs = PtentCrsWrap->getCrsMatrix();
899 Ptentative = PtentCrsWrap;
905 const Map& nonUniqueMapRef = *nonUniqueMap;
907 size_t total_nnz_count = 0;
909 for (GO agg = 0; agg < numAggs; ++agg) {
910 LO myAggSize = aggStart[agg + 1] - aggStart[agg];
913 Teuchos::SerialDenseMatrix<LO, SC> localQR(myAggSize, NSDim);
914 for (
size_t j = 0; j < NSDim; ++j) {
915 bool bIsZeroNSColumn =
true;
916 for (LO k = 0; k < myAggSize; ++k) {
920 SC nsVal = fineNS[j][nonUniqueMapRef.getLocalElement(aggToRowMap[aggStart[agg] + k])];
921 localQR(k, j) = nsVal;
922 if (nsVal != zero) bIsZeroNSColumn =
false;
924 GetOStream(
Runtime1, -1) <<
"length of fine level nsp: " << fineNullspace->getGlobalLength() << std::endl;
925 GetOStream(
Runtime1, -1) <<
"length of fine level nsp w overlap: " << fineNullspaceWithOverlap->getGlobalLength() << std::endl;
926 GetOStream(
Runtime1, -1) <<
"(local?) aggId=" << agg << std::endl;
927 GetOStream(
Runtime1, -1) <<
"aggSize=" << myAggSize << std::endl;
928 GetOStream(
Runtime1, -1) <<
"agg DOF=" << k << std::endl;
929 GetOStream(
Runtime1, -1) <<
"NS vector j=" << j << std::endl;
930 GetOStream(
Runtime1, -1) <<
"j*myAggSize + k = " << j * myAggSize + k << std::endl;
931 GetOStream(
Runtime1, -1) <<
"aggToRowMap[" << agg <<
"][" << k <<
"] = " << aggToRowMap[aggStart[agg] + k] << std::endl;
932 GetOStream(
Runtime1, -1) <<
"id aggToRowMap[agg][k]=" << aggToRowMap[aggStart[agg] + k] <<
" is global element in nonUniqueMap = " << nonUniqueMapRef.isNodeGlobalElement(aggToRowMap[aggStart[agg] + k]) << std::endl;
933 GetOStream(
Runtime1, -1) <<
"colMap local id aggToRowMap[agg][k]=" << nonUniqueMapRef.getLocalElement(aggToRowMap[aggStart[agg] + k]) << std::endl;
934 GetOStream(
Runtime1, -1) <<
"fineNS...=" << fineNS[j][nonUniqueMapRef.getLocalElement(aggToRowMap[aggStart[agg] + k])] << std::endl;
935 GetOStream(
Errors, -1) <<
"caught an error!" << std::endl;
938 TEUCHOS_TEST_FOR_EXCEPTION(bIsZeroNSColumn ==
true,
Exceptions::RuntimeError,
"MueLu::TentativePFactory::MakeTentative: fine level NS part has a zero column. Error.");
941 Xpetra::global_size_t offset = agg * NSDim;
943 if (myAggSize >= Teuchos::as<LocalOrdinal>(NSDim)) {
948 SC tau = localQR(0, 0);
953 for (
size_t k = 0; k < Teuchos::as<size_t>(myAggSize); ++k) {
954 Magnitude tmag = STS::magnitude(localQR(k, 0));
955 dtemp += tmag * tmag;
957 dtemp = Teuchos::ScalarTraits<Magnitude>::squareroot(dtemp);
959 localQR(0, 0) = dtemp;
961 qrSolver.setMatrix(Teuchos::rcp(&localQR,
false));
968 for (
size_t j = 0; j < NSDim; ++j) {
969 for (
size_t k = 0; k <= j; ++k) {
971 if (coarseMapRef.isNodeLocalElement(offset + k)) {
972 coarseNS[j][offset + k] = localQR(k, j);
975 GetOStream(
Errors, -1) <<
"caught error in coarseNS insert, j=" << j <<
", offset+k = " << offset + k << std::endl;
985 Magnitude dtemp = Teuchos::ScalarTraits<SC>::magnitude(localQR(0, 0));
989 localQR(i, 0) *= dtemp;
993 Teuchos::RCP<Teuchos::SerialDenseMatrix<LO, SC>> qFactor = qrSolver.getQ();
994 for (
size_t j = 0; j < NSDim; j++) {
995 for (
size_t i = 0; i < Teuchos::as<size_t>(myAggSize); i++) {
996 localQR(i, j) = (*qFactor)(i, j);
1006 for (
size_t j = 0; j < NSDim; j++)
1007 for (
size_t k = 0; k < NSDim; k++) {
1009 "Caught error in coarseNS insert, j=" << j <<
", offset+k = " << offset + k);
1011 if (k < as<size_t>(myAggSize))
1012 coarseNS[j][offset + k] = localQR(k, j);
1014 coarseNS[j][offset + k] = (k == j ? one : zero);
1018 for (
size_t i = 0; i < as<size_t>(myAggSize); i++)
1019 for (
size_t j = 0; j < NSDim; j++)
1020 localQR(i, j) = (j == i ? one : zero);
1027 for (GO j = 0; j < myAggSize; ++j) {
1031 GO globalRow = aggToRowMap[aggStart[agg] + j];
1034 if (rowMapForPtentRef.isNodeGlobalElement(globalRow) ==
false) {
1035 ghostQrows[qctr] = globalRow;
1036 for (
size_t k = 0; k < NSDim; ++k) {
1037 ghostQcols[k][qctr] = coarseMapRef.getGlobalElement(agg * NSDim + k);
1038 ghostQvals[k][qctr] = localQR(j, k);
1043 for (
size_t k = 0; k < NSDim; ++k) {
1045 if (localQR(j, k) != Teuchos::ScalarTraits<SC>::zero()) {
1046 localColPtr[nnz] = agg * NSDim + k;
1047 globalColPtr[nnz] = coarseMapRef.getGlobalElement(localColPtr[nnz]);
1048 valPtr[nnz] = localQR(j, k);
1053 GetOStream(
Errors, -1) <<
"caught error in colPtr/valPtr insert, current index=" << nnz << std::endl;
1058 Ptentative->insertGlobalValues(globalRow, globalColPtr.view(0, nnz), valPtr.view(0, nnz));
1060 GetOStream(
Errors, -1) <<
"pid " << A->getRowMap()->getComm()->getRank()
1061 <<
"caught error during Ptent row insertion, global row "
1062 << globalRow << std::endl;
1072 GetOStream(
Runtime1) <<
"TentativePFactory : aggregates may cross process boundaries" << std::endl;
1075 RCP<Xpetra::Vector<GO, LO, GO, Node>> targetQrowNums = Xpetra::VectorFactory<GO, LO, GO, Node>::Build(rowMapForPtent);
1076 targetQrowNums->putScalar(-1);
1077 targetQrowNums->doImport(*ghostQrowNums, *importer, Xpetra::INSERT);
1078 ArrayRCP<GO> targetQrows = targetQrowNums->getDataNonConst(0);
1081 Array<GO> gidsToImport;
1082 gidsToImport.reserve(targetQrows.size());
1083 for (
typename ArrayRCP<GO>::iterator r = targetQrows.begin(); r != targetQrows.end(); ++r) {
1085 gidsToImport.push_back(*r);
1088 RCP<const Map> reducedMap = MapFactory::Build(A->getRowMap()->lib(),
1089 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
1090 gidsToImport, indexBase, A->getRowMap()->getComm());
1093 importer = ImportFactory::Build(ghostQMap, reducedMap);
1095 Array<RCP<Xpetra::Vector<GO, LO, GO, Node>>> targetQcolumns(NSDim);
1096 for (
size_t i = 0; i < NSDim; ++i) {
1097 targetQcolumns[i] = Xpetra::VectorFactory<GO, LO, GO, Node>::Build(reducedMap);
1098 targetQcolumns[i]->doImport(*(ghostQcolumns[i]), *importer, Xpetra::INSERT);
1100 RCP<MultiVector> targetQvalues = MultiVectorFactory::Build(reducedMap, NSDim);
1101 targetQvalues->doImport(*ghostQvalues, *importer, Xpetra::INSERT);
1103 ArrayRCP<ArrayRCP<SC>> targetQvals;
1104 ArrayRCP<ArrayRCP<GO>> targetQcols;
1105 if (targetQvalues->getLocalLength() > 0) {
1106 targetQvals.resize(NSDim);
1107 targetQcols.resize(NSDim);
1108 for (
size_t i = 0; i < NSDim; ++i) {
1109 targetQvals[i] = targetQvalues->getDataNonConst(i);
1110 targetQcols[i] = targetQcolumns[i]->getDataNonConst(0);
1114 valPtr = Array<SC>(NSDim, 0.);
1115 globalColPtr = Array<GO>(NSDim, 0);
1116 for (
typename Array<GO>::iterator r = gidsToImport.begin(); r != gidsToImport.end(); ++r) {
1117 if (targetQvalues->getLocalLength() > 0) {
1118 for (
size_t j = 0; j < NSDim; ++j) {
1119 valPtr[j] = targetQvals[j][reducedMap->getLocalElement(*r)];
1120 globalColPtr[j] = targetQcols[j][reducedMap->getLocalElement(*r)];
1122 Ptentative->insertGlobalValues(*r, globalColPtr.view(0, NSDim), valPtr.view(0, NSDim));
1126 Ptentative->fillComplete(coarseMap, A->getDomainMap());