13#ifndef __BelosTsqrOrthoManagerImpl_hpp
14#define __BelosTsqrOrthoManagerImpl_hpp
20#include "Teuchos_as.hpp"
21#include "Teuchos_ParameterList.hpp"
22#include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
23#ifdef BELOS_TEUCHOS_TIME_MONITOR
24# include "Teuchos_TimeMonitor.hpp"
97 template<
class Scalar>
121 template<
class Scalar>
155 template<
class Scalar,
class MV>
157 public Teuchos::ParameterListAcceptorDefaultBase {
163 typedef Teuchos::SerialDenseMatrix<int, Scalar>
mat_type;
167 typedef Teuchos::ScalarTraits<Scalar> SCT;
168 typedef Teuchos::ScalarTraits<magnitude_type> SCTM;
170 typedef typename MVT::tsqr_adaptor_type tsqr_adaptor_type;
214 const std::string&
label);
255 if (
label != label_) {
258#ifdef BELOS_TEUCHOS_TIME_MONITOR
271 const std::string&
getLabel ()
const {
return label_; }
284 MVT::MvTransMv (SCT::one(),
X, Y, Z);
305 norm (
const MV&
X, std::vector<magnitude_type>&
normVec)
const;
318 Teuchos::Array<mat_ptr> C,
319 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q);
372 Teuchos::Array<mat_ptr> C,
374 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
378 return projectAndNormalizeImpl (
X,
X,
false, C, B,
Q);
403 Teuchos::Array<mat_ptr> C,
405 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
409 return projectAndNormalizeImpl (
X_in,
X_out,
true, C, B,
Q);
420 const int ncols = MVT::GetNumberVecs(
X);
426 return XTX.normFrobenius();
438 return X1_T_X2.normFrobenius();
452 Teuchos::RCP<Teuchos::ParameterList> params_;
455 mutable Teuchos::RCP<const Teuchos::ParameterList> defaultParams_;
461 tsqr_adaptor_type tsqrAdaptor_;
480 bool randomizeNullSpace_;
487 bool reorthogonalizeBlocks_;
492 bool throwOnReorthogFault_;
506 bool forceNonnegativeDiagonal_;
508#ifdef BELOS_TEUCHOS_TIME_MONITOR
520 Teuchos::RCP<ReorthogonalizationCallback<Scalar> > reorthogCallback_;
522#ifdef BELOS_TEUCHOS_TIME_MONITOR
531 static Teuchos::RCP<Teuchos::Time>
537 return Teuchos::TimeMonitor::getNewCounter (
timerLabel);
546 clearTimer (
const std::string& prefix,
547 const std::string& timerName)
549 const std::string timerLabel =
550 prefix.empty() ? timerName : (prefix +
": " + timerName);
551 Teuchos::TimeMonitor::clearCounter (timerLabel);
557 raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
558 const std::vector<magnitude_type>& normsAfterSecondPass,
559 const std::vector<int>& faultIndices);
571 checkProjectionDims (
int& ncols_X,
575 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const;
588 allocateProjectionCoefficients (Teuchos::Array<mat_ptr>& C,
589 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
591 const bool attemptToRecycle =
true)
const;
602 projectAndNormalizeImpl (MV& X_in,
604 const bool outOfPlace,
605 Teuchos::Array<mat_ptr> C,
607 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q);
616 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
617 Teuchos::ArrayView<mat_ptr> C)
const;
622 const Teuchos::RCP<const MV>& Q,
651 int rawNormalize (MV& X, MV& Q,
mat_type& B);
670 int normalizeOne (MV& X,
mat_ptr B)
const;
699 int normalizeImpl (MV& X, MV& Q,
mat_ptr B,
const bool outOfPlace);
702 template<
class Scalar,
class MV>
707 using Teuchos::ParameterList;
708 using Teuchos::parameterList;
710 using Teuchos::sublist;
727 randomizeNullSpace_ =
728 theParams->get<
bool> (
"randomizeNullSpace",
730 reorthogonalizeBlocks_ =
731 theParams->get<
bool> (
"reorthogonalizeBlocks",
733 throwOnReorthogFault_ =
734 theParams->get<
bool> (
"throwOnReorthogFault",
736 blockReorthogThreshold_ =
739 relativeRankTolerance_ =
742 forceNonnegativeDiagonal_ =
743 theParams->get<
bool> (
"forceNonnegativeDiagonal",
748 if (!
theParams->isSublist (
"TSQR implementation")) {
762 template<
class Scalar,
class MV>
765 const std::string&
label) :
769 randomizeNullSpace_ (
true),
770 reorthogonalizeBlocks_ (
true),
771 throwOnReorthogFault_ (
false),
772 blockReorthogThreshold_ (0),
773 relativeRankTolerance_ (0),
774 forceNonnegativeDiagonal_ (
false)
778#ifdef BELOS_TEUCHOS_TIME_MONITOR
785 template<
class Scalar,
class MV>
791 randomizeNullSpace_ (
true),
792 reorthogonalizeBlocks_ (
true),
793 throwOnReorthogFault_ (
false),
794 blockReorthogThreshold_ (0),
795 relativeRankTolerance_ (0),
796 forceNonnegativeDiagonal_ (
false)
800#ifdef BELOS_TEUCHOS_TIME_MONITOR
807 template<
class Scalar,
class MV>
810 norm (
const MV&
X, std::vector<magnitude_type>&
normVec)
const
812 const int numCols = MVT::GetNumberVecs (
X);
820 template<
class Scalar,
class MV>
823 Teuchos::Array<mat_ptr> C,
824 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
826#ifdef BELOS_TEUCHOS_TIME_MONITOR
846 allocateProjectionCoefficients (C,
Q,
X,
true);
851 if (reorthogonalizeBlocks_)
856 rawProject (
X,
Q, C);
860 if (reorthogonalizeBlocks_) {
880 if (! reorthogCallback_.is_null()) {
885 Teuchos::Array<mat_ptr>
C2;
886 allocateProjectionCoefficients (
C2,
Q,
X,
false);
890 rawProject (
X,
Q,
C2);
899 template<
class Scalar,
class MV>
903 using Teuchos::Range1D;
906#ifdef BELOS_TEUCHOS_TIME_MONITOR
918 const int numCols = MVT::GetNumberVecs (
X);
927 return normalizeOne (
X, B);
957 MVT::GetGlobalLength(*Q_) != MVT::GetGlobalLength(
X) ||
958 numCols > MVT::GetNumberVecs (*Q_)) {
968 if (MVT::GetNumberVecs(*Q_) ==
numCols) {
969 return normalizeImpl (
X, *Q_, B,
false);
972 return normalizeImpl (
X, *
Q_view, B,
false);
976 template<
class Scalar,
class MV>
980 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q,
985 const int ncols_X = MVT::GetNumberVecs (
X);
991 const int ncols_Qi = MVT::GetNumberVecs (*
Q[
i]);
998 mat_type&
Ci = *C[
i];
1002 Ci.putScalar (SCT::zero());
1010 const int ncols_Qi = MVT::GetNumberVecs (*
Q[
i]);
1016 template<
class Scalar,
class MV>
1021#ifdef BELOS_TEUCHOS_TIME_MONITOR
1026 const int numVecs = MVT::GetNumberVecs(
X);
1031 using Teuchos::Range1D;
1036 const int rank = normalizeOne (
X, B);
1039 MVT::Assign (
X, *
Q_0);
1045 return normalizeImpl (
X,
Q, B,
true);
1049 template<
class Scalar,
class MV>
1055 Teuchos::Array<mat_ptr> C,
1057 Teuchos::ArrayView<Teuchos::RCP<const MV> >
Q)
1059 using Teuchos::Range1D;
1063#ifdef BELOS_TEUCHOS_TIME_MONITOR
1072 std::invalid_argument,
1073 "Belos::TsqrOrthoManagerImpl::"
1074 "projectAndNormalizeImpl(..., outOfPlace=true, ...):"
1075 "X_out has " << MVT::GetNumberVecs(
X_out)
1076 <<
" columns, but X_in has "
1077 << MVT::GetNumberVecs(
X_in) <<
" columns.");
1091 return normalizeOutOfPlace (
X_in,
X_out, B);
1093 return normalize (
X_in, B);
1100 allocateProjectionCoefficients (C,
Q,
X_in,
true);
1106 if (reorthogonalizeBlocks_) {
1111 rawProject (
X_in,
Q, C);
1128 std::invalid_argument,
1129 "normalizeOne: Input matrix B must be at "
1131 <<
", but is instead " << B->numRows()
1132 <<
" x " << B->numCols() <<
".");
1212 "Belos::TsqrOrthoManagerImpl::projectAndNormalize"
1213 "OutOfPlace(): After projecting and normalizing the "
1214 "random vectors (used to replace the null space "
1215 "basis vectors from normalizing X), they have rank "
1222 if (reorthogonalizeBlocks_) {
1225 std::vector<magnitude_type>
1227 std::vector<magnitude_type>
1242 Teuchos::BLAS<int, Scalar>
blas;
1269 if (! reorthogCallback_.is_null()) {
1270 using Teuchos::arrayViewFromVector;
1290 using Teuchos::Copy;
1291 using Teuchos::NO_TRANS;
1303 Teuchos::Array<mat_ptr>
C2;
1304 allocateProjectionCoefficients (
C2,
Q,
X_in,
false);
1328 "Teuchos::SerialDenseMatrix::multiply "
1329 "returned err = " <<
err <<
" != 0");
1340 "Teuchos::SerialDenseMatrix::multiply "
1341 "returned err = " <<
err1 <<
" != 0");
1346 for (
int j = 0;
j <
rank; ++
j) {
1354 for (
int j = 0;
j <
rank; ++
j) {
1365 if (throwOnReorthogFault_) {
1376 "TsqrOrthoManagerImpl has not yet implemented"
1377 " recovery from an orthogonalization fault.");
1385 template<
class Scalar,
class MV>
1387 TsqrOrthoManagerImpl<Scalar, MV>::
1388 raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
1389 const std::vector<magnitude_type>& normsAfterSecondPass,
1390 const std::vector<int>& faultIndices)
1393 typedef std::vector<int>::size_type size_type;
1394 std::ostringstream
os;
1396 os <<
"Orthogonalization fault at the following column(s) of X:" << endl;
1397 os <<
"Column\tNorm decrease factor" << endl;
1404 throw TsqrOrthoFault (
os.str());
1407 template<
class Scalar,
class MV>
1408 Teuchos::RCP<const Teuchos::ParameterList>
1411 using Teuchos::ParameterList;
1412 using Teuchos::parameterList;
1415 if (defaultParams_.is_null()) {
1420 params->set (
"TSQR implementation", *(tsqrAdaptor_.getValidParameters()),
1421 "TSQR implementation parameters.");
1427 "Whether to fill in null space vectors with random data.");
1431 "Whether to do block reorthogonalization as necessary.");
1438 "If reorthogonalizeBlocks==true, and if the norm of "
1439 "any column within a block decreases by this much or "
1440 "more after orthogonalization, we reorthogonalize.");
1445 Teuchos::as<magnitude_type>(10) * SCTM::eps();
1451 "Relative tolerance to determine the numerical rank of a "
1452 "block when normalizing.");
1458 "Whether to throw an exception if an orthogonalization "
1459 "fault occurs. This only matters if reorthogonalization "
1460 "is enabled (reorthogonalizeBlocks==true).");
1464 "Whether to force the R factor produced by the normalization "
1465 "step to have a nonnegative diagonal.");
1469 return defaultParams_;
1472 template<
class Scalar,
class MV>
1473 Teuchos::RCP<const Teuchos::ParameterList>
1476 using Teuchos::ParameterList;
1499 template<
class Scalar,
class MV>
1504 Teuchos::SerialDenseMatrix<int, Scalar>& B)
1511 tsqrAdaptor_.factorExplicit (
X,
Q, B, forceNonnegativeDiagonal_);
1514 rank = tsqrAdaptor_.revealRank (
Q, B, relativeRankTolerance_);
1515 }
catch (std::exception&
e) {
1516 throw TsqrOrthoError (
e.what());
1521 template<
class Scalar,
class MV>
1523 TsqrOrthoManagerImpl<Scalar, MV>::
1524 normalizeOne (MV& X,
1525 Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > B)
const
1532 B_out = Teuchos::rcp (
new mat_type (1, 1));
1538 "normalizeOne: Input matrix B must be at least 1 x 1, but "
1541 B_out = Teuchos::rcp (
new mat_type (Teuchos::View, *B, 1, 1));
1545 std::vector<magnitude_type>
theNorm (1, SCTM::zero());
1561 if (
theNorm[0] == SCTM::zero()) {
1564 if (randomizeNullSpace_) {
1567 if (
theNorm[0] == SCTM::zero()) {
1572 throw TsqrOrthoError(
"normalizeOne: a supposedly random "
1573 "vector has norm zero!");
1579 MVT::MvScale (
X, alpha);
1587 MVT::MvScale (
X, alpha);
1593 template<
class Scalar,
class MV>
1595 TsqrOrthoManagerImpl<Scalar, MV>::
1597 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
1598 Teuchos::ArrayView<Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > > C)
const
1600#ifdef BELOS_TEUCHOS_TIME_MONITOR
1614 mat_type&
Ci = *C[
i];
1615 const MV&
Qi = *
Q[
i];
1616 innerProd (
Qi,
X,
Ci);
1617 MVT::MvTimesMatAddMv (-SCT::one(),
Qi,
Ci, SCT::one(),
X);
1622 template<
class Scalar,
class MV>
1624 TsqrOrthoManagerImpl<Scalar, MV>::
1626 const Teuchos::RCP<const MV>& Q,
1627 const Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> >& C)
const
1629#ifdef BELOS_TEUCHOS_TIME_MONITOR
1634 innerProd (*
Q,
X, *C);
1635 MVT::MvTimesMatAddMv (-SCT::one(), *
Q, *C, SCT::one(),
X);
1638 template<
class Scalar,
class MV>
1640 TsqrOrthoManagerImpl<Scalar, MV>::
1641 normalizeImpl (MV& X,
1643 Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > B,
1644 const bool outOfPlace)
1646 using Teuchos::Range1D;
1649 using Teuchos::ScalarTraits;
1650 using Teuchos::tuple;
1652 const int numCols = MVT::GetNumberVecs (
X);
1660 MVT::GetNumberVecs (
Q) <
numCols, std::invalid_argument,
1661 "TsqrOrthoManagerImpl::normalizeImpl: Q has "
1662 << MVT::GetNumberVecs(
Q) <<
" columns. This is too "
1663 "few, since X has " <<
numCols <<
" columns.");
1679 B->numRows() <
numCols || B->numCols() <
numCols, std::invalid_argument,
1680 "TsqrOrthoManagerImpl::normalizeImpl: Input matrix B must be at least "
1681 <<
numCols <<
" x " <<
numCols <<
", but is instead " << B->numRows ()
1682 <<
" x " << B->numCols() <<
".");
1709 "Belos::TsqrOrthoManagerImpl::normalizeImpl: rawNormalize returned rank "
1710 " = " <<
rank <<
" for a matrix X with " <<
numCols <<
" columns. "
1711 "Please report this bug to the Belos developers.");
1749 std::vector<magnitude_type>
norms (MVT::GetNumberVecs (*
Q_null));
1753 typedef typename std::vector<magnitude_type>::const_iterator
iter_type;
1755 if (*
it == SCTM::zero()) {
1760 std::ostringstream
os;
1761 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1762 "We are being asked to randomize the null space, for a matrix "
1763 "with " <<
numCols <<
" columns and reported column rank "
1764 <<
rank <<
". The inclusive range of columns to fill with "
1767 "space vectors with random numbers, at least one of the vectors"
1768 " has norm zero. Here are the norms of all the null space "
1775 os <<
"].) There is a tiny probability that this could happen "
1776 "randomly, but it is likely a bug. Please report it to the "
1777 "Belos developers, especially if you are able to reproduce the "
1825 std::vector<magnitude_type>
norms (MVT::GetNumberVecs(*
X_null));
1827 std::ostringstream
os;
1828 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1829 <<
"We are being asked to randomize the null space, "
1830 <<
"for a matrix with " <<
numCols <<
" columns and "
1831 <<
"column rank " <<
rank <<
". After projecting and "
1832 <<
"normalizing the generated random vectors, they "
1835 <<
". (The inclusive range of columns to fill with "
1838 <<
"column norms of the resulting Q factor are: [";
1839 for (
typename std::vector<magnitude_type>::size_type
k = 0;
1842 if (
k !=
norms.size()-1) {
1846 os <<
"].) There is a tiny probability that this could "
1847 <<
"happen randomly, but it is likely a bug. Please "
1848 <<
"report it to the Belos developers, especially if "
1849 <<
"you are able to reproduce the behavior.";
1852 TsqrOrthoError,
os.str ());
1863 }
else if (
rank > 0) {
1874 template<
class Scalar,
class MV>
1876 TsqrOrthoManagerImpl<Scalar, MV>::
1877 checkProjectionDims (
int& ncols_X,
1881 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const
1897 using Teuchos::ArrayView;
1901 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.
void setReorthogonalizationCallback(const Teuchos::RCP< ReorthogonalizationCallback< Scalar > > &callback)
Set callback to be invoked on reorthogonalization.
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.
Teuchos::RCP< mat_type > mat_ptr
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms)
Set parameters from the given parameter list.
void innerProd(const MV &X, const MV &Y, mat_type &Z) const
Euclidean inner product.
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitude_type
int normalizeOutOfPlace(MV &X, MV &Q, mat_ptr B)
Normalize X into Q*B, overwriting X.
void setLabel(const std::string &label)
Set the label for timers.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Default valid parameter list.
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 norm(const MV &X, std::vector< magnitude_type > &normVec) const
Compute the 2-norm of each column j of X.
magnitude_type orthogError(const MV &X1, const MV &X2) const
Return the Frobenius norm of the inner product of X1 with itself.
void project(MV &X, Teuchos::Array< mat_ptr > C, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q)
Compute and .
int normalize(MV &X, mat_ptr B)
Orthogonalize the columns of X in place.
Teuchos::RCP< const Teuchos::ParameterList > getFastParameters()
Get "fast" parameters for TsqrOrthoManagerImpl.
const std::string & getLabel() const
Get the label for timers (if timers are enabled).
magnitude_type relativeRankTolerance() const
Relative tolerance for determining (via the SVD) whether a block is of full numerical rank.
magnitude_type orthonormError(const MV &X) const
Return .
Teuchos::SerialDenseMatrix< int, Scalar > mat_type
Type of the projection and normalization coefficients.
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).