13#ifndef __BelosTsqrOrthoManagerImpl_hpp
14#define __BelosTsqrOrthoManagerImpl_hpp
21#include "Teuchos_as.hpp"
22#include "Teuchos_ParameterList.hpp"
23#include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
24#ifdef BELOS_TEUCHOS_TIME_MONITOR
25# include "Teuchos_TimeMonitor.hpp"
98 template<
class Scalar>
122 template<
class Scalar>
156 template<
class Scalar,
class MV,
class DM>
158 public Teuchos::ParameterListAcceptorDefaultBase {
168 typedef Teuchos::ScalarTraits<Scalar> SCT;
169 typedef Teuchos::ScalarTraits<magnitude_type> SCTM;
172 typedef typename MVT::tsqr_adaptor_type tsqr_adaptor_type;
216 const std::string&
label);
257 if (
label != label_) {
260#ifdef BELOS_TEUCHOS_TIME_MONITOR
273 const std::string&
getLabel ()
const {
return label_; }
286 MVT::MvTransMv (SCT::one(),
X, Y, Z);
307 norm (
const MV&
X, std::vector<magnitude_type>&
normVec)
const;
320 Teuchos::Array<mat_ptr> C,
321 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q);
374 Teuchos::Array<mat_ptr> C,
376 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
380 return projectAndNormalizeImpl (
X,
X,
false, C, B,
Q);
405 Teuchos::Array<mat_ptr> C,
407 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
411 return projectAndNormalizeImpl (
X_in,
X_out,
true, C, B,
Q);
422 const int ncols = MVT::GetNumberVecs(
X);
425 DMT::SyncDeviceToHost( *
XTX );
429 DMT::SyncHostToDevice( *
XTX );
430 return DMT::NormFrobenius( *
XTX );
442 return DMT::NormFrobenius( *
X1_T_X2 );
456 Teuchos::RCP<Teuchos::ParameterList> params_;
459 mutable Teuchos::RCP<const Teuchos::ParameterList> defaultParams_;
465 tsqr_adaptor_type tsqrAdaptor_;
484 bool randomizeNullSpace_;
491 bool reorthogonalizeBlocks_;
496 bool throwOnReorthogFault_;
510 bool forceNonnegativeDiagonal_;
512#ifdef BELOS_TEUCHOS_TIME_MONITOR
524 Teuchos::RCP<ReorthogonalizationCallback<Scalar> > reorthogCallback_;
526#ifdef BELOS_TEUCHOS_TIME_MONITOR
535 static Teuchos::RCP<Teuchos::Time>
541 return Teuchos::TimeMonitor::getNewCounter (
timerLabel);
550 clearTimer (
const std::string& prefix,
551 const std::string& timerName)
553 const std::string timerLabel =
554 prefix.empty() ? timerName : (prefix +
": " + timerName);
555 Teuchos::TimeMonitor::clearCounter (timerLabel);
561 raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
562 const std::vector<magnitude_type>& normsAfterSecondPass,
563 const std::vector<int>& faultIndices);
575 checkProjectionDims (
int& ncols_X,
579 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const;
592 allocateProjectionCoefficients (Teuchos::Array<mat_ptr>& C,
593 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
595 const bool attemptToRecycle =
true)
const;
606 projectAndNormalizeImpl (MV& X_in,
608 const bool outOfPlace,
609 Teuchos::Array<mat_ptr> C,
611 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q);
620 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
621 Teuchos::ArrayView<mat_ptr> C)
const;
626 const Teuchos::RCP<const MV>& Q,
655 int rawNormalize (MV& X, MV& Q,
mat_type& B);
674 int normalizeOne (MV& X,
mat_ptr B)
const;
703 int normalizeImpl (MV& X, MV& Q,
mat_ptr B,
const bool outOfPlace);
706 template<
class Scalar,
class MV,
class DM>
711 using Teuchos::ParameterList;
712 using Teuchos::parameterList;
714 using Teuchos::sublist;
731 randomizeNullSpace_ =
732 theParams->get<
bool> (
"randomizeNullSpace",
734 reorthogonalizeBlocks_ =
735 theParams->get<
bool> (
"reorthogonalizeBlocks",
737 throwOnReorthogFault_ =
738 theParams->get<
bool> (
"throwOnReorthogFault",
740 blockReorthogThreshold_ =
743 relativeRankTolerance_ =
746 forceNonnegativeDiagonal_ =
747 theParams->get<
bool> (
"forceNonnegativeDiagonal",
752 if (!
theParams->isSublist (
"TSQR implementation")) {
766 template<
class Scalar,
class MV,
class DM>
769 const std::string&
label) :
773 randomizeNullSpace_ (
true),
774 reorthogonalizeBlocks_ (
true),
775 throwOnReorthogFault_ (
false),
776 blockReorthogThreshold_ (0),
777 relativeRankTolerance_ (0),
778 forceNonnegativeDiagonal_ (
false)
782#ifdef BELOS_TEUCHOS_TIME_MONITOR
789 template<
class Scalar,
class MV,
class DM>
795 randomizeNullSpace_ (
true),
796 reorthogonalizeBlocks_ (
true),
797 throwOnReorthogFault_ (
false),
798 blockReorthogThreshold_ (0),
799 relativeRankTolerance_ (0),
800 forceNonnegativeDiagonal_ (
false)
804#ifdef BELOS_TEUCHOS_TIME_MONITOR
811 template<
class Scalar,
class MV,
class DM>
814 norm (
const MV&
X, std::vector<magnitude_type>&
normVec)
const
816 const int numCols = MVT::GetNumberVecs (
X);
824 template<
class Scalar,
class MV,
class DM>
827 Teuchos::Array<mat_ptr> C,
828 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
830#ifdef BELOS_TEUCHOS_TIME_MONITOR
850 allocateProjectionCoefficients (C,
Q,
X,
true);
855 if (reorthogonalizeBlocks_)
860 rawProject (
X,
Q, C);
864 if (reorthogonalizeBlocks_) {
884 if (! reorthogCallback_.is_null()) {
889 Teuchos::Array<mat_ptr>
C2;
890 allocateProjectionCoefficients (
C2,
Q,
X,
false);
894 rawProject (
X,
Q,
C2);
897 DMT::Add(*C[
k],*
C2[
k]);
903 template<
class Scalar,
class MV,
class DM>
907 using Teuchos::Range1D;
910#ifdef BELOS_TEUCHOS_TIME_MONITOR
922 const int numCols = MVT::GetNumberVecs (
X);
931 return normalizeOne (
X, B);
961 MVT::GetGlobalLength(*Q_) != MVT::GetGlobalLength(
X) ||
962 numCols > MVT::GetNumberVecs (*Q_)) {
972 if (MVT::GetNumberVecs(*Q_) ==
numCols) {
973 return normalizeImpl (
X, *Q_, B,
false);
976 return normalizeImpl (
X, *
Q_view, B,
false);
980 template<
class Scalar,
class MV,
class DM>
984 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q,
989 const int ncols_X = MVT::GetNumberVecs (
X);
995 const int ncols_Qi = MVT::GetNumberVecs (*
Q[
i]);
1002 mat_type&
Ci = *C[
i];
1006 DMT::PutScalar(
Ci, SCT::zero());
1014 const int ncols_Qi = MVT::GetNumberVecs (*
Q[
i]);
1020 template<
class Scalar,
class MV,
class DM>
1025#ifdef BELOS_TEUCHOS_TIME_MONITOR
1030 const int numVecs = MVT::GetNumberVecs(
X);
1035 using Teuchos::Range1D;
1040 const int rank = normalizeOne (
X, B);
1043 MVT::Assign (
X, *
Q_0);
1049 return normalizeImpl (
X,
Q, B,
true);
1053 template<
class Scalar,
class MV,
class DM>
1059 Teuchos::Array<mat_ptr> C,
1061 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
1063 using Teuchos::Range1D;
1067#ifdef BELOS_TEUCHOS_TIME_MONITOR
1076 std::invalid_argument,
1077 "Belos::TsqrOrthoManagerImpl::"
1078 "projectAndNormalizeImpl(..., outOfPlace=true, ...):"
1079 "X_out has " << MVT::GetNumberVecs(
X_out)
1080 <<
" columns, but X_in has "
1081 << MVT::GetNumberVecs(
X_in) <<
" columns.");
1095 return normalizeOutOfPlace (
X_in,
X_out, B);
1097 return normalize (
X_in, B);
1104 allocateProjectionCoefficients (C,
Q,
X_in,
true);
1110 if (reorthogonalizeBlocks_) {
1115 rawProject (
X_in,
Q, C);
1132 DMT::GetNumCols(*B) <
ncols_X,
1133 std::invalid_argument,
1134 "normalizeOne: Input matrix B must be at "
1136 <<
", but is instead " << DMT::GetNumRows(*B)
1137 <<
" x " << DMT::GetNumCols(*B) <<
".");
1217 "Belos::TsqrOrthoManagerImpl::projectAndNormalize"
1218 "OutOfPlace(): After projecting and normalizing the "
1219 "random vectors (used to replace the null space "
1220 "basis vectors from normalizing X), they have rank "
1227 if (reorthogonalizeBlocks_) {
1230 std::vector<magnitude_type>
1232 std::vector<magnitude_type>
1247 Teuchos::BLAS<int, Scalar>
blas;
1248 DMT::SyncDeviceToHost( *
B_out );
1275 if (! reorthogCallback_.is_null()) {
1276 using Teuchos::arrayViewFromVector;
1296 using Teuchos::Copy;
1297 using Teuchos::NO_TRANS;
1309 Teuchos::Array<mat_ptr>
C2;
1310 allocateProjectionCoefficients (
C2,
Q,
X_in,
false);
1331 DMT::SyncDeviceToHost( *
B2 );
1332 DMT::SyncDeviceToHost( *
B_out );
1334 DMT::GetNumCols( *
B2 ), SCT::one(), DMT::GetRawHostPtr( *
B2 ),
1335 DMT::GetStride( *
B2 ), DMT::GetRawHostPtr( *
B_copy ),
1336 DMT::GetStride( *
B_copy ), SCT::zero(),
1337 DMT::GetRawHostPtr( *
B_out ), DMT::GetStride( *
B_out ) );
1338 DMT::SyncHostToDevice( *
B_out );
1345 DMT::SyncDeviceToHost( *C[
k] );
1346 DMT::SyncDeviceToHost( *
C2[
k] );
1349 DMT::GetNumCols( *
C2[
k] ), SCT::one(), DMT::GetRawHostPtr( *
C2[
k] ),
1350 DMT::GetStride( *
C2[
k] ), DMT::GetRawHostPtr( *
B_copy ),
1351 DMT::GetStride( *
B_copy ), SCT::one(),
1352 DMT::GetRawHostPtr( *C[
k] ), DMT::GetStride( *C[
k] ) );
1353 DMT::SyncHostToDevice( *C[
k] );
1358 for (
int j = 0;
j <
rank; ++
j) {
1359 mat_ptr
B2_j = DMT::Subview( *
B2,
rank, 1, 0,
j );
1366 for (
int j = 0;
j <
rank; ++
j) {
1377 if (throwOnReorthogFault_) {
1388 "TsqrOrthoManagerImpl has not yet implemented"
1389 " recovery from an orthogonalization fault.");
1396 template<
class Scalar,
class MV,
class DM>
1398 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1399 raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
1400 const std::vector<magnitude_type>& normsAfterSecondPass,
1401 const std::vector<int>& faultIndices)
1404 typedef std::vector<int>::size_type size_type;
1405 std::ostringstream
os;
1407 os <<
"Orthogonalization fault at the following column(s) of X:" << endl;
1408 os <<
"Column\tNorm decrease factor" << endl;
1415 throw TsqrOrthoFault (
os.str());
1418 template<
class Scalar,
class MV,
class DM>
1419 Teuchos::RCP<const Teuchos::ParameterList>
1422 using Teuchos::ParameterList;
1423 using Teuchos::parameterList;
1426 if (defaultParams_.is_null()) {
1431 params->set (
"TSQR implementation", *(tsqrAdaptor_.getValidParameters()),
1432 "TSQR implementation parameters.");
1438 "Whether to fill in null space vectors with random data.");
1442 "Whether to do block reorthogonalization as necessary.");
1449 "If reorthogonalizeBlocks==true, and if the norm of "
1450 "any column within a block decreases by this much or "
1451 "more after orthogonalization, we reorthogonalize.");
1456 Teuchos::as<magnitude_type>(10) * SCTM::eps();
1462 "Relative tolerance to determine the numerical rank of a "
1463 "block when normalizing.");
1469 "Whether to throw an exception if an orthogonalization "
1470 "fault occurs. This only matters if reorthogonalization "
1471 "is enabled (reorthogonalizeBlocks==true).");
1475 "Whether to force the R factor produced by the normalization "
1476 "step to have a nonnegative diagonal.");
1480 return defaultParams_;
1483 template<
class Scalar,
class MV,
class DM>
1484 Teuchos::RCP<const Teuchos::ParameterList>
1487 using Teuchos::ParameterList;
1510 template<
class Scalar,
class MV,
class DM>
1522 tsqrAdaptor_.factorExplicit (
X,
Q, B, forceNonnegativeDiagonal_);
1525 rank = tsqrAdaptor_.revealRank (
Q, B, relativeRankTolerance_);
1526 }
catch (std::exception&
e) {
1527 throw TsqrOrthoError (
e.what());
1532 template<
class Scalar,
class MV,
class DM>
1534 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1535 normalizeOne (MV& X,
1536 Teuchos::RCP<DM> B)
const
1543 B_out = DMT::Create(1, 1);
1549 "normalizeOne: Input matrix B must be at least 1 x 1, but "
1552 B_out = DMT::Subview(*B, 1, 1);
1556 std::vector<magnitude_type>
theNorm (1, SCTM::zero());
1572 if (
theNorm[0] == SCTM::zero()) {
1575 if (randomizeNullSpace_) {
1578 if (
theNorm[0] == SCTM::zero()) {
1583 throw TsqrOrthoError(
"normalizeOne: a supposedly random "
1584 "vector has norm zero!");
1590 MVT::MvScale (
X, alpha);
1598 MVT::MvScale (
X, alpha);
1604 template<
class Scalar,
class MV,
class DM>
1606 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1608 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
1609 Teuchos::ArrayView<Teuchos::RCP<DM> > C)
const
1611#ifdef BELOS_TEUCHOS_TIME_MONITOR
1625 mat_type&
Ci = *C[
i];
1626 const MV&
Qi = *
Q[
i];
1627 innerProd (
Qi,
X,
Ci);
1628 MVT::MvTimesMatAddMv (-SCT::one(),
Qi,
Ci, SCT::one(),
X);
1633 template<
class Scalar,
class MV,
class DM>
1635 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1637 const Teuchos::RCP<const MV>& Q,
1638 const Teuchos::RCP<DM>& C)
const
1640#ifdef BELOS_TEUCHOS_TIME_MONITOR
1645 innerProd (*
Q,
X, *C);
1646 MVT::MvTimesMatAddMv (-SCT::one(), *
Q, *C, SCT::one(),
X);
1649 template<
class Scalar,
class MV,
class DM>
1651 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1652 normalizeImpl (MV& X,
1655 const bool outOfPlace)
1657 using Teuchos::Range1D;
1660 using Teuchos::ScalarTraits;
1661 using Teuchos::tuple;
1663 const int numCols = MVT::GetNumberVecs (
X);
1671 MVT::GetNumberVecs (
Q) <
numCols, std::invalid_argument,
1672 "TsqrOrthoManagerImpl::normalizeImpl: Q has "
1673 << MVT::GetNumberVecs(
Q) <<
" columns. This is too "
1674 "few, since X has " <<
numCols <<
" columns.");
1690 DMT::GetNumRows(*B) <
numCols || DMT::GetNumCols(*B) <
numCols, std::invalid_argument,
1691 "TsqrOrthoManagerImpl::normalizeImpl: Input matrix B must be at least "
1692 <<
numCols <<
" x " <<
numCols <<
", but is instead " << DMT::GetNumRows (*B)
1693 <<
" x " << DMT::GetNumCols(*B) <<
".");
1720 "Belos::TsqrOrthoManagerImpl::normalizeImpl: rawNormalize returned rank "
1721 " = " <<
rank <<
" for a matrix X with " <<
numCols <<
" columns. "
1722 "Please report this bug to the Belos developers.");
1760 std::vector<magnitude_type>
norms (MVT::GetNumberVecs (*
Q_null));
1764 typedef typename std::vector<magnitude_type>::const_iterator
iter_type;
1766 if (*
it == SCTM::zero()) {
1771 std::ostringstream
os;
1772 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1773 "We are being asked to randomize the null space, for a matrix "
1774 "with " <<
numCols <<
" columns and reported column rank "
1775 <<
rank <<
". The inclusive range of columns to fill with "
1778 "space vectors with random numbers, at least one of the vectors"
1779 " has norm zero. Here are the norms of all the null space "
1786 os <<
"].) There is a tiny probability that this could happen "
1787 "randomly, but it is likely a bug. Please report it to the "
1788 "Belos developers, especially if you are able to reproduce the "
1836 std::vector<magnitude_type>
norms (MVT::GetNumberVecs(*
X_null));
1838 std::ostringstream
os;
1839 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1840 <<
"We are being asked to randomize the null space, "
1841 <<
"for a matrix with " <<
numCols <<
" columns and "
1842 <<
"column rank " <<
rank <<
". After projecting and "
1843 <<
"normalizing the generated random vectors, they "
1846 <<
". (The inclusive range of columns to fill with "
1849 <<
"column norms of the resulting Q factor are: [";
1850 for (
typename std::vector<magnitude_type>::size_type
k = 0;
1853 if (
k !=
norms.size()-1) {
1857 os <<
"].) There is a tiny probability that this could "
1858 <<
"happen randomly, but it is likely a bug. Please "
1859 <<
"report it to the Belos developers, especially if "
1860 <<
"you are able to reproduce the behavior.";
1863 TsqrOrthoError,
os.str ());
1874 }
else if (
rank > 0) {
1885 template<
class Scalar,
class MV,
class DM>
1887 TsqrOrthoManagerImpl<Scalar, MV, DM>::
1888 checkProjectionDims (
int& ncols_X,
1892 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const
1908 using Teuchos::ArrayView;
1912 const MV&
Qi = **
it;
Belos header file which uses auto-configuration information to include necessary C++ headers.
Declaration of basic traits for the multivector type.
Templated virtual class for providing orthogonalization/orthonormalization methods.
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
Exception thrown to signal error in an orthogonalization manager method.
Interface of callback invoked by TsqrOrthoManager on reorthogonalization.
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
The type of a norm result.
virtual void operator()(Teuchos::ArrayView< magnitude_type > normsBeforeFirstPass, Teuchos::ArrayView< magnitude_type > normsAfterFirstPass)=0
Callback invoked by TsqrOrthoManager on reorthogonalization.
virtual ~ReorthogonalizationCallback()
Destructor (virtual for memory safety of derived classes)
Scalar scalar_type
The template parameter of this class; the type of an inner product result.
Error in TsqrOrthoManager or TsqrOrthoManagerImpl.
TsqrOrthoError(const std::string &what_arg)
TsqrOrthoFault(const std::string &what_arg)
TSQR-based OrthoManager subclass implementation.
DM mat_type
Type of the projection and normalization coefficients.
const std::string & getLabel() const
Get the label for timers (if timers are enabled).
magnitude_type blockReorthogThreshold() const
Relative tolerance for triggering a block reorthogonalization.
TsqrOrthoManagerImpl(const Teuchos::RCP< Teuchos::ParameterList > ¶ms, const std::string &label)
Constructor (that sets user-specified parameters).
void setLabel(const std::string &label)
Set the label for timers.
magnitude_type orthonormError(const MV &X) const
Return .
int normalize(MV &X, mat_ptr B)
Orthogonalize the columns of X in place.
Teuchos::RCP< mat_type > mat_ptr
magnitude_type orthogError(const MV &X1, const MV &X2) const
Return the Frobenius norm of the inner product of X1 with itself.
void setReorthogonalizationCallback(const Teuchos::RCP< ReorthogonalizationCallback< Scalar > > &callback)
Set callback to be invoked on reorthogonalization.
Teuchos::RCP< const Teuchos::ParameterList > getFastParameters()
Get "fast" parameters for TsqrOrthoManagerImpl.
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
void norm(const MV &X, std::vector< magnitude_type > &normVec) const
Compute the 2-norm of each column j of X.
void project(MV &X, Teuchos::Array< mat_ptr > C, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q)
Compute and .
int normalizeOutOfPlace(MV &X, MV &Q, mat_ptr B)
Normalize X into Q*B, overwriting X.
int projectAndNormalize(MV &X, Teuchos::Array< mat_ptr > C, mat_ptr B, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q)
Project X against Q and normalize X.
void innerProd(const MV &X, const MV &Y, mat_type &Z) const
Euclidean inner product.
magnitude_type relativeRankTolerance() const
Relative tolerance for determining (via the SVD) whether a block is of full numerical rank.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms)
Set parameters from the given parameter list.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Default valid parameter list.
int projectAndNormalizeOutOfPlace(MV &X_in, MV &X_out, Teuchos::Array< mat_ptr > C, mat_ptr B, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q)
Project and normalize X_in into X_out; overwrite X_in.