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 {
 
   99    typedef Scalar scalar_type;
 
  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);
 
  329      for (
int k = 0; k < ncols; ++k) {
 
  332      return XTX.normFrobenius();
 
 
  340      const int ncols_X1 = MVT::GetNumberVecs (X1);
 
  341      const int ncols_X2 = MVT::GetNumberVecs (X2);
 
  342      mat_type X1_T_X2 (ncols_X1, ncols_X2);
 
  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_;
 
  417    raiseReorthogFault (
const std::vector<magnitude_type>& normsAfterFirstPass,
 
  418                        const std::vector<magnitude_type>& normsAfterSecondPass,
 
  419                        const std::vector<int>& faultIndices);
 
  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,
 
  451                                    const bool attemptToRecycle = 
true) 
const;
 
  462    projectAndNormalizeImpl (MV& X_in, 
 
  464                             const bool outOfPlace,
 
  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; 
 
  573    RCP<const ParameterList> defaultParams = getValidParameters ();
 
  575    RCP<ParameterList> tsqrParams;
 
  577    RCP<ParameterList> theParams;
 
  578    if (params.is_null()) {
 
  579      theParams = parameterList (*defaultParams);
 
  587      randomizeNullSpace_ = 
 
  588        theParams->get<
bool> (
"randomizeNullSpace", 
 
  589                              defaultParams->get<
bool> (
"randomizeNullSpace"));
 
  590      reorthogonalizeBlocks_ = 
 
  591        theParams->get<
bool> (
"reorthogonalizeBlocks", 
 
  592                              defaultParams->get<
bool> (
"reorthogonalizeBlocks"));
 
  593      throwOnReorthogFault_ = 
 
  594        theParams->get<
bool> (
"throwOnReorthogFault", 
 
  595                              defaultParams->get<
bool> (
"throwOnReorthogFault"));
 
  596      blockReorthogThreshold_ = 
 
  597        theParams->get<M> (
"blockReorthogThreshold",
 
  598                           defaultParams->get<M> (
"blockReorthogThreshold"));
 
  599      relativeRankTolerance_ = 
 
  600        theParams->get<M> (
"relativeRankTolerance", 
 
  601                           defaultParams->get<M> (
"relativeRankTolerance"));
 
  602      forceNonnegativeDiagonal_ = 
 
  603        theParams->get<
bool> (
"forceNonnegativeDiagonal", 
 
  604                              defaultParams->get<
bool> (
"forceNonnegativeDiagonal"));
 
  608      if (! theParams->isSublist (
"TSQR implementation")) {
 
  609        theParams->set (
"TSQR implementation", 
 
  610                        defaultParams->sublist (
"TSQR implementation"));
 
  612      tsqrParams = sublist (theParams, 
"TSQR implementation", 
true);
 
  616    tsqrAdaptor_.setParameterList (tsqrParams);
 
  619    setMyParamList (theParams);
 
 
  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);
 
  663    if (normVec.size() < 
static_cast<size_t>(numCols))
 
  664      normVec.resize (numCols); 
 
  665    MVT::MvNorm (X, normVec);
 
 
  668  template<
class Scalar, 
class MV>
 
  671                                             Teuchos::Array<mat_ptr> C,
 
  672                                             Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
 
  674    int ncols_X, num_Q_blocks, ncols_Q_total;
 
  675    checkProjectionDims (ncols_X, num_Q_blocks, ncols_Q_total, X, Q);
 
  679    if (ncols_X == 0 || num_Q_blocks == 0 || ncols_Q_total == 0)
 
  683    allocateProjectionCoefficients (C, Q, X, 
true);
 
  687    std::vector<magnitude_type> columnNormsBefore (ncols_X, magnitude_type(0));
 
  688    if (reorthogonalizeBlocks_)
 
  689      MVT::MvNorm (X, columnNormsBefore);
 
  693    rawProject (X, Q, C); 
 
  697    if (reorthogonalizeBlocks_)
 
  699        std::vector<magnitude_type> columnNormsAfter (ncols_X, magnitude_type(0));
 
  700        MVT::MvNorm (X, columnNormsAfter);
 
  703        const magnitude_type relThres = blockReorthogThreshold();
 
  709        bool reorthogonalize = 
false;
 
  710        for (
int j = 0; j < ncols_X; ++j)
 
  711          if (columnNormsAfter[j] < relThres * columnNormsBefore[j])
 
  713              reorthogonalize = 
true;
 
  719            Teuchos::Array<mat_ptr> C2;
 
  720            allocateProjectionCoefficients (C2, Q, X, 
false);
 
  724            rawProject (X, Q, C2);
 
  726            for (
int k = 0; k < num_Q_blocks; ++k)
 
 
  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_)) {
 
  785      Q_ = MVT::Clone (X, numCols);
 
  794    if (MVT::GetNumberVecs(*Q_) == numCols) {
 
  795      return normalizeImpl (X, *Q_, B, 
false);
 
  797      RCP<MV> Q_view = MVT::CloneViewNonConst (*Q_, Range1D(0, numCols-1));
 
  798      return normalizeImpl (X, *Q_view, B, 
false);
 
 
  802  template<
class Scalar, 
class MV>
 
  806                                  Teuchos::ArrayView<Teuchos::RCP<const MV> > Q,
 
  808                                  const bool attemptToRecycle)
 const 
  810    const int num_Q_blocks = Q.size();
 
  811    const int ncols_X = MVT::GetNumberVecs (X);
 
  812    C.resize (num_Q_blocks);
 
  813    if (attemptToRecycle)
 
  815        for (
int i = 0; i < num_Q_blocks; ++i) 
 
  817            const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
 
  821              C[i] = rcp (
new mat_type (ncols_Qi, ncols_X));
 
  824                mat_type& Ci = *C[i];
 
  825                if (Ci.numRows() != ncols_Qi || Ci.numCols() != ncols_X)
 
  826                  Ci.shape (ncols_Qi, ncols_X);
 
  828                  Ci.putScalar (SCT::zero());
 
  834        for (
int i = 0; i < num_Q_blocks; ++i) 
 
  836            const int ncols_Qi = MVT::GetNumberVecs (*Q[i]);
 
  837            C[i] = rcp (
new mat_type (ncols_Qi, ncols_X));
 
  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);
 
  859      RCP<MV> Q_0 = MVT::CloneViewNonConst (Q, Range1D(0,0));
 
  860      MVT::Assign (X, *Q_0);
 
  866      return normalizeImpl (X, Q, B, 
true);
 
 
  870  template<
class Scalar, 
class MV>
 
  875                           const bool outOfPlace,
 
  876                           Teuchos::Array<mat_ptr> C,
 
  878                           Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
 
  880    using Teuchos::Range1D;
 
  886      TEUCHOS_TEST_FOR_EXCEPTION(MVT::GetNumberVecs(X_out) < MVT::GetNumberVecs(X_in),
 
  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.");
 
  896    int ncols_X, num_Q_blocks, ncols_Q_total;
 
  897    checkProjectionDims (ncols_X, num_Q_blocks, ncols_Q_total, X_in, Q);
 
  904    if (num_Q_blocks == 0 || ncols_Q_total == 0) {
 
  906        return normalizeOutOfPlace (X_in, X_out, B);
 
  908        return normalize (X_in, B);
 
  915    allocateProjectionCoefficients (C, Q, X_in, 
true);
 
  920    std::vector<magnitude_type> normsBeforeFirstPass (ncols_X, SCTM::zero());
 
  921    if (reorthogonalizeBlocks_) {
 
  922      MVT::MvNorm (X_in, normsBeforeFirstPass);
 
  926    rawProject (X_in, Q, C);
 
  939      B_out = rcp (
new mat_type (ncols_X, ncols_X));
 
  942      TEUCHOS_TEST_FOR_EXCEPTION(B->numRows() < ncols_X || B->numCols() < ncols_X,
 
  943                         std::invalid_argument,
 
  944                         "normalizeOne: Input matrix B must be at " 
  945                         "least " << ncols_X << 
" x " << ncols_X 
 
  946                         << 
", but is instead " << B->numRows()
 
  947                         << 
" x " << B->numCols() << 
".");
 
  951      B_out = rcp (
new mat_type (Teuchos::View, *B, ncols_X, ncols_X));
 
  957    const int firstPassRank = outOfPlace ? 
 
  958      normalizeOutOfPlace (X_in, X_out, B_out) : 
 
  959      normalize (X_in, B_out);
 
  968    int rank = firstPassRank; 
 
  984    if (firstPassRank < ncols_X && randomizeNullSpace_) {
 
  985      const int numNullSpaceCols = ncols_X - firstPassRank;
 
  986      const Range1D nullSpaceIndices (firstPassRank, ncols_X - 1);
 
  989      Teuchos::Array<mat_ptr> C_null (num_Q_blocks);
 
  990      for (
int k = 0; k < num_Q_blocks; ++k) {
 
  991        const int numColsQk = MVT::GetNumberVecs(*Q[k]);
 
  992        C_null[k] = rcp (
new mat_type (numColsQk, numNullSpaceCols));
 
  995      RCP<mat_type> B_null (
new mat_type (numNullSpaceCols, numNullSpaceCols));
 
  997      int randomVectorsRank;
 
 1001        RCP<MV> X_out_null = MVT::CloneViewNonConst (X_out, nullSpaceIndices);
 
 1006        RCP<MV> X_in_null = MVT::CloneViewNonConst (X_in, nullSpaceIndices);
 
 1007        MVT::Assign (*X_out_null, *X_in_null);
 
 1010        rawProject (*X_in_null, Q, C_null);
 
 1011        randomVectorsRank = normalizeOutOfPlace (*X_in_null, *X_out_null, B_null);
 
 1015        RCP<MV> X_null = MVT::CloneViewNonConst (X_in, nullSpaceIndices);
 
 1018        rawProject (*X_null, Q, C_null);
 
 1019        randomVectorsRank = normalize (*X_null, B_null);
 
 1025      TEUCHOS_TEST_FOR_EXCEPTION(randomVectorsRank != numNullSpaceCols, 
 
 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 " 
 1031                         << randomVectorsRank << 
", but should have full " 
 1032                         "rank " << numNullSpaceCols << 
".");
 
 1037    if (reorthogonalizeBlocks_) {
 
 1040      std::vector<magnitude_type> 
 
 1041        normsAfterFirstPass (firstPassRank, SCTM::zero());
 
 1042      std::vector<magnitude_type> 
 
 1043        normsAfterSecondPass (firstPassRank, SCTM::zero());
 
 1057      Teuchos::BLAS<int, Scalar> blas;
 
 1058      for (
int j = 0; j < firstPassRank; ++j) {
 
 1059        const Scalar* 
const B_j = &(*B_out)(0,j);
 
 1062        normsAfterFirstPass[j] = blas.NRM2 (firstPassRank, B_j, 1);
 
 1066      bool reorthogonalize = 
false;
 
 1067      for (
int j = 0; j < firstPassRank; ++j) {
 
 1074        const magnitude_type curThreshold = 
 
 1075          blockReorthogThreshold() * normsBeforeFirstPass[j];
 
 1076        if (normsAfterFirstPass[j] < curThreshold) {
 
 1077          reorthogonalize = 
true; 
 
 1092      bool reorthogFault = 
false;
 
 1094      std::vector<int> faultIndices;
 
 1095      if (reorthogonalize) {
 
 1096        using Teuchos::Copy;
 
 1097        using Teuchos::NO_TRANS;
 
 1103          MVT::Assign (X_out, X_in);
 
 1108        Teuchos::Array<mat_ptr> C2;
 
 1109        allocateProjectionCoefficients (C2, Q, X_in, 
false);
 
 1114        rawProject (X_in, Q, C2);
 
 1117        RCP<mat_type> B2 (
new mat_type (ncols_X, ncols_X));
 
 1120        const int secondPassRank = outOfPlace ? 
 
 1121          normalizeOutOfPlace (X_in, X_out, B2) : 
 
 1122          normalize (X_in, B2);
 
 1123        rank = secondPassRank; 
 
 1128        mat_type B_copy (Copy, *B_out, B_out->numRows(), B_out->numCols());
 
 1130        const int err = B_out->multiply (NO_TRANS, NO_TRANS, SCT::one(), 
 
 1131                                         *B2, B_copy, SCT::zero());
 
 1132        TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::logic_error, 
 
 1133                           "Teuchos::SerialDenseMatrix::multiply " 
 1134                           "returned err = " << err << 
" != 0");
 
 1138        for (
int k = 0; k < num_Q_blocks; ++k) {
 
 1139          mat_type C_k_copy (Copy, *C[k], C[k]->numRows(), C[k]->numCols());
 
 1142          const int err2 = C[k]->multiply (NO_TRANS, NO_TRANS, SCT::one(), 
 
 1143                                          *C2[k], B_copy, SCT::one());
 
 1144          TEUCHOS_TEST_FOR_EXCEPTION(err2 != 0, std::logic_error, 
 
 1145                             "Teuchos::SerialDenseMatrix::multiply " 
 1146                             "returned err = " << err << 
" != 0");
 
 1151        for (
int j = 0; j < rank; ++j) {
 
 1152          const Scalar* 
const B2_j = &(*B2)(0,j);
 
 1153          normsAfterSecondPass[j] = blas.NRM2 (rank, B2_j, 1);
 
 1158        reorthogFault = 
false;
 
 1159        for (
int j = 0; j < rank; ++j) {
 
 1160          const magnitude_type relativeLowerBound = 
 
 1161            blockReorthogThreshold() * normsAfterFirstPass[j];
 
 1162          if (normsAfterSecondPass[j] < relativeLowerBound) {
 
 1163            reorthogFault = 
true; 
 
 1164            faultIndices.push_back (j);
 
 1169      if (reorthogFault) {
 
 1170        if (throwOnReorthogFault_) {
 
 1171          raiseReorthogFault (normsAfterFirstPass, 
 
 1172                              normsAfterSecondPass, 
 
 1180          TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error, 
 
 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;
 
 1203    for (size_type k = 0; k < faultIndices.size(); ++k)
 
 1205        const int index = faultIndices[k];
 
 1206        const magnitude_type decreaseFactor = 
 
 1207          normsAfterSecondPass[index] / normsAfterFirstPass[index];
 
 1208        os << index << 
"\t" << decreaseFactor << 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()) {
 
 1222      RCP<ParameterList> params = parameterList (
"TsqrOrthoManagerImpl");
 
 1226      params->set (
"TSQR implementation", *(tsqrAdaptor_.getValidParameters()),
 
 1227                   "TSQR implementation parameters.");
 
 1231      const bool defaultRandomizeNullSpace = 
true;
 
 1232      params->set (
"randomizeNullSpace", defaultRandomizeNullSpace, 
 
 1233                   "Whether to fill in null space vectors with random data.");
 
 1235      const bool defaultReorthogonalizeBlocks = 
true;
 
 1236      params->set (
"reorthogonalizeBlocks", defaultReorthogonalizeBlocks,
 
 1237                   "Whether to do block reorthogonalization as necessary.");
 
 1241      const magnitude_type defaultBlockReorthogThreshold = 
 
 1242        magnitude_type(10) * SCTM::squareroot (SCTM::eps());
 
 1243      params->set (
"blockReorthogThreshold", defaultBlockReorthogThreshold, 
 
 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.");
 
 1250      const magnitude_type defaultRelativeRankTolerance = 
 
 1251        Teuchos::as<magnitude_type>(10) * SCTM::eps();
 
 1256      params->set (
"relativeRankTolerance", defaultRelativeRankTolerance,
 
 1257                   "Relative tolerance to determine the numerical rank of a " 
 1258                   "block when normalizing.");
 
 1262      const bool defaultThrowOnReorthogFault = 
true;
 
 1263      params->set (
"throwOnReorthogFault", defaultThrowOnReorthogFault,
 
 1264                   "Whether to throw an exception if an orthogonalization " 
 1265                   "fault occurs.  This only matters if reorthogonalization " 
 1266                   "is enabled (reorthogonalizeBlocks==true).");
 
 1268      const bool defaultForceNonnegativeDiagonal = 
false;
 
 1269      params->set (
"forceNonnegativeDiagonal", defaultForceNonnegativeDiagonal,
 
 1270                   "Whether to force the R factor produced by the normalization " 
 1271                   "step to have a nonnegative diagonal.");
 
 1273      defaultParams_ = params;
 
 1275    return defaultParams_;
 
 
 1278  template<
class Scalar, 
class MV>
 
 1279  Teuchos::RCP<const Teuchos::ParameterList>
 
 1282    using Teuchos::ParameterList;
 
 1286    RCP<const ParameterList> defaultParams = getValidParameters();
 
 1288    RCP<ParameterList> params = rcp (
new ParameterList (*defaultParams));
 
 1297    const bool randomizeNullSpace = 
false;
 
 1298    params->set (
"randomizeNullSpace", randomizeNullSpace);      
 
 1299    const bool reorthogonalizeBlocks = 
false;
 
 1300    params->set (
"reorthogonalizeBlocks", reorthogonalizeBlocks);
 
 
 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));
 
 1340      const int numRows = B->numRows();
 
 1341      const int numCols = B->numCols();
 
 1342      TEUCHOS_TEST_FOR_EXCEPTION(numRows < 1 || numCols < 1, 
 
 1343                         std::invalid_argument,
 
 1344                         "normalizeOne: Input matrix B must be at " 
 1345                         "least 1 x 1, but is instead " << numRows
 
 1346                         << 
" x " << numCols << 
".");
 
 1348      B_out = rcp (
new mat_type (Teuchos::View, *B, 1, 1));
 
 1352    std::vector<magnitude_type> theNorm (1, SCTM::zero());
 
 1353    MVT::MvNorm (X, theNorm);
 
 1354    (*B_out)(0,0) = theNorm[0];
 
 1368    if (theNorm[0] == SCTM::zero()) {
 
 1371      if (randomizeNullSpace_) {
 
 1373        MVT::MvNorm (X, theNorm);
 
 1374        if (theNorm[0] == SCTM::zero()) {
 
 1379          throw TsqrOrthoError(
"normalizeOne: a supposedly random " 
 1380                               "vector has norm zero!");
 
 1385          const Scalar alpha = SCT::one() / theNorm[0];
 
 1386          MVT::MvScale (X, alpha);
 
 1393      const Scalar alpha = SCT::one() / theNorm[0];
 
 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 
 1408    const int num_Q_blocks = Q.size();
 
 1409    for (
int i = 0; i < num_Q_blocks; ++i)
 
 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;
 
 1454    const bool extraDebug = 
false;
 
 1456    const int numCols = MVT::GetNumberVecs (X);
 
 1463    TEUCHOS_TEST_FOR_EXCEPTION(MVT::GetNumberVecs(Q) < numCols, 
 
 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.");
 
 1471    RCP<MV> Q_view = MVT::CloneViewNonConst (Q, Range1D(0, numCols-1));
 
 1479      B_out = rcp (
new mat_type (numCols, numCols));
 
 1482      TEUCHOS_TEST_FOR_EXCEPTION(B->numRows() < numCols || B->numCols() < numCols,
 
 1483                         std::invalid_argument,
 
 1484                         "normalizeOne: Input matrix B must be at " 
 1485                         "least " << numCols << 
" x " << numCols 
 
 1486                         << 
", but is instead " << B->numRows()
 
 1487                         << 
" x " << B->numCols() << 
".");
 
 1490      B_out = rcp (
new mat_type (Teuchos::View, *B, numCols, numCols));
 
 1494      std::vector<magnitude_type> norms (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;
 
 1498      for (iter_type iter = norms.begin(); iter != norms.end(); ++iter) {
 
 1500        if (iter+1 != norms.end())
 
 1514    const int rank = rawNormalize (X, *Q_view, *B_out);
 
 1525      std::vector<magnitude_type> norms (numCols);
 
 1526      MVT::MvNorm (*Q_view, norms);
 
 1527      cerr << 
"Column norms of Q_view after orthogonalization: ";
 
 1528      for (
typename std::vector<magnitude_type>::const_iterator iter = norms.begin(); 
 
 1529           iter != norms.end(); ++iter) {
 
 1531        if (iter+1 != norms.end())
 
 1535    TEUCHOS_TEST_FOR_EXCEPTION(rank < 0 || rank > numCols, std::logic_error,
 
 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.");
 
 1540    if (extraDebug && rank == 0) {
 
 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) {
 
 1546        typedef typename mat_type::scalarType mat_scalar_type;
 
 1547        mat_scalar_type sumOfSquares = ScalarTraits<mat_scalar_type>::zero();
 
 1548        for (
typename mat_type::ordinalType i = 0; i <= j; ++i) {
 
 1549          const mat_scalar_type B_ij = 
 
 1550            ScalarTraits<mat_scalar_type>::magnitude (B_ref(i,j));
 
 1551          sumOfSquares += B_ij*B_ij;
 
 1553        norms[j] = ScalarTraits<mat_scalar_type>::squareroot (sumOfSquares);
 
 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)
 
 1568    if (rank == numCols || ! randomizeNullSpace_) {
 
 1572        MVT::Assign (*Q_view, X);
 
 1577    if (randomizeNullSpace_ && rank < numCols) {
 
 1584      const int nullSpaceNumCols = numCols - rank;
 
 1587      Range1D nullSpaceIndices (rank, numCols-1);
 
 1594      RCP<MV> Q_null = MVT::CloneViewNonConst (*Q_view, nullSpaceIndices);
 
 1596      MVT::MvRandom (*Q_null); 
 
 1602        std::vector<magnitude_type> norms (MVT::GetNumberVecs(*Q_null));
 
 1603        MVT::MvNorm (*Q_null, norms);
 
 1605        bool anyZero = 
false;
 
 1606        typedef typename std::vector<magnitude_type>::const_iterator iter_type;
 
 1607        for (iter_type it = norms.begin(); it != norms.end(); ++it) {
 
 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 " 
 1618            "random data is [" << nullSpaceIndices.lbound() << 
","  
 1619             << nullSpaceIndices.ubound() << 
"].  After filling the null " 
 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 " 
 1623          for (iter_type it = norms.begin(); it != norms.end(); ++it) {
 
 1625            if (it+1 != norms.end())
 
 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 " 
 1632          TEUCHOS_TEST_FOR_EXCEPTION(anyZero, TsqrOrthoError, os.str());
 
 1643        RCP<const MV> Q_col = MVT::CloneView (*Q_view, Range1D(0, rank-1));
 
 1648        mat_ptr C_null (
new mat_type (rank, nullSpaceNumCols));
 
 1649        rawProject (*Q_null, Q_col, C_null);
 
 1658      RCP<MV> X_null = MVT::CloneViewNonConst (X, nullSpaceIndices);
 
 1661      mat_type B_null (nullSpaceNumCols, nullSpaceNumCols);
 
 1663      const int nullSpaceBasisRank = rawNormalize (*Q_null, *X_null, B_null);
 
 1677      if (nullSpaceBasisRank < nullSpaceNumCols) {
 
 1678        std::vector<magnitude_type> norms (MVT::GetNumberVecs(*X_null));
 
 1679        MVT::MvNorm (*X_null, norms);
 
 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 " 
 1686           << 
"only have rank " << nullSpaceBasisRank << 
".  They" 
 1687           << 
" should have full rank " << nullSpaceNumCols 
 
 1688           << 
".  (The inclusive range of columns to fill with " 
 1689           << 
"random data is [" << nullSpaceIndices.lbound() 
 
 1690           << 
"," << nullSpaceIndices.ubound() << 
"].  The " 
 1691           << 
"column norms of the resulting Q factor are: [";
 
 1692        for (
typename std::vector<magnitude_type>::size_type k = 0; 
 
 1693             k < norms.size(); ++k) {
 
 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.";
 
 1704        TEUCHOS_TEST_FOR_EXCEPTION(nullSpaceBasisRank < nullSpaceNumCols, 
 
 1705                           TsqrOrthoError, os.str());
 
 1715        MVT::Assign (*X_null, *Q_null);
 
 1716      } 
else if (rank > 0) {
 
 1718        RCP<const MV> Q_col = MVT::CloneView (*Q_view, Range1D(0, rank-1));
 
 1719        RCP<MV> X_col = MVT::CloneViewNonConst (X, Range1D(0, rank-1));
 
 1720        MVT::Assign (*Q_col, *X_col);
 
 1727  template<
class Scalar, 
class MV>
 
 1729  TsqrOrthoManagerImpl<Scalar, MV>::
 
 1730  checkProjectionDims (
int& ncols_X, 
 
 1734                       Teuchos::ArrayView<Teuchos::RCP<const MV> > Q)
 const 
 1742    int the_ncols_X, the_num_Q_blocks, the_ncols_Q_total;
 
 1743    the_num_Q_blocks = Q.size();
 
 1744    the_ncols_X = MVT::GetNumberVecs (X);
 
 1747    the_ncols_Q_total = 0;
 
 1750    using Teuchos::ArrayView;
 
 1752    typedef typename ArrayView<RCP<const MV> >::const_iterator iter_type;
 
 1753    for (iter_type it = Q.begin(); it != Q.end(); ++it) {
 
 1754      const MV& Qi = **it;
 
 1755      the_ncols_Q_total += MVT::GetNumberVecs (Qi);
 
 1759    ncols_X = the_ncols_X;
 
 1760    num_Q_blocks = the_num_Q_blocks;
 
 1761    ncols_Q_total = the_ncols_Q_total;
 
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.
 
Traits class which defines basic operations on multivectors.
 
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.