91 const std::string prefix =
"MueLu::SaPFactory(" + levelIDs +
"): ";
93 typedef typename Teuchos::ScalarTraits<SC>::coordinateType Coordinate;
94 typedef typename Teuchos::ScalarTraits<SC>::magnitudeType MT;
99 RCP<const FactoryBase> initialPFact = GetFactory(
"P");
100 if (initialPFact == Teuchos::null) {
103 const ParameterList& pL = GetParameterList();
106 RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel,
"A");
107 RCP<Matrix> Ptent = coarseLevel.
Get<RCP<Matrix> >(
"P", initialPFact.get());
111 if (Ptent == Teuchos::null) {
112 finalP = Teuchos::null;
113 Set(coarseLevel,
"P", finalP);
117 if (restrictionMode_) {
125 RCP<ParameterList> APparams;
126 if (pL.isSublist(
"matrixmatrix: kernel params"))
127 APparams = rcp(
new ParameterList(pL.sublist(
"matrixmatrix: kernel params")));
129 APparams = rcp(
new ParameterList);
130 if (coarseLevel.
IsAvailable(
"AP reuse data",
this)) {
131 GetOStream(
static_cast<MsgType>(
Runtime0 |
Test)) <<
"Reusing previous AP data" << std::endl;
133 APparams = coarseLevel.
Get<RCP<ParameterList> >(
"AP reuse data",
this);
135 if (APparams->isParameter(
"graph"))
136 finalP = APparams->get<RCP<Matrix> >(
"graph");
139 APparams->set(
"compute global constants: temporaries", APparams->get(
"compute global constants: temporaries",
false));
140 APparams->set(
"compute global constants", APparams->get(
"compute global constants",
false));
142 const SC
dampingFactor = as<SC>(pL.get<
double>(
"sa: damping factor"));
143 const LO maxEigenIterations = as<LO>(pL.get<
int>(
"sa: eigenvalue estimate num iterations"));
144 const bool estimateMaxEigen = pL.get<
bool>(
"sa: calculate eigenvalue estimate");
145 const bool useAbsValueRowSum = pL.get<
bool>(
"sa: use rowsumabs diagonal scaling");
146 const bool doQRStep = pL.get<
bool>(
"tentative: calculate qr");
147 const bool enforceConstraints = pL.get<
bool>(
"sa: enforce constraints");
148 const MT userDefinedMaxEigen = as<MT>(pL.get<
double>(
"sa: max eigenvalue"));
149 double dTol = pL.get<
double>(
"sa: rowsumabs diagonal replacement tolerance");
150 const MT diagonalReplacementTolerance = (dTol == as<double>(-1) ? Teuchos::ScalarTraits<MT>::eps() * 100 : as<MT>(pL.get<
double>(
"sa: rowsumabs diagonal replacement tolerance")));
151 const SC diagonalReplacementValue = as<SC>(pL.get<
double>(
"sa: rowsumabs diagonal replacement value"));
152 const bool replaceSingleEntryRowWithZero = pL.get<
bool>(
"sa: rowsumabs replace single entry row with zero");
153 const bool useAutomaticDiagTol = pL.get<
bool>(
"sa: rowsumabs use automatic diagonal tolerance");
157 "MueLu::TentativePFactory::MakeTentative: cannot use 'enforce constraints' and 'calculate qr' at the same time");
161 Teuchos::RCP<Vector> invDiag;
162 if (userDefinedMaxEigen == -1.) {
164 lambdaMax = A->GetMaxEigenvalueEstimate();
165 if (lambdaMax == -Teuchos::ScalarTraits<SC>::one() || estimateMaxEigen) {
166 GetOStream(
Statistics1) <<
"Calculating max eigenvalue estimate now (max iters = " << maxEigenIterations << ((useAbsValueRowSum) ?
", use rowSumAbs diagonal)" :
", use point diagonal)") << std::endl;
167 Coordinate stopTol = 1e-4;
168 if (useAbsValueRowSum) {
169 const bool returnReciprocal =
true;
171 diagonalReplacementTolerance,
172 diagonalReplacementValue,
173 replaceSingleEntryRowWithZero,
174 useAutomaticDiagTol);
176 "SaPFactory: eigenvalue estimate: diagonal reciprocal is null.");
180 A->SetMaxEigenvalueEstimate(lambdaMax);
182 GetOStream(
Statistics1) <<
"Using cached max eigenvalue estimate" << std::endl;
185 lambdaMax = userDefinedMaxEigen;
186 A->SetMaxEigenvalueEstimate(lambdaMax);
192 if (!useAbsValueRowSum)
194 else if (invDiag == Teuchos::null) {
195 GetOStream(
Runtime0) <<
"Using rowsumabs diagonal" << std::endl;
196 const bool returnReciprocal =
true;
198 diagonalReplacementTolerance,
199 diagonalReplacementValue,
200 replaceSingleEntryRowWithZero,
201 useAutomaticDiagTol);
202 TEUCHOS_TEST_FOR_EXCEPTION(invDiag.is_null(),
Exceptions::RuntimeError,
"SaPFactory: diagonal reciprocal is null.");
206 TEUCHOS_TEST_FOR_EXCEPTION(!std::isfinite(Teuchos::ScalarTraits<SC>::magnitude(omega)),
Exceptions::RuntimeError,
"Prolongator damping factor needs to be finite.");
211 finalP =
MueLu::IteratorOps<SC, LO, GO, NO>::Jacobi(omega, *invDiag, *A, *Ptent, finalP, GetOStream(
Statistics2), std::string(
"MueLu::SaP-") +
toString(coarseLevel.
GetLevelID()), APparams);
212 if (enforceConstraints) {
213 if (!pL.get<
bool>(
"use kokkos refactor")) {
214 if (A->GetFixedBlockSize() == 1)
215 optimalSatisfyPConstraintsForScalarPDEsNonKokkos(finalP);
217 SatisfyPConstraintsNonKokkos(A, finalP);
222 SatisfyPConstraints(A, finalP);
234 if (!restrictionMode_) {
236 if (!finalP.is_null()) {
237 std::ostringstream oss;
239 finalP->setObjectLabel(oss.str());
241 Set(coarseLevel,
"P", finalP);
243 APparams->set(
"graph", finalP);
244 Set(coarseLevel,
"AP reuse data", APparams);
247 if (Ptent->IsView(
"stridedMaps"))
248 finalP->CreateView(
"stridedMaps", Ptent);
256 std::ostringstream oss;
258 R->setObjectLabel(oss.str());
262 Set(coarseLevel,
"R", R);
265 if (Ptent->IsView(
"stridedMaps"))
266 R->CreateView(
"stridedMaps", Ptent,
true );
270 RCP<ParameterList> params = rcp(
new ParameterList());
271 params->set(
"printLoadBalancingInfo",
true);
272 params->set(
"printCommInfo",
true);
296 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
297 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
298 LO nPDEs = A->GetFixedBlockSize();
299 Teuchos::ArrayRCP<Scalar> ConstraintViolationSum(nPDEs);
300 Teuchos::ArrayRCP<Scalar> Rsum(nPDEs);
301 Teuchos::ArrayRCP<size_t> nPositive(nPDEs);
302 for (
size_t k = 0; k < (size_t)nPDEs; k++) ConstraintViolationSum[k] = zero;
303 for (
size_t k = 0; k < (size_t)nPDEs; k++) Rsum[k] = zero;
304 for (
size_t k = 0; k < (size_t)nPDEs; k++) nPositive[k] = 0;
306 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
307 Teuchos::ArrayView<const LocalOrdinal> indices;
308 Teuchos::ArrayView<const Scalar> vals1;
309 Teuchos::ArrayView<Scalar> vals;
310 P->getLocalRowView((LO)i, indices, vals1);
311 size_t nnz = indices.size();
312 if (nnz == 0)
continue;
314 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
316 bool checkRow =
true;
321 for (LO j = 0; j < indices.size(); j++) {
322 Rsum[j % nPDEs] += vals[j];
323 if (Teuchos::ScalarTraits<SC>::real(vals[j]) < Teuchos::ScalarTraits<SC>::real(zero)) {
324 ConstraintViolationSum[j % nPDEs] += vals[j];
327 if (Teuchos::ScalarTraits<SC>::real(vals[j]) != Teuchos::ScalarTraits<SC>::real(zero))
328 (nPositive[j % nPDEs])++;
330 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(1.00001)) {
331 ConstraintViolationSum[j % nPDEs] += (vals[j] - one);
341 for (
size_t k = 0; k < (size_t)nPDEs; k++) {
342 if (Teuchos::ScalarTraits<SC>::real(Rsum[k]) < Teuchos::ScalarTraits<SC>::magnitude(zero)) {
343 ConstraintViolationSum[k] += (-Rsum[k]);
344 }
else if (Teuchos::ScalarTraits<SC>::real(Rsum[k]) > Teuchos::ScalarTraits<SC>::magnitude(1.00001)) {
345 ConstraintViolationSum[k] += (one - Rsum[k]);
350 for (
size_t k = 0; k < (size_t)nPDEs; k++) {
351 if (Teuchos::ScalarTraits<SC>::magnitude(ConstraintViolationSum[k]) != Teuchos::ScalarTraits<SC>::magnitude(zero))
356 for (LO j = 0; j < indices.size(); j++) {
357 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(zero)) {
358 vals[j] += (ConstraintViolationSum[j % nPDEs] / (as<Scalar>(nPositive[j % nPDEs])));
361 for (
size_t k = 0; k < (size_t)nPDEs; k++) ConstraintViolationSum[k] = zero;
363 for (
size_t k = 0; k < (size_t)nPDEs; k++) Rsum[k] = zero;
364 for (
size_t k = 0; k < (size_t)nPDEs; k++) nPositive[k] = 0;
371 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
372 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
375 Teuchos::ArrayRCP<Scalar> scalarData(3 * maxEntriesPerRow);
378 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
379 Teuchos::ArrayView<const LocalOrdinal> indices;
380 Teuchos::ArrayView<const Scalar> vals1;
381 Teuchos::ArrayView<Scalar> vals;
383 size_t nnz = indices.size();
385 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
387 for (
size_t j = 0; j < nnz; j++) rsumTarget += vals[j];
389 if (nnz > as<size_t>(maxEntriesPerRow)) {
390 maxEntriesPerRow = nnz * 3;
391 scalarData.resize(3 * maxEntriesPerRow);
393 hasFeasible = constrainRow(vals.getRawPtr(), as<LocalOrdinal>(nnz), zero, one, rsumTarget, vals.getRawPtr(), scalarData.getRawPtr());
396 for (
size_t j = 0; j < nnz; j++) vals[j] = one / as<Scalar>(nnz);
522 Scalar notFlippedLeftBound, notFlippedRghtBound, aBigNumber, *origSorted;
523 Scalar rowSumDeviation, temp, *fixedSorted, delta;
524 Scalar closestToLeftBoundDist, closestToRghtBoundDist;
529 notFlippedLeftBound = leftBound;
530 notFlippedRghtBound = rghtBound;
532 if ((Teuchos::ScalarTraits<SC>::real(rsumTarget) >= Teuchos::ScalarTraits<SC>::real(leftBound * as<Scalar>(nEntries))) &&
533 (Teuchos::ScalarTraits<SC>::real(rsumTarget) <= Teuchos::ScalarTraits<SC>::real(rghtBound * as<Scalar>(nEntries))))
534 hasFeasibleSol =
true;
536 hasFeasibleSol =
false;
537 return hasFeasibleSol;
542 aBigNumber = Teuchos::ScalarTraits<SC>::zero();
544 if (Teuchos::ScalarTraits<SC>::magnitude(orig[i]) > Teuchos::ScalarTraits<SC>::magnitude(aBigNumber))
545 aBigNumber = Teuchos::ScalarTraits<SC>::magnitude(orig[i]);
547 aBigNumber = aBigNumber + (Teuchos::ScalarTraits<SC>::magnitude(leftBound) + Teuchos::ScalarTraits<SC>::magnitude(rghtBound)) * as<Scalar>(100.0);
549 origSorted = &scalarData[0];
550 fixedSorted = &(scalarData[nEntries]);
553 for (
LocalOrdinal i = 0; i < nEntries; i++) inds[i] = i;
554 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[i];
557 std::sort(inds, inds + nEntries,
558 [origSorted](
LocalOrdinal leftIndex,
LocalOrdinal rightIndex) {
return Teuchos::ScalarTraits<SC>::real(origSorted[leftIndex]) < Teuchos::ScalarTraits<SC>::real(origSorted[rightIndex]); });
560 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[inds[i]];
562 closestToLeftBound = 0;
563 while ((closestToLeftBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToLeftBound]) <= Teuchos::ScalarTraits<SC>::real(leftBound))) closestToLeftBound++;
566 closestToRghtBound = closestToLeftBound;
567 while ((closestToRghtBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToRghtBound]) <= Teuchos::ScalarTraits<SC>::real(rghtBound))) closestToRghtBound++;
572 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
573 if (closestToRghtBound == nEntries)
574 closestToRghtBoundDist = aBigNumber;
576 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
581 rowSumDeviation = leftBound * as<Scalar>(closestToLeftBound) + as<Scalar>((nEntries - closestToRghtBound)) * rghtBound - rsumTarget;
582 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) rowSumDeviation += origSorted[i];
587 if (Teuchos::ScalarTraits<SC>::real(rowSumDeviation) < Teuchos::ScalarTraits<SC>::real(Teuchos::ScalarTraits<SC>::zero())) {
590 leftBound = -rghtBound;
595 if ((nEntries % 2) == 1) origSorted[(nEntries / 2)] = -origSorted[(nEntries / 2)];
597 temp = origSorted[i];
598 origSorted[i] = -origSorted[nEntries - 1 - i];
599 origSorted[nEntries - i - 1] = -temp;
605 closestToLeftBound = nEntries - closestToRghtBound;
606 closestToRghtBound = nEntries - itemp;
607 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
608 if (closestToRghtBound == nEntries)
609 closestToRghtBoundDist = aBigNumber;
611 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
613 rowSumDeviation = -rowSumDeviation;
618 for (
LocalOrdinal i = 0; i < closestToLeftBound; i++) fixedSorted[i] = leftBound;
619 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i];
620 for (
LocalOrdinal i = closestToRghtBound; i < nEntries; i++) fixedSorted[i] = rghtBound;
622 while ((Teuchos::ScalarTraits<SC>::magnitude(rowSumDeviation) > Teuchos::ScalarTraits<SC>::magnitude(as<Scalar>(1.e-10) * rsumTarget))) {
623 if (closestToRghtBound != closestToLeftBound)
624 delta = rowSumDeviation / as<Scalar>(closestToRghtBound - closestToLeftBound);
628 if (Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
629 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist)) {
630 rowSumDeviation = Teuchos::ScalarTraits<SC>::zero();
631 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i] - delta;
633 rowSumDeviation = rowSumDeviation - closestToLeftBoundDist;
634 fixedSorted[closestToLeftBound] = leftBound;
635 closestToLeftBound++;
636 if (closestToLeftBound < nEntries)
637 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
639 closestToLeftBoundDist = aBigNumber;
642 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
644 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i] - delta;
646 rowSumDeviation = rowSumDeviation + closestToRghtBoundDist;
648 fixedSorted[closestToRghtBound] = origSorted[closestToRghtBound];
649 closestToRghtBound++;
651 if (closestToRghtBound >= nEntries)
652 closestToRghtBoundDist = aBigNumber;
654 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
662 if ((nEntries % 2) == 1) fixedSorted[(nEntries / 2)] = -fixedSorted[(nEntries / 2)];
664 temp = fixedSorted[i];
665 fixedSorted[i] = -fixedSorted[nEntries - 1 - i];
666 fixedSorted[nEntries - i - 1] = -temp;
669 for (
LocalOrdinal i = 0; i < nEntries; i++) fixedUnsorted[inds[i]] = fixedSorted[i];
673 bool lowerViolation =
false;
674 bool upperViolation =
false;
675 bool sumViolation =
false;
676 using TST = Teuchos::ScalarTraits<SC>;
679 if (TST::real(fixedUnsorted[i]) < TST::real(notFlippedLeftBound)) lowerViolation =
true;
680 if (TST::real(fixedUnsorted[i]) > TST::real(notFlippedRghtBound)) upperViolation =
true;
681 temp += fixedUnsorted[i];
683 SC tol = as<Scalar>(std::max(1.0e-8, as<double>(100 * TST::eps())));
684 if (TST::magnitude(temp - rsumTarget) > TST::magnitude(tol * rsumTarget)) sumViolation =
true;
686 TEUCHOS_TEST_FOR_EXCEPTION(lowerViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a lower bound violation??? ");
687 TEUCHOS_TEST_FOR_EXCEPTION(upperViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in an upper bound violation??? ");
688 TEUCHOS_TEST_FOR_EXCEPTION(sumViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a row sum violation??? ");
690 return hasFeasibleSol;
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Jacobi(Scalar omega, const Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Dinv, const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > C_in, Teuchos::FancyOStream &fos, const std::string &label, RCP< ParameterList > ¶ms)