#include "Configuration.hpp" #include #include #include #include #include #include "MpiEnvironment.hpp" #include #include // helper function to parse Communication Mode cmd args std::istream& operator>>(std::istream& in, CommunicationMode& comm) { std::string buf; in >> buf; const auto& str2comm = StringToCommunicationMode(); auto r = std::find_if(std::begin(str2comm), std::end(str2comm), [&](auto& t) { return t.first == buf; }); if (r == std::end(str2comm)) { throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); } comm = r->second; return in; } auto Configuration::parseArgs(int argc, char* argv[], const MpiEnvironment& env) -> Configuration { namespace po = boost::program_options; Configuration cfg; po::options_description desc{"Allowed options"}; desc.add_options()("help,h", "produce help message") // ("nprocs-x,x", po::value(&cfg.Procs.Cols), "number of processes in x-direction") // ("nprocs-y,y", po::value(&cfg.Procs.Rows), "number of processes in y-direction") // ("generations,g", po::value(&cfg.Generations), "number of generations simulated") // ("commmode,m", po::value(&cfg.CommMode), "Communication Mode. Collective or P2P") // ("inputfile,f", po::value(&cfg.InputFilePath)->required(), "path to wireworld file") // ("outputfile,o", po::value(&cfg.OutputFilePath), "path to output file"); // po::positional_options_description poDesc; poDesc.add("inputfile", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv) .options(desc) // .positional(poDesc) // .run(), vm); if (vm.count("help") > 0 && env.isMaster()) { std::cout << desc << "\n"; } po::notify(vm); } catch (const po::error& err) { MpiReportErrorAbort(err.what()); } // if no dimensions given, use MPI_Dims_create if (cfg.Procs.Cols < 1 || cfg.Procs.Rows < 1) { std::array dims{{static_cast(cfg.Procs.Cols), static_cast(cfg.Procs.Rows)}}; MPI_Dims_create(static_cast(env.worldSize()), // nnodes 2, // ndims dims.data()); // dims cfg.Procs.Cols = static_cast(dims[0]); cfg.Procs.Rows = static_cast(dims[1]); } // validate const auto& totalCellCount = cfg.Procs.Cols * cfg.Procs.Rows; const auto& worldSize = env.worldSize(); if (totalCellCount != static_cast(worldSize)) { MpiReportErrorAbort(boost::str(boost::format("Total number of cells (%d) does not match " "the MPI World size (%d)") % totalCellCount % worldSize)); } return cfg; }