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