118 const std::string prefix =
"MueLu::SaPFactory(" + levelIDs +
"): ";
120 typedef typename Teuchos::ScalarTraits<SC>::coordinateType Coordinate;
121 typedef typename Teuchos::ScalarTraits<SC>::magnitudeType MT;
127 RCP<const FactoryBase> initialPFact =
GetFactory(
"P");
128 if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.
GetFactoryManager()->GetFactory(
"Ptent"); }
133 RCP<Matrix> Ptent = coarseLevel.
Get< RCP<Matrix> >(
"P", initialPFact.get());
137 if (Ptent == Teuchos::null) {
138 finalP = Teuchos::null;
139 Set(coarseLevel,
"P", finalP);
151 RCP<ParameterList> APparams = rcp(
new ParameterList);;
152 if(pL.isSublist(
"matrixmatrix: kernel params"))
153 APparams->sublist(
"matrixmatrix: kernel params") = pL.sublist(
"matrixmatrix: kernel params");
155 if (coarseLevel.
IsAvailable(
"AP reuse data",
this)) {
158 APparams = coarseLevel.
Get< RCP<ParameterList> >(
"AP reuse data",
this);
160 if (APparams->isParameter(
"graph"))
161 finalP = APparams->get< RCP<Matrix> >(
"graph");
164 APparams->set(
"compute global constants: temporaries",APparams->get(
"compute global constants: temporaries",
false));
165 APparams->set(
"compute global constants",APparams->get(
"compute global constants",
false));
167 const SC dampingFactor = as<SC>(pL.get<
double>(
"sa: damping factor"));
168 const LO maxEigenIterations = as<LO>(pL.get<
int> (
"sa: eigenvalue estimate num iterations"));
169 const bool estimateMaxEigen = pL.get<
bool> (
"sa: calculate eigenvalue estimate");
170 const bool useAbsValueRowSum= pL.get<
bool> (
"sa: use rowsumabs diagonal scaling");
171 const bool doQRStep = pL.get<
bool>(
"tentative: calculate qr");
172 const bool enforceConstraints= pL.get<
bool>(
"sa: enforce constraints");
173 const MT userDefinedMaxEigen = as<MT>(pL.get<
double>(
"sa: max eigenvalue"));
174 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
175 double dTol = pL.get<
double>(
"sa: rowsumabs diagonal replacement tolerance");
176 const Magnitude diagonalReplacementTolerance = (dTol == as<double>(-1) ? Teuchos::ScalarTraits<Scalar>::eps()*100 : as<Magnitude>(pL.get<
double>(
"sa: rowsumabs diagonal replacement tolerance")));
177 const SC diagonalReplacementValue = as<SC>(pL.get<
double>(
"sa: rowsumabs diagonal replacement value"));
178 const bool replaceSingleEntryRowWithZero = pL.get<
bool>(
"sa: rowsumabs replace single entry row with zero");
179 const bool useAutomaticDiagTol = pL.get<
bool>(
"sa: rowsumabs use automatic diagonal tolerance");
183 "MueLu::TentativePFactory::MakeTentative: cannot use 'enforce constraints' and 'calculate qr' at the same time");
185 if (dampingFactor != Teuchos::ScalarTraits<SC>::zero()) {
188 Teuchos::RCP<Vector> invDiag;
189 if (userDefinedMaxEigen == -1.)
192 lambdaMax = A->GetMaxEigenvalueEstimate();
193 if (lambdaMax == -Teuchos::ScalarTraits<SC>::one() || estimateMaxEigen) {
194 GetOStream(
Statistics1) <<
"Calculating max eigenvalue estimate now (max iters = "<< maxEigenIterations <<
195 ( (useAbsValueRowSum) ?
", use rowSumAbs diagonal)" :
", use point diagonal)") << std::endl;
196 Coordinate stopTol = 1e-4;
197 if (useAbsValueRowSum) {
198 const bool returnReciprocal=
true;
200 diagonalReplacementTolerance,
201 diagonalReplacementValue,
202 replaceSingleEntryRowWithZero,
203 useAutomaticDiagTol);
205 "SaPFactory: eigenvalue estimate: diagonal reciprocal is null.");
209 A->SetMaxEigenvalueEstimate(lambdaMax);
215 lambdaMax = userDefinedMaxEigen;
216 A->SetMaxEigenvalueEstimate(lambdaMax);
218 GetOStream(
Statistics1) <<
"Prolongator damping factor = " << dampingFactor/lambdaMax <<
" (" << dampingFactor <<
" / " << lambdaMax <<
")" << std::endl;
222 if (!useAbsValueRowSum)
224 else if (invDiag == Teuchos::null) {
226 const bool returnReciprocal=
true;
228 diagonalReplacementTolerance,
229 diagonalReplacementValue,
230 replaceSingleEntryRowWithZero,
231 useAutomaticDiagTol);
232 TEUCHOS_TEST_FOR_EXCEPTION(invDiag.is_null(),
Exceptions::RuntimeError,
"SaPFactory: diagonal reciprocal is null.");
235 SC omega = dampingFactor / lambdaMax;
236 TEUCHOS_TEST_FOR_EXCEPTION(!std::isfinite(Teuchos::ScalarTraits<SC>::magnitude(omega)),
Exceptions::RuntimeError,
"Prolongator damping factor needs to be finite.");
239 finalP = Xpetra::IteratorOps<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Jacobi(omega, *invDiag, *A, *Ptent, finalP,
241 if (enforceConstraints) {
254 if(!finalP.is_null()) {std::ostringstream oss; oss <<
"P_" << coarseLevel.
GetLevelID(); finalP->setObjectLabel(oss.str());}
255 Set(coarseLevel,
"P", finalP);
257 APparams->set(
"graph", finalP);
258 Set(coarseLevel,
"AP reuse data", APparams);
261 if (Ptent->IsView(
"stridedMaps"))
262 finalP->CreateView(
"stridedMaps", Ptent);
265 RCP<ParameterList> params = rcp(
new ParameterList());
266 params->set(
"printLoadBalancingInfo",
true);
267 params->set(
"printCommInfo",
true);
277 if(!R.is_null()) {std::ostringstream oss; oss <<
"R_" << coarseLevel.
GetLevelID(); R->setObjectLabel(oss.str());}
280 Set(coarseLevel,
"R", R);
283 if (Ptent->IsView(
"stridedMaps"))
284 R->CreateView(
"stridedMaps", Ptent,
true);
287 RCP<ParameterList> params = rcp(
new ParameterList());
288 params->set(
"printLoadBalancingInfo",
true);
289 params->set(
"printCommInfo",
true);
315 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
316 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
317 LO nPDEs = A->GetFixedBlockSize();
318 Teuchos::ArrayRCP<Scalar> ConstraintViolationSum(nPDEs);
319 Teuchos::ArrayRCP<Scalar> Rsum(nPDEs);
320 Teuchos::ArrayRCP<size_t> nPositive(nPDEs);
321 for (
size_t k=0; k < (size_t) nPDEs; k++) ConstraintViolationSum[k] = zero;
322 for (
size_t k=0; k < (size_t) nPDEs; k++) Rsum[k] = zero;
323 for (
size_t k=0; k < (size_t) nPDEs; k++) nPositive[k] = 0;
326 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
328 Teuchos::ArrayView<const LocalOrdinal> indices;
329 Teuchos::ArrayView<const Scalar> vals1;
330 Teuchos::ArrayView< Scalar> vals;
331 P->getLocalRowView((LO) i, indices, vals1);
332 size_t nnz = indices.size();
333 if (nnz == 0)
continue;
335 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
338 bool checkRow =
true;
344 for (LO j = 0; j < indices.size(); j++) {
345 Rsum[ j%nPDEs ] += vals[j];
346 if (Teuchos::ScalarTraits<SC>::real(vals[j]) < Teuchos::ScalarTraits<SC>::real(zero)) {
347 ConstraintViolationSum[ j%nPDEs ] += vals[j];
351 if (Teuchos::ScalarTraits<SC>::real(vals[j]) != Teuchos::ScalarTraits<SC>::real(zero))
352 (nPositive[ j%nPDEs])++;
354 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(1.00001 )) {
355 ConstraintViolationSum[ j%nPDEs ] += (vals[j] - one);
365 for (
size_t k=0; k < (size_t) nPDEs; k++) {
367 if (Teuchos::ScalarTraits<SC>::real(Rsum[ k ]) < Teuchos::ScalarTraits<SC>::magnitude(zero)) {
368 ConstraintViolationSum[k] += (-Rsum[k]);
370 else if (Teuchos::ScalarTraits<SC>::real(Rsum[ k ]) > Teuchos::ScalarTraits<SC>::magnitude(1.00001)) {
371 ConstraintViolationSum[k] += (one - Rsum[k]);
376 for (
size_t k=0; k < (size_t) nPDEs; k++) {
377 if (Teuchos::ScalarTraits<SC>::magnitude(ConstraintViolationSum[ k ]) != Teuchos::ScalarTraits<SC>::magnitude(zero))
382 for (LO j = 0; j < indices.size(); j++) {
383 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(zero)) {
384 vals[j] += (ConstraintViolationSum[j%nPDEs]/ (as<Scalar>(nPositive[j%nPDEs])));
387 for (
size_t k=0; k < (size_t) nPDEs; k++) ConstraintViolationSum[k] = zero;
389 for (
size_t k=0; k < (size_t) nPDEs; k++) Rsum[k] = zero;
390 for (
size_t k=0; k < (size_t) nPDEs; k++) nPositive[k] = 0;
398 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
399 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
402 Teuchos::ArrayRCP<Scalar> scalarData(3*maxEntriesPerRow);
405 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
407 Teuchos::ArrayView<const LocalOrdinal> indices;
408 Teuchos::ArrayView<const Scalar> vals1;
409 Teuchos::ArrayView< Scalar> vals;
411 size_t nnz = indices.size();
414 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
416 for (
size_t j = 0; j < nnz; j++) rsumTarget += vals[j];
418 if (nnz > as<size_t>(maxEntriesPerRow)) {
419 maxEntriesPerRow = nnz*3;
420 scalarData.resize(3*maxEntriesPerRow);
422 hasFeasible =
constrainRow(vals.getRawPtr(), as<LocalOrdinal>(nnz), zero , one, rsumTarget, vals.getRawPtr(), scalarData.getRawPtr());
425 for (
size_t j = 0; j < nnz; j++) vals[j] = one/as<Scalar>(nnz);
551 Scalar notFlippedLeftBound, notFlippedRghtBound, aBigNumber, *origSorted;
552 Scalar rowSumDeviation, temp, *fixedSorted, delta;
553 Scalar closestToLeftBoundDist, closestToRghtBoundDist;
558 notFlippedLeftBound = leftBound;
559 notFlippedRghtBound = rghtBound;
561 if ((Teuchos::ScalarTraits<SC>::real(rsumTarget) >= Teuchos::ScalarTraits<SC>::real(leftBound*as<Scalar>(nEntries))) &&
562 (Teuchos::ScalarTraits<SC>::real(rsumTarget) <= Teuchos::ScalarTraits<SC>::real(rghtBound*as<Scalar>(nEntries))))
563 hasFeasibleSol =
true;
565 hasFeasibleSol=
false;
566 return hasFeasibleSol;
571 aBigNumber = Teuchos::ScalarTraits<SC>::zero();
573 if ( Teuchos::ScalarTraits<SC>::magnitude(orig[i]) > Teuchos::ScalarTraits<SC>::magnitude(aBigNumber))
574 aBigNumber = Teuchos::ScalarTraits<SC>::magnitude(orig[i]);
576 aBigNumber = aBigNumber+ (Teuchos::ScalarTraits<SC>::magnitude(leftBound) + Teuchos::ScalarTraits<SC>::magnitude(rghtBound))*as<Scalar>(100.0);
578 origSorted = &scalarData[0];
579 fixedSorted = &(scalarData[nEntries]);
582 for (
LocalOrdinal i = 0; i < nEntries; i++) inds[i] = i;
583 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[i];
586 std::sort(inds, inds+nEntries,
588 {
return Teuchos::ScalarTraits<SC>::real(origSorted[leftIndex]) < Teuchos::ScalarTraits<SC>::real(origSorted[rightIndex]);});
590 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[inds[i]];
592 closestToLeftBound = 0;
593 while ((closestToLeftBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToLeftBound]) <= Teuchos::ScalarTraits<SC>::real(leftBound))) closestToLeftBound++;
596 closestToRghtBound = closestToLeftBound;
597 while ((closestToRghtBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToRghtBound]) <= Teuchos::ScalarTraits<SC>::real(rghtBound))) closestToRghtBound++;
602 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
603 if (closestToRghtBound==nEntries) closestToRghtBoundDist= aBigNumber;
604 else closestToRghtBoundDist= origSorted[closestToRghtBound] - rghtBound;
609 rowSumDeviation = leftBound*as<Scalar>(closestToLeftBound) + as<Scalar>((nEntries-closestToRghtBound))*rghtBound - rsumTarget;
610 for (
LocalOrdinal i=closestToLeftBound; i < closestToRghtBound; i++) rowSumDeviation += origSorted[i];
615 if (Teuchos::ScalarTraits<SC>::real(rowSumDeviation) < Teuchos::ScalarTraits<SC>::real(Teuchos::ScalarTraits<SC>::zero())) {
617 temp = leftBound; leftBound = -rghtBound; rghtBound = temp;
621 if ((nEntries%2) == 1) origSorted[(nEntries/2) ] = -origSorted[(nEntries/2) ];
624 origSorted[i] = -origSorted[nEntries-1-i];
625 origSorted[nEntries-i-1] = -temp;
631 closestToLeftBound = nEntries-closestToRghtBound;
632 closestToRghtBound = nEntries-itemp;
633 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
634 if (closestToRghtBound==nEntries) closestToRghtBoundDist= aBigNumber;
635 else closestToRghtBoundDist= origSorted[closestToRghtBound] - rghtBound;
637 rowSumDeviation = -rowSumDeviation;
642 for (
LocalOrdinal i = 0; i < closestToLeftBound; i++) fixedSorted[i] = leftBound;
643 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i];
644 for (
LocalOrdinal i = closestToRghtBound; i < nEntries; i++) fixedSorted[i] = rghtBound;
646 while ((Teuchos::ScalarTraits<SC>::magnitude(rowSumDeviation) > Teuchos::ScalarTraits<SC>::magnitude(as<Scalar>(1.e-10)*rsumTarget))){
647 if (closestToRghtBound != closestToLeftBound)
648 delta = rowSumDeviation/ as<Scalar>(closestToRghtBound - closestToLeftBound);
649 else delta = aBigNumber;
651 if (Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
652 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist)) {
653 rowSumDeviation = Teuchos::ScalarTraits<SC>::zero();
654 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound ; i++) fixedSorted[i] = origSorted[i] - delta;
657 rowSumDeviation = rowSumDeviation - closestToLeftBoundDist;
658 fixedSorted[closestToLeftBound] = leftBound;
659 closestToLeftBound++;
660 if (closestToLeftBound < nEntries) closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
661 else closestToLeftBoundDist = aBigNumber;
665 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
667 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound ; i++) fixedSorted[i] = origSorted[i] - delta;
670 rowSumDeviation = rowSumDeviation + closestToRghtBoundDist;
672 fixedSorted[closestToRghtBound] = origSorted[closestToRghtBound];
673 closestToRghtBound++;
675 if (closestToRghtBound >= nEntries) closestToRghtBoundDist = aBigNumber;
676 else closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
684 if ((nEntries%2) == 1) fixedSorted[(nEntries/2) ] = -fixedSorted[(nEntries/2) ];
687 fixedSorted[i] = -fixedSorted[nEntries-1-i];
688 fixedSorted[nEntries-i-1] = -temp;
691 for (
LocalOrdinal i = 0; i < nEntries; i++) fixedUnsorted[inds[i]] = fixedSorted[i];
695 bool lowerViolation =
false;
696 bool upperViolation =
false;
697 bool sumViolation =
false;
698 using TST = Teuchos::ScalarTraits<SC>;
701 if (TST::real(fixedUnsorted[i]) < TST::real(notFlippedLeftBound)) lowerViolation =
true;
702 if (TST::real(fixedUnsorted[i]) > TST::real(notFlippedRghtBound)) upperViolation =
true;
703 temp += fixedUnsorted[i];
705 SC tol = as<Scalar>(std::max(1.0e-8, as<double>(100*TST::eps())));
706 if (TST::magnitude(temp - rsumTarget) > TST::magnitude(tol*rsumTarget)) sumViolation =
true;
708 TEUCHOS_TEST_FOR_EXCEPTION(lowerViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a lower bound violation??? ");
709 TEUCHOS_TEST_FOR_EXCEPTION(upperViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in an upper bound violation??? ");
710 TEUCHOS_TEST_FOR_EXCEPTION(sumViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a row sum violation??? ");
712 return hasFeasibleSol;