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-2025 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
42namespace 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
64 } // End of set_text_effect
65
66 /// Variable to decide on effects
67 std::string Text_effect = "1";
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
92 std::string debug_string(const std::string& filename,
93 const int& line_number,
94 const std::string& message,
95 const bool& shorten,
96 const bool& start_on_new_line)
97 {
98 // Temporary storage for the filename which can be edited
99 std::string file = filename;
100
101 // The delimeter
102 std::string delimiter = "_";
103
104 // Posiiton of the delimiter
105 size_t pos = 0;
106
107 // The string before the delimiter
108 std::string token;
109
110 // Get the filename (gets rid of e.g. ./ before filename)
111 while ((pos = file.find("/")) != std::string::npos)
112 {
113 // Get the string before the delimiter
114 token = file.substr(0, pos);
115
116 // Erase the string before the delimeter
117 file = file.substr(pos + delimiter.length());
118 }
119
120 // Make a string
121 std::string prefix{};
122
123 if (shorten)
124 {
125 // While we can find delimeters
126 while ((pos = file.find(delimiter)) != std::string::npos)
127 {
128 // Get the string before the delimiter
129 token = file.substr(0, pos);
130
131 // Output the string
132 prefix += toupper(token.at(0));
133
134 // Erase the delimeter
135 file = file.substr(pos + delimiter.length());
136 }
137
138 // Output the string
139 prefix += toupper(file.at(0));
140 }
141 else
142 {
143 // Output the string
144 prefix += file;
145 }
146
147 // Construct the full message and make the prefix bold red
148 std::string debug_string{};
150 {
151 debug_string = "\n";
152 }
153 debug_string += "\033[1;31m";
155 debug_string += ":";
156 debug_string += std::to_string(line_number);
157 debug_string += ":\033[0m ";
159 return debug_string;
160 } // End of create_debug_string
161 } // namespace DebugHelpers
162
163
164 //=====================================================================
165 /// Helper namespace containing function that computes second invariant
166 /// of tensor
167 //=====================================================================
168 namespace SecondInvariantHelper
169 {
170 /// Compute second invariant of tensor
172 {
173 // get size of tensor
174 unsigned n = tensor.nrow();
175 double trace_of_tensor = 0.0;
176 double trace_of_tensor_squared = 0.0;
177 for (unsigned i = 0; i < n; i++)
178 {
179 // Calculate the trace of the tensor: T_ii
181 // Calculate the trace of the tensor squared: T_ij T_ji
182 for (unsigned j = 0; j < n; j++)
183 {
185 }
186 }
187
188 // return the second invariant: 1.0/2.0*[(T_ii)^2 - T_ij T_ji]
189 return 0.5 *
191 }
192
193 } // namespace SecondInvariantHelper
194
195
196 //==============================================
197 /// Namespace for error messages for broken
198 /// copy constructors and assignment operators
199 //==============================================
200 namespace BrokenCopy
201 {
202 /// Issue error message and terminate execution
203 void broken_assign(const std::string& class_name)
204 {
205 // Write the error message into a string
206 std::string error_message = "Assignment operator for class\n\n";
207 error_message += class_name;
208 error_message += "\n\n";
209 error_message += "is deliberately broken to avoid the accidental \n";
210 error_message += "use of the inappropriate C++ default.\n";
211 error_message += "If you really need an assignment operator\n";
212 error_message += "for this class, write it yourself...\n";
213
214 throw OomphLibError(
215 error_message, "broken_assign()", OOMPH_EXCEPTION_LOCATION);
216 }
217
218
219 /// Issue error message and terminate execution
220 void broken_copy(const std::string& class_name)
221 {
222 // Write the error message into a string
223 std::string error_message = "Copy constructor for class\n\n";
224 error_message += class_name;
225 error_message += "\n\n";
226 error_message += "is deliberately broken to avoid the accidental\n";
227 error_message += "use of the inappropriate C++ default.\n";
228 error_message +=
229 "All function arguments should be passed by reference or\n";
230 error_message +=
231 "constant reference. If you really need a copy constructor\n";
232 error_message += "for this class, write it yourself...\n";
233
234 throw OomphLibError(
236 }
237 } // namespace BrokenCopy
238
239
240 //////////////////////////////////////////////////////////////////
241 //////////////////////////////////////////////////////////////////
242 //////////////////////////////////////////////////////////////////
243
244
245 //====================================================================
246 /// Namespace for global (cumulative) timings
247 //====================================================================
248 namespace CumulativeTimings
249 {
250 /// (Re-)start i-th timer
251 void start(const unsigned& i)
252 {
253 Start_time[i] = clock();
254 }
255
256 /// Halt i-th timer
257 void halt(const unsigned& i)
258 {
259 Timing[i] += clock() - Start_time[i];
260 }
261
262 /// Report time accumulated by i-th timer
263 double cumulative_time(const unsigned& i)
264 {
265 return double(Timing[i]) / CLOCKS_PER_SEC;
266 }
267
268 /// Reset i-th timer
269 void reset(const unsigned& i)
270 {
271 Timing[i] = clock_t(0.0);
272 }
273
274 /// Reset all timers
275 void reset()
276 {
277 unsigned n = Timing.size();
278 for (unsigned i = 0; i < n; i++)
279 {
280 Timing[i] = clock_t(0.0);
281 }
282 }
283
284 /// Set number of timings that can be recorded in parallel
285 void set_ntimers(const unsigned& ntimers)
286 {
287 Timing.resize(ntimers, clock_t(0.0));
288 Start_time.resize(ntimers, clock_t(0.0));
289 }
290
291 /// Cumulative timings
293
294 /// Start times of active timers
296
297 } // namespace CumulativeTimings
298
299
300 //======================================================================
301 /// Set output directory (we try to open a file in it
302 /// to see if the directory exists -- if it doesn't we'll
303 /// issue a warning -- or, if directory_must_exist()==true,
304 /// die by throwing and OomphLibError
305 //======================================================================
306 void DocInfo::set_directory(const std::string& directory_)
307 {
308 // Try to open a file in output directory
309 std::ostringstream filename;
310 filename << directory_ << "/.dummy_check.dat";
311 std::ofstream some_file;
312 some_file.open(filename.str().c_str());
313 if (!some_file.is_open())
314 {
315 // Construct the error message
316 std::string error_message = "Problem opening output file.\n";
317 error_message += "I suspect you haven't created the output directory ";
318 error_message += directory_;
319 error_message += "\n";
320
321 // Issue a warning if the directory does not have to exist
323 {
324 // Create an Oomph Lib warning
326 error_message, "set_directory()", OOMPH_EXCEPTION_LOCATION);
327 }
328 // Otherwise throw an error
329 else
330 {
331 error_message += "and the Directory_must_exist flag is true.\n";
332 throw OomphLibError(
334 }
335 }
336 // Write to the dummy file
337 some_file << "Dummy file, opened to check if output directory "
338 << std::endl;
339 some_file << "exists. Can be deleted...." << std::endl;
340 some_file.close();
341 // Set directory
343 }
344
345
346 // =================================================================
347 /// Conversion functions for easily making strings (e.g. for filenames - to
348 /// avoid stack smashing problems with cstrings and long filenames).
349 // =================================================================
350 namespace StringConversion
351 {
352 /// Convert a string to lower case (outputs a copy).
353 std::string to_lower(const std::string& input)
354 {
355 std::string output(input);
356 std::string::iterator it;
357 for (it = output.begin(); it != output.end(); ++it)
358 {
359 ::tolower(*it);
360 }
361
362 return output;
363 }
364
365 /// Convert a string to upper case (outputs a copy).
366 std::string to_upper(const std::string& input)
367 {
368 std::string output(input);
369 std::string::iterator it;
370 for (it = output.begin(); it != output.end(); ++it)
371 {
372 ::toupper(*it);
373 }
374 return output;
375 }
376
377 /// Split a string, s, into a vector of strings where ever there is
378 /// an instance of delimiter (i.e. is delimiter is " " will give a list of
379 /// words). Note that mutliple delimiters in a row will give empty
380 /// strings.
381 void split_string(const std::string& s,
382 char delim,
384 {
385 // From http://stackoverflow.com/questions/236129/splitting-a-string-in-c
386 std::stringstream ss(s);
387 std::string item;
388 while (std::getline(ss, item, delim))
389 {
390 elems.push_back(item);
391 }
392 }
393
394 /// Split a string, s, into a vector of strings where ever there is
395 /// an instance of delimiter (i.e. is delimiter is " " will give a list of
396 /// words). Note that mutliple delimiters in a row will give empty
397 /// strings. Return by value.
398 Vector<std::string> split_string(const std::string& s, char delim)
399 {
400 // From http://stackoverflow.com/questions/236129/splitting-a-string-in-c
403 return elems;
404 }
405
406 } // namespace StringConversion
407
408
409 //====================================================================
410 /// Namespace for command line arguments
411 //====================================================================
412 namespace CommandLineArgs
413 {
414 /// Number of arguments + 1
415 int Argc;
416
417 /// Arguments themselves
418 char** Argv;
419
420 /// Map to indicate an input flag as having been set
421 std::map<std::string, ArgInfo<bool>> Specified_command_line_flag;
422
423 /// Map to associate an input flag with a double -- specified via pointer
424 std::map<std::string, ArgInfo<double>> Specified_command_line_double_pt;
425
426 /// Map to associate an input flag with an int -- specified via pointer
427 std::map<std::string, ArgInfo<int>> Specified_command_line_int_pt;
428
429 /// Map to associate an input flag with an unsigned -- specified via pointer
430 std::map<std::string, ArgInfo<unsigned>> Specified_command_line_unsigned_pt;
431
432 /// Map to associate an input flag with a string -- specified via pointer
433 std::map<std::string, ArgInfo<std::string>>
435
436 /// Set values
437 void setup(int argc, char** argv)
438 {
439 Argc = argc;
440 Argv = argv;
441 }
442
443 /// Doc the command line arguments
444 void output()
445 {
446 oomph_info << "You are running the program: " << CommandLineArgs::Argv[0]
447 << std::endl;
448 oomph_info << "with the following command line args: " << std::endl;
449 std::stringstream str;
450 for (int i = 1; i < CommandLineArgs::Argc; i++)
451 {
452 str << CommandLineArgs::Argv[i] << " ";
453 }
454 oomph_info << str.str() << std::endl;
455 }
456
457
458 /// Specify possible argument-free command line flag
460 const std::string& doc)
461 {
463 ArgInfo<bool>(false, 0, doc);
464 }
465
466 /// Specify possible command line flag that specifies a double,
467 /// accessed via pointer
469 double* arg_pt,
470 const std::string& doc)
471 {
473 ArgInfo<double>(false, arg_pt, doc);
474 }
475
476 /// Specify possible command line flag that specifies an int,
477 /// accessed via pointer
479 int* arg_pt,
480 const std::string& doc)
481 {
483 ArgInfo<int>(false, arg_pt, doc);
484 }
485
486 /// Specify possible command line flag that specifies an unsigned,
487 /// accessed via pointer
489 unsigned* arg_pt,
490 const std::string& doc)
491 {
493 ArgInfo<unsigned>(false, arg_pt, doc);
494 }
495
496 /// Specify possible command line flag that specifies a string,
497 /// accessed via pointer
499 std::string* arg_pt,
500 const std::string& doc)
501 {
503 ArgInfo<std::string>(false, arg_pt, doc);
504 }
505
506
507 /// Check if command line flag has been set (value will have been
508 /// assigned directly).
509 bool command_line_flag_has_been_set(const std::string& flag)
510 {
511 for (std::map<std::string, ArgInfo<bool>>::iterator it =
514 it++)
515 {
516 if (it->first == flag)
517 {
518 return it->second.is_set;
519 }
520 }
521
522 for (std::map<std::string, ArgInfo<double>>::iterator it =
525 it++)
526 {
527 if (it->first == flag)
528 {
529 return (it->second).is_set;
530 }
531 }
532
533 for (std::map<std::string, ArgInfo<int>>::iterator it =
536 it++)
537 {
538 if (it->first == flag)
539 {
540 return (it->second).is_set;
541 }
542 }
543
544 for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
547 it++)
548 {
549 if (it->first == flag)
550 {
551 return (it->second).is_set;
552 }
553 }
554
555 for (std::map<std::string, ArgInfo<std::string>>::iterator it =
558 it++)
559 {
560 if (it->first == flag)
561 {
562 return (it->second).is_set;
563 }
564 }
565
566 return false;
567 }
568
569 /// Document the values of all flags (specified or not).
570 void doc_all_flags(std::ostream& outstream)
571 {
572 for (std::map<std::string, ArgInfo<bool>>::iterator it =
575 it++)
576 {
577 outstream << it->first << " " << it->second.is_set << std::endl;
578 }
579 for (std::map<std::string, ArgInfo<double>>::iterator it =
582 it++)
583 {
584 outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
585 }
586 for (std::map<std::string, ArgInfo<int>>::iterator it =
589 it++)
590 {
591 outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
592 }
593 for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
596 it++)
597 {
598 outstream << it->first << " " << *(it->second.arg_pt) << std::endl;
599 }
600 for (std::map<std::string, ArgInfo<std::string>>::iterator it =
603 it++)
604 {
605 // Quote blank strings, otherwise trying to parse the output in any way
606 // will go wrong.
607 std::string arg_string = *(it->second.arg_pt);
608 if (arg_string == "")
609 {
610 arg_string = "\"\"";
611 }
612
613 outstream << it->first << " " << arg_string << std::endl;
614 }
615 }
616
617 /// Document specified command line flags
619 {
620 oomph_info << std::endl;
621 oomph_info << "Specified (and recognised) command line flags:\n";
622 oomph_info << "----------------------------------------------\n";
623
624 for (std::map<std::string, ArgInfo<bool>>::iterator it =
627 it++)
628 {
629 if (it->second.is_set)
630 {
631 oomph_info << it->first << std::endl;
632 }
633 }
634
635 for (std::map<std::string, ArgInfo<double>>::iterator it =
638 it++)
639 {
640 if (it->second.is_set)
641 {
642 oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
643 }
644 }
645
646 for (std::map<std::string, ArgInfo<int>>::iterator it =
649 it++)
650 {
651 if (it->second.is_set)
652 {
653 oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
654 }
655 }
656
657 for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
660 it++)
661 {
662 if (it->second.is_set)
663 {
664 oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
665 }
666 }
667
668 for (std::map<std::string, ArgInfo<std::string>>::iterator it =
671 it++)
672 {
673 if (it->second.is_set)
674 {
675 oomph_info << it->first << " " << *(it->second.arg_pt) << std::endl;
676 }
677 }
678
679 oomph_info << std::endl;
680 }
681
682
683 /// Document available command line flags
685 {
686 oomph_info << std::endl;
687 oomph_info << "Available command line flags:\n";
688 oomph_info << "-----------------------------\n";
689
690 for (std::map<std::string, ArgInfo<bool>>::iterator it =
693 it++)
694 {
695 oomph_info << it->first << std::endl
696 << it->second.doc << std::endl
697 << std::endl;
698 }
699
700 for (std::map<std::string, ArgInfo<double>>::iterator it =
703 it++)
704 {
705 oomph_info << it->first << " <double> " << std::endl
706 << it->second.doc << std::endl
707 << std::endl;
708 }
709
710 for (std::map<std::string, ArgInfo<int>>::iterator it =
713 it++)
714 {
715 oomph_info << it->first << " <int> " << std::endl
716 << it->second.doc << std::endl
717 << std::endl;
718 }
719
720 for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
723 it++)
724 {
725 oomph_info << it->first << " <unsigned> " << std::endl
726 << it->second.doc << std::endl
727 << std::endl;
728 }
729
730 for (std::map<std::string, ArgInfo<std::string>>::iterator it =
733 it++)
734 {
735 oomph_info << it->first << " <string> " << std::endl
736 << it->second.doc << std::endl
737 << std::endl;
738 }
739
740 oomph_info << std::endl;
741 }
742
743
744 /// Helper function to check if command line index is legal
745 void check_arg_index(const int& argc, const int& arg_index)
746 {
747 if (arg_index >= argc)
748 {
749 output();
751 std::stringstream error_stream;
753 << "Tried to read more command line arguments than\n"
754 << "specified. This tends to happen if a required argument\n"
755 << "to a command line flag was omitted, e.g. by running \n\n"
756 << " ./a.out -some_double \n\n rather than\n\n"
757 << " ./a.out -some_double 1.23 \n\n"
758 << "To aid the debugging I've output the available\n"
759 << "command line arguments above.\n";
760 throw OomphLibError(
762 }
763 }
764
765
766 /// Parse command line, check for recognised flags and assign
767 /// associated values
769 char* argv[],
770 const bool& throw_on_unrecognised_args)
771 {
772 // Keep looping over command line arguments
773 int arg_index = 1;
774 while (arg_index < argc)
775 {
776 bool found_match = false;
777
778 if ((strcmp(argv[arg_index], "-help") == 0) ||
779 (strcmp(argv[arg_index], "--help") == 0))
780 {
782 << "NOTE: You entered --help or -help on the command line\n";
783 oomph_info << "so I'm going to tell you about this code's\n";
784 oomph_info << "available command line flags and then return.\n";
786
787#ifdef OOMPH_HAS_MPI
788 int flag;
790 if (flag != 0) MPI_Helpers::finalize();
791#endif
792 oomph_info << "Shutting down...\n";
793 exit(0);
794 }
795
796
797 // Check if the flag has been previously specified as a simple argument
798 // free command line argument
799 for (std::map<std::string, ArgInfo<bool>>::iterator it =
802 it++)
803 {
804 if (it->first == argv[arg_index])
805 {
807 found_match = true;
808 break;
809 }
810 }
811
812 if (!found_match)
813 {
814 // Check if the flag has been previously specified as a
815 // command line argument that specifies (and is followed by) a double
816 for (std::map<std::string, ArgInfo<double>>::iterator it =
819 it++)
820 {
821 if (it->first == argv[arg_index])
822 {
823 // Next command line argument specifies the double. Set it via
824 // the pointer
825 arg_index++;
827 it->second.is_set = true;
828 *(it->second.arg_pt) = atof(argv[arg_index]);
829 found_match = true;
830 break;
831 }
832 }
833 }
834
835
836 if (!found_match)
837 {
838 // Check if the flag has been previously specified as a
839 // command line argument that specifies (and is followed by) an int
840 for (std::map<std::string, ArgInfo<int>>::iterator it =
843 it++)
844 {
845 if (it->first == argv[arg_index])
846 {
847 // Next command line argument specifies the int. Set it via
848 // the pointer
849 arg_index++;
851 it->second.is_set = true;
852 *(it->second.arg_pt) = atoi(argv[arg_index]);
853 found_match = true;
854 break;
855 }
856 }
857 }
858
859
860 if (!found_match)
861 {
862 // Check if the flag has been previously specified as a
863 // command line argument that specifies (and is followed by) an
864 // unsigned
865 for (std::map<std::string, ArgInfo<unsigned>>::iterator it =
868 it++)
869 {
870 if (it->first == argv[arg_index])
871 {
872 // Next command line argument specifies the unsigned. Set it via
873 // the pointer
874 arg_index++;
876 it->second.is_set = true;
877 *(it->second.arg_pt) = unsigned(atoi(argv[arg_index]));
878 found_match = true;
879 break;
880 }
881 }
882 }
883
884
885 if (!found_match)
886 {
887 // Check if the flag has been previously specified as a
888 // command line argument that specifies (and is followed by) a string
889 for (std::map<std::string, ArgInfo<std::string>>::iterator it =
892 it++)
893 {
894 if (it->first == argv[arg_index])
895 {
896 // Next command line argument specifies the string. Set it via
897 // the pointer
898 arg_index++;
900 it->second.is_set = true;
901 *(it->second.arg_pt) = argv[arg_index];
902 found_match = true;
903 break;
904 }
905 }
906 }
907
908
909 // Oh dear, we still haven't found the argument in the list.
910 // Maybe it was specified wrongly -- issue warning.
911 if (!found_match)
912 {
913 // Construct the error message
914 std::string error_message = "Command line argument\n\n";
915 error_message += argv[arg_index];
916 error_message += "\n\nwas not recognised. This may be legal\n";
917 error_message += "but seems sufficiently suspicious to flag up.\n";
918 error_message += "If it should have been recognised, make sure you\n";
919 error_message += "used the right number of \"-\" signs...\n";
920
922 {
923 error_message += "Throwing an error because you requested it with";
924 error_message += " throw_on_unrecognised_args option.";
925 throw OomphLibError(
927 }
928 else
929 {
930 // Create an Oomph Lib warning
933 }
934 }
935
936
937 arg_index++;
938 }
939 }
940
941
942 /// Parse previously specified command line, check for
943 /// recognised flags and assign associated values
948
949 } // namespace CommandLineArgs
950
951#ifdef OOMPH_HAS_MPI
952 //========================================================================
953 /// Single (global) instantiation of the mpi output modifier
954 //========================================================================
956
957 //========================================================================
958 /// Precede the output by the processor ID but output everything
959 //========================================================================
961 {
962 int my_rank = Communicator_pt->my_rank();
963
965 {
966 stream << "Processor " << my_rank << ": ";
967 // Continue processing
968 return true;
969 }
970 else
971 {
972 if (unsigned(my_rank) == Output_rank)
973 {
974 stream << "Processor " << my_rank << ": ";
975 // Continue processing
976 return true;
977 }
978 else
979 {
980 return false;
981 }
982 }
983 }
984
985#endif
986
987 //=============================================================================
988 /// Initialize mpi. If optional boolean flag is set to false, we use
989 /// MPI_COMM_WORLD itself as oomph-lib's communicator. Defaults to true.
990 //=============================================================================
992 char** argv,
994 {
995#ifdef OOMPH_HAS_MPI
996 // call mpi int
997 MPI_Init(&argc, &argv);
998
999
1000 // By default, create the oomph-lib communicator using MPI_Comm_dup so that
1001 // the communicator has the same group of processes but a new context
1004 {
1006 }
1007
1009 {
1010 oomph_info << "Oomph-lib communicator is a duplicate of MPI_COMM_WORLD\n";
1011 }
1012 else
1013 {
1014 oomph_info << "Oomph-lib communicator is MPI_COMM_WORLD\n";
1015 }
1016
1017 // create the oomph-lib communicator
1018 // note: oomph_comm_world is deleted when the destructor of
1019 // Communicator_pt is called
1021
1022 // Change MPI error handler so that error will return
1023 // rather than aborting
1025
1026 // Use MPI output modifier: Each processor precedes its output
1027 // by its rank
1030#else
1031 // create a serial communicator
1033#endif
1035 }
1036
1037 //=============================================================================
1038 /// finalize mpi
1039 //=============================================================================
1041 {
1042 // delete the communicator
1043 delete Communicator_pt;
1044
1045 // and call MPI_Finalize
1046#ifdef OOMPH_HAS_MPI
1047 MPI_Finalize();
1048#endif
1049 }
1050
1051 //=============================================================================
1052 /// access to the global oomph-lib communicator
1053 //=============================================================================
1055 {
1056#ifdef MPI
1057#ifdef PARANOID
1059 {
1060 std::ostringstream error_message_stream;
1062 << "MPI has not been initialised.\n Call MPI_Helpers::init(...)";
1066 }
1067#endif
1068 return Communicator_pt;
1069
1070#else // ifndef MPI
1071
1072 // If MPI is not enabled then we are unlikely to have called init, so to
1073 // be nice to users create a new serial comm_pt if none exits.
1074
1075 if (Communicator_pt == 0)
1076 {
1078 }
1079
1080 // #ifdef PARANOID
1081 // if(!Communicator_pt->serial_communicator())
1082 // {
1083 // std::string error_msg =
1084 // "MPI_Helpers has somehow ended up with a non-serial\n"
1085 // + "communicator pointer even though MPI is disabled!";
1086 // throw OomphLibError(error_msg.str(),
1087 // OOMPH_CURRENT_FUNCTION,
1088 // OOMPH_EXCEPTION_LOCATION);
1089 // }
1090 // #endif
1091
1092 return Communicator_pt;
1093
1094#endif // end ifdef MPI
1095 }
1096
1099
1100
1101 //====================================================================
1102 /// Namespace for flagging up obsolete parts of the code
1103 //====================================================================
1104 namespace ObsoleteCode
1105 {
1106 /// Flag up obsolete parts of the code
1107 bool FlagObsoleteCode = true;
1108
1109 /// Output warning message
1111 {
1112 if (FlagObsoleteCode)
1113 {
1114 std::string junk;
1115 oomph_info << "\n\n--------------------------------------------\n";
1116 oomph_info << "You are using obsolete code " << std::endl;
1117 oomph_info << "--------------------------------------------\n\n";
1118 oomph_info << "Enter: \"s\" to suppress further messages" << std::endl;
1119 oomph_info << " \"k\" to crash the code to allow a trace back in "
1120 "the debugger"
1121 << std::endl;
1122
1123 oomph_info << " any other key to continue\n \n";
1124 oomph_info << " [Note: Insert \n \n ";
1125 oomph_info << " "
1126 "ObsoleteCode::FlagObsoleteCode=false;\n \n";
1127 oomph_info << " into your code to suppress these "
1128 "messages \n";
1129 oomph_info << " altogether.] \n";
1130
1131 std::cin >> junk;
1132 if (junk == "s")
1133 {
1134 FlagObsoleteCode = false;
1135 }
1136 if (junk == "k")
1137 {
1138 throw OomphLibError(
1140 }
1141 }
1142 }
1143
1144
1145 /// Ouput a warning message with a string argument
1146 void obsolete(const std::string& message)
1147 {
1148 if (FlagObsoleteCode)
1149 {
1150 oomph_info << "\n\n------------------------------------" << std::endl;
1151 oomph_info << message << std::endl;
1152 oomph_info << "----------------------------------------" << std::endl;
1153
1154 obsolete();
1155 }
1156 }
1157
1158 } // namespace ObsoleteCode
1159
1160
1161 //====================================================================
1162 /// Namespace for tecplot stuff
1163 //====================================================================
1164 namespace TecplotNames
1165 {
1166 /// Tecplot colours
1168
1169
1170 /// Setup namespace
1171 void setup()
1172 {
1173 colour.resize(5);
1174 colour[0] = "RED";
1175 colour[1] = "GREEN";
1176 colour[2] = "BLUE";
1177 colour[3] = "CYAN";
1178 colour[4] = "BLACK";
1179 }
1180
1181
1182 } // namespace TecplotNames
1183
1184
1185#ifdef LEAK_CHECK
1186
1187 //====================================================================
1188 /// Namespace for leak check: Keep a running count of all instantiated
1189 /// objects -- add your own if you want to...
1190 //====================================================================
1191 namespace LeakCheckNames
1192 {
1204
1205 void reset()
1206 {
1207 QuadTree_build = 0;
1208 OcTree_build = 0;
1214 HangInfo_build = 0;
1215 Node_build = 0;
1218 }
1219
1220 void doc()
1221 {
1222 oomph_info << "\n Leak check: # of builds - # of deletes for the "
1223 "following objects: \n\n";
1224 oomph_info << "LeakCheckNames::QuadTree_build "
1225 << LeakCheckNames::QuadTree_build << std::endl;
1226 oomph_info << "LeakCheckNames::QuadTreeForest_build "
1228 oomph_info << "LeakCheckNames::OcTree_build "
1229 << LeakCheckNames::OcTree_build << std::endl;
1230 oomph_info << "LeakCheckNames::OcTreeForest_build "
1231 << LeakCheckNames::OcTreeForest_build << std::endl;
1232 oomph_info << "LeakCheckNames::RefineableQElement<2>_build "
1233 << LeakCheckNames::RefineableQElement<2> _build << std::endl;
1234 oomph_info << "LeakCheckNames::RefineableQElement<3>_build "
1235 << LeakCheckNames::RefineableQElement<3> _build << std::endl;
1236 oomph_info << "LeakCheckNames::MacroElement_build "
1237 << LeakCheckNames::MacroElement_build << std::endl;
1238 oomph_info << "LeakCheckNames::HangInfo_build "
1239 << LeakCheckNames::HangInfo_build << std::endl;
1240 oomph_info << "LeakCheckNames::Node_build " << LeakCheckNames::Node_build
1241 << std::endl;
1242 oomph_info << "LeakCheckNames::GeomReference_build "
1244 oomph_info << "LeakCheckNames::AlgebraicNode_build "
1246 oomph_info << std::endl;
1247 }
1248
1249
1250 } // namespace LeakCheckNames
1251
1252
1253#endif
1254
1255
1256 ///////////////////////////////////////////////////////////////////////////
1257 /////////////////////////////////////////////////////////////////////////////
1258
1259
1260 //====================================================================
1261 /// Namespace for pause() command
1262 //====================================================================
1263 namespace PauseFlags
1264 {
1265 /// Flag to enable pausing code -- pause the code by default
1266 bool PauseFlag = true;
1267
1268 } // namespace PauseFlags
1269
1270 //======================================================================
1271 /// Pause and display message
1272 //======================================================================
1273 void pause(std::string message)
1274 {
1275 std::string junk;
1277 {
1278 oomph_info << message << "\n hit any key to continue [hit \"S\" "
1279 << "to suppress further interruptions]\n";
1280 std::cin >> junk;
1281 if (junk == "S")
1282 {
1283 PauseFlags::PauseFlag = false;
1284 }
1285 }
1286 else
1287 {
1288 oomph_info << "\n[Suppressed pause message] \n";
1289 }
1290 }
1291
1292
1293 ///////////////////////////////////////////////////////////////////////////
1294 ///////////////////////////////////////////////////////////////////////////
1295 ///////////////////////////////////////////////////////////////////////////
1296
1297 //=============================================================================
1298 /// Helper for recording execution time.
1299 //=============================================================================
1300 namespace TimingHelpers
1301 {
1302 /// returns the time in seconds after some point in past
1303 double timer()
1304 {
1305#ifdef OOMPH_HAS_MPI
1307 {
1308 return MPI_Wtime();
1309 }
1310 else
1311#endif
1312 {
1313 time_t t = clock();
1314 return double(t) / double(CLOCKS_PER_SEC);
1315 }
1316 }
1317
1318 /// Returns a nicely formatted string from an input time in seconds;
1319 /// the format depends on the size of time, e.g.:
1320 /// 86510 will be printed as 1d 1m:50
1321 /// 3710 will be printed as 1h:01:50
1322 /// 700 will be printed as 11m:40
1323 /// 59 will be printed as 59s
1325 {
1326 std::ostringstream ss;
1327
1328 unsigned sec_within_day = unsigned(time_in_sec) % (3600 * 24);
1329
1330 unsigned days = unsigned(time_in_sec) / (3600 * 24);
1331 unsigned hours = sec_within_day / 3600;
1332 unsigned minutes = (sec_within_day % 3600) / 60;
1333 unsigned seconds = (sec_within_day % 3600) % 60;
1334
1335 if (days > 0)
1336 {
1337 ss << days << "d ";
1338 }
1339
1340 if (hours > 0)
1341 {
1342 ss << hours << "h:";
1343 ss << std::setw(2) << std::setfill('0');
1344 ss << minutes << ":";
1345 ss << seconds;
1346 }
1347 else if (minutes > 0)
1348 {
1349 ss << minutes << "m:";
1350 ss << std::setw(2) << std::setfill('0');
1351 ss << seconds;
1352 }
1353 else
1354 {
1356 ss << std::setprecision(1) << std::fixed << seconds_double << "s";
1357 }
1358
1359 return ss.str();
1360 }
1361 } // end of namespace TimingHelpers
1362
1363
1364 ////////////////////////////////////////////////////////////////////
1365 ////////////////////////////////////////////////////////////////////
1366 ////////////////////////////////////////////////////////////////////
1367
1368
1369 //===============================================================
1370 /// Namespace with helper functions to assess total memory usage
1371 /// on the fly using system() -- details are very machine specific! This just
1372 /// provides the overall machinery with default settings for
1373 /// our own (linux machines). Uses the system command
1374 /// to spawn a command that computes the total memory usage
1375 /// on the machine where this is called. [Disclaimer: works
1376 /// on my machine(s) -- no guarantees for any other platform;
1377 /// linux or not. MH]
1378 //===============================================================
1379 namespace MemoryUsage
1380 {
1381 /// Boolean to suppress synchronisation of doc memory
1382 /// usage on processors (via mpi barriers). True (i.e. sync is
1383 /// suppressed) by default because not all processors may
1384 /// reach the relevant doc memory usage statements
1385 /// causing the code to hang).
1387
1388 /// String containing system command that obtains memory usage
1389 /// of all processes.
1390 /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1391 /// no guarantees for any other platform; linux or not. MH]
1392 std::string My_memory_usage_system_string = "ps aux";
1393
1394 /// Bool allowing quick bypassing of ALL operations related
1395 /// to memory usage monitoring -- this allows the code to remain
1396 /// "instrumented" without incurring the heavy penalties associated
1397 /// with the system calls and i/o. Default setting: false.
1399
1400 /// String containing name of file in which we document
1401 /// my memory usage -- you may want to change this to allow different
1402 /// processors to write to separate files (especially in mpi
1403 /// context). Note that file is appended to
1404 /// so it ought to be emptied (either manually or by calling
1405 /// helper function empty_memory_usage_file()
1406 std::string My_memory_usage_filename = "my_memory_usage.dat";
1407
1408 /// Function to empty file that records my memory usage in
1409 /// file whose name is specified by My_memory_usage_filename.
1411 {
1412 // bail out straight away?
1414
1415 // Open without appending and write header
1416 std::ofstream the_file;
1417 the_file.open(My_memory_usage_filename.c_str());
1418 the_file << "# My memory usage: \n";
1419 the_file.close();
1420 }
1421
1422
1423#ifdef OOMPH_HAS_UNISTDH
1424
1425 /// Doc my memory usage, prepended by string (which allows
1426 /// identification from where the function is called, say) that records
1427 /// memory usage in file whose name is specified by
1428 /// My_memory_usage_filename. Data is appended to that file; wipe it with
1429 /// empty_my_memory_usage_file(). Note: This requires getpid() which is
1430 /// defined in unistd.h so if you don't have that we won't build that
1431 /// function!
1432 void doc_my_memory_usage(const std::string& prefix_string)
1433 {
1434 // bail out straight away?
1436
1437 // Write prefix
1438 std::ofstream the_file;
1439 the_file.open(My_memory_usage_filename.c_str(), std::ios::app);
1440 the_file << prefix_string << " ";
1441 the_file.close();
1442
1443 // Sync all processors if in parallel (unless suppressed)
1444#ifdef OOMPH_HAS_MPI
1447 {
1449 }
1450#endif
1451
1452 // Process memory usage command and write to file
1453 std::stringstream tmp;
1454 tmp << My_memory_usage_system_string << " | awk '{if ($2==" << getpid()
1455 << "){print $4}}' >> " << My_memory_usage_filename;
1456 int success = system(tmp.str().c_str());
1457
1458 // Dummy command to shut up compiler warnings
1459 success += 1;
1460 }
1461
1462#endif
1463
1464 /// String containing system command that obtains total memory usage.
1465 /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1466 /// no guarantees for any other platform; linux or not. MH]
1468 "ps aux | awk 'BEGIN{sum=0}{sum+=$4}END{print sum}'";
1469
1470 /// String containing name of file in which we document total
1471 /// memory usage -- you may want to change this to allow different
1472 /// processors to write to separate files (especially in mpi
1473 /// context). Note that file is appended to
1474 /// so it ought to be emptied (either manually or by calling
1475 /// helper function empty_memory_usage_file()
1476 std::string Total_memory_usage_filename = "memory_usage.dat";
1477
1478 /// Function to empty file that records total memory usage in
1479 /// file whose name is specified by Total_memory_usage_filename.
1481 {
1482 // bail out straight away?
1484
1485 // Open without appending and write header
1486 std::ofstream the_file;
1488 the_file << "# Total memory usage: \n";
1489 the_file.close();
1490 }
1491
1492 /// Doc total memory usage, prepended by string (which allows
1493 /// identification from where the function is called, say) that records
1494 /// memory usage in file whose name is specified by
1495 /// Total_memory_usage_filename. Data is appended to that file; wipe it with
1496 /// empty_memory_usage_file().
1497 void doc_total_memory_usage(const std::string& prefix_string)
1498 {
1499 // bail out straight away?
1501
1502 // Write prefix
1503 std::ofstream the_file;
1504 the_file.open(Total_memory_usage_filename.c_str(), std::ios::app);
1505 the_file << prefix_string << " ";
1506 the_file.close();
1507
1508 // Sync all processors if in parallel
1509#ifdef OOMPH_HAS_MPI
1512 {
1514 }
1515#endif
1516
1517 // Process memory usage command and write to file
1518 std::stringstream tmp;
1521 int success = system(tmp.str().c_str());
1522
1523 // Dummy command to shut up compiler warnings
1524 success += 1;
1525 }
1526
1527
1528 /// Function to empty file that records total and local memory usage
1529 /// in appropriate files
1531 {
1532 // bail out straight away?
1534
1538 }
1539
1540 /// Doc total and local memory usage, prepended by string (which
1541 /// allows identification from where the function is called, say). NOTE:
1542 /// Local memory usage only works if we have unistd.h header
1543 void doc_memory_usage(const std::string& prefix_string)
1544 {
1545 // bail out straight away?
1547
1548#ifdef OOMPH_HAS_UNISTDH
1550#endif
1551
1553 }
1554
1555
1556 /// String containing system command that runs "top" (or equivalent)
1557 /// "indefinitely" and writes to file specified in Top_output_filename.
1558 /// Default assignment for linux. [Disclaimer: works on my machine(s) --
1559 /// no guarantees for any other platform; linux or not. MH]
1560 std::string Top_system_string = "while true; do top -b -n 2 ; done ";
1561
1562 /// String containing name of file in which we document "continuous"
1563 /// output from "top" (or equivalent)-- you may want to change this to
1564 /// allow different processors to write to separate files (especially in mpi
1565 /// context). Note that file is appended to
1566 /// so it ought to be emptied (either manually or by calling
1567 /// helper function empty_top_file()
1568 std::string Top_output_filename = "top_output.dat";
1569
1570 /// Function to empty file that records continuous output from top in
1571 /// file whose name is specified by Top_output_filename
1573 {
1574 // bail out straight away?
1576
1577 // Open without appending and write header
1578 std::ofstream the_file;
1579 the_file.open(Top_output_filename.c_str());
1580 the_file << "# Continuous output from top obtained with: \n";
1581 the_file << "# " << Top_system_string << "\n";
1582 the_file.close();
1583 }
1584
1585
1586 /// Start running top continuously and output (append) into
1587 /// file specified by Top_output_filename. Wipe that file with
1588 /// empty_top_file() if you wish. Note that this is again quite Linux
1589 /// specific and unlikely to work on other operating systems. Insert
1590 /// optional comment into output file before starting.
1591 void run_continous_top(const std::string& comment)
1592 {
1593 // bail out straight away?
1595
1596 // Sync all processors if in parallel
1597 std::string modifier = "";
1598
1599#ifdef OOMPH_HAS_MPI
1601 {
1603 {
1605 }
1606 std::stringstream tmp;
1607 tmp << "_proc" << MPI_Helpers::communicator_pt()->my_rank();
1608 modifier = tmp.str();
1609 }
1610#endif
1611
1612 // Process memory usage command and write to file
1613 std::stringstream tmp;
1614
1615 // String stream seems unhappy about direct insertions of these
1616 std::string backslash = "\\";
1617 std::string dollar = "$";
1618
1619 // Create files that spawn and kill continuous top
1620 tmp << "echo \"#/bin/bash\" > run_continuous_top" << modifier << ".bash; "
1621 << "echo \" echo " << backslash << "\" kill " << backslash << dollar
1622 << backslash << dollar << " " << backslash
1623 << "\" > kill_continuous_top" << modifier
1624 << ".bash; chmod a+x kill_continuous_top" << modifier << ".bash; "
1625 << Top_system_string << " \" >> run_continuous_top" << modifier
1626 << ".bash; chmod a+x run_continuous_top" << modifier << ".bash ";
1627 int success = system(tmp.str().c_str());
1628
1629 // Add comment to annotate?
1630 if (comment != "")
1631 {
1633 }
1634
1635 // Start spawning
1636 std::stringstream tmp2;
1637 tmp2 << "./run_continuous_top" << modifier << ".bash >> "
1638 << Top_output_filename << " & ";
1639 success = system(tmp2.str().c_str());
1640
1641 // Dummy command to shut up compiler warnings
1642 success += 1;
1643 }
1644
1645
1646 /// Stop running top continuously. Note that this is
1647 /// again quite Linux specific and unlikely to work on other operating
1648 /// systems. Insert optional comment into output file before stopping.
1649 void stop_continous_top(const std::string& comment)
1650 {
1651 // bail out straight away?
1653
1654 // Sync all processors if in parallel
1655 std::string modifier = "";
1656
1657#ifdef OOMPH_HAS_MPI
1659 {
1661 {
1663 }
1664 std::stringstream tmp;
1665 tmp << "_proc" << MPI_Helpers::communicator_pt()->my_rank();
1666 modifier = tmp.str();
1667 }
1668#endif
1669
1670 // Add comment to annotate?
1671 if (comment != "")
1672 {
1674 }
1675
1676 // Kill
1677 std::stringstream tmp2;
1678 tmp2 << "./kill_continuous_top" << modifier << ".bash >> "
1679 << Top_output_filename << " & ";
1680 int success = system(tmp2.str().c_str());
1681
1682 // Dummy command to shut up compiler warnings
1683 success += 1;
1684 }
1685
1686
1687 /// Insert comment into running continuous top output
1689 {
1690 // bail out straight away?
1692
1693 std::stringstream tmp;
1694 tmp << " echo \"OOMPH-LIB EVENT: " << comment << "\" >> "
1696 int success = system(tmp.str().c_str());
1697
1698 // Dummy command to shut up compiler warnings
1699 success += 1;
1700 }
1701
1702
1703 } // end of namespace MemoryUsage
1704
1705
1706} // 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
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 ...
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....
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
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.
void reset()
Reset all timers.
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.
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_number, const std::string &message, const bool &shorten, const bool &start_on_new_line)
Return the concaternation of the initials of the input file name and line number. The make_new_line f...
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...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
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...