300 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
301 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
302 LO nPDEs = A->GetFixedBlockSize();
303 Teuchos::ArrayRCP<Scalar> ConstraintViolationSum(nPDEs);
304 Teuchos::ArrayRCP<Scalar> Rsum(nPDEs);
305 Teuchos::ArrayRCP<size_t> nPositive(nPDEs);
306 for (
size_t k = 0; k < (size_t)nPDEs; k++) ConstraintViolationSum[k] = zero;
307 for (
size_t k = 0; k < (size_t)nPDEs; k++) Rsum[k] = zero;
308 for (
size_t k = 0; k < (size_t)nPDEs; k++) nPositive[k] = 0;
310 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
311 Teuchos::ArrayView<const LocalOrdinal> indices;
312 Teuchos::ArrayView<const Scalar> vals1;
313 Teuchos::ArrayView<Scalar> vals;
314 P->getLocalRowView((LO)i, indices, vals1);
315 size_t nnz = indices.size();
316 if (nnz == 0)
continue;
318 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
320 bool checkRow =
true;
325 for (LO j = 0; j < indices.size(); j++) {
326 Rsum[j % nPDEs] += vals[j];
327 if (Teuchos::ScalarTraits<SC>::real(vals[j]) < Teuchos::ScalarTraits<SC>::real(zero)) {
328 ConstraintViolationSum[j % nPDEs] += vals[j];
331 if (Teuchos::ScalarTraits<SC>::real(vals[j]) != Teuchos::ScalarTraits<SC>::real(zero))
332 (nPositive[j % nPDEs])++;
334 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(1.00001)) {
335 ConstraintViolationSum[j % nPDEs] += (vals[j] - one);
345 for (
size_t k = 0; k < (size_t)nPDEs; k++) {
346 if (Teuchos::ScalarTraits<SC>::real(Rsum[k]) < Teuchos::ScalarTraits<SC>::magnitude(zero)) {
347 ConstraintViolationSum[k] += (-Rsum[k]);
348 }
else if (Teuchos::ScalarTraits<SC>::real(Rsum[k]) > Teuchos::ScalarTraits<SC>::magnitude(1.00001)) {
349 ConstraintViolationSum[k] += (one - Rsum[k]);
354 for (
size_t k = 0; k < (size_t)nPDEs; k++) {
355 if (Teuchos::ScalarTraits<SC>::magnitude(ConstraintViolationSum[k]) != Teuchos::ScalarTraits<SC>::magnitude(zero))
360 for (LO j = 0; j < indices.size(); j++) {
361 if (Teuchos::ScalarTraits<SC>::real(vals[j]) > Teuchos::ScalarTraits<SC>::real(zero)) {
362 vals[j] += (ConstraintViolationSum[j % nPDEs] / (as<Scalar>(nPositive[j % nPDEs])));
365 for (
size_t k = 0; k < (size_t)nPDEs; k++) ConstraintViolationSum[k] = zero;
367 for (
size_t k = 0; k < (size_t)nPDEs; k++) Rsum[k] = zero;
368 for (
size_t k = 0; k < (size_t)nPDEs; k++) nPositive[k] = 0;
375 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
376 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
379 Teuchos::ArrayRCP<Scalar> scalarData(3 * maxEntriesPerRow);
382 for (
size_t i = 0; i < as<size_t>(P->getRowMap()->getLocalNumElements()); i++) {
383 Teuchos::ArrayView<const LocalOrdinal> indices;
384 Teuchos::ArrayView<const Scalar> vals1;
385 Teuchos::ArrayView<Scalar> vals;
387 size_t nnz = indices.size();
389 vals = ArrayView<Scalar>(
const_cast<SC*
>(vals1.getRawPtr()), nnz);
391 for (
size_t j = 0; j < nnz; j++) rsumTarget += vals[j];
393 if (nnz > as<size_t>(maxEntriesPerRow)) {
394 maxEntriesPerRow = nnz * 3;
395 scalarData.resize(3 * maxEntriesPerRow);
397 hasFeasible = constrainRow(vals.getRawPtr(), as<LocalOrdinal>(nnz), zero, one, rsumTarget, vals.getRawPtr(), scalarData.getRawPtr());
400 for (
size_t j = 0; j < nnz; j++) vals[j] = one / as<Scalar>(nnz);
526 Scalar notFlippedLeftBound, notFlippedRghtBound, aBigNumber, *origSorted;
527 Scalar rowSumDeviation, temp, *fixedSorted, delta;
528 Scalar closestToLeftBoundDist, closestToRghtBoundDist;
533 notFlippedLeftBound = leftBound;
534 notFlippedRghtBound = rghtBound;
536 if ((Teuchos::ScalarTraits<SC>::real(rsumTarget) >= Teuchos::ScalarTraits<SC>::real(leftBound * as<Scalar>(nEntries))) &&
537 (Teuchos::ScalarTraits<SC>::real(rsumTarget) <= Teuchos::ScalarTraits<SC>::real(rghtBound * as<Scalar>(nEntries))))
538 hasFeasibleSol =
true;
540 hasFeasibleSol =
false;
541 return hasFeasibleSol;
546 aBigNumber = Teuchos::ScalarTraits<SC>::zero();
548 if (Teuchos::ScalarTraits<SC>::magnitude(orig[i]) > Teuchos::ScalarTraits<SC>::magnitude(aBigNumber))
549 aBigNumber = Teuchos::ScalarTraits<SC>::magnitude(orig[i]);
551 aBigNumber = aBigNumber + (Teuchos::ScalarTraits<SC>::magnitude(leftBound) + Teuchos::ScalarTraits<SC>::magnitude(rghtBound)) * as<Scalar>(100.0);
553 origSorted = &scalarData[0];
554 fixedSorted = &(scalarData[nEntries]);
557 for (
LocalOrdinal i = 0; i < nEntries; i++) inds[i] = i;
558 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[i];
561 std::sort(inds, inds + nEntries,
562 [origSorted](
LocalOrdinal leftIndex,
LocalOrdinal rightIndex) {
return Teuchos::ScalarTraits<SC>::real(origSorted[leftIndex]) < Teuchos::ScalarTraits<SC>::real(origSorted[rightIndex]); });
564 for (
LocalOrdinal i = 0; i < nEntries; i++) origSorted[i] = orig[inds[i]];
566 closestToLeftBound = 0;
567 while ((closestToLeftBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToLeftBound]) <= Teuchos::ScalarTraits<SC>::real(leftBound))) closestToLeftBound++;
570 closestToRghtBound = closestToLeftBound;
571 while ((closestToRghtBound < nEntries) && (Teuchos::ScalarTraits<SC>::real(origSorted[closestToRghtBound]) <= Teuchos::ScalarTraits<SC>::real(rghtBound))) closestToRghtBound++;
576 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
577 if (closestToRghtBound == nEntries)
578 closestToRghtBoundDist = aBigNumber;
580 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
585 rowSumDeviation = leftBound * as<Scalar>(closestToLeftBound) + as<Scalar>((nEntries - closestToRghtBound)) * rghtBound - rsumTarget;
586 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) rowSumDeviation += origSorted[i];
591 if (Teuchos::ScalarTraits<SC>::real(rowSumDeviation) < Teuchos::ScalarTraits<SC>::real(Teuchos::ScalarTraits<SC>::zero())) {
594 leftBound = -rghtBound;
599 if ((nEntries % 2) == 1) origSorted[(nEntries / 2)] = -origSorted[(nEntries / 2)];
601 temp = origSorted[i];
602 origSorted[i] = -origSorted[nEntries - 1 - i];
603 origSorted[nEntries - i - 1] = -temp;
609 closestToLeftBound = nEntries - closestToRghtBound;
610 closestToRghtBound = nEntries - itemp;
611 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
612 if (closestToRghtBound == nEntries)
613 closestToRghtBoundDist = aBigNumber;
615 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
617 rowSumDeviation = -rowSumDeviation;
622 for (
LocalOrdinal i = 0; i < closestToLeftBound; i++) fixedSorted[i] = leftBound;
623 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i];
624 for (
LocalOrdinal i = closestToRghtBound; i < nEntries; i++) fixedSorted[i] = rghtBound;
626 while ((Teuchos::ScalarTraits<SC>::magnitude(rowSumDeviation) > Teuchos::ScalarTraits<SC>::magnitude(as<Scalar>(1.e-10) * rsumTarget))) {
627 if (closestToRghtBound != closestToLeftBound)
628 delta = rowSumDeviation / as<Scalar>(closestToRghtBound - closestToLeftBound);
632 if (Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
633 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToLeftBoundDist)) {
634 rowSumDeviation = Teuchos::ScalarTraits<SC>::zero();
635 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i] - delta;
637 rowSumDeviation = rowSumDeviation - closestToLeftBoundDist;
638 fixedSorted[closestToLeftBound] = leftBound;
639 closestToLeftBound++;
640 if (closestToLeftBound < nEntries)
641 closestToLeftBoundDist = origSorted[closestToLeftBound] - leftBound;
643 closestToLeftBoundDist = aBigNumber;
646 if (Teuchos::ScalarTraits<SC>::magnitude(delta) <= Teuchos::ScalarTraits<SC>::magnitude(closestToRghtBoundDist)) {
648 for (
LocalOrdinal i = closestToLeftBound; i < closestToRghtBound; i++) fixedSorted[i] = origSorted[i] - delta;
650 rowSumDeviation = rowSumDeviation + closestToRghtBoundDist;
652 fixedSorted[closestToRghtBound] = origSorted[closestToRghtBound];
653 closestToRghtBound++;
655 if (closestToRghtBound >= nEntries)
656 closestToRghtBoundDist = aBigNumber;
658 closestToRghtBoundDist = origSorted[closestToRghtBound] - rghtBound;
666 if ((nEntries % 2) == 1) fixedSorted[(nEntries / 2)] = -fixedSorted[(nEntries / 2)];
668 temp = fixedSorted[i];
669 fixedSorted[i] = -fixedSorted[nEntries - 1 - i];
670 fixedSorted[nEntries - i - 1] = -temp;
673 for (
LocalOrdinal i = 0; i < nEntries; i++) fixedUnsorted[inds[i]] = fixedSorted[i];
677 bool lowerViolation =
false;
678 bool upperViolation =
false;
679 bool sumViolation =
false;
680 using TST = Teuchos::ScalarTraits<SC>;
683 if (TST::real(fixedUnsorted[i]) < TST::real(notFlippedLeftBound)) lowerViolation =
true;
684 if (TST::real(fixedUnsorted[i]) > TST::real(notFlippedRghtBound)) upperViolation =
true;
685 temp += fixedUnsorted[i];
687 SC tol = as<Scalar>(std::max(1.0e-8, as<double>(100 * TST::eps())));
688 if (TST::magnitude(temp - rsumTarget) > TST::magnitude(tol * rsumTarget)) sumViolation =
true;
690 TEUCHOS_TEST_FOR_EXCEPTION(lowerViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a lower bound violation??? ");
691 TEUCHOS_TEST_FOR_EXCEPTION(upperViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in an upper bound violation??? ");
692 TEUCHOS_TEST_FOR_EXCEPTION(sumViolation,
Exceptions::RuntimeError,
"MueLu::SaPFactory::constrainRow: feasible solution but computation resulted in a row sum violation??? ");
694 return hasFeasibleSol;