Global.cc 10.4 KB
Newer Older
1 2 3 4 5 6 7
/******************************************************************************
 *
 * AMDiS - Adaptive multidimensional simulations
 *
 * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
 * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
 *
8
 * Authors:
9 10 11 12 13 14 15 16 17
 * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * This file is part of AMDiS
 *
 * See also license.opensource.txt in the distribution.
18
 *
19
 ******************************************************************************/
20 21


22 23 24 25
#include <stdarg.h>
#include <stdio.h>
#include <sstream>

26
#include "Global.h"
27
#include "Initfile.h"
28 29 30 31
#include "Element.h"
#include "Line.h"
#include "Triangle.h"
#include "Tetrahedron.h"
32 33
#ifdef HAVE_PARALLEL_PETSC
  #include "petsc.h"
34
#endif
35 36 37
#ifdef HAVE_OPENMP
#include <omp.h>
#endif
38 39
namespace AMDiS {

40
  const char *funcName = NULL;
41

42
#if defined(HAVE_PARALLEL_DOMAIN_AMDIS) || defined(HAVE_OPENMP) || defined(HAVE_MPI)
43
  bool Msg::outputMainRank = true;
44 45
#endif

46 47 48
  ThreadPrivate<const char *> Msg::oldFuncName(NULL);
  std::ostream* Msg::out = NULL;
  std::ostream* Msg::error = NULL;
49
  int Global::dimOfWorld = 0;
50
  std::vector<std::vector<int> > Global::geoIndexTable;
51 52 53
  int Msg::msgInfo = 10;
  bool Msg::msgWait = true;

54 55 56 57 58
  Element *Global::referenceElement[4] =
    { NULL,
      new Line(NULL),
      new Triangle(NULL),
      new Tetrahedron(NULL)
Thomas Witkowski's avatar
Thomas Witkowski committed
59
    };
60

61

62 63 64 65 66
  void Msg::wait(bool w)
  {
    FUNCNAME("Msg::wait()");

    if (w) {
Praetorius, Simon's avatar
Praetorius, Simon committed
67
      char line;
68
      MSG("wait for <enter> ...");
69 70
      std::cin >> line;
//       char* result = fgets(line, 9, stdin);
71 72 73
    }
  }

74

75
  void Msg::change_out(std::ostream  *fp)
76 77
  {
    FUNCNAME("Msg::change_out()");
78

79
    if (fp) {
Praetorius, Simon's avatar
Praetorius, Simon committed
80 81 82 83
//       if (out && *out != std::cout && *out != std::cerr) {
// 	dynamic_cast< std::ofstream*>(out)->close();
// 	delete out;
//       }
84 85 86 87 88

      out = fp;
    } else {
      ERROR("file pointer is pointer to nil;\n");
      ERROR("use previous stream for errors furthermore\n");
89
    }
90 91
  }

92

93
  void Msg::change_error_out(std::ofstream *fp)
94
  {
95 96 97
    FUNCNAME("Msg::change_error_out()");

    if (fp) {
Praetorius, Simon's avatar
Praetorius, Simon committed
98 99 100 101
//       if (error && *error != std::cout && *error != std::cerr) {
// 	dynamic_cast< std::ofstream*>(error)->close();
// 	delete error;
//       }
102

103 104 105 106 107
      error = fp;
    } else {
      ERROR("file pointer is pointer to nil;\n");
      ERROR("use previous stream for errors furthermore\n");
    }
108 109
  }

110

111 112
  void Msg::open_error_file(const char *filename, OPENMODE type)
  {
113
    FUNCNAME("Msg::open_error_file()");
114
    std::ofstream *fp;
115

116
    if (filename && (fp = new std::ofstream(filename, type))) {
Praetorius, Simon's avatar
Praetorius, Simon committed
117 118 119 120
//       if (error && *error != std::cout && *error != std::cerr) {
// 	dynamic_cast< std::ofstream*>(error)->close();
// 	delete error;
//       }
121 122 123 124 125 126 127 128 129

      error = fp;
    } else {
      if (filename)
	ERROR("can not open %s;\n", filename);
      else
	ERROR("no filename specified;\n");
      ERROR("use previous stream for errors furthermore\n");
    }
130 131
  }

132

133 134
  void Msg::print_funcname(const char *funcName)
  {
135
#if defined(HAVE_PARALLEL_DOMAIN_AMDIS) || defined(HAVE_MPI)
136 137 138
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif
139 140 141 142
#ifdef HAVE_OPENMP
    if (outputMainRank && omp_get_thread_num() != 0)
      return;
#endif
143

144
    if (!out)
145
      out = &std::cout;
146

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
147
    if (funcName &&  oldFuncName.get() != funcName) {
148
      PRINT_LINE((*out), funcName << ":" << std::endl);
149
    } else if (!funcName) {
150
      PRINT_LINE((*out), "*unknown function*" << std::endl);
151
    }
152 153
    PRINT_LINE((*out), "               ");

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
154
    oldFuncName.set(funcName);
155 156
  }

157

158
  void Msg::print_error_funcname(const char *funcName, const char *file, int line)
159 160 161
  {
    static int old_line = -1;

162
    if (!error)
163
      error = &std::cerr;
164

165 166
    std::stringstream oss;

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
167
    if (funcName && oldFuncName.get() != funcName) {
168
      oss << funcName << ": ";
169
    } else if (!funcName) {
170
      if (line-old_line > 5)
171
	oss << "*unknown function*";
172
    }
173

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
174
    if (oldFuncName.get() != funcName) {
175
      oss << "ERROR in " << file << ", line " << line << std::endl;;
Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
176
      oldFuncName.set(funcName);
177
    } else if (line - old_line > 5)
178
      oss << "ERROR in " << file << ", line " << line << "\n" << std::endl;
179

180
    PRINT_LINE((*error), oss.str());
181 182 183
    old_line = line;
  }

184

185 186
  void Msg::print_error_exit(const char *format, ...)
  {
187 188
    va_list arg;
    char buff[255];
189

190
    if (!error)
191
      error = &std::cerr;
192 193 194

    va_start(arg, format);
    vsprintf(buff, format, arg);
195
    PRINT_LINE((*error), buff);
196
    va_end(arg);
197
#if defined HAVE_PARALLEL_DOMAIN_AMDIS && !defined HAVE_PARALLEL_MTL4 && (defined NDEBUG)
198 199 200
  #if (PETSC_VERSION_MINOR >= 5)
    PetscError(MPI_COMM_WORLD, __LINE__, "Msg::print_error_exit", "Global.cc", 1, PETSC_ERROR_INITIAL, buff);
  #else
201
    PetscError(MPI_COMM_WORLD, __LINE__, "Msg::print_error_exit", "Global.cc", "src/", 1, PETSC_ERROR_INITIAL, buff);
202
  #endif
203
#else
204
    throw std::runtime_error(buff);
205
#endif
206 207 208
    exit(1);
  }

209

210 211
  void Msg::print_error(const char *format, ...)
  {
212 213
    va_list arg;
    char buff[255];
214 215


216
    if (!error)
217
      error = &std::cerr;
218 219 220

    va_start(arg, format);
    vsprintf(buff, format, arg);
221
    PRINT_LINE((*error), buff);
222 223 224
    va_end(arg);
  }

225

226
  void Msg::print_warn_funcname(const char *funcName,
227
				const char *file,
228 229
				int line)
  {
230
#if (defined(HAVE_PARALLEL_DOMAIN_AMDIS) || defined(HAVE_MPI)) && defined(NDEBUG)
Thomas Witkowski's avatar
Thomas Witkowski committed
231 232 233
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif
234 235 236 237
#ifdef HAVE_OPENMP
    if (outputMainRank && omp_get_thread_num() != 0)
      return;
#endif
Thomas Witkowski's avatar
Thomas Witkowski committed
238

239
    static int old_line = -1;
240

241
    if (!out)
242
      out = &std::cout;
243

244 245
    std::stringstream oss;

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
246
    if (funcName  &&  oldFuncName.get() != funcName) {
247 248 249
      oss << funcName << ": ";
    } else if (!funcName) {
      oss << "*unknown function*";
250
    }
251

Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
252
    if (oldFuncName.get() != funcName) {
253
      oss << "WARNING in " << file << ", line " << line << std::endl;
Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
254
      oldFuncName.set(funcName);
255 256 257 258
    } else if (line - old_line > 5) {
      oss << "WARNING in " << file << ", line " << line << std::endl;
    }

259
    if (oss.str() != "")
260
      PRINT_LINE((*out), oss.str());
261

262 263 264
    old_line = line;
  }

265

266 267
  void Msg::print_warn(const char *format, ...)
  {
268
#if (defined(HAVE_PARALLEL_DOMAIN_AMDIS) || defined(HAVE_MPI)) && defined(NDEBUG)
Thomas Witkowski's avatar
Thomas Witkowski committed
269 270
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
271 272 273 274
#endif
#ifdef HAVE_OPENMP
    if (outputMainRank && omp_get_thread_num() != 0)
      return;
Thomas Witkowski's avatar
Thomas Witkowski committed
275
#endif
276 277
    va_list arg;
    char buff[255];
278

279
    if (!out)
280
      out = &std::cout;
281 282 283

    va_start(arg, format);
    vsprintf(buff, format, arg);
284
    PRINT_LINE((*out), buff);
285 286 287 288 289 290
    va_end(arg);
  }


  void Msg::print(const char *format, ...)
  {
Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
291
#ifndef SUPPRESS_OUTPUT
292
#if defined(HAVE_PARALLEL_DOMAIN_AMDIS) || defined(HAVE_MPI)
293 294 295
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif
296 297 298 299
#ifdef HAVE_OPENMP
    if (outputMainRank && omp_get_thread_num() != 0)
      return;
#endif
300

301 302
    va_list arg;
    char buff[255];
303

304
    if (!out)
305
      out = &std::cout;
306 307 308

    va_start(arg, format);
    vsprintf(buff, format, arg);
309
    (*out) << buff;
310
    va_end(arg);
Thomas Witkowski's avatar
Blub  
Thomas Witkowski committed
311
#endif
312 313
  }

314

315 316 317 318 319
  void Global::init()
  {
    int d = -1;

    // get dimension
320
    Parameters::get("dimension of world",d,0);
321
    TEST_EXIT(d > 0)("Cannot initialize dimension!\n");
322
    TEST_EXIT((d == 1) || (d == 2) || (d == 3))("Invalid world dimension %d!\n",d);
323 324 325 326

    // set dimension
    dimOfWorld = d;

327 328 329 330 331
    // prepare geoIndex-Table
    int geoTableSize = abs(static_cast<int>(MINPART)) + MAXPART + 1;
    geoIndexTable.resize(4);
    for (int i = 0; i < 4; i++) {
      geoIndexTable[i].resize(geoTableSize);
332
      for (int j = 0; j < geoTableSize; j++)
333
	geoIndexTable[i][j] = 0;
334 335
    }

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    geoIndexTable[0][PARTS - MINPART] = 1;
    geoIndexTable[0][VERTEX - MINPART] = 1;
    geoIndexTable[0][EDGE - MINPART] = 0;
    geoIndexTable[0][FACE - MINPART] = 0;
    geoIndexTable[0][WORLD - MINPART] = dimOfWorld;

    for (int i = 1; i < 4; i++) {
      geoIndexTable[i][CENTER - MINPART] = referenceElement[i]->getGeo(CENTER);
      geoIndexTable[i][VERTEX - MINPART] = referenceElement[i]->getGeo(VERTEX);
      geoIndexTable[i][EDGE - MINPART] = referenceElement[i]->getGeo(EDGE);
      geoIndexTable[i][FACE - MINPART] = referenceElement[i]->getGeo(FACE);
      geoIndexTable[i][DIMEN - MINPART] = referenceElement[i]->getGeo(DIMEN);
      geoIndexTable[i][PARTS - MINPART] = referenceElement[i]->getGeo(PARTS);
      geoIndexTable[i][NEIGH - MINPART] = referenceElement[i]->getGeo(NEIGH);
      geoIndexTable[i][WORLD - MINPART] = dimOfWorld;
      geoIndexTable[i][BOUNDARY - MINPART] = referenceElement[i]->getGeo(BOUNDARY);
      geoIndexTable[i][PROJECTION - MINPART] = referenceElement[i]->getGeo(PROJECTION);
    }
354

355
    // set msgWait
356
    Msg::setMsgWait(!(Parameters::getMsgWait() == 0));
357 358
  }

359

360 361
  void Global::clear()
  {
Thomas Witkowski's avatar
Thomas Witkowski committed
362 363 364
    delete referenceElement[1];
    delete referenceElement[2];
    delete referenceElement[3];
365
  }
366

367

368 369
  int fac(int i)
  {
370
    if (i <= 1)
371
      return 1;
372
    else
373
      return i * fac(i - 1);
374 375
  }

376

377 378 379 380 381 382
  void waitSec(int seconds)
  {
    clock_t endwait = clock () + seconds * CLOCKS_PER_SEC;
    while (clock() < endwait) {}
  }

383

384
  void processMemUsage(double& vm_usage, double& resident_set, bool inMegaByte)
385
  {
386
#ifndef _WIN32
387 388 389
    using std::ios_base;
    using std::ifstream;
    using std::string;
390

391 392
    vm_usage     = 0.0;
    resident_set = 0.0;
393 394

    // 'file' stat seems to give the most reliable results
395
    ifstream stat_stream("/proc/self/stat",ios_base::in);
396

397 398 399 400 401
    // dummy vars for leading entries in stat that we don't care about
    string pid, comm, state, ppid, pgrp, session, tty_nr;
    string tpgid, flags, minflt, cminflt, majflt, cmajflt;
    string utime, stime, cutime, cstime, priority, nice;
    string O, itrealvalue, starttime;
402 403

    // the two fields we want
404 405
    unsigned long vsize;
    long rss;
406

407 408 409 410 411
    stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
		>> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
		>> utime >> stime >> cutime >> cstime >> priority >> nice
		>> O >> itrealvalue >> starttime >> vsize >> rss;

412
    // in case x86-64 is configured to use 2MB pages
413
    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024;
414
    vm_usage = vsize / 1024.0;
415
    resident_set = rss * page_size_kb;
416 417 418 419 420

    if (inMegaByte) {
      vm_usage /= 1024.0;
      resident_set /= 1024.0;
    }
421 422 423
#else
    ERROR("Function not available under MS Windows\n");
#endif
424 425 426
  }


427
}