1 /* Ergo, version 3.8, a program for linear scaling electronic structure
2  * calculations.
3  * Copyright (C) 2019 Elias Rudberg, Emanuel H. Rubensson, Pawel Salek,
4  * and Anastasia Kruchinina.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Primary academic reference:
20  * Ergo: An open-source program for linear-scaling electronic structure
21  * calculations,
22  * Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, and Anastasia
23  * Kruchinina,
24  * SoftwareX 7, 107 (2018),
25  * <http://dx.doi.org/10.1016/j.softx.2018.03.005>
26  *
27  * For further information about Ergo, see <http://www.ergoscf.org>.
28  */
29 
30 /** @file matInclude.cc
31 
32     \brief Some utilities related to hierarchical matrix library.
33 */
34 
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <stdexcept>
39 #include <cstring>
40 #include <cstdio>
41 
42 #include "matInclude.h"
43 
44 namespace mat {
45 
46 #ifdef _OPENMP
47   unsigned int Params::nProcs = 0;
48   unsigned int Params::matrixParallelLevel = 0;
49 #endif
50 
51 
getNormType(const char * normStr)52   normType getNormType(const char* normStr) {
53     if ( strcmp(normStr, "eucl") == 0)
54       return mat::euclNorm;
55     if ( strcmp(normStr, "frob") == 0)
56       return mat::frobNorm;
57     if ( strcmp(normStr, "mixed") == 0)
58       return mat::mixedNorm;
59     throw "Error in mat::getNormType: Unknown norm type string.";
60   }
61 
getNormTypeString(normType nType)62   std::string getNormTypeString(normType nType) {
63     switch(nType) {
64     case mat::euclNorm:  return "eucl";
65     case mat::frobNorm:  return "frob";
66     case mat::mixedNorm: return "mixed";
67     }
68     throw "Error in mat::getNormTypeString: Unknown norm type.";
69   }
70 
71 
72   // Class "Time" implementation starts here!
73 
get_wall_seconds()74   double Time::get_wall_seconds() {
75     struct timeval tv;
76     if(gettimeofday(&tv, NULL) != 0)
77       throw std::runtime_error("Error in get_wall_seconds(), in gettimeofday().");
78     double seconds = tv.tv_sec + (double)tv.tv_usec / 1000000;
79     return seconds;
80   }
81 
Time()82   Time::Time():ticTime(0) { }
83 
tic()84   void Time::tic() {
85     ticTime = get_wall_seconds();
86   }
87 
toc()88   float Time::toc() {
89     double returnValue = get_wall_seconds() - ticTime;
90     return (float)returnValue;
91   }
92 
93 
94   // Class "MemUsage" implementation starts here!
95 
getNumberFromBuffer(const char * buffer,const char * s)96   int MemUsage::getNumberFromBuffer(const char* buffer, const char* s) {
97     const char* p = buffer;
98     int slen = strlen(s);
99     while(1) {
100       if(*p == '\0')
101 	return -11;
102       /*  now p points to the beginning of a new line. */
103       if(memcmp(p, s, slen) == 0)
104 	{
105 	  int number;
106 	  /*  string found! */
107 	  /*  skip until blank or tab */
108 	  while(*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
109 	    p++;
110 	  /*  skip blanks and tabs */
111 	  while(*p == ' ' || *p == '\t')
112 	    p++;
113 	  /*  get number */
114 	  number = atoi(p);
115 	  /*  skip until blank or tab */
116 	  while(*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
117 	    p++;
118 	  /*  skip blanks and tabs */
119 	  while(*p == ' ' || *p == '\t')
120 	    p++;
121 	  /*  now p should point to "kB" */
122 	  if(memcmp(p, "kB", 2) != 0)
123 	    return -22;
124 	  return number;
125 	}
126       /*  skip to next line */
127       while(*p != '\n' && *p != '\0')
128 	p++;
129       p++;
130     }
131     return -33;
132   }
133 
getMemUsage(Values & values)134   void MemUsage::getMemUsage(Values & values) {
135     char fileName[888];
136     const size_t PROCFILESIZE = 8888;
137     char buffer[PROCFILESIZE];
138     values.virt = 0;
139     values.res  = 0;
140     values.peak = 0;
141     int pid = getpid();
142     sprintf(fileName, "/proc/%i/status", pid);
143     memset(buffer, 0, PROCFILESIZE);
144     FILE* f = fopen(fileName, "rt");
145     // Elias note 2011-01-19: Earlier an exception was thown here, but now we just return with zero result, to make it work on Mac.
146     if(f == NULL)
147       return;
148     size_t noOfBytesRead = fread(buffer, 1, PROCFILESIZE, f);
149     fclose(f);
150     if(noOfBytesRead <= 0)
151       throw std::runtime_error("Error reading proc status file to get mem usage.");
152     if(noOfBytesRead >= PROCFILESIZE)
153       throw std::runtime_error("Error reading proc status file to get mem usage: (noOfBytesRead >= PROCFILESIZE).");
154     int VmSize_kB = getNumberFromBuffer(buffer, "VmSize:");
155     int VmRSS_kB  = getNumberFromBuffer(buffer, "VmRSS:");
156     int VmPeak_kB = getNumberFromBuffer(buffer, "VmPeak:");
157     if(VmSize_kB <= 0 || VmRSS_kB <= 0)
158       throw std::runtime_error("error getting VmSize_kB or VmRSS_kB.");
159     values.virt   = (float)VmSize_kB / 1000000;
160     values.res    = (float)VmRSS_kB  / 1000000;
161     if(VmPeak_kB > 0)
162       values.peak = (float)VmPeak_kB / 1000000;
163     else
164       values.peak = 0;
165   }
166 
167 } // end namespace mat
168