bool ML_Epetra::ValidateMLPParameters(const Teuchos::ParameterList &inList, int depth){
  using Teuchos::ParameterList;
  using Teuchos::Exceptions::InvalidParameterName;
  using Teuchos::Exceptions::InvalidParameterType;
  using Teuchos::Exceptions::InvalidParameterValue;
  using std::cout;
  using std::endl;
  using std::string;
  
  ParameterList List,*validList;
  bool rv=true;

  /* Build a copy of the list to be validated. */
  for (ParameterList::ConstIterator param = inList.begin(); param != inList.end(); ++param) {
    const std::string pname=inList.name(param);
    if (pname.find("user-defined function",0) == std::string::npos) {
      List.setEntry(pname,inList.entry(param));
    }
  }

  List.setName(inList.name());

  /* Get Defaults + Validate */
  try {
    validList = GetValidMLPParameters();
  }
  catch(...) {
    std::cout << "Error in GetValidMLPParameters.  Please report this bug to the ML "
      "developers." << std::endl;
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    exit(EXIT_FAILURE);
  }
  try {
    List.validateParameters (*validList, depth, Teuchos::VALIDATE_USED_ENABLED, 
			     Teuchos::VALIDATE_DEFAULTS_DISABLED);
  }
#ifdef HAVE_IFPACK_DYNAMIC_FACTORY
  catch(InvalidParameterName &excpt)  {/*rv=false; std::cout<<excpt.what()<<std::endl;*/}
#else
  catch(InvalidParameterName &excpt)  {rv=false; std::cout<<excpt.what()<<std::endl;}
#endif
  catch(InvalidParameterType &excpt)  {rv=false; std::cout<<excpt.what()<<std::endl;}
  catch(InvalidParameterValue &excpt) {rv=false; std::cout<<excpt.what()<<std::endl;}
  catch(...) {rv=false;}
  delete validList;
  return rv;
}
bool
ComparisonHelper::metricComparisonTest(const RCP<const Comm<int> > &comm,
                                       const Zoltan2::MetricValues<zscalar_t> & metric,
                                       const Zoltan2::MetricValues<zscalar_t> & ref_metric,
                                       const Teuchos::ParameterList & metricPlist,
                                       ostringstream &msg)
{
  // run a comparison of min and max agains a given metric
  // return an error message on failure
  bool pass = true;
  string test_name = metricPlist.name() + " test";
  double local_ref_value = ref_metric.getMaxImbalance()/ref_metric.getAvgImbalance();
  double local_value = metric.getMaxImbalance()/metric.getAvgImbalance();
  
  // reduce problem metric
  double value;
  Teuchos::Ptr<double> global(&value);
  comm->barrier();
  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,local_value,global);
  
  // reduce reference metric
  double ref_value;
  Teuchos::Ptr<double> globalRef(&ref_value);
  comm->barrier();
  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,local_ref_value,globalRef);
  
  // want to reduce value to max value for all procs
  
  if (metricPlist.isParameter("lower"))
  {
    double min = metricPlist.get<double>("lower")*ref_value;
    
    if(value < min)
    {
      msg << test_name << " FAILED: Minimum imbalance per part, "
      << value << ", less than specified allowable minimum, " << min << ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: Minimum imbalance per part, "
      << value << ", greater than specified allowable minimum, " << min << ".\n";
    }
  }
  
  if(metricPlist.isParameter("upper" ) && pass != false) {
    
    double max = metricPlist.get<double>("upper") * ref_value;
    if (value > max)
    {
      msg << test_name << " FAILED: Maximum imbalance per part, "
      << value << ", greater than specified allowable maximum, " << max << ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: Maximum imbalance per part, "
      << value << ", less than specified allowable maximum, " << max << ".\n";
    }
    
  }

  return pass;
}
// BDD, to do: print metrics even for pass
//             reduce max metric to process 0
//             print only on process 0 --- duh.
bool ComparisonHelper::timerComparisonTest(const RCP<const Comm<int> > &comm,
                                           const double time,
                                           const double ref_time,
                                           const Teuchos::ParameterList & metricPlist,
                                           ostringstream &msg)
{
  // Reduce time from test
  double global_time;
  Teuchos::Ptr<double> global(&global_time);
  comm->barrier();
  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
  
  // Reduce time from reference
  double global_ref_time;
  Teuchos::Ptr<double> globalRef(&global_ref_time);
  comm->barrier();
  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
  
  
  // run a comparison of min and max agains a given metric
  // return an error message on failure
  bool pass = true;
  string test_name = metricPlist.name() + " test";
  if (metricPlist.isParameter("lower"))
  {
    double min = metricPlist.get<double>("lower")*global_ref_time;
    
    if(global_time < min)
    {
      msg << test_name << " FAILED: Minimum time, "
      << time <<
      "[s], less than specified allowable minimum time, " << min <<"[s]"<< ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: Minimum time, "
      << time <<
      "[s], greater than specified allowable minimum time, " << min <<"[s]"<< ".\n";
    }
  }
  
  if(metricPlist.isParameter("upper" ) && pass != false) {
    
    double max = metricPlist.get<double>("upper") * global_ref_time;
    if (global_time > max)
    {
      msg << test_name << " FAILED: Maximum time, "
      << global_time <<
      "[s], greater than specified allowable maximum time, " << max <<"[s]"<< ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: Maximum time, "
      << global_time <<
      "[s], less than specified allowable maximum time, " << max <<"[s]"<< ".\n";
    }
    
  }
  
  return pass;
}
Exemple #4
0
bool ML_Epetra::ValidateRefMaxwellParameters(const Teuchos::ParameterList &inList){
  using Teuchos::ParameterList;
  using Teuchos::Exceptions::InvalidParameterName;
  using Teuchos::Exceptions::InvalidParameterType;
  using Teuchos::Exceptions::InvalidParameterValue;
  using std::cout;
  using std::endl;
  using std::string;

  ParameterList List,*validList;
  bool rv=true;
  
  /* Build a list with level-specific stuff stripped */
  //TODO this should be fixed
  for (ParameterList::ConstIterator param = inList.begin(); param != inList.end(); ++param) {
    const string pname=inList.name(param);
    if (pname.find("(level",0) == string::npos) {
      List.setEntry(pname,inList.entry(param));
    }
  }

  List.setName(inList.name());

  /* Get Defaults + Validate */
  try{
    validList = GetValidRefMaxwellParameters();
  }
  catch(...) {
    cout << "Error in GetValidMLPParameters.  Please report this bug to the ML "
      "developers." << endl;
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    exit(EXIT_FAILURE);
  }
  try {
    List.validateParameters(*validList, 0, Teuchos::VALIDATE_USED_DISABLED,
			    Teuchos::VALIDATE_DEFAULTS_DISABLED);
  }
  catch(InvalidParameterName &excpt)  {rv=false; cout<<excpt.what();}
  catch(InvalidParameterType &excpt)  {rv=false; cout<<excpt.what();}
  catch(InvalidParameterValue &excpt) {rv=false; cout<<excpt.what();}
  catch(...) {rv=false;}
  delete validList;
  return rv;
}
bool TouchContFileParameters( Teuchos::ParameterList & fileParams )
{
  // Either int or double type
  int dummyInt;
  double dummyDouble;

  // Looping the list
  Teuchos::map<string, Teuchos::ParameterEntry>::const_iterator i;
  for (i = fileParams.begin(); i !=fileParams.end(); ++i) {

    if (fileParams.isType<int>(fileParams.name(i)))
      dummyInt = fileParams.get<int>(fileParams.name(i));

    if (fileParams.isType<double>(fileParams.name(i)))
      dummyDouble = fileParams.get<double>(fileParams.name(i));
  }

  return true;
}
void buildResponseMap(const Teuchos::ParameterList & p,
                      std::map<std::string,std::pair<ResponseId,std::pair<std::list<std::string>,std::list<std::string> > > > & responses)
{
   static Teuchos::RCP<const Teuchos::ParameterList> validList;

   // build valid parameter list
   if(validList==Teuchos::null) {
      Teuchos::RCP<Teuchos::ParameterList> tmpList = Teuchos::rcp(new Teuchos::ParameterList);
      tmpList->set<std::string>("Type","");
      tmpList->set<std::string>("Field Name","");
      tmpList->set<std::string>("Element Blocks","empty","Element blocks for this response",Teuchos::rcp(new CommaSeperatedEntryValidator));
      tmpList->set<std::string>("Evaluation Types","empty","Evaluation types for this response",Teuchos::rcp(new CommaSeperatedEntryValidator));

      validList = tmpList;
   }
 
   CommaSeperatedEntryValidator validator;
   const std::string & sublistName = p.name();
   std::vector<std::string> tokens;

   responses.clear();

   // loop over entries of parameter list, must satisfy response formatting
   for(Teuchos::ParameterList::ConstIterator itr=p.begin(); itr!=p.end();++itr) {
 
      const std::string & paramName = itr->first;
      const Teuchos::ParameterEntry & pe = itr->second;

      // make sure this is a parameter list
      TEUCHOS_TEST_FOR_EXCEPTION(!pe.isList(),Teuchos::Exceptions::InvalidParameterValue,
                         "In list \""+sublistName+"\", the parameter \""+paramName+"\" is expected "
                         "to be a sublist. Response map cannot be built!");

      // extract parameter list and validate
      const Teuchos::ParameterList & respList = Teuchos::getValue<Teuchos::ParameterList>(pe); 
      respList.validateParameters(*validList);

      const std::string & respLabel = paramName;
      ResponseId & rid = responses[respLabel].first;
      std::list<std::string> & eBlocks = responses[respLabel].second.first; // element blocks
      std::list<std::string> & eTypes = responses[respLabel].second.second;  // evaluation types

      rid.type = respList.get<std::string>("Type");
      rid.name = respList.get<std::string>("Field Name");

      CommaSeperatedEntryValidator::split(respList.get<std::string>("Element Blocks"),",",tokens);
      eBlocks.assign(tokens.begin(),tokens.end()); // this should automatically wipe out old values
      
      CommaSeperatedEntryValidator::split(respList.get<std::string>("Evaluation Types"),",",tokens);
      eTypes.assign(tokens.begin(),tokens.end()); // this should automatically wipe out old values
   }
}
Operator<Node>::Operator(Teuchos::RCP<const ::Tpetra::CrsGraph<int,int,Node> > input_graph,
 	                 const Teuchos::ParameterList& paramlist, int base)
  : input_graph_(input_graph), 
    operation_already_computed_(false),
    base_(base)
{
  input_map_ = input_graph->getRowMap(); //think this is safe

  if(paramlist.name() != "EmptyParameterList")
  {
    setParameters(paramlist);
  }

}
bool
ComparisonHelper::metricComparisonTest(const RCP<const Comm<int> > &comm,
                                       const Zoltan2::MetricValues<zscalar_t> & metric,
                                       const Zoltan2::MetricValues<zscalar_t> & ref_metric,
                                       const Teuchos::ParameterList & metricPlist,
                                       ostringstream &msg)
{
  // run a comparison of min and max agains a given metric
  // return an error message on failure
  bool pass = true;
  string test_name = metricPlist.name() + " test";
  double ref_value = ref_metric.getMaxImbalance();
  double value = metric.getMaxImbalance();
  
  // want to reduce value to max value for all procs
  
  if (metricPlist.isParameter("lower"))
  {
    double min = metricPlist.get<double>("lower")*ref_value;
    
    if(value < min)
    {
      msg << test_name << " FAILED: imbalance per part, "
      << value << ", less than specified allowable minimum, " << min << ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: imbalance per part, "
      << value << ", greater than specified allowable minimum, " << min << ".\n";
    }
  }
  
  if(metricPlist.isParameter("upper" ) && pass != false) {
    
    double max = metricPlist.get<double>("upper") * ref_value;
    if (value > max)
    {
      msg << test_name << " FAILED: imbalance per part, "
      << value << ", greater than specified allowable maximum, " << max << ".\n";
      pass = false;
    }else{
      msg << test_name << " PASSED: imbalance per part, "
      << value << ", less than specified allowable maximum, " << max << ".\n";
    }
    
  }

  return pass;
}
bool ComparisonHelper::metricComparisonTest(const RCP<const Comm<int> > &comm,
                                       const MetricAnalyzerInfo & metric,
                                       const MetricAnalyzerInfo & ref_metric,
                                       const Teuchos::ParameterList & metricPlist,
                                       ostringstream &msg)
{
  // run a comparison of min and max against a given metric
  // return an error message on failure
  bool pass = true;
  string test_name = metricPlist.name() + " test";
  double ref_value = ref_metric.theValue;
  double value = metric.theValue;

  if (ref_value == 0) {
    throw std::logic_error( "The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
  }
  double percentRatio = value / ref_value;
  
  // want to reduce value to max value for all procs
  
  if (ref_metric.bFoundLowerBound) {
    double min = ref_metric.lowerValue;
    if (percentRatio < min) {
      msg << test_name << " FAILED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which less than specified allowable minimum percent, " << min << ".\n";
      pass = false;
    }
    else {
      msg << test_name << " PASSED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is greater than specified allowable minimum percent, " << min << ".\n";
    }
  }
  
  if (ref_metric.bFoundUpperBound) {
    double max = ref_metric.upperValue;
    if (percentRatio > max) {
      msg << test_name << " FAILED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is greater than specified allowable maximum percent, " << max << ".\n";
      pass = false;
    }
    else {
      msg << test_name << " PASSED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is less than specified allowable maximum percent, " << max << ".\n";
    }
  }

  return pass;
}
Exemple #10
0
bool WriteHeaderToContFile( const string & fileName,
    const Teuchos::ParameterList & fileParams )
{
  // The file to open
  ofstream oFile(fileName.c_str());

  // Writing the header
  oFile << "#" << setw(6) << "ID";

  // Looping on the parameters
  Teuchos::map<string, Teuchos::ParameterEntry>::const_iterator i;
  for (i = fileParams.begin(); i !=fileParams.end(); ++i) 
    oFile << setw(15) << fileParams.name(i);
  oFile << std::endl;

  // Closing
  oFile.close();

  return true;
}
void Operator<Node>::paramsToUpper(Teuchos::ParameterList &plist, int &changed, bool rmUnderscore)
{
  changed = 0;

  // get a list of all parameter names in the list

  std::vector<std::string> paramNames ;
  Teuchos::ParameterList::ConstIterator pIter;

  pIter = plist.begin();

  while (1){
    //////////////////////////////////////////////////////////////////////
    // Compiler considered this while statement an error
    // for ( pIter = plist.begin() ; pIter != plist.end() ; pIter++ ){
    // }
    //////////////////////////////////////////////////////////////////////
    if (pIter == plist.end()) break;
    const std::string & nm = plist.name(pIter);
    paramNames.push_back(nm);
    pIter++;
  }

  // Change parameter names and values to upper case

  for (unsigned int i=0; i < paramNames.size(); i++){

    std::string origName(paramNames[i]);
    int paramNameChanged = 0;
    stringToUpper(paramNames[i], paramNameChanged, rmUnderscore);

    if (plist.isSublist(origName)){
      Teuchos::ParameterList &sublist = plist.sublist(origName);

      int sublistChanged=0;
      paramsToUpper(sublist, sublistChanged, false);

      if (paramNameChanged){

        // this didn't work, so I need to remove the old sublist
        // and create a new one
        //
        //sublist.setName(paramNames[i]);

        Teuchos::ParameterList newlist(sublist);
        plist.remove(origName);
        plist.set(paramNames[i], newlist);
      }
    }
    else if (plist.isParameter(origName)){

      std::string paramVal(plist.get<std::string>(origName));

      int paramValChanged=0;
      stringToUpper(paramVal, paramValChanged);

      if (paramNameChanged || paramValChanged){
        if (paramNameChanged){
          plist.remove(origName);
        }
        plist.set(paramNames[i], paramVal);
        changed++;
      }
    }
  } // next parameter or sublist
}
    //! @name Constructor/Destructor
    //@{
    AMGXOperator(const Teuchos::RCP<Tpetra::CrsMatrix<SC,LO,GO,NO> > &inA, Teuchos::ParameterList &paramListIn) {
      RCP<const Teuchos::Comm<int> > comm = inA->getRowMap()->getComm();
      int numProcs = comm->getSize();
      int myRank   = comm->getRank();

      RCP<Teuchos::Time> amgxTimer = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: initialize");
      amgxTimer->start();
      // Initialize
      AMGX_SAFE_CALL(AMGX_initialize());
      AMGX_SAFE_CALL(AMGX_initialize_plugins());

      /*system*/
      //AMGX_SAFE_CALL(AMGX_register_print_callback(&print_callback));
      AMGX_SAFE_CALL(AMGX_install_signal_handler());
      Teuchos::ParameterList configs = paramListIn.sublist("amgx:params", true);
      if (configs.isParameter("json file")) {
        AMGX_SAFE_CALL(AMGX_config_create_from_file(&Config_, (const char *) &configs.get<std::string>("json file")[0]));
      } else {
        std::ostringstream oss;
        oss << "";
        ParameterList::ConstIterator itr;
        for (itr = configs.begin(); itr != configs.end(); ++itr) {
          const std::string&    name  = configs.name(itr);
          const ParameterEntry& entry = configs.entry(itr);
          oss << name << "=" << filterValueToString(entry) << ", ";
        }
        oss << "\0";
        std::string configString = oss.str();
        if (configString == "") {
          //print msg that using defaults
          //GetOStream(Warnings0) << "Warning: No configuration parameters specified, using default AMGX configuration parameters. \n";
        }
        AMGX_SAFE_CALL(AMGX_config_create(&Config_, configString.c_str()));
      }

      // TODO: we probably need to add "exception_handling=1" to the parameter list
      // to switch on internal error handling (with no need for AMGX_SAFE_CALL)

#define NEW_COMM
#ifdef NEW_COMM
      // NOTE: MPI communicator used in AMGX_resources_create must exist in the scope of AMGX_matrix_comm_from_maps_one_ring
      // FIXME: fix for serial comm
      RCP<const Teuchos::MpiComm<int> > tmpic = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm->duplicate());
      TEUCHOS_TEST_FOR_EXCEPTION(tmpic.is_null(), Exceptions::RuntimeError, "Communicator is not MpiComm");

      RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > rawMpiComm = tmpic->getRawMpiComm();
      MPI_Comm mpiComm = *rawMpiComm;
#endif

      // Construct AMGX resources
      if (numProcs == 1) {
        AMGX_resources_create_simple(&Resources_, Config_);

      } else {
        int numGPUDevices;
        cudaGetDeviceCount(&numGPUDevices);
        int device[] = {(comm->getRank() % numGPUDevices)};

        AMGX_config_add_parameters(&Config_, "communicator=MPI");
#ifdef NEW_COMM
        AMGX_resources_create(&Resources_, Config_, &mpiComm, 1/* number of GPU devices utilized by this rank */, device);
#else
        AMGX_resources_create(&Resources_, Config_, MPI_COMM_WORLD, 1/* number of GPU devices utilized by this rank */, device);
#endif
      }

      AMGX_Mode mode = AMGX_mode_dDDI;
      AMGX_solver_create(&Solver_, Resources_, mode,  Config_);
      AMGX_matrix_create(&A_,      Resources_, mode);
      AMGX_vector_create(&X_,      Resources_, mode);
      AMGX_vector_create(&Y_,      Resources_, mode);

      amgxTimer->stop();
      amgxTimer->incrementNumCalls();

      std::vector<int> amgx2muelu;

      // Construct AMGX communication pattern
      if (numProcs > 1) {
        RCP<const Tpetra::Import<LO,GO> > importer = inA->getCrsGraph()->getImporter();

        TEUCHOS_TEST_FOR_EXCEPTION(importer.is_null(), MueLu::Exceptions::RuntimeError, "The matrix A has no Import object.");

        Tpetra::Distributor distributor = importer->getDistributor();

        Array<int> sendRanks = distributor.getImagesTo();
        Array<int> recvRanks = distributor.getImagesFrom();

        std::sort(sendRanks.begin(), sendRanks.end());
        std::sort(recvRanks.begin(), recvRanks.end());

        bool match = true;
        if (sendRanks.size() != recvRanks.size()) {
          match = false;
        } else {
          for (int i = 0; i < sendRanks.size(); i++) {
            if (recvRanks[i] != sendRanks[i])
              match = false;
              break;
          }
        }
        TEUCHOS_TEST_FOR_EXCEPTION(!match, MueLu::Exceptions::RuntimeError, "AMGX requires that the processors that we send to and receive from are the same. "
                                   "This is not the case: we send to {" << sendRanks << "} and receive from {" << recvRanks << "}");

        int        num_neighbors = sendRanks.size();  // does not include the calling process
        const int* neighbors     = &sendRanks[0];

        // Later on, we'll have to organize the send and recv data by PIDs,
        // i.e, a vector V of vectors, where V[i] is PID i's vector of data.
        // Hence we need to be able to quickly look up  an array index
        // associated with each PID.
        Tpetra::Details::HashTable<int,int> hashTable(3*num_neighbors);
        for (int i = 0; i < num_neighbors; i++)
          hashTable.add(neighbors[i], i);

        // Get some information out
        ArrayView<const int> exportLIDs = importer->getExportLIDs();
        ArrayView<const int> exportPIDs = importer->getExportPIDs();
        Array<int> importPIDs;
        Tpetra::Import_Util::getPids(*importer, importPIDs, true/* make local -1 */);

        // Construct the reordering for AMGX as in AMGX_matrix_upload_all documentation
        RCP<const Map> rowMap = inA->getRowMap();
        RCP<const Map> colMap = inA->getColMap();

        int N = rowMap->getNodeNumElements(), Nc = colMap->getNodeNumElements();
        muelu2amgx_.resize(Nc, -1);

        int numUniqExports = 0;
        for (int i = 0; i < exportLIDs.size(); i++)
          if (muelu2amgx_[exportLIDs[i]] == -1) {
            numUniqExports++;
            muelu2amgx_[exportLIDs[i]] = -2;
          }

        int localOffset = 0, exportOffset = N - numUniqExports;
        // Go through exported LIDs and put them at the end of LIDs
        for (int i = 0; i < exportLIDs.size(); i++)
          if (muelu2amgx_[exportLIDs[i]] < 0) // exportLIDs are not unique
            muelu2amgx_[exportLIDs[i]] = exportOffset++;
        // Go through all non-export LIDs, and put them at the beginning of LIDs
        for (int i = 0; i < N; i++)
          if (muelu2amgx_[i] == -1)
            muelu2amgx_[i] = localOffset++;
        // Go through the tail (imported LIDs), and order those by neighbors
        int importOffset = N;
        for (int k = 0; k < num_neighbors; k++)
          for (int i = 0; i < importPIDs.size(); i++)
            if (importPIDs[i] != -1 && hashTable.get(importPIDs[i]) == k)
              muelu2amgx_[i] = importOffset++;

        amgx2muelu.resize(muelu2amgx_.size());
        for (int i = 0; i < muelu2amgx_.size(); i++)
          amgx2muelu[muelu2amgx_[i]] = i;

        // Construct send arrays
        std::vector<std::vector<int> > sendDatas (num_neighbors);
        std::vector<int>               send_sizes(num_neighbors, 0);
        for (int i = 0; i < exportPIDs.size(); i++) {
          int index = hashTable.get(exportPIDs[i]);
          sendDatas [index].push_back(muelu2amgx_[exportLIDs[i]]);
          send_sizes[index]++;
        }
        // FIXME: sendDatas must be sorted (based on GIDs)

        std::vector<const int*> send_maps(num_neighbors);
        for (int i = 0; i < num_neighbors; i++)
          send_maps[i] = &(sendDatas[i][0]);

        // Debugging
        printMaps(comm, sendDatas, amgx2muelu, neighbors, *importer->getTargetMap(), "send_map_vector");

        // Construct recv arrays
        std::vector<std::vector<int> > recvDatas (num_neighbors);
        std::vector<int>               recv_sizes(num_neighbors, 0);
        for (int i = 0; i < importPIDs.size(); i++)
          if (importPIDs[i] != -1) {
            int index = hashTable.get(importPIDs[i]);
            recvDatas [index].push_back(muelu2amgx_[i]);
            recv_sizes[index]++;
        }
        // FIXME: recvDatas must be sorted (based on GIDs)

        std::vector<const int*> recv_maps(num_neighbors);
        for (int i = 0; i < num_neighbors; i++)
          recv_maps[i] = &(recvDatas[i][0]);

        // Debugging
        printMaps(comm, recvDatas, amgx2muelu, neighbors, *importer->getTargetMap(), "recv_map_vector");

        AMGX_SAFE_CALL(AMGX_matrix_comm_from_maps_one_ring(A_, 1, num_neighbors, neighbors, &send_sizes[0], &send_maps[0], &recv_sizes[0], &recv_maps[0]));

        AMGX_vector_bind(X_, A_);
        AMGX_vector_bind(Y_, A_);
      }

      RCP<Teuchos::Time> matrixTransformTimer = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: transform matrix");
      matrixTransformTimer->start();

      ArrayRCP<const size_t> ia_s;
      ArrayRCP<const int>    ja;
      ArrayRCP<const double> a;
      inA->getAllValues(ia_s, ja, a);

      ArrayRCP<int> ia(ia_s.size());
      for (int i = 0; i < ia.size(); i++)
        ia[i] = Teuchos::as<int>(ia_s[i]);

      N_      = inA->getNodeNumRows();
      int nnz = inA->getNodeNumEntries();

      matrixTransformTimer->stop();
      matrixTransformTimer->incrementNumCalls();


      // Upload matrix
      // TODO Do we need to pin memory here through AMGX_pin_memory?
      RCP<Teuchos::Time> matrixTimer = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: transfer matrix  CPU->GPU");
      matrixTimer->start();
      if (numProcs == 1) {
        AMGX_matrix_upload_all(A_, N_, nnz, 1, 1, &ia[0], &ja[0], &a[0], NULL);

      } else {
        // Transform the matrix
        std::vector<int>    ia_new(ia.size());
        std::vector<int>    ja_new(ja.size());
        std::vector<double> a_new (a.size());

        ia_new[0] = 0;
        for (int i = 0; i < N_; i++) {
          int oldRow = amgx2muelu[i];

          ia_new[i+1] = ia_new[i] + (ia[oldRow+1] - ia[oldRow]);

          for (int j = ia[oldRow]; j < ia[oldRow+1]; j++) {
            int offset = j - ia[oldRow];
            ja_new[ia_new[i] + offset] = muelu2amgx_[ja[j]];
            a_new [ia_new[i] + offset] = a[j];
          }
          // Do bubble sort on two arrays
          // NOTE: There are multiple possible optimizations here (even of bubble sort)
          bool swapped;
          do {
            swapped = false;

            for (int j = ia_new[i]; j < ia_new[i+1]-1; j++)
              if (ja_new[j] > ja_new[j+1]) {
                std::swap(ja_new[j], ja_new[j+1]);
                std::swap(a_new [j], a_new [j+1]);
                swapped = true;
              }
          } while (swapped == true);
        }

        AMGX_matrix_upload_all(A_, N_, nnz, 1, 1, &ia_new[0], &ja_new[0], &a_new[0], NULL);
      }
      matrixTimer->stop();
      matrixTimer->incrementNumCalls();

      domainMap_ = inA->getDomainMap();
      rangeMap_  = inA->getRangeMap();

      RCP<Teuchos::Time> realSetupTimer = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: real setup");
      realSetupTimer->start();
      AMGX_solver_setup(Solver_, A_);
      realSetupTimer->stop();
      realSetupTimer->incrementNumCalls();

      vectorTimer1_ = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: transfer vectors CPU->GPU");
      vectorTimer2_ = Teuchos::TimeMonitor::getNewTimer("MueLu: AMGX: transfer vector  GPU->CPU");
    }
Exemple #13
0
int main(int argc, char *argv[]) {
  using Teuchos::RCP; // reference count pointers
  using Teuchos::rcp;
  using Teuchos::TimeMonitor;

  //
  // MPI initialization using Teuchos
  //

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

  //
  // Parameters
  //

  Teuchos::CommandLineProcessor clp(false); // Note:

  GO nx,ny,nz;
  nx=500;
  ny=500;
  nz=100;
  Galeri::Xpetra::Parameters<GO> matrixParameters(clp, nx, ny, nz, "Laplace2D"); // manage parameters of the test case
  Xpetra::Parameters             xpetraParameters(clp);                          // manage parameters of Xpetra

  std::string xmlFileName = "scalingTest.xml"; clp.setOption("xml",   &xmlFileName, "read parameters from a file. Otherwise, this example uses by default 'scalingTest.xml'");
  int amgAsPrecond=1; clp.setOption("precond",&amgAsPrecond,"apply multigrid as preconditioner");
  int amgAsSolver=0; clp.setOption("fixPoint",&amgAsSolver,"apply multigrid as solver");
  bool printTimings=true; clp.setOption("timings","notimings",&printTimings,"print timings to screen");

  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;
  }

  if (comm->getRank() == 0) {
    std::cout << "========================================================" << std::endl
              << xpetraParameters << matrixParameters;
  }

  RCP<TimeMonitor> globalTimeMonitor = rcp (new TimeMonitor(*TimeMonitor::getNewTimer("ScalingTest: S - Global Time")));

  // read aggregation options from file
  Teuchos::FileInputSource fileSrc(xmlFileName);
  Teuchos::XMLObject fileXML = fileSrc.getObject();
  Teuchos::XMLParameterListReader listReader;
  Teuchos::ParameterList aggList = listReader.toParameterList(fileXML);
  //std::cout << "===========aggList start===========" << std::endl;
  //aggList.print(std::cout);
  //std::cout << "===========aggList end===========" << std::endl;

  // instantiate aggregate factory, set options from parameter list
  RCP<MueLu::SingleLevelFactoryBase> aggFact;
  if (aggList.name() == "UncoupledAggregationFactory") {

     RCP<UncoupledAggregationFactory> ucFact = rcp( new UncoupledAggregationFactory() );
     //ucFact->SetParameterList(aggList);
     //FIXME hack until UCAgg uses PL interface
     std::string ordering = aggList.get<std::string>("Ordering");
     MueLu::AggOptions::Ordering eordering;
     if (ordering=="Natural") eordering = MueLu::AggOptions::NATURAL;
     if (ordering=="Graph") eordering = MueLu::AggOptions::GRAPH;
     if (ordering=="Random") eordering = MueLu::AggOptions::RANDOM;
     ucFact->SetOrdering(eordering);
     ucFact->SetMaxNeighAlreadySelected(aggList.get<int>("MaxNeighAlreadySelected"));
     ucFact->SetMinNodesPerAggregate(aggList.get<int>("MinNodesPerAggregate"));
     aggFact = ucFact;

  } else if (aggList.name() == "CoupledAggregationFactory") {

     RCP<CoupledAggregationFactory> cFact = rcp( new CoupledAggregationFactory() );
     //cFact->SetParameterList(aggList);
     //FIXME hack until CoupledAgg uses PL interface
     //cFact->SetOrdering(aggList.get<std::string>("Ordering"));
     cFact->SetMaxNeighAlreadySelected(aggList.get<int>("MaxNeighAlreadySelected"));
     cFact->SetMinNodesPerAggregate(aggList.get<int>("MinNodesPerAggregate"));
     aggFact = cFact;

  } else {

    throw(MueLu::Exceptions::RuntimeError("List's name does not correspond to a known aggregation factory."));

  }

  //Teuchos::ParameterList tlist = aggFact->GetParameterList();
  //std::cout << "===========verify List start===========" << std::endl;
  //tlist.print(std::cout);
  //std::cout << "===========verify List end===========" << std::endl;

  // build matrix
  RCP<TimeMonitor> tm = rcp (new TimeMonitor(*TimeMonitor::getNewTimer("ScalingTest: 1 - Matrix Build")));

  RCP<const Map> map;
  RCP<MultiVector> coordinates;

  // Retrieve matrix parameters (they may have been changed on the command line), and pass them to Galeri.
  // Galeri will attempt to create a square-as-possible distribution of subdomains di, e.g.,
  //                                 d1  d2  d3
  //                                 d4  d5  d6
  //                                 d7  d8  d9
  //                                 d10 d11 d12
  // A perfect distribution is only possible when the #processors is a perfect square.
  // This *will* result in "strip" distribution if the #processors is a prime number or if the factors are very different in
  // size. For example, np=14 will give a 7-by-2 distribution.
  // If you don't want Galeri to do this, specify mx or my on the galeriList.
  Teuchos::ParameterList pl = matrixParameters.GetParameterList();
  Teuchos::ParameterList galeriList;
  galeriList.set("nx", pl.get("nx",nx));
  galeriList.set("ny", pl.get("ny",ny));
  //galeriList.set("mx", comm->getSize());
  //galeriList.set("my", 1);

  if (matrixParameters.GetMatrixType() == "Laplace1D") {
    map = MapFactory::Build(xpetraParameters.GetLib(), matrixParameters.GetNumGlobalElements(), 0, comm);
    coordinates = Galeri::Xpetra::Utils::CreateCartesianCoordinates<SC,LO,GO,Map,MultiVector>("1D",map,matrixParameters.GetParameterList());
  }
  else if (matrixParameters.GetMatrixType() == "Laplace2D" || matrixParameters.GetMatrixType() == "Star2D") {
    map = Galeri::Xpetra::CreateMap<LO, GO, Node>(xpetraParameters.GetLib(), "Cartesian2D", comm, galeriList);
    coordinates = Galeri::Xpetra::Utils::CreateCartesianCoordinates<SC,LO,GO,Map,MultiVector>("2D",map,matrixParameters.GetParameterList());
  }
  else if (matrixParameters.GetMatrixType() == "Laplace3D") {
    coordinates = Galeri::Xpetra::Utils::CreateCartesianCoordinates<SC,LO,GO,Map,MultiVector>("3D",map,matrixParameters.GetParameterList());
    //map = Galeri::Xpetra::CreateMap<LO, GO, Node>(xpetraParameters.GetLib(), "Cartesian3D", comm, galeriList); //TODO when available in Galeri
    map = MapFactory::Build(xpetraParameters.GetLib(), matrixParameters.GetNumGlobalElements(), 0, comm);
  }

  if (comm->getRank() == 0) {
    GO mx = galeriList.get("mx", -1);
    GO my = galeriList.get("my", -1);
    std::cout << "Processor subdomains in x direction: " << mx << std::endl
              << "Processor subdomains in y direction: " << my << std::endl
              << "========================================================" << std::endl;
  }

  RCP<Galeri::Xpetra::Problem<Map,CrsMatrixWrap,MultiVector> > Pr =
      Galeri::Xpetra::BuildProblem<SC,LO,GO,Map,CrsMatrixWrap,MultiVector>(matrixParameters.GetMatrixType(), map, matrixParameters.GetParameterList());
  RCP<Matrix> A = Pr->BuildMatrix();

  tm = Teuchos::null;

  Level level;
  RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(new FactoryManager());
  level.SetFactoryManager(factoryHandler);
  level.SetLevelID(0);
  level.Set("A", A);

  level.Request("Aggregates", aggFact.get());
  level.Request(*aggFact);

  level.setVerbLevel(Teuchos::VERB_NONE);
  aggFact->setVerbLevel(Teuchos::VERB_NONE);
  tm = rcp (new TimeMonitor(*TimeMonitor::getNewTimer("aggregation time")));
  aggFact->Build(level);
  tm = Teuchos::null;

  globalTimeMonitor = Teuchos::null;

  if (printTimings)
    TimeMonitor::summarize();

} //main