Sierra Toolkit  Version of the Day
UseCaseEnvironment.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010 Sandia Corporation. */
3 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
4 /* license for use of this work by or on behalf of the U.S. Government. */
5 /* Export of this program may require a license from the */
6 /* United States Government. */
7 /*------------------------------------------------------------------------*/
8 
9 #include <iostream>
10 #include <iomanip>
11 
12 #include <stk_util/diag/Writer.hpp>
13 #include <stk_util/diag/PrintTimer.hpp>
14 
15 #include <stk_util/util/Bootstrap.hpp>
16 #include <stk_util/util/IndentStreambuf.hpp>
17 
18 #include <stk_util/parallel/ParallelReduce.hpp>
19 
20 #include <stk_util/use_cases/UseCaseEnvironment.hpp>
21 
22 namespace {
23 
24 namespace bopt = boost::program_options;
25 
26 // Parse command line bit masks and produce -h documentation. (Probably moved to Util at some point)
27 typedef unsigned long OptionMask;
28 
29 struct OptionMaskName
30 {
31  OptionMaskName()
32  : m_name(""),
33  m_mask(0),
34  m_description("")
35  {}
36 
37  OptionMaskName(const std::string &name, const OptionMask &mask, const std::string &description = "No description available")
38  : m_name(name),
39  m_mask(mask),
40  m_description(description)
41  {}
42 
43  virtual ~OptionMaskName()
44  {}
45 
46  std::string m_name;
47  OptionMask m_mask;
48  std::string m_description;
49 };
50 
51 
52 class OptionMaskNameMap: public std::map<std::string, OptionMaskName>
53 {
54 public:
55  void mask(const std::string &name, const OptionMask mask, const std::string &description) {
56  iterator it = find(name);
57  if (it == end())
58  insert(std::make_pair(name, OptionMaskName(name, mask, description)));
59  else {
60  (*it).second.m_mask = mask;
61  (*it).second.m_description = description;
62  }
63  }
64 };
65 
66 class OptionMaskParser
67 {
68 public:
69  typedef OptionMask Mask;
70 
71 public:
76  OptionMaskParser(const std::string &description)
77  : m_optionMaskNameMap(),
78  m_description(description),
79  m_optionMask(0),
80  m_status(true)
81  {}
82 
83  virtual ~OptionMaskParser()
84  {}
85 
86  Mask parse(const char *mask) const;
87 
88  virtual void parseArg(const std::string &name) const;
89 
90  std::string describe() const {
91  std::ostringstream strout;
92  strout << m_description << std::endl;
93  for (OptionMaskNameMap::const_iterator it = m_optionMaskNameMap.begin(); it != m_optionMaskNameMap.end(); ++it)
94  strout << " " << (*it).first << std::setw(14 - (*it).first.size()) << " " << (*it).second.m_description << std::endl;
95  return strout.str();
96  }
97 
98  void mask(const std::string &name, const Mask mask, const std::string &description) {
99  m_optionMaskNameMap.mask(name, mask, description);
100  }
101 
102 protected:
103  OptionMaskNameMap m_optionMaskNameMap;
104  std::string m_description;
105  mutable OptionMask m_optionMask;
106  mutable bool m_status;
107 };
108 
109 
110 OptionMaskParser::Mask
111 OptionMaskParser::parse(
112  const char * mask) const
113 {
114  if (mask) {
115  const std::string mask_string(mask);
116 
117  m_status = true;
118 
119  std::string::const_iterator it0 = mask_string.begin();
120  std::string::const_iterator it1;
121  std::string::const_iterator it2;
122  std::string::const_iterator it3;
123  do {
124  // Trim preceeding spaces
125  while (it0 != mask_string.end() && *it0 == ' ')
126  it0++;
127 
128  if (it0 == mask_string.end())
129  break;
130 
131  for (it1 = it0; it1 != mask_string.end(); ++it1) {
132  if (*it1 == '(' || *it1 == ':' || *it1 == ',')
133  break;
134  }
135 
136  // Trim trailing spaces
137  it2 = it1;
138  while (it2 != it0 && *(it2 - 1) == ' ')
139  --it2;
140 
141  std::string name(it0, it2);
142 
143  // Get argument list
144  if (*it1 == '(') {
145  it2 = it1 + 1;
146 
147  // Trim preceeding spaces
148  while (it2 != mask_string.end() && *it2 == ' ')
149  ++it2;
150 
151  int paren_count = 0;
152 
153  for (; it1 != mask_string.end(); ++it1) {
154  if (*it1 == '(')
155  ++paren_count;
156  else if (*it1 == ')') {
157  --paren_count;
158  if (paren_count == 0)
159  break;
160  }
161  }
162  it3 = it1;
163 
164  // Trim trailing spaces
165  while (it3 != it2 && *(it3 - 1) == ' ')
166  --it3;
167 
168  // Find next argument start
169  for (; it1 != mask_string.end(); ++it1)
170  if (*it1 == ':' || *it1 == ',')
171  break;
172  }
173  else
174  it2 = it3 = it1;
175 
176  const std::string arg(it2, it3);
177 
178  parseArg(name);
179 
180  it0 = it1 + 1;
181  } while (it1 != mask_string.end());
182  }
183 
184  return m_optionMask;
185 }
186 
187 
188 void
189 OptionMaskParser::parseArg(
190  const std::string & name) const
191 {
192  OptionMaskNameMap::const_iterator mask_entry = m_optionMaskNameMap.find(name);
193 
194  if (mask_entry != m_optionMaskNameMap.end()) m_optionMask |= (*mask_entry).second.m_mask;
195  else {
196  Mask mask_hex = 0;
197  std::istringstream mask_hex_stream(name.c_str());
198  if (mask_hex_stream >> std::resetiosflags(std::ios::basefield) >> mask_hex)
199  m_optionMask |= mask_hex;
200  else
201  m_status = false;
202  }
203 }
204 
205 // Build output logging description for binding output streams
206 std::string
207 build_log_description(
208  const bopt::variables_map & vm,
209  const std::string & working_directory,
210  int parallel_rank,
211  int parallel_size)
212 {
213  std::ostringstream output_description;
214 
215  // On processor 0:
216  // [outfile=path] [poutfile=path.n.r] [doutfile=path.n.r] out>{-|cout|cerr|outfile}+pout pout>{null|poutfile} dout>{out|doutfile}
217 
218  // On processor 1..n:
219  // [poutfile=path.n.r] [doutfile=path.n.r] out>pout pout>{null|poutfile} dout>{out|doutfile}
220 
221  std::string out_path = "-";
222  if (vm.count("output-log"))
223  out_path = vm["output-log"].as<std::string>();
224  if (out_path == "-")
225  out_path = "cout";
226 
227  std::string out_ostream;
228 
229  if (!stk_classic::get_log_ostream(out_path))
230  if (out_path.size() && out_path[0] != '/')
231  out_path = working_directory + out_path;
232 
233  if (parallel_rank == 0) {
234  if (!stk_classic::get_log_ostream(out_path)) {
235  output_description << "outfile=\"" << out_path << "\"";
236  out_ostream = "outfile";
237  }
238  else
239  out_ostream = out_path;
240  }
241  else
242  out_ostream = "null";
243 
244  std::string pout_ostream = "null";
245  if (vm.count("pout")) {
246  std::string pout_path = vm["pout"].as<std::string>();
247  if (pout_path == "-") {
248  std::ostringstream s;
249 
250  if (stk_classic::get_log_ostream(out_path))
251  s << working_directory << "sierra.log." << parallel_size << "." << parallel_rank;
252  else
253  s << out_path << "." << parallel_size << "." << parallel_rank;
254  pout_path = s.str();
255  }
256  else if (pout_path.find("/") == std::string::npos && !stk_classic::get_log_ostream(pout_path)) {
257  std::ostringstream s;
258 
259  s << working_directory << pout_path << "." << parallel_size << "." << parallel_rank;
260  pout_path = s.str();
261  }
262 
263  if (!stk_classic::get_log_ostream(pout_path)) {
264  output_description << " poutfile=\"" << pout_path << "\"";
265  pout_ostream = "poutfile";
266  }
267  else
268  pout_ostream = pout_path;
269  }
270 
271  std::string dout_ostream;
272  if (vm.count("dout")) {
273  std::string dout_path = vm["dout"].as<std::string>();
274  if (!dout_path.empty() && stk_classic::is_registered_ostream(dout_path))
275  dout_ostream = dout_path;
276  else {
277  std::ostringstream s;
278  if (dout_path.size() && dout_path[0] != '/')
279  s << working_directory << dout_path << "." << parallel_size << "." << parallel_rank;
280  else
281  s << dout_path << parallel_size << "." << parallel_rank;
282  dout_path = s.str();
283  output_description << " doutfile=\"" << dout_path << "\"";
284  dout_ostream = "doutfile";
285  }
286  }
287  else
288  dout_ostream = "out";
289 
290  if (parallel_rank == 0)
291  output_description << " out>" << out_ostream << "+pout";
292  else
293  output_description << " out>pout";
294 
295  output_description << " pout>" << pout_ostream << " dout>" << dout_ostream;
296 
297  return output_description.str();
298 }
299 
300 OptionMaskParser dw_option_mask("use case diagnostic writer");
301 OptionMaskParser timer_option_mask("use case timers");
302 
303 void
304 bootstrap()
305 {
308  dw_option_mask.mask("search", use_case::LOG_SEARCH, "log search diagnostics");
309  dw_option_mask.mask("transfer", use_case::LOG_TRANSFER, "log transfer diagnostics");
310  dw_option_mask.mask("timer", use_case::LOG_TIMER, "log timer diagnostics");
311 
312  timer_option_mask.mask("mesh", use_case::TIMER_MESH, "mesh operations timers");
313  timer_option_mask.mask("meshio", use_case::TIMER_MESH_IO, "mesh I/O timers");
314  timer_option_mask.mask("transfer", use_case::TIMER_TRANSFER, "transfer timers");
315  timer_option_mask.mask("search", use_case::TIMER_SEARCH, "search timers");
316 
317  boost::program_options::options_description desc("Use case environment options");
318  desc.add_options()
319  ("help,h", "produce help message")
320  ("directory,d", boost::program_options::value<std::string>(), "working directory")
321  ("output-log,o", boost::program_options::value<std::string>(), "output log path")
322  ("pout", boost::program_options::value<std::string>()->implicit_value("-"), "per-processor log file path")
323  ("dout", boost::program_options::value<std::string>()->implicit_value("out"), "diagnostic output stream one of: 'cout', 'cerr', 'out' or a file path")
324  ("dw", boost::program_options::value<std::string>(), dw_option_mask.describe().c_str())
325  ("timer", boost::program_options::value<std::string>(), timer_option_mask.describe().c_str())
326  ("runtest,r", boost::program_options::value<std::string>(), "runtest pid file");
327 
329 }
330 
331 stk_classic::Bootstrap x(bootstrap);
332 
333 } // namespace <empty>
334 
335 namespace use_case {
336 
337 // Output streams
338 std::ostream &
339 out() {
340  static std::ostream s_out(std::cout.rdbuf());
341 
342  return s_out;
343 }
344 
345 
346 std::ostream &
347 pout() {
348  static std::ostream s_pout(std::cout.rdbuf());
349 
350  return s_pout;
351 }
352 
353 
354 std::ostream &
355 dout() {
356  static std::ostream s_dout(std::cout.rdbuf());
357 
358  return s_dout;
359 }
360 
361 
362 std::ostream &
363 tout() {
364  static std::ostream s_tout(std::cout.rdbuf());
365 
366  return s_tout;
367 }
368 
369 
370 std::ostream &
371 dwout() {
372  static stk_classic::indent_streambuf s_dwoutStreambuf(std::cout.rdbuf());
373  static std::ostream s_dwout(&s_dwoutStreambuf);
374 
375  return s_dwout;
376 }
377 
378 
379 // Diagnostic writer
381 dw()
382 {
383  static stk_classic::diag::Writer s_diagWriter(dwout().rdbuf(), 0);
384 
385  return s_diagWriter;
386 }
387 
388 
389 // Message reporting
390 std::ostream &
391 operator<<(
392  std::ostream & os,
393  message_type type)
394 {
395  switch (type & stk_classic::MSG_TYPE_MASK) {
396  case MSG_WARNING:
397  os << "Warning";
398  break;
399  case MSG_FATAL:
400  os << "Fatal error";
401  break;
402  case MSG_INFORMATION:
403  os << "Information";
404  break;
405  case MSG_EXCEPTION:
406  os << "Exception";
407  break;
408  case MSG_PARALLEL_EXCEPTION:
409  os << "Parallel exception";
410  break;
411  }
412  return os;
413 }
414 
415 
416 void
417 report_handler(
418  const char * message,
419  int type)
420 {
421  if (type & stk_classic::MSG_DEFERRED)
422  pout() << "Deferred " << (message_type) type << ": " << message << std::endl;
423 
424  else
425  out() << (message_type) type << ": " << message << std::endl;
426 }
427 
428 
429 // Timers
431 timerSet()
432 {
433  static stk_classic::diag::TimerSet s_timerSet(TIMER_ALL);
434 
435  return s_timerSet;
436 }
437 
438 
439 stk_classic::diag::Timer &timer() {
440  static stk_classic::diag::Timer s_timer = stk_classic::diag::createRootTimer("Use Cases", timerSet());
441 
442  return s_timer;
443 }
444 
445 
446 UseCaseEnvironment::UseCaseEnvironment(
447  int * argc,
448  char *** argv)
449  : m_comm(stk_classic::parallel_machine_init(argc, argv)),
450  m_need_to_finalize(true)
451 {
452  initialize(argc, argv);
453 }
454 
455 UseCaseEnvironment::UseCaseEnvironment(
456  int * argc,
457  char *** argv,
459  : m_comm(comm),
460  m_need_to_finalize(false)
461 {
462  initialize(argc, argv);
463 }
464 
465 void UseCaseEnvironment::initialize(int* argc, char*** argv)
466 {
467  stk_classic::register_log_ostream(std::cout, "cout");
468  stk_classic::register_log_ostream(std::cerr, "cerr");
469 
474 
475  static_cast<stk_classic::indent_streambuf *>(dwout().rdbuf())->redirect(dout().rdbuf());
476 
477  stk_classic::set_report_handler(report_handler);
478 
480 
481  for (int i = 0; i < *argc; ++i) {
482  const std::string s((*argv)[i]);
483  if (s == "-h" || s == "-help" || s == "--help") {
484  std::cout << "Usage: " << (*argv)[0] << " [options...]" << std::endl;
485  std::cout << stk_classic::get_options_description() << std::endl;
486  return; // So application can handle app-specific options.
487  }
488  }
489 
490  // Broadcast argc and argv to all processors.
493 
494  stk_classic::BroadcastArg b_arg(m_comm, *argc, *argv);
495 
496  // Parse broadcast arguments
497  bopt::variables_map &vm = stk_classic::get_variables_map();
498  try {
499  bopt::store(bopt::command_line_parser(b_arg.m_argc, b_arg.m_argv).options(stk_classic::get_options_description()).allow_unregistered().run(), vm);
500  bopt::notify(vm);
501  }
502  catch (std::exception &x) {
504  }
505 
506  // Parse diagnostic messages to display
507  if (vm.count("dw"))
508  dw().setPrintMask(dw_option_mask.parse(vm["dw"].as<std::string>().c_str()));
509 
510  // Parse timer metrics and classes to display
511  stk_classic::diag::setEnabledTimerMetricsMask(stk_classic::diag::METRICS_CPU_TIME | stk_classic::diag::METRICS_WALL_TIME);
512  if (vm.count("timer"))
513  timerSet().setEnabledTimerMask(timer_option_mask.parse(vm["timer"].as<std::string>().c_str()));
514 
515  // Set working directory
516  m_workingDirectory = "./";
517  if (vm.count("directory"))
518  m_workingDirectory = vm["directory"].as<std::string>();
519  if (m_workingDirectory.length() && m_workingDirectory[m_workingDirectory.length() - 1] != '/')
520  m_workingDirectory += "/";
521 
522  std::string output_description = build_log_description(vm, m_workingDirectory, parallel_rank, parallel_size);
523 
524  stk_classic::bind_output_streams(output_description);
525 
526  dout() << "Output log binding: " << output_description << std::endl;
527 
528  // Start use case root timer
529  timer().start();
530 }
531 
532 UseCaseEnvironment::~UseCaseEnvironment()
533 {
535 
536 // Stop use case root timer
537  timer().stop();
538 
539  stk_classic::diag::printTimersTable(out(), timer(), stk_classic::diag::METRICS_CPU_TIME | stk_classic::diag::METRICS_WALL_TIME, false, m_comm);
540 
541  stk_classic::diag::deleteRootTimer(timer());
542 
543  static_cast<stk_classic::indent_streambuf *>(dwout().rdbuf())->redirect(std::cout.rdbuf());
544 
549 
552 
553  if (m_need_to_finalize) {
555  }
556 }
557 
558 bool print_status(stk_classic::ParallelMachine comm, bool success)
559 {
560  int error_flag = success ? 0 : 1;
561  stk_classic::all_reduce( comm , stk_classic::ReduceMax<1>( & error_flag ) );
562  bool all_success = !error_flag;
563 
564  int rank = stk_classic::parallel_machine_rank(comm);
565  if (rank == 0) {
566  std::cout << ( all_success ? "STK_USECASE_PASS" : "Use case failed.") << std::endl;
567  }
568 
569  return all_success;
570 }
571 
572 } // namespace use_case
stk_classic::Bootstrap::bootstrap
static void bootstrap()
Member function bootstrap runs through the stored bootstrap function pointers and executes each funct...
Definition: Bootstrap.cpp:21
stk_classic::Bootstrap
Class Bootstrap serves as a bootstrapping mechanism for products in the sierra toolkit and elsewhere.
Definition: Bootstrap.hpp:35
stk_classic::get_log_ostream
std::ostream * get_log_ostream(const std::string &name)
Function get_log_file_ostream return the output stream of the log file with the specified name from t...
Definition: OutputLog.cpp:263
stk_classic::parallel_machine_size
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
stk_classic::diag::resetiosflags
_resetiosflags resetiosflags(std::ios_base::fmtflags flags)
Function resetiosflags clears the ios flags as a manipulator.
Definition: WriterManip.hpp:148
sierra::tout
std::ostream & tout()
Regression test textual output stream.
Definition: OutputLog.cpp:682
stk_classic::basic_indent_streambuf
Class basic_indent_streambuf implements a output streambuf that performs indentation,...
Definition: IndentStreambuf.hpp:40
sierra::Env::working_directory
const std::string working_directory()
Function working_directory returns the current working directory of this application execution.
Definition: Env.cpp:252
stk_classic::diag::Timer::stop
Timer & stop()
Definition: Timer.cpp:831
stk_classic::parallel_machine_finalize
void parallel_machine_finalize()
parallel_machine_finalize calls MPI_Finalize.
Definition: Parallel.hpp:64
stk_classic::diag::TimerSet
Class TimerSet implements a set of timer classifications. A time classification consists of a bit mas...
Definition: Timer.hpp:117
stk_classic::diag::TimerSet::setEnabledTimerMask
void setEnabledTimerMask(TimerMask timer_mask)
Definition: Timer.hpp:157
stk_classic::ParallelMachine
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
stk_classic::mesh::operator<<
std::ostream & operator<<(std::ostream &s, const Bucket &k)
Print the part names for which this bucket is a subset.
Definition: Bucket.cpp:239
stk_classic::mesh::insert
bool insert(PartVector &v, Part &part)
Insert a part into a properly ordered collection of parts. Returns true if this is a new insertion.
Definition: Part.cpp:85
stk_classic::register_log_ostream
void register_log_ostream(std::ostream &os, const std::string &name)
Function register_log_ostream takes an existing std::ostream and makes it available for output redire...
Definition: OutputLog.cpp:205
stk_classic::all_reduce
void all_reduce(ParallelMachine, const ReduceOp &)
stk_classic::RuntimeDoomedSymmetric
Class RuntimeDoomedSymmetric reports a fatal error message to the report system.
Definition: RuntimeDoomed.hpp:221
stk_classic::unregister_ostream
void unregister_ostream(std::ostream &os)
Function unregister_ostream unregisters an output stream.
Definition: OutputLog.cpp:300
stk_classic::MSG_INFORMATION
Message is informational.
Definition: RuntimeMessage.hpp:57
stk_classic::set_report_handler
REH set_report_handler(REH reh)
Function set_report_handler sets the exception report function to be called when an report_exception(...
Definition: ReportHandler.cpp:82
stk_classic::diag::Writer::setPrintMask
Writer & setPrintMask(PrintMask mask=0)
Member function setPrintMask sets the print output mask.
Definition: Writer.hpp:255
stk_classic::unregister_log_ostream
void unregister_log_ostream(std::ostream &os)
Function register_log_ostream takes an existing std::ostream and makes it available for output redire...
Definition: OutputLog.cpp:228
stk_classic::report_deferred_messages
void report_deferred_messages(ParallelMachine comm)
Function report_deferred_messages aggregates and reports the message on the root processor.
Definition: RuntimeMessage.cpp:291
stk_classic::parallel_machine_init
ParallelMachine parallel_machine_init(int *argc, char ***argv)
parallel_machine_init calls MPI_Init.
Definition: Parallel.hpp:54
stk_classic
Sierra Toolkit.
Definition: AlgorithmRunner.cpp:16
stk_classic::diag::setw
_setw setw(int width)
Function setw sets the width for the next field as a manipulator.
Definition: WriterManip.hpp:44
sierra::dout
std::ostream & dout()
Diagnostic output stream.
Definition: OutputLog.cpp:674
stk_classic::get_options_description
boost::program_options::options_description & get_options_description()
Function get_options_description is a singleton used to store the command line option descriptions fo...
Definition: ProgramOptions.cpp:14
stk_classic::diag::Timer::start
Timer & start()
Definition: Timer.cpp:819
sierra::dwout
std::ostream & dwout()
Diagnostic writer stream.
Definition: OutputLog.cpp:690
sierra::Env::parallel_rank
int parallel_rank()
function parallel_rank returns the rank of this processor in the current mpi communicator.
Definition: Env.cpp:318
stk_classic::register_ostream
void register_ostream(std::ostream &os, const std::string &name)
Function register_ostream registers an output stream with the output stream registry....
Definition: OutputLog.cpp:275
stk_classic::diag::Writer
Class Writer implements a runtime selectable diagnostic output writer to aid in the development and d...
Definition: Writer.hpp:49
stk_classic::mesh::find
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
Definition: Part.cpp:22
sierra::out
std::ostream & out()
Normal output stream.
Definition: OutputLog.cpp:658
sierra::pout
std::ostream & pout()
Per-processor output stream (See RuntimeDeferredx)
Definition: OutputLog.cpp:666
stk_classic::MSG_EXCEPTION
Message is an exception.
Definition: RuntimeMessage.hpp:56
sierra::Env::parallel_size
int parallel_size()
function parallel_size returns the number of processors in the current mpi communicator.
Definition: Env.cpp:314
stk_classic::MSG_DEFERRED
Message is deferred.
Definition: RuntimeMessage.hpp:61
stk_classic::MSG_WARNING
Message is a warning.
Definition: RuntimeMessage.hpp:54
stk_classic::diag::Timer
Class Timer implements a diagnostic timer and timer container for the collection and display of execu...
Definition: Timer.hpp:185
stk_classic::parallel_machine_rank
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
stk_classic::bind_output_streams
void bind_output_streams(const std::string &output_description)
Function bind_output_streams parses the output_description and opens and registers the log streams an...
Definition: OutputLog.cpp:644
stk_classic::is_registered_ostream
bool is_registered_ostream(const std::string &name)
Function is_registered_ostream returns true if an output stream of the specified name is registered.
Definition: OutputLog.cpp:356
stk_classic::BroadcastArg
Class BroadcastArg creates a copy of argc and argv after broadcasting them from processor 0.
Definition: BroadcastArg.hpp:21
stk_classic::get_variables_map
boost::program_options::variables_map & get_variables_map()
Function get_variabel_map is a singleton used to store the variables parsed from the line option desc...
Definition: ProgramOptions.cpp:22
stk_classic::MSG_TYPE_MASK
Mask of levels.
Definition: RuntimeMessage.hpp:59