13#ifndef __AnasaziTsqrOrthoManagerImpl_hpp
14#define __AnasaziTsqrOrthoManagerImpl_hpp
20#include "Teuchos_as.hpp"
21#include "Teuchos_LAPACK.hpp"
22#include "Teuchos_ParameterList.hpp"
23#include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
95 template<
class Scalar,
class MV>
97 public Teuchos::ParameterListAcceptorDefaultBase {
100 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
101 typedef MV multivector_type;
104 typedef Teuchos::SerialDenseMatrix<int, Scalar>
mat_type;
105 typedef Teuchos::RCP<mat_type> mat_ptr;
108 typedef Teuchos::ScalarTraits<Scalar> SCT;
109 typedef Teuchos::ScalarTraits<magnitude_type> SCTM;
111 typedef typename MVT::tsqr_adaptor_type tsqr_adaptor_type;
155 const std::string&
label);
171 if (
label != label_) {
177 const std::string&
getLabel ()
const {
return label_; }
190 MVT::MvTransMv (SCT::one(), X,
Y, Z);
211 norm (
const MV& X, std::vector<magnitude_type>&
normvec)
const;
224 Teuchos::Array<mat_ptr>
C,
225 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q);
278 Teuchos::Array<mat_ptr>
C,
280 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
284 return projectAndNormalizeImpl (X, X,
false,
C,
B, Q);
309 Teuchos::Array<mat_ptr>
C,
311 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
315 return projectAndNormalizeImpl (
X_in,
X_out,
true,
C,
B, Q);
325 const Scalar ONE = SCT::one();
326 const int ncols = MVT::GetNumberVecs(X);
332 return XTX.normFrobenius();
344 return X1_T_X2.normFrobenius();
358 Teuchos::RCP<Teuchos::ParameterList> params_;
361 mutable Teuchos::RCP<const Teuchos::ParameterList> defaultParams_;
367 tsqr_adaptor_type tsqrAdaptor_;
387 bool randomizeNullSpace_;
394 bool reorthogonalizeBlocks_;
399 bool throwOnReorthogFault_;
402 magnitude_type blockReorthogThreshold_;
405 magnitude_type relativeRankTolerance_;
413 bool forceNonnegativeDiagonal_;
431 checkProjectionDims (
int&
ncols_X,
435 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const;
448 allocateProjectionCoefficients (Teuchos::Array<mat_ptr>&
C,
449 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
462 projectAndNormalizeImpl (MV&
X_in,
465 Teuchos::Array<mat_ptr>
C,
467 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q);
476 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
477 Teuchos::ArrayView<mat_ptr>
C)
const;
482 const Teuchos::RCP<const MV>& Q,
483 const mat_ptr&
C)
const;
511 int rawNormalize (MV& X, MV& Q,
mat_type&
B);
530 int normalizeOne (MV& X, mat_ptr
B)
const;
559 int normalizeImpl (MV& X, MV& Q, mat_ptr
B,
const bool outOfPlace);
562 template<
class Scalar,
class MV>
567 using Teuchos::ParameterList;
568 using Teuchos::parameterList;
570 using Teuchos::sublist;
571 typedef magnitude_type
M;
587 randomizeNullSpace_ =
588 theParams->get<
bool> (
"randomizeNullSpace",
590 reorthogonalizeBlocks_ =
591 theParams->get<
bool> (
"reorthogonalizeBlocks",
593 throwOnReorthogFault_ =
594 theParams->get<
bool> (
"throwOnReorthogFault",
596 blockReorthogThreshold_ =
599 relativeRankTolerance_ =
602 forceNonnegativeDiagonal_ =
603 theParams->get<
bool> (
"forceNonnegativeDiagonal",
608 if (!
theParams->isSublist (
"TSQR implementation")) {
622 template<
class Scalar,
class MV>
625 const std::string&
label) :
629 randomizeNullSpace_ (
true),
630 reorthogonalizeBlocks_ (
true),
631 throwOnReorthogFault_ (
false),
632 blockReorthogThreshold_ (0),
633 relativeRankTolerance_ (0),
634 forceNonnegativeDiagonal_ (
false)
639 template<
class Scalar,
class MV>
645 randomizeNullSpace_ (
true),
646 reorthogonalizeBlocks_ (
true),
647 throwOnReorthogFault_ (
false),
648 blockReorthogThreshold_ (0),
649 relativeRankTolerance_ (0),
650 forceNonnegativeDiagonal_ (
false)
655 template<
class Scalar,
class MV>
658 norm (
const MV& X, std::vector<magnitude_type>&
normVec)
const
660 const int numCols = MVT::GetNumberVecs (X);
668 template<
class Scalar,
class MV>
671 Teuchos::Array<mat_ptr>
C,
672 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
683 allocateProjectionCoefficients (
C, Q, X,
true);
688 if (reorthogonalizeBlocks_)
693 rawProject (X, Q,
C);
697 if (reorthogonalizeBlocks_)
703 const magnitude_type
relThres = blockReorthogThreshold();
719 Teuchos::Array<mat_ptr>
C2;
720 allocateProjectionCoefficients (
C2, Q, X,
false);
724 rawProject (X, Q,
C2);
734 template<
class Scalar,
class MV>
738 using Teuchos::Range1D;
744 const int numCols = MVT::GetNumberVecs (X);
753 return normalizeOne (X,
B);
783 MVT::GetGlobalLength(*Q_) != MVT::GetGlobalLength(X) ||
784 numCols > MVT::GetNumberVecs (*Q_)) {
794 if (MVT::GetNumberVecs(*Q_) ==
numCols) {
795 return normalizeImpl (X, *Q_,
B,
false);
798 return normalizeImpl (X, *
Q_view,
B,
false);
802 template<
class Scalar,
class MV>
806 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
811 const int ncols_X = MVT::GetNumberVecs (X);
817 const int ncols_Qi = MVT::GetNumberVecs (*Q[
i]);
824 mat_type&
Ci = *
C[
i];
828 Ci.putScalar (SCT::zero());
836 const int ncols_Qi = MVT::GetNumberVecs (*Q[
i]);
842 template<
class Scalar,
class MV>
847 const int numVecs = MVT::GetNumberVecs(X);
850 }
else if (numVecs == 1) {
852 using Teuchos::Range1D;
857 const int rank = normalizeOne (X,
B);
860 MVT::Assign (X, *
Q_0);
866 return normalizeImpl (X, Q,
B,
true);
870 template<
class Scalar,
class MV>
876 Teuchos::Array<mat_ptr>
C,
878 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
880 using Teuchos::Range1D;
887 std::invalid_argument,
888 "Belos::TsqrOrthoManagerImpl::"
889 "projectAndNormalizeOutOfPlace(...):"
890 "X_out has " << MVT::GetNumberVecs(
X_out)
891 <<
" columns, but X_in has "
892 << MVT::GetNumberVecs(
X_in) <<
" columns.");
908 return normalize (
X_in,
B);
915 allocateProjectionCoefficients (
C, Q,
X_in,
true);
921 if (reorthogonalizeBlocks_) {
926 rawProject (
X_in, Q,
C);
943 std::invalid_argument,
944 "normalizeOne: Input matrix B must be at "
946 <<
", but is instead " <<
B->numRows()
947 <<
" x " <<
B->numCols() <<
".");
991 const int numColsQk = MVT::GetNumberVecs(*Q[
k]);
1027 "Belos::TsqrOrthoManagerImpl::projectAndNormalize"
1028 "OutOfPlace(): After projecting and normalizing the "
1029 "random vectors (used to replace the null space "
1030 "basis vectors from normalizing X), they have rank "
1037 if (reorthogonalizeBlocks_) {
1040 std::vector<magnitude_type>
1042 std::vector<magnitude_type>
1057 Teuchos::BLAS<int, Scalar>
blas;
1096 using Teuchos::Copy;
1097 using Teuchos::NO_TRANS;
1108 Teuchos::Array<mat_ptr>
C2;
1109 allocateProjectionCoefficients (
C2, Q,
X_in,
false);
1114 rawProject (
X_in, Q,
C2);
1133 "Teuchos::SerialDenseMatrix::multiply "
1134 "returned err = " <<
err <<
" != 0");
1145 "Teuchos::SerialDenseMatrix::multiply "
1146 "returned err = " <<
err <<
" != 0");
1151 for (
int j = 0;
j <
rank; ++
j) {
1159 for (
int j = 0;
j <
rank; ++
j) {
1170 if (throwOnReorthogFault_) {
1181 "TsqrOrthoManagerImpl has not yet implemented"
1182 " recovery from an orthogonalization fault.");
1190 template<
class Scalar,
class MV>
1192 TsqrOrthoManagerImpl<Scalar, MV>::
1193 raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
1194 const std::vector<magnitude_type>& normsAfterSecondPass,
1195 const std::vector<int>& faultIndices)
1198 typedef std::vector<int>::size_type
size_type;
1199 std::ostringstream
os;
1201 os <<
"Orthogonalization fault at the following column(s) of X:" <<
endl;
1202 os <<
"Column\tNorm decrease factor" <<
endl;
1210 throw TsqrOrthoFault (
os.str());
1213 template<
class Scalar,
class MV>
1214 Teuchos::RCP<const Teuchos::ParameterList>
1217 using Teuchos::ParameterList;
1218 using Teuchos::parameterList;
1221 if (defaultParams_.is_null()) {
1226 params->set (
"TSQR implementation", *(tsqrAdaptor_.getValidParameters()),
1227 "TSQR implementation parameters.");
1233 "Whether to fill in null space vectors with random data.");
1237 "Whether to do block reorthogonalization as necessary.");
1242 magnitude_type(10) * SCTM::squareroot (SCTM::eps());
1244 "If reorthogonalizeBlocks==true, and if the norm of "
1245 "any column within a block decreases by this much or "
1246 "more after orthogonalization, we reorthogonalize.");
1251 Teuchos::as<magnitude_type>(10) * SCTM::eps();
1257 "Relative tolerance to determine the numerical rank of a "
1258 "block when normalizing.");
1264 "Whether to throw an exception if an orthogonalization "
1265 "fault occurs. This only matters if reorthogonalization "
1266 "is enabled (reorthogonalizeBlocks==true).");
1270 "Whether to force the R factor produced by the normalization "
1271 "step to have a nonnegative diagonal.");
1275 return defaultParams_;
1278 template<
class Scalar,
class MV>
1279 Teuchos::RCP<const Teuchos::ParameterList>
1282 using Teuchos::ParameterList;
1305 template<
class Scalar,
class MV>
1310 Teuchos::SerialDenseMatrix<int, Scalar>&
B)
1317 tsqrAdaptor_.factorExplicit (X, Q,
B, forceNonnegativeDiagonal_);
1320 rank = tsqrAdaptor_.revealRank (Q,
B, relativeRankTolerance_);
1321 }
catch (std::exception&
e) {
1322 throw TsqrOrthoError (
e.what());
1327 template<
class Scalar,
class MV>
1329 TsqrOrthoManagerImpl<Scalar, MV>::
1330 normalizeOne (MV& X,
1331 Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > B)
const
1338 B_out = rcp (
new mat_type (1, 1));
1343 std::invalid_argument,
1344 "normalizeOne: Input matrix B must be at "
1345 "least 1 x 1, but is instead " <<
numRows
1348 B_out = rcp (
new mat_type (Teuchos::View, *
B, 1, 1));
1352 std::vector<magnitude_type>
theNorm (1, SCTM::zero());
1368 if (
theNorm[0] == SCTM::zero()) {
1371 if (randomizeNullSpace_) {
1374 if (
theNorm[0] == SCTM::zero()) {
1379 throw TsqrOrthoError(
"normalizeOne: a supposedly random "
1380 "vector has norm zero!");
1386 MVT::MvScale (X,
alpha);
1394 MVT::MvScale (X,
alpha);
1400 template<
class Scalar,
class MV>
1402 TsqrOrthoManagerImpl<Scalar, MV>::
1404 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
1405 Teuchos::ArrayView<Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > > C)
const
1417 mat_type&
Ci = *
C[
i];
1418 const MV&
Qi = *Q[
i];
1419 innerProd (
Qi, X,
Ci);
1420 MVT::MvTimesMatAddMv (-SCT::one(),
Qi,
Ci, SCT::one(), X);
1425 template<
class Scalar,
class MV>
1427 TsqrOrthoManagerImpl<Scalar, MV>::
1429 const Teuchos::RCP<const MV>& Q,
1430 const Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> >& C)
const
1433 innerProd (*Q, X, *
C);
1434 MVT::MvTimesMatAddMv (-SCT::one(), *Q, *
C, SCT::one(), X);
1437 template<
class Scalar,
class MV>
1439 TsqrOrthoManagerImpl<Scalar, MV>::
1440 normalizeImpl (MV& X,
1442 Teuchos::RCP<Teuchos::SerialDenseMatrix<int, Scalar> > B,
1443 const bool outOfPlace)
1445 using Teuchos::Range1D;
1448 using Teuchos::ScalarTraits;
1449 using Teuchos::tuple;
1456 const int numCols = MVT::GetNumberVecs (X);
1464 std::invalid_argument,
1465 "TsqrOrthoManagerImpl::normalizeImpl(X,Q,B): Q has "
1466 << MVT::GetNumberVecs(Q) <<
" columns. This is too "
1467 "few, since X has " <<
numCols <<
" columns.");
1483 std::invalid_argument,
1484 "normalizeOne: Input matrix B must be at "
1486 <<
", but is instead " <<
B->numRows()
1487 <<
" x " <<
B->numCols() <<
".");
1495 MVT::MvNorm (X,
norms);
1496 cerr <<
"Column norms of X before orthogonalization: ";
1497 typedef typename std::vector<magnitude_type>::const_iterator
iter_type;
1527 cerr <<
"Column norms of Q_view after orthogonalization: ";
1528 for (
typename std::vector<magnitude_type>::const_iterator
iter =
norms.begin();
1536 "Belos::TsqrOrthoManagerImpl::normalizeImpl: "
1537 "rawNormalize() returned rank = " <<
rank <<
" for a "
1538 "matrix X with " <<
numCols <<
" columns. Please report"
1539 " this bug to the Belos developers.");
1543 const mat_type&
B_ref = *
B;
1544 std::vector<magnitude_type>
norms (
B_ref.numCols());
1545 for (
typename mat_type::ordinalType
j = 0;
j <
B_ref.numCols(); ++
j) {
1548 for (
typename mat_type::ordinalType
i = 0;
i <=
j; ++
i) {
1550 ScalarTraits<mat_scalar_type>::magnitude (
B_ref(
i,
j));
1557 cerr <<
"Norms of columns of B after orthogonalization: ";
1558 for (
typename mat_type::ordinalType
j = 0;
j <
B_ref.numCols(); ++
j) {
1560 if (
j !=
B_ref.numCols() - 1)
1572 MVT::Assign (*
Q_view, X);
1602 std::vector<magnitude_type>
norms (MVT::GetNumberVecs(*
Q_null));
1606 typedef typename std::vector<magnitude_type>::const_iterator
iter_type;
1608 if (*
it == SCTM::zero()) {
1613 std::ostringstream
os;
1614 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1615 "We are being asked to randomize the null space, for a matrix "
1616 "with " <<
numCols <<
" columns and reported column rank "
1617 <<
rank <<
". The inclusive range of columns to fill with "
1620 "space vectors with random numbers, at least one of the vectors"
1621 " has norm zero. Here are the norms of all the null space "
1628 os <<
"].) There is a tiny probability that this could happen "
1629 "randomly, but it is likely a bug. Please report it to the "
1630 "Belos developers, especially if you are able to reproduce the "
1678 std::vector<magnitude_type>
norms (MVT::GetNumberVecs(*
X_null));
1680 std::ostringstream
os;
1681 os <<
"TsqrOrthoManagerImpl::normalizeImpl: "
1682 <<
"We are being asked to randomize the null space, "
1683 <<
"for a matrix with " <<
numCols <<
" columns and "
1684 <<
"column rank " <<
rank <<
". After projecting and "
1685 <<
"normalizing the generated random vectors, they "
1688 <<
". (The inclusive range of columns to fill with "
1691 <<
"column norms of the resulting Q factor are: [";
1692 for (
typename std::vector<magnitude_type>::size_type
k = 0;
1695 if (
k !=
norms.size()-1) {
1699 os <<
"].) There is a tiny probability that this could "
1700 <<
"happen randomly, but it is likely a bug. Please "
1701 <<
"report it to the Belos developers, especially if "
1702 <<
"you are able to reproduce the behavior.";
1705 TsqrOrthoError,
os.str());
1716 }
else if (
rank > 0) {
1727 template<
class Scalar,
class MV>
1729 TsqrOrthoManagerImpl<Scalar, MV>::
1730 checkProjectionDims (
int& ncols_X,
1734 Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
const
1750 using Teuchos::ArrayView;
1754 const MV&
Qi = **
it;
Anasazi 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.
Anasazi's templated virtual class for constructing an operator that can interface with the OperatorTr...
Operator()
Default constructor.
Exception thrown to signal error in an orthogonalization manager method.
TsqrOrthoManager(Impl) error.
TSQR-based OrthoManager subclass implementation.
void innerProd(const MV &X, const MV &Y, mat_type &Z) const
Euclidean inner product.
magnitude_type orthogError(const MV &X1, const MV &X2) const
Return the Frobenius norm of the inner product of X1 with itself.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Default valid parameter list.
int normalizeOutOfPlace(MV &X, MV &Q, mat_ptr B)
Normalize X into Q*B, overwriting X.
magnitude_type relativeRankTolerance() const
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.
magnitude_type blockReorthogThreshold() const
void norm(const MV &X, std::vector< magnitude_type > &normvec) const
const std::string & getLabel() const
Get the label for timers (if timers are enabled).
magnitude_type orthonormError(const MV &X) const
Return .
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > ¶ms)
Set parameters from the given parameter list.
int normalize(MV &X, mat_ptr B)
Orthogonalize the columns of X in place.
void project(MV &X, Teuchos::Array< mat_ptr > C, Teuchos::ArrayView< Teuchos::RCP< const MV > > Q)
Compute and .
TsqrOrthoManagerImpl(const Teuchos::RCP< Teuchos::ParameterList > ¶ms, const std::string &label)
Constructor (that sets user-specified parameters).
Teuchos::SerialDenseMatrix< int, Scalar > mat_type
Teuchos::RCP< const Teuchos::ParameterList > getFastParameters()
Get "fast" parameters for TsqrOrthoManagerImpl.
void setLabel(const std::string &label)
Set the label for timers.
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.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.