gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
ScannerBit_standalone.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
16 
17 #include <map>
18 #include <vector>
19 #include <string>
20 #include <cstdlib>
21 #include <csignal>
22 #include <unordered_set>
23 #ifdef WITH_MPI
25  #include <mpi.h>
27 #endif
28 
29 #include <stdlib.h>
30 #include <getopt.h>
31 
32 #include "gambit/Logs/logger.hpp"
38 #include "gambit/Utils/version.hpp"
44 
45 using namespace Gambit;
46 using namespace Gambit::Scanner;
47 
49 
50 void do_cleanup()
51 {
52  Gambit::Scanner::Plugins::plugin_info.dump(); // Also calls printer finalise() routine
53 }
54 
55 void sighandler(int)
56 {
58 }
59 
60 inline void scanner_diagnostic()
61 {
62  std::string output = Scanner::Plugins::plugin_info().print_all("scanner");
63  print_to_screen(output, "scanners");
64 }
65 
67 {
68  std::string output = Scanner::Plugins::plugin_info().print_all("objective");
69  print_to_screen(output, "objectives");
70 }
71 
72 inline void prior_diagnostic()
73 {
74  std::string output = Scanner::Plugins::plugin_info().print_priors("priors");
75  print_to_screen(output, "priors");
76 }
77 
78 inline void ff_prior_diagnostic(const std::string& command)
79 {
80  if (command != "priors")
81  {
82  std::string output = Scanner::Plugins::plugin_info().print_priors(command);
83  print_to_screen(output, command);
84  }
85 }
86 
87 inline void ff_scanner_diagnostic(const std::string& command)
88 {
89  std::string output = Scanner::Plugins::plugin_info().print_plugin("scanner", command);
90  print_to_screen(output, command);
91 }
92 
93 inline void ff_test_function_diagnostic(const std::string& command)
94 {
95  std::string output = Scanner::Plugins::plugin_info().print_plugin("objective", command);
96  print_to_screen(output, command);
97 }
98 
99 inline void bail()
100 {
101 cout << "\nusage: ScannerBit_standalone [options] [<command>] "
102  "\n "
103  "\nRun scan: "
104  "\n ScannerBit_standalone -f <inifile> Start a scan using instructions from inifile "
105  "\n e.g.: ScannerBit_standalone -f yaml_files/ScannerBit.yaml "
106  "\n "
107  "\nAvailable commands: "
108  "\n scanners List registered scanners plugins "
109  "\n objectives List registered objective plugins "
110  "\n plugins List all registered plugins "
111  "\n <name> Give info on a plugin or scanner "
112  "\n e.g.: "
113  "\n ScannerBit_standalone MultiNest "
114  "\n "
115  "\nBasic options: "
116  "\n -v/--version Display GAMBIT/ScannerBit version information "
117  "\n -h/--help Display this usage information "
118  "\n -f <inifile> Start scan using <inifile> "
119  "\n -r/--restart Restart the scan defined by <inifile>. Existing "
120  "\n output files for the run will be overwritten. "
121  "\n Default behaviour in the absence of this option is"
122  "\n to attempt to resume the scan from any existing "
123  "\n output. "
124  "\n" << endl << endl;
125  logger().disable();
126  //scan_error().silent_forced_throw();
127 }
128 
129 inline bool arg_parser(std::string &filename, std::vector<std::string> &vec, int argc, char **argv)
130 {
131  int iarg = 0;
132  int index = -1;
133  int file_index;
134  bool resume = true;
135 
136  if (argc < 2)
137  {
138  bail();
139  return EXIT_SUCCESS;
140  }
141 
142  const struct option primary_options[] =
143  {
144  {"version", no_argument, 0, 'v'},
145  {"restart", no_argument, 0, 'r'},
146  {0,0,0,0},
147  };
148 
149  while(iarg != -1)
150  {
151  iarg = getopt_long(argc, argv, "vhrf:", primary_options, &index);
152 
153  switch (iarg)
154  {
155  case 'v':
156  {
157  std::cout << "\nThis is ScannerBit v" + gambit_version() << std::endl;
158  //logger().disable();
159  return EXIT_SUCCESS;
160  }
161  case 'h':
162  case '?':
163  bail();
164  return EXIT_SUCCESS;
165  case 'r':
166  resume = false;
167  break;
168  case 'f':
169  filename = optarg;
170  file_index = optind - 1;
171  break;
172  }
173  }
174 
175  for (int i = 1; i < argc; i++)
176  {
177  if (i != file_index && argv[i][0] != '-')
178  vec.push_back(argv[i]);
179  }
180 
181  return resume;
182 }
183 
184 int main(int argc, char **argv)
185 {
186  signal(SIGTERM, sighandler_soft);
187  signal(SIGINT, sighandler_soft);
188  signal(SIGUSR1, sighandler_soft);
189  signal(SIGUSR2, sighandler_soft);
190 
191  // Default exit behaviour in cases where no exceptions are raised
192  int return_value(EXIT_SUCCESS);
193 
194  #ifdef WITH_MPI
195  bool allow_finalize(true);
196  GMPI::Init();
197  #endif
198 
199  #ifdef WITH_MPI
200  bool use_mpi_abort = true; // Set later via inifile value
201  #endif
202 
203  {
204  #ifdef WITH_MPI
205  // Create an MPI communicator group for use by error handlers
206  GMPI::Comm errorComm;
207  errorComm.dup(MPI_COMM_WORLD,"errorComm"); // duplicates the COMM_WORLD context
208  const int ERROR_TAG=1; // Tag for error messages
209  errorComm.mytag = ERROR_TAG;
210  signaldata().set_MPI_comm(&errorComm); // Provide a communicator for signal handling routines to use.
211  // Create an MPI communicator group for ScannerBit to use
212  GMPI::Comm scanComm;
213  scanComm.dup(MPI_COMM_WORLD,"scanComm"); // duplicates the COMM_WORLD context
214  Scanner::Plugins::plugin_info.initMPIdata(&scanComm);
215  // MPI rank for use in error messages;
216  int rank = scanComm.Get_rank();
217  #else
218  int rank = 0;
219  #endif
220 
221  try
222  {
223  std::string filename = "";
224  std::vector<std::string> args;
225  bool resume = arg_parser(filename, args, argc, argv);
226 
227  if (args.size() > 0)
228  {
229  bool help = true;
230  std::unordered_set<std::string> valid_commands;
231  std::vector<std::string> scanner_names = Scanner::Plugins::plugin_info().print_plugin_names("scanner");
232  std::vector<std::string> objective_names = Scanner::Plugins::plugin_info().print_plugin_names("objective");
233  std::vector<std::string> prior_groups = Scanner::Plugins::plugin_info().list_prior_groups();
234  valid_commands.insert(scanner_names.begin(), scanner_names.end());
235  valid_commands.insert(objective_names.begin(), objective_names.end());
236  valid_commands.insert(prior_groups.begin(), prior_groups.end());
237  valid_commands.insert("priors");
238  valid_commands.insert("objectives");
239  valid_commands.insert("test-functions");
240  valid_commands.insert("scanners");
241 
242  for (auto &&command : args)
243  {
244  if (valid_commands.find(command) != valid_commands.end())
245  {
246  help = false;
247  if (command == "scanners") scanner_diagnostic();
248  if (command == "test-functions" || command == "objectives") test_function_diagnostic();
249  if (command == "priors") prior_diagnostic();
250  ff_scanner_diagnostic(command);
252  ff_prior_diagnostic(command);
253  }
254  }
255 
256  if (help && filename == "")
257  {
258  bail();
259  return EXIT_SUCCESS;
260  }
261  }
262 
263  if (filename != "")
264  {
265  IniParser::Parser iniFile;
266  iniFile.readFile(filename);
267 
268  #ifdef WITH_MPI
269  use_mpi_abort = iniFile.getValueOrDef<bool>(true, "use_mpi_abort");
270  #endif
271 
272  // Initialise the random number generator, letting the RNG class choose its own default.
273  Random::create_rng_engine(iniFile.getValueOrDef<std::string>("default", "rng"));
274 
275  // Set up the printer (redirection of scan output)
276  Printers::PrinterManager printerManager(iniFile.getPrinterNode(),resume);
277  printerInterface = &printerManager;
278 
279  //Make scanner yaml node
280  YAML::Node scanner_node;
281  scanner_node["Scanner"] = iniFile.getScannerNode();
282  scanner_node["Parameters"] = iniFile.getParametersNode();
283  scanner_node["Priors"] = iniFile.getPriorsNode();
284 
285  //Create the master scan manager
286  Scanner::Scan_Manager scan(scanner_node, &printerManager, 0);
287 
288  // Set cleanup function to call during premature shutdown
290 
291  //Do the scan!
292  //logger() << "Starting scan." << EOM;
293  scan.Run();
294 
295  if (rank == 0)
296  std::cout << "ScannerBit has finished successfully!" << std::endl;
297  }
298  }
299 
300  catch (const SilentShutdownException& e)
301  {
302  // No need to do anything, just let program shut down normally from here
303  }
304 
305  catch (const SoftShutdownException& e)
306  {
307  std::ostringstream ss;
308  ss << e.what() << endl;
309  ss << "ScannerBit has performed a controlled early shutdown." << endl;
310  if(rank == 0)
311  std::cout << ss.str();
312  }
313 
314  catch (const HardShutdownException& e)
315  {
316  std::ostringstream ss;
317  ss << e.what() << endl;
318  ss << "ScannerBit has shutdown (but could not finalise or abort MPI)." << endl;
319  if(rank == 0)
320  std::cout << ss.str();
321 
322  return EXIT_SUCCESS;
323  }
324 
325  // Shut down due receipt of MPI emergency shutdown message
326  catch (const MPIShutdownException& e)
327  {
328  std::ostringstream ss;
329  ss << e.what() << endl;
330  ss << "ScannerBit has shutdown due to an error on another process." << endl;
331  if(rank == 0)
332  std::cout << ss.str();
333  #ifdef WITH_MPI
334  signaldata().discard_excess_shutdown_messages();
335  allow_finalize = GMPI::PrepareForFinalizeWithTimeout(use_mpi_abort);
336  #endif
337 
338  return_value = EXIT_FAILURE;
339  }
340 
341  catch (const std::exception& e)
342  {
343  if (rank == 0)
344  {
345  std::cout << endl << " \033[00;31;1mFATAL ERROR\033[00m" << endl << endl;
346  std::cout << "ScannerBit has exited with fatal exception: " << e.what() << endl;
347  }
348  #ifdef WITH_MPI
349  signaldata().broadcast_shutdown_signal();
350  signaldata().discard_excess_shutdown_messages();
351  allow_finalize = GMPI::PrepareForFinalizeWithTimeout(use_mpi_abort);
352  #endif
353 
354  return_value = EXIT_FAILURE;
355  }
356 
357  #ifdef WITH_MPI
358  if (signaldata().shutdown_begun()) signaldata().discard_excess_shutdown_messages();
359  #endif
360  }
361 
362  #ifdef WITH_MPI
363  if (allow_finalize) GMPI::Finalize();
364  #endif
365 
366  return return_value;
367 }
Manager class for creating printer objects.
void bail()
Special exception used during clean exit from diagnostics.
Definition: exceptions.hpp:336
Printers::PrinterManager * printerInterface
void ff_scanner_diagnostic(const std::string &command)
void prior_diagnostic()
int main(int argc, char **argv)
Header for logging classes.
TYPE getValueOrDef(TYPE def, const args &... keys) const
ScannerBit executable-level header file.
Base class for ini-file parsers using yaml-cpp.
Logging access header for GAMBIT.
Special exception used during controlled early shutdown.
Definition: exceptions.hpp:346
Manager class for printers.
Utility Functions for the Gambit Scanner.
void ff_prior_diagnostic(const std::string &command)
virtual const char * what() const
Definition: exceptions.cpp:535
Special exception raised when emergency shutdown triggered via MPI.
Definition: exceptions.hpp:364
void scanner_diagnostic()
YAML::Node getPriorsNode() const
Special exception used during emergency early shutdown.
Definition: exceptions.hpp:355
EXPORT_SYMBOLS SignalData & signaldata()
Retrieve global instance of signal handler options struct.
Class to hold details of scanner plugins and define simple comparison operations on them...
YAML::Node getPrinterNode() const
Utility Functions for the Gambit Scanner.
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Scanner method implementations.
static void create_rng_engine(str, int=-1)
Choose the engine to use for random number generation, based on the contents of the ini file...
void test_function_diagnostic()
Simple header file for turning compiler warnings back on after having included one of the begin_ignor...
Inifile parser base class.
str & gambit_version()
Statically construct a string containing the full GAMBIT version information and return a reference t...
Definition: version.cpp:32
virtual void readFile(str filename)
Read in the YAML file.
void sighandler_soft(int sig)
Signal handler functions.
Utility Functions for the Gambit Scanner.
void ff_test_function_diagnostic(const std::string &command)
Pragma directives to suppress compiler warnings coming from including MPI library headers...
YAML::Node getScannerNode() const
virtual const char * what() const
Definition: exceptions.cpp:530
void dump()
Dump contents for resume.
Loader singleton class for scanner plugins.
std::vector< T > vec(std::vector< T > vector)
Definition: daFunk.hpp:142
YAML::Node getParametersNode() const
Getters for key/value section.
void do_cleanup()
virtual const char * what() const
Definition: exceptions.cpp:540
void sighandler(int)
EXPORT_SYMBOLS pluginInfo plugin_info
Access Functor for plugin info.
bool arg_parser(std::string &filename, std::vector< std::string > &vec, int argc, char **argv)
Version numbering.
TODO: see if we can use this one:
Definition: Analysis.hpp:33
void set_cleanup(void_func f)
Set cleanup function.
void print_to_screen(const std::string &file_in, const std::string &name)