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 SCF_statistics.cc
31
32 @brief Class for keeping timings and other statistics related to
33 self-consistent field (SCF) procedure.
34
35 @author: Emanuel Rubensson <em>responsible</em>.
36 */
37
38 #include <stdexcept>
39 #include <fstream>
40 #include "SCF_statistics.h"
41
SCF_timer()42 SCF_timer::SCF_timer()
43 : stopped_already(false) {
44 startTimeWall = Util::TimeMeter::get_wall_seconds();
45 Util::TimeMeter::get_current_cpu_times(startTimeCPU_usr, startTimeCPU_sys);
46 }
47
stop()48 void SCF_timer::stop() {
49 if (stopped_already)
50 throw std::runtime_error("Attempt to stop timer already stopped.");
51 elapsedTimeWall = Util::TimeMeter::get_wall_seconds() - startTimeWall;
52 double stopTimeCPU_sys, stopTimeCPU_usr;
53 Util::TimeMeter::get_current_cpu_times(stopTimeCPU_usr, stopTimeCPU_sys);
54 elapsedTimeCPU_sys = stopTimeCPU_sys - startTimeCPU_sys;
55 elapsedTimeCPU_usr = stopTimeCPU_usr - startTimeCPU_usr;
56 stopped_already = true;
57 }
58
start_timer(std::string identifier)59 void SCF_statistics::start_timer(std::string identifier) {
60 timers[identifier] = SCF_timer();
61 }
stop_timer(std::string identifier)62 void SCF_statistics::stop_timer(std::string identifier) {
63 if ( timers.find(identifier) == timers.end() )
64 throw std::runtime_error("Attempt to stop timer not in timer map.");
65 timers[identifier].stop();
66 }
67
add_value(std::string identifier,double value)68 void SCF_statistics::add_value(std::string identifier, double value) {
69 if ( values.find(identifier) != values.end() )
70 throw std::runtime_error("Attempt to add value already in value map.");
71 values[identifier] = value;
72 }
73
add_values(ValueMap & values_to_add)74 void SCF_statistics::add_values( ValueMap & values_to_add) {
75 ValueMap::const_iterator it;
76 for ( it=values_to_add.begin() ; it != values_to_add.end(); it++ )
77 values[it->first] = it->second;
78 }
79
80
output_mfile(std::string name)81 void SCF_statistics::output_mfile(std::string name) {
82 std::string m_name = name + ".m";
83 std::ofstream os(m_name.c_str());
84
85 // First output the names of all variables as one big comment
86 os << "%% SCF_statistics, list of all variables " << std::endl;
87 {
88 os << "%% Timers: " << std::endl;
89 TimerMap::const_iterator it;
90 for ( it=timers.begin() ; it != timers.end(); it++ ) {
91 std::string s = (*it).first;
92 std::string s_wall = s + "_walltime";
93 std::string s_cpu_sys = s + "_cpu_sys";
94 std::string s_cpu_usr = s + "_cpu_usr";
95 os << "% " << s_wall << std::endl;
96 os << "% " << s_cpu_sys << std::endl;
97 os << "% " << s_cpu_usr << std::endl;
98 }
99 }
100 {
101 os << "%% Other values: " << std::endl;
102 ValueMap::const_iterator it;
103 for ( it=values.begin() ; it != values.end(); it++ ) {
104 std::string s = (*it).first;
105 os << "% " << s << std::endl;
106 }
107 }
108 os << "%" << std::endl << std::endl;
109
110 // Now output the values
111 os << "%% SCF_statistics timers " << std::endl;
112 {
113 TimerMap::const_iterator it;
114 for ( it=timers.begin() ; it != timers.end(); it++ ) {
115 std::string s = (*it).first;
116 std::string s_wall = s + "_walltime";
117 std::string s_cpu_sys = s + "_cpu_sys";
118 std::string s_cpu_usr = s + "_cpu_usr";
119 double time_cpu_sys = (*it).second.elapsedTimeCPU_sys;
120 double time_cpu_usr = (*it).second.elapsedTimeCPU_usr;
121 double time_wall = (*it).second.elapsedTimeWall;
122 output_value( os, s_wall , time_wall );
123 output_value( os, s_cpu_sys, time_cpu_sys );
124 output_value( os, s_cpu_usr, time_cpu_usr );
125 }
126 }
127 os << "%% SCF_statistics other values " << std::endl;
128 {
129 ValueMap::const_iterator it;
130 for ( it=values.begin() ; it != values.end(); it++ ) {
131 std::string s = (*it).first;
132 double value = (*it).second;
133 output_value( os, s, value );
134 }
135 }
136 }
137
output_value(std::ofstream & os,std::string id,double value)138 void SCF_statistics::output_value( std::ofstream & os,
139 std::string id,
140 double value ) {
141 os << "if ( ~exist( '" << id << "' ) )" << std::endl;
142 os << " " << id << " = [];" << std::endl;
143 os << "end" << std::endl;
144 os << id << " = [" << id << " " << value << "];"
145 << std::endl;
146 }
147