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 output.cc
31 
32     @brief Functionality for writing output messages to a text file.
33 
34     @author: Elias Rudberg <em>responsible</em>
35 */
36 
37 #include <time.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include "output.h"
42 #include "utilities.h"
43 
44 static int global_memory_usage_output_flag = 0; /* mem output disabled by default */
45 
46 /* We choose to have output disabled by default, until enable_output() is called, to make sure output is disabled on worker processes when CHT is used. */
47 static int global_output_enabled_flag = 0; /* output disabled by default */
48 
49 static int use_printf = 0; /* use printf */
50 
51 /* general output routine  */
52 void
do_output(int logCategory,int logArea,const char * format,...)53 do_output(int logCategory, int logArea, const char* format, ...)
54 {
55   va_list a;
56   va_start(a, format);
57   if(use_printf)
58     do_voutput_printf(logCategory, logArea, format, a);
59   else
60     do_voutput(logCategory, logArea, format, a);
61   va_end(a);
62 }
63 
64 /* output in stdout using printf */
65 void
enable_printf_output()66 enable_printf_output()
67 {
68   global_output_enabled_flag = 1;
69   use_printf = 1;
70 
71   //global_memory_usage_output_flag = 1;
72 }
73 
74 
75 int
do_voutput_printf(int logCategory,int logArea,const char * format,va_list a)76 do_voutput_printf(int logCategory, int logArea, const char* format, va_list a)
77 {
78   if(global_output_enabled_flag == 0)
79     return 0; // Output is disabled; do nothing, just return.
80 
81   char ss[8888]; /* FIXME: Do something nicer here. */
82   int r;
83 
84   memset(ss, 0, sizeof(ss));
85   r = vsnprintf(ss, sizeof(ss), format, a);
86 
87   printf("%s\n", ss);
88 
89   return r;
90 }
91 
92 
93 int
do_voutput(int logCategory,int logArea,const char * format,va_list a)94 do_voutput(int logCategory, int logArea, const char* format, va_list a)
95 {
96   if(global_output_enabled_flag == 0)
97     return 0; // Output is disabled; do nothing, just return.
98 
99   char ss[8888]; /* FIXME: Do something nicer here. */
100   int r;
101 
102   memset(ss, 0, sizeof(ss));
103 
104   /* The output line should begin with two characters
105      specifying the log category, followed by two characters
106      specifying the log area. */
107   switch(logCategory)
108     {
109     case LOG_CAT_UNDEFINED: strcat(ss, "  "); break;
110     case LOG_CAT_ERROR:     strcat(ss, "ER"); break;
111     case LOG_CAT_WARNING:   strcat(ss, "WA"); break;
112     case LOG_CAT_INFO:      strcat(ss, "IN"); break;
113     case LOG_CAT_EXTRAINFO: strcat(ss, "EX"); break;
114     case LOG_CAT_RESULTS:   strcat(ss, "RE"); break;
115     case LOG_CAT_TIMINGS:   strcat(ss, "TI"); break;
116     case LOG_CAT_MEMUSAGE:  strcat(ss, "ME"); break;
117     default:                strcat(ss, "  "); break;
118     }
119   switch(logArea)
120     {
121     case LOG_AREA_UNDEFINED: strcat(ss, "  "); break;
122     case LOG_AREA_MAIN:      strcat(ss, "MA"); break;
123     case LOG_AREA_SCF:       strcat(ss, "SC"); break;
124     case LOG_AREA_LR:        strcat(ss, "LR"); break;
125     case LOG_AREA_INTEGRALS: strcat(ss, "IN"); break;
126     case LOG_AREA_DENSFROMF: strcat(ss, "DE"); break;
127     case LOG_AREA_DFT      : strcat(ss, "DF"); break;
128     case LOG_AREA_LOWLEVEL:  strcat(ss, "LO"); break;
129     case LOG_AREA_CI:        strcat(ss, "CI"); break;
130     case LOG_AREA_ED:        strcat(ss, "ED"); break;
131     case LOG_AREA_GS:        strcat(ss, "GS"); break;
132     default:                 strcat(ss, "  "); break;
133     }
134 
135   strcat(ss, " ");
136 
137   r = vsnprintf(ss+5, sizeof(ss)-5, format, a);
138 
139 #if 0
140   /* This needs to be protected with mutex. */
141   if(global_output_file == NULL)
142     global_output_file = fopen("ergoscf.out", "wt");
143   fprintf(global_output_file, "%s\n", ss);
144   fflush(global_output_file);
145 #else
146   /* append to output file */
147   {
148     FILE *output_file = fopen("ergoscf.out", "at");
149     fprintf(output_file, "%s\n", ss);
150     fclose(output_file);
151   }
152 #endif
153   return r;
154 }
155 
156 
157 
158 void
do_output_time(int logCategory,int logArea,const char * s)159 do_output_time(int logCategory, int logArea, const char* s)
160 {
161   int len;
162   char timeString[88];
163   char ss[222];
164   time_t rawtime;
165   time(&rawtime);
166   strcpy(timeString, ctime(&rawtime));
167   len = (int)strlen(timeString);
168   if(timeString[len-1] == '\n')
169     timeString[len-1] = '\0';
170   sprintf(ss, "%s %s", s, timeString);
171   do_output(logCategory, logArea, ss);
172 }
173 
174 void
enable_memory_usage_output()175 enable_memory_usage_output()
176 {
177   global_memory_usage_output_flag = 1;
178 }
179 
180 void
enable_output()181 enable_output()
182 {
183   global_output_enabled_flag = 1;
184 }
185 
output_current_memory_usage(int logArea,const char * contextString)186 void output_current_memory_usage(int logArea, const char* contextString)
187 {
188   double virt, res, virtPeak;
189 
190   if(global_memory_usage_output_flag == 0)
191     return;
192 
193   if(get_memory_usage_by_procfile(&virt, &res, &virtPeak) != 0)
194     {
195       /* error getting memory usage */
196       do_output(LOG_CAT_MEMUSAGE, logArea, "memory usage at '%s': virt ???? res ???? v peak ????",
197 		contextString);
198     }
199   else
200     {
201       do_output(LOG_CAT_MEMUSAGE, logArea, "memory usage at '%s': virt %6.3f G res %6.3f G v peak %6.3f G",
202 		contextString, virt, res, virtPeak);
203     }
204 }
205 
206 
207