Skip to content
Snippets Groups Projects
Global.h 15.37 KiB
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  crystal growth group                                                  ==
// ==                                                                        ==
// ==  Stiftung caesar                                                       ==
// ==  Ludwig-Erhard-Allee 2                                                 ==
// ==  53175 Bonn                                                            ==
// ==  germany                                                               ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  http://www.caesar.de/cg/AMDiS                                         ==
// ==                                                                        ==
// ============================================================================

/** \file Global.h */

/** \mainpage AMDiS
 * @{ <img src="vis.png"> @}
 */

/** \defgroup Common Common
 */

#ifndef AMDIS_GLOBAL_H
#define AMDIS_GLOBAL_H

#if (__GNUC__) && (__GNUC__ > 2) 
#define OPENMODE ::std::ios::openmode
#else
#define OPENMODE ::std::ios::open_mode
#endif

/** \brief current AMDiS version */
#define AMDIS_VERSION  "AMDiS: Version 0.100"

// ============================================================================
// ===== includes =============================================================
// ============================================================================

#include <string>
#include <vector>
#include <fstream>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <functional>
#include <float.h>

namespace AMDiS {
  // ============================================================================
  // ===== forward declarations =================================================
  // ============================================================================

  class Mesh;
  class Element;

  extern const char *funcName;

  // ============================================================================
  // ===== definitions ==========================================================
  // ============================================================================

  /** \brief used by matrix vector multiplication */
  typedef enum { NoTranspose,
		 Transpose,
		 ConjugateTranspose } MatrixTranspose;

  /** \brief speciefies the norm used by Estimator. */
  typedef enum { NO_NORM = 0, H1_NORM = 1, L2_NORM = 2 } Norm;


  /** \brief datatype for degrees of freedom */
  typedef signed int DegreeOfFreedom;


  /** \brief
   * returns the GeoIndex of d for dimension dim.
   */
#define INDEX_OF_DIM(d, dim) (static_cast<GeoIndex>((d == dim) ? CENTER : d + 1))

  /** \brief
   * returns the dimension of GeoIndex ind for dimension dim
   */
#define DIM_OF_INDEX(ind, dim) ((static_cast<int>(ind) == 0) ? dim : static_cast<int>(ind) - 1)


  /** \brief
   * Returns boundary->getBound() if boundary is not NULL. Returns INTERIOR
   * otherwise.
   */
  //#define GET_BOUND(boundary) ((boundary) ? (boundary)->getBound() : INTERIOR)

  /** \brief
   * Calculates factorial of i
   */
  int fac(int i);

  /** \brief
   * Calculates the logaritmic error progression
   */
#define EOC(e,eo) log(eo/::std::max(e,1.0e-15))/M_LN2

  /** \brief
   * Content comparision of two pointers. Used e.g. for ::std::find_if
   */
  template<typename T>
  struct comparePtrContents : public ::std::binary_function<T*, T*, bool>
  {
    /** \brief
     * Overrides binary_function::operator()
     */
    bool operator()(T* a, T* b) const {
      return (*a == *b);
    };
  };

  // ===== some simple template functions ====================================== 

  //template<typename T> T max(T a,T b ) {return  ((a) > (b) ? (a) : (b));}
  template<typename T,typename S> inline T max(T a,S b )
  {
    return  ((a) > (b) ? (a) : (b));
  }

  template<typename T> inline T min(T a,T b) 
  {
    return  ((a) < (b)) ? (a) : (b);
  }

  template<typename T> inline T abs(T a) 
  {
    return  ((a) >= 0 ? (a) : -(a));
  }

  template<typename T> inline T sqr(T a) 
  {
    return  ((a)*(a));
  }

  // ===== some predefined values ===============================================
  const double m_e = 		2.7182818284590452354;
  const double m_log2e = 		1.4426950408889634074;
  const double m_log10e = 	0.43429448190325182765;
  const double m_ln2 = 		0.69314718055994530942;
  const double m_ln10 = 		2.30258509299404568402;
  const double m_pi = 		3.14159265358979323846;
  const double m_pi_2 = 		1.57079632679489661923;
  const double m_pi_4 = 		0.78539816339744830962;
  const double m_1_pi = 		0.31830988618379067154;
  const double m_2_pi = 		0.63661977236758134308;
  const double m_2_sqrtpi = 	1.12837916709551257390;
  const double m_sqrt2 = 		1.41421356237309504880;
  const double m_sqrt1_2 = 	0.70710678118654752440;

  // ===== tolerance for floating point comparison ==============================
#define DBL_TOL DBL_EPSILON
#define FLT_TOL FLT_EPSILON

  // ============================================================================
  // ===== class Msg ============================================================
  // ============================================================================

  /** \brief
   * Manages the output of messages, warnings, errors, ...
   * Used by the macros FUNCNAME, ERROR, ERROR_EXIT, WARNING, TEST, MSG, INFO,
   * PRINT_INFO, WAIT, WAIT_REALLY.
   * Don't use this class directly but only via these macros!
   */
  class Msg
  {
  public:
    /** \brief
     * Prints a formated message to the message stream
     */
    static void print(const char *format, ...);

    /** \brief
     * Prints a formated message to the error stream
     */
    static void print_error(const char *format, ...);

    /** \brief
     * Prints a formated message to the error stream and exits 
     */
    static void print_error_exit(const char *format, ...);

    /** \brief
     *
     */
    static void catch_error_exit(const char *format, ...) {};

    /** \brief
     * Prints an error message with funcname, file, and line to the error stream
     */
    static void print_error_funcname(const char *funcname,
				     const char *file, 
				     int line);

    /** \brief
     * Prints a warning to the message stream
     */
    static void print_warn(const char *format, ...);

    /** \brief
     * Prints a warning with funcname, file, and line to the message stream
     */
    static void print_warn_funcname(const char *funcname,
				    const char *file, 
				    int line);

    /** \brief
     * Prints the funcname to the message stream
     */
    static void print_funcname(const char *funcname);

    /** \brief
     * Changes the message stream
     */
    static void change_out(::std::ostream*);

    /** \brief
     * Creates a filestream and sets the message stream to this filestream
     */
    static void open_file(const char *filename, OPENMODE);

    /** \brief
     * Changes the error stream 
     */
    static void change_error_out(::std::ofstream *fp);

    /** \brief
     * Creates a filestream and sets the error stream to this filestream
     */
    static void open_error_file(const char *filename, OPENMODE);

    /** \brief
     * Generates a filename from path, file and ntime
     */
    static const char *generate_filename(const char *path, 
					 const char *file, 
					 int         ntime);

    /** \brief
     * Sets \ref msgInfo
     */
    static void setMsgInfo(int info) { msgInfo = info; };

    /** \brief
     * Returns \ref msgInfo
     */
    static int  getMsgInfo() { return msgInfo; };

    /** \brief
     * Sets \ref msgWait
     */
    static void setMsgWait(bool wait) { msgWait = wait; };

    /** \brief
     * Returns \ref msgWait
     */
    static bool getMsgWait() { return msgWait; };

    /** \brief
     * Waits for enter if w is true
     */
    static void wait(bool w);

    /** \brief
     * Returns \ref out
     */
    static ::std::ostream *getOutStream() { return out; };

    /** \brief
     * Returns \ref error
     */
    static ::std::ostream *getErrorStream() { return error; };

  protected:
    /** \brief
     * Message stram
     */
    static ::std::ostream *out;

    /** \brief
     * Error stream
     */
    static ::std::ostream *error;

    /** \brief
     * Remember funcName to avoid multiple output of funcName within the same
     * function call
     */
    static const char *oldFuncName;

    /** \brief
     * Global info level
     */
    static int msgInfo;

    /** \brief
     * Spezifies whether to wait when WAIT is called
     */
    static bool msgWait;
  };

  // ============================================================================
  // ===== message macros =======================================================
  // ============================================================================

  /** \brief 
   * Should be the first call in every functions. It defines the current function
   * name nn for message output via MSG, WARNING, ...
   */

#define FUNCNAME(nn) const char *funcName; funcName = nn;

  /** \brief 
   * prints an error message 
   */
#define ERROR Msg::print_error_funcname(funcName,__FILE__, __LINE__),	\
    Msg::print_error

  /** \brief 
   * prints an error message and exits 
   */
#define ERROR_EXIT Msg::print_error_funcname(funcName,__FILE__, __LINE__), \
    Msg::print_error_exit

  /** \brief 
   * prints a warning
   */
#define WARNING Msg::print_warn_funcname(funcName,__FILE__, __LINE__),	\
    Msg::print_warn

  /** \brief 
   * if test is false, an error message is printed
   */
#define TEST(test) if ((test));else ERROR


  /** \brief 
   * if test is false, an error message is printed and the program exits
   */
#define TEST_EXIT(test) if ((test));else ERROR_EXIT
  /** \brief
   * In debug mode, it corresponds to ERROR_EXIT, otherwise it is noop.
   */
#if (DEBUG == 0) 
  #define TEST_EXIT_DBG(test) if (false) Msg::catch_error_exit
#else
#define TEST_EXIT_DBG(test) if ((test));else ERROR_EXIT
#endif

  /** \brief 
   * prints a message
   */
#define MSG Msg::print_funcname(funcName), Msg::print

  /** \brief 
   * prints a message, if min(Msg::msgInfo, info) >= noinfo
   */
#define INFO(info,noinfo)						\
  if (Msg::getMsgInfo()&&(::std::min(Msg::getMsgInfo(),(info))>=(noinfo))) MSG

  /** \brief 
   * prints a message, if min(Msg::msgInfo, info) >= noinfo
   */
#define PRINT_INFO(info,noinfo)						\
  if (Msg::getMsgInfo()&&(::std::min(Msg::getMsgInfo(),(info))>=(noinfo))) Msg::print


  /** \brief 
   * If the value of Msg::wait is not zero the macro will produce the message 
   * 'wait for <enter> ...' and will continue after pressing the return or enter
   * key. Otherwise the program continues without a message.
   */
#define WAIT Msg::wait(Msg::getMsgWait())

  /** \brief
   * produces the message 'wait for <enter> ...' and will continue after pressing
   * the return or enter key.
   */
#define WAIT_REALLY Msg::wait(true)

#include <time.h>
#define TIME_USED(f,s) ((double)((s)-(f))/(double)CLOCKS_PER_SEC)

  /** \brief
   * internal used indices to represent the different geometrical objects.
   * Used as parameter for getGeo() and as template parameter for FixVec. 
   */
  typedef enum
    {
      CENTER   = 0, /**< in 1d the center is at the edge, in 2d at the face, in 3d 
		     * at the interior of an element. So a Line has no edge but
		     * only a center, a Triangle has no face but only a center.
		     */
      VERTEX   = 1, /**< index for element vertices.
		     * number of vertices is equal to number of parts and 
		     * neighbours.
		     */
      EDGE     = 2, /**< index for element edges */
      FACE     = 3, /**< index for element faces */
      DIMEN    =-1, /**< index for problem dimension */
      PARTS    =-2, /**< index for parts of an element (vertices in 1d, edges in 2d
		     * , faces in 3d). Number of element parts is equal to number
		     * of vertices and neighbours. 
		     */
      NEIGH    =-3, /**< index for neighbours of an element.
		     * Number of element neighbours is equal to number of 
		     * vertices and parts.
		     */
      WORLD    =-4, /**< index for world dimension */
      BOUNDARY =-5, /**< index for boundary nodes of an element. This could be
		     * vertices, edges or faces.
		     */
      PROJECTION=-6 /**< index for element and boundary projections */
    } GeoIndex;

#define MAXPART FACE
#define MINPART PROJECTION

  // ============================================================================
  // ===== class Global =========================================================
  // ============================================================================

  /** \ingroup Common
   * \brief
   * Static class wich holds global information about the world and all types of
   * elements.
   */
  class Global
  {
  public:
    /** \brief
     * returns a pointer to \ref referenceElement [dim]. With this pointer you
     * can get information about the element via Element's getGeo method.
     */
    static const Element *getReferenceElement(int dim) {
      FUNCNAME("Global::getReferenceElement()");
      TEST_EXIT((dim > 0) && (dim < 4))("invalid dim: %d\n", dim);
      return referenceElement[dim];
    };

    /** \brief
     * returns geometrical information. Currently this is only dimOfWorld.
     */
    static inline int getGeo(GeoIndex p) {
      if (WORLD == p) 
	return dimOfWorld; 

      ERROR_EXIT("Illegal request for geometry data: part=%d!\n", p);
      return 0;
    };

    /** \brief
     * returns geometrical information about elements of the dimension dim.
     * getGeo(VERTEX, 3) returns 4 because a Tetrahedron has 4 vertices.
     */
    static inline int getGeo(GeoIndex p, int dim) {
      TEST_EXIT_DBG((p >= MINPART) && (p <= MAXPART))
	("Calling for invalid geometry value %d\n",p);
      TEST_EXIT_DBG((dim >= 0) && (dim < 4))
	("invalid dim: %d\n", dim);
      TEST_EXIT_DBG((dim != 0) || (p == PARTS || p == VERTEX || p == EDGE || p == FACE))
	("dim = 0\n");

      return geoIndexTable[dim][p - MINPART];
    }

    /** \brief
     * inits the Global class with the help of Parameters.
     */
    static void init();

  private:
    /** \brief
     * Global is a pure static class. So the constructor is private to avoid
     * instantiation.
     */
    Global();

  private:
    /** \brief
     * dimension of the simulated world
     */
    static int dimOfWorld;

    /** \brief
     * contains a pointer to a Line, a Triangle, and a Tetrahedron.
     * This allows the access to information of the concrete elements via
     * the dimension index.
     * referenceElement[3]->getGeo(VERTEX) gives the number of vertices of a
     * Tetrahedron wich is 4 => no switch statement is necessary.
     */
    static Element *referenceElement[4];

    /** \brief
     * Stores the precalculated results that should be returned by Global::getGeo.
     */
    static ::std::vector< ::std::vector< int > > geoIndexTable;
  };

#define COMMA ,

  const int RescheduleErrorCode = 23;

  ::std::string memSizeStr(int size);
}

#endif // AMDIS_GLOBAL_H