Example #1
0
int main(int argc, char *argv[]) {
#include "MueLu_UseShortNames.hpp"

  Teuchos::oblackholestream blackhole;
  Teuchos::GlobalMPISession mpiSession(&argc,&argv,&blackhole);
  RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm();

  /**********************************************************************************/
  /* SET TEST PARAMETERS                                                            */
  /**********************************************************************************/
  // Note: use --help to list available options.
  Teuchos::CommandLineProcessor clp(false);

  // Default is Laplace1D with nx = 8748.
  // It's a nice size for 1D and perfect aggregation. (6561=3^8)
  //Nice size for 1D and perfect aggregation on small numbers of processors. (8748=4*3^7)
  Galeri::Xpetra::Parameters<GO> matrixParameters(clp, 8748); // manage parameters of the test case
  Xpetra::Parameters xpetraParameters(clp);             // manage parameters of xpetra

  // custom parameters
  int nSmoothers=2;
  LO maxLevels = 3;
  LO its=10;
  std::string coarseSolver="ifpack2";
  // std::string coarseSolver="amesos2";
  int pauseForDebugger=0;
  clp.setOption("nSmoothers",&nSmoothers,"number of Gauss-Seidel smoothers in the MergedSmootehrs");
  clp.setOption("maxLevels",&maxLevels,"maximum number of levels allowed. If 1, then a MergedSmoother is used on the coarse grid");
  clp.setOption("its",&its,"number of multigrid cycles");
  clp.setOption("coarseSolver",&coarseSolver,"amesos2 or ifpack2 (Tpetra specific. Ignored for Epetra)");
  clp.setOption("debug",&pauseForDebugger,"pause to attach debugger");

  switch (clp.parse(argc,argv)) {
    case Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED:        return EXIT_SUCCESS; break;
    case Teuchos::CommandLineProcessor::PARSE_ERROR:
    case Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION: return EXIT_FAILURE; break;
    case Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL:                               break;
  }

  matrixParameters.check();
  xpetraParameters.check();
  // TODO: check custom parameters

  if (comm->getRank() == 0) {
    // matrixParameters.print();
    // xpetraParameters.print();
    // TODO: print custom parameters
  }

  if (pauseForDebugger) {
    Utils::PauseForDebugger();
  }

  /**********************************************************************************/
  /* CREATE INITIAL MATRIX                                                          */
  /**********************************************************************************/
  const RCP<const Map> map = MapFactory::Build(xpetraParameters.GetLib(), matrixParameters.GetNumGlobalElements(), 0, comm);
  RCP<Galeri::Xpetra::Problem<Map,CrsMatrixWrap,MultiVector> > Pr =
      Galeri::Xpetra::BuildProblem<SC,LO,GO,Map,CrsMatrixWrap,MultiVector>(matrixParameters.GetMatrixType(), map, matrixParameters.GetParameterList()); //TODO: Matrix vs. CrsMatrixWrap
  RCP<Matrix> Op = Pr->BuildMatrix();

#ifdef NEUMANN
  // Tranform matrix to Neumann b.c.
  // Essentially, we need to update two diagonal elements

  // TODO: calls to getLocalRowView not really needed

  Op->resumeFill();

  Teuchos::ArrayView<const LO> indices;
  Teuchos::ArrayView<const SC> values;
  Teuchos::Array<SC> newValues(2, 0.0);

  size_t myRank = Op->getRowMap()->getComm()->getRank();
  size_t nCpus  = Op->getRowMap()->getComm()->getSize();
  if (myRank == 0) { // JG TODO: can we use rowMap->isNodeLocalElement(0) instead for more genericity?
    //LO firstRow = 0;
    newValues[0] = 1.0; newValues[1] = -1.0;
    Op->getLocalRowView(0, indices, values);
    Op->replaceLocalValues(0, indices, newValues);
  }
  if (myRank == nCpus-1) { // JG TODO: can we use rowMap->isNodeLocalElement(lastRow) instead for more genericity?
    LO lastRow = Op->getNodeNumRows()-1;
    newValues[0] = -1.0; newValues[1] = 1.0;
    Op->getLocalRowView(lastRow, indices, values);
    Op->replaceLocalValues(lastRow, indices, newValues);
  }

  Op->fillComplete();
#endif // NEUMANN

  /**********************************************************************************/
  /*                                                                                */
  /**********************************************************************************/

  RCP<MultiVector> nullSpace = MultiVectorFactory::Build(map,1);
  nullSpace->putScalar( (SC) 1.0);
  Teuchos::Array<Teuchos::ScalarTraits<SC>::magnitudeType> norms(1);
  nullSpace->norm1(norms);
  if (comm->getRank() == 0)
    std::cout << "||NS|| = " << norms[0] << std::endl;

  RCP<MueLu::Hierarchy<SC,LO,GO,NO,LMO> > H = rcp( new Hierarchy() );
  H->SetDefaultVerbLevel(MueLu::Extreme);
  H->IsPreconditioner(false);

  RCP<MueLu::Level> Finest = H->GetLevel();
  Finest->setDefaultVerbLevel(Teuchos::VERB_HIGH);
  Finest->Set("A", Op);
  Finest->Set("Nullspace", nullSpace);

  FactoryManager M;

  M.SetFactory("Aggregates", rcp(new CoupledAggregationFactory()));
  M.SetFactory("Ptent",      rcp(new TentativePFactory()));
  M.SetFactory("P",          rcp(new SaPFactory()));

#ifdef EMIN
  // Energy-minimization
  RCP<PatternFactory> PatternFact = rcp(new PatternFactory());
#if 0
  PatternFact->SetFactory("P", M.GetFactory("Ptent"));
#else
  PatternFact->SetFactory("P", M.GetFactory("P"));
#endif
  M.SetFactory("Ppattern",   PatternFact);

  RCP<EminPFactory> EminPFact = rcp(new EminPFactory());
  EminPFact->SetFactory("P", M.GetFactory("Ptent"));
  M.SetFactory("P",          EminPFact);

  RCP<NullspacePresmoothFactory> NullPreFact = rcp(new NullspacePresmoothFactory());
  NullPreFact->SetFactory("Nullspace", M.GetFactory("Nullspace"));
  M.SetFactory("Nullspace",  NullPreFact);
#endif

  RCP<SmootherPrototype> smooProto = gimmeMergedSmoother(nSmoothers, xpetraParameters.GetLib(), coarseSolver, comm->getRank());
  M.SetFactory("Smoother",   rcp(new SmootherFactory(smooProto)));

  Teuchos::ParameterList status;

  RCP<SmootherPrototype> coarseProto;
  if (maxLevels != 1)
    coarseProto = gimmeCoarseProto(xpetraParameters.GetLib(), coarseSolver, comm->getRank());
  else
    coarseProto = gimmeMergedSmoother(nSmoothers, xpetraParameters.GetLib(), coarseSolver, comm->getRank());

  if (coarseProto == Teuchos::null)
    return EXIT_FAILURE;

#ifdef NEUMANN
  // Use coarse level projection solver
  RCP<SmootherPrototype> projectedSolver = rcp(new ProjectorSmoother(coarseProto));
  RCP<SmootherFactory> coarseSolveFact   = rcp(new SmootherFactory(projectedSolver));
#else
  RCP<SmootherFactory> coarseSolveFact   = rcp(new SmootherFactory(coarseProto));
#endif
  M.SetFactory("CoarseSolver", coarseSolveFact);

  H->EnableGraphDumping("graph.dot", 2);

  H->Setup(M, 0, maxLevels);
  //if (comm->getRank() == 0) {
  //  std::cout  << "======================\n Multigrid statistics \n======================" << std::endl;
  //  status.print(std::cout,Teuchos::ParameterList::PrintOptions().indent(2));
  //}

  // Define RHS
  RCP<MultiVector> X = MultiVectorFactory::Build(map,1);
  RCP<MultiVector> RHS = MultiVectorFactory::Build(map,1);

  X->setSeed(846930886);
  X->randomize();
  X->norm2(norms);
  if (comm->getRank() == 0)
    std::cout << "||X_true|| = " << std::setiosflags(std::ios::fixed) << std::setprecision(10) << norms[0] << std::endl;


  Op->apply(*X,*RHS,Teuchos::NO_TRANS,(SC)1.0,(SC)0.0);

  // Use AMG directly as an iterative method
  {
    X->putScalar( (SC) 0.0);

    H->Iterate(*RHS,its,*X);

    X->norm2(norms);
    if (comm->getRank() == 0)
      std::cout << "||X_" << std::setprecision(2) << its << "|| = " << std::setiosflags(std::ios::fixed) << std::setprecision(10) << norms[0] << std::endl;
  }

  return EXIT_SUCCESS;

}