oomph_utilities.h
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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //A header containing useful utility classes, functions and constants
31 
32 //Include guard to prevent multiple inclusions of the header
33 #ifndef OOMPH_UTILITIES_HEADER
34 #define OOMPH_UTILITIES_HEADER
35 
36 // Config header generated by autoconfig
37 #ifdef HAVE_CONFIG_H
38  #include <oomph-lib-config.h>
39 #endif
40 
41 
42 #ifdef OOMPH_HAS_MPI
43 //mpi headers
44 #include "mpi.h"
45 #endif
46 
47 //Standard libray headers
48 #include<string>
49 #include<sstream>
50 #include<fstream>
51 #include<cmath>
52 #include<map>
53 #include<ctime>
54 #include<complex>
55 
56 //oomph-lib headers
57 #include "Vector.h"
58 #include "oomph_definitions.h"
59 #include "communicator.h"
60 
61 /* // Header for cxx-prettyprint: A C++ Container Pretty-Printer. If the */
62 /* // standard in use is older than C++11 then use a special older version of */
63 /* // the header. Header is from here: */
64 /* // http://louisdx.github.io/cxx-prettyprint/ */
65 /* #if __cplusplus <= 199711L */
66 /* #include "prettyprint98.h" */
67 /* #else */
68 /* #include "prettyprint.h" */
69 /* #endif */
70 
71 // Header for name demangling
72 #include <cxxabi.h>
73 
74 namespace oomph
75 {
76 
77 // Forward declaration needed for second invariant helper
78 template<class TYPE>
79 class DenseMatrix;
80 
81 //=====================================================================
82 /// Helper namespace containing function that computes second invariant
83 /// of tensor
84 //=====================================================================
85  namespace SecondInvariantHelper
86  {
87 
88  /// Compute second invariant of tensor
89  extern double second_invariant(const DenseMatrix<double>& tensor);
90 
91  }
92 
93 
94 //==============================================
95 /// Namespace for error messages for broken
96 /// copy constructors and assignment operators
97 //==============================================
98 namespace BrokenCopy
99 {
100 
101  /// Issue error message and terminate execution
102  extern void broken_assign(const std::string& class_name);
103 
104  /// Issue error message and terminate execution
105  extern void broken_copy(const std::string& class_name);
106 
107 }
108 
109 //========================================
110 /// Namespace for mathematical constants
111 ///
112 //=======================================
113 namespace MathematicalConstants
114 {
115  /// 50 digits from maple
116  const double Pi=3.1415926535897932384626433832795028841971693993751;
117 
118  /// The imaginary unit
119  const std::complex<double> I(0.0,1.0);
120 }
121 
122 
123 //================================================================
124 /// Function-type-object to perform absolute comparison of objects.
125 /// Apparently this inlines better
126 //================================================================
127 template <class T>
128 class AbsCmp
129 {
130 public:
131 
132  /// Comparison. Are the values identical or not?
133  bool operator()(const T &x, const T &y) const
134  {
135  return std::abs(x) < std::abs(y);
136  }
137 };
138 
139 
140 // =================================================================
141 /// Conversion functions for easily making strings (e.g. for filenames - to
142 /// avoid stack smashing problems with cstrings and long filenames).
143 // =================================================================
144 namespace StringConversion
145 {
146 
147  /// \short Conversion function that should work for anything with
148  /// operator<< defined (at least all basic types).
149  template<class T> std::string to_string(T object, unsigned float_precision=8)
150  {
151  std::stringstream ss;
152  ss.precision(float_precision);
153  ss << object;
154  return ss.str();
155  }
156 
157  /// \short Convert a string to lower case (outputs a copy).
158  std::string to_lower(const std::string& input);
159 
160  /// \short Convert a string to upper case (outputs a copy).
161  std::string to_upper(const std::string& input);
162 
163  /// \short Split a string, s, into a vector of strings where ever there is
164  /// an instance of delimiter (i.e. is delimiter is " " will give a list of
165  /// words). Note that multiple delimiters in a row will give empty
166  /// strings.
167  void split_string(const std::string &s, char delim, Vector<std::string> &elems);
168 
169  /// \short Split a string, s, into a vector of strings where ever there is
170  /// an instance of delimiter (i.e. is delimiter is " " will give a list of
171  /// words). Note that multiple delimiters in a row will give empty
172  /// strings. Return by value.
173  Vector<std::string> split_string(const std::string &s, char delim);
174 
175 }
176 
177 
178 namespace TypeNames
179 {
180 
181  /// \short Get the type name of an object. Only for use in debugging, do
182  /// not write real code using this function as it is implementation
183  /// dependant!
184  template<class T> std::string get_type_name(T& obj)
185  {
186  using namespace StringConversion;
187 
188  int status;
189  std::string typestr = to_string(abi::__cxa_demangle(typeid(obj).name(),0,0,&status));
190 
191  // Throw if there was an error
192  if(status != 0)
193  {
194  std::string err = "Error code " + to_string(status) +
195  " in demangler, see documentation of abi::__cxa_demangle for the meaning";
196  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
197  }
198 
199  return typestr;
200  }
201 
202  /// \short Get the type name of an object from a pointer to the object (we
203  /// usually want the type of the object itself not the pointer because the
204  /// type of the pointer may be a base class). Only for use in debugging,
205  /// do not write real code using this function as it is implementation
206  /// dependant!
207  template<class T> std::string get_type_name(T* obj)
208  {
209  return get_type_name(*obj);
210  }
211 
212 }
213 
214 //////////////////////////////////////////////////////////////////
215 //////////////////////////////////////////////////////////////////
216 //////////////////////////////////////////////////////////////////
217 
218 
219 
220 //====================================================================
221 /// Namespace for global (cumulative) timings
222 //====================================================================
223 namespace CumulativeTimings
224 {
225 
226  /// (Re-)start i-th timer
227  extern void start(const unsigned& i);
228 
229  /// Halt i-th timer
230  extern void halt(const unsigned& i);
231 
232  /// Reset i-th timer
233  extern void reset(const unsigned& i);
234 
235  /// Reset all timers
236  extern void reset();
237 
238  /// Report time accumulated by i-th timer
239  extern double cumulative_time(const unsigned& i);
240 
241  /// Set number of timings that can be recorded in parallel
242  extern void set_ntimers(const unsigned& ntimers);
243 
244  /// Cumulative timings
245  extern Vector<clock_t> Timing;
246 
247  /// Start times of active timers
249 
250 }
251 
252 
253  // ============================================================
254  // Automatically checked casting functions (from boost)
255  // ============================================================
256 
257  /// \short Runtime checked dynamic cast. This is the safe but slightly slower
258  /// cast. Use it in any of these cases:
259  /// - You aren't entirely sure the cast is always safe.
260  /// - You have strange inheritance structures (e.g. the "Diamond of Death" in
261  /// element inheritance).
262  /// - Efficiency is not critical.
263  /// Note that if you just want to check if a pointer can be converted to
264  /// some type you will need to use a plain dynamic_cast. Adapted from
265  /// polymorphic_cast in boost/cast.hpp, see
266  /// http://www.boost.org/doc/libs/1_52_0/libs/conversion/cast.htm for more
267  /// details.
268  template <class Target, class Source>
269  inline Target checked_dynamic_cast(Source* x)
270  {
271  Target tmp = dynamic_cast<Target>(x);
272 #ifdef PARANOID
273  if(tmp == 0)
274  {
275  throw OomphLibError("Bad cast.", OOMPH_CURRENT_FUNCTION,
276  OOMPH_EXCEPTION_LOCATION);
277  }
278 #endif
279  return tmp;
280  }
281 
282  /// \short Checked static cast. Only use this cast if ALL of these are true:
283  /// - You are sure that the cast will always succeed.
284  /// - You aren't using any strange inheritance structures (e.g. the "Diamond of
285  /// Death" in element inheritance, if you aren't sure just try compiling).
286  /// - You need efficiency.
287  /// Adapted from polymorphic_downcast in boost/cast.hpp, See
288  /// http://www.boost.org/doc/libs/1_52_0/libs/conversion/cast.htm for more
289  /// details.
290  template <class Target, class Source>
291  inline Target checked_static_cast(Source* x)
292  {
293 #ifdef PARANOID
294  // Check that the cast will work as expected.
295  if(dynamic_cast<Target>(x) != x)
296  {
297  throw OomphLibError("Bad cast.", OOMPH_CURRENT_FUNCTION,
298  OOMPH_EXCEPTION_LOCATION);
299  }
300 #endif
301  return static_cast<Target>(x);
302  }
303 
304 //////////////////////////////////////////////////////////////////
305 //////////////////////////////////////////////////////////////////
306 //////////////////////////////////////////////////////////////////
307 
308 //====================================================================
309 /// Timer
310 //====================================================================
311 class Timer
312 {
313 
314  public:
315 
316  /// Constructor: Specify number of timers
317  Timer(const unsigned& n_timer)
318  {
319  set_ntimers(n_timer);
320  }
321 
322  /// (Re-)start i-th timer
323  void start(const unsigned& i)
324  {
325  Start_time[i]=clock();
326  }
327 
328  /// Halt i-th timer
329  void halt(const unsigned& i)
330  {
331  Timing[i]+=clock()-Start_time[i];
332  }
333 
334  /// Report time accumulated by i-th timer
335  double cumulative_time(const unsigned& i)
336  {
337  return double(Timing[i])/CLOCKS_PER_SEC;
338  }
339 
340  /// Reset i-th timer
341  void reset(const unsigned& i)
342  {
343  Timing[i]=clock_t(0.0);
344  }
345 
346  /// Reset all timers
347  void reset()
348  {
349  unsigned n=Timing.size();
350  for (unsigned i=0;i<n;i++)
351  {
352  Timing[i]=clock_t(0.0);
353  }
354  }
355 
356  /// Set number of timings that can be recorded in parallel
357  void set_ntimers(const unsigned& ntimers)
358  {
359  Timing.resize(ntimers,clock_t(0.0));
360  Start_time.resize(ntimers,clock_t(0.0));
361  }
362 
363  private:
364 
365  /// Cumulative timings
367 
368  /// Start times of active timers
370 
371 };
372 
373 
374 
375 //////////////////////////////////////////////////////////////////
376 //////////////////////////////////////////////////////////////////
377 //////////////////////////////////////////////////////////////////
378 
379 
380 //======================================================================
381 // Namespace for black-box FD Newton solver.
382 //======================================================================
383 namespace BlackBoxFDNewtonSolver
384 {
385 
386 
387 // Function pointer for function that specifies residuals: The arguments
388 // are: Parameters, unknowns, residuals
389 typedef void (*ResidualFctPt)(const Vector<double>& parameters,
390  const Vector<double>& unknowns,
391  Vector<double>& residuals);
392 
393 // Maximum number of Newton iterations
394 extern unsigned Max_iter;
395 
396 // Number of Newton iterations taken in most recent invocation
397 extern unsigned N_iter_taken;
398 
399 // Flag to indicate if progress of Newton iteration is to be documented
400 // (defaults to false)
401  extern bool Doc_Progress;
402 
403 // Size of increment used in finite-difference calculations
404 extern double FD_step;
405 
406 // Tolerance (maximum allowed value of an single residual at convergence)
407 extern double Tol;
408 
409 // Use steplength control do make globally convergent (default false)
410 extern bool Use_step_length_control;
411 
412 // Black-box FD Newton solver:
413 // Calling sequence for residual function is
414 // \code residual_fct(parameters,unknowns,residuals) \endcode
415 // where all arguments are double Vectors.
416 // unknowns.size() = residuals.size()
417 extern void black_box_fd_newton_solve(ResidualFctPt residual_fct,
418  const Vector<double>& params,
419  Vector<double>& unknowns);
420 
421 
422 // Line search helper for globally convergent Newton method
423 extern void line_search(const Vector<double>& x_old,
424  const double half_residual_squared_old,
425  const Vector<double>& gradient,
426  ResidualFctPt residual_fct,
427  const Vector<double>& params,
428  Vector<double>& newton_dir,
429  Vector<double>& x,
430  double& half_residual_squared,
431  const double& stpmax);
432 
433 }
434 
435 
436 //====================================================================
437 /// \short Collection of data structures for storing information about
438 /// linear solves. Currently only contains storage for the
439 /// iteration counts and the linear solver time.
440 //====================================================================
442 {
443 
444 public:
445 
446  /// \short Constructor. Initialised the Iterations_and_times vector of vector
447  /// of pairs.
448  DocLinearSolverInfo() : Iterations_and_times()
449  {}
450 
451  /// \short Set up a new vector of pairs for a new time step.
453  {
454  // For each new time step, we have a new vector consisting of pairs of
455  // unsigned (for the iteration) and double (for the timing results).
456  Iterations_and_times.push_back(Vector<Vector<double> >());
457  }
458 
460  {
461  Iterations_and_times.pop_back();
462  setup_new_time_step();
463  }
464 
465  /// \short Add a new iteration and time pair.
466  void add_iteration_and_time
467  (unsigned iter, double prec_setup_time, double linear_solver_time)
468  {
469 #ifdef PARANOID
470  if(Iterations_and_times.size() == 0)
471  {
472  std::ostringstream error_message;
473  error_message << "Iterations_and_times is empty. "
474  << "Call setup_new_time_step()\n";
475  throw OomphLibError(
476  error_message.str(),OOMPH_CURRENT_FUNCTION,
477  OOMPH_EXCEPTION_LOCATION);
478  }
479 #endif
480  Vector<double> tmp_iter_time_vec(3,0);
481  tmp_iter_time_vec[0] = (double)iter;
482  tmp_iter_time_vec[1] = prec_setup_time;
483  tmp_iter_time_vec[2] = linear_solver_time;
484  Iterations_and_times.back().push_back(tmp_iter_time_vec);
485  }
486 
487  /// The number of time steps
488  unsigned current_ntime_step() const
489  {return Iterations_and_times.size();}
490 
491  /// The number of Newton steps.
492  unsigned current_nnewton_step() const
493  {return Iterations_and_times.back().size();}
494 
495  /// \short Accessor function for the iteration and times.
497  {return Iterations_and_times;}
498 
499  /// \short Accessor function for the iteration and times (const version).
501  {return Iterations_and_times;}
502 
503 private:
504 
505  /// Storage for number of iterations during Newton steps
507 };
508 
509 //====================================================================
510 /// \short Information for documentation of results:
511 /// Directory and file number to enable output
512 /// in the form RESLT/filename11.dat, say.
513 /// Documentation can be switched on and off.
514 //====================================================================
515 class DocInfo
516 {
517 
518 public:
519 
520  /// \short Constructor. Default settings: Current directory, step `0',
521  /// label="", full documentation enabled and output directory is required
522  /// to exist when set_directory() is called.
523  DocInfo() : Directory("."), Doc_flag(true), Number(0),
524  Label(""), Directory_must_exist(true)
525  {}
526 
527  /// \short Constructor with specific directory.
528  DocInfo(const std::string& directory) :
529  Directory(directory), Doc_flag(true), Number(0),
530  Label(""), Directory_must_exist(true)
531  {}
532 
533  /// Output directory
534  std::string directory() const {return Directory;}
535 
536  /// \short Set output directory (we try to open a file in it
537  /// to see if the directory exists -- if it doesn't we'll
538  /// issue a warning -- or, if directory_must_exist()==true,
539  /// throw and OomphLibError
540  void set_directory(const std::string& directory);
541 
542  /// \short Enable documentation
543  void enable_doc() {Doc_flag=true;}
544 
545  /// \short Disable documentation
546  void disable_doc() {Doc_flag=false;}
547 
548  /// \short Are we documenting?
549  bool is_doc_enabled() const {return Doc_flag;}
550 
551  /// Number used (e.g.) for labeling output files
552  unsigned& number() {return Number;}
553 
554  /// Number used (e.g.) for labeling output files. Const version.
555  unsigned number() const {return Number;}
556 
557  /// Get number as a string (useful to completely avoid C-strings).
559  {
561  }
562 
563  /// String used (e.g.) for labeling output files
564  std::string& label() {return Label;}
565 
566  /// String used (e.g.) for labeling output files. Const version.
567  std::string label() const {return Label;}
568 
569  /// \short Call to throw an error if directory does not exist
570  void enable_error_if_directory_does_not_exist() {Directory_must_exist=true;}
571 
572  /// \short Call to issue a warning if the directory does not exists
573  void disable_error_if_directory_does_not_exist() {Directory_must_exist=false;}
574 
575 private:
576 
577  /// Directory name
579 
580  /// Doc or don't?
581  bool Doc_flag;
582 
583  /// Number to label output file, say
584  unsigned Number;
585 
586  /// String to label output file, say
588 
589  /// Boolean flag to decide response if an output
590  /// directory doesn't exist: If true, we terminate
591  /// code execution by throwing an OomphLibError rather than
592  /// just issuing a warning.
594 };
595 
596 
597 //====================================================================
598 // Namespace for command line arguments
599 //====================================================================
600 namespace CommandLineArgs
601 {
602 
603  /// Structure to store information on a command line argument
604  template<class T>
605  struct ArgInfo
606  {
607 
608  /// Proper constructor
609  ArgInfo(const bool& is_set,
610  T* arg_pt,
611  const std::string& doc)
612  {
613  this->is_set = is_set;
614  this->arg_pt = arg_pt;
615  this->doc = doc;
616  }
617 
618  /// Default constructor. We need this to be able to store these things in
619  /// maps.
621  {
622  this->is_set = false;
623  this->arg_pt = 0;
624  this->doc = "";
625  }
626 
627  // /// Assignment operator. We need this to be able to store these things in
628  // /// maps.
629  // void operator=(const ArgInfo& that)
630  // {
631  // this->is_set = that.is_set;
632  // this->arg_pt = that.arg_pt;
633  // this->doc = that.doc;
634  // }
635 
636  /// Has this argument been set?
637  bool is_set;
638 
639  /// The place to put the argument's value when it is set
641 
642  /// Information about what the argument does
644  };
645 
646  // Number of arguments + 1
647  extern int Argc;
648 
649  // Arguments themselves
650  extern char** Argv;
651 
652  /// Map to indicate an input flag as having been set
653  extern std::map<std::string, ArgInfo<bool> > Specified_command_line_flag;
654 
655  /// Map to associate an input flag with a double -- specified via pointer
656  extern std::map<std::string, ArgInfo<double> >
658 
659  /// Map to associate an input flag with an int -- specified via pointer
660  extern std::map<std::string, ArgInfo<int> >
662 
663  /// Map to associate an input flag with an unsigned -- specified via pointer
664  extern std::map<std::string, ArgInfo<unsigned> >
666 
667  /// Map to associate an input flag with a string -- specified via pointer
668  extern std::map<std::string, ArgInfo<std::string> >
670 
671  // Set values
672  extern void setup(int argc, char** argv);
673 
674  // Doc the command line arguments
675  extern void output();
676 
677  /// Specify possible argument-free command line flag
678  extern void specify_command_line_flag
679  (const std::string& command_line_flag,
680  const std::string& documentation="Undocumented");
681 
682  /// \short Specify possible command line flag that specifies a double, accessed
683  /// via pointer
684  extern void specify_command_line_flag
685  (const std::string& command_line_flag, double* arg_pt,
686  const std::string& documentation="Undocumented");
687 
688  /// \short Specify possible command line flag that specifies an int, accessed
689  /// via pointer
690  extern void specify_command_line_flag
691  (const std::string& command_line_flag, int* arg_pt,
692  const std::string& documentation="Undocumented");
693 
694  /// \short Specify possible command line flag that specifies an unsigned,
695  /// accessed via pointer
696  extern void specify_command_line_flag
697  (const std::string& command_line_flag, unsigned* arg_pt,
698  const std::string& documentation="Undocumented");
699 
700  /// \short Specify possible command line flag that specifies a string,
701  /// accessed via pointer
702  extern void specify_command_line_flag
703  (const std::string& command_line_flag, std::string* arg_pt,
704  const std::string& documentation="Undocumented");
705 
706  /// \short Check if specified flag has been set (the associated
707  /// value will have been assigned directly)
708  extern bool command_line_flag_has_been_set(const std::string& flag);
709 
710  /// Document the values of all flags (specified or not)
711  extern void doc_all_flags(std::ostream& outstream=*oomph_info.stream_pt());
712 
713  /// Document specified command line flags
714  extern void doc_specified_flags();
715 
716  /// Document available command line flags
717  extern void doc_available_flags();
718 
719  /// Helper function to check if command line index is legal
720  extern void check_arg_index(const int& argc,const int& arg_index);
721 
722  /// \short Parse command line, check for recognised flags and assign
723  /// associated values
724  extern void parse_and_assign(int argc, char *argv[],
725  const bool& throw_on_unrecognised_args=true);
726 
727  /// \short Parse previously specified command line, check for
728  /// recognised flags and assign associated values
729  extern void parse_and_assign(const bool& throw_on_unrecognised_args=true);
730 
731 }
732 
733 // forward declaration of OomphCommunicator class
734 class OomphCommunicator;
735 
736 #ifdef OOMPH_HAS_MPI
737 //========================================================================
738 /// MPI output modifier: Precedes every output by
739 /// specification of the processor ID. Output can be restricted
740 /// to a single processor.
741 //========================================================================
743 {
744 
745 private:
746 
747  /// \short Rank of single processor that produces output (only used
748  /// if Output_from_single_processor=true
749  unsigned Output_rank;
750 
751  /// Boolean to control if output is performed only on a single
752  /// processor (default: false)
754 
755  /// Communicator
757 
758 public:
759 
760 
761  /// Constructor -- initialise flags for output from all processors
762  MPIOutputModifier() : Output_rank(0),
763  Output_from_single_processor(false)
764  {}
765 
766  /// Return pointer to communicator
767  OomphCommunicator*& communicator_pt() { return Communicator_pt; }
768 
769  /// Precede the output by the processor ID but output everything
770  virtual bool operator()(std::ostream &stream);
771 
772  /// Switch to ensure output is only produced from a single
773  /// processor (default: Master node, i.e. rank 0)
774  void restrict_output_to_single_processor(const unsigned& output_rank=0)
775  {
776  Output_from_single_processor=true;
777  Output_rank=output_rank;
778  }
779 
780 
781  /// Switch to ensure output is only produced from a single
782  /// processor (default: Master node, i.e. rank 0)
784  {
785  Output_from_single_processor=false;
786  }
787 
788 
789 };
790 
791 
792 //========================================================================
793 /// Single (global) instantiation of the mpi output modifier
794 //========================================================================
796 
797 //=== Forward DenseMatrix class
798 template <class T>
799 class DenseMatrix;
800 
801 // forward declaration of oomph-communicator class
802 //class OomphCommunicator;
803 
804 #endif
805 
806 
807 //======================================================================
808 /// \short MPI_Helpers class contains static helper methods to support MPI
809 /// within oomph-lib. The methods init(...) and finalize() initialize and
810 /// finalize MPI in oomph-lib and manage the oomph-libs global communicator
811 /// communicator_pt().
812 /// NOTE: This class encapsulates static helper methods and instances of it
813 /// CANNOT be instantiated.
814 //=====================================================================
816 {
817 
818  public:
819 
820  /// \short initialise mpi (oomph-libs equivalent of MPI_Init(...))
821  /// Initialises MPI and creates the global oomph-lib communicator.
822  /// If optional boolean flag is set to false, we use
823  /// MPI_COMM_WORLD itself as oomph-lib's communicator. Defaults to true.
824  static void init(int argc, char **argv,
825  const bool& make_duplicate_of_mpi_comm_world=true);
826 
827  /// finalize mpi (oomph-lib equivalent of MPI_Finalize())
828  /// Deletes the global oomph-lib communicator and finalizes MPI.
829  static void finalize();
830 
831  /// access to global communicator. This is the oomph-lib equivalent of
832  /// MPI_COMM_WORLD
833  static OomphCommunicator* communicator_pt();
834 
835  /// return true if MPI has been initialised
836  static bool mpi_has_been_initialised() { return MPI_has_been_initialised; }
837 
838  private:
839 
840  /// \short private default constructor definition (to prevent instances of
841  /// the class being instantiated)
842  MPI_Helpers();
843 
844  /// \short private copy constructor definition (to prevent instances of
845  /// the class being instantiated)
846  MPI_Helpers(const MPI_Helpers&);
847 
848  /// Bool set to true if MPI has been initialised
850 
851  /// the global communicator
853 };
854 
855 
856 //====================================================================
857 // Namespace for flagging up obsolete parts of the code
858 //====================================================================
859 namespace ObsoleteCode
860 {
861 
862  // Flag up obsolete parts of the code
863  extern bool FlagObsoleteCode;
864 
865  // Output warning message
866  extern void obsolete();
867 
868  // Output specified warning message
869  extern void obsolete(const std::string &message);
870 
871 }
872 
873 //====================================================================
874 // Namespace for tecplot stuff
875 //====================================================================
876 namespace TecplotNames
877 {
878 
879  // Tecplot colours
881 
882  // Setup tecplot colours namespace
883  extern void setup();
884 
885 }
886 
887 
888 #ifdef LEAK_CHECK
889 
890 //====================================================================
891 // Namespace for leak check: Keep a running count of all instantiated
892 // objects -- add your own if you want to...
893 //====================================================================
894 namespace LeakCheckNames
895 {
896 
897  extern long QuadTree_build;
898  extern long OcTree_build;
899  extern long QuadTreeForest_build;
900  extern long OcTreeForest_build;
901  extern long RefineableQElement<2>_build;
902  extern long RefineableQElement<3>_build;
903  extern long MacroElement_build;
904  extern long HangInfo_build;
905  extern long Node_build;
906  extern long GeomReference_build;
908  extern long AlgebraicNode_build;
909 
910  // Reset counters
911  extern void reset();
912 
913  // Doc counters
914  extern void doc();
915 }
916 
917 #endif
918 
919 //====================================================================
920 // Namespace for pause() command
921 //====================================================================
922 namespace PauseFlags
923 {
924 
925  // Flag to enable pausing code
926  extern bool PauseFlag;
927 
928 }
929 
930 /// Pause and dump out message
931 void pause(std::string message);
932 
933 
934 
935 //=============================================================================
936 /// Helper for recording execution time.
937 //=============================================================================
938 namespace TimingHelpers
939 {
940 
941  /// returns the time in seconds after some point in past
942  double timer();
943 
944 }//end of namespace TimingHelpers
945 
946 
947 
948 
949 
950 ////////////////////////////////////////////////////////////////////
951 ////////////////////////////////////////////////////////////////////
952 ////////////////////////////////////////////////////////////////////
953 
954 
955 
956 //===============================================================
957 /// Namespace with helper functions to assess total memory usage
958 /// on the fly using system() -- details are very machine specific! This just
959 /// provides the overall machinery with default settings for
960 /// our own (linux machines). Uses the system command
961 /// to spawn a command that computes the total memory usage
962 /// on the machine where this is called. [Disclaimer: works
963 /// on my machine(s) -- no guarantees for any other platform;
964 /// Linux or not. MH]
965 //===============================================================
966 namespace MemoryUsage
967 {
968 
969  /// \short Boolean to suppress synchronisation of doc memory
970  /// usage on processors (via mpi barriers). True (i.e. sync is
971  /// is suppressed by default because not all processors may
972  /// execute the reach the relevant doc memory usage statements
973  /// causing the code to hang).
974  extern bool Suppress_mpi_synchronisation;
975 
976  /// \short String containing system command that obtains memory usage
977  /// of all processes.
978  /// Default assignment for Linux. [Disclaimer: works on my machine(s) --
979  /// no guarantees for any other platform; Linux or not. MH]
981 
982  /// \short Bool allowing quick bypassing of ALL operations related
983  /// to memory usage monitoring -- this allows the code to remain
984  /// "instrumented" without incurring the heavy penalties associated
985  /// with the system calls and i/o. Default setting: false.
987 
988  /// \short String containing name of file in which we document
989  /// my memory usage -- you may want to change this to allow different
990  /// processors to write to separate files (especially in mpi
991  /// context). Note that file is appended to
992  /// so it ought to be emptied (either manually or by calling
993  /// helper function empty_memory_usage_file()
995 
996  /// \short Function to empty file that records my memory usage in
997  /// file whose name is specified by My_memory_usage_filename.
999 
1000 #ifdef OOMPH_HAS_UNISTDH
1001 
1002  /// \short Doc my memory usage, prepended by string (which allows
1003  /// identification from where the function is called, say) that records
1004  /// memory usage in file whose name is specified by My_memory_usage_filename.
1005  /// Data is appended to that file; wipe it with empty_my_memory_usage_file().
1006  /// Note: This requires getpid() which is defined in unistd.h so if you
1007  /// don't have that we won't build that function!
1008  void doc_my_memory_usage(const std::string& prefix_string=0);
1009 
1010 #endif
1011 
1012  /// \short String containing system command that obtains total memory usage.
1013  /// Default assignment for Linux. [Disclaimer: works on my machine(s) --
1014  /// no guarantees for any other platform; Linux or not. MH]
1016 
1017  /// \short String containing name of file in which we document total
1018  /// memory usage -- you may want to change this to allow different
1019  /// processors to write to separate files (especially in mpi
1020  /// context). Note that file is appended to
1021  /// so it ought to be emptied (either manually or by calling
1022  /// helper function empty_memory_usage_file()
1024 
1025  /// \short Function to empty file that records total memory usage in
1026  /// file whose name is specified by Total_memory_usage_filename.
1028 
1029  /// \short Doc total memory usage, prepended by string (which allows
1030  /// identification from where the function is called, say) that records
1031  /// mem usage in file whose name is specified by Total_memory_usage_filename.
1032  /// Data is appended to that file; wipe it with empty_memory_usage_file().
1033  void doc_total_memory_usage(const std::string& prefix_string="");
1034 
1035  /// \short Function to empty file that records total and local memory usage
1036  /// in appropriate files
1037  void empty_memory_usage_files();
1038 
1039  /// \short Doc total and local memory usage, prepended by string (which allows
1040  /// identification from where the function is called, say)
1041  void doc_memory_usage(const std::string& prefix_string="");
1042 
1043  /// \short String containing system command that runs "top" (or equivalent)
1044  /// "indefinitely" and writes to file specified in Top_output_filename.
1045  /// Default assignment for Linux. [Disclaimer: works on my machine(s) --
1046  /// no guarantees for any other platform; Linux or not. MH]
1048 
1049  /// \short String containing name of file in which we document "continuous"
1050  /// output from "top" (or equivalent)-- you may want to change this to
1051  /// allow different processors to write to separate files (especially in mpi
1052  /// context). Note that file is appended to
1053  /// so it ought to be emptied (either manually or by calling
1054  /// helper function empty_top_file()
1056 
1057  /// \short Function to empty file that records continuous output from top in
1058  /// file whose name is specified by Top_output_filename
1059  void empty_top_file();
1060 
1061  /// \short Start running top continuously and output (append) into
1062  /// file specified by Top_output_filename. Wipe that file with
1063  /// empty_top_file() first if you wish. Note that this is again
1064  /// quite Linux specific and unlikely to work on other operating systems.
1065  /// Insert optional comment into output file before starting.
1066  void run_continous_top(const std::string& comment="");
1067 
1068  /// \short Stop running top continuously. Note that this is
1069  /// again quite Linux specific and unlikely to work on other operating
1070  /// systems.
1071  /// Insert optional comment into output file before stopping.
1072  void stop_continous_top(const std::string& comment="");
1073 
1074  /// \short Insert comment into running continuous top output
1075  void insert_comment_to_continous_top(const std::string& comment);
1076 
1077 } // end of namespace MemoryUsage
1078 
1079 
1080 
1081  ////////////////////////////////////////////////////////////////
1082  ////////////////////////////////////////////////////////////////
1083  ////////////////////////////////////////////////////////////////
1084 
1085  // Forward decl.
1086  class Problem;
1087  template <class T> class DenseMatrix;
1088 
1089  /// Function base class for exact solutions/initial conditions/boundary
1090  /// conditions. This is needed so that we can have solutions that depend
1091  /// on problem parameters with resorting to global variables.
1093  {
1094  public:
1095  // Some typedefs first:
1096 
1097  /// General function of space and time which returns a double.
1098  typedef double (*TimeSpaceToDoubleFctPt)(const double& t,
1099  const Vector<double>&x);
1100 
1101  /// General function of space and time which returns a vector of doubles.
1102  typedef Vector<double> (*TimeSpaceToDoubleVectFctPt) (const double& t,
1103  const Vector<double>&x);
1104 
1105  /// General function of time, space and a value vector which returns a
1106  /// vector of doubles.
1107  typedef Vector<double> (*TimeSpaceValueToDoubleVectFctPt)
1108  (const double& t, const Vector<double>&x, const Vector<double>&u);
1109 
1110  /// Virtual destructor
1112 
1113  /// Call the function.
1114  virtual Vector<double> operator()(const double& t,
1115  const Vector<double>&x) const = 0;
1116 
1117  /// Call the derivative function.
1118  virtual Vector<double> derivative(const double& t, const Vector<double>& x,
1119  const Vector<double>& u) const = 0;
1120 
1121  /// The derivatives of the derivative function with respect to u (note
1122  /// that this is not quite the jacobian of the residuals for an ODE
1123  /// problem defined by this solution: you also need the time derivative
1124  /// part there). Broken virtual function because not often needed.
1125  virtual void jacobian(const double& t, const Vector<double>& x,
1126  const Vector<double>& u,
1127  DenseMatrix<double>& jacobian) const
1128  {
1129  std::string err = "No Jacobian function implemented";
1130  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
1131  OOMPH_EXCEPTION_LOCATION);
1132  }
1133 
1134  /// Is a jacobian function implemented?
1135  virtual bool have_jacobian() const {return false;}
1136 
1137  /// Overload to grab data from the problem.
1138  virtual void initialise_from_problem(const Problem* problem_pt) {}
1139  };
1140 
1141 
1142 
1143  /// Function class for a simple function with no external parameters (just
1144  /// stores a function pointer, only needed for compatability).
1146  {
1147  // This could easily be extended to take
1148  // FiniteElement::UnsteadyExactSolutionFctPt function (i.e. functions
1149  // where the output is placed into a given vector rather than returned)
1150  // as well--just add the appropriate storage pointers and constructors.
1151 
1152  public:
1153  // Constructors:
1154 
1156  {
1157  Solution_fpt = 0;
1158  Derivative_fpt = 0;
1159  }
1160 
1161  SolutionFunctor(TimeSpaceToDoubleVectFctPt solution_fpt)
1162  {
1163  Solution_fpt = solution_fpt;
1164  Derivative_fpt = 0;
1165  }
1166 
1167  SolutionFunctor(TimeSpaceToDoubleVectFctPt solution_fpt,
1168  TimeSpaceValueToDoubleVectFctPt derivative_fpt)
1169  {
1170  Solution_fpt = solution_fpt;
1171  Derivative_fpt = derivative_fpt;
1172  }
1173 
1174  virtual ~SolutionFunctor() {}
1175 
1177  {
1178  Solution_fpt = that.Solution_fpt;
1179  Derivative_fpt = that.Derivative_fpt;
1180  }
1181 
1182  void operator=(const SolutionFunctor& that)
1183  {
1184  this->Solution_fpt = that.Solution_fpt;
1185  this->Derivative_fpt = that.Derivative_fpt;
1186  }
1187 
1188  /// Call the function.
1189  virtual Vector<double> operator()(const double& t, const Vector<double>&x) const
1190  {
1191 #ifdef PARANOID
1192  if(Solution_fpt == 0)
1193  {
1194  std::string err = "Solution_fpt is null!";
1195  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
1196  OOMPH_EXCEPTION_LOCATION);
1197  }
1198 #endif
1199  return Solution_fpt(t, x);
1200  }
1201 
1202  /// Call the derivative function.
1203  virtual Vector<double> derivative(const double& t, const Vector<double>& x,
1204  const Vector<double>& u) const
1205  {
1206 #ifdef PARANOID
1207  if(Derivative_fpt == 0)
1208  {
1209  std::string err = "Derivative_fpt is null!";
1210  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
1211  OOMPH_EXCEPTION_LOCATION);
1212  }
1213 #endif
1214  return Derivative_fpt(t, x, u);
1215  }
1216 
1217  /// Storage for solution
1218  TimeSpaceToDoubleVectFctPt Solution_fpt;
1219 
1220  /// Storage for derivative
1221  TimeSpaceValueToDoubleVectFctPt Derivative_fpt;
1222  };
1223 
1224 
1225 }
1226 #endif
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...
Vector< clock_t > Start_time
Start times of active timers.
DocInfo(const std::string &directory)
Constructor with specific directory.
Target checked_static_cast(Source *x)
Checked static cast. Only use this cast if ALL of these are true:
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
TimeSpaceValueToDoubleVectFctPt Derivative_fpt
Storage for derivative.
unsigned number() const
Number used (e.g.) for labeling output files. Const version.
void specify_command_line_flag(const std::string &command_line_flag, const std::string &doc)
Specify possible argument-free command line flag.
virtual bool have_jacobian() const
Is a jacobian function implemented?
virtual void jacobian(const double &t, const Vector< double > &x, const Vector< double > &u, DenseMatrix< double > &jacobian) const
double Tol
Relative tolerance to within radius of points on DtN boundary are allowed to deviate from specified v...
bool is_doc_enabled() const
Are we documenting?
char ** Argv
Arguments themselves.
std::string to_lower(const std::string &input)
Convert a string to lower case (outputs a copy).
Structure to store information on a command line argument.
Vector< clock_t > Timing
Cumulative timings.
bool Doc_Progress
Flag to indicate if progress of Newton iteration is to be documented (defaults to false) ...
Information for documentation of results: Directory and file number to enable output in the form RESL...
void restrict_output_to_single_processor(const unsigned &output_rank=0)
std::string directory() const
Output directory.
std::string My_memory_usage_system_string
String containing system command that obtains memory usage of all processes. Default assignment for l...
cstr elem_len * i
Definition: cfortran.h:607
void setup_new_time_step()
Set up a new vector of pairs for a new time step.
std::string Top_system_string
String containing system command that runs "top" (or equivalent) "indefinitely" and writes to file sp...
const double Pi
50 digits from maple
MPI_Helpers class contains static helper methods to support MPI within oomph-lib. The methods init(...
std::map< std::string, ArgInfo< int > > Specified_command_line_int_pt
Map to associate an input flag with an int – specified via pointer.
void check_arg_index(const int &argc, const int &arg_index)
Helper function to check if command line index is legal.
void obsolete()
Output warning message.
The Problem class.
Definition: problem.h:152
std::string Directory
Directory name.
std::string & label()
String used (e.g.) for labeling output files.
void enable_doc()
Enable documentation.
Timer(const unsigned &n_timer)
Constructor: Specify number of timers.
virtual Vector< double > derivative(const double &t, const Vector< double > &x, const Vector< double > &u) const
Call the derivative function.
void run_continous_top(const std::string &comment)
Start running top continuously and output (append) into file specified by Top_output_filename. Wipe that file with empty_top_file() if you wish. Note that this is again quite Linux specific and unlikely to work on other operating systems. Insert optional comment into output file before starting.
char t
Definition: cfortran.h:572
std::map< std::string, ArgInfo< std::string > > Specified_command_line_string_pt
Map to associate an input flag with a string – specified via pointer.
unsigned N_iter_taken
Number of Newton iterations taken in most recent invocation.
Target checked_dynamic_cast(Source *x)
Runtime checked dynamic cast. This is the safe but slightly slower cast. Use it in any of these cases...
void empty_total_memory_usage_file()
Function to empty file that records total memory usage in file whose name is specified by Total_memor...
OomphInfo oomph_info
unsigned Output_rank
Rank of single processor that produces output (only used if Output_from_single_processor=true.
double cumulative_time(const unsigned &i)
Report time accumulated by i-th timer.
static bool mpi_has_been_initialised()
return true if MPI has been initialised
std::string number_as_string() const
Get number as a string (useful to completely avoid C-strings).
OomphCommunicator *& communicator_pt()
Return pointer to communicator.
std::map< std::string, ArgInfo< bool > > Specified_command_line_flag
Map to indicate an input flag as having been set.
void set_ntimers(const unsigned &ntimers)
Set number of timings that can be recorded in parallel.
bool Use_step_length_control
Use steplength control do make globally convergent (default false)
void empty_memory_usage_files()
Function to empty file that records total and local memory usage in appropriate files.
std::map< std::string, ArgInfo< unsigned > > Specified_command_line_unsigned_pt
Map to associate an input flag with an unsigned – specified via pointer.
unsigned current_ntime_step() const
The number of time steps.
bool operator()(const T &x, const T &y) const
Comparison. Are the values identical or not?
unsigned & number()
Number used (e.g.) for labeling output files.
OomphCommunicator * Communicator_pt
Communicator.
std::string to_upper(const std::string &input)
Convert a string to upper case (outputs a copy).
void insert_comment_to_continous_top(const std::string &comment)
Insert comment into running continuous top output.
long AlgebraicNodeNodeUpdateInfo_build
bool is_set
Has this argument been set?
unsigned Number
The unsigned.
virtual void initialise_from_problem(const Problem *problem_pt)
Overload to grab data from the problem.
void start(const unsigned &i)
(Re-)start i-th timer
void setup()
Setup terminate helper.
void reset(const unsigned &i)
Reset i-th timer.
SolutionFunctor(TimeSpaceToDoubleVectFctPt solution_fpt, TimeSpaceValueToDoubleVectFctPt derivative_fpt)
static OomphCommunicator * Communicator_pt
the global communicator
std::map< std::string, ArgInfo< double > > Specified_command_line_double_pt
Map to associate an input flag with a double – specified via pointer.
Vector< Vector< Vector< double > > > & iterations_and_times()
Accessor function for the iteration and times.
void reset(const unsigned &i)
Reset i-th timer.
std::ostream *& stream_pt()
Access function for the stream pointer.
DocLinearSolverInfo()
Constructor. Initialised the Iterations_and_times vector of vector of pairs.
const std::complex< double > I(0.0, 1.0)
The imaginary unit.
static bool MPI_has_been_initialised
Bool set to true if MPI has been initialised.
void start(const unsigned &i)
(Re-)start i-th timer
std::string Label
String to label output file, say.
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...
static char t char * s
Definition: cfortran.h:572
std::string Top_output_filename
String containing name of file in which we document "continuous" output from "top" (or equivalent)– ...
std::string get_type_name(T *obj)
Get the type name of an object from a pointer to the object (we usually want the type of the object i...
Vector< clock_t > Timing
Cumulative timings.
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.
DocInfo()
Constructor. Default settings: Current directory, step `0&#39;, label="", full documentation enabled and ...
unsigned Max_iter
Max. # of Newton iterations.
Vector< Vector< Vector< double > > > Iterations_and_times
Storage for number of iterations during Newton steps.
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...
virtual Vector< double > operator()(const double &t, const Vector< double > &x) const
Call the function.
void halt(const unsigned &i)
Halt i-th timer.
std::string doc
Information about what the argument does.
Vector< Vector< Vector< double > > > iterations_and_times() const
Accessor function for the iteration and times (const version).
MPIOutputModifier oomph_mpi_output
Single (global) instantiation of the mpi output modifier.
SolutionFunctor(const SolutionFunctor &that)
double timer()
returns the time in seconds after some point in past
void output(std::ostream &outfile)
Output with default number of plot points.
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 empty_my_memory_usage_file()
Function to empty file that records my memory usage in file whose name is specified by My_memory_usag...
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 black_box_fd_newton_solve(ResidualFctPt residual_fct, const Vector< double > &params, Vector< double > &unknowns)
Black-box FD Newton solver: Calling sequence for residual function is.
void disable_error_if_directory_does_not_exist()
Call to issue a warning if the directory does not exists.
unsigned current_nnewton_step() const
The number of Newton steps.
void disable_doc()
Disable documentation.
std::string label() const
String used (e.g.) for labeling output files. Const version.
int Argc
Number of arguments + 1.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
std::string Total_memory_usage_filename
String containing name of file in which we document total memory usage – you may want to change this...
bool Suppress_mpi_synchronisation
Boolean to suppress synchronisation of doc memory usage on processors (via mpi barriers). True (i.e. sync is suppressed) by default because not all processors may reach the relevant doc memory usage statements causing the code to hang).
void enable_error_if_directory_does_not_exist()
Call to throw an error if directory does not exist.
unsigned Number
Number to label output file, say.
bool PauseFlag
Flag to enable pausing code – pause the code by default.
Vector< clock_t > Start_time
Start times of active timers.
bool Bypass_all_memory_usage_monitoring
Bool allowing quick bypassing of ALL operations related to memory usage monitoring – this allows the...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
std::string Total_memory_usage_system_string
String containing system command that obtains total memory usage. Default assignment for linux...
bool Doc_flag
Doc or don&#39;t?
void pause(std::string message)
Pause and display message.
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
Definition: communicator.h:50
void empty_top_file()
Function to empty file that records continuous output from top in file whose name is specified by Top...
virtual ~SolutionFunctorBase()
Virtual destructor.
Vector< std::string > colour
Tecplot colours.
void doc_available_flags()
Document available command line flags.
SolutionFunctor(TimeSpaceToDoubleVectFctPt solution_fpt)
long RefineableQElement< 2 > _build
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...
void line_search(const Vector< double > &x_old, const double half_residual_squared_old, const Vector< double > &gradient, ResidualFctPt residual_fct, const Vector< double > &params, Vector< double > &newton_dir, Vector< double > &x, double &half_residual_squared, const double &stpmax)
Line search helper for globally convergent Newton method.
double cumulative_time(const unsigned &i)
Report time accumulated by i-th timer.
MPIOutputModifier()
Constructor – initialise flags for output from all processors.
ArgInfo(const bool &is_set, T *arg_pt, const std::string &doc)
Proper constructor.
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...
void reset()
Reset all timers.
void doc_specified_flags()
Document specified command line flags.
void doc_all_flags(std::ostream &outstream)
Document the values of all flags (specified or not).
void(* ResidualFctPt)(const Vector< double > &, const Vector< double > &, Vector< double > &)
Function pointer for residual function: Parameters, unknowns, residuals.
double second_invariant(const DenseMatrix< double > &tensor)
Compute second invariant of tensor.
bool FlagObsoleteCode
Flag up obsolete parts of the code.
void operator=(const SolutionFunctor &that)
void halt(const unsigned &i)
Halt i-th timer.
void set_ntimers(const unsigned &ntimers)
Set number of timings that can be recorded in parallel.
Collection of data structures for storing information about linear solves. Currently only contains st...
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types)...
T * arg_pt
The place to put the argument&#39;s value when it is set.
TimeSpaceToDoubleVectFctPt Solution_fpt
Storage for solution.
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Definition: communicator.h:57