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-2022 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
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
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
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 =
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 =
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 =
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 =
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 {
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 =
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
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
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;
1206 HangInfo_build = 0;
1207 Node_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 "
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 "
1236 oomph_info << "LeakCheckNames::AlgebraicNode_build "
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
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()
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>.
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
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.