Example #1
0
void run(const UserInputForTests &uinput,
         const ParameterList &problem_parameters,
         RCP<ComparisonHelper> & comparison_helper,
         const RCP<const Teuchos::Comm<int> > & comm)
{
  // Major steps in running a problem in zoltan 2
  // 1. get an input adapter
  // 2. construct the problem
  // 3. solve the problem
  // 4. analyze metrics
  // 5. clean up

  int rank = comm->getRank();
  
  if(!problem_parameters.isParameter("kind"))
  {
    if(rank == 0) std::cerr << "Problem kind not provided" << std::endl;
    return;
  }
  if(!problem_parameters.isParameter("InputAdapterParameters"))
  {
    if(rank == 0) std::cerr << "Input adapter parameters not provided" << std::endl;
    return;
  }
  if(!problem_parameters.isParameter("Zoltan2Parameters"))
  {
    if(rank == 0) std::cerr << "Zoltan2 problem parameters not provided" << std::endl;
    return;
  }

  if(rank == 0)
    cout << "\n\nRunning test: " << problem_parameters.name() << endl;
  
  ////////////////////////////////////////////////////////////
  // 0. add comparison source
  ////////////////////////////////////////////////////////////
  ComparisonSource * comparison_source = new ComparisonSource;
  comparison_helper->AddSource(problem_parameters.name(), comparison_source);
  comparison_source->addTimer("adapter construction time");
  comparison_source->addTimer("problem construction time");
  comparison_source->addTimer("solve time");
  ////////////////////////////////////////////////////////////
  // 1. get basic input adapter
  ////////////////////////////////////////////////////////////
  
  const ParameterList &adapterPlist = problem_parameters.sublist("InputAdapterParameters");
  comparison_source->timers["adapter construction time"]->start();
  base_adapter_t * ia = AdapterForTests::getAdapterForInput(const_cast<UserInputForTests *>(&uinput), adapterPlist,comm); // a pointer to a basic type
  comparison_source->timers["adapter construction time"]->stop();
  
//  if(rank == 0) cout << "Got input adapter... " << endl;
  if(ia == nullptr)
  {
    if(rank == 0)
      cout << "Get adapter for input failed" << endl;
    return;
  }
  
  ////////////////////////////////////////////////////////////
  // 2. construct a Zoltan2 problem
  ////////////////////////////////////////////////////////////
  string adapter_name = adapterPlist.get<string>("input adapter"); // If we are here we have an input adapter, no need to check for one.
  // get Zoltan2 partion parameters
  ParameterList zoltan2_parameters = const_cast<ParameterList &>(problem_parameters.sublist("Zoltan2Parameters"));
  
  //if(rank == 0){
  //  cout << "\nZoltan 2 parameters:" << endl;
  //  zoltan2_parameters.print(std::cout);
  //  cout << endl;
  //}

  comparison_source->timers["problem construction time"]->start();
  std::string problem_kind = problem_parameters.get<std::string>("kind"); 
  if (rank == 0) std::cout << "Creating a new " << problem_kind << " problem." << std::endl;
#ifdef HAVE_ZOLTAN2_MPI
  base_problem_t * problem = 
    Zoltan2_TestingFramework::ProblemFactory::newProblem(problem_kind, adapter_name, ia, &zoltan2_parameters, MPI_COMM_WORLD);
#else
  base_problem_t * problem = 
    Zoltan2_TestingFramework::ProblemFactory::newProblem(problem_kind, adapter_name, ia, &zoltan2_parameters);
#endif

  if (problem == nullptr) {
    if (rank == 0)
      std::cerr << "Input adapter type: " + adapter_name + ", is unvailable, or misspelled." << std::endl;
    return;
  }

  ////////////////////////////////////////////////////////////
  // 3. Solve the problem
  ////////////////////////////////////////////////////////////
  
  comparison_source->timers["solve time"]->start();
  
  if (problem_kind == "partitioning") {
    reinterpret_cast<partitioning_problem_t *>(problem)->solve();
  } else if (problem_kind == "ordering") {
    reinterpret_cast<ordering_problem_t *>(problem)->solve();
  } else if (problem_kind == "coloring") {
    reinterpret_cast<coloring_problem_t *>(problem)->solve();
  }
  comparison_source->timers["solve time"]->stop();
  if (rank == 0)
    cout << problem_kind + "Problem solved." << endl;
 

//#define KDDKDD
#ifdef KDDKDD
  {
  const base_adapter_t::gno_t *kddIDs = NULL;
  ia->getIDsView(kddIDs);
    for (size_t i = 0; i < ia->getLocalNumIDs(); i++) {
      std::cout << rank << " LID " << i
                << " GID " << kddIDs[i]
                << " PART " 
                << reinterpret_cast<partitioning_problem_t *>(problem)->getSolution().getPartListView()[i]
                << std::endl;
    }
  }
#endif

  ////////////////////////////////////////////////////////////
  // 4. Print problem metrics
  ////////////////////////////////////////////////////////////
  // An environment.  This is usually created by the problem.
  // BDD unused, only applicable to partitioning problems
  // RCP<const Zoltan2::Environment> env =
  //   reinterpret_cast<partitioning_problem_t *>(problem)->getEnvironment();

 // get metric object
  RCP<EvaluatePartition<basic_id_t> >metricObject =
      rcp(Zoltan2_TestingFramework::EvaluatePartitionFactory::
    newEvaluatePartition(reinterpret_cast<partitioning_problem_t*>
             (problem), adapter_name, ia,
             &zoltan2_parameters));
  
  std::string metric_types[] = {"Metrics", "Graph Metrics"};
  for (auto metric_type : metric_types) {
    if( problem_parameters.isParameter(metric_type)) {
      // calculate pass fail based on imbalance
      if(rank == 0) cout << "Analyzing " << metric_type << endl;
      if(rank == 0) {
        std::cout << metric_type << " for " << problem_kind << ":" << std::endl; 
        if (metric_type == "Metrics")
          metricObject->printMetrics(cout);
        else if (metric_type == "Graph Metrics")
          metricObject->printGraphMetrics(cout);
      }

      std::ostringstream msg;
      auto metricsPlist = problem_parameters.sublist(metric_type); // get the metrics plist
      bool all_tests_pass = false;
      all_tests_pass
      = MetricAnalyzer::analyzeMetrics( metricsPlist,
                                        metricObject,
                                        comm,
                                        msg); 

      std::cout << msg.str() << std::endl;
      if(rank == 0 && all_tests_pass) cout << "All " << metric_type  << " tests PASSED." << endl;
      else if (rank == 0) cout << "One or more " << metric_type << " tests FAILED." << endl;
    } else if (rank == 0) cout << metric_type  << " analysis unrequested. PASSED." << endl;
  }
  
#define BDD
#ifdef BDD 
  if (problem_kind == "ordering") {
    std::cout << "\nLet's examine the solution..." << std::endl;
    auto solution = reinterpret_cast<ordering_problem_t *>(problem)->getSolution();
    if (solution->haveSeparators() ) {
      
      std::ostringstream sol;
      sol << "Number of column blocks: " << solution->getNumSeparatorBlocks() << std::endl;
      if (solution->getPermutationSize() < 100) {
        if (solution->havePerm()) {
          sol << "permutation: {";
          for (auto &x : solution->getPermutationRCPConst(false)) sol << " " << x;
          sol << "}" << std::endl;
        }
       
       if (solution->haveInverse()) { 
          sol << "inverse permutation: {";
          for (auto &x : solution->getPermutationRCPConst(true)) sol << " " << x;
          sol << "}" << std::endl;
       }
        
       if (solution->haveSeparatorRange()) {
          sol << "separator range: {";
          for (auto &x : solution->getSeparatorRangeRCPConst()) sol << " " << x;
          sol << "}" << std::endl;
       }
       
        if (solution->haveSeparatorTree()) { 
          sol << "separator tree: {";
          for (auto &x : solution->getSeparatorTreeRCPConst()) sol << " " << x;
          sol << "}" << std::endl;
        }
      }

      std::cout << sol.str() << std::endl;
    }
  }
#endif
  // 4b. timers
//  if(zoltan2_parameters.isParameter("timer_output_stream"))
//    reinterpret_cast<partitioning_problem_t *>(problem)->printTimers();

  ////////////////////////////////////////////////////////////
  // 5. Add solution to map for possible comparison testing
  ////////////////////////////////////////////////////////////
  comparison_source->adapter = RCP<basic_id_t>(reinterpret_cast<basic_id_t *>(ia));
  comparison_source->problem = RCP<base_problem_t>(reinterpret_cast<base_problem_t *>(problem));
  comparison_source->metricObject = metricObject;
  comparison_source->problem_kind = problem_parameters.isParameter("kind") ? problem_parameters.get<string>("kind") : "?";
  comparison_source->adapter_kind = adapter_name;
  
  // write mesh solution
//  auto sol = reinterpret_cast<partitioning_problem_t *>(problem)->getSolution();
//  MyUtils::writePartionSolution(sol.getPartListView(), ia->getLocalNumIDs(), comm);

  ////////////////////////////////////////////////////////////
  // 6. Clean up
  ////////////////////////////////////////////////////////////
}