MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
functions.h File Reference

Go to the source code of this file.

Classes

struct  detail_::APPROX_ERROR< T, U >
 

Namespaces

namespace  detail_
 

Functions

 ATTRIBUTES1 (ATTRIBUTE_NORETURN) void mTerm(const MInt errorCode
 controlled termination of maia with a user defined error message More...
 
MFloat cpuTime ()
 Return the process cpu time (user time) (high-resolution timer - do not use clock()) More...
 
MFloat wallTime ()
 
template<class Real >
Real ABS (const Real x)
 
template<class T >
constexpr T mMin (const T &x, const T &y)
 
template<class T >
constexpr T mMax (const T &x, const T &y)
 
template<class T >
MIN3 (const T &x, const T &y, const T &z)
 
template<class T >
MAX3 (const T &x, const T &y, const T &z)
 
template<class T >
constexpr const T & Clamp (const T &v, const T &lo, const T &hi)
 
MInt copyFile (const MString &fromName, const MString &toName)
 Copies file fromName to file toName. More...
 
MBool fileExists (const MString &fileName)
 Returns true if the file fileName exists, false otherwise. More...
 
template<class Real >
constexpr Real POW2 (const Real x)
 
template<class Real >
constexpr Real POW3 (const Real x)
 
template<class Real >
constexpr Real POW4 (const Real x)
 
template<class Real >
constexpr Real POW5 (const Real x)
 
template<class Real >
constexpr Real POW6 (const Real x)
 
template<typename T >
T constexpr POWX (T base, MUint exponent)
 Compile time power calculation. More...
 
template<typename T >
std::enable_if< std::is_unsigned< T >::value, int >::type constexpr signum (T x)
 
template<typename T >
std::enable_if< std::is_signed< T >::value, int >::type constexpr signum (T x)
 
template<typename T >
std::enable_if< std::is_unsigned< T >::value, int >::type constexpr signum0 (T x)
 
template<typename T >
std::enable_if< std::is_signed< T >::value, int >::type constexpr signum0 (T x)
 
template<class T , class U >
MBool approx (const T &, const U &, const T)
 
template<>
MBool approx< MFloat, MFloat > (const MFloat &a, const MFloat &b, const MFloat eps)
 
template<class T >
MBool isApproxInt (const T &, const T)
 
template<>
MBool isApproxInt< MFloat > (const MFloat &a, const MFloat eps)
 Return true if argument is approximately an integer. More...
 
MInt ipow (MInt base, MInt exp)
 Integer exponent function for non-negative exponents. More...
 
void checkMultiSolverGridExtents (const MInt nDim, const MFloat *centerOfGravity, const MFloat lengthLevel0, const MInt minLevel, const MFloat *targetGridCenterOfGravity, const MFloat targetGridLengthLevel0, const MInt targetGridMinLevel)
 Checks if the given grid extents and cell sizes match when creating a multisolver grid and corresponding single solver grids to ensure that the same min-level cells and Hilbert order is used. More...
 
MInt loadPointCoordinatesFromFile (const MString inputFileName, const MInt nDim, std::vector< MFloat > &coordinates)
 Loads point coordinates from an input file. More...
 
void writeMemoryStatistics (const MPI_Comm comm, const MInt noDomains, const MInt domainId, const MString at, const MString comment="")
 Write memory statistics. More...
 
int intSwap (int f)
 
float floatSwap (float f)
 
double doubleSwap (double f)
 
template<class ContainerT >
void tokenize (const std::string &str, ContainerT &tokens, const std::string &delimiters=" ", MBool trimEmpty=false)
 
void createDir (const std::string &dir)
 

Variables

const MStringlocation
 
const MString const MStringmessage = "")
 

Function Documentation

◆ ABS()

template<class Real >
Real ABS ( const Real  x)
inline

Definition at line 85 of file functions.h.

85 {
86 return std::fabs(x);
87}

◆ approx()

template<class T , class U >
MBool approx ( const T &  ,
const U &  ,
const  T 
)

Definition at line 272 of file functions.h.

272 {
274 error();
275 return true;
276}

◆ approx< MFloat, MFloat >()

template<>
MBool approx< MFloat, MFloat > ( const MFloat a,
const MFloat b,
const MFloat  eps 
)
inline

Definition at line 279 of file functions.h.

279 {
280 return std::fabs(a - b) < eps;
281}
Definition: contexttypes.h:19

◆ ATTRIBUTES1()

ATTRIBUTES1 ( ATTRIBUTE_NORETURN  ) const
Author
Pascal Meysonnat, Christoph Siewert, Michael Schlottke
Date
September/November 2011, June 2012

◆ checkMultiSolverGridExtents()

void checkMultiSolverGridExtents ( const MInt  nDim,
const MFloat centerOfGravity,
const MFloat  lengthLevel0,
const MInt  minLevel,
const MFloat targetGridCenterOfGravity,
const MFloat  targetGridLengthLevel0,
const MInt  targetGridMinLevel 
)

Note: from createGridMap()

Definition at line 112 of file functions.cpp.

114 {
115 // Define epsilon for floating point comparisons (argh!)... the original
116 // definition is taken from the grid constructor but it must be clear to anyone
117 // that this is a less-than-optimal solution
118 const MFloat eps = 1.0 / FPOW2(30) * lengthLevel0;
119
120 m_log << std::setprecision(15) << "Check multisolver grid extends: length0=" << lengthLevel0
121 << "; minLevel=" << minLevel << "; targetLenght0=" << targetGridLengthLevel0
122 << "; targetMinLevel=" << targetGridMinLevel << "; eps=" << eps << std::endl;
123
124 // Check extents
125 const std::array<MString, 3> dirs = {{"x", "y", "z"}};
126 for(MInt dir = 0; dir < nDim; dir++) {
127 const std::array<MFloat, 2> gridExtent = {
128 {centerOfGravity[dir] - 0.5 * lengthLevel0, centerOfGravity[dir] + 0.5 * lengthLevel0}};
129 const std::array<MFloat, 2> globalExtent = {{targetGridCenterOfGravity[dir] - 0.5 * targetGridLengthLevel0,
130 targetGridCenterOfGravity[dir] + 0.5 * targetGridLengthLevel0}};
131
132 if(gridExtent[0] + eps < globalExtent[0]) {
133 TERMM(1,
134 "Grid extents exceed multisolver bouding box in negative " + dirs[dir]
135 + "-direction: grid=" + std::to_string(gridExtent[0]) + "; box=" + std::to_string(globalExtent[0]));
136 }
137 if(gridExtent[1] - eps > globalExtent[1]) {
138 TERMM(1,
139 "Grid extents exceed multisolver bouding box in positive " + dirs[dir]
140 + "-direction: grid=" + std::to_string(gridExtent[1]) + "; box=" + std::to_string(globalExtent[1]));
141 }
142 m_log << std::setprecision(15) << "Grid extents in the " << dirs[dir] << "-direction: [" << gridExtent[0] << ", "
143 << gridExtent[1] << "]; global: [" << globalExtent[0] << ", " << globalExtent[1] << "]" << std::endl;
144 }
145
146 // Check cell length at min level
147 const MFloat gridMinLevelLength = lengthLevel0 * FFPOW2(minLevel);
148 const MFloat globalMinLevelLength = targetGridLengthLevel0 * FFPOW2(targetGridMinLevel);
149 if(fabs(gridMinLevelLength - globalMinLevelLength) > eps) {
150 TERMM(1,
151 "Length of min level cells do not match between grid and given multisolver bounding "
152 "box: grid: "
153 + std::to_string(gridMinLevelLength) + "; box: " + std::to_string(globalMinLevelLength));
154 } else {
155 m_log << std::setprecision(15)
156 << "Length of min level cells match between grid and given multisolver bounding "
157 "box: grid: "
158 << gridMinLevelLength << "; box: " << globalMinLevelLength << std::endl;
159 }
160
161 // Check if grid centers are displaced by an integer multiple of the min
162 // level length
163 for(MInt dir = 0; dir < nDim; dir++) {
164 const MFloat displacement = fabs(centerOfGravity[dir] - targetGridCenterOfGravity[dir]);
165 const MFloat quotient = displacement / globalMinLevelLength;
166 if(!isApproxInt(quotient, eps)) {
167 TERMM(1, "The grid centers are displaced in the " + dirs[dir]
168 + "-direction by a non-integer multiple of the length of a "
169 "partition cell: "
170 + std::to_string(quotient));
171 } else {
172 m_log << std::setprecision(15) << "The grid centers are displaced in the " << dirs[dir]
173 << "-direction by a multiple of the length of a "
174 "partition cell: "
175 << quotient << " (displacement = " << displacement << ")" << std::endl;
176 }
177 }
178}
MBool isApproxInt(const T &, const T)
Definition: functions.h:284
InfoOutFile m_log
constexpr MFloat FPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
int32_t MInt
Definition: maiatypes.h:62
double MFloat
Definition: maiatypes.h:52

◆ Clamp()

template<class T >
constexpr const T & Clamp ( const T &  v,
const T &  lo,
const T &  hi 
)
constexpr

Definition at line 107 of file functions.h.

107 {
108 TERMM_IF_COND((hi < lo), "");
109 return (v < lo) ? lo : (hi < v) ? hi : v;
110}

◆ copyFile()

MInt copyFile ( const MString fromName,
const MString toName 
)
Returns
error code
Return values
0if copying succeeded
-1if copying failed

Definition at line 83 of file functions.cpp.

83 {
84 if(!fileExists(fromName)) {
85 std::cerr << "Could not copy file " << fromName << ".\n";
86 return -1;
87 }
88 if(fileExists(toName)) {
89 remove(toName.c_str());
90 }
91 std::ifstream src(fromName.c_str());
92 std::ofstream dst(toName.c_str());
93 if(src.good() && dst.good()) {
94 dst << src.rdbuf();
95 dst.close();
96 dst.clear();
97 src.close();
98 src.clear();
99 } else {
100 std::cerr << "Could not copy file " << fromName << " (2).\n";
101 return -1;
102 }
103 return 0;
104}
MBool fileExists(const MString &fileName)
Returns true if the file fileName exists, false otherwise.
Definition: functions.cpp:73

◆ cpuTime()

MFloat cpuTime ( )
inline

Definition at line 73 of file functions.h.

73 {
74 timespec tp;
75 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
76 const MFloat t_user = (tp.tv_sec + (MFloat)tp.tv_nsec / 1e9);
77 return t_user;
78}
constexpr MFloat tp[4]
taylor-polynom coefficients for equilibrium calculation (0:rest, 1:face, 2:edge, 3:corner)

◆ createDir()

void createDir ( const std::string &  dir)
inline

Definition at line 462 of file functions.h.

462 {
463 struct stat s {};
464 if(stat(dir.c_str(), &s) < 0) {
465 // Create directory if it does not yet exist
466 mkdir(dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IXGRP | S_IXGRP);
467 }
468}

◆ doubleSwap()

double doubleSwap ( double  f)
inline

Definition at line 379 of file functions.h.

379 { // Change endian of double
380 union {
381 double f;
382 unsigned char b[8];
383 } dat1{}, dat2{};
384
385 dat1.f = f;
386 dat2.b[0] = dat1.b[7];
387 dat2.b[1] = dat1.b[6];
388 dat2.b[2] = dat1.b[5];
389 dat2.b[3] = dat1.b[4];
390 dat2.b[4] = dat1.b[3];
391 dat2.b[5] = dat1.b[2];
392 dat2.b[6] = dat1.b[1];
393 dat2.b[7] = dat1.b[0];
394 return dat2.f;
395}

◆ fileExists()

MBool fileExists ( const MString fileName)

Definition at line 73 of file functions.cpp.

73 {
74 struct stat buffer;
75 return (stat(fileName.c_str(), &buffer) == 0);
76}

◆ floatSwap()

float floatSwap ( float  f)
inline

Definition at line 365 of file functions.h.

365 { // Change endian of float
366 union {
367 float f;
368 unsigned char b[4];
369 } dat1{}, dat2{};
370
371 dat1.f = f;
372 dat2.b[0] = dat1.b[3];
373 dat2.b[1] = dat1.b[2];
374 dat2.b[2] = dat1.b[1];
375 dat2.b[3] = dat1.b[0];
376 return dat2.f;
377}

◆ intSwap()

int intSwap ( int  f)
inline

Definition at line 351 of file functions.h.

351 { // Change endian of int
352 union {
353 int f;
354 unsigned char b[4];
355 } dat1{}, dat2{};
356
357 dat1.f = f;
358 dat2.b[0] = dat1.b[3];
359 dat2.b[1] = dat1.b[2];
360 dat2.b[2] = dat1.b[1];
361 dat2.b[3] = dat1.b[0];
362 return dat2.f;
363}

◆ ipow()

MInt ipow ( MInt  base,
MInt  exp 
)
inline
Author
Michael Schlottke (mic) mic@a.nosp@m.ia.r.nosp@m.wth-a.nosp@m.ache.nosp@m.n.de
Date
2012-11-14
Parameters
[in]baseThe base (positive or negative).
[in]expThe exponent (non-negative).
Returns
base^exp, i.e. base to the power of exp

Taken from http://stackoverflow.com/a/101613/1329844.

Definition at line 317 of file functions.h.

317 {
318 ASSERT(exp >= 0, "Error in ipow: exponent is less than zero (must be greater or equal to zero)!");
319
320 MInt result = 1;
321 while(exp) {
322 if(exp & 1) {
323#ifndef NDEBUG
324 // This piece of code checks (if no -DNDEBUG flag was given during compilation) if signed integer overflow
325 // occurs, and if yes, aborts the program. Signed integer overflow is detected if the result of the last
326 // multiplication can not be reversed.
327 MInt result_test = result * base;
328 ASSERT(((base != 0 && result_test / base == result) || base == 0), "Error in ipow: signed integer overflow!");
329#endif
330 result *= base;
331 }
332 exp >>= 1;
333 base *= base;
334 }
335
336 return result;
337}

◆ isApproxInt()

template<class T >
MBool isApproxInt ( const T &  ,
const  T 
)

Definition at line 284 of file functions.h.

284 {
286 error();
287 return true;
288}

◆ isApproxInt< MFloat >()

template<>
MBool isApproxInt< MFloat > ( const MFloat a,
const MFloat  eps 
)
inline
Author
Michael Schlottke-Lakemper (mic) mic@a.nosp@m.ia.r.nosp@m.wth-a.nosp@m.ache.nosp@m.n.de
Date
2016-07-08
Parameters
[in]aArgument to check.
[in]epsEpsilon for floating point comparison.
Returns
True if argument is approximately an integer.

Definition at line 300 of file functions.h.

300 {
301 return approx(std::fabs(std::round(a) - a), 0.0, eps);
302}
MBool approx(const T &, const U &, const T)
Definition: functions.h:272

◆ loadPointCoordinatesFromFile()

MInt loadPointCoordinatesFromFile ( const MString  inputFileName,
const MInt  nDim,
std::vector< MFloat > &  coordinates 
)

Definition at line 182 of file functions.cpp.

182 {
183 TRACE();
184
185 MString line;
186 MFloat curFloat;
187 MInt noPoints = 0;
188 std::istringstream iss;
189 std::ifstream csvFile(inputFileName);
190 coordinates.clear();
191
192 // Read all lines and get coordinates
193 while(getline(csvFile, line)) {
194 iss.str(line);
195 iss.clear();
196
197 for(MInt i = 0; i < nDim; i++) {
198 iss >> curFloat;
199 if(iss.fail()) {
200 std::ostringstream err;
201 // start line count at one
202 err << "Error at line " << noPoints + 1 << ": " << line << "\n"
203 << "Either wrong dimension (nDim = " << nDim << ") or otherwise wrong format."
204 << "Format should be nDim floats seperated by spaces per line.";
205 TERMM(1, err.str());
206 }
207 coordinates.push_back(curFloat);
208 }
209 noPoints++;
210 }
211
212 return noPoints;
213}
std::basic_string< char > MString
Definition: maiatypes.h:55
std::istream & getline(std::istream &input, std::string &line)
Definition: cpptoml.h:1519

◆ MAX3()

template<class T >
T MAX3 ( const T &  x,
const T &  y,
const T &  z 
)
inline

Definition at line 102 of file functions.h.

102 {
103 return std::max(std::max(x, y), z);
104}
define array structures

◆ MIN3()

template<class T >
T MIN3 ( const T &  x,
const T &  y,
const T &  z 
)
inline

Definition at line 98 of file functions.h.

98 {
99 return std::min(std::min(x, y), z);
100}

◆ mMax()

template<class T >
constexpr T mMax ( const T &  x,
const T &  y 
)
inlineconstexpr

Definition at line 94 of file functions.h.

94 {
95 return std::max(x, y);
96}

◆ mMin()

template<class T >
constexpr T mMin ( const T &  x,
const T &  y 
)
inlineconstexpr

Definition at line 90 of file functions.h.

90 {
91 return std::min(x, y);
92}

◆ POW2()

template<class Real >
constexpr Real POW2 ( const Real  x)
constexpr

Definition at line 119 of file functions.h.

119 {
120 return (x * x);
121}

◆ POW3()

template<class Real >
constexpr Real POW3 ( const Real  x)
constexpr

Definition at line 123 of file functions.h.

123 {
124 return (x * x * x);
125}

◆ POW4()

template<class Real >
constexpr Real POW4 ( const Real  x)
constexpr

Definition at line 127 of file functions.h.

127 {
128 return (x * x * x * x);
129}

◆ POW5()

template<class Real >
constexpr Real POW5 ( const Real  x)
constexpr

Definition at line 131 of file functions.h.

131 {
132 return (x * x * x * x * x);
133}

◆ POW6()

template<class Real >
constexpr Real POW6 ( const Real  x)
constexpr

Definition at line 135 of file functions.h.

135 {
136 return (x * x * x * x * x * x);
137}

◆ POWX()

template<typename T >
T constexpr POWX ( base,
MUint  exponent 
)
constexpr
Author
Miro Gondrum
Date
27.05.2021
Parameters
[in]base
[in]exponent

Definition at line 146 of file functions.h.

146 {
147 return (exponent == 0) ? 1 : base * POWX(base, exponent - 1);
148}
T constexpr POWX(T base, MUint exponent)
Compile time power calculation.
Definition: functions.h:146

◆ signum() [1/2]

template<typename T >
std::enable_if< std::is_unsigned< T >::value, int >::type constexpr signum ( x)
inlineconstexpr

Definition at line 151 of file functions.h.

151 {
152 return T(0) < x;
153}

◆ signum() [2/2]

template<typename T >
std::enable_if< std::is_signed< T >::value, int >::type constexpr signum ( x)
inlineconstexpr

Definition at line 156 of file functions.h.

156 {
157 return (T(0) < x) - (x < T(0));
158}

◆ signum0() [1/2]

template<typename T >
std::enable_if< std::is_unsigned< T >::value, int >::type constexpr signum0 ( x)
inlineconstexpr

Definition at line 162 of file functions.h.

162 {
163 return T(0) <= x;
164}

◆ signum0() [2/2]

template<typename T >
std::enable_if< std::is_signed< T >::value, int >::type constexpr signum0 ( x)
inlineconstexpr

Definition at line 167 of file functions.h.

167 {
168 return (T(0) <= x) - (x < T(0));
169}

◆ tokenize()

template<class ContainerT >
void tokenize ( const std::string &  str,
ContainerT &  tokens,
const std::string &  delimiters = " ",
MBool  trimEmpty = false 
)
inline

Definition at line 439 of file functions.h.

440 {
441 std::string::size_type pos = 0;
442 std::string::size_type lastPos = 0;
443 std::string::size_type length = str.length();
444
445 using value_type = typename ContainerT::value_type;
446 using size_type = typename ContainerT::size_type;
447
448 while(lastPos < length + 1) {
449 pos = str.find_first_of(delimiters, lastPos);
450 if(pos == std::string::npos) {
451 pos = length;
452 }
453
454 if(pos != lastPos || !trimEmpty) {
455 tokens.push_back(value_type(str.data() + lastPos, (size_type)pos - lastPos));
456 }
457
458 lastPos = pos + 1;
459 }
460}

◆ wallTime()

MFloat wallTime ( )
inline

Definition at line 80 of file functions.h.

80{ return MPI_Wtime(); }

◆ writeMemoryStatistics()

void writeMemoryStatistics ( const MPI_Comm  comm,
const MInt  noDomains,
const MInt  domainId,
const MString  at,
const MString  comment = "" 
)

Definition at line 218 of file functions.cpp.

219 {
220 // Static members to compute difference to last memory evaluation
221 static MLong virtMemLast = 0;
222 static MLong physMemLast = 0;
223 // OBTAIN MEMORY USAGE
224 MLong virtMem = 0;
225 MLong physMem = 0;
226 MLong stackMem = 0;
227 MLong physMemFree = 0;
228 MLong memAvailable = 0;
229
230 {
231 // Create error flags
232 MInt fileNotFound = 0;
233 MInt memoryNotFound = 0;
234
235 // Open status file of the process
236 std::ifstream fin;
237 fin.open("/proc/self/status");
238 // Modify flag if file is not found
239 if(!fin) {
240 fileNotFound = 1;
241 }
242
243 MString line;
244 MString name;
245 MLong buffer;
246 std::istringstream iss;
247 std::array<MInt, 5> foundInfo;
248 foundInfo.fill(false);
249
250 // Read all lines and get memory usage/allocation size for this process
251 while(getline(fin, line)) {
252 buffer = 0;
253 iss.str(line);
254 iss.clear();
255 getline(iss, name, ':');
256 if(name == "VmRSS") { // Physical memory currently used by current process
257 iss >> buffer;
258 physMem = buffer;
259 foundInfo[0] = true;
260 } else if(name == "VmData") { // Allocated memory size on heap
261 iss >> buffer;
262 virtMem += buffer;
263 foundInfo[1] = true;
264 } else if(name == "VmStk") { // Allocated memory size on stack
265 iss >> buffer;
266 virtMem += buffer;
267 stackMem = buffer;
268 foundInfo[2] = true;
269 }
270 }
271 fin.close();
272
273 // Open meminfo file on current node to determine total free/available memory per node
274 fin.open("/proc/meminfo");
275 if(!fin) {
276 fileNotFound = 1;
277 }
278
279 while(getline(fin, line)) {
280 buffer = 0;
281 iss.str(line);
282 iss.clear();
283 getline(iss, name, ':');
284 if(name == "MemFree") {
285 iss >> buffer;
286 physMemFree = buffer;
287 foundInfo[3] = true;
288 } else if(name == "MemAvailable") {
289 iss >> buffer;
290 memAvailable = buffer;
291 foundInfo[4] = true;
292 }
293 }
294 fin.close();
295
296 // Set flag if any memory usage couldn't be gathered from file
297 memoryNotFound = std::any_of(foundInfo.begin(), foundInfo.end(), [](MBool i) { return !i; });
298
299 // Allreduce flags, only proceed if there was no error
300 MPI_Allreduce(MPI_IN_PLACE, &fileNotFound, 1, MPI_INT, MPI_MAX, comm, AT_, "MPI_IN_PLACE", "&fileNotFound");
301 MPI_Allreduce(MPI_IN_PLACE, &memoryNotFound, 1, MPI_INT, MPI_MAX, comm, AT_, "MPI_IN_PLACE", "&memoryNotFound");
302 MPI_Allreduce(MPI_IN_PLACE, &foundInfo[0], 5, MPI_INT, MPI_MAX, comm, AT_, "MPI_IN_PLACE", "&foundInfo");
303
304 if(fileNotFound || memoryNotFound) {
305 // Throw error and return from function if file or memory couldn't be accessed
306 if(domainId == 0) {
307 std::stringstream ss;
308 ss << "Error in writeMemoryStatistics: Could not determine memory statistics! " << fileNotFound << " "
309 << memoryNotFound << " (";
310 for(MInt i = 0; i < 5; i++) {
311 ss << " " << foundInfo[i];
312 }
313 ss << ")" << std::endl;
314 std::cerr << ss.str();
315 m_log << ss.str();
316 }
317 return;
318 }
319 }
320
321 MLongScratchSpace physMemPerProcess(noDomains, AT_, "physMemPerProcess");
322 MLongScratchSpace virtMemPerProcess(noDomains, AT_, "virtMemPerProcess");
323
324 // Gather memory from each process
325 MPI_Gather(&physMem, 1, MPI_LONG, physMemPerProcess.getPointer(), 1, MPI_LONG, 0, comm, AT_, "physMem",
326 "physMemPerProcess.getPointer()");
327 MPI_Gather(&virtMem, 1, MPI_LONG, virtMemPerProcess.getPointer(), 1, MPI_LONG, 0, comm, AT_, "virtMem",
328 "virtMemPerProcess.getPointer()");
329
330 MLongScratchSpace physMemDiffPerProcess(noDomains, AT_, "physMemDiffPerProcess");
331 MLongScratchSpace virtMemDiffPerProcess(noDomains, AT_, "virtMemDiffPerProcess");
332
333 MLong physMemDiff = physMem - physMemLast;
334 MLong virtMemDiff = virtMem - virtMemLast;
335 // Gather difference in allocated memory from each process
336 MPI_Gather(&physMemDiff, 1, MPI_LONG, physMemDiffPerProcess.getPointer(), 1, MPI_LONG, 0, comm, AT_, "physMem",
337 "physMemDiffPerProcess.getPointer()");
338 MPI_Gather(&virtMemDiff, 1, MPI_LONG, virtMemDiffPerProcess.getPointer(), 1, MPI_LONG, 0, comm, AT_, "virtMem",
339 "virtMemDiffPerProcess.getPointer()");
340
341 // Store current values for next evaluation
342 physMemLast = physMem;
343 virtMemLast = virtMem;
344
345 // Gather stack memory usage
346 MLongScratchSpace stackMemPerProcess(noDomains, AT_, "stackMemPerProcess");
347 MPI_Gather(&stackMem, 1, MPI_LONG, stackMemPerProcess.getPointer(), 1, MPI_LONG, 0, comm, AT_, "stackMem",
348 "stackMemPerProcess.getPointer()");
349
350 // Compute minimum free/available memory
351 MLong minPhysMemFree = physMemFree;
352 MPI_Allreduce(MPI_IN_PLACE, &minPhysMemFree, 1, MPI_LONG, MPI_MIN, comm, AT_, "MPI_IN_PLACE", "&minPhysMemFree");
353 MLong minMemAvailable = memAvailable;
354 MPI_Allreduce(MPI_IN_PLACE, &minMemAvailable, 1, MPI_LONG, MPI_MIN, comm, AT_, "MPI_IN_PLACE", "&minMemAvailable");
355
356 // Determine global memory statistics
357 if(domainId == 0) {
358 MLong totalPhysMem = 0;
359 MLong totalVirtMem = 0;
360 MLong totalPhysMemDiffSum = 0;
361 MLong totalVirtMemDiffSum = 0;
362 MLong totalPhysMemDiffMax = 0;
363 MLong totalVirtMemDiffMax = 0;
364 MLong maxStackMem = 0;
365
366 for(MInt i = 0; i < noDomains; i++) {
367 // Total allocation size
368 totalPhysMem += physMemPerProcess[i];
369 totalVirtMem += virtMemPerProcess[i];
370 // Total difference in allocation size compared to the last evaluation
371 totalPhysMemDiffSum += physMemDiffPerProcess[i];
372 totalVirtMemDiffSum += virtMemDiffPerProcess[i];
373 // Maximum difference in allocation size over all processes
374 totalPhysMemDiffMax = std::max(physMemDiffPerProcess[i], totalPhysMemDiffMax);
375 totalVirtMemDiffMax = std::max(virtMemDiffPerProcess[i], totalVirtMemDiffMax);
376 // Maximum stack memory usage
377 maxStackMem = std::max(stackMemPerProcess[i], maxStackMem);
378 }
379
380 // Get maximum size of the process stack (this assumes it is the same on all ranks)
381 rlimit rlim;
382 getrlimit(RLIMIT_STACK, &rlim);
383 // Define rlimit as an unsigned long (same as it's defined in the kernel)
384 const MUlong rlim_stack = rlim.rlim_cur;
385 // Note: issue warning if stack usage is quite high (compared to stack size limit)
386 if(maxStackMem > 0.5 * rlim_stack) {
387 std::stringstream warning;
388 warning << std::endl
389 << "WARNING: maximum stack memory usage >50% of its limit, use 'ulimit -s unlimited' to remove this "
390 "memory restriction and avoid segmentation faults if the stack memory usage exceeds its limit."
391 << std::endl;
392 warning << "WARNING: stack memory usage " << (MFloat)maxStackMem << " KB; stack limit "
393 << (MFloat)rlim_stack / 1024 << " KB" << std::endl
394 << std::endl;
395 m_log << warning.str();
396 std::cerr << warning.str();
397 }
398
399 // Write memory statistics
400#ifndef NDEBUG
401 // Memory per process
402 for(MInt i = 0; i < noDomains; i++) {
403 m_log << " Process " << i << " - Current memory usage: physical = " << (MFloat)physMemPerProcess[i] / 1024
404 << " MB; allocation = " << (MFloat)virtMemPerProcess[i] / 1024 << " MB" << std::endl;
405 }
406#endif
407
408 std::stringstream ss;
409 ss << std::endl;
410 ss << "******************************* MEMORY STATISTICS *******************************" << std::endl;
411 ss << "***** Comment: " << comment << " - #ranks: " << noDomains << std::endl;
412 ss << "***** Location: " << at << std::endl;
413 ss << "***** " << std::endl;
414 // Average memory
415 ss << "***** Average memory usage: physical = " << (MFloat)totalPhysMem / (noDomains * 1024)
416 << " MB; allocation = " << (MFloat)totalVirtMem / (noDomains * 1024) << " MB\n";
417
418 // Min/Max memory
419 ss << "***** Minimun memory usage: physical = "
420 << (MFloat)*std::min_element(physMemPerProcess.begin(), physMemPerProcess.end()) / 1024
421 << " MB; allocation = " << (MFloat)*std::min_element(virtMemPerProcess.begin(), virtMemPerProcess.end()) / 1024
422 << " MB\n";
423 ss << "***** Maximum memory usage: physical = "
424 << (MFloat)*std::max_element(physMemPerProcess.begin(), physMemPerProcess.end()) / 1024
425 << " MB; allocation = " << (MFloat)*std::max_element(virtMemPerProcess.begin(), virtMemPerProcess.end()) / 1024
426 << " MB\n";
427 ss << "***** Maximum diff in memory usage: physical = " << (MFloat)totalPhysMemDiffMax / 1024
428 << " MB; allocation = " << (MFloat)totalVirtMemDiffMax / 1024 << " MB\n";
429
430 // Total memory
431 ss << "***** Total physical memory usage (RAM): " << (MFloat)totalPhysMem / (1024 * 1024) << " GB\n";
432 ss << "***** Diff total physical memory usage (RAM): " << (MFloat)totalPhysMemDiffSum / (1024 * 1024) << " GB\n";
433 ss << "***** Total allocation size (Virtual Memory): " << (MFloat)totalVirtMem / (1024 * 1024) << " GB"
434 << std::endl;
435 ss << "***** Diff total allocation size (Virtual Memory): " << (MFloat)totalVirtMemDiffSum / (1024 * 1024) << " GB"
436 << std::endl;
437 ss << "***** " << std::endl;
438 ss << "***** Maximum stack memory: " << (MFloat)maxStackMem << " KB; stack limit " << (MFloat)rlim_stack / 1024
439 << " KB" << std::endl;
440 ss << "***** " << std::endl;
441 ss << "***** Minimum available memory per node (meminfo): " << (MFloat)minMemAvailable / (1024 * 1024) << " GB"
442 << std::endl;
443 ss << "***** Minimum free memory per node (RAM): " << (MFloat)minPhysMemFree / (1024 * 1024) << " GB" << std::endl;
444 ss << "******************************* MEMORY STATISTICS *******************************" << std::endl << std::endl;
445
446 std::cout << ss.str() << std::endl;
447 m_log << ss.str() << std::endl;
448 }
449}
This class is a ScratchSpace.
Definition: scratch.h:758
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
uint64_t MUlong
Definition: maiatypes.h:65
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather

Variable Documentation

◆ location

const MString& location

Definition at line 37 of file functions.h.

◆ message

const MString const MString& message = "")

Definition at line 37 of file functions.h.