Пример #1
0
RCP<Epetra_CrsMatrix> getMyEpetraMatrix(int numRows, int numCols, double shift=0.0)
{
  const RCP<const Epetra_Comm> comm = getEpetraComm();

  const Epetra_Map rowMap(numRows, 0, *comm);
  const Epetra_Map domainMap(numCols, numCols, 0, *comm);

  const RCP<Epetra_CrsMatrix> epetraCrsM =
    rcp(new Epetra_CrsMatrix(Copy, rowMap,domainMap,0));

  Array<double> rowEntries(numCols);
  Array<int> columnIndices(numCols);
  for (int j = 0; j < numCols; ++j)
    columnIndices[j] = j;

  const int numLocalRows = rowMap.NumMyElements();
  for (int i = 0; i < numLocalRows; ++i) {
    for (int j = 0; j < numCols; ++j) {
      rowEntries[j] = as<double>(i+1) + as<double>(j+1) / 10 + shift;
    }

    epetraCrsM->InsertMyValues( i, numCols, &rowEntries[0], &columnIndices[0] );
  }

  epetraCrsM->FillComplete(domainMap,rowMap);
  return epetraCrsM;
}
Пример #2
0
// =========================================================================
RCP<Epetra_CrsMatrix>
contructEpetraMatrix(const int n,
                     const Epetra_Comm & eComm)
{
  RCP<Epetra_CrsMatrix> A;
  // Build the matrix (-1,2,-1).
  Epetra_Map map(n, 0, eComm);
  int * myGlobalElements = map.MyGlobalElements();
  A = rcp(new Epetra_CrsMatrix(Copy, map, 3));
  double vals[] = {-1.0, 2.0, -1.0};
  for (int k = 0; k < map.NumMyElements(); k++) {
    if (myGlobalElements[k] == 0) {
      int cols[] = {myGlobalElements[k], myGlobalElements[k]+1};
      TEUCHOS_ASSERT_EQUALITY(0, A->InsertGlobalValues(myGlobalElements[k],
                              2,
                              &vals[1],
                              cols));
    } else if (myGlobalElements[k] == n-1) {
      int cols[] = {myGlobalElements[k]-1, myGlobalElements[k]};
      TEUCHOS_ASSERT_EQUALITY(0, A->InsertGlobalValues(myGlobalElements[k],
                              2,
                              vals,
                              cols));
    } else {
      int cols[] = {myGlobalElements[k]-1, myGlobalElements[k], myGlobalElements[k]+1};
      TEUCHOS_ASSERT_EQUALITY(0, A->InsertGlobalValues(myGlobalElements[k],
                              3,
                              vals,
                              cols));
    }
  }
  TEUCHOS_ASSERT_EQUALITY(0, A->FillComplete(true));

  return A;
}
Пример #3
0
int rebalanceEpetraProblem( RCP<Epetra_Map>         &Map,
                            RCP<Epetra_CrsMatrix>   &A,
                            RCP<Epetra_MultiVector> &B,
                            RCP<Epetra_MultiVector> &X,
                            Epetra_Comm             &Comm
                          )
{
  // Rebalance linear system across multiple processors.
  if ( Comm.NumProc() > 1 ) {
    RCP<Epetra_Map> newMap = rcp( new Epetra_Map( Map->NumGlobalElements(), Map->IndexBase(), Comm ) );
    RCP<Epetra_Import> newImport = rcp( new Epetra_Import( *newMap, *Map ) );

    // Create rebalanced versions of the linear system.
    RCP<Epetra_CrsMatrix> newA = rcp( new Epetra_CrsMatrix( BELOSEPETRACOPY, *newMap, 0 ) );
    newA->Import( *A, *newImport, Insert );
    newA->FillComplete();
    RCP<Epetra_MultiVector> newB = rcp( new Epetra_MultiVector( *newMap, B->NumVectors() ) );
    newB->Import( *B, *newImport, Insert );
    RCP<Epetra_MultiVector> newX = rcp( new Epetra_MultiVector( *newMap, X->NumVectors() ) );
    newX->Import( *X, *newImport, Insert );

    // Set the pointers to the new rebalance linear system.
    A = newA;
    B = newB;
    X = newX;
    Map = newMap;
  }

  return (0);
}
Пример #4
0
RCP<Epetra_CrsMatrix> UserInputForTests::getEpetraCrsMatrix()
{
  if (M_.is_null())
    throw std::runtime_error("could not read mtx file");
  RCP<Epetra_CrsGraph> egraph = getEpetraCrsGraph();
  eM_ = rcp(new Epetra_CrsMatrix(Copy, *egraph));

  size_t maxRow = M_->getNodeMaxNumRowEntries();
  int nrows = egraph->NumMyRows();
  int base = egraph->IndexBase();
  const Epetra_BlockMap &rowMap = egraph->RowMap();
  const Epetra_BlockMap &colMap = egraph->ColMap();
  Array<int> colGid(maxRow);

  for (int i=0; i < nrows; i++){
    ArrayView<const int> colLid;
    ArrayView<const scalar_t> nz;
    M_->getLocalRowView(i+base, colLid, nz);
    size_t rowSize = colLid.size();
    int rowGid = rowMap.GID(i+base);
    for (size_t j=0; j < rowSize; j++){
      colGid[j] = colMap.GID(colLid[j]);
    }
    eM_->InsertGlobalValues(
      rowGid, rowSize, nz.getRawPtr(), colGid.getRawPtr());
  }
  eM_->FillComplete();
  return eM_;
}
Пример #5
0
RCP<Epetra_Operator> 
MockModelEval_D::
create_W() const
{
  RCP<Epetra_CrsMatrix> W = rcp(new Epetra_CrsMatrix(Copy, *graph));
  W->FillComplete();
  return W;
}
Пример #6
0
// construct a diagonal matrix
const Teuchos::RCP<const Thyra::LinearOpBase<double> > DiagMatrix(int cnt,double * vec,std::string label)
{
   const RCP<Epetra_SerialComm> comm = rcp(new Epetra_SerialComm());
   const RCP<Epetra_Map> map = rcp(new Epetra_Map(cnt,0,*comm));
   const RCP<Epetra_CrsMatrix> ptrF  = rcp(new Epetra_CrsMatrix(Copy,*map,1));

   // construct a diagonal matrix
   for(int i=0;i<cnt;i++)
      ptrF->InsertGlobalValues(i,1,&vec[i],&i);
   ptrF->FillComplete();

   // return thyra object
   return Thyra::epetraLinearOp(ptrF,label);
}
Пример #7
0
const RCP<Epetra_Operator> buildStridedSystem(const Epetra_Comm & comm,int size)
{
  Epetra_Map map(2*size,0,comm);

  RCP<Epetra_CrsMatrix> mat = rcp(new Epetra_CrsMatrix(Copy,map,0));

  int numUnks = 2;
  double valuesA[] = { -1.0, 2.0, 7.0, -1.0 };
  double valuesB[] = { -1.0, 2.0, 9.0, -1.0 };
  int iTempA[] = {-numUnks,0, 1,numUnks}, indices[4];
  int iTempB[] = {-numUnks,0,-1,numUnks};
  double * vPtr;
  int * iPtr;

  for(int i=0;i<map.NumMyElements()/numUnks;i++) {
     int count = 4;
     int gidA = map.GID(2*i);
     int gidB = gidA+1;

     for(int n=0;n<numUnks;n++) {
        int * iTemp = (n==0) ? iTempA : iTempB;
        int gid = (n==0) ? gidA : gidB;

        indices[0] = gid+iTemp[0];
        indices[1] = gid+iTemp[1];
        indices[2] = gid+iTemp[2];
        indices[3] = gid+iTemp[3];

        vPtr = (n==0) ? valuesA : valuesB;
        iPtr = indices;
     
        if(gid<numUnks) {
           vPtr++;
           iPtr = &indices[1];
           count = 3;
        }
        else if(gid>map.MaxAllGID()-numUnks)
           count = 3;

        mat->InsertGlobalValues(gid,count,vPtr,iPtr);
     }
  }

  mat->FillComplete();

  EpetraExt::RowMatrixToMatrixMarketFile("strided.mm",*mat);

  return mat;
}
Пример #8
0
RCP<Thyra::LinearOpBase<double> > buildExampleOp(int type,const Epetra_Comm & comm,double scale)
{
   Epetra_Map map(3,0,comm);
   RCP<Epetra_CrsMatrix> mat = rcp(new Epetra_CrsMatrix(Copy,map,3));

   double values[3];
   int indices[3] = { 0, 1, 2 };

   switch(type) {
   case 3:
      values[0] = 9.0; values[1] = 8.0; values[2] = 7.0;
      mat->InsertGlobalValues(0,3,values,indices);

      values[0] = 1.0; values[1] = 2.0; values[2] = 3.0;
      mat->InsertGlobalValues(1,3,values,indices);

      values[0] = 4.0; values[1] = 5.0; values[2] = 6.0;
      mat->InsertGlobalValues(2,3,values,indices);
      break;
   case 2:
      values[0] = 5.0; values[1] = 0.0; values[2] = 6.0;
      mat->InsertGlobalValues(0,3,values,indices);

      values[0] = 2.0; values[1] = 6.0; values[2] = 0.0;
      mat->InsertGlobalValues(1,3,values,indices);

      values[0] = 0.0; values[1] = 3.0; values[2] = 7.0;
      mat->InsertGlobalValues(2,3,values,indices);
      break;
   case 1:
      values[0] = 1.0; values[1] = 0.0; values[2] = 2.0;
      mat->InsertGlobalValues(0,3,values,indices);

      values[0] = 2.0; values[1] = 5.0; values[2] = 0.0;
      mat->InsertGlobalValues(1,3,values,indices);

      values[0] = 0.0; values[1] = 3.0; values[2] = 1.0;
      mat->InsertGlobalValues(2,3,values,indices);
   default:
      break;
   }

   mat->FillComplete();
   mat->Scale(scale);

   return Thyra::nonconstEpetraLinearOp(mat);
}
Пример #9
0
static const RCP<const Thyra::LinearOpBase<double> > build2x2(const RCP<const Epetra_Map> & map,double a,double b,double c,double d)
{
   int indicies[2];
   double row0[2];
   double row1[2];

   indicies[0] = 0;
   indicies[1] = 1;

   // build a CrsMatrix
   RCP<Epetra_CrsMatrix> blk  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   row0[0] = a; row0[1] = c;  // do a transpose here!
   row1[0] = b; row1[1] = d; 
   blk->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   blk->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   blk->FillComplete();

   return Thyra::epetraLinearOp(blk);
}
Пример #10
0
void newAssembly(Teuchos::FancyOStream &out)
{
  RCP<panzer::DOFManager<int,int> > my_dofM;
  RCP<Map> rowmap;
  RCP<Map> colmap;
  RCP<panzer::ConnManager<int,int> > conn;

  const std::vector<int> & myElements=conn->getElementBlock("eblock-0_0_0");

  std::vector<std::vector<int> > gids;
  std::vector<std::vector<int> > lids;
  std::vector< std::vector<std::vector<double> > >miniMat;
  fillMeUp1(gids,lids,miniMat,my_dofM,myElements,colmap);


  RCP<CrsGraph> crsgraph = rcp(new CrsGraph(Copy,*rowmap,*colmap,-1));

  //Tell the graph where elements will be.
  for(size_t e=0;e<myElements.size();++e){
    for (size_t i = 0; i < gids[e].size(); ++i) {
      crsgraph->InsertGlobalIndices(gids[e][i],gids[e].size(), &gids[e][0]);
    }
  }
  {
    crsgraph->FillComplete();
  }
  RCP<CrsMatrix> crsmat = rcp(new CrsMatrix(Copy,*crsgraph));
  
  //Where the data transfer takes place.
  for(std::size_t i=0;i<20;i++) {
    Teuchos::TimeMonitor LocalTimer(*New_Time);

    for ( size_t e = 0; e < myElements.size(); ++e) {
      for (size_t i = 0; i < gids[e].size(); ++i) {
        int accid=lids[e][i];
        crsmat->SumIntoMyValues(accid,lids[e].size(),&miniMat[e][i][0],&lids[e][0]);
      }
    }
  }

  return;
}
Пример #11
0
const RCP<Thyra::LinearOpBase<double> > buildSystem(const Epetra_Comm & comm,int size)
{
   Epetra_Map map(size,0,comm);

   RCP<Epetra_CrsMatrix> mat = rcp(new Epetra_CrsMatrix(Copy,map,0));

   double values[] = { -1.0, 2.0, -1.0};
   int iTemp[] = {-1,0,1}, indices[3];
   double * vPtr;
   int * iPtr;

   for(int i=0;i<map.NumMyElements();i++) {
      int count = 3;
      int gid = map.GID(i);

      vPtr = values;
      iPtr = indices;

      indices[0] = gid+iTemp[0];
      indices[1] = gid+iTemp[1];
      indices[2] = gid+iTemp[2];
      
      if(gid==0) {
         vPtr = &values[1];
         iPtr = &indices[1];
         count = 2;
      }
      else if(gid==map.MaxAllGID())
         count = 2;

      mat->InsertGlobalValues(gid,count,vPtr,iPtr);
   }

   mat->FillComplete();

   return Thyra::nonconstEpetraLinearOp(mat);
}
Пример #12
0
RCP<Epetra_CrsGraph> UserInputForTests::getEpetraCrsGraph()
{
  if (M_.is_null())
    throw std::runtime_error("could not read mtx file");
  RCP<const tcrsGraph_t> tgraph = M_->getCrsGraph();
  RCP<const Tpetra::Map<lno_t, gno_t> > trowMap = tgraph->getRowMap();
  RCP<const Tpetra::Map<lno_t, gno_t> > tcolMap = tgraph->getColMap();

  int nElts = static_cast<int>(trowMap->getGlobalNumElements());
  int nMyElts = static_cast<int>(trowMap->getNodeNumElements());
  int base = trowMap->getIndexBase();
  ArrayView<const int> gids = trowMap->getNodeElementList();

  Epetra_BlockMap erowMap(nElts, nMyElts,
    gids.getRawPtr(), 1, base, *ecomm_);

  Array<int> rowSize(nMyElts);
  for (int i=0; i < nMyElts; i++){
    rowSize[i] = static_cast<int>(M_->getNumEntriesInLocalRow(i+base));
  }

  size_t maxRow = M_->getNodeMaxNumRowEntries();
  Array<int> colGids(maxRow);
  ArrayView<const int> colLid;

  eG_ = rcp(new Epetra_CrsGraph(Copy, erowMap, 
    rowSize.getRawPtr(), true));

  for (int i=0; i < nMyElts; i++){
    tgraph->getLocalRowView(i+base, colLid);
    for (int j=0; j < colLid.size(); j++)
      colGids[j] = tcolMap->getGlobalElement(colLid[j]);
    eG_->InsertGlobalIndices(gids[i], rowSize[i], colGids.getRawPtr());
  }
  eG_->FillComplete();
  return eG_;
}
Пример #13
0
// Serial only. Very straightforward: one eval per column. Could speed up a lot
// using graph coloring.
double
testJacobian (panzer::AssemblyEngine_TemplateManager<panzer::Traits>& ae_tm,
              const Teuchos::RCP<panzer::LinearObjFactory<panzer::Traits> >& linObjFactory,
              const Teuchos::RCP<const Epetra_Vector> x0 = Teuchos::null)
{
  using Teuchos::RCP;
  using Teuchos::rcp;

  const RCP<panzer::LinearObjContainer> ghost_con = linObjFactory->buildGhostedLinearObjContainer();
  const RCP<panzer::LinearObjContainer> con = linObjFactory->buildLinearObjContainer();
  linObjFactory->initializeGhostedContainer(panzer::LinearObjContainer::X |
                                            panzer::LinearObjContainer::F |
                                            panzer::LinearObjContainer::Mat, *ghost_con);
  const RCP<panzer::EpetraLinearObjContainer>
    ep_con = Teuchos::rcp_dynamic_cast<panzer::EpetraLinearObjContainer>(con);

  SparseTriple t;
  { // Finite-difference Jacobian. Should use graph coloring to greatly reduce
    // number of evaluations. But brute force for now.
    RCP<Epetra_Vector> x, f0;
    for (int i = -1; ; ++i) {
      linObjFactory->initializeContainer(panzer::LinearObjContainer::X | panzer::LinearObjContainer::F |
                                         panzer::LinearObjContainer::Mat, *con);
      ghost_con->initialize();
      con->initialize();
      const Epetra_Map& row_map = ep_con->get_A()->RowMap(), col_map = ep_con->get_A()->ColMap();
      if (i == -1) {
        if (Teuchos::nonnull(x0))
          x = rcp(new Epetra_Vector(*x0));
        else
          x = rcp(new Epetra_Vector(ep_con->get_x()->Map()));
        t.m = t.n = x->GlobalLength();
      }
      // For a linear problem, could make delta 1 to remove cancellation
      // error. But I want to look at a nonlinear Robin condition, so do a true
      // finite difference.
      const double delta = 1e-6;
      const bool i_mine = row_map.MyGID(i);
      double x_prev = 0;
      int i_lid = 0;
      if (i_mine && i >= 0) {
        i_lid = col_map.LID(i);
        x_prev = (*x)[i_lid];
        (*x)[i_lid] += delta;
      }
      ep_con->set_x(x);
      panzer::AssemblyEngineInArgs input(ghost_con, ep_con);
      input.alpha = 0;
      input.beta = 1;
      ae_tm.getAsObject<panzer::Traits::Residual>()->evaluate(input);
      if (i == -1)
        f0 = ep_con->get_f();
      else {
        const Epetra_Vector& f = *ep_con->get_f();
        if (i_mine) (*x)[i_lid] = x_prev;
        for (int k = 0; k < f.MyLength(); ++k) {
          const double d = f[k] - (*f0)[k];
          if (d == 0) continue;
          t.i.push_back(row_map.GID(k));
          t.j.push_back(i);
          t.v.push_back(d/delta);
        }
      }
      if (i + 1 == t.m) break;
    }
  }

  { // AD Jacobian.
    linObjFactory->initializeContainer(panzer::LinearObjContainer::X | panzer::LinearObjContainer::F |
                                       panzer::LinearObjContainer::Mat, *con);
    ghost_con->initialize();
    con->initialize();
    if (Teuchos::nonnull(x0))
      ep_con->set_x(rcp(new Epetra_Vector(*x0)));
    else
      ep_con->get_x()->PutScalar(0);
    panzer::AssemblyEngineInArgs input(ghost_con, ep_con);
    input.alpha = 0;
    input.beta = 1;
    ae_tm.getAsObject<panzer::Traits::Jacobian>()->evaluate(input);
    EpetraExt::RowMatrixToMatrixMarketFile("A_ad.mm", *ep_con->get_A());
  }

  RCP<Epetra_CrsMatrix> A_fd;
  {
    const Epetra_Map& row_map = ep_con->get_A()->RowMap(), col_map = ep_con->get_A()->ColMap();
    A_fd = rcp(new Epetra_CrsMatrix(Copy, row_map, 40));
    for (int i = 0; i < static_cast<int>(t.v.size()); ++i)
      A_fd->InsertGlobalValues(t.i[i], 1, &t.v[i], &t.j[i]);
    A_fd->FillComplete();
  }
  EpetraExt::RowMatrixToMatrixMarketFile("A_fd.mm", *A_fd);

  { // Check error.
    const double A_fd_inf_norm = A_fd->NormInf();
    RCP<Epetra_CrsMatrix> D = rcp(new Epetra_CrsMatrix(Copy, ep_con->get_A()->Graph()));
    D->FillComplete();
    Epetra_CrsMatrix* D_ptr = D.get();
    EpetraExt::MatrixMatrix::Add(*ep_con->get_A(), false, -1, *A_fd, false, 1, D_ptr);
    const double D_inf_norm = D->NormInf();
    return D_inf_norm / A_fd_inf_norm;
  }
}
Пример #14
0
int
main (int argc, char *argv[])
{
  using namespace Anasazi;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using std::endl;

#ifdef HAVE_MPI
  // Initialize MPI
  MPI_Init (&argc, &argv);
#endif // HAVE_MPI

  // Create an Epetra communicator
#ifdef HAVE_MPI
  Epetra_MpiComm Comm (MPI_COMM_WORLD);
#else
  Epetra_SerialComm Comm;
#endif // HAVE_MPI

  // Create an Anasazi output manager
  BasicOutputManager<double> printer;
  printer.stream(Errors) << Anasazi_Version() << std::endl << std::endl;

  // Get the sorting std::string from the command line
  std::string which ("LM");
  Teuchos::CommandLineProcessor cmdp (false, true);
  cmdp.setOption("sort", &which, "Targetted eigenvalues (SM or LM).");
  if (cmdp.parse (argc, argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
#ifdef HAVE_MPI
    MPI_Finalize ();
#endif // HAVE_MPI
    return -1;
  }

  // Dimension of the matrix
  //
  // Discretization points in any one direction.
  const int nx = 10;
  // Size of matrix nx*nx
  const int NumGlobalElements = nx*nx;

  // Construct a Map that puts approximately the same number of
  // equations on each process.
  Epetra_Map Map (NumGlobalElements, 0, Comm);

  // Get update list and number of local equations from newly created Map.
  int NumMyElements = Map.NumMyElements ();

  std::vector<int> MyGlobalElements (NumMyElements);
  Map.MyGlobalElements (&MyGlobalElements[0]);

  // Create an integer vector NumNz that is used to build the Petra
  // matrix.  NumNz[i] is the number of OFF-DIAGONAL terms for the
  // i-th global equation on this process.
  std::vector<int> NumNz (NumMyElements);

  /* We are building a matrix of block structure:

      | T -I          |
      |-I  T -I       |
      |   -I  T       |
      |        ...  -I|
      |           -I T|

   where each block is dimension nx by nx and the matrix is on the order of
   nx*nx.  The block T is a tridiagonal matrix.
  */
  for (int i=0; i<NumMyElements; ++i) {
    if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1 ||
        MyGlobalElements[i] == nx-1 || MyGlobalElements[i] == nx*(nx-1) ) {
      NumNz[i] = 3;
    }
    else if (MyGlobalElements[i] < nx || MyGlobalElements[i] > nx*(nx-1) ||
             MyGlobalElements[i]%nx == 0 || (MyGlobalElements[i]+1)%nx == 0) {
      NumNz[i] = 4;
    }
    else {
      NumNz[i] = 5;
    }
  }

  // Create an Epetra_Matrix
  RCP<Epetra_CrsMatrix> A = rcp (new Epetra_CrsMatrix (Epetra_DataAccess::Copy, Map, &NumNz[0]));

  // Compute coefficients for discrete convection-diffution operator
  const double one = 1.0;
  std::vector<double> Values(4);
  std::vector<int> Indices(4);
  double rho = 0.0;
  double h = one /(nx+1);
  double h2 = h*h;
  double c = 5.0e-01*rho/ h;
  Values[0] = -one/h2 - c; Values[1] = -one/h2 + c; Values[2] = -one/h2; Values[3]= -one/h2;
  double diag = 4.0 / h2;
  int NumEntries;

  for (int i=0; i<NumMyElements; ++i) {
    if (MyGlobalElements[i]==0) {
      Indices[0] = 1;
      Indices[1] = nx;
      NumEntries = 2;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i] == nx*(nx-1)) {
      Indices[0] = nx*(nx-1)+1;
      Indices[1] = nx*(nx-2);
      NumEntries = 2;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i] == nx-1) {
      Indices[0] = nx-2;
      NumEntries = 1;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
      Indices[0] = 2*nx-1;
      info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i] == NumGlobalElements-1) {
      Indices[0] = NumGlobalElements-2;
      NumEntries = 1;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
      Indices[0] = nx*(nx-1)-1;
      info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i] < nx) {
      Indices[0] = MyGlobalElements[i]-1;
      Indices[1] = MyGlobalElements[i]+1;
      Indices[2] = MyGlobalElements[i]+nx;
      NumEntries = 3;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i] > nx*(nx-1)) {
      Indices[0] = MyGlobalElements[i]-1;
      Indices[1] = MyGlobalElements[i]+1;
      Indices[2] = MyGlobalElements[i]-nx;
      NumEntries = 3;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if (MyGlobalElements[i]%nx == 0) {
      Indices[0] = MyGlobalElements[i]+1;
      Indices[1] = MyGlobalElements[i]-nx;
      Indices[2] = MyGlobalElements[i]+nx;
      NumEntries = 3;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else if ((MyGlobalElements[i]+1)%nx == 0) {
      Indices[0] = MyGlobalElements[i]-nx;
      Indices[1] = MyGlobalElements[i]+nx;
      NumEntries = 2;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
      Indices[0] = MyGlobalElements[i]-1;
      NumEntries = 1;
      info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    else {
      Indices[0] = MyGlobalElements[i]-1;
      Indices[1] = MyGlobalElements[i]+1;
      Indices[2] = MyGlobalElements[i]-nx;
      Indices[3] = MyGlobalElements[i]+nx;
      NumEntries = 4;
      int info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
      TEUCHOS_TEST_FOR_EXCEPTION
        (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
         << info << " != 0." );
    }
    // Put in the diagonal entry
    int info = A->InsertGlobalValues(MyGlobalElements[i], 1, &diag, &MyGlobalElements[i]);
    TEUCHOS_TEST_FOR_EXCEPTION
      (info != 0, std::runtime_error, "InsertGlobalValues returned info = "
       << info << " != 0." );
  }

  // Finish up
  int info = A->FillComplete ();
  TEUCHOS_TEST_FOR_EXCEPTION
    (info != 0, std::runtime_error, "A->FillComplete() returned info = "
     << info << " != 0." );
  A->SetTracebackMode (1); // Shutdown Epetra Warning tracebacks

  // Create a identity matrix for the temporary mass matrix
  RCP<Epetra_CrsMatrix> M = rcp (new Epetra_CrsMatrix (Epetra_DataAccess::Copy, Map, 1));
  for (int i=0; i<NumMyElements; i++) {
    Values[0] = one;
    Indices[0] = i;
    NumEntries = 1;
    info = M->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]);
    TEUCHOS_TEST_FOR_EXCEPTION
      (info != 0, std::runtime_error, "M->InsertGlobalValues() returned info = "
       << info << " != 0." );
  }
  // Finish up
  info = M->FillComplete ();
  TEUCHOS_TEST_FOR_EXCEPTION
    (info != 0, std::runtime_error, "M->FillComplete() returned info = "
     << info << " != 0." );
  M->SetTracebackMode (1); // Shutdown Epetra Warning tracebacks

  //************************************
  // Call the LOBPCG solver manager
  //***********************************
  //
  // Variables used for the LOBPCG Method
  const int nev       = 10;
  const int blockSize = 5;
  const int maxIters  = 500;
  const double tol    = 1.0e-8;

  typedef Epetra_MultiVector MV;
  typedef Epetra_Operator OP;
  typedef MultiVecTraits<double, Epetra_MultiVector> MVT;

  // Create an Epetra_MultiVector for an initial vector to start the
  // solver.  Note: This needs to have the same number of columns as
  // the blocksize.
  RCP<Epetra_MultiVector> ivec = rcp (new Epetra_MultiVector (Map, blockSize));
  ivec->Random (); // fill the initial vector with random values

  // Create the eigenproblem.
  RCP<BasicEigenproblem<double, MV, OP> > MyProblem =
    rcp (new BasicEigenproblem<double, MV, OP> (A, ivec));

  // Inform the eigenproblem that the operator A is symmetric
  MyProblem->setHermitian (true);

  // Set the number of eigenvalues requested
  MyProblem->setNEV (nev);

  // Tell the eigenproblem that you are finishing passing it information.
  const bool success = MyProblem->setProblem ();
  if (! success) {
    printer.print (Errors, "Anasazi::BasicEigenproblem::setProblem() reported an error.\n");
#ifdef HAVE_MPI
    MPI_Finalize ();
#endif // HAVE_MPI
    return -1;
  }

  // Create parameter list to pass into the solver manager
  Teuchos::ParameterList MyPL;
  MyPL.set ("Which", which);
  MyPL.set ("Block Size", blockSize);
  MyPL.set ("Maximum Iterations", maxIters);
  MyPL.set ("Convergence Tolerance", tol);
  MyPL.set ("Full Ortho", true);
  MyPL.set ("Use Locking", true);

  // Create the solver manager
  LOBPCGSolMgr<double, MV, OP> MySolverMan (MyProblem, MyPL);

  // Solve the problem
  ReturnType returnCode = MySolverMan.solve ();

  // Get the eigenvalues and eigenvectors from the eigenproblem
  Eigensolution<double,MV> sol = MyProblem->getSolution ();
  std::vector<Value<double> > evals = sol.Evals;
  RCP<MV> evecs = sol.Evecs;

  // Compute residuals.
  std::vector<double> normR (sol.numVecs);
  if (sol.numVecs > 0) {
    Teuchos::SerialDenseMatrix<int,double> T (sol.numVecs, sol.numVecs);
    Epetra_MultiVector tempAevec (Map, sol.numVecs );
    T.putScalar (0.0);
    for (int i = 0; i < sol.numVecs; ++i) {
      T(i,i) = evals[i].realpart;
    }
    A->Apply (*evecs, tempAevec);
    MVT::MvTimesMatAddMv (-1.0, *evecs, T, 1.0, tempAevec);
    MVT::MvNorm (tempAevec, normR);
  }

  // Print the results
  std::ostringstream os;
  os.setf (std::ios_base::right, std::ios_base::adjustfield);
  os << "Solver manager returned "
     << (returnCode == Converged ? "converged." : "unconverged.") << endl;
  os << endl;
  os << "------------------------------------------------------" << endl;
  os << std::setw(16) << "Eigenvalue"
     << std::setw(18) << "Direct Residual"
     << endl;
  os << "------------------------------------------------------" << endl;
  for (int i = 0; i < sol.numVecs; ++i) {
    os << std::setw(16) << evals[i].realpart
       << std::setw(18) << normR[i] / evals[i].realpart
       << endl;
  }
  os << "------------------------------------------------------" << endl;
  printer.print (Errors, os.str ());

#ifdef HAVE_MPI
  MPI_Finalize ();
#endif // HAVE_MPI
  return 0;
}
void tSIMPLEPreconditionerFactory::initializeTest()
{
   std::vector<int> indicies(2);
   std::vector<double> row0(2),row1(2);

   tolerance_ = 1.0e-13;

   comm=GetComm();

   const RCP<Epetra_Map> map = rcp(new Epetra_Map(2,0,*comm));

   const RCP<Epetra_CrsMatrix> ptrF  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrB  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrBt = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrC  = rcp(new Epetra_CrsMatrix(Copy,*map,2));

   const RCP<Epetra_CrsMatrix> ptrInvF = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrInvS = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrInvMass = rcp(new Epetra_CrsMatrix(Copy,*map,2));

   indicies[0] = 0;
   indicies[1] = 1;

   // build F matrix
   row0[0] = 1.0; row0[1] = 2.0; 
   row1[0] = 2.0; row1[1] = 1.0; 
   ptrF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrF->FillComplete();
   F_ = Thyra::epetraLinearOp(ptrF,"ptrF");

   // build block info for block diagonal (one block)
   block_starts_=arcp(new int[2],0,2);
   block_gids_=arcp(new int[2],0,2);
   int *block_starts=block_starts_.getRawPtr();
   int *block_gids=block_gids_.getRawPtr();
   block_starts[0]=0;block_starts[1]=2;
   block_gids[0]=ptrF->LRID(0);
   block_gids[1]=ptrF->LRID(1);
   
   // build B matrix
   row0[0] =  1.0; row0[1] = -3.0; 
   row1[0] = -1.0; row1[1] =  1.0; 
   ptrB->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrB->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrB->FillComplete();
   B_ = Thyra::epetraLinearOp(ptrB,"ptrB");
   
   // build Bt matrix
   row0[0] =  1.0; row0[1] = -1.0; 
   row1[0] = -3.0; row1[1] =  1.0; 
   ptrBt->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrBt->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrBt->FillComplete();
   Bt_ = Thyra::epetraLinearOp(ptrBt,"ptrBt");

   // build C matrix
   row0[0] = 1.0; row0[1] = 2.0; 
   row1[0] = 2.0; row1[1] = 1.0; 
   ptrC->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrC->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrC->FillComplete();
   C_ = Thyra::epetraLinearOp(ptrC,"ptrC");

   // build inv(F) matrix
   row0[0] = -1.0/3.0; row0[1] =  2.0/3.0;
   row1[0] =  2.0/3.0; row1[1] = -1.0/3.0;
   ptrInvF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvF->FillComplete();
   invF_ = rcp(new StaticOpInverseFactory(Thyra::epetraLinearOp(ptrInvF,"ptrInvF")));

   // build inv(Pschur) matrix
   row0[0] = 0.037037037037037; row0[1] = 0.222222222222222;
   row1[0] = 0.222222222222222; row1[1] = 0.333333333333333;
   ptrInvS->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvS->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvS->FillComplete();
   invS_ = rcp(new StaticOpInverseFactory(Thyra::epetraLinearOp(ptrInvS,"ptrInvS")));

   A_ = Thyra::block2x2<double>(F_,Bt_,B_,C_,"A");
}
Пример #16
0
// build a single subblock Epetra_CrsMatrix
RCP<Epetra_CrsMatrix> buildSubBlock(int i,int j,const Epetra_CrsMatrix & A,const std::vector<std::pair<int,RCP<Epetra_Map> > > & subMaps)
{
   // get the number of variables families
   int numVarFamily = subMaps.size();

   TEUCHOS_ASSERT(i>=0 && i<numVarFamily);
   TEUCHOS_ASSERT(j>=0 && j<numVarFamily);

   const Epetra_Map & gRowMap = *subMaps[i].second;
   const Epetra_Map & rowMap = *Teuchos::get_extra_data<RCP<Epetra_Map> >(subMaps[i].second,"contigMap");
   const Epetra_Map & colMap = *Teuchos::get_extra_data<RCP<Epetra_Map> >(subMaps[j].second,"contigMap");
   int colFamilyCnt = subMaps[j].first;

   // compute the number of global variables
   // and the row and column block offset
   int numGlobalVars = 0;
   int rowBlockOffset = 0;
   int colBlockOffset = 0;
   for(int k=0;k<numVarFamily;k++) {
      numGlobalVars += subMaps[k].first;
 
      // compute block offsets
      if(k<i) rowBlockOffset += subMaps[k].first;
      if(k<j) colBlockOffset += subMaps[k].first;
   }

   // copy all global rows to here
   Epetra_Import import(gRowMap,A.RowMap());
   Epetra_CrsMatrix localA(Copy,gRowMap,0);
   localA.Import(A,import,Insert);

   RCP<Epetra_CrsMatrix> mat = rcp(new Epetra_CrsMatrix(Copy,rowMap,0));

   // get entry information
   int numMyRows = rowMap.NumMyElements();
   int maxNumEntries = A.GlobalMaxNumEntries();

   // for extraction
   std::vector<int> indices(maxNumEntries);
   std::vector<double> values(maxNumEntries);

   // for insertion
   std::vector<int> colIndices(maxNumEntries);
   std::vector<double> colValues(maxNumEntries);

   // insert each row into subblock
   // let FillComplete handle column distribution
   for(int localRow=0;localRow<numMyRows;localRow++) {
      int numEntries = -1; 
      int globalRow = gRowMap.GID(localRow);
      int contigRow = rowMap.GID(localRow);

      TEUCHOS_ASSERT(globalRow>=0);
      TEUCHOS_ASSERT(contigRow>=0);

      // extract a global row copy
      int err = localA.ExtractGlobalRowCopy(globalRow, maxNumEntries, numEntries, &values[0], &indices[0]);
      TEUCHOS_ASSERT(err==0);

      int numOwnedCols = 0;
      for(int localCol=0;localCol<numEntries;localCol++) {
         int globalCol = indices[localCol];

         // determinate which block this column ID is in
         int block = globalCol / numGlobalVars;
         
         bool inFamily = true; 
 
         // test the beginning of the block
         inFamily &= (block*numGlobalVars+colBlockOffset <= globalCol);
         inFamily &= ((block*numGlobalVars+colBlockOffset+colFamilyCnt) > globalCol);

         // is this column in the variable family
         if(inFamily) {
            int familyOffset = globalCol-(block*numGlobalVars+colBlockOffset);

            colIndices[numOwnedCols] = block*colFamilyCnt + familyOffset;
            colValues[numOwnedCols] = values[localCol];

            numOwnedCols++;
         }
      }

      // insert it into the new matrix
      mat->InsertGlobalValues(contigRow,numOwnedCols,&colValues[0],&colIndices[0]);
   }

   // fill it and automagically optimize the storage
   mat->FillComplete(colMap,rowMap);

   return mat;
}
Пример #17
0
int main(int argc, char *argv[]) 
{

  using std::cout;
  using std::endl;

  bool boolret;
  int MyPID;

#ifdef HAVE_MPI
  // Initialize MPI
  MPI_Init(&argc,&argv);
  Epetra_MpiComm Comm(MPI_COMM_WORLD);
#else
  Epetra_SerialComm Comm;
#endif
  MyPID = Comm.MyPID();

  bool testFailed = false;
  bool verbose = false;
  bool debug = false;
  bool shortrun = false;
  bool skinny = true;
  bool useSA = false;
  std::string which("SR");
  int numElements = 100;
  std::string prec("none");
  int user_verbosity = 0;
  int numicgs = 2;

  bool success = true;
  try {

    CommandLineProcessor cmdp(false,true);
    cmdp.setOption("verbose","quiet",&verbose,"Print messages and results.");
    cmdp.setOption("debug","nodebug",&debug,"Print debugging information.");
    cmdp.setOption("sort",&which,"Targetted eigenvalues (SR or LR).");
    cmdp.setOption("shortrun","longrun",&shortrun,"Allow only a small number of iterations.");
    cmdp.setOption("skinny","hefty",&skinny,"Use a skinny (low-mem) or hefty (higher-mem) implementation of IRTR.");
    cmdp.setOption("numElements",&numElements,"Number of elements in discretization.");
    cmdp.setOption("prec",&prec,"Preconditioning type (""none"", ""olsen"", ""simple""");
    cmdp.setOption("useSA","noSA",&useSA,"Use subspace acceleration.");
    cmdp.setOption("verbosity",&user_verbosity,"Additional verbosity falgs.");
    cmdp.setOption("numICGS",&numicgs,"Num ICGS iterations");
    if (cmdp.parse(argc,argv) != CommandLineProcessor::PARSE_SUCCESSFUL) {
#ifdef HAVE_MPI
      MPI_Finalize();
#endif
      return -1;
    }
    if (debug) verbose = true;
    if (prec != "olsen" && prec != "simple") {
      prec = "none";
    }

    typedef double ScalarType;
    typedef ScalarTraits<ScalarType>                   SCT;
    typedef SCT::magnitudeType               MagnitudeType;
    typedef Epetra_MultiVector                          MV;
    typedef Epetra_Operator                             OP;
    typedef Anasazi::MultiVecTraits<ScalarType,MV>     MVT;
    typedef Anasazi::OperatorTraits<ScalarType,MV,OP>  OPT;
    const ScalarType ONE  = SCT::one();

    if (verbose && MyPID == 0) {
      cout << Anasazi::Anasazi_Version() << endl << endl;
    }

    //  Problem information
    int space_dim = 1;
    std::vector<double> brick_dim( space_dim );
    brick_dim[0] = 1.0;
    std::vector<int> elements( space_dim );
    elements[0] = numElements;

    // Create problem
    RCP<ModalProblem> testCase = rcp( new ModeLaplace1DQ1(Comm, brick_dim[0], elements[0]) );
    //
    // Get the stiffness and mass matrices
    RCP<const Epetra_CrsMatrix> K = rcp( const_cast<Epetra_CrsMatrix *>(testCase->getStiffness()), false );
    RCP<const Epetra_CrsMatrix> M = rcp( const_cast<Epetra_CrsMatrix *>(testCase->getMass()), false );
    RCP<const Epetra_CrsMatrix> P;
    if (prec != "none") {
      // construct a diagonal preconditioner
      Epetra_Vector D(K->RowMap(),false);
      K->ExtractDiagonalCopy(D);
      for (int i=0; i<D.MyLength(); ++i) {
        D[i] = 1.0 / D[i];
      }
      RCP<Epetra_CrsMatrix> ncP = rcp( new Epetra_CrsMatrix(Epetra_DataAccess::Copy,K->RowMap(),K->RowMap(),1,true) );
      for (int i=0; i<D.MyLength(); ++i) {
        ncP->InsertMyValues(i,1,&D[i],&i);
      }
      ncP->FillComplete(true);
      P = ncP;
    }
    //
    // Create the initial vectors
    int blockSize = 5;
    RCP<Epetra_MultiVector> ivec = rcp( new Epetra_MultiVector(K->OperatorDomainMap(), blockSize) );
    ivec->Random();

    // Create eigenproblem
    const int nev = 5;
    RCP<Anasazi::BasicEigenproblem<ScalarType,MV,OP> > problem =
      rcp( new Anasazi::BasicEigenproblem<ScalarType,MV,OP>(K,M,ivec) );
    //
    // Inform the eigenproblem that the operator K is symmetric
    problem->setHermitian(true);
    //
    // Set the number of eigenvalues requested
    problem->setNEV( nev );
    //
    // Set the preconditioner, if using one. Also, indicates the type.
    if (prec != "none") {
      problem->setPrec(P);
    }
    //
    // Inform the eigenproblem that you are done passing it information
    boolret = problem->setProblem();
    if (boolret != true) {
      if (verbose && MyPID == 0) {
        cout << "Anasazi::BasicEigenproblem::SetProblem() returned with error." << endl
          << "End Result: TEST FAILED" << endl;	
      }
#ifdef HAVE_MPI
      MPI_Finalize() ;
#endif
      return -1;
    }


    // Set verbosity level
    int verbosity = Anasazi::Errors + Anasazi::Warnings;
    if (verbose) {
      verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails;
    }
    if (debug) {
      verbosity += Anasazi::Debug;
    }
    verbosity |= user_verbosity;


    // Eigensolver parameters
    int maxIters;
    if (shortrun) {
      maxIters = 50;
    }
    else {
      maxIters = 450;
    }
    MagnitudeType tol = 1.0e-6;
    //
    // Create parameter list to pass into the solver manager
    ParameterList MyPL;
    MyPL.set( "Skinny Solver", skinny);
    MyPL.set( "Verbosity", verbosity );
    MyPL.set( "Which", which );
    MyPL.set( "Block Size", blockSize );
    MyPL.set( "Maximum Iterations", maxIters );
    MyPL.set( "Convergence Tolerance", tol );
    MyPL.set( "Use SA", useSA );
    MyPL.set( "Num ICGS", numicgs );
    if (prec == "olsen") {
      MyPL.set( "Olsen Prec", true );
    }
    else if (prec == "simple") {
      MyPL.set( "Olsen Prec", false );
    }
    //
    // Create the solver manager
    Anasazi::RTRSolMgr<ScalarType,MV,OP> MySolverMan(problem, MyPL);

    // Solve the problem to the specified tolerances or length
    Anasazi::ReturnType returnCode = MySolverMan.solve();
    testFailed = false;
    if (returnCode != Anasazi::Converged) {
      if (shortrun==false) {
        testFailed = true;
      }
    }

    /*
    // 
    // Check that the parameters were all consumed
    if (MyPL.getEntryPtr("Verbosity")->isUsed() == false ||
        MyPL.getEntryPtr("Which")->isUsed() == false ||
        MyPL.getEntryPtr("Skinny Solver")->isUsed() == false ||
        MyPL.getEntryPtr("Block Size")->isUsed() == false ||
        MyPL.getEntryPtr("Maximum Iterations")->isUsed() == false ||
        MyPL.getEntryPtr("Convergence Tolerance")->isUsed() == false) {
      if (verbose && MyPID==0) {
        cout << "Failure! Unused parameters: " << endl;
        MyPL.unused(cout);
      }
    }
    */

    // Get the eigenvalues and eigenvectors from the eigenproblem
    Anasazi::Eigensolution<ScalarType,MV> sol = problem->getSolution();
    std::vector<Anasazi::Value<ScalarType> > evals = sol.Evals;
    RCP<MV> evecs = sol.Evecs;
    int numev = sol.numVecs;

    if (numev > 0) {

      std::ostringstream os;
      os.setf(std::ios::scientific, std::ios::floatfield);
      os.precision(6);

      // Check the problem against the analytical solutions
      if (verbose) {
        double *revals = new double[numev];
        for (int i=0; i<numev; i++) {
          revals[i] = evals[i].realpart;
        }
        bool smallest = false;
        if (which == "SR") {
          smallest = true;
        }
        testCase->eigenCheck( *evecs, revals, 0, smallest );
        delete [] revals;
      }

      // Compute the direct residual
      std::vector<ScalarType> normV( numev );
      SerialDenseMatrix<int,ScalarType> T(numev,numev);
      for (int i=0; i<numev; i++) {
        T(i,i) = evals[i].realpart;
      }
      RCP<MV> Mvecs = MVT::Clone( *evecs, numev ),
        Kvecs = MVT::Clone( *evecs, numev );
      OPT::Apply( *K, *evecs, *Kvecs );
      OPT::Apply( *M, *evecs, *Mvecs );
      MVT::MvTimesMatAddMv( -ONE, *Mvecs, T, ONE, *Kvecs );
      // compute M-norm of residuals
      OPT::Apply( *M, *Kvecs, *Mvecs );
      MVT::MvDot( *Mvecs, *Kvecs, normV );

      os << "Number of iterations performed in RTR_test.exe: " << MySolverMan.getNumIters() << endl
        << "Direct residual norms computed in RTR_test.exe" << endl
        << std::setw(20) << "Eigenvalue" << std::setw(20) << "Residual(M)" << endl
        << "----------------------------------------" << endl;
      for (int i=0; i<numev; i++) {
        if ( SCT::magnitude(evals[i].realpart) != SCT::zero() ) {
          normV[i] = SCT::magnitude( SCT::squareroot( normV[i] ) / evals[i].realpart );
        }
        else {
          normV[i] = SCT::magnitude( SCT::squareroot( normV[i] ) );
        }
        os << std::setw(20) << evals[i].realpart << std::setw(20) << normV[i] << endl;
        if ( normV[i] > tol ) {
          testFailed = true;
        }
      }
      if (verbose && MyPID==0) {
        cout << endl << os.str() << endl;
      }

    }
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,cout,success);

#ifdef HAVE_MPI
  MPI_Finalize() ;
#endif

  if (testFailed || success==false) {
    if (verbose && MyPID==0) {
      cout << "End Result: TEST FAILED" << endl;	
    }
    return -1;
  }
  //
  // Default return value
  //
  if (verbose && MyPID==0) {
    cout << "End Result: TEST PASSED" << endl;
  }
  return 0;

}
Пример #18
0
int main(int argc, char *argv[]) {

  using Teuchos::RCP; // reference count pointers
  using Teuchos::rcp; //

  //
  // MPI initialization using Teuchos
  //

#ifdef HAVE_MPI
  MPI_Init(&argc, &argv);
  Epetra_MpiComm comm(MPI_COMM_WORLD);
#else
  Epetra_SerialComm comm;
#endif

  //
  // Parameters
  //

  GlobalOrdinal numGlobalElements = 256; // problem size

  //
  // Construct the problem
  //

  // Construct a Map that puts approximately the same number of equations on each processor
  const Epetra_Map map(numGlobalElements, 0, comm);

  // Get update list and number of local equations from newly created map.
  const size_t         numMyElements    = map.NumMyElements();
  const GlobalOrdinal* myGlobalElements = map.MyGlobalElements();

  // Create a CrsMatrix using the map, with a dynamic allocation of 3 entries per row
  RCP<Epetra_CrsMatrix> A = rcp(new Epetra_CrsMatrix(Copy, map, 3));

  // Add rows one-at-a-time
  for (size_t i = 0; i < numMyElements; i++) {
    if (myGlobalElements[i] == 0) {

      //TODO: should be rewritten in an Epetra style
      A->InsertGlobalValues(myGlobalElements[i], 2,
                            Teuchos::tuple<Scalar> (2.0, -1.0).getRawPtr(),
                            Teuchos::tuple<GlobalOrdinal>(myGlobalElements[i], myGlobalElements[i] +1).getRawPtr());

    }
    else if (myGlobalElements[i] == numGlobalElements - 1) {
      A->InsertGlobalValues(myGlobalElements[i], 2,
                            Teuchos::tuple<Scalar> (-1.0, 2.0).getRawPtr(),
                            Teuchos::tuple<GlobalOrdinal>(myGlobalElements[i] -1, myGlobalElements[i]).getRawPtr());
    }
    else {
      A->InsertGlobalValues(myGlobalElements[i], 3,
                            Teuchos::tuple<Scalar> (-1.0, 2.0, -1.0).getRawPtr(),
                            Teuchos::tuple<GlobalOrdinal>(myGlobalElements[i] -1, myGlobalElements[i], myGlobalElements[i] +1).getRawPtr());
    }
  }

  // Complete the fill, ask that storage be reallocated and optimized
  A->FillComplete();

  //
  // Construct a multigrid preconditioner
  //

  // Turns a Epetra_CrsMatrix into a MueLu::Matrix
  RCP<Xpetra::CrsMatrix<SC, LO, GO, NO, LMO> > mueluA_ = rcp(new Xpetra::EpetraCrsMatrix(A)); //TODO: should not be needed
  RCP<Xpetra::Matrix <SC, LO, GO, NO, LMO> > mueluA  = rcp(new Xpetra::CrsMatrixWrap<SC, LO, GO, NO, LMO>(mueluA_));

  // Multigrid Hierarchy
  RCP<Hierarchy> H = rcp(new Hierarchy(mueluA));
  H->setVerbLevel(Teuchos::VERB_HIGH);

  // Multigrid setup phase (using default parameters)
  H->Setup();

  //
  // Define RHS / LHS
  //

  RCP<Epetra_Vector> X = rcp(new Epetra_Vector(map));
  RCP<Epetra_Vector> B = rcp(new Epetra_Vector(map));

  X->PutScalar((Scalar) 0.0);
  B->SetSeed(846930886); B->Random();

#ifndef HAVE_MUELU_BELOS

  //
  // Use AMG directly as an iterative solver (not as a preconditionner)
  //

  int nIts = 9;

  // Wrap Epetra Vectors into Xpetra Vectors
  RCP<Vector> mueluX = rcp(new Xpetra::EpetraVector(X));
  RCP<Vector> mueluB = rcp(new Xpetra::EpetraVector(B));

  H->Iterate(*mueluB, nIts, *mueluX);

  // Print relative residual norm
  ST::magnitudeType residualNorms = Utils::ResidualNorm(*mueluA, *mueluX, *mueluB)[0];
  if (comm.MyPID() == 0)
    std::cout << "||Residual|| = " << residualNorms << std::endl;

#else // HAVE_MUELU_BELOS

  //
  // Solve Ax = b using AMG as a preconditioner in Belos
  //

  // Matrix and Multivector type that will be used with Belos
  typedef Epetra_MultiVector   MV;
  typedef Belos::OperatorT<MV> OP;

  // Define Operator and Preconditioner
  RCP<OP> belosOp   = rcp(new Belos::XpetraOp<SC, LO, GO, NO, LMO>(mueluA)); // Turns a Xpetra::Matrix object into a Belos operator
  RCP<OP> belosPrec = rcp(new Belos::MueLuOp<SC, LO, GO, NO, LMO>(H));       // Turns a MueLu::Hierarchy object into a Belos operator

  // Construct a Belos LinearProblem object
  RCP< Belos::LinearProblem<SC, MV, OP> > belosProblem = rcp(new Belos::LinearProblem<SC, MV, OP>(belosOp, X, B));
  belosProblem->setLeftPrec(belosPrec);

  bool set = belosProblem->setProblem();
  if (set == false) {
    std::cout << std::endl << "ERROR:  Belos::LinearProblem failed to set up correctly!" << std::endl;
    return EXIT_FAILURE;
  }

  // Belos parameter list
  int maxIts = 20;
  double tol = 1e-4;
  Teuchos::ParameterList belosList;
  belosList.set("Maximum Iterations",    maxIts); // Maximum number of iterations allowed
  belosList.set("Convergence Tolerance", tol);    // Relative convergence tolerance requested
  belosList.set("Verbosity", Belos::Errors + Belos::Warnings + Belos::TimingDetails + Belos::StatusTestDetails);

  // Create an iterative solver manager
  RCP< Belos::SolverManager<SC, MV, OP> > solver = rcp(new Belos::BlockCGSolMgr<SC, MV, OP>(belosProblem, rcp(&belosList, false)));

  // Perform solve
  Belos::ReturnType ret = solver->solve();

  // Get the number of iterations for this solve.
  std::cout << "Number of iterations performed for this solve: " << solver->getNumIters() << std::endl;

  // Compute actual residuals.
  int numrhs=1;
  bool badRes = false;
  std::vector<SC> actual_resids(numrhs);
  std::vector<SC> rhs_norm(numrhs);
  RCP<Epetra_MultiVector > resid = rcp(new Epetra_MultiVector(map, numrhs));

  typedef Belos::OperatorTraits<SC, MV, OP> OPT;
  typedef Belos::MultiVecTraits<SC, MV>     MVT;

  OPT::Apply(*belosOp, *X, *resid);
  MVT::MvAddMv(-1.0, *resid, 1.0, *B, *resid);
  MVT::MvNorm(*resid, actual_resids);
  MVT::MvNorm(*B, rhs_norm);
  std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl;
  for (int i = 0; i < numrhs; i++) {
    SC actRes = actual_resids[i]/rhs_norm[i];
    std::cout <<"Problem " << i << " : \t" << actRes <<std::endl;
    if (actRes > tol) { badRes = true; }
  }

  // Check convergence
  if (ret != Belos::Converged || badRes) {
    std::cout << std::endl << "ERROR:  Belos did not converge! " << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << std::endl << "SUCCESS:  Belos converged!" << std::endl;

#endif // HAVE_MUELU_BELOS


#ifdef HAVE_MPI
  MPI_Finalize();
#endif

  return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
#ifdef HAVE_MPI
  MPI_Init(&argc,&argv);
  Epetra_MpiComm Comm( MPI_COMM_WORLD );
#else
  Epetra_SerialComm Comm;
#endif
  // My MPI process rank.                                                                                                                                                                  
  const int MyPID = Comm.MyPID();

  // "/Users/sakashitatatsuya/Downloads/barista_trunk_slepc/sample/hamiltonian_matrix.ip"
  std::ifstream  ifs(argv[1]);
  alps::Parameters params(ifs);
  Teuchos::oblackholestream blackHole;
  std::ostream& out = (MyPID == 0) ? std::cout : blackHole;

  barista::Hamiltonian<> hamiltonian(params);
  matrix_type matrix(hamiltonian.dimension(), hamiltonian.dimension());
  hamiltonian.fill<double>(matrix);
  int m,n;
  int N;
  m = n = N = hamiltonian.dimension();
  //std::cout << matrix << std::endl;

  std::ofstream ofs;
  if (MyPID==0) {
    ofs.open("anasazi_time.txt");
    if (!ofs) {
#ifdef HAVE_MPI
      MPI_Finalize() ;
#endif
      return -1;
    }
  }

  //Teuchos::ParameterList GaleriList;
  using Teuchos::RCP;
  using Teuchos::rcp;
  typedef Teuchos::ScalarTraits<double> STS;

  const double one = STS::one();
  const double zero = STS::zero();

  // The problem is defined on a 2D grid, global size is nx * nx.
  //int nx = N; 
  //GaleriList.set("n", nx * nx);
  //GaleriList.set("nx", nx);
  //GaleriList.set("ny", nx);
  //Teuchos::RCP<Epetra_Map> Map = Teuchos::rcp( Galeri::CreateMap("Linear", Comm, GaleriList) );
  //Teuchos::RCP<Epetra_RowMatrix> A = Teuchos::rcp( Galeri::CreateCrsMatrix("Laplace2D", &*Map, GaleriList) );

  // Construct a Map that puts approximately the same number of rows
  // of the matrix A on each processor.
  Epetra_Map RowMap (N, 0, Comm);
  Epetra_Map ColMap (N, 0, Comm);
  // Get update list and number of local equations from newly created Map.
  const int NumMyRowElements = RowMap.NumMyElements ();
  std::vector<int> MyGlobalRowElements (NumMyRowElements);
  RowMap.MyGlobalElements (&MyGlobalRowElements[0]);


  // Create an Epetra_CrsMatrix using the given row map.                                                                                                                                   
  RCP<Epetra_CrsMatrix> A = rcp (new Epetra_CrsMatrix (Copy, RowMap, n));

  // We use info to catch any errors that may have happened during                                                                                                                           // matrix assembly, and report them globally.  We do this so that                                                                                                                          // the MPI processes won't call FillComplete() unless they all                                                                                                                             // successfully filled their parts of the matrix.                                                                                                                                         
  int info = 0;
  try {
    //                                                                                                                                                                                     
    // Compute coefficients for the discrete integral operator.                                                                                                                           
    //                                                                                                                                                                                      
    std::vector<double> Values (n);
    std::vector<int> Indices (n);
    //const double inv_mp1 = one / (m+1);
    //const double inv_np1 = one / (n+1);
    int count;
    //for (int i = 0; i < n; ++i) {
    //  Indices[i] = i;
    //}
    for (int i = 0; i < NumMyRowElements; ++i) {
      count =0;
      for (int j = 0; j < n; ++j) {
	if (matrix(MyGlobalRowElements[i],j)!=0) {
	  Values[count] = matrix(MyGlobalRowElements[i],j);
	  Indices[count] = j;
	  count++;
	}
      }

      info = A->InsertGlobalValues (MyGlobalRowElements[i], count,
                                    &Values[0], &Indices[0]);
      // Make sure that the insertion succeeded.  Teuchos'                                                                                                                                 
      // TEST_FOR_EXCEPTION macro gives a nice error message if the                                                                                                                        
      // thrown exception isn't caught.  We'll report this on the                                                                                                                          
      // offending MPI process.                                                                                                                                                             
      /*                                                                                                                     
      TEST_FOR_EXCEPTION( info != 0, std::runtime_error, "Failed to insert n="                                                                                                             
      << n << " global value" << (n != 1 ? "s" : "")                                                                                                                    
      << " in row " << MyGlobalRowElements[i]                                                                                                                           
      << " of the matrix." );                                                                                                                                           
      */
    } // for i = 0...                                                                                                                                                                       
    // Call FillComplete on the matrix.  Since the matrix isn't square,                                                                                                                    
    // we have to give FillComplete the domain and range maps, which in                                                                                                                    
    // this case are the column resp. row maps.                                                                                                                                             
    info = A->FillComplete (ColMap, RowMap);
    /*                                                                                                                                                                                     
    TEST_FOR_EXCEPTION( info != 0, std::runtime_error,                                                                                                                                     
    "FillComplete failed with INFO = " << info << ".");                                                                                                                 
    */
    info = A->OptimizeStorage();
    /*                                                                                                                                                                                     
    TEST_FOR_EXCEPTION( info != 0, std::runtime_error,                                                                                                                                
    "OptimizeStorage failed with INFO = " << info << ".");                                                                                                              
    */
  } catch (std::runtime_error& e) {
    // If multiple MPI processes are reporting errors, sometimes                                                                                                                           
    // forming the error message as a string and then writing it to                                                                                                                        
    // the output stream prevents messages from different processes                                                                                                                        
    // from being interleaved.                                                                                                                                                              
    std::ostringstream os;
    os << "*** Error on MPI process " << MyPID << ": " << e.what();
    cerr << os.str() << endl;
    if (info == 0)
      info = -1; // All procs will share info later on.                                                                                                                                     
  }

  //  Variables used for the Block Davidson Method
  const int    nev         = 5;
  const int    blockSize   = 5;
  const int    numBlocks   = 8;
  const int    maxRestarts = 500;
  const double tol         = 1.0e-8;

  typedef Epetra_MultiVector MV;
  typedef Epetra_Operator OP;
  typedef Anasazi::MultiVecTraits<double, Epetra_MultiVector> MVT;

  // Create an Epetra_MultiVector for an initial vector to start the solver.
  // Note:  This needs to have the same number of columns as the blocksize.
  //
  //Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(*Map, blockSize) );
  Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(ColMap, blockSize) );
  ivec->Random();

  // Create the eigenproblem.
  Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > problem =
    Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(A, ivec) );

  // Inform the eigenproblem that the operator A is symmetric
  problem->setHermitian(true);

  // Set the number of eigenvalues requested
  problem->setNEV( nev );

  // Inform the eigenproblem that you are finishing passing it information
  bool boolret = problem->setProblem();
  if (boolret != true) {
    std::cout<<"Anasazi::BasicEigenproblem::setProblem() returned an error." << std::endl;
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    return -1;
  }

  // Create parameter list to pass into the solver manager
  Teuchos::ParameterList anasaziPL;
  anasaziPL.set( "Which", "LM" );
  anasaziPL.set( "Block Size", blockSize );
  anasaziPL.set( "Maximum Iterations", 500 );
  anasaziPL.set( "Convergence Tolerance", tol );
  anasaziPL.set( "Verbosity", Anasazi::Errors+Anasazi::Warnings+Anasazi::TimingDetails+Anasazi::FinalSummary );

  // Create the solver manager
  Anasazi::LOBPCGSolMgr<double, MV, OP> anasaziSolver(problem, anasaziPL);

  // Solve the problem
  double start, end;
  MPI_Barrier(MPI_COMM_WORLD);
  start = MPI_Wtime();
  Anasazi::ReturnType returnCode = anasaziSolver.solve();
  MPI_Barrier(MPI_COMM_WORLD);
  end = MPI_Wtime();

  // Get the eigenvalues and eigenvectors from the eigenproblem
  Anasazi::Eigensolution<double,MV> sol = problem->getSolution();
  std::vector<Anasazi::Value<double> > evals = sol.Evals;
  Teuchos::RCP<MV> evecs = sol.Evecs;

  // Compute residuals.
  std::vector<double> normR(sol.numVecs);
  Teuchos::SerialDenseMatrix<int,double> T(sol.numVecs, sol.numVecs);
  Epetra_MultiVector tempAevec( ColMap, sol.numVecs );
  T.putScalar(0.0); 
  for (int i=0; i<sol.numVecs; i++) {
    T(i,i) = evals[i].realpart;
  }
  A->Apply( *evecs, tempAevec );
  MVT::MvTimesMatAddMv( -1.0, *evecs, T, 1.0, tempAevec );
  MVT::MvNorm( tempAevec, normR );

  if (MyPID == 0) {
  // Print the results
  std::cout<<"Solver manager returned " << (returnCode == Anasazi::Converged ? "converged." : "unconverged.") << std::endl;
  std::cout<<std::endl;
  std::cout<<"------------------------------------------------------"<<std::endl;
  std::cout<<std::setw(16)<<"Eigenvalue"
           <<std::setw(18)<<"Direct Residual"
           <<std::endl;
  std::cout<<"------------------------------------------------------"<<std::endl;
  for (int i=0; i<sol.numVecs; i++) {
    std::cout<<std::setw(16)<<evals[i].realpart
             <<std::setw(18)<<normR[i]/evals[i].realpart
             <<std::endl;
  }
  std::cout<<"------------------------------------------------------"<<std::endl;
  }

  // Print out the map and matrices
  //ColMap.Print (out);

  //A->Print (cout);
  //RowMap.Print (cout);

  double time;
  int iter;
  if (MyPID==0) {
    iter = anasaziSolver.getNumIters();
    Teuchos::Array<Teuchos::RCP<Teuchos::Time> > timer = anasaziSolver.getTimers();
    Teuchos::RCP<Teuchos::Time> _timerSolve = timer[0];
    cout << "timerSolve=" << _timerSolve << endl;
    time = end - start;
    cout << "time=" << time << endl;
    ofs << "time=" << time << endl;
    cout << "iter=" << iter << endl;
    ofs << "iter=" << iter << endl;
  }

#ifdef HAVE_MPI
  MPI_Finalize() ; 
#endif

  return 0;
}
void tJacobi2x2PreconditionerFactory::initializeTest()
{
   std::vector<int> indicies(2);
   std::vector<double> row0(2),row1(2);

   tolerance_ = 1.0e-14;

   comm = rcp(new Epetra_SerialComm());
   const RCP<Epetra_Map> map = rcp(new Epetra_Map(2,0,*comm));

   const RCP<Epetra_CrsMatrix> ptrF  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrG  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrD  = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrC  = rcp(new Epetra_CrsMatrix(Copy,*map,2));

   const RCP<Epetra_CrsMatrix> ptrInvF = rcp(new Epetra_CrsMatrix(Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrInvC = rcp(new Epetra_CrsMatrix(Copy,*map,2));

   indicies[0] = 0;
   indicies[1] = 1;

   // build F matrix
   row0[0] = 1.0; row0[1] = 2.0; 
   row1[0] = 2.0; row1[1] = 1.0; 
   ptrF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrF->FillComplete();
   F_ = Thyra::epetraLinearOp(ptrF,"ptrF");
   
   // build D matrix
   row0[0] =  1.0; row0[1] = -3.0; 
   row1[0] = -1.0; row1[1] =  1.0; 
   ptrD->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrD->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrD->FillComplete();
   D_ = Thyra::epetraLinearOp(ptrD,"ptrD");
   
   // build G matrix
   row0[0] =  1.0; row0[1] = -1.0; 
   row1[0] = -3.0; row1[1] =  1.0; 
   ptrG->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrG->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrG->FillComplete();
   G_ = Thyra::epetraLinearOp(ptrG,"ptrG");

   // build C matrix
   row0[0] =  9.0; row0[1] =  2.0; 
   row1[0] =  6.0; row1[1] =  5.0; 
   ptrC->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrC->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrC->FillComplete();
   C_ = Thyra::epetraLinearOp(ptrC,"ptrC");

   // build inv(F) matrix
   row0[0] = -1.0/3.0; row0[1] =  2.0/3.0;
   row1[0] =  2.0/3.0; row1[1] = -1.0/3.0;
   ptrInvF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvF->FillComplete();
   invF_ = Thyra::epetraLinearOp(ptrInvF,"ptrInvF");

   // build inv(C) matrix
   row0[0] =  0.151515151515151; row0[1] = -0.060606060606061;
   row1[0] = -0.181818181818182; row1[1] =  0.272727272727273;
   ptrInvC->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvC->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvC->FillComplete();
   invC_ = Thyra::epetraLinearOp(ptrInvC,"ptrInvC");

   A_ = Thyra::block2x2<double>(F_,G_,D_,C_,"A");
}
Пример #21
0
Teuchos::Array<double>
test_original_matrix_free_epetra(
  const Teuchos::Array<int> & var_degree ,
  const int nGrid ,
  const int iterCount ,
  const bool print_flag ,
  const bool test_block ,
  const bool check )
{
  typedef double value_type ;
  typedef Stokhos::OneDOrthogPolyBasis<int,value_type> abstract_basis_type;
  typedef Stokhos::LegendreBasis<int,value_type> basis_type;
  typedef Stokhos::CompletePolynomialBasis<int,value_type> product_basis_type;
  typedef Stokhos::Sparse3Tensor<int,value_type> Cijk_type;

  using Teuchos::rcp;
  using Teuchos::RCP;
  using Teuchos::Array;
  using Teuchos::ParameterList;

   // Create a communicator for Epetra objects
  RCP<const Epetra_Comm> globalComm;
#ifdef HAVE_MPI
  RCP<const Epetra_MpiComm> globalMpiComm = 
    rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
  //globalMpiComm->Print(std::cout);
  globalComm = globalMpiComm;
#else
   RCP<const Epetra_SerialComm> globalSerialComm =
     rcp(new Epetra_SerialComm);
   //globalSerialComm->Print(std::cout);
   globalComm = globalSerialComm;
#endif

  //int MyPID = globalComm->MyPID();

  // Create Stochastic Galerkin basis and expansion
  const size_t num_KL = var_degree.size();
  Array< RCP<const abstract_basis_type> > bases(num_KL); 
  for (size_t i=0; i<num_KL; i++)
    bases[i] = rcp(new basis_type(var_degree[i],true));
  RCP<const product_basis_type> basis = 
    rcp(new product_basis_type(bases, 1e-12));
  const size_t stoch_length = basis->size();
  RCP<Cijk_type> Cijk = basis->computeTripleProductTensor();

  // Create stochastic parallel distribution
  ParameterList parallelParams;
  RCP<Stokhos::ParallelData> sg_parallel_data =
    rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams));
  RCP<const EpetraExt::MultiComm> sg_comm = 
    sg_parallel_data->getMultiComm();
  RCP<const Epetra_Comm> app_comm = 
    sg_parallel_data->getSpatialComm();
  RCP<const Stokhos::EpetraSparse3Tensor> epetraCijk =
    sg_parallel_data->getEpetraCijk();
  RCP<const Epetra_BlockMap> stoch_row_map = 
    epetraCijk->getStochasticRowMap();

  //------------------------------
  // Generate FEM graph:

  Teuchos::Array< Teuchos::Array<int> > fem_graph ;

  const size_t fem_length = nGrid * nGrid * nGrid ;
  generate_fem_graph( nGrid , fem_graph );

  //------------------------------

  // Generate Epetra objects
  RCP<const Epetra_Map> x_map = rcp(new Epetra_Map(static_cast<int>(fem_length), 0, *app_comm));
  RCP<const Epetra_Map> sg_x_map = 
    rcp(EpetraExt::BlockUtility::GenerateBlockMap(
	  *x_map, *stoch_row_map, *sg_comm));

  RCP<Epetra_CrsGraph> graph = rcp(new Epetra_CrsGraph(Copy, *x_map, 27));
  int *my_GIDs = x_map->MyGlobalElements();
  int num_my_GIDs = x_map->NumMyElements();
  for (int i=0; i<num_my_GIDs; ++i) {
    int row = my_GIDs[i];
    int num_indices = fem_graph[row].size();
    int *indices = &(fem_graph[row][0]);
    graph->InsertGlobalIndices(row, num_indices, indices);
  }
  graph->FillComplete();
  int nnz = graph->NumGlobalNonzeros();
  
  RCP<ParameterList> sg_op_params = rcp(new ParameterList);
  RCP<Stokhos::MatrixFreeOperator> sg_A = 
    rcp(new Stokhos::MatrixFreeOperator(sg_comm, basis, epetraCijk, 
					x_map, x_map, sg_x_map, sg_x_map, 
					sg_op_params));
  RCP<Epetra_BlockMap> sg_A_overlap_map =
    rcp(new Epetra_LocalMap(
	  static_cast<int>(stoch_length), 0, *(sg_parallel_data->getStochasticComm())));
  RCP< Stokhos::EpetraOperatorOrthogPoly > A_sg_blocks = 
    rcp(new Stokhos::EpetraOperatorOrthogPoly(
	  basis, sg_A_overlap_map, x_map, x_map, sg_x_map, sg_comm));
  for (unsigned int i=0; i<stoch_length; i++) {
    RCP<Epetra_CrsMatrix> A = rcp(new Epetra_CrsMatrix(Copy, *graph));
    A->FillComplete();
    A->PutScalar(1.0);
    A_sg_blocks->setCoeffPtr(i, A);
  }
  sg_A->setupOperator(A_sg_blocks);

  RCP<Stokhos::EpetraVectorOrthogPoly> sg_x =
    rcp(new Stokhos::EpetraVectorOrthogPoly(
	  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
  RCP<Stokhos::EpetraVectorOrthogPoly> sg_y =
    rcp(new Stokhos::EpetraVectorOrthogPoly(
	  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
  sg_x->init(1.0);
  sg_y->init(0.0);


  // Time apply
  Teuchos::Time clock("apply") ;
  clock.start();
  for ( int iter = 0 ; iter < iterCount ; ++iter ) {
    sg_A->Apply( *(sg_x->getBlockVector()), *(sg_y->getBlockVector()) );
  }
  clock.stop();
  double seconds_per_iter = 
    clock.totalElapsedTime() / ((double) iterCount );

  // Averge time across proc's
  double average_seconds_per_iter;
  globalComm->SumAll(&seconds_per_iter, &average_seconds_per_iter, 1);
  average_seconds_per_iter /= globalComm->NumProc();

  // Compute number of fem mat-vec's
  int n_apply = 0;
  int n_add = 0;
  for (Cijk_type::k_iterator k_it=Cijk->k_begin(); 
       k_it!=Cijk->k_end(); ++k_it) {
    for (Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it); 
	 j_it != Cijk->j_end(k_it); ++j_it) {
      ++n_apply;
      for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it); 
	   i_it != Cijk->i_end(j_it); ++i_it) {
	++n_add;
      }
    }
  }

  const double flops = 1.0e-9*(2.0*static_cast<double>(n_apply)*nnz + 
			       static_cast<double>(n_add)*fem_length);

  //------------------------------

  Teuchos::Array<double> perf(8);
  perf[0] = stoch_length;
  perf[1] = fem_length;
  perf[2] = stoch_length * fem_length;
  perf[3] = Cijk->num_entries();
  perf[4] = nnz;
  perf[5] = average_seconds_per_iter ;
  perf[6] = flops/average_seconds_per_iter;
  perf[7] = flops;

  return perf;
}
void tLSCStablePreconditionerFactory::initializeTest()
{
   std::vector<int> indicies(2);
   std::vector<double> row0(2),row1(2);

   tolerance_ = 1.0e-13;

   comm = rcp(new Epetra_SerialComm());
   const RCP<Epetra_Map> map = rcp(new Epetra_Map(2,0,*comm));

   const RCP<Epetra_CrsMatrix> ptrF  = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrB  = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrBt = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));

   const RCP<Epetra_CrsMatrix> ptrInvF = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrInvS = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));
   const RCP<Epetra_CrsMatrix> ptrInvMass = rcp(new Epetra_CrsMatrix(Epetra_DataAccess::Copy,*map,2));

   indicies[0] = 0;
   indicies[1] = 1;

   // build F matrix
   row0[0] = 1.0; row0[1] = 2.0; 
   row1[0] = 2.0; row1[1] = 1.0; 
   ptrF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrF->FillComplete();
   F_ = Thyra::epetraLinearOp(ptrF,"ptrF");
   
   // build B matrix
   row0[0] =  1.0; row0[1] = -3.0; 
   row1[0] = -1.0; row1[1] =  1.0; 
   ptrB->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrB->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrB->FillComplete();
   B_ = Thyra::epetraLinearOp(ptrB,"ptrB");
   
   // build Bt matrix
   row0[0] =  1.0; row0[1] = -1.0; 
   row1[0] = -3.0; row1[1] =  1.0; 
   ptrBt->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrBt->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrBt->FillComplete();
   Bt_ = Thyra::epetraLinearOp(ptrBt,"ptrBt");

   // build inv(F) matrix
   row0[0] = -1.0/3.0; row0[1] =  2.0/3.0;
   row1[0] =  2.0/3.0; row1[1] = -1.0/3.0;
   ptrInvF->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvF->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvF->FillComplete();
   invF_ = Thyra::epetraLinearOp(ptrInvF,"ptrInvF");

   // build inv(Mass) matrix
   row0[0] =  3.0; row0[1] =  0.0;
   row1[0] =  0.0; row1[1] =  2.0;
   ptrInvMass->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvMass->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvMass->FillComplete();
   invMass_ = Thyra::epetraLinearOp(ptrInvMass,"ptrInvMass");

   // build inv(Pschur) matrix
   row0[0] = 0.208333333333333; row0[1] = 0.375000000000000;
   row1[0] = 0.375000000000000; row1[1] = 0.875000000000000;
   ptrInvS->InsertGlobalValues(0,2,&row0[0],&indicies[0]);
   ptrInvS->InsertGlobalValues(1,2,&row1[0],&indicies[0]);
   ptrInvS->FillComplete();
   invBQBt_ = Thyra::scale<double>(-1.0,Thyra::epetraLinearOp(ptrInvS,"ptrInvS"));

   A_ = Thyra::block2x2<double>(F_,Bt_,B_,Thyra::zero(Bt_->range(),B_->domain()),"A");
}
Пример #23
0
// int
// main(int argc, char * argv[])
TEUCHOS_UNIT_TEST(tALOperator, test)
{
   // Build communicator
#ifdef HAVE_MPI
   Epetra_MpiComm Comm(MPI_COMM_WORLD);
#else
   Epetra_SerialComm Comm;
#endif

   // Get process information
   int myPID = Comm.MyPID();
   out << "MPI_PID = " << myPID << ", UNIX_PID = " << getpid() << std::endl;

   // Maps.
   int dim = 2, numVel = 3, numPre = 2, errCode;
   Epetra_Map mapVel(numVel, 0, Comm), mapPre(numPre, 0, Comm);
   Epetra_Map mapAll(numVel * dim + numPre, 0, Comm);

   // Reorder.
   std::vector<int> reorderedVec;
   int numMyLen = mapVel.NumMyElements();
   int * myGlb;
   myGlb = mapVel.MyGlobalElements();
   for(int i = 0; i < dim; i++)
      for(int j = 0; j < numMyLen; j++)
         reorderedVec.push_back(myGlb[j] + numVel * i);
   numMyLen = mapPre.NumMyElements();
   myGlb = mapPre.MyGlobalElements();
   for(int j = 0; j < numMyLen; j++)
      reorderedVec.push_back(myGlb[j] + numVel * dim);

   Teuchos::RCP < Epetra_Map > mapReorder = Teuchos::rcp(
         new Epetra_Map(-1, reorderedVec.size(), &reorderedVec[0], 0, Comm));
   Teuchos::RCP < Epetra_Import > importReorder = Teuchos::rcp(new Epetra_Import(*mapReorder, mapAll));

   std::vector<std::vector<int> > blockedVec;
   numMyLen = mapVel.NumMyElements();
   myGlb = mapVel.MyGlobalElements();
   for(int i = 0; i < dim; i++)
   {
      reorderedVec.clear();
      for(int j = 0; j < numMyLen; j++)
         reorderedVec.push_back(myGlb[j] + numVel * i);
      blockedVec.push_back(reorderedVec);
   }
   numMyLen = mapPre.NumMyElements();
   myGlb = mapPre.MyGlobalElements();
   reorderedVec.clear();
   for(int j = 0; j < numMyLen; j++)
      reorderedVec.push_back(myGlb[j] + numVel * dim);
   blockedVec.push_back(reorderedVec);

   // Read matrices and vector.
   Epetra_CrsMatrix *ptrMat = 0, *ptrMp = 0;
   TEUCHOS_ASSERT(EpetraExt::MatrixMarketFileToCrsMatrix("data/tOpMat.mm", mapAll, ptrMat)==0);
   TEUCHOS_ASSERT(EpetraExt::MatrixMarketFileToCrsMatrix("data/tOpMp.mm", mapPre, ptrMp)==0);
   LinearOp lpMp = Thyra::epetraLinearOp(Teuchos::rcpFromRef(*ptrMp));
   // This vector is computed by Matlab for comparison.
   Epetra_Vector *ptrExact = 0;
   TEUCHOS_ASSERT(EpetraExt::MatrixMarketFileToVector("data/tOpRhs.mm", mapAll, ptrExact)==0);

   // Reorder matrix.
   RCP < Epetra_CrsMatrix > mat = Teuchos::rcp(new Epetra_CrsMatrix(Copy, *mapReorder, ptrMat->GlobalMaxNumEntries()));
   errCode = mat->Import(*ptrMat, *importReorder, Insert);
   errCode = mat->FillComplete();

   // Build augmented Lagrangian-based operator.
   Teko::NS::ALOperator al(blockedVec, mat, lpMp);

   // Initialize vectors.
   Epetra_Vector x(*mapReorder, false), b(*mapReorder, false);
   x.PutScalar(1.0);
   b.PutScalar(0.0);

   // Apply operator.
   al.Apply(x, b);

   // Compare computed vector and exact vector.
   b.Update(-1.0, *ptrExact, 1.0);
   double norm2;
   b.Norm2(&norm2);
   if(norm2 < 1.0e-15)
   {
      out << "Test:ALOperator: Passed." << std::endl;
      errCode = 0;
   }
   else
   {
      out << "Test:ALOperator: Failed." << std::endl;
      errCode = -1;
   }

   delete ptrMat;
   delete ptrMp;
   delete ptrExact;

   TEST_ASSERT(errCode==0);
}
int main (int argc, char *argv[])
{
  // Initialize MPI
  Teuchos::GlobalMPISession (&argc, &argv, NULL);

  // Create output stream. (Handy for multicore output.)
  const RCP<Teuchos::FancyOStream> out =
    Teuchos::VerboseObjectBase::getDefaultOStream();

  // Create a communicator for Epetra objects
#ifdef HAVE_MPI
  RCP<Epetra_MpiComm> eComm =
    rcp<Epetra_MpiComm> (new Epetra_MpiComm (MPI_COMM_WORLD));
#else
  RCP<Epetra_SerialComm> eComm =
    rcp<Epetra_SerialComm> (new Epetra_SerialComm());
#endif

  bool success = true;
  try {
    // Create map.
    // Do strong scaling tests, so keep numGlobalElements independent of
    // the number of processes.
    int numGlobalElements = 5e7;
    int indexBase = 0;
    RCP<Epetra_Map> map =
      rcp(new Epetra_Map (numGlobalElements, indexBase, *eComm));

    //// Create map with overlay.
    //int numMyOverlapNodes = 3;

    //// Get an approximation of my nodes.
    //int numMyElements = numGlobalElements / eComm->NumProc();
    //int startIndex = eComm->MyPID() * numMyElements;
    //// Calculate the resulting number of total nodes.
    //int numTotalNodes = numMyElements * eComm->NumProc();
    //// Add one node to the first numGlobalElements-numTotalNodes processes.
    //if (eComm->MyPID() < numGlobalElements - numTotalNodes)
    //{
    //    numMyElements++;
    //    startIndex += eComm->MyPID();
    //}
    //else
    //{
    //    startIndex += numGlobalElements - numTotalNodes;
    //}

    //Teuchos::Array<int> indices(numMyElements);
    //for (int k = 0;  k<numMyElements; k++)
    //    indices[k] = startIndex + k;

    //std::cout << numGlobalElements << std::endl;
    //std::cout << numMyElements << std::endl;

    //RCP<Epetra_Map> overlapMap =
    //    rcp(new Epetra_Map (numGlobalElements, numMyElements, indices.getRawPtr(), indexBase, *eComm));

    //overlapMap->Print(std::cout);

    //throw 1;
    // tests on one vector
    RCP<Epetra_Vector> u = rcp(new Epetra_Vector(*map));
    u->Random();

    RCP<Teuchos::Time> meanValueTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::MeanValue");
    {
      Teuchos::TimeMonitor tm(*meanValueTime);
      double meanVal;
      TEUCHOS_ASSERT_EQUALITY(0, u->MeanValue(&meanVal));
    }

    RCP<Teuchos::Time> maxValueTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::MaxValue");
    {
      Teuchos::TimeMonitor tm(*maxValueTime);
      double maxValue;
      TEUCHOS_ASSERT_EQUALITY(0, u->MaxValue(&maxValue));
    }

    RCP<Teuchos::Time> minValueTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::MinValue");
    {
      Teuchos::TimeMonitor tm(*minValueTime);
      double minValue;
      TEUCHOS_ASSERT_EQUALITY(0, u->MinValue(&minValue));
    }

    RCP<Teuchos::Time> norm1Time =
      Teuchos::TimeMonitor::getNewTimer("Vector::Norm1");
    {
      Teuchos::TimeMonitor tm(*norm1Time);
      double norm1;
      TEUCHOS_ASSERT_EQUALITY(0, u->Norm1(&norm1));
    }

    RCP<Teuchos::Time> norm2Time =
      Teuchos::TimeMonitor::getNewTimer("Vector::Norm2");
    {
      Teuchos::TimeMonitor tm(*norm2Time);
      double norm2;
      TEUCHOS_ASSERT_EQUALITY(0, u->Norm2(&norm2));
    }

    RCP<Teuchos::Time> normInfTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::NormInf");
    {
      Teuchos::TimeMonitor tm(*normInfTime);
      double normInf;
      TEUCHOS_ASSERT_EQUALITY(0, u->NormInf(&normInf));
    }

    RCP<Teuchos::Time> scaleTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::Scale");
    {
      Teuchos::TimeMonitor tm(*scaleTime);
      double alpha = 0.5;
      TEUCHOS_ASSERT_EQUALITY(0, u->Scale(0.5));
    }
    // tests involving two vectors
    RCP<Epetra_Vector> v = rcp(new Epetra_Vector(*map));
    v->Random();

    RCP<Teuchos::Time> dotTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::Dot");
    {
      Teuchos::TimeMonitor tm(*dotTime);
      double dot;
      TEUCHOS_ASSERT_EQUALITY(0, u->Dot(*v, &dot));
    }

    RCP<Teuchos::Time> multiplyTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::Multiply");
    {
      Teuchos::TimeMonitor tm(*multiplyTime);
      TEUCHOS_ASSERT_EQUALITY(0, u->Multiply(1.0, *u, *v, 1.0));
    }

    RCP<Teuchos::Time> updateTime =
      Teuchos::TimeMonitor::getNewTimer("Vector::Update");
    {
      Teuchos::TimeMonitor tm(*updateTime);
      TEUCHOS_ASSERT_EQUALITY(0, u->Update(1.0, *v, 1.0));
    }

    // matrix-vector tests
    // diagonal test matrix
    RCP<Epetra_CrsMatrix> D =
      rcp(new Epetra_CrsMatrix(Copy, *map, 1));
    for (int k = 0; k < map->NumMyElements(); k++) {
      int col = map->GID(k);
      double val = 1.0 / (col+1);
      //TEUCHOS_ASSERT_EQUALITY(0, D->InsertMyValues(k, 1, &val, &col));
      TEUCHOS_ASSERT_EQUALITY(0, D->InsertGlobalValues(col, 1, &val, &col));
    }
    TEUCHOS_ASSERT_EQUALITY(0, D->FillComplete());

    // tridiagonal test matrix
    RCP<Epetra_CrsMatrix> T =
      rcp(new Epetra_CrsMatrix(Copy, *map, 3));
    for (int k = 0; k < map->NumMyElements(); k++) {
      int row = map->GID(k);
      if (row > 0) {
        int col = row-1;
        double val = -1.0;
        //TEUCHOS_ASSERT_EQUALITY(0, T->InsertMyValues(k, 1, &val, &col));
        TEUCHOS_ASSERT_EQUALITY(0, T->InsertGlobalValues(row, 1, &val, &col));
      }
      {
        int col = row;
        double val = 2.0;
        //TEUCHOS_ASSERT_EQUALITY(0, T->InsertMyValues(k, 1, &val, &col));
        TEUCHOS_ASSERT_EQUALITY(0, T->InsertGlobalValues(row, 1, &val, &col));
      }
      if (row < numGlobalElements-1) {
        int col = row+1;
        double val = -1.0;
        //TEUCHOS_ASSERT_EQUALITY(0, T->InsertMyValues(k, 1, &val, &col));
        TEUCHOS_ASSERT_EQUALITY(0, T->InsertGlobalValues(row, 1, &val, &col));
      }
    }
    TEUCHOS_ASSERT_EQUALITY(0, T->FillComplete());

    // start timings
    RCP<Teuchos::Time> mNorm1Time =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::Norm1");
    {
      Teuchos::TimeMonitor tm(*mNorm1Time);
      double dNorm1 = D->NormOne();
      double tNorm1 = T->NormOne();
    }

    RCP<Teuchos::Time> mNormInfTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::NormInf");
    {
      Teuchos::TimeMonitor tm(*mNormInfTime);
      double dNormInf = D->NormInf();
      double tNormInf = T->NormInf();
    }

    RCP<Teuchos::Time> mNormFrobTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::NormFrobenius");
    {
      Teuchos::TimeMonitor tm(*mNormFrobTime);
      double dNormFrob = D->NormFrobenius();
      double tNormFrob = T->NormFrobenius();
    }

    RCP<Teuchos::Time> mScaleTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::Scale");
    {
      Teuchos::TimeMonitor tm(*mScaleTime);
      TEUCHOS_ASSERT_EQUALITY(0, D->Scale(2.0));
      TEUCHOS_ASSERT_EQUALITY(0, T->Scale(2.0));
    }

    RCP<Teuchos::Time> leftScaleTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::LeftScale");
    {
      Teuchos::TimeMonitor tm(*leftScaleTime);
      TEUCHOS_ASSERT_EQUALITY(0, D->LeftScale(*v));
      TEUCHOS_ASSERT_EQUALITY(0, T->LeftScale(*v));
    }

    RCP<Teuchos::Time> rightScaleTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::RightScale");
    {
      Teuchos::TimeMonitor tm(*rightScaleTime);
      TEUCHOS_ASSERT_EQUALITY(0, D->RightScale(*v));
      TEUCHOS_ASSERT_EQUALITY(0, T->RightScale(*v));
    }

    RCP<Teuchos::Time> applyTime =
      Teuchos::TimeMonitor::getNewTimer("CrsMatrix::Apply");
    {
      Teuchos::TimeMonitor tm(*applyTime);
      TEUCHOS_ASSERT_EQUALITY(0, D->Apply(*u, *v));
      TEUCHOS_ASSERT_EQUALITY(0, T->Apply(*u, *v));
    }
    // print timing data
    Teuchos::TimeMonitor::summarize();
  }
  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, *out, success);

  return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
Пример #25
0
//
//  Diagonal:  0=no change, 1=eliminate entry
//             from the map for the largest row element in process 0
//             2=add diagonal entries to the matrix, with a zero value 
//             (assume row map contains all diagonal entries). 
//
//  ReindexRowMap:  
//    0=no change, 1= add 2 (still contiguous), 2=non-contiguous
//  
//  ReindexColMap
//    0=same as RowMap, 1=add 4 - Different From RowMap, but contiguous) 
//
//  RangeMap:
//    0=no change, 1=serial map, 2=bizarre distribution, 3=replicated map
//
//  DomainMap:
//    0=no change, 1=serial map, 2=bizarre distribution, 3=replicated map
//
RCP<Epetra_CrsMatrix> NewMatNewMap(Epetra_CrsMatrix& In, 
					   int Diagonal, 
					   int ReindexRowMap,
					   int ReindexColMap,
					   int RangeMapType,
					   int DomainMapType
					   )
{

  //
  //  If we are making no change, return the original matrix (which has a linear map) 
  //
#if 0
  std::cout << __FILE__ << "::" << __LINE__ << " " 
       << Diagonal << " " 
       << ReindexRowMap << " " 
       << ReindexColMap << " " 
       << RangeMapType << " " 
       << DomainMapType << " " << std::endl ; 
#endif

  if ( Diagonal + ReindexRowMap + ReindexColMap + RangeMapType + DomainMapType == 0 ) {
    RCP<Epetra_CrsMatrix> ReturnOrig = rcp( &In, false );
    return ReturnOrig ;
  }

  //
  //  Diagonal==2 is used for a different purpose - 
  //    Making sure that the diagonal of the matrix is non-empty.
  //  Note:  The diagonal must exist in In.RowMap().
  //
  if ( Diagonal == 2 ) { 
    assert( ReindexRowMap==0 && ReindexColMap == 0 ) ; 
  }

  int (*RowPermute)(int in) = 0;
  int (*ColPermute)(int in) = 0;

  assert( Diagonal >= 0  && Diagonal <= 2 ); 
  assert( ReindexRowMap>=0 && ReindexRowMap<=2 );
  assert( ReindexColMap>=0 && ReindexColMap<=1 );
  assert( RangeMapType>=0 && RangeMapType<=3 );
  assert( DomainMapType>=0 && DomainMapType<=3 );

  Epetra_Map DomainMap = In.DomainMap();
  Epetra_Map RangeMap = In.RangeMap();
  Epetra_Map ColMap = In.ColMap();
  Epetra_Map RowMap = In.RowMap();
  int NumMyRowElements = RowMap.NumMyElements();
  int NumMyColElements = ColMap.NumMyElements();
  int NumMyRangeElements = RangeMap.NumMyElements();
  int NumMyDomainElements = DomainMap.NumMyElements();

  int NumGlobalRowElements = RowMap.NumGlobalElements();
  int NumGlobalColElements = ColMap.NumGlobalElements();
  int NumGlobalRangeElements = RangeMap.NumGlobalElements();
  int NumGlobalDomainElements = DomainMap.NumGlobalElements();
  assert( NumGlobalRangeElements == NumGlobalDomainElements ) ; 

  std::vector<int> MyGlobalRowElements( NumMyRowElements ) ; 
  std::vector<int> NumEntriesPerRow( NumMyRowElements ) ; 
  std::vector<int> MyPermutedGlobalRowElements( NumMyRowElements ) ; 
  std::vector<int> MyGlobalColElements( NumMyColElements ) ; 
  std::vector<int> MyPermutedGlobalColElements( NumMyColElements ) ; // Used to create the column map
  std::vector<int> MyPermutedGlobalColElementTable( NumMyColElements ) ; // To convert local indices to global
  std::vector<int> MyGlobalRangeElements( NumMyRangeElements ) ; 
  std::vector<int> MyPermutedGlobalRangeElements( NumMyRangeElements ) ; 
  std::vector<int> MyGlobalDomainElements( NumMyDomainElements ) ; 
  std::vector<int> MyPermutedGlobalDomainElements( NumMyDomainElements ) ; 
  RowMap.MyGlobalElements(&MyGlobalRowElements[0]);
  ColMap.MyGlobalElements(&MyGlobalColElements[0]);
  RangeMap.MyGlobalElements(&MyGlobalRangeElements[0]);
  DomainMap.MyGlobalElements(&MyGlobalDomainElements[0]);

  switch( ReindexRowMap ) {
  case 0:
    RowPermute = &NoPermute ;
    break; 
  case 1:
    RowPermute = &SmallRowPermute ;
    break; 
  case 2:
    RowPermute = BigRowPermute ;
    break; 
  }
  switch( ReindexColMap ) {
  case 0:
    ColPermute = RowPermute ;
    break; 
  case 1:
    ColPermute = &SmallColPermute ;
    break; 
  }

  //
  //  Create Serial Range and Domain Maps based on the permuted indexing
  //
  int nlocal = 0;
  if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements;
  std::vector<int> AllIDs( NumGlobalRangeElements ) ; 
  for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDs[i] = (*RowPermute)( i ) ; 
  Epetra_Map SerialRangeMap( -1, nlocal, &AllIDs[0], 0, In.Comm()); 
  std::vector<int> AllIDBs( NumGlobalRangeElements ) ; 
  for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDBs[i] = (*ColPermute)( i ) ; 
  Epetra_Map SerialDomainMap( -1, nlocal, &AllIDBs[0], 0, In.Comm()); 

  //
  //  Create Bizarre Range and Domain Maps based on the permuted indexing
  //  These are nearly serial, having all but one element on process 0
  //  The goal here is to make sure that we can use Domain and Range maps 
  //  that are neither serial, nor distributed in the normal manner.
  //
  std::vector<int> AllIDCs( NumGlobalRangeElements ) ; 
  for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDCs[i] = (*ColPermute)( i ) ; 
  if ( In.Comm().NumProc() > 1 ) { 
    if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements-1;
    if (In.Comm().MyPID()==1) {
      nlocal = 1;
      AllIDCs[0] = (*ColPermute)( NumGlobalRangeElements - 1 );
    }
  } 
  int iam = In.Comm().MyPID();
  Epetra_Map BizarreDomainMap( -1, nlocal, &AllIDCs[0], 0, In.Comm()); 

  std::vector<int> AllIDDs( NumGlobalRangeElements ) ; 
  for ( int i = 0; i < NumGlobalRangeElements ; i++ ) AllIDDs[i] = (*RowPermute)( i ) ; 
  if ( In.Comm().NumProc() > 1 ) { 
    if (In.Comm().MyPID()==0) nlocal = NumGlobalRangeElements-1;
    if (In.Comm().MyPID()==1) {
      nlocal = 1;
      AllIDDs[0] = (*RowPermute)( NumGlobalRangeElements -1 ) ;
    }
  } 
  Epetra_Map BizarreRangeMap( -1, nlocal, &AllIDDs[0], 0, In.Comm()); 


  //
  //  Compute the column map 
  //
  //  If Diagonal==1, remove the column corresponding to the last row owned 
  //  by process 0.  Removing this column from a tridiagonal matrix, leaves
  //  a disconnected, but non-singular matrix.  
  //
  int NumMyColElementsOut = 0 ; 
  int NumGlobalColElementsOut ; 
  if ( Diagonal == 1 ) 
    NumGlobalColElementsOut = NumGlobalColElements-1; 
  else
    NumGlobalColElementsOut = NumGlobalColElements; 
  if ( Diagonal == 1 && iam==0 ) { 
    for ( int i=0; i < NumMyColElements  ; i++ ) {
      if ( MyGlobalColElements[i] != MyGlobalRowElements[NumMyRowElements-1] ) {
	MyPermutedGlobalColElements[NumMyColElementsOut++] = 
	  (*ColPermute)( MyGlobalColElements[i] ) ; 
      }
    }
    assert( NumMyColElementsOut == NumMyColElements-1 );
  } else {
    for ( int i=0; i < NumMyColElements  ; i++ )  
      MyPermutedGlobalColElements[i] = 
	(*ColPermute)( MyGlobalColElements[i] ) ; 
    NumMyColElementsOut = NumMyColElements ; 
    if ( Diagonal == 2 ) {
      //  For each row, make sure that the column map has this row in it, 
      //    if it doesn't, add it to the column map.  
      //  Note:  MyPermutedGlobalColElements == MyGlobalColElements when 
      //  Diagonal==2 because  ( Diagonal == 2 ) implies:
      //     ReindexRowMap==0 && ReindexColMap == 0  - see assert above
      for ( int i=0; i < NumMyRowElements  ; i++ ) {
	bool MissingDiagonal = true; 
	for ( int j=0; j < NumMyColElements; j++ ) { 
	  if ( MyGlobalRowElements[i] == MyGlobalColElements[j] ) {
	    MissingDiagonal = false; 
	  }
	}
	if ( MissingDiagonal ) {
	  MyPermutedGlobalColElements.resize(NumMyColElements+1);
	  MyPermutedGlobalColElements[NumMyColElementsOut] = MyGlobalRowElements[i];
	  NumMyColElementsOut++;
	}
      }
      In.Comm().SumAll(&NumMyColElementsOut,&NumGlobalColElementsOut,1); 
    }
  }

  //
  //  These tables are used both as the permutation tables and to create the maps.
  //
  for ( int i=0; i < NumMyColElements  ; i++ ) 
    MyPermutedGlobalColElementTable[i] = 
      (*ColPermute)( MyGlobalColElements[i] ) ; 
  for ( int i=0; i < NumMyRowElements  ; i++ ) 
    MyPermutedGlobalRowElements[i] = 
      (*RowPermute)( MyGlobalRowElements[i] ) ; 
  for ( int i=0; i < NumMyRangeElements  ; i++ ) 
    MyPermutedGlobalRangeElements[i] = 
      (*RowPermute)( MyGlobalRangeElements[i] ) ; 
  for ( int i=0; i < NumMyDomainElements  ; i++ ) 
    MyPermutedGlobalDomainElements[i] = 
      (*ColPermute)( MyGlobalDomainElements[i] ) ; 

  RCP<Epetra_Map> PermutedRowMap = 
    rcp( new Epetra_Map( NumGlobalRowElements, NumMyRowElements, 
			 &MyPermutedGlobalRowElements[0], 0, In.Comm() ) ); 
									
  RCP<Epetra_Map> PermutedColMap = 
    rcp( new Epetra_Map( NumGlobalColElementsOut, NumMyColElementsOut, 
			 &MyPermutedGlobalColElements[0], 0, In.Comm() ) ); 
									
  RCP<Epetra_Map> PermutedRangeMap = 
    rcp( new Epetra_Map( NumGlobalRangeElements, NumMyRangeElements, 
			 &MyPermutedGlobalRangeElements[0], 0, In.Comm() ) ); 
									
  RCP<Epetra_Map> PermutedDomainMap = 
    rcp( new Epetra_Map( NumGlobalDomainElements, NumMyDomainElements, 
			 &MyPermutedGlobalDomainElements[0], 0, In.Comm() ) ); 
									
  //
  //  These vectors are filled and then passed to InsertGlobalValues 
  //
  std::vector<int> ThisRowIndices( In.MaxNumEntries() );
  std::vector<double> ThisRowValues( In.MaxNumEntries() );
  std::vector<int> PermutedGlobalColIndices( In.MaxNumEntries() );

  //std::cout << __FILE__ << "::" <<__LINE__ << std::endl ; 
  RCP<Epetra_CrsMatrix> Out = 
    rcp( new Epetra_CrsMatrix( Copy, *PermutedRowMap, *PermutedColMap, 0 ) );

  for (int i=0; i<NumMyRowElements; i++)
    {

      int NumIndicesThisRow = 0;
      assert( In.ExtractMyRowCopy( i, 
				   In.MaxNumEntries(),
				   NumIndicesThisRow,
				   &ThisRowValues[0],
				   &ThisRowIndices[0] ) == 0 ) ;
      for (int j = 0 ; j < NumIndicesThisRow ; j++ )
	{
	  PermutedGlobalColIndices[j] = MyPermutedGlobalColElementTable[ ThisRowIndices[j] ]  ;
	}
      bool MissingDiagonal = false; 
      if ( Diagonal==2 ) { 
	//
	assert( MyGlobalRowElements[i] == MyPermutedGlobalRowElements[i] );
	MissingDiagonal = true; 
	for( int j =0 ; j < NumIndicesThisRow ; j++ ) {
	  if ( PermutedGlobalColIndices[j] == MyPermutedGlobalRowElements[i] ) {
	    MissingDiagonal = false ; 
	  }
	}
#if 0
	std::cout  << __FILE__ << "::" << __LINE__ 
	      << " i = " << i 
	      << " MyPermutedGlobalRowElements[i]  = " << MyPermutedGlobalRowElements[i] 
	      <<   " MissingDiagonal = " << MissingDiagonal << std::endl ; 
#endif

      }
      if ( MissingDiagonal ) { 
	ThisRowValues.resize(NumIndicesThisRow+1) ; 
	ThisRowValues[NumIndicesThisRow] = 0.0;
	PermutedGlobalColIndices.resize(NumIndicesThisRow+1);
	PermutedGlobalColIndices[NumIndicesThisRow] = MyPermutedGlobalRowElements[i] ;
	
#if 0
	std::cout  << __FILE__ << "::" << __LINE__ 
	      << " i = " << i 
	      << "NumIndicesThisRow = " << NumIndicesThisRow 
	      << "ThisRowValues[NumIndicesThisRow = " << ThisRowValues[NumIndicesThisRow] 
	      << " PermutedGlobalColIndices[NumIndcesThisRow] = " << PermutedGlobalColIndices[NumIndicesThisRow] 
	      << std::endl ; 
#endif

	NumIndicesThisRow++  ;

      } 
      assert( Out->InsertGlobalValues( MyPermutedGlobalRowElements[i], 
				       NumIndicesThisRow,
				       &ThisRowValues[0],
				       &PermutedGlobalColIndices[0] ) >= 0 ); 
    }

  //

  Epetra_LocalMap ReplicatedMap( NumGlobalRangeElements, 0, In.Comm() );

  RCP<Epetra_Map> OutRangeMap ;
  RCP<Epetra_Map> OutDomainMap ;
  
  switch( RangeMapType ) {
  case 0:
    OutRangeMap = PermutedRangeMap ;
    break;
  case 1:
    OutRangeMap = rcp(&SerialRangeMap, false); 
    break;
  case 2:
    OutRangeMap = rcp(&BizarreRangeMap, false); 
    break;
  case 3:
    OutRangeMap = rcp(&ReplicatedMap, false); 
    break;
  }
  //  switch( DomainMapType ) {
  switch( DomainMapType ) {
  case 0:
    OutDomainMap = PermutedDomainMap ;
    break;
  case 1:
    OutDomainMap = rcp(&SerialDomainMap, false); 
    break;
  case 2:
    OutDomainMap = rcp(&BizarreDomainMap, false); 
    break;
  case 3:
    OutDomainMap = rcp(&ReplicatedMap, false); 
    break;
  }
#if 0
  assert(Out->FillComplete( *PermutedDomainMap, *PermutedRangeMap )==0);
#else
  assert(Out->FillComplete( *OutDomainMap, *OutRangeMap )==0);
#endif

#if 0
  std::cout << __FILE__ << "::" << __LINE__ << std::endl ;
  Out->Print( std::cout ) ; 
#endif

  return Out;
}