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