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.h
31  *
32  * Copyright(c) Emanuel Rubensson 2006
33  *
34  * @author Emanuel Rubensson  @a responsible @a author
35  * @date October 2006
36  *
37  */
38 #ifndef MAT_MATINCLUDE
39 #define MAT_MATINCLUDE
40 #include <iostream>
41 #include <vector>
42 #include <fstream>
43 #include <ios>
44 #include <cassert>
45 #include <ctime>
46 #include <limits>
47 #include <stdexcept>
48 
49 #ifdef _OPENMP
50 #include <omp.h>
51 #endif
52 
53 /* We need to include config.h to get the PRECISION_QUAD_FLT128 and USE_SSE_INTRINSICS flags. */
54 #include "config.h"
55 
56 #include "template_blas_num_limits.h"
57 
58 #include "Failure.h"
59 #include "DebugPolicies.h"
60 #include "SizesAndBlocks.h"
61 #include "Memory_buffer_thread.h"
62 
63 #ifdef _OPENMP
64 #define MAT_OMP_INIT enum omp_failType {noFail = 0, standardFail, runtimeFail, matFail}; \
65   volatile omp_failType omp_fail = noFail;				\
66   std::exception omp_exce;						\
67   std::runtime_error omp_runtime("");					\
68   Failure omp_matFail;							\
69   omp_set_nested(true);
70 // if (omp_fail == noFail) {
71 #define MAT_OMP_START try {
72 #define MAT_OMP_END }						\
73   catch(Failure & omp_fail_caught) {				\
74     omp_fail = matFail;       omp_matFail = omp_fail_caught; }	\
75   catch(std::runtime_error & omp_runtime_caught) {		\
76     omp_fail = runtimeFail;  omp_runtime = omp_runtime_caught; } \
77   catch(std::exception & omp_exce_caught) {			\
78     omp_fail = standardFail;  omp_exce = omp_exce_caught; \
79 }
80 #define MAT_OMP_FINALIZE if(omp_fail)					\
81     { std::cerr<<"Exception was thrown in OpenMP parallel region\n";	\
82       switch (omp_fail) {						\
83       case standardFail: throw omp_exce; break;				\
84       case  runtimeFail: throw omp_runtime; break;			\
85       case      matFail: throw omp_matFail; break;			\
86       default: throw Failure("Odd error in omp parallel loop\n");}	\
87     }
88 #else
89 #define MAT_OMP_INIT
90 #define MAT_OMP_START
91 #define MAT_OMP_END
92 #define MAT_OMP_FINALIZE
93 #endif
94 
95 namespace mat{
96   class Params {
97   protected:
98 #ifdef _OPENMP
99     static unsigned int nProcs;
100     static unsigned int matrixParallelLevel;
101 #endif
102   public:
getNProcs()103     static unsigned int getNProcs() {
104 #ifdef _OPENMP
105       if (nProcs == 0)
106 	throw Failure("mat::Params::getNProcs(): nProcs == 0 Forgot to call setNProcs()?");
107       return nProcs;
108 #else
109       return 1;
110 #endif
111     }
setNProcs(unsigned int const nP)112     static void setNProcs(unsigned int const nP) {
113 #ifdef _OPENMP
114       nProcs = nP;
115 #ifdef USE_SSE_INTRINSICS
116       Memory_buffer_thread::instance().init_buffers(nProcs);
117 #endif
118 #endif
119     }
getMatrixParallelLevel()120     static unsigned int getMatrixParallelLevel() {
121 #ifdef _OPENMP
122       if (matrixParallelLevel == 0)
123 	throw Failure("mat::Params::getMatrixParallelLevel(): matrixParallelLevel == 0 Forgot to call setMatrixParallelLevel()?");
124       return matrixParallelLevel;
125 #else
126       return 0;
127 #endif
128     }
setMatrixParallelLevel(unsigned int const mPL)129     static void setMatrixParallelLevel(unsigned int const mPL) {
130 #ifdef _OPENMP
131       matrixParallelLevel = mPL;
132 #endif
133     }
134   };
135 
136 
137 
138   enum property {zero, ful};
139   enum normType {frobNorm, euclNorm, mixedNorm};
140   normType getNormType(const char* normStr);
141   std::string getNormTypeString(normType nType);
142 
143   /* getMachineEpsilon(): function for getting the machine epsilon (the
144      difference between 1 and the least value greater than 1 that is
145      representable) for the given floating-point type.  */
146   template<typename Treal>
getMachineEpsilon()147     inline static Treal getMachineEpsilon() {
148     return template_blas_get_machine_epsilon<Treal>();
149   }
150 
151   template<typename Treal>
getRelPrecision()152     inline static Treal getRelPrecision() {
153     return getMachineEpsilon<Treal>();
154   }
155 
156   class Time {
157     static double get_wall_seconds();
158     double ticTime;
159   public:
160     Time();
161     void tic();
162     float toc();
163   };
164 
165   class MemUsage {
166   private:
167     static int getNumberFromBuffer(const char* buffer, const char* s);
168   public:
169     struct Values {
170       float res;
171       float virt;
172       float peak;
ValuesValues173       Values() : res(0), virt(0), peak(0) { }
174     };
175     static void getMemUsage(Values & values);
176   };
177 
178 } /* end namespace mat */
179 #endif
180