DOCI-Exact  1.0
SparseMatrix_CRS.cpp
Go to the documentation of this file.
1 #include <cmath>
2 #include <hdf5.h>
3 #include "SparseMatrix_CRS.h"
4 
5 #ifdef __INTEL_COMPILER
6 #include <mkl.h>
7 #endif
8 
9 // this helps to check the return codes of HDF5 calls
10 #define HDF5_STATUS_CHECK(status) if(status < 0) std::cerr << __FILE__ << ":" << __LINE__ << ": Problem with writing to file. Status code=" << status << std::endl;
11 
12 using namespace helpers;
13 
19 {
20  this->n = n;
21  row.reserve(n+1);
22 }
23 
30 double SparseMatrix_CRS::operator()(unsigned int i,unsigned int j) const
31 {
32  assert(i<n && j<n);
33 
34  for(unsigned int k=row[i];k<row[i+1];k++)
35  if( col[k] == j )
36  return data[k];
37 
38  return 0;
39 }
40 
44 unsigned int SparseMatrix_CRS::gn() const
45 {
46  return n;
47 }
48 
54 {
55  assert(dense.getm() == dense.getn());
56  this->n = dense.getn();
57  row.resize(n+1);
58 
59  data.clear();
60  col.clear();
61 
62  row[0] = 0;
63 
64  for(unsigned int i=0;i<n;i++)
65  {
66  for(unsigned int j=0;j<n;j++)
67  if( fabs(dense(i,j)) > 1e-14 )
68  {
69  data.push_back(dense(i,j));
70  col.push_back(j);
71  }
72 
73  row[i+1] = col.size();
74  }
75 
76  row.back() = col.size();
77 }
78 
84 {
85  assert(dense.getm() == dense.getn() && dense.getn() == n);
86  dense = 0;
87 
88  for(unsigned int i=0;i<row.size()-1;i++)
89  for(unsigned int k=row[i];k<row[i+1];k++)
90  dense(i,col[k]) = dense(col[k],i) = data[k];
91 }
92 
97 {
98  std::cout << "Data(" << data.size() << "):" << std::endl;
99  for(unsigned int i=0;i<data.size();i++)
100  std::cout << data[i] << " ";
101  std::cout << std::endl;
102 
103  std::cout << "Col indices:" << std::endl;
104  for(unsigned int i=0;i<col.size();i++)
105  std::cout << col[i] << " ";
106  std::cout << std::endl;
107 
108  std::cout << "Row indices:" << std::endl;
109  for(unsigned int i=0;i<row.size();i++)
110  std::cout << row[i] << " ";
111  std::cout << std::endl;
112 }
113 
120 std::ostream &operator<<(std::ostream &output,helpers::SparseMatrix_CRS &matrix_p)
121 {
122  for(unsigned int i=0;i<matrix_p.row.size()-1;i++)
123  for(unsigned int k=matrix_p.row[i];k<matrix_p.row[i+1];k++)
124  output << i << "\t" << matrix_p.col[k] << "\t" << matrix_p.data[k] << std::endl;
125 
126  return output;
127 }
128 
137 void SparseMatrix_CRS::PushToRow(unsigned int j, double value)
138 {
139  if(col.empty() || row.back() == col.size() || col.back() < j)
140  {
141  data.push_back(value);
142  col.push_back(j);
143  }
144  else
145  {
146  unsigned int begin = row.back();
147  for(unsigned int i=begin;i<col.size();i++)
148  {
149  if( col[i] > j )
150  {
151  col.insert(col.begin() + i,j);
152  data.insert(data.begin() + i,value);
153  break;
154  } else if (col[i] == j)
155  {
156  data[i] += value;
157 
158  if(fabs(data[i])<1e-14)
159  {
160  data.erase(data.begin() + i);
161  col.erase(col.begin() + i);
162  }
163  break;
164  }
165  }
166  }
167 }
168 
182 void SparseMatrix_CRS::PushToRowNext(unsigned int j, double value)
183 {
184  assert(col.empty() || row.back() == col.size() || col.back() < j);
185 
186  data.push_back(value);
187  col.push_back(j);
188 }
189 
194 {
195  if(row.size() == (n+1))
196  return;
197 
198  row.push_back(data.size());
199 
200  // fill the lower part with data
201  // from the upper part
202 // for(unsigned int j=1;j<row.size();j++)
203 // for(unsigned int k=row[j-1]+1;k<row[j];k++)
204 // {
205 // if(col[k] == (row.size()-1))
206 // {
207 // data.push_back(data[k]);
208 // col.push_back(j-1);
209 // break;
210 // }
211 // }
212 }
213 
219 void SparseMatrix_CRS::mvprod(const double *x, double *y) const
220 {
221 #ifdef __INTEL_COMPILER
222  char uplo = 'U';
223 
224  mkl_cspblas_dcsrsymv(&uplo, (const int *) &n, data.data(), (const int *) row.data(), (const int *) col.data(), x, y);
225 #else
226 
227 //#pragma omp parallel
228  for(unsigned int i=0;i<n;i++)
229  {
230  y[i] = 0;
231 
232  // upper diagonal
233  for(unsigned int k=row[i];k<row[i+1];k++)
234  {
235  y[i] += data[k] * x[col[k]];
236  }
237 
238  // lower diagonal
239  for(unsigned int j=0;j<i;j++)
240  for(unsigned int k=row[j]+1;k<row[j+1];k++)
241  {
242  if(col[k] == i)
243  {
244  y[i] += data[k] * x[j];
245  break;
246  }
247  }
248  }
249 #endif
250 }
251 
258 void SparseMatrix_CRS::mvprod(const double *x, double *y, double beta) const
259 {
260 #pragma omp parallel
261  for(unsigned int i=0;i<n;i++)
262  {
263  y[i] *= beta;
264 
265  // upper diagonal
266  for(unsigned int k=row[i];k<row[i+1];k++)
267  {
268  y[i] += data[k] * x[col[k]];
269  }
270 
271  // lower diagonal
272  for(unsigned int j=0;j<i;j++)
273  for(unsigned int k=row[j]+1;k<row[j+1];k++)
274  {
275  if(col[k] == i)
276  {
277  y[i] += data[k] * x[j];
278  break;
279  }
280  }
281  }
282 }
283 
290 int SparseMatrix_CRS::WriteToFile(const char *filename, const char *name, bool append) const
291 {
292  hid_t file_id, group_id, dataset_id, attribute_id, dataspace_id, scalar_id;
293  herr_t status;
294 
295  if(append)
296  file_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
297  else
298  file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
299 
300  group_id = H5Gcreate(file_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
301 
302  hsize_t dimblock = data.size();
303 
304  scalar_id = H5Screate(H5S_SCALAR);
305 
306  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
307 
308  dataset_id = H5Dcreate(group_id, "data", H5T_IEEE_F64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
309 
310  status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data() );
311  HDF5_STATUS_CHECK(status);
312 
313  unsigned int size = data.size();
314  attribute_id = H5Acreate (dataset_id, "size", H5T_STD_U64LE, scalar_id, H5P_DEFAULT, H5P_DEFAULT);
315  HDF5_STATUS_CHECK(attribute_id);
316  status = H5Awrite (attribute_id, H5T_NATIVE_UINT, &size );
317  HDF5_STATUS_CHECK(status);
318 
319  status = H5Aclose(attribute_id);
320  HDF5_STATUS_CHECK(status);
321 
322  status = H5Dclose(dataset_id);
323  HDF5_STATUS_CHECK(status);
324 
325  dataset_id = H5Dcreate(group_id, "col", H5T_STD_U64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
326 
327  status = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, col.data() );
328  HDF5_STATUS_CHECK(status);
329 
330  size = col.size();
331  attribute_id = H5Acreate (dataset_id, "size", H5T_STD_U64LE, scalar_id, H5P_DEFAULT, H5P_DEFAULT);
332  status = H5Awrite (attribute_id, H5T_NATIVE_UINT, &size );
333  HDF5_STATUS_CHECK(status);
334 
335  status = H5Aclose(attribute_id);
336  HDF5_STATUS_CHECK(status);
337 
338  status = H5Dclose(dataset_id);
339  HDF5_STATUS_CHECK(status);
340 
341  status = H5Sclose(dataspace_id);
342  HDF5_STATUS_CHECK(status);
343 
344  dimblock = row.size();
345 
346  dataspace_id = H5Screate_simple(1, &dimblock, NULL);
347 
348  dataset_id = H5Dcreate(group_id, "row", H5T_STD_U64LE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
349 
350  status = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, row.data() );
351  HDF5_STATUS_CHECK(status);
352 
353  status = H5Dclose(dataset_id);
354  HDF5_STATUS_CHECK(status);
355 
356  status = H5Sclose(dataspace_id);
357  HDF5_STATUS_CHECK(status);
358 
359  dataset_id = H5Dcreate(group_id, "n", H5T_STD_U64LE, scalar_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
360 
361  status = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &n );
362  HDF5_STATUS_CHECK(status);
363 
364  status = H5Dclose(dataset_id);
365  HDF5_STATUS_CHECK(status);
366 
367  status = H5Sclose(scalar_id);
368  HDF5_STATUS_CHECK(status);
369 
370  status = H5Gclose(group_id);
371  HDF5_STATUS_CHECK(status);
372 
373  status = H5Fclose(file_id);
374  HDF5_STATUS_CHECK(status);
375 
376  return 0;
377 }
378 
384 int SparseMatrix_CRS::ReadFromFile(const char *filename, const char *name)
385 {
386  hid_t file_id, group_id, dataset_id, attribute_id;
387  herr_t status;
388 
389  file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
390  HDF5_STATUS_CHECK(file_id);
391 
392  group_id = H5Gopen(file_id, name, H5P_DEFAULT);
393  HDF5_STATUS_CHECK(group_id);
394 
395  dataset_id = H5Dopen(group_id, "n", H5P_DEFAULT);
396  HDF5_STATUS_CHECK(dataset_id);
397 
398  status = H5Dread(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &n);
399  HDF5_STATUS_CHECK(status);
400 
401  status = H5Dclose(dataset_id);
402  HDF5_STATUS_CHECK(status);
403 
404  row.resize(n+1);
405 
406  unsigned int size;
407 
408  dataset_id = H5Dopen(group_id, "data", H5P_DEFAULT);
409  HDF5_STATUS_CHECK(dataset_id);
410 
411  attribute_id = H5Aopen(dataset_id, "size", H5P_DEFAULT);
412  HDF5_STATUS_CHECK(attribute_id);
413 
414  status = H5Aread(attribute_id, H5T_NATIVE_UINT, &size);
415  HDF5_STATUS_CHECK(status);
416 
417 
418  status = H5Aclose(attribute_id);
419  HDF5_STATUS_CHECK(status);
420 
421  data.resize(size);
422 
423  status = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
424  HDF5_STATUS_CHECK(status);
425 
426  status = H5Dclose(dataset_id);
427  HDF5_STATUS_CHECK(status);
428 
429 
430  dataset_id = H5Dopen(group_id, "col", H5P_DEFAULT);
431  HDF5_STATUS_CHECK(dataset_id);
432 
433  attribute_id = H5Aopen(dataset_id, "size", H5P_DEFAULT);
434  HDF5_STATUS_CHECK(attribute_id);
435 
436  status = H5Aread(attribute_id, H5T_NATIVE_UINT, &size);
437  HDF5_STATUS_CHECK(status);
438 
439  status = H5Aclose(attribute_id);
440  HDF5_STATUS_CHECK(status);
441 
442  col.resize(size);
443 
444  status = H5Dread(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, col.data());
445  HDF5_STATUS_CHECK(status);
446 
447  status = H5Dclose(dataset_id);
448  HDF5_STATUS_CHECK(status);
449 
450 
451  dataset_id = H5Dopen(group_id, "row", H5P_DEFAULT);
452  HDF5_STATUS_CHECK(dataset_id);
453 
454  status = H5Dread(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, row.data());
455  HDF5_STATUS_CHECK(status);
456 
457  status = H5Dclose(dataset_id);
458  HDF5_STATUS_CHECK(status);
459 
460  status = H5Gclose(group_id);
461  HDF5_STATUS_CHECK(status);
462 
463  status = H5Fclose(file_id);
464  HDF5_STATUS_CHECK(status);
465 
466  return 0;
467 }
468 
474 unsigned int SparseMatrix_CRS::NumOfElInRow(unsigned int idx) const
475 {
476  return (row[idx+1]-row[idx]);
477 }
478 
485 double SparseMatrix_CRS::GetElementInRow(unsigned int row_index, unsigned int element_index) const
486 {
487  return data[row[row_index]+element_index];
488 }
489 
496 unsigned int SparseMatrix_CRS::GetElementColIndexInRow(unsigned int row_index, unsigned int element_index) const
497 {
498  return col[row[row_index]+element_index];
499 }
500 
501 
508 void SparseMatrix_CRS::SetGuess(unsigned int count)
509 {
510  data.reserve(count);
511  col.reserve(count);
512 }
513 
524 void SparseMatrix_CRS::AddList(std::vector< std::unique_ptr<SparseMatrix_CRS> > &list)
525 {
526  unsigned int total_size = 0;
527 
528  for(auto& smat : list)
529  total_size += smat->data.size();
530 
531  data.reserve(total_size);
532  col.reserve(total_size);
533 
534  data.clear();
535  col.clear();
536 
537  row.reserve(n+1);
538  row.clear();
539 
540  for(auto &smat: list)
541  {
542  auto prev_start = data.size();
543 
544  data.insert(data.end(), smat->data.begin(), smat->data.end());
545  col.insert(col.end(), smat->col.begin(), smat->col.end());
546 
547  for(unsigned int i=0;i<smat->row.size();++i)
548  row.push_back(prev_start + smat->row[i]);
549 
550  smat.reset();
551  }
552 
553  assert(data.size() == total_size);
554  assert(col.size() == total_size);
555  assert(row.size() == n);
556 
557  row.push_back(data.size());
558 }
559 
560 /* vim: set ts=3 sw=3 expandtab :*/
#define HDF5_STATUS_CHECK(status)
std::ostream & operator<<(std::ostream &output, helpers::SparseMatrix_CRS &matrix_p)
void ConvertFromMatrix(const helpers::matrix &dense)
SparseMatrix_CRS(unsigned int n)
double operator()(unsigned int i, unsigned int j) const
int getn() const
Definition: helpers.cpp:128
unsigned int NumOfElInRow(unsigned int idx) const
int getm() const
Definition: helpers.cpp:136
void ConvertToMatrix(helpers::matrix &dense) const
unsigned int GetElementColIndexInRow(unsigned int row_index, unsigned int element_index) const
double GetElementInRow(unsigned int row_index, unsigned int element_index) const
void PushToRow(unsigned int j, double value)
void PushToRowNext(unsigned int j, double value)
unsigned int gn() const
void AddList(std::vector< std::unique_ptr< SparseMatrix_CRS > > &)
int ReadFromFile(const char *, const char *)
int WriteToFile(const char *, const char *, bool=false) const
void mvprod(const double *, double *) const