8 #include <spdlog/spdlog.h> 27 void Runner::setup() {
28 spdlog::set_async_mode(1048576);
31 Runner::Runner(
const vector<string>& overrides_list,
const string& config_file,
32 const RunMode& mode,
int timestep)
33 : m_config_file(config_file), m_mode(mode), m_uses_mpi(false), m_timestep(timestep), m_world_rank(0) {
34 for (
const string& kv: overrides_list) {
36 if (parts.size() != 2) {
37 throw runtime_error(
string(
"Couldn't parse the override ") + kv);
52 m_config.put(
override.first,
override.second);
54 bool has_raw_population =
false;
55 for (
auto& it:
m_config.get_child(
"run.regions")) {
56 if (it.first ==
"region") {
57 pt::ptree& region_config = it.second;
58 string name = region_config.get<
string>(
"<xmlattr>.name");
62 if (region_config.count(
"raw_population") != 0) {
63 has_raw_population =
true;
68 throw runtime_error(
"You need at least one region");
71 "One of the regions does not contain the necessary information to work in a multi region environment (districts, cities, ...)");
74 m_config.get_child(
"run").erase(
"regions");
80 cout <<
"Configuration info:" << endl;
81 cout <<
" - name: " <<
m_name << endl;
83 cout <<
" - regions:" << endl;
85 boost::optional<string> remote = it.second.get_optional<
string>(
"remote");
87 cout <<
" - '" << it.first <<
"' running at " << remote << endl;
89 cout <<
" - '" << it.first <<
"' running locally" << endl;
99 auto output_dir = base_dir /
m_name;
100 bool fresh = fs::create_directory(output_dir);
102 cout <<
"--> Created new output directory at " << output_dir <<
"." << endl;
104 cout <<
"--> Using existing output directory at " << output_dir <<
", will overwrite." << endl;
108 boost::optional<string> remote = it.second.get_optional<
string>(
"remote");
113 throw runtime_error(
"MPI support is not enabled in this build");
119 for (
auto& it: m_region_configs) {
120 cout <<
"\r--> Initializing simulators [" << i <<
"/" << m_region_configs.size() <<
"]";
124 boost::optional<string> remote = it.second.get_optional<
string>(
"remote");
126 string sim_name = sim_config.get<
string>(
"run.regions.region.<xmlattr>.name");
140 if (sim_name ==
"TODO get process ID") {
151 std::map<string, AsyncSimulator*> comm_map;
154 it.second->setCommunicationMap(comm_map);
159 if (
m_uses_mpi and m_local_simulators.size() > 1) {
160 throw runtime_error(
"You can't have multiple simulators in one system when working with MPI");
170 sim->setName(config.get<
string>(
"run.regions.region.<xmlattr>.name"));
174 std::string pathStr =
hdf5Path(name).string();
193 MPI_Init_thread(NULL, NULL, MPI_THREAD_SERIALIZED, &provided);
194 if (provided != MPI_THREAD_SERIALIZED)
throw runtime_error(
"We need serialized thread support in MPI");
201 char processor_name[MPI_MAX_PROCESSOR_NAME];
203 MPI_Get_processor_name(processor_name, &name_len);
206 vector<SimulatorWorldrank> worldranks;
208 boost::optional<string> remote = it.second.get_optional<
string>(
"remote");
212 MPI_Send(&
setup, 1, MPI_INT, 0, 30, MPI_COMM_WORLD);
215 worldranks.emplace_back(it.second.get<
string>(
"<xmlattr>.name"), 0);
223 MPI_Recv(&data, 21, m_setup_message, i, 30, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
224 worldranks.push_back(data);
227 char* name = swr.simulator_name;
228 int rank = swr.world_rank;
231 if (unique_name and unique_rank) {
233 ::value_type(std::string(name), rank));
238 throw runtime_error(to_string(
m_worldranks.size()) +
" simulators but " 239 + to_string(m_region_configs.size()) +
" regions.");
245 MPI_Send(&data, 21, m_setup_message, i, 31,
251 if (i == m_world_size)
continue;
253 MPI_Recv(&data, 21, m_setup_message, i, 31, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
262 MPI_Datatype type[2] = {MPI_CHAR, MPI_INT};
264 int blocklen[2] = {20, 1};
270 MPI_Type_create_struct(2, blocklen, disp, type, &m_setup_message);
271 MPI_Type_commit(&m_setup_message);
277 boost::optional<string> remote = config.get_optional<
string>(
"run.regions.region.remote");
278 m_async_simulators[name] = make_shared<RemoteSimulatorSender>(name, stoi(remote.get()));
288 std::numeric_limits<size_t>::max(),
289 std::numeric_limits<size_t>::max());
294 auto checkpointing =
m_config.get_child_optional(
"run.outputs.checkpointing");
296 int freq = checkpointing.get().get<
int>(
"<xmlattr>.frequency");
305 saver->forceSave(sim);
309 auto visualization =
m_config.get_child_optional(
"run.outputs.visualization");
315 std::string vis_output_dir = fs::system_complete(
m_output_dir / (
string(
"vis_") + sim.
getName())).string();
316 auto vis_saver = make_shared<ClusterSaver>(
"vis_output",
"vis_pop_output",
"vis_facility_output",
320 vis_saver->update(sim);
326 map<string, vector<unsigned int>> cases;
333 cout <<
"--> We are running locally,";
334 cout <<
" printing infected/adopted." << endl;
335 int num_days =
m_config.get<
int>(
"run.num_days");
336 cout << endl <<
" day | ";
340 for (
int i = 15 - it.first.size(); i > 0; i--) cout <<
' ';
344 cout << endl <<
"-----+";
345 for (
auto& it: m_region_configs) {
346 cout <<
"-----------------+";
355 for (
int day = start_day; day <
m_timestep + num_days; day++) {
356 cout << setw(4) << day <<
" | ";
358 vector<SimulatorStatus> results =
m_coord->timeStep();
362 cout << setw(7) << results[i].infected <<
" " << setw(7) << results[i].adopted <<
" | ";
363 cases[it.first].push_back(results[i].infected);
377 for (
int i = 0; i <
m_world_size; i++) MPI_Send(
nullptr, 0, MPI_INT, i, 10, MPI_COMM_WORLD);
391 auto cases_conf =
m_config.get_child_optional(
"run.outputs.cases");
392 auto person_conf =
m_config.get_child_optional(
"run.outputs.persons");
397 .print(cases[it.first]);
402 .print(it.second->getPopulation());
413 for (
const string& name: names) {
417 new_config.add_child(
"run.regions", regions);
422 return fs::system_complete(
m_output_dir / (
string(
"cp_") + name +
".h5"));
static std::string replace(std::string source, std::string from, std::string to)
Replace all occurences of a string with another.
static boost::filesystem::path getOutputDir()
Utility method: get the path to the output directory.
Interface for install directory queries.
std::shared_ptr< spdlog::logger > m_logger
std::map< std::string, std::string > m_overrides
Produces a file with daily cases count.
boost::filesystem::path m_output_dir
std::map< std::string, std::shared_ptr< Hdf5Saver > > m_hdf5_savers
std::map< std::string, shared_ptr< AsyncSimulator > > m_async_simulators
void loadFromTimestep(unsigned int timestep, shared_ptr< Simulator > sim) const
Load from timestep, if the specified timestep is present in the hdf5 file.
void initOutputs(Simulator &sim)
void registerObserver(const std::shared_ptr< U > &u, CallbackType f)
Time Dependent Person DataType.
std::shared_ptr< Coordinator > m_coord
Conversion from or to string.
virtual void update(const Simulator &sim)
boost::filesystem::path hdf5Path(const string &name)
virtual void update(const Simulator &sim)
Update function which is called by the subject.
Setup for the simulator and configuration tree.
std::map< std::string, std::shared_ptr< ClusterSaver > > m_vis_savers
Provides a stopwatch interface to time: it accumulates time between start/stop pairs.
std::map< std::string, boost::property_tree::ptree > m_region_configs
Header for the CasesFile class.
std::map< std::string, shared_ptr< Simulator > > m_local_simulators
Header for the SimulatorBuilder class.
std::string m_travel_schedule
std::vector< std::string > m_region_order
static std::string trim(std::string const &source, std::string const &t=" ")
Trim characters at both ends of string.
boost::property_tree::ptree getConfig()
Main class that contains and direct the virtual world.
std::string m_config_file
Produces a file with daily cases count.
std::shared_ptr< Simulator > addLocalSimulator(const string &name, const boost::property_tree::ptree &config)
Header for the PersonFile class.
static std::shared_ptr< Simulator > build(const boost::property_tree::ptree &pt_config)
Build simulator.
boost::property_tree::ptree getRegionsConfig(const std::vector< string > &names)
boost::property_tree::ptree m_config
std::shared_ptr< AsyncSimulator > addRemoteSimulator(const string &name, const boost::property_tree::ptree &config)
static std::vector< std::string > split(const std::string &str, const std::string &delimiters)
Split a string (in order of occurence) by splitting it on the given delimiters.
boost::bimap< string, int > m_worldranks
unsigned int getLastSavedTimestep() const
Retrieves the last saved timestep index in the hdf5 file.
boost::property_tree::ptree m_config_pt
Configuration property tree.