v2DM-DOCI  1.0
helpers.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2014 Ward Poelmans
2 
3  This file is part of Hubbard-GPU.
4 
5  Hubbard-GPU is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  Hubbard-GPU is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with Hubbard-GPU. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <iostream>
20 #include <algorithm>
21 #include <sstream>
22 #include <cstring>
23 #include <assert.h>
24 #include <hdf5.h>
25 
26 #include "lapack.h"
27 #include "helpers.h"
28 
29 // macro to help check return status of HDF5 functions
30 #define HDF5_STATUS_CHECK(status) { \
31  if(status < 0) \
32  std::cerr << __FILE__ << ":" << __LINE__ << \
33  ": Problem with writing to file. Status code=" \
34  << status << std::endl; \
35 }
36 
37 using namespace helpers;
38 
44 {
45  this->n = 0;
46  this->m = 0;
47 }
48 
53 matrix::matrix(int n_, int m_)
54 {
55  assert(n_ && m_);
56  this->n = n_;
57  this->m = m_;
58  mat.reset(new double [n*m]);
59 }
60 
64 matrix::matrix(const matrix &orig)
65 {
66  n = orig.n;
67  m = orig.m;
68  mat.reset(new double [n*m]);
69  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(double));
70 }
71 
77 {
78  n = orig.n;
79  m = orig.m;
80  mat = std::move(orig.mat);
81 }
82 
84 {
85  n = orig.n;
86  m = orig.m;
87  mat.reset(new double [n*m]);
88  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(double));
89  return *this;
90 }
91 
97 {
98  for(int i=0;i<n*m;i++)
99  mat[i] = val;
100 
101  return *this;
102 }
103 
107 int matrix::getn() const
108 {
109  return n;
110 }
111 
115 int matrix::getm() const
116 {
117  return m;
118 }
119 
120 double matrix::operator()(int x,int y) const
121 {
122  assert(x<n && y<m);
123  return mat[x+y*n];
124 }
125 
126 double& matrix::operator()(int x,int y)
127 {
128  assert(x<n && y<m);
129  return mat[x+y*n];
130 }
131 
132 double& matrix::operator[](int x)
133 {
134  assert(x<n*m);
135  return mat[x];
136 }
137 
138 double matrix::operator[](int x) const
139 {
140  assert(x<n*m);
141  return mat[x];
142 }
143 
144 double* matrix::getpointer() const
145 {
146  return mat.get();
147 }
148 
154 matrix& matrix::prod(matrix const &A, matrix const &B)
155 {
156  char trans = 'N';
157 
158  double alpha = 1.0;
159  double beta = 0.0;
160 
161  assert(A.n == n && B.m == m);
162 
163  dgemm_(&trans,&trans,&A.n,&B.m,&A.m,&alpha,A.mat.get(),&A.n,B.mat.get(),&B.n,&beta,mat.get(),&A.n);
164 
165  return *this;
166 }
167 
173 std::unique_ptr<double []> matrix::svd()
174 {
175  char jobu = 'A';
176  char jobvt = 'N';
177 
178  int count_sing = std::min(n,m);
179 
180  std::unique_ptr<double []> sing_vals(new double[count_sing]);
181 
182  // MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)).
183  int lwork = std::max( 3*count_sing + std::max(n,m), 5*count_sing);
184  std::unique_ptr<double []> work(new double[lwork]);
185 
186  std::unique_ptr<double []> vt(new double[n*n]);
187 
188  int info;
189 
190  dgesvd_(&jobu,&jobvt,&n,&m,mat.get(),&n,sing_vals.get(),vt.get(),&n,0,&m,work.get(),&lwork,&info);
191 
192  if(info)
193  std::cerr << "svd failed. info = " << info << std::endl;
194 
195  // overwrite the matrix with the right singular vectors
196  m = n;
197  mat = std::move(vt);
198 
199  return sing_vals;
200 }
201 
206 std::unique_ptr<double []> matrix::sym_eig()
207 {
208  assert(n==m);
209  std::unique_ptr<double []> eigs(new double[n]);
210 
211  char jobz = 'N';
212  char uplo = 'U';
213 
214  int lwork = 3*n - 1;
215 
216  std::unique_ptr<double []> work (new double [lwork]);
217 
218  int info = 0;
219 
220  dsyev_(&jobz,&uplo,&n,mat.get(),&n,eigs.get(),work.get(),&lwork,&info);
221 
222  if(info)
223  std::cerr << "dsyev failed. info = " << info << std::endl;
224 
225  return eigs;
226 }
227 
228 void matrix::Print() const
229 {
230  for(int i=0;i<n;i++)
231  for(int j=0;j<m;j++)
232  std::cout << i << " " << j << "\t" << (*this)(i,j) << std::endl;
233 }
234 
235 double matrix::trace() const
236 {
237  double result = 0;
238 
239  for(int i=0;i<std::min(m,n);i++)
240  result += (*this)(i,i);
241 
242  return result;
243 }
244 
245 
246 void matrix::SaveToFile(std::string filename) const
247 {
248  hid_t file_id, dataset_id, dataspace_id, attribute_id;
249  herr_t status;
250 
251  file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
252  HDF5_STATUS_CHECK(file_id);
253 
254  hsize_t dimarray = n*m;
255  dataspace_id = H5Screate_simple(1, &dimarray, NULL);
256 
257  dataset_id = H5Dcreate(file_id, "matrix", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
258 
259  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mat.get() );
260  HDF5_STATUS_CHECK(status);
261 
262  status = H5Sclose(dataspace_id);
263  HDF5_STATUS_CHECK(status);
264 
265  dataspace_id = H5Screate(H5S_SCALAR);
266 
267  attribute_id = H5Acreate (dataset_id, "n", H5T_STD_I32LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
268  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &n );
269  HDF5_STATUS_CHECK(status);
270 
271  status = H5Aclose(attribute_id);
272  HDF5_STATUS_CHECK(status);
273 
274  attribute_id = H5Acreate (dataset_id, "m", H5T_STD_I32LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
275  status = H5Awrite (attribute_id, H5T_NATIVE_INT, &m );
276  HDF5_STATUS_CHECK(status);
277 
278  status = H5Aclose(attribute_id);
279  HDF5_STATUS_CHECK(status);
280 
281  status = H5Sclose(dataspace_id);
282  HDF5_STATUS_CHECK(status);
283 
284  status = H5Dclose(dataset_id);
285  HDF5_STATUS_CHECK(status);
286 
287  status = H5Fclose(file_id);
288  HDF5_STATUS_CHECK(status);
289 }
290 
291 void matrix::ReadFromFile(std::string filename) const
292 {
293  hid_t file_id, dataset_id, attribute_id;
294  herr_t status;
295  int n_, m_;
296 
297  file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
298  HDF5_STATUS_CHECK(file_id);
299 
300  dataset_id = H5Dopen(file_id, "matrix", H5P_DEFAULT);
301  HDF5_STATUS_CHECK(dataset_id);
302 
303  attribute_id = H5Aopen(dataset_id, "n", H5P_DEFAULT);
304  HDF5_STATUS_CHECK(attribute_id);
305 
306  status = H5Aread(attribute_id, H5T_NATIVE_INT, &n_);
307  HDF5_STATUS_CHECK(status);
308 
309  status = H5Aclose(attribute_id);
310  HDF5_STATUS_CHECK(status);
311 
312  attribute_id = H5Aopen(dataset_id, "m", H5P_DEFAULT);
313  HDF5_STATUS_CHECK(attribute_id);
314 
315  status = H5Aread(attribute_id, H5T_NATIVE_INT, &m_);
316  HDF5_STATUS_CHECK(status);
317 
318  status = H5Aclose(attribute_id);
319  HDF5_STATUS_CHECK(status);
320 
321  if(n!=n_ || m!=m_)
322  std::cerr << "Matrix size not compatable with file: " << n_ << "x" << m_ << std::endl;
323  else
324  {
325  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mat.get());
326  HDF5_STATUS_CHECK(status);
327  }
328 
329  status = H5Dclose(dataset_id);
330  HDF5_STATUS_CHECK(status);
331 
332  status = H5Fclose(file_id);
333  HDF5_STATUS_CHECK(status);
334 }
335 
341 {
342  this->n = 0;
343  this->m = 0;
344 }
345 
350 cmatrix::cmatrix(int n_, int m_)
351 {
352  assert(n_ && m_);
353  this->n = n_;
354  this->m = m_;
355  mat.reset(new std::complex<double> [n*m]);
356 }
357 
362 {
363  n = orig.n;
364  m = orig.m;
365  mat.reset(new std::complex<double> [n*m]);
366  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(std::complex<double>));
367 }
368 
374 {
375  n = orig.n;
376  m = orig.m;
377  mat = std::move(orig.mat);
378 }
379 
381 {
382  n = orig.n;
383  m = orig.m;
384  mat.reset(new std::complex<double> [n*m]);
385  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(std::complex<double>));
386  return *this;
387 }
388 
393 cmatrix& cmatrix::operator=(std::complex<double> val)
394 {
395  for(int i=0;i<n*m;i++)
396  mat[i] = val;
397 
398  return *this;
399 }
400 
404 int cmatrix::getn() const
405 {
406  return n;
407 }
408 
412 int cmatrix::getm() const
413 {
414  return m;
415 }
416 
417 std::complex<double> cmatrix::operator()(int x,int y) const
418 {
419  assert(x<n && y<m);
420  return mat[x+y*n];
421 }
422 
423 std::complex<double>& cmatrix::operator()(int x,int y)
424 {
425  assert(x<n && y<m);
426  return mat[x+y*n];
427 }
428 
429 std::complex<double>& cmatrix::operator[](int x)
430 {
431  assert(x<n*m);
432  return mat[x];
433 }
434 
435 std::complex<double> cmatrix::operator[](int x) const
436 {
437  assert(x<n*m);
438  return mat[x];
439 }
440 
441 std::complex<double>* cmatrix::getpointer() const
442 {
443  return mat.get();
444 }
445 
446 void cmatrix::Print() const
447 {
448  for(int i=0;i<n;i++)
449  for(int j=0;j<m;j++)
450  std::cout << i << " " << j << "\t" << (*this)(i,j) << std::endl;
451 }
452 
453 
458  template<typename T>
460 {
461  this->n = 0;
462  this->m = 0;
463 }
464 
469  template<typename T>
470 tmatrix<T>::tmatrix(int n_, int m_)
471 {
472  assert(n_>0 && m_>0);
473  this->n = n_;
474  this->m = m_;
475  mat.reset(new T [n*m]);
476 }
477 
481  template<typename T>
483 {
484  n = orig.n;
485  m = orig.m;
486  mat.reset(new T [n*m]);
487  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(T));
488 }
489 
494  template<typename T>
496 {
497  n = orig.n;
498  m = orig.m;
499  mat = std::move(orig.mat);
500 }
501 
502  template<typename T>
504 {
505  n = orig.n;
506  m = orig.m;
507  mat.reset(new T [n*m]);
508  std::memcpy(mat.get(), orig.getpointer(), n*m*sizeof(T));
509  return *this;
510 }
511 
516  template<typename T>
518 {
519  for(int i=0;i<n*m;i++)
520  mat[i] = val;
521 
522  return *this;
523 }
524 
528  template<typename T>
529 unsigned int tmatrix<T>::getn() const
530 {
531  return n;
532 }
533 
537  template<typename T>
538 unsigned int tmatrix<T>::getm() const
539 {
540  return m;
541 }
542 
543  template<typename T>
544 T tmatrix<T>::operator()(int x,int y) const
545 {
546  assert(x<n && y<m);
547  return mat[x+y*n];
548 }
549 
550  template<typename T>
551 T& tmatrix<T>::operator()(int x,int y)
552 {
553  assert(x<n && y<m);
554  return mat[x+y*n];
555 }
556 
557  template<typename T>
559 {
560  assert(x<n*m);
561  return mat[x];
562 }
563 
564  template<typename T>
566 {
567  assert(x<n*m);
568  return mat[x];
569 }
570 
571  template<typename T>
573 {
574  return mat.get();
575 }
576 
577  template<typename T>
578 void tmatrix<T>::Print() const
579 {
580  for(int i=0;i<n;i++)
581  for(int j=0;j<m;j++)
582  std::cout << i << " " << j << "\t" << (*this)(i,j) << std::endl;
583 }
584 
585 namespace helpers
586 {
587  template class tmatrix<int>;
588  template class tmatrix<unsigned int>;
589 }
590 
591 /* vim: set ts=8 sw=4 tw=0 expandtab :*/
cmatrix & operator=(const cmatrix &orig)
Definition: helpers.cpp:380
void SaveToFile(std::string filename) const
Definition: helpers.cpp:246
matrix & operator=(const matrix &orig)
Definition: helpers.cpp:83
tmatrix< T > & operator=(const tmatrix< T > &orig)
Definition: helpers.cpp:503
void ReadFromFile(std::string filename) const
Definition: helpers.cpp:291
int getm() const
Definition: helpers.cpp:412
void Print() const
Definition: helpers.cpp:228
int getn() const
Definition: helpers.cpp:107
T & operator[](int x)
Definition: helpers.cpp:558
int getm() const
Definition: helpers.cpp:115
matrix & prod(matrix const &A, matrix const &B)
Definition: helpers.cpp:154
void dgemm_(char *transA, char *transB, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc)
void dsyev_(char *jobz, char *uplo, int *n, double *A, int *lda, double *W, double *work, int *lwork, int *info)
void Print() const
Definition: helpers.cpp:446
unsigned int getn() const
Definition: helpers.cpp:529
std::unique_ptr< double[]> mat
n by m array of double
Definition: helpers.h:78
unsigned int m
number of columns
Definition: helpers.h:173
std::unique_ptr< double[]> svd()
Definition: helpers.cpp:173
int n
number of rows
Definition: helpers.h:80
#define HDF5_STATUS_CHECK(status)
Definition: helpers.cpp:30
std::complex< double > & operator[](int x)
Definition: helpers.cpp:429
std::complex< double > operator()(int x, int y) const
Definition: helpers.cpp:417
int m
number of columns
Definition: helpers.h:130
std::unique_ptr< double[]> sym_eig()
Definition: helpers.cpp:206
std::unique_ptr< std::complex< double >[]> mat
n by m array of complex
Definition: helpers.h:126
int n
number of rows
Definition: helpers.h:128
void Print() const
Definition: helpers.cpp:578
double operator()(int x, int y) const
Definition: helpers.cpp:120
double & operator[](int x)
Definition: helpers.cpp:132
T operator()(int x, int y) const
Definition: helpers.cpp:544
int m
number of columns
Definition: helpers.h:82
T * getpointer() const
Definition: helpers.cpp:572
unsigned int getm() const
Definition: helpers.cpp:538
void dgesvd_(char *jobu, char *jobvt, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork, int *info)
double trace() const
Definition: helpers.cpp:235
std::complex< double > * getpointer() const
Definition: helpers.cpp:441
double * getpointer() const
Definition: helpers.cpp:144
unsigned int n
number of rows
Definition: helpers.h:171
int getn() const
Definition: helpers.cpp:404