OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
IpplInfo.cpp
Go to the documentation of this file.
1 //
2 // IpplInfo has the following capabilities:
3 // 1) It initializes all globally-used Ippl variables, such as the
4 // Communicate class and other manager classes;
5 // 2) It parses command-line arguments to determine how to configure the
6 // global state of the Ippl application;
7 // 3) It properly selects and configures the Communicate class, generally
8 // resulting in initialization of the parallel machine;
9 // 4) It offers to the user a single class with access member functions to
10 // query for information about the Ippl application (such as what is
11 // the Communicate class instance to use, how many processors are there
12 // in the current run, etc.)
13 //
14 // Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
15 //
16 // All rights reserved
17 //
18 // This file is part of OPAL.
19 //
20 // OPAL is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
27 //
28 #include "Utility/IpplInfo.h"
29 #include "Utility/Inform.h"
30 #include "Utility/IpplStats.h"
31 #include "Utility/PAssert.h"
33 #include "Utility/vmap.h"
35 #include "Message/CommCreator.h"
36 #include "Message/Communicate.h"
37 
38 #include "IpplVersions.h"
39 
40 #include <unistd.h>
41 #include <cstdio>
42 #include <csignal>
43 
45 // public static members of IpplInfo, initialized to default values
52 
54  if (Comm == 0)
55  Comm = new Communicate();
56  if (Stats == 0)
57  Stats = new IpplStats();
58  if (Info == 0)
59  Info = new Inform("Ippl");
60  if (Warn == 0)
61  Warn = new Inform("Warning", std::cerr);
62  if (Error == 0)
63  Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
64  if (Debug == 0)
65  Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
66 }
67 
69  delete Comm;
70  delete Stats;
71  delete Info;
72  delete Warn;
73  delete Error;
74  delete Debug;
75 
76  Comm = 0;
77  Stats = 0;
78  Info = 0;
79  Warn = 0;
80  Error = 0;
81  Debug = 0;
82 }
83 
84 std::stack<StaticIpplInfo> IpplInfo::stashedStaticMembers;
85 
86 // should we use the optimization of deferring guard cell fills until
87 // absolutely needed? Can be changed to true by specifying the
88 // flag --defergcfill
90 
91 // should we use the compression capabilities in {[Bare]Field,LField}? Can be
92 // changed to false by specifying the flag --nofieldcompression
93 bool IpplInfo::noFieldCompression = false;
94 
95 // private static members of IpplInfo, initialized to default values
96 MPI_Comm IpplInfo::communicator_m = MPI_COMM_WORLD;
97 int IpplInfo::NumCreated = 0;
98 bool IpplInfo::CommInitialized = false;
99 bool IpplInfo::PrintStats = false;
100 bool IpplInfo::NeedDeleteComm = false;
101 int IpplInfo::MyArgc = 0;
102 char **IpplInfo::MyArgv = 0;
103 int IpplInfo::MyNode = 0;
104 int IpplInfo::TotalNodes = 1;
105 int IpplInfo::NumSMPs = 1;
106 int* IpplInfo::SMPIDList = 0;
107 int* IpplInfo::SMPNodeList = 0;
108 bool IpplInfo::UseChecksums = false;
109 bool IpplInfo::Retransmit = false;
110 int IpplInfo::MaxFFTNodes = 0;
111 int IpplInfo::ChunkSize = 512*1024; // 512K == 64K doubles
112 bool IpplInfo::PerSMPParallelIO = false;
113 bool IpplInfo::offsetStorage = false;
114 bool IpplInfo::extraCompressChecks = false;
115 
117 // print out current state to the given output stream
118 std::ostream& operator<<(std::ostream& o, const IpplInfo&) {
119  o << "------------------------------------------\n";
120  o << "IPPL Framework Application Summary:\n";
121  o << " Running on node " << IpplInfo::myNode();
122  o << ", out of " << IpplInfo::getNodes() << " total.\n";
123  o << " Number of SMPs: " << IpplInfo::getSMPs() << "\n";
124  o << " Relative SMP node: " << IpplInfo::mySMPNode();
125  o << ", out of " << IpplInfo::getSMPNodes(IpplInfo::mySMP());
126  o << " nodes.\n";
127  o << " Communication method: " << IpplInfo::Comm->name() << "\n";
128  o << " Disc read chunk size: " << IpplInfo::chunkSize() << " bytes.\n";
129  o << " Deferring guard cell fills? ";
130  o << IpplInfo::deferGuardCellFills << "\n";
131  o << " Turning off Field compression? ";
132  o << IpplInfo::noFieldCompression << "\n";
133  o << " Offsetting storage? ";
134  o << IpplInfo::offsetStorage << "\n";
135  o << " Using extra compression checks in expressions? ";
136  o << IpplInfo::extraCompressChecks << "\n";
137  o << " Use per-SMP parallel IO? ";
138  o << IpplInfo::perSMPParallelIO() << "\n";
139  o << " Computing message CRC checksums? ";
140  o << IpplInfo::useChecksums() << "\n";
141  o << " Retransmit messages on error (only if checkums on)? ";
142  o << IpplInfo::retransmit() << "\n";
143 
144  o << " Elapsed wall-clock time (in seconds): ";
145  o << IpplInfo::Stats->getTime().clock_time() << "\n";
146  o << " Elapsed CPU-clock time (in seconds) : ";
147  o << IpplInfo::Stats->getTime().cpu_time() << "\n";
148  o << "------------------------------------------\n";
149  return o;
150 }
151 
152 
154 // Constructor 1: parse argc, argv, and create proper Communicate object
155 // The second argument controls whether the IPPL-specific command line
156 // arguments are stripped out (the default) or left in (if the setting
157 // is IpplInfo::KEEP).
158 IpplInfo::IpplInfo(int& argc, char**& argv, int removeargs, MPI_Comm mpicomm) {
159 
160  int i; // loop variables
161  int connectoption = (-1); // for connection method option
162  int retargc; // number of args to return to caller
163  char **retargv; // arguments to return
164  bool printsummary = false; // print summary at end of constructor
165 
166  //Inform dbgmsg("IpplInfo(argc,argv)", INFORM_ALL_NODES);
167 
168  // determine whether we should strip out ippl-specific arguments, or keep
169  bool stripargs = (removeargs != KEEP);
170 
171  communicator_m = mpicomm;
172 
173  if (NumCreated == 0) {
174  Comm = new Communicate();
175  Stats = new IpplStats();
176  Info = new Inform("Ippl");
177  Warn = new Inform("Warning", std::cerr);
178  Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
179  Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
180  }
181  // You can only specify argc, argv once; if it is done again, print a warning
182  // and continue as if we had not given argc, argv.
183  if ( CommInitialized ) {
184  // ADA WARNMSG("Attempt to create IpplInfo with argc, argv again." << endl);
185  //WARNMSG("Using previous argc,argv settings." << endl);
186  } else {
187  // dbgmsg << "Starting initialization: argc = " << argc << ", " << endl;
188  // for (unsigned int dbgi=0; dbgi < argc; ++dbgi)
189  // dbgmsg << " argv[" << dbgi << "] = '" << argv[dbgi] << "'" << endl;
190 
191  // first make a pass through the arguments, figure out whether we should
192  // run in parallel, and start up the parallel environment. After this,
193  // process all the other cmdline args
194  std::string commtype;
195  bool startcomm = false;
196  bool comminit = true; // do comm. system's init call
197  int nprocs = (-1); // num of processes to start; -1 means default
198 
199 
200  /*
201  if no argument is given, we assume mpi as
202  communication method
203  */
204  commtype = std::string("mpi");
205  startcomm = true;
206 
207  for (i=1; i < argc; ++i) {
208  if ( ( strcmp(argv[i], "--processes") == 0 ) ||
209  ( strcmp(argv[i], "-procs") == 0 ) ) {
210  // The user specified how many processes to use. This may not be useful
211  // for all communication methods.
212  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
213  nprocs = atoi(argv[++i]);
214  else
215  param_error(argv[i],
216  "Please specify a positive number of processes", 0);
217  } else if ( ( strcmp(argv[i], "--commlib") == 0 ) ||
218  ( strcmp(argv[i], "-comm") == 0 ) ) {
219  // The user specified what kind of comm library to use
220  if ( (i + 1) < argc && argv[i+1][0] != '-' ) {
221  commtype = argv[++i];
222  startcomm = true;
223  } else {
224  param_error(argv[i], "Please use one of: ",
226  startcomm = false;
227  }
228 
229  } else if ( strcmp(argv[i], "--nocomminit") == 0 ) {
230  // The user requested that we do not let the run-time system call
231  // whatever initialization routine it might have (like MPI_Init).
232  // This is in case another agency has already done the initialization.
233  comminit = false;
234  }
235  }
236 
237  // create Communicate object now.
238  // dbgmsg << "Setting up parallel environment ..." << endl;
239  if (startcomm && nprocs != 0 && nprocs != 1) {
240  // dbgmsg << " commlibarg=" << commtype << endl;
241  // dbgmsg << ", nprocs=" << nprocs << endl;
242  Communicate *newcomm = CommCreator::create(commtype.c_str(),
243  argc, argv,
244  nprocs, comminit, mpicomm);
245 
246  if (newcomm == 0) {
247  if (CommCreator::supported(commtype.c_str()))
248  param_error("--commlib", "Could not initialize this ",
249  "communication library.", commtype.c_str());
250  else if (CommCreator::known(commtype.c_str()))
251  param_error("--commlib", "This communication library is not ",
252  "available.", commtype.c_str());
253  else
254  param_error("--commlib", "Please use one of: ",
256  } else {
257  // success, we have a new comm object
258  NeedDeleteComm = true;
259  delete Comm;
260  Comm = newcomm;
261 
262  // cache our node number and node count
263  MyNode = Comm->myNode();
264  TotalNodes = Comm->getNodes();
265  find_smp_nodes();
266 
267  // advance the default random number generator
268  IpplRandom.AdvanceSeed(Comm->myNode());
269 
270  // dbgmsg << " Comm creation successful." << endl;
271  // dbgmsg << *this << endl;
272  }
273  }
274 
275  // dbgmsg << "After comm init: argc = " << argc << ", " << endl;
276  // for (unsigned int dbgi=0; dbgi < argc; ++dbgi)
277  // dbgmsg << " argv[" << dbgi << "] = '" << argv[dbgi] << "'" << endl;
278 
279  // keep track of which arguments we do no use; these are returned
280  retargc = 1;
281  retargv = new char*[argc];
282  retargv[0] = argv[0]; // we always return arg 0 (the exec. name)
283 
284  // if we're not stripping out arguments, just save all the args
285  if (!stripargs)
286  for (i=1; i < argc; ++i)
287  retargv[retargc++] = argv[i];
288 
289 
290  // Parse command-line options, looking for ippl options. When found,
291  // save their suggested values and use them at the end to create data, etc.
292  for (i=1; i < argc; ++i) {
293  if ( ( strcmp(argv[i], "--processes") == 0 ) ||
294  ( strcmp(argv[i], "-procs") == 0 ) ) {
295  // handled above
296  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
297  ++i;
298 
299  } else if ( ( strcmp(argv[i], "--nocomminit") == 0 ) ) {
300  // handled above, nothing to do here but skip the arg
301 
302  } else if ( ( strcmp(argv[i], "--summary") == 0 ) ) {
303  // set flag to print out summary of Ippl library settings at the
304  // end of this constructor
305  printsummary = true;
306 
307  } else if ( ( strcmp(argv[i], "--ipplversion") == 0 ) ) {
308  printVersion();
309  std::string options = compileOptions();
310  std::string header("Compile-time options: ");
311  while (options.length() > 58) {
312  std::string line = options.substr(0, 58);
313  size_t n = line.find_last_of(' ');
314  INFOMSG(header << line.substr(0, n) << "\n");
315 
316  header = std::string(22, ' ');
317  options = options.substr(n + 1);
318  }
319  INFOMSG(header << options << endl);
320  exit(0);
321 
322  } else if ( ( strcmp(argv[i], "--checksums") == 0 ) ||
323  ( strcmp(argv[i], "--checksum") == 0 ) ) {
324  UseChecksums = true;
325 
326  } else if ( ( strcmp(argv[i], "--retransmit") == 0 ) ) {
327  Retransmit = true;
328 
329  } else if ( ( strcmp(argv[i], "--ipplversionall") == 0 ) ||
330  ( strcmp(argv[i], "-vall") == 0 ) ) {
331  printVersion();
332  std::string options = compileOptions();
333  std::string header("Compile-time options: ");
334  while (options.length() > 58) {
335  std::string line = options.substr(0, 58);
336  size_t n = line.find_last_of(' ');
337  INFOMSG(header << line.substr(0, n) << "\n");
338 
339  header = std::string(22, ' ');
340  options = options.substr(n + 1);
341  }
342  INFOMSG(header << options << endl);
343  exit(0);
344 
345  } else if ( ( strcmp(argv[i], "--time") == 0 ) ||
346  ( strcmp(argv[i], "-time") == 0 ) ||
347  ( strcmp(argv[i], "--statistics") == 0 ) ||
348  ( strcmp(argv[i], "-stats") == 0 ) ) {
349  // The user specified that the program stats be printed at
350  // the end of the program.
351  PrintStats = true;
352 
353  } else if ( ( strcmp(argv[i], "--info") == 0 ) ) {
354  // Set the output level for informative messages.
355  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
356  Info->setOutputLevel(atoi(argv[++i]));
357  else
358  param_error(argv[i],
359  "Please specify an output level from 0 to 5", 0);
360 
361  } else if ( ( strcmp(argv[i], "--warn") == 0 ) ) {
362  // Set the output level for warning messages.
363  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
364  Warn->setOutputLevel(atoi(argv[++i]));
365  else
366  param_error(argv[i],
367  "Please specify an output level from 0 to 5", 0);
368 
369  } else if ( ( strcmp(argv[i], "--error") == 0 ) ) {
370  // Set the output level for error messages.
371  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
372  Error->setOutputLevel(atoi(argv[++i]));
373  else
374  param_error(argv[i],
375  "Please specify an output level from 0 to 5", 0);
376 
377  } else if ( ( strcmp(argv[i], "--debug") == 0 ) ) {
378  // Set the output level for debug messages.
379  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 )
380  Debug->setOutputLevel(atoi(argv[++i]));
381  else
382  param_error(argv[i],
383  "Please specify an output level from 0 to 5", 0);
384 
385  } else if ( ( strcmp(argv[i], "--connect") == 0 ) ) {
386  // Set the default external connection method
387  if ( (i + 1) < argc && argv[i+1][0] != '-' )
388  connectoption = ++i;
389  else
390  param_error(argv[i], "Please use one of: ",
392 
393  } else if ( ( strcmp(argv[i], "--connectnodes") == 0 ) ) {
394  // Set the number of nodes that are used in connections, by default
395  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
396  DataConnectCreator::setDefaultNodes(atoi(argv[++i]));
397  else
398  param_error(argv[i],
399  "Please specify a number of nodes for connections > 0",
400  0);
401 
402  } else if ( ( strcmp(argv[i], "--commlib") == 0 ) ||
403  ( strcmp(argv[i], "-comm") == 0 ) ) {
404  // handled above
405  if ( (i + 1) < argc && argv[i+1][0] != '-' )
406  ++i;
407 
408  } else if ( strcmp(argv[i], "--profile") == 0 ) {
409  // handled above in
410  if ( (i + 1) < argc && argv[i+1][0] != '-' )
411  ++i;
412 
413  } else if ( ( strcmp(argv[i], "--persmppario") == 0 ) ) {
414  // Turn on the ability to use per-smp parallel IO
415  PerSMPParallelIO = true;
416 
417  } else if ( ( strcmp(argv[i], "--nopersmppario") == 0 ) ) {
418  // Turn off the ability to use per-smp parallel IO
419  PerSMPParallelIO = false;
420 
421  } else if ( ( strcmp(argv[i], "--chunksize") == 0 ) ) {
422  // Set the I/O chunk size, used to limit how many items
423  // are read in or written to disk at one time.
424  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) >= 0 ) {
425  ChunkSize = atoi(argv[++i]);
426  char units = static_cast<char>(toupper(argv[i][strlen(argv[i])-1]));
427  if (units == 'K')
428  ChunkSize *= 1024;
429  else if (units == 'M')
430  ChunkSize *= 1024*1024;
431  else if (units == 'G')
432  ChunkSize *= 1024*1024*1024;
433  } else {
434  param_error(argv[i],
435  "Please specify a timeout value (in seconds)", 0);
436  }
437  } else if ( ( strcmp(argv[i], "--defergcfill") == 0 ) ) {
438  // Turn on the defer guard cell fill optimization
439  deferGuardCellFills = true;
440 
441  } else if ( ( strcmp(argv[i], "--offsetstorage") == 0 ) ) {
442  // Turn on the offset-storage modification to LFields
443  offsetStorage = true;
444 
445  } else if ( ( strcmp(argv[i], "--extracompcheck") == 0 ) ) {
446  // Turn on the extra compression checks in expressions
447  extraCompressChecks = true;
448 
449  } else if ( ( strcmp(argv[i], "--nofieldcompression") == 0 ) ) {
450  // Turn off compression in the Field classes
451  noFieldCompression = true;
452 
453  } else if ( ( strcmp(argv[i], "--directio") == 0 ) ) {
454  // Turn on the use of Direct-IO, if possible
455  param_error(argv[i],
456  "Direct-IO is not available in this build of IPPL", 0);
457  } else if ( ( strcmp(argv[i], "--maxfftnodes") == 0 ) ) {
458  // Limit the number of nodes that can participate in FFT operations
459  if ( (i + 1) < argc && argv[i+1][0] != '-' && atoi(argv[i+1]) > 0 )
460  MaxFFTNodes = atoi(argv[++i]);
461  else
462  param_error(argv[i],
463  "Please specify a maximum number of FFT nodes > 0", 0);
464 
465  } else if ( ( strcmp(argv[i], "--ipplhelp") == 0 ) ||
466  ( strcmp(argv[i], "-h") == 0 ) ||
467  ( strcmp(argv[i], "-?") == 0 ) ) {
468  // print out summary of command line switches and exit
469  INFOMSG("Usage: " << argv[0] << " [<option> <option> ...]\n");
470  INFOMSG(" The possible values for <option> are:\n");
471  printHelp();
472  INFOMSG(" --ipplversion : Print a brief version summary.\n");
473  INFOMSG(" --ipplversionall : Print a detailed version summary.\n");
474  INFOMSG(" --ipplhelp : Display this command-line summary.\n");
475  INFOMSG(endl);
476  exit(0);
477 
478  } else {
479  // Unknown option; just ignore it.
480  if (stripargs)
481  retargv[retargc++] = argv[i];
482  }
483  }
484 
485  // We can get on with creating and initializing all globally-used objects.
486 
487  // Select the default connection method
488  if ( connectoption >= 0 ) {
489  if ( ! DataConnectCreator::setDefaultMethod(argv[connectoption]) ) {
490  if (DataConnectCreator::supported(argv[connectoption]))
491  param_error(argv[connectoption - 1], "Could not initialize this ",
492  "connection.", argv[connectoption]);
493  else if (DataConnectCreator::known(argv[connectoption]))
494  param_error(argv[connectoption - 1],"This connection method is not ",
495  "available.", argv[connectoption]);
496  else
497  param_error(argv[connectoption - 1], "Please use one of: ",
499  }
500  }
501 
502  // indicate back to the caller which arguments are left
503  MyArgc = retargc;
504  MyArgv = retargv;
505  if (stripargs) {
506  argc = retargc;
507  argv = retargv;
508  }
509 
510  // Inform dbgmsg("IpplInfo::IpplInfo", INFORM_ALL_NODES);
511  // dbgmsg << "Created IpplInfo. node = " << MyNode << " out of ";
512  // dbgmsg << TotalNodes << ", commlib = " << Comm->name() << endl;
513 
514  // now, at end, start the timer running, and print out a summary if asked
515  Stats->getTime().stop();
516  Stats->getTime().clear();
517  Stats->getTime().start();
518  }
519 
520  // indicate we've created one more Ippl object
521  CommInitialized = true;
522  NumCreated++;
523 
524  // At the very end, print out a summary if requested
525  if (printsummary)
526  INFOMSG(*this << endl);
527 }
528 
529 
531 // Constructor 2: default constructor.
533  if (NumCreated == 0) {
534  Comm = new Communicate();
535  Stats = new IpplStats();
536  Info = new Inform("Ippl");
537  Warn = new Inform("Warning", std::cerr);
538  Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
539  Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
540  }
541 
542  // just indicate we've also been created
543  NumCreated++;
544 }
545 
546 
548 // Constructor 3: copy constructor.
550  if (NumCreated == 0) {
551  Comm = new Communicate();
552  Stats = new IpplStats();
553  Info = new Inform("Ippl");
554  Warn = new Inform("Warning", std::cerr);
555  Error = new Inform("Error", std::cerr, INFORM_ALL_NODES);
556  Debug = new Inform("**DEBUG**", std::cerr, INFORM_ALL_NODES);
557  }
558 
559  // just indicate we've also been created
560  NumCreated++;
561 }
562 
563 
565 // Destructor: need to delete comm library if this is the last IpplInfo
567  // indicate we have one less instance; if this is the last one,
568  // close communication and clean up
569  // Inform dbgmsg("IpplInfo::~IpplInfo", INFORM_ALL_NODES);
570  // dbgmsg << "In destructor: Current NumCreated = " << NumCreated << endl;
571 
572  if ((--NumCreated) == 0) {
573  // at end of program, print statistics if requested to do so
574  if (PrintStats) {
575  Inform statsmsg("Stats", INFORM_ALL_NODES);
576  statsmsg << *this;
577  printStatistics(statsmsg);
578  }
579 
580  // Delete the communications object, if necessary, to shut down parallel
581  // environment
582  if (NeedDeleteComm) {
583  // dbgmsg << " Deleting comm object, since now NumCreated = ";
584  // dbgmsg << NumCreated << endl;
585  delete Comm;
586  Comm = 0;
587  NeedDeleteComm = false;
588  }
589  CommInitialized = false;
590 
591  // delete other dynamically-allocated static objects
592  delete [] MyArgv;
593  if (SMPIDList != 0) {
594  delete [] SMPIDList;
595  }
596  if (SMPNodeList != 0) {
597  delete [] SMPNodeList;
598  }
599  delete Stats;
600 
601  MyArgv = 0;
602  SMPIDList = 0;
603  SMPNodeList = 0;
604  Stats = 0;
605  }
606 }
607 
608 
610 // equal operator
612  // nothing to do, we don't even need to indicate we've made another
613  return *this;
614 }
615 
616 void IpplInfo::abort(const char *msg) {
617  // print out message, if one was provided
618  if (msg != 0) {
619  ERRORMSG(msg << endl);
620  }
621 
622  // print out final stats, if necessary
623  if (PrintStats) {
624  Inform statsmsg("Stats", INFORM_ALL_NODES);
625  statsmsg << IpplInfo();
626  printStatistics(statsmsg);
627  }
628 
629  // delete communication object, if necessary
630  if (NeedDeleteComm) {
631  NeedDeleteComm = false;
632  delete Comm;
633  Comm = 0;
634  }
635 
636  // that's it, folks this error will be propperly catched in the main
637  throw std::runtime_error("Error form IpplInfo::abort");
638 }
639 
640 
642 // Signal to ALL the nodes that we should exit or abort. If we abort,
643 // a core file will be produced. If we exit, no core file will be made.
644 // The node which calls abortAllNodes will print out the given message;
645 // the other nodes will print out that they are aborting due to a message
646 // from this node.
647 void IpplInfo::abortAllNodes(const char *msg) {
648  // print out message, if one was provided
649  if (msg != 0) {
650  ERRORMSG(msg << endl);
651  }
652 
653  // print out final stats, if necessary
654  if (PrintStats) {
655  Inform statsmsg("Stats", INFORM_ALL_NODES);
656  statsmsg << IpplInfo();
657  printStatistics(statsmsg);
658  }
659 
660  // broadcast out the kill message, if necessary
661  if (getNodes() > 1)
662  Comm->broadcast_others(new Message, IPPL_ABORT_TAG);
663 
664  throw std::runtime_error("Error form IpplInfo::abortAllNodes");
665 
666 }
667 
669 // getNodes: return the number of 'Nodes' in use for the computation
671  return TotalNodes;
672 }
673 
674 
676 // getContexts: return the number of 'Contexts' for the given node
677 int IpplInfo::getContexts(const int n) {
678  return Comm->getContexts(n);
679 }
680 
681 
683 // getProcesses: return the number of 'Processes' for the given Node and Context
684 int IpplInfo::getProcesses(const int n, const int c) {
685  return Comm->getProcesses(n, c);
686 }
687 
688 
690 // myNode: return which Node we are running on right now
692  return MyNode;
693 }
694 
695 
697 // getSMPs: return number of SMP's (each of which may be running
698 // several processes)
700  return NumSMPs;
701 }
702 
703 
705 // getSMPNodes: return number of nodes on the SMP with the given index
706 int IpplInfo::getSMPNodes(int smpindx) {
707  int num = 0;
708  if (SMPIDList == 0) {
709  num = 1;
710  } else {
711  for (int i=0; i < TotalNodes; ++i)
712  if (SMPIDList[i] == smpindx)
713  num++;
714  }
715  return num;
716 }
717 
718 
720 // mySMP: return ID of my SMP (numbered 0 ... getSMPs() - 1)
722  return (SMPIDList != 0 ? SMPIDList[MyNode] : 0);
723 }
724 
725 
727 // mySMPNode: return relative node number within the nodes on our SMP
729  return (SMPNodeList != 0 ? SMPNodeList[MyNode] : 0);
730 }
731 
732 
734 // printVersion: print out a version summary. If the argument is true,
735 // print out a detailed listing, otherwise a summary.
737  INFOMSG("IPPL Framework version " << version() << endl);
738  INFOMSG("Last build date: " << compileDate() << " by user ");
739  INFOMSG(compileUser() << endl);
740  INFOMSG("Built for machine: " << compileMachine() << endl);
741 }
742 
743 
745  INFOMSG(" --summary : Print IPPL lib summary at start.\n");
746  INFOMSG(" --processes <n> : Number of parallel nodes to use.\n");
747  INFOMSG(" --commlib <x> : Selects a parallel comm. library.\n");
748  INFOMSG(" <x> = ");
750  INFOMSG(" --nocomminit : IPPL does not do communication\n");
751  INFOMSG(" initialization, assume already done.\n");
752  INFOMSG(" --connect <x> : Select external connection method.\n");
753  INFOMSG(" <x> = ");
755  INFOMSG(" --time : Show total time used in execution.\n");
756  INFOMSG(" --notime : Do not show timing info (default).\n");
757  INFOMSG(" --info <n> : Set info message level. 0 = off.\n");
758  INFOMSG(" --warn <n> : Set warning message level. 0 = off.\n");
759  INFOMSG(" --error <n> : Set error message level. 0 = off.\n");
760  INFOMSG(" --debug <n> : Set debug message level. 0 = off.\n");
761  /*#ifdef PROFILING_ON
762  INFOMSG(" --profile <gr> : Enable profiling for groups (e.g., M+P+io) \n");
763  INFOMSG(" M - Message, P - Pete, V - Viz, A - Assign, I - IO\n");
764  INFOMSG(" F - Field, L - Layout, S - Sparse, D - Domainmap \n");
765  INFOMSG(" Ut - Utility, R - Region, Ff - FFT \n");
766  INFOMSG(" U - User, 1 - User1, 2 - User2, 3 - User3, 4 - User4\n");
767 
768  #endif*/ //PROFILING_ON
769  INFOMSG(" --defergcfill : Turn on deferred guard cell fills.\n");
770  INFOMSG(" --nofieldcompression: Turn off compression in the Field classes.\n");
771  INFOMSG(" --offsetstorage : Turn on random LField storage offsets.\n");
772  INFOMSG(" --extracompcheck : Turn on extra compression checks in evaluator.\n");
773  INFOMSG(" --checksums : Turn on CRC checksums for messages.\n");
774  INFOMSG(" --retransmit : Resent messages if a CRC error occurs.\n");
775  INFOMSG(" --maxfftnodes <n> : Limit the nodes that work on FFT's.\n");
776  INFOMSG(" --chunksize <n> : Set I/O chunk size. Can end w/K,M,G.\n");
777  INFOMSG(" --persmppario : Enable on-SMP parallel IO option.\n");
778  INFOMSG(" --nopersmppario : Disable on-SMP parallel IO option (default).\n");
779 }
780 
782 // here: as in stop in IpplInfo::here (in the debugger)
784 {
785 }
786 
788 // print out statistics to the given Inform stream
790 
791 
793 // version: return the name of this version of Ippl, as a string
794 // (from Versions.h)
795 const char *IpplInfo::version() {
796  return ippl_version_name;
797 }
798 
799 
800 
802 // compileArch: return the architecture on which this library was built
803 // (from IpplVersions.h)
804 const char *IpplInfo::compileArch() {
805  return ippl_compile_arch;
806 }
807 
808 
810 // compileDate: return the date on which this library was prepared for
811 // compilation (from IpplVersions.h)
812 const char *IpplInfo::compileDate() {
813  return ippl_compile_date;
814 }
815 
816 
818 // compileLine: return the compiler command used to compile each source file
819 // (from IpplVersions.h)
820 const char *IpplInfo::compileLine() {
821  return ippl_compile_line;
822 }
823 
824 
826 // compileMachine: return the machine on which this library was
827 // compiled (from IpplVersions.h)
829  return ippl_compile_machine;
830 }
831 
832 
834 // compileOptions: return the option list used to compile this library
835 // (from IpplVersions.h)
837  return ippl_compile_options;
838 }
839 
840 
842 // compileUser: return the username of the user who compiled this
843 // library (from IpplVersions.h)
844 const char *IpplInfo::compileUser() {
845  return ippl_compile_user;
846 }
847 
848 
850 // param_error: print out an error message when an illegal cmd-line
851 // parameter is encountered.
852 // Arguments are: parameter, error message, bad value (if any)
853 void IpplInfo::param_error(const char *param, const char *msg,
854  const char *bad) {
855  if ( param != 0 )
856  ERRORMSG(param << " ");
857  if ( bad != 0 )
858  ERRORMSG(bad << " ");
859  if ( msg != 0 )
860  ERRORMSG(": " << msg);
861  ERRORMSG(endl);
862  IpplInfo::abort(0);
863 }
864 
865 void IpplInfo::param_error(const char *param, const char *msg1,
866  const char *msg2, const char *bad) {
867  if ( param != 0 )
868  ERRORMSG(param << " ");
869  if ( bad != 0 )
870  ERRORMSG(bad << " ");
871  if ( msg1 != 0 )
872  ERRORMSG(": " << msg1);
873  if ( msg2 != 0 )
874  ERRORMSG(msg2);
875  ERRORMSG(endl);
876  IpplInfo::abort(0);
877 }
878 
879 
881 // find out how many SMP's there are, and which processor we are on
882 // our local SMP (e.g., if there are two SMP's with 4 nodes each,
883 // the process will have a node number from 0 ... 7, and an SMP node
884 // number from 0 ... 3
886  // Inform dbgmsg("IpplInfo::find_smp_nodes", INFORM_ALL_NODES);
887 
888  // create a tag for use in sending info to/from other nodes
889  int tag = Comm->next_tag(IPPL_MAKE_HOST_MAP_TAG, IPPL_TAG_CYCLE);
890 
891  // create arrays to store the Node -> SMP mapping, and the relative
892  // SMP node number
893  if (SMPIDList != 0)
894  delete [] SMPIDList;
895  if (SMPNodeList != 0)
896  delete [] SMPNodeList;
897  SMPIDList = new int[TotalNodes];
898  SMPNodeList = new int[TotalNodes];
899 
900  // obtain the hostname and processor ID to send out
901  char name[1024];
902  if (gethostname(name, 1023) != 0) {
903  ERRORMSG("Could not get hostname ... using localhost." << endl);
904  strcpy(name, "localhost");
905  }
906  std::string NodeName(name,strlen(name));
907  // dbgmsg << "My hostname is " << NodeName << endl;
908 
909  // all other nodes send their hostname to node 0; node 0 gets the names,
910  // maps pnode ID's -> SMP ID's, then broadcasts all the necessary info to
911  // all other nodes
912  if (MyNode != 0) {
913  // other nodes send their node name to node 0
914  Message *msg = new Message;
915  ::putMessage(*msg,NodeName);
916  // dbgmsg << "Sending my name to node 0." << endl;
917  Comm->send(msg, 0, tag);
918 
919  // receive back the SMPIDList mapping
920  int node = 0;
921  msg = Comm->receive_block(node, tag);
922  PInsist(msg != 0 && node == 0,
923  "SPMDList map not received from master in IpplInfo::find_smp_nodes!!");
926  delete msg;
927  }
928  else {
929  // collect node names from everyone else, and then retransmit the collected
930  // list.
931  SMPIDList[0] = 0;
932  vmap<std::string,int> smpMap;
934  smpMap.insert(vmap<std::string,int>::value_type(NodeName, 0));
935  unsigned int unreceived = TotalNodes - 1;
936  while (unreceived-- > 0) {
937  // get the hostname from the remote node
938  int node = COMM_ANY_NODE;
939  Message *msg = Comm->receive_block(node, tag);
940  PInsist(msg != 0,
941  "Hostname not received by master in IpplInfo::find_smp_nodes!!");
942  std::string nodename;
943  ::getMessage(*msg,nodename);
944  delete msg;
945  // dbgmsg <<"Received name '"<< nodename <<"' from node "<< node<<endl;
946 
947  // put it in the mapping from hostname -> SMP ID, if necessary
948  smpiter = smpMap.find(nodename);
949  if (smpiter == smpMap.end())
950  smpMap.insert(vmap<std::string,int>::value_type(nodename,smpMap.size()));
951 
952  // from the hostname, get the SMP ID number and store it in SMPIDList
953  SMPIDList[node] = smpMap[nodename];
954  }
955 
956  // convert from SMPID mapping -> relative node number
957  for (int smpindx = 0; (unsigned int) smpindx < smpMap.size(); ++smpindx) {
958  int smpnodes = 0;
959  for (int n=0; n < TotalNodes; ++n) {
960  if (SMPIDList[n] == smpindx)
961  SMPNodeList[n] = smpnodes++;
962  }
963  }
964 
965  // broadcast SMP info to other nodes
966  if (TotalNodes > 1) {
967  Message *msg = new Message;
970  Comm->broadcast_others(msg, tag);
971  }
972  }
973 
974  // compute number of SMP's ... necessary for all but node 0, but we'll do
975  // it for all
976  NumSMPs = 0;
977  for (int ns=0; ns < TotalNodes; ++ns)
978  if (SMPNodeList[ns] == 0)
979  NumSMPs++;
980 
981  // dbgmsg << "Results of SMP mapping: NumSMPs = " << NumSMPs << endl;
982  // for (unsigned int n=0; n < TotalNodes; ++n) {
983  // dbgmsg << " n=" << n << ", SMPID=" << SMPIDList[n] << ", SMPNode=";
984  // dbgmsg << SMPNodeList[n] << endl;
985  // }
986 }
987 
989  PAssert_EQ(stashedStaticMembers.size(), 0);
990 
991  StaticIpplInfo obj;
992 
993  obj.Comm = Comm;
994  obj.Stats = Stats;
995  obj.Info = Info;
996  obj.Warn = Warn;
997  obj.Error = Error;
998  obj.Debug = Debug;
1004  obj.NumCreated = NumCreated;
1006  obj.PrintStats = PrintStats;
1008  obj.UseChecksums = UseChecksums;
1009  obj.Retransmit = Retransmit;
1010  obj.MyArgc = MyArgc;
1011  obj.MyArgv = MyArgv;
1012  obj.MyNode = MyNode;
1013  obj.TotalNodes = TotalNodes;
1014  obj.NumSMPs = NumSMPs;
1015  obj.SMPIDList = SMPIDList;
1016  obj.SMPNodeList = SMPNodeList;
1017  obj.MaxFFTNodes = MaxFFTNodes;
1018  obj.ChunkSize = ChunkSize;
1020 
1021  stashedStaticMembers.push(obj);
1022 
1023  Comm = 0;
1024  Stats = 0;
1025  Info = 0;
1026  Warn = 0;
1027  Error = 0;
1028  Debug = 0;
1029 
1030  deferGuardCellFills = false;
1031  noFieldCompression = false;
1032  offsetStorage = false;
1033  extraCompressChecks = false;
1034  communicator_m = MPI_COMM_WORLD;
1035  NumCreated = 0;
1036  CommInitialized = false;
1037  PrintStats = false;
1038  NeedDeleteComm = false;
1039  UseChecksums = false;
1040  Retransmit = false;
1041  MyArgc = 0;
1042  MyArgv = 0;
1043  MyNode = 0;
1044  TotalNodes = 1;
1045  NumSMPs = 1;
1046  SMPIDList = 0;
1047  SMPNodeList = 0;
1048  MaxFFTNodes = 0;
1049  ChunkSize = 512*1024; // 512K == 64K doubles
1050  PerSMPParallelIO = false;
1051 }
1052 
1054  PAssert_EQ(stashedStaticMembers.size(), 1);
1055 
1057  stashedStaticMembers.pop();
1058  // Delete the communications object, if necessary, to shut down parallel
1059  // environment
1060  // Comm is deleted in destructor
1061  delete [] MyArgv;
1062  delete [] SMPIDList;
1063  delete [] SMPNodeList;
1064  delete Info;
1065  delete Warn;
1066  delete Error;
1067  delete Debug;
1068  delete Stats;
1069 
1070  Comm = obj.Comm;
1071  Stats = obj.Stats;
1072  Info = obj.Info;
1073  Warn = obj.Warn;
1074  Error = obj.Error;
1075  Debug = obj.Debug;
1081  NumCreated = obj.NumCreated;
1083  PrintStats = obj.PrintStats;
1085  UseChecksums = obj.UseChecksums;
1086  Retransmit = obj.Retransmit;
1087  MyArgc = obj.MyArgc;
1088  MyArgv = obj.MyArgv;
1089  MyNode = obj.MyNode;
1090  TotalNodes = obj.TotalNodes;
1091  NumSMPs = obj.NumSMPs;
1092  SMPIDList = obj.SMPIDList;
1093  SMPNodeList = obj.SMPNodeList;
1094  MaxFFTNodes = obj.MaxFFTNodes;
1095  ChunkSize = obj.ChunkSize;
1097 }
const char * ippl_compile_date
Definition: IpplVersions.h:10
const char * ippl_compile_user
Definition: IpplVersions.h:13
const char * ippl_compile_line
Definition: IpplVersions.h:9
const char * ippl_compile_options
Definition: IpplVersions.h:12
const char * ippl_version_name
Definition: IpplVersions.h:7
const char * ippl_compile_machine
Definition: IpplVersions.h:11
const char * ippl_compile_arch
Definition: IpplVersions.h:8
const int COMM_ANY_NODE
Definition: Communicate.h:40
void putMessage(Message &m, const T &t)
Definition: Message.h:549
void getMessage_iter(Message &m, OutputIterator o)
Definition: Message.h:595
void getMessage(Message &m, T &t)
Definition: Message.h:572
#define IPPL_TAG_CYCLE
Definition: Tags.h:90
#define IPPL_MAKE_HOST_MAP_TAG
Definition: Tags.h:89
#define IPPL_ABORT_TAG
Definition: Tags.h:25
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define INFORM_ALL_NODES
Definition: Inform.h:39
std::ostream & operator<<(std::ostream &o, const IpplInfo &)
Definition: IpplInfo.cpp:118
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define INFOMSG(msg)
Definition: IpplInfo.h:348
#define PInsist(c, m)
Definition: PAssert.h:120
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
RandomNumberGen IpplRandom
const std::string name
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:51
Definition: types.h:26
static void setDefaultNodes(int)
static bool supported(int)
static const char * getAllMethodNames()
static bool setDefaultMethod(int)
static bool known(int)
static const char * getAllLibraryNames()
Definition: CommCreator.cpp:53
static bool supported(int)
Definition: CommCreator.cpp:61
static Communicate * create(int, int &, char **&, int=(-1), bool=true, MPI_Comm mpicomm=MPI_COMM_WORLD)
Definition: CommCreator.cpp:95
static bool known(const char *nm)
Definition: CommCreator.h:69
virtual const char * name() const
Definition: Communicate.h:137
Definition: Inform.h:42
Inform & setOutputLevel(const int)
Definition: Inform.cpp:228
static bool NeedDeleteComm
Definition: IpplInfo.h:298
static void deleteGlobals()
Definition: IpplInfo.cpp:68
@ KEEP
Definition: IpplInfo.h:74
static bool noFieldCompression
Definition: IpplInfo.h:262
static int NumCreated
Definition: IpplInfo.h:287
static void printStatistics(Inform &)
Definition: IpplInfo.cpp:789
static void instantiateGlobals()
Definition: IpplInfo.cpp:53
static bool extraCompressChecks
Definition: IpplInfo.h:270
static void printVersion(void)
Definition: IpplInfo.cpp:736
static IpplStats * Stats
Definition: IpplInfo.h:87
static int * SMPIDList
Definition: IpplInfo.h:318
static MPI_Comm communicator_m
Definition: IpplInfo.h:283
static bool offsetStorage
Definition: IpplInfo.h:266
static Inform * Warn
Definition: IpplInfo.h:79
static bool perSMPParallelIO()
Definition: IpplInfo.h:211
static int chunkSize()
Definition: IpplInfo.h:206
static int TotalNodes
Definition: IpplInfo.h:313
static void printHelp()
Definition: IpplInfo.cpp:744
static void pop()
Definition: IpplInfo.cpp:1053
static int NumSMPs
Definition: IpplInfo.h:317
static const char * compileMachine()
Definition: IpplInfo.cpp:828
static int * SMPNodeList
Definition: IpplInfo.h:319
static int MyArgc
Definition: IpplInfo.h:307
static void stash()
Definition: IpplInfo.cpp:988
static int MyNode
Definition: IpplInfo.h:312
static Inform * Info
Definition: IpplInfo.h:78
static char ** MyArgv
Definition: IpplInfo.h:308
static bool Retransmit
Definition: IpplInfo.h:304
static Inform * Error
Definition: IpplInfo.h:80
static bool PerSMPParallelIO
Definition: IpplInfo.h:331
static void param_error(const char *, const char *, const char *)
Definition: IpplInfo.cpp:853
static void abort(const char *=0)
Definition: IpplInfo.cpp:616
static int getProcesses(int, int)
Definition: IpplInfo.cpp:684
static int getContexts(int)
Definition: IpplInfo.cpp:677
static int getSMPNodes(int)
Definition: IpplInfo.cpp:706
static const char * compileLine()
Definition: IpplInfo.cpp:820
static const char * compileArch()
Definition: IpplInfo.cpp:804
static bool retransmit()
Definition: IpplInfo.h:195
static void find_smp_nodes()
Definition: IpplInfo.cpp:885
static bool useChecksums()
Definition: IpplInfo.h:192
static int MaxFFTNodes
Definition: IpplInfo.h:323
static bool CommInitialized
Definition: IpplInfo.h:291
static int getSMPs()
Definition: IpplInfo.cpp:699
static const char * version()
Definition: IpplInfo.cpp:795
static void here()
Definition: IpplInfo.cpp:783
static void abortAllNodes(const char *=0)
Definition: IpplInfo.cpp:647
static int getNodes()
Definition: IpplInfo.cpp:670
static bool PrintStats
Definition: IpplInfo.h:295
static int mySMPNode()
Definition: IpplInfo.cpp:728
static std::stack< StaticIpplInfo > stashedStaticMembers
Definition: IpplInfo.h:333
static const char * compileUser()
Definition: IpplInfo.cpp:844
static bool deferGuardCellFills
Definition: IpplInfo.h:259
static bool UseChecksums
Definition: IpplInfo.h:301
static Inform * Debug
Definition: IpplInfo.h:81
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84
static int mySMP()
Definition: IpplInfo.cpp:721
static const char * compileDate()
Definition: IpplInfo.cpp:812
IpplInfo & operator=(const IpplInfo &)
Definition: IpplInfo.cpp:611
static const char * compileOptions()
Definition: IpplInfo.cpp:836
static int ChunkSize
Definition: IpplInfo.h:326
Timer & getTime()
Definition: IpplStats.h:82
void print(Inform &)
Definition: IpplStats.cpp:105
void AdvanceSeed(int adv=0)
Definition: RNGXDiv.h:147
Communicate * Comm
bool extraCompressChecks
bool deferGuardCellFills
MPI_Comm communicator_m
IpplStats * Stats
void start()
Definition: Timer.cpp:34
void stop()
Definition: Timer.cpp:39
void clear()
Definition: Timer.cpp:29
double clock_time()
Definition: Timer.cpp:50
double cpu_time()
Definition: Timer.cpp:65
Definition: vmap.h:59
rep_type::iterator iterator
Definition: vmap.h:98
size_type size() const
Definition: vmap.h:120
iterator end()
Definition: vmap.h:108
iterator find(const key_type &x)
Definition: vmap.hpp:214
std::pair< Key, T > value_type
Definition: vmap.h:64
std::pair< iterator, bool > insert(const value_type &x)
Definition: vmap.hpp:73