Phoebe developer's documentation  1.1.0
Phonon and Electron Boltzmann Equations
SMatrix.h
1 #ifndef S_MATRIX_H
2 #define S_MATRIX_H
3 
4 #include <tuple>
5 #include <vector>
6 
7 #include "Blas.h"
8 #include "exceptions.h"
9 
19 template <typename T>
20 class SerialMatrix {
22  int numRows_;
23  int numCols_;
24  size_t numElements_;
25 
26  T* mat = nullptr; // pointer to the internal array structure.
27 
29  std::tuple<int, int> local2Global(const int& k);
30 
31  public:
32  int global2Local(const int& row, const int& col);
33 
36  static const char transN = 'N';
39  static const char transT = 'T';
42  static const char transC = 'C';
43 
52  SerialMatrix(const int& numRows, const int& numCols,
53  const int& numBlasRows = 0, const int& numBlasCols = 0,
54  const int& numBlocksRows = 0, const int& numBlocksCols = 0);
55 
59 
63 
67 
71 
75  std::vector<std::tuple<int, int>> getAllLocalStates();
76 
80  bool indicesAreLocal(const int& row, const int& col);
81 
84  int rows() const;
87  int localRows() const;
90  int cols() const;
93  int localCols() const;
96  size_t size() const;
99  T& operator()(const int &row, const int &col);
102  const T& operator()(const int &row, const int &col) const;
103 
109 
114  void outputToHDF5(const std::string &outFileName,
115  const std::string &dataSetName) {}
116 
128  SerialMatrix<T> prod(const SerialMatrix<T>& that, const char& trans1 = transN,
129  const char& trans2 = transN);
130 
134  if(numRows_ != m1.rows() || numCols_ != m1.cols()) {
135  Error("Cannot add matrices of different sizes.");
136  }
137  for (size_t s = 0; s < size(); s++) mat[s] += m1.mat[s];
138  return *this;
139  }
140 
144  if(numRows_ != m1.rows() || numCols_ != m1.cols()) {
145  Error("Cannot subtract matrices of different sizes.");
146  }
147  for (size_t s = 0; s < size(); s++) mat[s] -= m1.mat[s];
148  return *this;
149  }
150 
153  SerialMatrix<T> operator*=(const T& that) {
154  for (size_t s = 0; s < size(); s++) mat[s] *= that;
155  return *this;
156  }
157 
160  SerialMatrix<T> operator/=(const T& that) {
161  for (size_t s = 0; s < size(); s++) mat[s] /= that;
162  return *this;
163  }
164 
168  void eye();
169 
173  std::tuple<std::vector<double>, SerialMatrix<T>> diagonalize();
174 
179  std::tuple<std::vector<double>, SerialMatrix<T>> diagonalize(int numEigenvalues,
180  bool checkNegativeEigenvalues = true);
181 
185  double squaredNorm();
186 
190  double norm();
191 
196  T dot(const SerialMatrix<T>& that);
197 
201 
203  void symmetrize();
204 
205 };
206 
207 // A default constructor to build a dense matrix of zeros to be filled
208 template <typename T>
209 SerialMatrix<T>::SerialMatrix(const int& numRows, const int& numCols,
210  const int& numBlasRows, const int& numBlasCols,
211  const int& numBlocksRows, const int& numBlocksCols) {
212  // these are used only the in the pmatrix case
213  (void) numBlocksRows;
214  (void) numBlocksCols;
215  (void) numBlasRows;
216  (void) numBlasCols;
217 
218  numRows_ = numRows;
219  numCols_ = numCols;
220  numElements_ = numRows_ * numCols_;
221  mat = new T[numRows_ * numCols_];
222  for (size_t i = 0; i < numElements_; i++) mat[i] = 0; // fill with zeroes
223  assert(mat != nullptr); // Memory could not be allocated, end program
224 }
225 
226 // default constructor
227 template <typename T>
229  mat = nullptr;
230  numRows_ = 0;
231  numCols_ = 0;
232  numElements_ = 0;
233 }
234 
235 // copy constructor
236 template <typename T>
238  numRows_ = that.numRows_;
239  numCols_ = that.numCols_;
240  numElements_ = that.numElements_;
241  if (mat != nullptr) {
242  delete[] mat;
243  mat = nullptr;
244  }
245  mat = new T[numElements_];
246  assert(mat != nullptr);
247  for (size_t i = 0; i < numElements_; i++) {
248  mat[i] = that.mat[i];
249  }
250 }
251 
252 template <typename T>
254  if (this != &that) {
255  numRows_ = that.numRows_;
256  numCols_ = that.numCols_;
257  numElements_ = that.numElements_;
258  // matrix allocation
259  if (mat != nullptr) {
260  delete[] mat;
261  }
262  mat = new T[numElements_];
263  assert(mat != nullptr);
264  for (size_t i = 0; i < numElements_; i++) {
265  mat[i] = that.mat[i];
266  }
267  }
268  return *this;
269 }
270 
271 // destructor
272 template <typename T>
274  if (mat != nullptr) delete[] mat;
275 }
276 
277 /* ------------- Very basic operations -------------- */
278 template <typename T>
280  return numRows_;
281 }
282 template <typename T>
284  return numRows_;
285 }
286 template <typename T>
288  return numCols_;
289 }
290 template <typename T>
292  return numCols_;
293 }
294 template <typename T>
295 size_t SerialMatrix<T>::size() const {
296  return numElements_;
297 }
298 
299 // Get/set element
300 template <typename T>
301 T& SerialMatrix<T>::operator()(const int &row, const int &col) {
302  if(row >= numRows_ || col >= numCols_ || row < 0 || col < 0) {
303  DeveloperError("Tried to reference a SMatrix state out of bounds: "
304  + std::to_string(row) + " " + std::to_string(col));
305  }
306  return mat[global2Local(row, col)];
307 }
308 
309 template <typename T>
310 const T& SerialMatrix<T>::operator()(const int &row, const int &col) const {
311  if(row >= numRows_ || col >= numCols_ || row < 0 || col < 0) {
312  DeveloperError("Tried to reference a SMatrix state out of bounds: "
313  + std::to_string(row) + " " + std::to_string(col));
314  }
315  return mat[global2Local(row, col)];
316 }
317 
318 template <typename T>
319 bool SerialMatrix<T>::indicesAreLocal(const int& row, const int& col) {
320  if(row >= numRows_ || col >= numCols_ || row < 0 || col < 0) {
321  DeveloperError("indicesAreLocal tried to reference a SMatrix state out of bounds: "
322  + std::to_string(row) + " " + std::to_string(col));
323  }
324  return true;
325 }
326 
327 template <typename T>
328 std::tuple<int, int> SerialMatrix<T>::local2Global(const int& k) {
329  // we convert this combined local index k into row / col indices
330  // k = j * nRows + i
331  if(numRows_ == 0) Error("attempted to div by zero in l2g");
332  int j = k / numRows_;
333  int i = k - j * numRows_;
334  return std::make_tuple(i, j);
335 }
336 
337 // Indexing to set up the matrix in col major format
338 template <typename T>
339 int SerialMatrix<T>::global2Local(const int& row, const int& col) {
340  return numRows_ * col + row;
341 }
342 
343 template <typename T>
344 std::vector<std::tuple<int, int>> SerialMatrix<T>::getAllLocalStates() {
345  std::vector<std::tuple<int, int>> x;
346  for (size_t k = 0; k < numElements_; k++) {
347  std::tuple<int, int> t = local2Global(k); // bloch indices
348  x.push_back(t);
349  }
350  return x;
351 }
352 
353 // General unary negation
354 template <typename T>
356  SerialMatrix<T> ret(numRows_, numCols_);
357  for (int row = 0; row < numRows_; row++) {
358  for (int col = 0; col < numCols_; col++) ret(row, col) = -(*this)(row, col);
359  }
360  return ret;
361 }
362 
363 // Sets the matrix to the identity matrix
364 template <typename T>
366  if(numRows_ != numCols_) {
367  Error("Cannot build an identity matrix with non-square matrix");
368  }
369  for (int row = 0; row < numRows_; row++) (*this)(row, row) = (T)1.0;
370 }
371 
372 // forward declaration of explicit specialization
373 // is needed because the generic implementation does not
374 // work for complex types
375 template<> double SerialMatrix<std::complex<double>>::norm();
376 
377 template <typename T>
379  T sumSq = 0;
380  for (int row = 0; row < numRows_; row++) {
381  for (int col = 0; col < numCols_; col++) {
382  sumSq += ((*this)(row, col) * (*this)(row, col));
383  }
384  }
385  return sqrt(sumSq);
386 }
387 
388 template <typename T>
390  double x = norm();
391  return x * x;
392 }
393 
394 template <typename T>
396  T scalar = (T)0.;
397  for (size_t i = 0; i < numElements_; i++) {
398  scalar += (*(mat + i)) * (*(that.mat + i));
399  }
400  return scalar;
401 }
402 
403 #endif // S_MATRIX_H
Header file for forward declaration of BLAS and LAPACK functions.
Object used to print an error message for developers, and stop the code.
Definition: exceptions.h:21
Object used to print an error message, and stop the code.
Definition: exceptions.h:10
Class for managing a (serial) matrix stored in memory.
Definition: SMatrix.h:20
std::tuple< std::vector< double >, SerialMatrix< T > > diagonalize()
Diagonalize a complex-hermitian / real-symmetric matrix.
SerialMatrix< T > operator/=(const T &that)
Matrix-scalar division.
Definition: SMatrix.h:160
~SerialMatrix()
Destructor, to delete raw buffer.
Definition: SMatrix.h:273
void symmetrize()
Symmetrize the matrix.
size_t size() const
Find global number of matrix elements.
Definition: SMatrix.h:295
SerialMatrix()
Default constructor.
Definition: SMatrix.h:228
SerialMatrix< T > & operator=(const SerialMatrix< T > &that)
Copy constructor.
Definition: SMatrix.h:253
SerialMatrix(const SerialMatrix< T > &that)
Copy constructor.
Definition: SMatrix.h:237
const T & operator()(const int &row, const int &col) const
Const get and set operator.
Definition: SMatrix.h:310
int localRows() const
Return local number of rows.
Definition: SMatrix.h:283
std::tuple< std::vector< double >, SerialMatrix< T > > diagonalize(int numEigenvalues, bool checkNegativeEigenvalues=true)
Diagonalize a complex-hermitian / real sym matrix for only some of its eigenvalues.
std::vector< std::tuple< int, int > > getAllLocalStates()
Find the global indices of the matrix elements that are stored locally by the current MPI process.
Definition: SMatrix.h:344
SerialMatrix(const int &numRows, const int &numCols, const int &numBlasRows=0, const int &numBlasCols=0, const int &numBlocksRows=0, const int &numBlocksCols=0)
Default SMatrix constructor.
Definition: SMatrix.h:209
void outputToHDF5(const std::string &outFileName, const std::string &dataSetName)
A dummy function not implemented, only for PMatrix currently.
Definition: SMatrix.h:114
static const char transC
Indicates that the matrix A is taken as its adjoint: transC(A) = A^+.
Definition: SMatrix.h:42
void enforcePositiveSemiDefinite()
A function to fix up a matrix with a bit of noise to be positive semi-definite, which currently does ...
Definition: SMatrix.h:108
double norm()
Computes the Frobenius norm of the matrix (or Euclidean norm, or L2 norm of the matrix).
Definition: SMatrix.h:378
void eye()
Sets this matrix as the identity.
Definition: SMatrix.h:365
SerialMatrix< T > operator-() const
Unary negation.
Definition: SMatrix.h:355
static const char transT
Indicates that the matrix A is taken as its transpose: transT(A) = A^T.
Definition: SMatrix.h:39
bool indicesAreLocal(const int &row, const int &col)
Returns true if the global indices (row,col) identify a matrix element stored by the MPI process.
Definition: SMatrix.h:319
double squaredNorm()
Computes the squared Frobenius norm of the matrix (or Euclidean norm, or L2 norm of the matrix)
Definition: SMatrix.h:389
T dot(const SerialMatrix< T > &that)
Computes a "scalar product" between two matrices A and B, defined as \sum_ij A_ij * B_ij.
Definition: SMatrix.h:395
int rows() const
Find global number of rows.
Definition: SMatrix.h:279
T & operator()(const int &row, const int &col)
Get and set operator.
Definition: SMatrix.h:301
int localCols() const
Return local number of rows.
Definition: SMatrix.h:291
SerialMatrix< T > operator-=(const SerialMatrix< T > &m1)
Matrix-matrix subtraction.
Definition: SMatrix.h:143
SerialMatrix< T > operator+=(const SerialMatrix< T > &m1)
Matrix-matrix addition.
Definition: SMatrix.h:133
SerialMatrix< T > operator*=(const T &that)
Matrix-scalar multiplication.
Definition: SMatrix.h:153
SerialMatrix< T > prod(const SerialMatrix< T > &that, const char &trans1=transN, const char &trans2=transN)
Matrix-matrix multiplication.
static const char transN
Indicates that the matrix A is not modified: transN(A) = A.
Definition: SMatrix.h:36
int cols() const
Find global number of columns.
Definition: SMatrix.h:287