Global.cc 9.91 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
namespace AMDiS {

37
  const char *funcName = NULL;
38
39

#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
40
  bool Msg::outputMainRank = true;
41
42
#endif

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

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

58

59
60
61
62
63
  void Msg::wait(bool w)
  {
    FUNCNAME("Msg::wait()");

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

71

72
  void Msg::change_out(std::ostream  *fp)
73
74
  {
    FUNCNAME("Msg::change_out()");
75

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

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

89

90
  void Msg::change_error_out(std::ofstream *fp)
91
  {
92
93
94
    FUNCNAME("Msg::change_error_out()");

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

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

107

108
109
  void Msg::open_error_file(const char *filename, OPENMODE type)
  {
110
    FUNCNAME("Msg::open_error_file()");
111
    std::ofstream *fp;
112

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

      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");
    }
127
128
  }

129

130
131
  void Msg::print_funcname(const char *funcName)
  {
132
133
134
135
136
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif

137
    if (!out)
138
      out = &std::cout;
139

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
140
    if (funcName &&  oldFuncName.get() != funcName) {
141
      PRINT_LINE((*out), funcName << ":" << std::endl);
142
    } else if (!funcName) {
143
      PRINT_LINE((*out), "*unknown function*" << std::endl);
144
    }
145
146
    PRINT_LINE((*out), "               ");

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
147
    oldFuncName.set(funcName);
148
149
  }

150

151
  void Msg::print_error_funcname(const char *funcName, const char *file, int line)
152
153
154
  {
    static int old_line = -1;

155
    if (!error)
156
      error = &std::cerr;
157

158
159
    std::stringstream oss;

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
160
    if (funcName && oldFuncName.get() != funcName) {
161
      oss << funcName << ": ";
162
    } else if (!funcName) {
163
      if (line-old_line > 5)
164
	oss << "*unknown function*";
165
    }
166

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
167
    if (oldFuncName.get() != funcName) {
168
      oss << "ERROR in " << file << ", line " << line << std::endl;;
Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
169
      oldFuncName.set(funcName);
170
    } else if (line - old_line > 5)
171
      oss << "ERROR in " << file << ", line " << line << "\n" << std::endl;
172

173
    PRINT_LINE((*error), oss.str());
174
175
176
    old_line = line;
  }

177

178
179
  void Msg::print_error_exit(const char *format, ...)
  {
180
181
    va_list arg;
    char buff[255];
182

183
    if (!error)
184
      error = &std::cerr;
185
186
187

    va_start(arg, format);
    vsprintf(buff, format, arg);
188
    PRINT_LINE((*error), buff);
189
    va_end(arg);
190
#if defined HAVE_PARALLEL_DOMAIN_AMDIS && !defined HAVE_PARALLEL_MTL4 && (defined NDEBUG)
191
192
193
  #if (PETSC_VERSION_MINOR >= 5)
    PetscError(MPI_COMM_WORLD, __LINE__, "Msg::print_error_exit", "Global.cc", 1, PETSC_ERROR_INITIAL, buff);
  #else
194
    PetscError(MPI_COMM_WORLD, __LINE__, "Msg::print_error_exit", "Global.cc", "src/", 1, PETSC_ERROR_INITIAL, buff);
195
  #endif
196
#else
197
    throw std::runtime_error(buff);
198
#endif
199
200
201
    exit(1);
  }

202

203
204
  void Msg::print_error(const char *format, ...)
  {
205
206
    va_list arg;
    char buff[255];
207
208


209
    if (!error)
210
      error = &std::cerr;
211
212
213

    va_start(arg, format);
    vsprintf(buff, format, arg);
214
    PRINT_LINE((*error), buff);
215
216
217
    va_end(arg);
  }

218

219
  void Msg::print_warn_funcname(const char *funcName,
220
				const char *file,
221
222
				int line)
  {
223
#if defined(HAVE_PARALLEL_DOMAIN_AMDIS) && defined(NDEBUG)
Thomas Witkowski's avatar
Thomas Witkowski committed
224
225
226
227
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif

228
    static int old_line = -1;
229

230
    if (!out)
231
      out = &std::cout;
232

233
234
    std::stringstream oss;

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
235
    if (funcName  &&  oldFuncName.get() != funcName) {
236
237
238
      oss << funcName << ": ";
    } else if (!funcName) {
      oss << "*unknown function*";
239
    }
240

Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
241
    if (oldFuncName.get() != funcName) {
242
      oss << "WARNING in " << file << ", line " << line << std::endl;
Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
243
      oldFuncName.set(funcName);
244
245
246
247
    } else if (line - old_line > 5) {
      oss << "WARNING in " << file << ", line " << line << std::endl;
    }

248
    if (oss.str() != "")
249
      PRINT_LINE((*out), oss.str());
250

251
252
253
    old_line = line;
  }

254

255
256
  void Msg::print_warn(const char *format, ...)
  {
257
#if defined(HAVE_PARALLEL_DOMAIN_AMDIS) && defined(NDEBUG)
Thomas Witkowski's avatar
Thomas Witkowski committed
258
259
260
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif
261
262
    va_list arg;
    char buff[255];
263

264
    if (!out)
265
      out = &std::cout;
266
267
268

    va_start(arg, format);
    vsprintf(buff, format, arg);
269
    PRINT_LINE((*out), buff);
270
271
272
273
274
275
    va_end(arg);
  }


  void Msg::print(const char *format, ...)
  {
Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
276
#ifndef SUPPRESS_OUTPUT
277
278
279
280
281
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
    if (outputMainRank && MPI::COMM_WORLD.Get_rank() != 0)
      return;
#endif

282
283
    va_list arg;
    char buff[255];
284

285
    if (!out)
286
      out = &std::cout;
287
288
289

    va_start(arg, format);
    vsprintf(buff, format, arg);
290
    (*out) << buff;
291
    va_end(arg);
Thomas Witkowski's avatar
Blub    
Thomas Witkowski committed
292
#endif
293
294
  }

295

296
297
298
299
300
301
  void Global::init()
  {
    int d = -1;

    // get dimension
    TEST_EXIT(Parameters::initialized())("Parameters not initialized!\n");
302
    Parameters::get("dimension of world",d,0);
303
    TEST_EXIT(d > 0)("Cannot initialize dimension!\n");
304
    TEST_EXIT((d == 1) || (d == 2) || (d == 3))("Invalid world dimension %d!\n",d);
305
306
307
308

    // set dimension
    dimOfWorld = d;

309
310
311
312
313
    // 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);
314
      for (int j = 0; j < geoTableSize; j++)
315
	geoIndexTable[i][j] = 0;
316
317
    }

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    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);
    }
336

337
    // set msgWait
338
    Msg::setMsgWait(!(Parameters::getMsgWait() == 0));
339
340
  }

341

342
343
  void Global::clear()
  {
Thomas Witkowski's avatar
Thomas Witkowski committed
344
345
346
    delete referenceElement[1];
    delete referenceElement[2];
    delete referenceElement[3];
347
  }
348

349

350
351
  int fac(int i)
  {
352
    if (i <= 1)
353
      return 1;
354
    else
355
      return i * fac(i - 1);
356
357
  }

358

359
360
361
362
363
364
  void waitSec(int seconds)
  {
    clock_t endwait = clock () + seconds * CLOCKS_PER_SEC;
    while (clock() < endwait) {}
  }

365

366
  void processMemUsage(double& vm_usage, double& resident_set, bool inMegaByte)
367
  {
368
#ifndef _WIN32
369
370
371
    using std::ios_base;
    using std::ifstream;
    using std::string;
372

373
374
    vm_usage     = 0.0;
    resident_set = 0.0;
375
376

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

379
380
381
382
383
    // 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;
384
385

    // the two fields we want
386
387
    unsigned long vsize;
    long rss;
388

389
390
391
392
393
    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;

394
    // in case x86-64 is configured to use 2MB pages
395
    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024;
396
    vm_usage = vsize / 1024.0;
397
    resident_set = rss * page_size_kb;
398
399
400
401
402

    if (inMegaByte) {
      vm_usage /= 1024.0;
      resident_set /= 1024.0;
    }
403
404
405
#else
    ERROR("Function not available under MS Windows\n");
#endif
406
407
408
  }


409
}