// ============================================================================ // == == // == 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); /** * \ingroup Assembler * \brief * Specifies the type of a FirstOrderTerm */ enum FirstOrderType { GRD_PSI, GRD_PHI }; } #endif // AMDIS_GLOBAL_H