oomph_utilities.cc
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2024 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifdef OOMPH_HAS_MPI
27 #include "mpi.h"
28 #endif
29 
30 #include <algorithm>
31 #include <limits.h>
32 #include <cstring>
33 
34 #ifdef OOMPH_HAS_UNISTDH
35 #include <unistd.h> // for getpid()
36 #endif
37 
38 #include "oomph_utilities.h"
39 #include "Vector.h"
40 #include "matrices.h"
41 
42 namespace oomph
43 {
44  //======start_of_ANSIEscapeCode_namespace=============================
45  /// Contains an enumeration of the ANSI escape codes used for
46  /// colouring text (when piped to the command line). Adapted from
47  /// the guide on:
48  /// https://stackoverflow.com/questions/2616906/how-do-i-output-
49  /// coloured-text-to-a-linux-terminal?utm_medium=organic&utm_source=
50  /// google_rich_qa&utm_campaign=google_rich_qa
51  /// Here, \033 is the ESC character, ASCII 27. It is followed by [,
52  /// then zero or more numbers separated by ;, and finally the letter
53  /// m. The numbers describe the colour and format to switch to from
54  /// that point onwards.
55  //====================================================================
56  namespace ANSIEscapeCode
57  {
58  /// Function to change text effect. NOTE: This assumes the user
59  /// knows what they're doing/assigning; no error checking done here...
60  void set_text_effect(std::string text_effect)
61  {
62  // Assign the string
63  Text_effect = text_effect;
64  } // End of set_text_effect
65 
66  /// Variable to decide on effects
68 
69  /// The code for each type of colour
70  std::string Black = "\033[" + Text_effect + ";30m";
71  std::string Red = "\033[" + Text_effect + ";31m";
72  std::string Green = "\033[" + Text_effect + ";32m";
73  std::string Yellow = "\033[" + Text_effect + ";33m";
74  std::string Blue = "\033[" + Text_effect + ";34m";
75  std::string Magenta = "\033[" + Text_effect + ";35m";
76  std::string Cyan = "\033[" + Text_effect + ";36m";
77  std::string Reset = "\033[0m";
78  } // namespace ANSIEscapeCode
79 
80 
81  //=====================================================================
82  /// Namespace for debugging helpers. Currently only contains a
83  /// function to prett-ify file name and line numbers (in red) to use
84  /// when debugging. Makes it easy to identify where a std::cout
85  /// statement was called.
86  //=====================================================================
87  namespace DebugHelpers
88  {
89  /// Return the concaternation of the initials of the input
90  /// file name and line number. The make_new_line flag indicates
91  /// whether the string starts with a "\n", i.e. a new line
93  const int& line,
94  const bool& make_new_line)
95  {
96  // Make a string
98 
99  // Temporary storage for the filename which can be edited
100  std::string file = filename;
101 
102  // The delimeter
103  std::string delimiter = "_";
104 
105  // Posiiton of the delimiter
106  size_t pos = 0;
107 
108  // The string before the delimiter
109  std::string token;
110 
111  // Get the filename (gets rid of e.g. ./ before filename)
112  while ((pos = file.find("/")) != std::string::npos)
113  {
114  // Get the string before the delimiter
115  token = file.substr(0, pos);
116 
117  // Erase the string before the delimeter
118  file = file.substr(pos + delimiter.length());
119  }
120 
121  // While we can find delimeters
122  while ((pos = file.find(delimiter)) != std::string::npos)
123  {
124  // Get the string before the delimiter
125  token = file.substr(0, pos);
126 
127  // Output the string
128  debug_string += toupper(token.at(0));
129 
130  // Erase the delimeter
131  file = file.substr(pos + delimiter.length());
132  }
133 
134  // Output the string
135  debug_string += toupper(file.at(0));
136 
137  // String stream
138  std::ostringstream debug_stream;
139 
140  // If they want a new line
141  if (make_new_line)
142  {
143  // Add a newline string
144  debug_stream << "\n";
145  }
146 
147  // Create debug string
148  debug_stream << "\033[1;31m" << debug_string << line << ":\033[0m ";
149 
150  // Return the string
151  return debug_stream.str();
152  } // End of create_debug_string
153  } // namespace DebugHelpers
154 
155 
156  //=====================================================================
157  /// Helper namespace containing function that computes second invariant
158  /// of tensor
159  //=====================================================================
160  namespace SecondInvariantHelper
161  {
162  /// Compute second invariant of tensor
163  double second_invariant(const DenseMatrix<double>& tensor)
164  {
165  // get size of tensor
166  unsigned n = tensor.nrow();
167  double trace_of_tensor = 0.0;
168  double trace_of_tensor_squared = 0.0;
169  for (unsigned i = 0; i < n; i++)
170  {
171  // Calculate the trace of the tensor: T_ii
172  trace_of_tensor += tensor(i, i);
173  // Calculate the trace of the tensor squared: T_ij T_ji
174  for (unsigned j = 0; j < n; j++)
175  {
176  trace_of_tensor_squared += tensor(i, j) * tensor(j, i);
177  }
178  }
179 
180  // return the second invariant: 1.0/2.0*[(T_ii)^2 - T_ij T_ji]
181  return 0.5 *
182  (trace_of_tensor * trace_of_tensor - trace_of_tensor_squared);
183  }
184 
185  } // namespace SecondInvariantHelper
186 
187 
188  //==============================================
189  /// Namespace for error messages for broken
190  /// copy constructors and assignment operators
191  //==============================================
192  namespace BrokenCopy
193  {
194  /// Issue error message and terminate execution
195  void broken_assign(const std::string& class_name)
196  {
197  // Write the error message into a string
198  std::string error_message = "Assignment operator for class\n\n";
199  error_message += class_name;
200  error_message += "\n\n";
201  error_message += "is deliberately broken to avoid the accidental \n";
202  error_message += "use of the inappropriate C++ default.\n";
203  error_message += "If you really need an assignment operator\n";
204  error_message += "for this class, write it yourself...\n";
205 
206  throw OomphLibError(
207  error_message, "broken_assign()", OOMPH_EXCEPTION_LOCATION);
208  }
209 
210 
211  /// Issue error message and terminate execution
212  void broken_copy(const std::string& class_name)
213  {
214  // Write the error message into a string
215  std::string error_message = "Copy constructor for class\n\n";
216  error_message += class_name;
217  error_message += "\n\n";
218  error_message += "is deliberately broken to avoid the accidental\n";
219  error_message += "use of the inappropriate C++ default.\n";
220  error_message +=
221  "All function arguments should be passed by reference or\n";
222  error_message +=
223  "constant reference. If you really need a copy constructor\n";
224  error_message += "for this class, write it yourself...\n";
225 
226  throw OomphLibError(
227  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
228  }
229  } // namespace BrokenCopy
230 
231 
232  /// ///////////////////////////////////////////////////////////////
233  /// ///////////////////////////////////////////////////////////////
234  /// ///////////////////////////////////////////////////////////////
235 
236 
237  //====================================================================
238  /// Namespace for global (cumulative) timings
239  //====================================================================
240  namespace CumulativeTimings
241  {
242  /// (Re-)start i-th timer
243  void start(const unsigned& i)
244  {
245  Start_time[i] = clock();
246  }
247 
248  /// Halt i-th timer
249  void halt(const unsigned& i)
250  {
251  Timing[i] += clock() - Start_time[i];
252  }
253 
254  /// Report time accumulated by i-th timer
255  double cumulative_time(const unsigned& i)
256  {
257  return double(Timing[i]) / CLOCKS_PER_SEC;
258  }
259 
260  /// Reset i-th timer
261  void reset(const unsigned& i)
262  {
263  Timing[i] = clock_t(0.0);
264  }
265 
266  /// Reset all timers
267  void reset()
268  {
269  unsigned n = Timing.size();
270  for (unsigned i = 0; i < n; i++)
271  {
272  Timing[i] = clock_t(0.0);
273  }
274  }
275 
276  /// Set number of timings that can be recorded in parallel
277  void set_ntimers(const unsigned& ntimers)
278  {
279  Timing.resize(ntimers, clock_t(0.0));
280  Start_time.resize(ntimers, clock_t(0.0));
281  }
282 
283  /// Cumulative timings
285 
286  /// Start times of active timers
288 
289  } // namespace CumulativeTimings
290 
291 
292  //======================================================================
293  /// Set output directory (we try to open a file in it
294  /// to see if the directory exists -- if it doesn't we'll
295  /// issue a warning -- or, if directory_must_exist()==true,
296  /// die by throwing and OomphLibError
297  //======================================================================
298  void DocInfo::set_directory(const std::string& directory_)
299  {
300  // Try to open a file in output directory
301  std::ostringstream filename;
302  filename << directory_ << "/.dummy_check.dat";
303  std::ofstream some_file;
304  some_file.open(filename.str().c_str());
305  if (!some_file.is_open())
306  {
307  // Construct the error message
308  std::string error_message = "Problem opening output file.\n";
309  error_message += "I suspect you haven't created the output directory ";
310  error_message += directory_;
311  error_message += "\n";
312 
313  // Issue a warning if the directory does not have to exist
315  {
316  // Create an Oomph Lib warning
318  error_message, "set_directory()", OOMPH_EXCEPTION_LOCATION);
319  }
320  // Otherwise throw an error
321  else
322  {
323  error_message += "and the Directory_must_exist flag is true.\n";
324  throw OomphLibError(
325  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
326  }
327  }
328  // Write to the dummy file
329  some_file << "Dummy file, opened to check if output directory "
330  << std::endl;
331  some_file << "exists. Can be deleted...." << std::endl;
332  some_file.close();
333  // Set directory
334  Directory = directory_;
335  }
336 
337 
338  // =================================================================
339  /// Conversion functions for easily making strings (e.g. for filenames - to
340  /// avoid stack smashing problems with cstrings and long filenames).
341  // =================================================================
342  namespace StringConversion
343  {
344  /// Convert a string to lower case (outputs a copy).
346  {
347  std::string output(input);
348  std::string::iterator it;
349  for (it = output.begin(); it != output.end(); ++it)
350  {
351  ::tolower(*it);
352  }
353 
354  return output;
355  }
356 
357  /// Convert a string to upper case (outputs a copy).
359  {
360  std::string output(input);
361  std::string::iterator it;
362  for (it = output.begin(); it != output.end(); ++it)
363  {
364  ::toupper(*it);
365  }
366  return output;
367  }
368 
369  /// Split a string, s, into a vector of strings where ever there is
370  /// an instance of delimiter (i.e. is delimiter is " " will give a list of
371  /// words). Note that mutliple delimiters in a row will give empty
372  /// strings.
374  char delim,
375  Vector<std::string>& elems)
376  {
377  // From http://stackoverflow.com/questions/236129/splitting-a-string-in-c
378  std::stringstream ss(s);
379  std::string item;
380  while (std::getline(ss, item, delim))
381  {
382  elems.push_back(item);
383  }
384  }
385 
386  /// Split a string, s, into a vector of strings where ever there is
387  /// an instance of delimiter (i.e. is delimiter is " " will give a list of
388  /// words). Note that mutliple delimiters in a row will give empty
389  /// strings. Return by value.
391  {
392  // From http://stackoverflow.com/questions/236129/splitting-a-string-in-c
393  Vector<std::string> elems;
394  split_string(s, delim, elems);
395  return elems;
396  }
397 
398  } // namespace StringConversion
399 
400 
401  //====================================================================
402  /// Namespace for command line arguments
403  //====================================================================
404  namespace CommandLineArgs
405  {
406  /// Number of arguments + 1
407  int Argc;
408 
409  /// Arguments themselves
410  char** Argv;
411 
412  /// Map to indicate an input flag as having been set
413  std::map<std::string, ArgInfo<bool>> Specified_command_line_flag;
414 
415  /// Map to associate an input flag with a double -- specified via pointer
416  std::map<std::string, ArgInfo<double>> Specified_command_line_double_pt;
417 
418  /// Map to associate an input flag with an int -- specified via pointer
419  std::map<std::string, ArgInfo<int>> Specified_command_line_int_pt;
420 
421  /// Map to associate an input flag with an unsigned -- specified via pointer
422  std::map<std::string, ArgInfo<unsigned>> Specified_command_line_unsigned_pt;
423 
424  /// Map to associate an input flag with a string -- specified via pointer
425  std::map<std::string, ArgInfo<std::string>>
427 
428  /// Set values
429  void setup(int argc, char** argv)
430  {
431  Argc = argc;
432  Argv = argv;
433  }
434 
435  /// Doc the command line arguments
436  void output()
437  {
438  oomph_info << "You are running the program: " << CommandLineArgs::Argv[0]
439  << std::endl;
440  oomph_info << "with the following command line args: " << std::endl;
441  std::stringstream str;
442  for (int i = 1; i < CommandLineArgs::Argc; i++)
443  {
444  str << CommandLineArgs::Argv[i] << " ";
445  }
446  oomph_info << str.str() << std::endl;
447  }
448 
449 
450  /// Specify possible argument-free command line flag
451  void specify_command_line_flag(const std::string& command_line_flag,
452  const std::string& doc)
453  {
454  Specified_command_line_flag[command_line_flag] =
455  ArgInfo<bool>(false, 0, doc);
456  }
457 
458  /// Specify possible command line flag that specifies a double,
459  /// accessed via pointer
460  void specify_command_line_flag(const std::string& command_line_flag,
461  double* arg_pt,
462  const std::string& doc)
463  {
464  Specified_command_line_double_pt[command_line_flag] =
465  ArgInfo<double>(false, arg_pt, doc);
466  }
467 
468  /// Specify possible command line flag that specifies an int,
469  /// accessed via pointer
470  void specify_command_line_flag(const std::string& command_line_flag,
471  int* arg_pt,
472  const std::string& doc)
473  {
474  Specified_command_line_int_pt[command_line_flag] =
475  ArgInfo<int>(false, arg_pt, doc);
476  }
477 
478  /// Specify possible command line flag that specifies an unsigned,
479  /// accessed via pointer
480  void specify_command_line_flag(const std::string& command_line_flag,
481  unsigned* arg_pt,
482  const std::string& doc)
483  {
484  Specified_command_line_unsigned_pt[command_line_flag] =
485  ArgInfo<unsigned>(false, arg_pt, doc);
486  }
487 
488  /// Specify possible command line flag that specifies a string,
489  /// accessed via pointer
490  void specify_command_line_flag(const std::string& command_line_flag,
491  std::string* arg_pt,
492  const std::string& doc)
493  {
494  Specified_command_line_string_pt[command_line_flag] =
495  ArgInfo<std::string>(false, arg_pt, doc);
496  }
497 
498 
499  /// Check if command line flag has been set (value will have been
500  /// assigned directly).
502  {
503  for (std::map<std::string, ArgInfo<bool>>::iterator it =
505  it != Specified_command_line_flag.end();
506  it++)
507  {
508  if (it->first == flag)
509  {
510  return it->second.is_set;
511  }
512  }
513 
514  for (std::map<std::string, ArgInfo<double>>::iterator it =
517  it++)
518  {
519  if (it->first == flag)
520  {
521  return (it->second).is_set;
522  }
523  }
524 
525  for (std::map<std::string, ArgInfo<int>>::iterator it =
527  it != Specified_command_line_int_pt.end();
528  it++)
529  {
530  if (it->first == flag)
531  {
532  return (it->second).is_set;
533  }
534  }
535 
536  for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
539  it++)
540  {
541  if (it->first == flag)
542  {
543  return (it->second).is_set;
544  }
545  }
546 
547  for (std::map<std::string, ArgInfo<std::string>>::iterator it =
550  it++)
551  {
552  if (it->first == flag)
553  {
554  return (it->second).is_set;
555  }
556  }
557 
558  return false;
559  }
560 
561  /// Document the values of all flags (specified or not).
562  void doc_all_flags(std::ostream& outstream)
563  {
564  for (std::map<std::string, ArgInfo<bool>>::iterator it =
566  it != Specified_command_line_flag.end();
567  it++)
568  {
569  outstream << it->first << " " << it->second.is_set << std::endl;
570  }
571  for (std::map<std::string, ArgInfo<double>>::iterator it =
574  it++)
575  {
576  outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
577  }
578  for (std::map<std::string, ArgInfo<int>>::iterator it =
580  it != Specified_command_line_int_pt.end();
581  it++)
582  {
583  outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
584  }
585  for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
588  it++)
589  {
590  outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
591  }
592  for (std::map<std::string, ArgInfo<std::string>>::iterator it =
595  it++)
596  {
597  // Quote blank strings, otherwise trying to parse the output in any way
598  // will go wrong.
599  std::string arg_string = *(it->second.arg_pt);
600  if (arg_string == "")
601  {
602  arg_string = "\"\"";
603  }
604 
605  outstream << it->first << " " << arg_string << std::endl;
606  }
607  }
608 
609  /// Document specified command line flags
611  {
612  oomph_info << std::endl;
613  oomph_info << "Specified (and recognised) command line flags:\n";
614  oomph_info << "----------------------------------------------\n";
615 
616  for (std::map<std::string, ArgInfo<bool>>::iterator it =
618  it != Specified_command_line_flag.end();
619  it++)
620  {
621  if (it->second.is_set)
622  {
623  oomph_info << it->first << std::endl;
624  }
625  }
626 
627  for (std::map<std::string, ArgInfo<double>>::iterator it =
630  it++)
631  {
632  if (it->second.is_set)
633  {
634  oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
635  }
636  }
637 
638  for (std::map<std::string, ArgInfo<int>>::iterator it =
640  it != Specified_command_line_int_pt.end();
641  it++)
642  {
643  if (it->second.is_set)
644  {
645  oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
646  }
647  }
648 
649  for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
652  it++)
653  {
654  if (it->second.is_set)
655  {
656  oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
657  }
658  }
659 
660  for (std::map<std::string, ArgInfo<std::string>>::iterator it =
663  it++)
664  {
665  if (it->second.is_set)
666  {
667  oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
668  }
669  }
670 
671  oomph_info << std::endl;
672  }
673 
674 
675  /// Document available command line flags
677  {
678  oomph_info << std::endl;
679  oomph_info << "Available command line flags:\n";
680  oomph_info << "-----------------------------\n";
681 
682  for (std::map<std::string, ArgInfo<bool>>::iterator it =
684  it != Specified_command_line_flag.end();
685  it++)
686  {
687  oomph_info << it->first << std::endl
688  << it->second.doc << std::endl
689  << std::endl;
690  }
691 
692  for (std::map<std::string, ArgInfo<double>>::iterator it =
695  it++)
696  {
697  oomph_info << it->first << " <double> " << std::endl
698  << it->second.doc << std::endl
699  << std::endl;
700  }
701 
702  for (std::map<std::string, ArgInfo<int>>::iterator it =
704  it != Specified_command_line_int_pt.end();
705  it++)
706  {
707  oomph_info << it->first << " <int> " << std::endl
708  << it->second.doc << std::endl
709  << std::endl;
710  }
711 
712  for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
715  it++)
716  {
717  oomph_info << it->first << " <unsigned> " << std::endl
718  << it->second.doc << std::endl
719  << std::endl;
720  }
721 
722  for (std::map<std::string, ArgInfo<std::string>>::iterator it =
725  it++)
726  {
727  oomph_info << it->first << " <string> " << std::endl
728  << it->second.doc << std::endl
729  << std::endl;
730  }
731 
732  oomph_info << std::endl;
733  }
734 
735 
736  /// Helper function to check if command line index is legal
737  void check_arg_index(const int& argc, const int& arg_index)
738  {
739  if (arg_index >= argc)
740  {
741  output();
743  std::stringstream error_stream;
744  error_stream
745  << "Tried to read more command line arguments than\n"
746  << "specified. This tends to happen if a required argument\n"
747  << "to a command line flag was omitted, e.g. by running \n\n"
748  << " ./a.out -some_double \n\n rather than\n\n"
749  << " ./a.out -some_double 1.23 \n\n"
750  << "To aid the debugging I've output the available\n"
751  << "command line arguments above.\n";
752  throw OomphLibError(
753  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
754  }
755  }
756 
757 
758  /// Parse command line, check for recognised flags and assign
759  /// associated values
760  void parse_and_assign(int argc,
761  char* argv[],
762  const bool& throw_on_unrecognised_args)
763  {
764  // Keep looping over command line arguments
765  int arg_index = 1;
766  while (arg_index < argc)
767  {
768  bool found_match = false;
769 
770  if ((strcmp(argv[arg_index], "-help") == 0) ||
771  (strcmp(argv[arg_index], "--help") == 0))
772  {
773  oomph_info
774  << "NOTE: You entered --help or -help on the command line\n";
775  oomph_info << "so I'm going to tell you about this code's\n";
776  oomph_info << "available command line flags and then return.\n";
778 
779 #ifdef OOMPH_HAS_MPI
780  int flag;
781  MPI_Initialized(&flag);
782  if (flag != 0) MPI_Helpers::finalize();
783 #endif
784  oomph_info << "Shutting down...\n";
785  exit(0);
786  }
787 
788 
789  // Check if the flag has been previously specified as a simple argument
790  // free command line argument
791  for (std::map<std::string, ArgInfo<bool>>::iterator it =
793  it != Specified_command_line_flag.end();
794  it++)
795  {
796  if (it->first == argv[arg_index])
797  {
798  Specified_command_line_flag[argv[arg_index]].is_set = true;
799  found_match = true;
800  break;
801  }
802  }
803 
804  if (!found_match)
805  {
806  // Check if the flag has been previously specified as a
807  // command line argument that specifies (and is followed by) a double
808  for (std::map<std::string, ArgInfo<double>>::iterator it =
811  it++)
812  {
813  if (it->first == argv[arg_index])
814  {
815  // Next command line argument specifies the double. Set it via
816  // the pointer
817  arg_index++;
818  check_arg_index(argc, arg_index);
819  it->second.is_set = true;
820  *(it->second.arg_pt) = atof(argv[arg_index]);
821  found_match = true;
822  break;
823  }
824  }
825  }
826 
827 
828  if (!found_match)
829  {
830  // Check if the flag has been previously specified as a
831  // command line argument that specifies (and is followed by) an int
832  for (std::map<std::string, ArgInfo<int>>::iterator it =
834  it != Specified_command_line_int_pt.end();
835  it++)
836  {
837  if (it->first == argv[arg_index])
838  {
839  // Next command line argument specifies the int. Set it via
840  // the pointer
841  arg_index++;
842  check_arg_index(argc, arg_index);
843  it->second.is_set = true;
844  *(it->second.arg_pt) = atoi(argv[arg_index]);
845  found_match = true;
846  break;
847  }
848  }
849  }
850 
851 
852  if (!found_match)
853  {
854  // Check if the flag has been previously specified as a
855  // command line argument that specifies (and is followed by) an
856  // unsigned
857  for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
860  it++)
861  {
862  if (it->first == argv[arg_index])
863  {
864  // Next command line argument specifies the unsigned. Set it via
865  // the pointer
866  arg_index++;
867  check_arg_index(argc, arg_index);
868  it->second.is_set = true;
869  *(it->second.arg_pt) = unsigned(atoi(argv[arg_index]));
870  found_match = true;
871  break;
872  }
873  }
874  }
875 
876 
877  if (!found_match)
878  {
879  // Check if the flag has been previously specified as a
880  // command line argument that specifies (and is followed by) a string
881  for (std::map<std::string, ArgInfo<std::string>>::iterator it =
884  it++)
885  {
886  if (it->first == argv[arg_index])
887  {
888  // Next command line argument specifies the string. Set it via
889  // the pointer
890  arg_index++;
891  check_arg_index(argc, arg_index);
892  it->second.is_set = true;
893  *(it->second.arg_pt) = argv[arg_index];
894  found_match = true;
895  break;
896  }
897  }
898  }
899 
900 
901  // Oh dear, we still haven't found the argument in the list.
902  // Maybe it was specified wrongly -- issue warning.
903  if (!found_match)
904  {
905  // Construct the error message
906  std::string error_message = "Command line argument\n\n";
907  error_message += argv[arg_index];
908  error_message += "\n\nwas not recognised. This may be legal\n";
909  error_message += "but seems sufficiently suspicious to flag up.\n";
910  error_message += "If it should have been recognised, make sure you\n";
911  error_message += "used the right number of \"-\" signs...\n";
912 
913  if (throw_on_unrecognised_args)
914  {
915  error_message += "Throwing an error because you requested it with";
916  error_message += " throw_on_unrecognised_args option.";
917  throw OomphLibError(
918  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
919  }
920  else
921  {
922  // Create an Oomph Lib warning
924  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
925  }
926  }
927 
928 
929  arg_index++;
930  }
931  }
932 
933 
934  /// Parse previously specified command line, check for
935  /// recognised flags and assign associated values
936  void parse_and_assign(const bool& throw_on_unrecognised_args)
937  {
938  parse_and_assign(Argc, Argv, throw_on_unrecognised_args);
939  }
940 
941  } // namespace CommandLineArgs
942 
943 #ifdef OOMPH_HAS_MPI
944  //========================================================================
945  /// Single (global) instantiation of the mpi output modifier
946  //========================================================================
948 
949  //========================================================================
950  /// Precede the output by the processor ID but output everything
951  //========================================================================
952  bool MPIOutputModifier::operator()(std::ostream& stream)
953  {
954  int my_rank = Communicator_pt->my_rank();
955 
957  {
958  stream << "Processor " << my_rank << ": ";
959  // Continue processing
960  return true;
961  }
962  else
963  {
964  if (unsigned(my_rank) == Output_rank)
965  {
966  stream << "Processor " << my_rank << ": ";
967  // Continue processing
968  return true;
969  }
970  else
971  {
972  return false;
973  }
974  }
975  }
976 
977 #endif
978 
979  //=============================================================================
980  /// Initialize mpi. If optional boolean flag is set to false, we use
981  /// MPI_COMM_WORLD itself as oomph-lib's communicator. Defaults to true.
982  //=============================================================================
983  void MPI_Helpers::init(int argc,
984  char** argv,
985  const bool& make_duplicate_of_mpi_comm_world)
986  {
987 #ifdef OOMPH_HAS_MPI
988  // call mpi int
989  MPI_Init(&argc, &argv);
990 
991 
992  // By default, create the oomph-lib communicator using MPI_Comm_dup so that
993  // the communicator has the same group of processes but a new context
994  MPI_Comm oomph_comm_world = MPI_COMM_WORLD;
995  if (make_duplicate_of_mpi_comm_world)
996  {
997  MPI_Comm_dup(MPI_COMM_WORLD, &oomph_comm_world);
998  }
999 
1000  if (MPI_COMM_WORLD != oomph_comm_world)
1001  {
1002  oomph_info << "Oomph-lib communicator is a duplicate of MPI_COMM_WORLD\n";
1003  }
1004  else
1005  {
1006  oomph_info << "Oomph-lib communicator is MPI_COMM_WORLD\n";
1007  }
1008 
1009  // create the oomph-lib communicator
1010  // note: oomph_comm_world is deleted when the destructor of
1011  // Communicator_pt is called
1012  Communicator_pt = new OomphCommunicator(oomph_comm_world, true);
1013 
1014  // Change MPI error handler so that error will return
1015  // rather than aborting
1016  MPI_Comm_set_errhandler(oomph_comm_world, MPI_ERRORS_RETURN);
1017 
1018  // Use MPI output modifier: Each processor precedes its output
1019  // by its rank
1022 #else
1023  // create a serial communicator
1025 #endif
1026  MPI_has_been_initialised = true;
1027  }
1028 
1029  //=============================================================================
1030  /// finalize mpi
1031  //=============================================================================
1033  {
1034  // delete the communicator
1035  delete Communicator_pt;
1036 
1037  // and call MPI_Finalize
1038 #ifdef OOMPH_HAS_MPI
1039  MPI_Finalize();
1040 #endif
1041  }
1042 
1043  //=============================================================================
1044  /// access to the global oomph-lib communicator
1045  //=============================================================================
1047  {
1048 #ifdef MPI
1049 #ifdef PARANOID
1051  {
1052  std::ostringstream error_message_stream;
1053  error_message_stream
1054  << "MPI has not been initialised.\n Call MPI_Helpers::init(...)";
1055  throw OomphLibError(error_message_stream.str(),
1056  OOMPH_CURRENT_FUNCTION,
1057  OOMPH_EXCEPTION_LOCATION);
1058  }
1059 #endif
1060  return Communicator_pt;
1061 
1062 #else // ifndef MPI
1063 
1064  // If MPI is not enabled then we are unlikely to have called init, so to
1065  // be nice to users create a new serial comm_pt if none exits.
1066 
1067  if (Communicator_pt == 0)
1068  {
1070  }
1071 
1072  // #ifdef PARANOID
1073  // if(!Communicator_pt->serial_communicator())
1074  // {
1075  // std::string error_msg =
1076  // "MPI_Helpers has somehow ended up with a non-serial\n"
1077  // + "communicator pointer even though MPI is disabled!";
1078  // throw OomphLibError(error_msg.str(),
1079  // OOMPH_CURRENT_FUNCTION,
1080  // OOMPH_EXCEPTION_LOCATION);
1081  // }
1082  // #endif
1083 
1084  return Communicator_pt;
1085 
1086 #endif // end ifdef MPI
1087  }
1088 
1091 
1092 
1093  //====================================================================
1094  /// Namespace for flagging up obsolete parts of the code
1095  //====================================================================
1096  namespace ObsoleteCode
1097  {
1098  /// Flag up obsolete parts of the code
1099  bool FlagObsoleteCode = true;
1100 
1101  /// Output warning message
1102  void obsolete()
1103  {
1104  if (FlagObsoleteCode)
1105  {
1106  std::string junk;
1107  oomph_info << "\n\n--------------------------------------------\n";
1108  oomph_info << "You are using obsolete code " << std::endl;
1109  oomph_info << "--------------------------------------------\n\n";
1110  oomph_info << "Enter: \"s\" to suppress further messages" << std::endl;
1111  oomph_info << " \"k\" to crash the code to allow a trace back in "
1112  "the debugger"
1113  << std::endl;
1114 
1115  oomph_info << " any other key to continue\n \n";
1116  oomph_info << " [Note: Insert \n \n ";
1117  oomph_info << " "
1118  "ObsoleteCode::FlagObsoleteCode=false;\n \n";
1119  oomph_info << " into your code to suppress these "
1120  "messages \n";
1121  oomph_info << " altogether.] \n";
1122 
1123  std::cin >> junk;
1124  if (junk == "s")
1125  {
1126  FlagObsoleteCode = false;
1127  }
1128  if (junk == "k")
1129  {
1130  throw OomphLibError(
1131  "Killed", OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1132  }
1133  }
1134  }
1135 
1136 
1137  /// Ouput a warning message with a string argument
1138  void obsolete(const std::string& message)
1139  {
1140  if (FlagObsoleteCode)
1141  {
1142  oomph_info << "\n\n------------------------------------" << std::endl;
1143  oomph_info << message << std::endl;
1144  oomph_info << "----------------------------------------" << std::endl;
1145 
1146  obsolete();
1147  }
1148  }
1149 
1150  } // namespace ObsoleteCode
1151 
1152 
1153  //====================================================================
1154  /// Namespace for tecplot stuff
1155  //====================================================================
1156  namespace TecplotNames
1157  {
1158  /// Tecplot colours
1160 
1161 
1162  /// Setup namespace
1163  void setup()
1164  {
1165  colour.resize(5);
1166  colour[0] = "RED";
1167  colour[1] = "GREEN";
1168  colour[2] = "BLUE";
1169  colour[3] = "CYAN";
1170  colour[4] = "BLACK";
1171  }
1172 
1173 
1174  } // namespace TecplotNames
1175 
1176 
1177 #ifdef LEAK_CHECK
1178 
1179  //====================================================================
1180  /// Namespace for leak check: Keep a running count of all instantiated
1181  /// objects -- add your own if you want to...
1182  //====================================================================
1183  namespace LeakCheckNames
1184  {
1196 
1197  void reset()
1198  {
1199  QuadTree_build = 0;
1200  OcTree_build = 0;
1202  OcTreeForest_build = 0;
1205  MacroElement_build = 0;
1206  HangInfo_build = 0;
1207  Node_build = 0;
1208  GeomReference_build = 0;
1209  AlgebraicNode_build = 0;
1210  }
1211 
1212  void doc()
1213  {
1214  oomph_info << "\n Leak check: # of builds - # of deletes for the "
1215  "following objects: \n\n";
1216  oomph_info << "LeakCheckNames::QuadTree_build "
1217  << LeakCheckNames::QuadTree_build << std::endl;
1218  oomph_info << "LeakCheckNames::QuadTreeForest_build "
1219  << LeakCheckNames::QuadTreeForest_build << std::endl;
1220  oomph_info << "LeakCheckNames::OcTree_build "
1221  << LeakCheckNames::OcTree_build << std::endl;
1222  oomph_info << "LeakCheckNames::OcTreeForest_build "
1223  << LeakCheckNames::OcTreeForest_build << std::endl;
1224  oomph_info << "LeakCheckNames::RefineableQElement<2>_build "
1225  << LeakCheckNames::RefineableQElement<2> _build << std::endl;
1226  oomph_info << "LeakCheckNames::RefineableQElement<3>_build "
1227  << LeakCheckNames::RefineableQElement<3> _build << std::endl;
1228  oomph_info << "LeakCheckNames::MacroElement_build "
1229  << LeakCheckNames::MacroElement_build << std::endl;
1230  oomph_info << "LeakCheckNames::HangInfo_build "
1231  << LeakCheckNames::HangInfo_build << std::endl;
1232  oomph_info << "LeakCheckNames::Node_build " << LeakCheckNames::Node_build
1233  << std::endl;
1234  oomph_info << "LeakCheckNames::GeomReference_build "
1235  << LeakCheckNames::GeomReference_build << std::endl;
1236  oomph_info << "LeakCheckNames::AlgebraicNode_build "
1237  << LeakCheckNames::AlgebraicNode_build << std::endl;
1238  oomph_info << std::endl;
1239  }
1240 
1241 
1242  } // namespace LeakCheckNames
1243 
1244 
1245 #endif
1246 
1247 
1248  /// ////////////////////////////////////////////////////////////////////////
1249  /// //////////////////////////////////////////////////////////////////////////
1250 
1251 
1252  //====================================================================
1253  /// Namespace for pause() command
1254  //====================================================================
1255  namespace PauseFlags
1256  {
1257  /// Flag to enable pausing code -- pause the code by default
1258  bool PauseFlag = true;
1259 
1260  } // namespace PauseFlags
1261 
1262  //======================================================================
1263  /// Pause and display message
1264  //======================================================================
1265  void pause(std::string message)
1266  {
1267  std::string junk;
1269  {
1270  oomph_info << message << "\n hit any key to continue [hit \"S\" "
1271  << "to suppress further interruptions]\n";
1272  std::cin >> junk;
1273  if (junk == "S")
1274  {
1275  PauseFlags::PauseFlag = false;
1276  }
1277  }
1278  else
1279  {
1280  oomph_info << "\n[Suppressed pause message] \n";
1281  }
1282  }
1283 
1284 
1285  /// ////////////////////////////////////////////////////////////////////////
1286  /// ////////////////////////////////////////////////////////////////////////
1287  /// ////////////////////////////////////////////////////////////////////////
1288 
1289  //=============================================================================
1290  /// Helper for recording execution time.
1291  //=============================================================================
1292  namespace TimingHelpers
1293  {
1294  /// returns the time in seconds after some point in past
1295  double timer()
1296  {
1297 #ifdef OOMPH_HAS_MPI
1299  {
1300  return MPI_Wtime();
1301  }
1302  else
1303 #endif
1304  {
1305  time_t t = clock();
1306  return double(t) / double(CLOCKS_PER_SEC);
1307  }
1308  }
1309 
1310  /// Returns a nicely formatted string from an input time in seconds;
1311  /// the format depends on the size of time, e.g.:
1312  /// 86510 will be printed as 1d 1m:50
1313  /// 3710 will be printed as 1h:01:50
1314  /// 700 will be printed as 11m:40
1315  /// 59 will be printed as 59s
1317  {
1318  std::ostringstream ss;
1319 
1320  unsigned sec_within_day = unsigned(time_in_sec) % (3600 * 24);
1321 
1322  unsigned days = unsigned(time_in_sec) / (3600 * 24);
1323  unsigned hours = sec_within_day / 3600;
1324  unsigned minutes = (sec_within_day % 3600) / 60;
1325  unsigned seconds = (sec_within_day % 3600) % 60;
1326 
1327  if (days > 0)
1328  {
1329  ss << days << "d ";
1330  }
1331 
1332  if (hours > 0)
1333  {
1334  ss << hours << "h:";
1335  ss << std::setw(2) << std::setfill('0');
1336  ss << minutes << ":";
1337  ss << seconds;
1338  }
1339  else if (minutes > 0)
1340  {
1341  ss << minutes << "m:";
1342  ss << std::setw(2) << std::setfill('0');
1343  ss << seconds;
1344  }
1345  else
1346  {
1347  double seconds_double = seconds + (time_in_sec - double(seconds));
1348  ss << std::setprecision(1) << std::fixed << seconds_double << "s";
1349  }
1350 
1351  return ss.str();
1352  }
1353  } // end of namespace TimingHelpers
1354 
1355 
1356  /// /////////////////////////////////////////////////////////////////
1357  /// /////////////////////////////////////////////////////////////////
1358  /// /////////////////////////////////////////////////////////////////
1359 
1360 
1361  //===============================================================
1362  /// Namespace with helper functions to assess total memory usage
1363  /// on the fly using system() -- details are very machine specific! This just
1364  /// provides the overall machinery with default settings for
1365  /// our own (linux machines). Uses the system command
1366  /// to spawn a command that computes the total memory usage
1367  /// on the machine where this is called. [Disclaimer: works
1368  /// on my machine(s) -- no guarantees for any other platform;
1369  /// linux or not. MH]
1370  //===============================================================
1371  namespace MemoryUsage
1372  {
1373  /// Boolean to suppress synchronisation of doc memory
1374  /// usage on processors (via mpi barriers). True (i.e. sync is
1375  /// suppressed) by default because not all processors may
1376  /// reach the relevant doc memory usage statements
1377  /// causing the code to hang).
1379 
1380  /// String containing system command that obtains memory usage
1381  /// of all processes.
1382  /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1383  /// no guarantees for any other platform; linux or not. MH]
1385 
1386  /// Bool allowing quick bypassing of ALL operations related
1387  /// to memory usage monitoring -- this allows the code to remain
1388  /// "instrumented" without incurring the heavy penalties associated
1389  /// with the system calls and i/o. Default setting: false.
1391 
1392  /// String containing name of file in which we document
1393  /// my memory usage -- you may want to change this to allow different
1394  /// processors to write to separate files (especially in mpi
1395  /// context). Note that file is appended to
1396  /// so it ought to be emptied (either manually or by calling
1397  /// helper function empty_memory_usage_file()
1398  std::string My_memory_usage_filename = "my_memory_usage.dat";
1399 
1400  /// Function to empty file that records my memory usage in
1401  /// file whose name is specified by My_memory_usage_filename.
1403  {
1404  // bail out straight away?
1406 
1407  // Open without appending and write header
1408  std::ofstream the_file;
1409  the_file.open(My_memory_usage_filename.c_str());
1410  the_file << "# My memory usage: \n";
1411  the_file.close();
1412  }
1413 
1414 
1415 #ifdef OOMPH_HAS_UNISTDH
1416 
1417  /// Doc my memory usage, prepended by string (which allows
1418  /// identification from where the function is called, say) that records
1419  /// memory usage in file whose name is specified by
1420  /// My_memory_usage_filename. Data is appended to that file; wipe it with
1421  /// empty_my_memory_usage_file(). Note: This requires getpid() which is
1422  /// defined in unistd.h so if you don't have that we won't build that
1423  /// function!
1424  void doc_my_memory_usage(const std::string& prefix_string)
1425  {
1426  // bail out straight away?
1428 
1429  // Write prefix
1430  std::ofstream the_file;
1431  the_file.open(My_memory_usage_filename.c_str(), std::ios::app);
1432  the_file << prefix_string << " ";
1433  the_file.close();
1434 
1435  // Sync all processors if in parallel (unless suppressed)
1436 #ifdef OOMPH_HAS_MPI
1439  {
1440  MPI_Barrier(MPI_Helpers::communicator_pt()->mpi_comm());
1441  }
1442 #endif
1443 
1444  // Process memory usage command and write to file
1445  std::stringstream tmp;
1446  tmp << My_memory_usage_system_string << " | awk '{if ($2==" << getpid()
1447  << "){print $4}}' >> " << My_memory_usage_filename;
1448  int success = system(tmp.str().c_str());
1449 
1450  // Dummy command to shut up compiler warnings
1451  success += 1;
1452  }
1453 
1454 #endif
1455 
1456  /// String containing system command that obtains total memory usage.
1457  /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1458  /// no guarantees for any other platform; linux or not. MH]
1460  "ps aux | awk 'BEGIN{sum=0}{sum+=$4}END{print sum}'";
1461 
1462  /// String containing name of file in which we document total
1463  /// memory usage -- you may want to change this to allow different
1464  /// processors to write to separate files (especially in mpi
1465  /// context). Note that file is appended to
1466  /// so it ought to be emptied (either manually or by calling
1467  /// helper function empty_memory_usage_file()
1469 
1470  /// Function to empty file that records total memory usage in
1471  /// file whose name is specified by Total_memory_usage_filename.
1473  {
1474  // bail out straight away?
1476 
1477  // Open without appending and write header
1478  std::ofstream the_file;
1479  the_file.open(Total_memory_usage_filename.c_str());
1480  the_file << "# Total memory usage: \n";
1481  the_file.close();
1482  }
1483 
1484  /// Doc total memory usage, prepended by string (which allows
1485  /// identification from where the function is called, say) that records
1486  /// memory usage in file whose name is specified by
1487  /// Total_memory_usage_filename. Data is appended to that file; wipe it with
1488  /// empty_memory_usage_file().
1489  void doc_total_memory_usage(const std::string& prefix_string)
1490  {
1491  // bail out straight away?
1493 
1494  // Write prefix
1495  std::ofstream the_file;
1496  the_file.open(Total_memory_usage_filename.c_str(), std::ios::app);
1497  the_file << prefix_string << " ";
1498  the_file.close();
1499 
1500  // Sync all processors if in parallel
1501 #ifdef OOMPH_HAS_MPI
1504  {
1505  MPI_Barrier(MPI_Helpers::communicator_pt()->mpi_comm());
1506  }
1507 #endif
1508 
1509  // Process memory usage command and write to file
1510  std::stringstream tmp;
1511  tmp << Total_memory_usage_system_string << " >> "
1513  int success = system(tmp.str().c_str());
1514 
1515  // Dummy command to shut up compiler warnings
1516  success += 1;
1517  }
1518 
1519 
1520  /// Function to empty file that records total and local memory usage
1521  /// in appropriate files
1523  {
1524  // bail out straight away?
1526 
1529  empty_top_file();
1530  }
1531 
1532  /// Doc total and local memory usage, prepended by string (which
1533  /// allows identification from where the function is called, say). NOTE:
1534  /// Local memory usage only works if we have unistd.h header
1535  void doc_memory_usage(const std::string& prefix_string)
1536  {
1537  // bail out straight away?
1539 
1540 #ifdef OOMPH_HAS_UNISTDH
1541  doc_my_memory_usage(prefix_string);
1542 #endif
1543 
1544  doc_total_memory_usage(prefix_string);
1545  }
1546 
1547 
1548  /// String containing system command that runs "top" (or equivalent)
1549  /// "indefinitely" and writes to file specified in Top_output_filename.
1550  /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1551  /// no guarantees for any other platform; linux or not. MH]
1552  std::string Top_system_string = "while true; do top -b -n 2 ; done ";
1553 
1554  /// String containing name of file in which we document "continuous"
1555  /// output from "top" (or equivalent)-- you may want to change this to
1556  /// allow different processors to write to separate files (especially in mpi
1557  /// context). Note that file is appended to
1558  /// so it ought to be emptied (either manually or by calling
1559  /// helper function empty_top_file()
1560  std::string Top_output_filename = "top_output.dat";
1561 
1562  /// Function to empty file that records continuous output from top in
1563  /// file whose name is specified by Top_output_filename
1565  {
1566  // bail out straight away?
1568 
1569  // Open without appending and write header
1570  std::ofstream the_file;
1571  the_file.open(Top_output_filename.c_str());
1572  the_file << "# Continuous output from top obtained with: \n";
1573  the_file << "# " << Top_system_string << "\n";
1574  the_file.close();
1575  }
1576 
1577 
1578  /// Start running top continuously and output (append) into
1579  /// file specified by Top_output_filename. Wipe that file with
1580  /// empty_top_file() if you wish. Note that this is again quite Linux
1581  /// specific and unlikely to work on other operating systems. Insert
1582  /// optional comment into output file before starting.
1583  void run_continous_top(const std::string& comment)
1584  {
1585  // bail out straight away?
1587 
1588  // Sync all processors if in parallel
1589  std::string modifier = "";
1590 
1591 #ifdef OOMPH_HAS_MPI
1593  {
1595  {
1596  MPI_Barrier(MPI_Helpers::communicator_pt()->mpi_comm());
1597  }
1598  std::stringstream tmp;
1599  tmp << "_proc" << MPI_Helpers::communicator_pt()->my_rank();
1600  modifier = tmp.str();
1601  }
1602 #endif
1603 
1604  // Process memory usage command and write to file
1605  std::stringstream tmp;
1606 
1607  // String stream seems unhappy about direct insertions of these
1608  std::string backslash = "\\";
1609  std::string dollar = "$";
1610 
1611  // Create files that spawn and kill continuous top
1612  tmp << "echo \"#/bin/bash\" > run_continuous_top" << modifier << ".bash; "
1613  << "echo \" echo " << backslash << "\" kill " << backslash << dollar
1614  << backslash << dollar << " " << backslash
1615  << "\" > kill_continuous_top" << modifier
1616  << ".bash; chmod a+x kill_continuous_top" << modifier << ".bash; "
1617  << Top_system_string << " \" >> run_continuous_top" << modifier
1618  << ".bash; chmod a+x run_continuous_top" << modifier << ".bash ";
1619  int success = system(tmp.str().c_str());
1620 
1621  // Add comment to annotate?
1622  if (comment != "")
1623  {
1625  }
1626 
1627  // Start spawning
1628  std::stringstream tmp2;
1629  tmp2 << "./run_continuous_top" << modifier << ".bash >> "
1630  << Top_output_filename << " & ";
1631  success = system(tmp2.str().c_str());
1632 
1633  // Dummy command to shut up compiler warnings
1634  success += 1;
1635  }
1636 
1637 
1638  /// Stop running top continuously. Note that this is
1639  /// again quite Linux specific and unlikely to work on other operating
1640  /// systems. Insert optional comment into output file before stopping.
1641  void stop_continous_top(const std::string& comment)
1642  {
1643  // bail out straight away?
1645 
1646  // Sync all processors if in parallel
1647  std::string modifier = "";
1648 
1649 #ifdef OOMPH_HAS_MPI
1651  {
1653  {
1654  MPI_Barrier(MPI_Helpers::communicator_pt()->mpi_comm());
1655  }
1656  std::stringstream tmp;
1657  tmp << "_proc" << MPI_Helpers::communicator_pt()->my_rank();
1658  modifier = tmp.str();
1659  }
1660 #endif
1661 
1662  // Add comment to annotate?
1663  if (comment != "")
1664  {
1666  }
1667 
1668  // Kill
1669  std::stringstream tmp2;
1670  tmp2 << "./kill_continuous_top" << modifier << ".bash >> "
1671  << Top_output_filename << " & ";
1672  int success = system(tmp2.str().c_str());
1673 
1674  // Dummy command to shut up compiler warnings
1675  success += 1;
1676  }
1677 
1678 
1679  /// Insert comment into running continuous top output
1681  {
1682  // bail out straight away?
1684 
1685  std::stringstream tmp;
1686  tmp << " echo \"OOMPH-LIB EVENT: " << comment << "\" >> "
1688  int success = system(tmp.str().c_str());
1689 
1690  // Dummy command to shut up compiler warnings
1691  success += 1;
1692  }
1693 
1694 
1695  } // end of namespace MemoryUsage
1696 
1697 
1698 } // namespace oomph
static char t char * s
Definition: cfortran.h:568
cstr elem_len * i
Definition: cfortran.h:603
char t
Definition: cfortran.h:568
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:485
bool Directory_must_exist
Boolean flag to decide response if an output directory doesn't exist: If true, we terminate code exec...
std::string Directory
Directory name.
void set_directory(const std::string &directory)
Set output directory (we try to open a file in it to see if the directory exists – if it doesn't we'l...
MPI output modifier: Precedes every output by specification of the processor ID. Output can be restri...
OomphCommunicator *& communicator_pt()
Return pointer to communicator.
OomphCommunicator * Communicator_pt
Communicator.
virtual bool operator()(std::ostream &stream)
Precede the output by the processor ID but output everything.
bool Output_from_single_processor
Boolean to control if output is performed only on a single processor (default: false)
unsigned Output_rank
Rank of single processor that produces output (only used if Output_from_single_processor=true.
static void finalize()
finalize mpi (oomph-lib equivalent of MPI_Finalize()) Deletes the global oomph-lib communicator and f...
static void init(int argc, char **argv, const bool &make_duplicate_of_mpi_comm_world=true)
initialise mpi (oomph-libs equivalent of MPI_Init(...)) Initialises MPI and creates the global oomph-...
static OomphCommunicator * Communicator_pt
the global communicator
static bool mpi_has_been_initialised()
return true if MPI has been initialised
static bool MPI_has_been_initialised
Bool set to true if MPI has been initialised.
static OomphCommunicator * communicator_pt()
access to global communicator. This is the oomph-lib equivalent of MPI_COMM_WORLD
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Definition: communicator.h:54
OutputModifier *& output_modifier_pt()
Access function for the output modifier pointer.
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
Refineable version of QElement<2,NNODE_1D>.
Refineable version of QElement<3,NNODE_1D>.
void set_text_effect(std::string text_effect)
Function to change text effect. NOTE: This assumes the user knows what they're doing/assigning; no er...
std::string Text_effect
Variable to decide on effects.
std::string Black
The code for each type of colour.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
void setup(int argc, char **argv)
Set values.
void doc_available_flags()
Document available command line flags.
std::map< std::string, ArgInfo< bool > > Specified_command_line_flag
Map to indicate an input flag as having been set.
char ** Argv
Arguments themselves.
bool command_line_flag_has_been_set(const std::string &flag)
Check if command line flag has been set (value will have been assigned directly).
void specify_command_line_flag(const std::string &command_line_flag, const std::string &doc)
Specify possible argument-free command line flag.
void check_arg_index(const int &argc, const int &arg_index)
Helper function to check if command line index is legal.
void doc_all_flags(std::ostream &outstream)
Document the values of all flags (specified or not).
std::map< std::string, ArgInfo< std::string > > Specified_command_line_string_pt
Map to associate an input flag with a string – specified via pointer.
std::map< std::string, ArgInfo< int > > Specified_command_line_int_pt
Map to associate an input flag with an int – specified via pointer.
void parse_and_assign(int argc, char *argv[], const bool &throw_on_unrecognised_args)
Parse command line, check for recognised flags and assign associated values.
std::map< std::string, ArgInfo< double > > Specified_command_line_double_pt
Map to associate an input flag with a double – specified via pointer.
int Argc
Number of arguments + 1.
void output()
Doc the command line arguments.
std::map< std::string, ArgInfo< unsigned > > Specified_command_line_unsigned_pt
Map to associate an input flag with an unsigned – specified via pointer.
void doc_specified_flags()
Document specified command line flags.
double cumulative_time(const unsigned &i)
Report time accumulated by i-th timer.
void set_ntimers(const unsigned &ntimers)
Set number of timings that can be recorded in parallel.
void reset(const unsigned &i)
Reset i-th timer.
Vector< clock_t > Timing
Cumulative timings.
void halt(const unsigned &i)
Halt i-th timer.
Vector< clock_t > Start_time
Start times of active timers.
void start(const unsigned &i)
(Re-)start i-th timer
std::string debug_string(const std::string &filename, const int &line, const bool &make_new_line)
Return the concaternation of the initials of the input file name and line number. The make_new_line f...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
long RefineableQElement< 2 > _build
void empty_top_file()
Function to empty file that records continuous output from top in file whose name is specified by Top...
std::string Top_output_filename
String containing name of file in which we document "continuous" output from "top" (or equivalent)– y...
bool Bypass_all_memory_usage_monitoring
Bool allowing quick bypassing of ALL operations related to memory usage monitoring – this allows the ...
void doc_total_memory_usage(const std::string &prefix_string)
Doc total memory usage, prepended by string (which allows identification from where the function is c...
void insert_comment_to_continous_top(const std::string &comment)
Insert comment into running continuous top output.
void doc_my_memory_usage(const std::string &prefix_string)
Doc my memory usage, prepended by string (which allows identification from where the function is call...
void empty_memory_usage_files()
Function to empty file that records total and local memory usage in appropriate files.
void run_continous_top(const std::string &comment)
Start running top continuously and output (append) into file specified by Top_output_filename....
std::string Top_system_string
String containing system command that runs "top" (or equivalent) "indefinitely" and writes to file sp...
void stop_continous_top(const std::string &comment)
Stop running top continuously. Note that this is again quite Linux specific and unlikely to work on o...
bool Suppress_mpi_synchronisation
Boolean to suppress synchronisation of doc memory usage on processors (via mpi barriers)....
void empty_total_memory_usage_file()
Function to empty file that records total memory usage in file whose name is specified by Total_memor...
std::string Total_memory_usage_system_string
String containing system command that obtains total memory usage. Default assignment for linux....
void doc_memory_usage(const std::string &prefix_string)
Doc total and local memory usage, prepended by string (which allows identification from where the fun...
std::string My_memory_usage_filename
String containing name of file in which we document my memory usage – you may want to change this to ...
void empty_my_memory_usage_file()
Function to empty file that records my memory usage in file whose name is specified by My_memory_usag...
std::string My_memory_usage_system_string
String containing system command that obtains memory usage of all processes. Default assignment for l...
std::string Total_memory_usage_filename
String containing name of file in which we document total memory usage – you may want to change this ...
void obsolete()
Output warning message.
bool FlagObsoleteCode
Flag up obsolete parts of the code.
bool PauseFlag
Flag to enable pausing code – pause the code by default.
double second_invariant(const DenseMatrix< double > &tensor)
Compute second invariant of tensor.
void split_string(const std::string &s, char delim, Vector< std::string > &elems)
Split a string, s, into a vector of strings where ever there is an instance of delimiter (i....
std::string to_lower(const std::string &input)
Convert a string to lower case (outputs a copy).
std::string to_upper(const std::string &input)
Convert a string to upper case (outputs a copy).
Vector< std::string > colour
Tecplot colours.
void setup()
Setup namespace.
double timer()
returns the time in seconds after some point in past
std::string convert_secs_to_formatted_string(const double &time_in_sec)
Returns a nicely formatted string from an input time in seconds; the format depends on the size of ti...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
void pause(std::string message)
Pause and display message.
MPIOutputModifier oomph_mpi_output
Single (global) instantiation of the mpi output modifier.
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...
Structure to store information on a command line argument.