예제 #1
0
double BasisAngle( const Epetra_MultiVector& S, const Epetra_MultiVector& T )
{
    //
    //  Computes the largest acute angle between the two orthogonal basis
    //
    if (S.NumVectors() != T.NumVectors()) {
        return acos( 0.0 );
    } else {
        int lwork, info = 0;
        int m = S.NumVectors(), n = T.NumVectors();
        int num_vecs = ( m < n ? m : n );
        double U[ 1 ], Vt[ 1 ];
        lwork = 3*m*n;
        std::vector<double> work( lwork );
        std::vector<double> theta( num_vecs );
        Epetra_LAPACK lapack;
        Epetra_LocalMap localMap( S.NumVectors(), 0, S.Map().Comm() );
        Epetra_MultiVector Pvec( localMap, T.NumVectors() );
        info = Pvec.Multiply( 'T', 'N', 1.0, S, T, 0.0 );
        //
        // Perform SVD on S^T*T
        //
        lapack.GESVD( 'N', 'N', num_vecs, num_vecs, Pvec.Values(), Pvec.Stride(),
                      &theta[0], U, 1, Vt, 1, &work[0], &lwork, &info );
        assert( info == 0 );
        return (acos( theta[num_vecs-1] ) );
    }
    //
    // Default return statement, should never be executed.
    //
    return acos( 0.0 );
}
예제 #2
0
  void IncSVDPOD::incStep(int lup) {

    Epetra_LAPACK lapack;

    // perform gram-schmidt expansion
    // expand() will update bases U_ and V_, factor B_, as well as counters curRank_ and numProc_
    this->expand(lup);

    // compute the SVD of B
    const int lwork = 5*curRank_;
    int info;
    Epetra_SerialDenseMatrix Uhat(::Copy,B_->A(),B_->LDA(),curRank_,curRank_), Vhat(curRank_,curRank_);
    std::vector<double> Shat(curRank_), work(lwork);

    // Note: this actually stores Vhat^T (we remedy this below)
    lapack.GESVD('O','A',curRank_,curRank_,Uhat.A(),Uhat.LDA(),&Shat[0],Uhat.A(),Uhat.LDA(),Vhat.A(),Vhat.LDA(),&work[0],&lwork,&info);
    TEUCHOS_TEST_FOR_EXCEPTION(info!=0,std::logic_error,"RBGen::IncSVDPOD::incStep(): GESVD return info != 0");

    // use filter to determine new rank
    std::vector<int> keepind = filter_->filter(Shat);
    std::vector<int> truncind(curRank_-keepind.size());
    {
      std::vector<int> allind(curRank_);
      for (int i=0; i<curRank_; i++) {
        allind[i] = i;
      }
      set_difference(allind.begin(),allind.end(),keepind.begin(),keepind.end(),truncind.begin());
      
      // Vhat actually contains Vhat^T; correct this here
      Epetra_SerialDenseMatrix Ucopy(Uhat), Vcopy(curRank_,curRank_); 
      std::vector<double> Scopy(Shat);
      for (int j=0; j<curRank_; j++) {
        for (int i=0; i<curRank_; i++) {
          Vcopy(i,j) = Vhat(j,i);
        }
      }
      // put the desired sigmas at the front of Uhat, Vhat
      for (unsigned int j=0; j<keepind.size(); j++) {
        std::copy(&Ucopy(0,keepind[j]),&Ucopy(curRank_,keepind[j]),&Uhat(0,j));
        std::copy(&Vcopy(0,keepind[j]),&Vcopy(curRank_,keepind[j]),&Vhat(0,j));
        Shat[j] = Scopy[keepind[j]];
      }
      for (unsigned int j=0; j<truncind.size(); j++) {
        std::copy(&Ucopy(0,truncind[j]),&Ucopy(curRank_,truncind[j]),&Uhat(0,keepind.size()+j));
        std::copy(&Vcopy(0,truncind[j]),&Vcopy(curRank_,truncind[j]),&Vhat(0,keepind.size()+j));
        Shat[keepind.size()+j] = Scopy[truncind[j]];
      }
    }

    // shrink back down again
    // shrink() will update bases U_ and V_, as well as singular values sigma_ and curRank_
    this->shrink(truncind.size(),Shat,Uhat,Vhat);

    // print out some info
    const Epetra_Comm *comm = &A_->Comm();
    if (comm->MyPID() == 0 && verbLevel_ >= 2) {
      std::cout 
        << "------------- IncSVDPOD::incStep() --------------" << std::endl
        << "| Cols Processed: " << numProc_ << std::endl
        << "|    Current lup: " << lup << std::endl
        << "|  Current ldown: " << truncind.size() << std::endl
        << "|   Current rank: " << curRank_ << std::endl
        << "| Current sigmas: " << std::endl;
      for (int i=0; i<curRank_; i++) {
        std::cout << "|                   " << sigma_[i] << std::endl;
      }
    }

  }