KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
matrix_market_interface.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ \.
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Riccardo Rossi
11 //
12 
13 #pragma once
14 
15 // System includes
16 #include <stdio.h>
17 
18 
19 // External includes
20 
21 // To avoid linking problems
22 extern "C"
23 {
24 #include "includes/mmio.h"
25 }
26 
27 #include <boost/numeric/ublas/matrix_sparse.hpp>
28 
29 
30 // Project includes
31 
32 namespace Kratos
33 {
34 
35 // Type checks
36 template<typename T>
37 constexpr bool IsCorrectType(MM_typecode& mm_code);
38 
39 template<>
40 constexpr inline bool IsCorrectType<double>(MM_typecode& mm_code)
41 {
42  return mm_is_real(mm_code);
43 }
44 
45 template<>
46 constexpr inline bool IsCorrectType<std::complex<double>>(MM_typecode& mm_code)
47 {
48  return mm_is_complex(mm_code);
49 }
50 
51 // Matrix I/O routines
52 inline bool ReadMatrixMarketMatrixEntry(FILE *f, int& I, int& J, double& V)
53 {
54 
55  return fscanf(f, "%d %d %lg", &I, &J, &V) == 3;
56 }
57 
58 inline bool ReadMatrixMarketMatrixEntry(FILE *f, int& I, int& J, std::complex<double>& V)
59 {
60  double real;
61  double imag;
62  const int i = fscanf(f, "%d %d %lg %lg", &I, &J, &real, &imag);
63  V = std::complex<double>(real, imag);
64  return i == 4;
65 }
66 
67 template <typename CompressedMatrixType> inline bool ReadMatrixMarketMatrix(const char *FileName, CompressedMatrixType &M)
68 {
69  typedef typename CompressedMatrixType::value_type ValueType;
70 
71  // Open MM file for reading
72  FILE *f = fopen(FileName, "r");
73 
74  if (f == NULL)
75  {
76  printf("ReadMatrixMarketMatrix(): unable to open %s.\n", FileName);
77  return false;
78  }
79 
80  // Process MM file header
81  MM_typecode mm_code;
82 
83  if (mm_read_banner(f, &mm_code) != 0)
84  {
85  printf("ReadMatrixMarketMatrix(): unable to read MatrixMarket banner.\n");
86  fclose(f);
87  return false;
88  }
89 
90  if (!mm_is_valid(mm_code))
91  {
92  printf("ReadMatrixMarketMatrix(): invalid MatrixMarket banner.\n");
93  fclose(f);
94  return false;
95  }
96 
97  // Check for supported types of MM file
98  if (!(mm_is_coordinate(mm_code) && mm_is_sparse(mm_code)))
99  {
100  printf("ReadMatrixMarketMatrix(): unsupported MatrixMarket type, \"%s\".\n", mm_typecode_to_str(mm_code));
101  fclose(f);
102  return false;
103  }
104 
105  // Read MM dimensions and NNZ
106  int size1, size2, nnz;
107 
108  if (mm_read_mtx_crd_size(f, &size1, &size2, &nnz) != 0)
109  {
110  printf("ReadMatrixMarketMatrix(): cannot read dimensions and NNZ.\n");
111  fclose(f);
112  return false;
113  }
114 
115  // Allocate temporary arrays
116  int *I = new int[nnz];
117  int *J = new int[nnz];
118  ValueType *V = new ValueType[nnz];
119 
120  // Check if matrix type matches MM file
121  if (!IsCorrectType<ValueType>(mm_code))
122  {
123  printf("ReadMatrixMarketMatrix(): MatrixMarket type, \"%s\" does not match provided matrix type.\n", mm_typecode_to_str(mm_code));
124  fclose(f);
125  return false;
126  }
127 
128  // Read MM file
129 
130  // Pattern file, only non-zero structure
131  if (mm_is_pattern(mm_code))
132  for (int i = 0; i < nnz; i++)
133  {
134  if (fscanf(f, "%d %d", &I[i], &J[i]) != 2)
135  {
136  printf("ReadMatrixMarketMatrix(): invalid data.\n");
137  fclose(f);
138 
139  delete[] I;
140  delete[] J;
141  delete[] V;
142 
143  return false;
144  }
145 
146  // Adjust to 0-based
147  I[i]--;
148  J[i]--;
149 
150  // Set all values to 1.00
151  V[i] = 1.00;
152  }
153  else
154  for (int i = 0; i < nnz; i++)
155  {
156  if (! ReadMatrixMarketMatrixEntry(f, I[i], J[i], V[i]))
157  {
158  printf("ReadMatrixMarketMatrix(): invalid data.\n");
159  fclose(f);
160 
161  delete[] I;
162  delete[] J;
163  delete[] V;
164 
165  return false;
166  }
167 
168  // Adjust to 0-based
169  I[i]--;
170  J[i]--;
171  }
172 
173  fclose(f);
174 
175  // Second stage
176  int *nz = new int[size1];
177 
178  for (int i = 0; i < size1; i++)
179  nz[i] = 0;
180 
181  // Count non-zeros on each line
182  if (mm_is_symmetric(mm_code))
183  for (int i = 0; i < nnz; i++)
184  {
185  if (I[i] == J[i])
186  nz[I[i]]++;
187  else
188  {
189  nz[I[i]]++;
190  nz[J[i]]++;
191  }
192  }
193  else
194  for (int i = 0; i < nnz; i++)
195  nz[I[i]]++;
196 
197  // Find out total number of non-zeros
198  int nnz2;
199 
200  if (mm_is_symmetric(mm_code))
201  {
202  int diagonals = 0;
203 
204  for (int i = 0; i < nnz; i++)
205  if (I[i] == J[i])
206  diagonals++;
207 
208  nnz2 = diagonals + 2 * (nnz - diagonals);
209  }
210  else
211  nnz2 = nnz;
212 
213  // Fill in an almost-CSR data structure
214  int *filled = new int[size1];
215  int *indices = new int[size1];
216  int *columns = new int[nnz2];
217  ValueType *values = new ValueType[nnz2];
218 
219  indices[0] = 0;
220  for (int i = 1; i < size1; i++)
221  indices[i] = indices[i - 1] + nz[i - 1];
222 
223  for (int i = 0; i < size1; i++)
224  filled[i] = 0;
225 
226  if (mm_is_symmetric(mm_code))
227  for (int i = 0; i < nnz; i++)
228  if (I[i] == J[i])
229  {
230  int index;
231 
232  index = indices[I[i]] + filled[I[i]];
233  columns[index] = J[i];
234  values[index] = V[i];
235  filled[I[i]]++;
236  }
237  else
238  {
239  int index;
240 
241  index = indices[I[i]] + filled[I[i]];
242  columns[index] = J[i];
243  values[index] = V[i];
244  filled[I[i]]++;
245 
246  index = indices[J[i]] + filled[J[i]];
247  columns[index] = I[i];
248  values[index] = V[i];
249  filled[J[i]]++;
250  }
251  else
252  for (int i = 0; i < nnz; i++)
253  {
254  int index;
255 
256  index = indices[I[i]] + filled[I[i]];
257  columns[index] = J[i];
258  values[index] = V[i];
259  filled[I[i]]++;
260  }
261 
262  // Create the matrix
263  CompressedMatrixType *m = new CompressedMatrixType(size1, size2, nnz2);
264 
265  int k = 0;
266 
267  for (int i = 0; i < size1; i++)
268  for (int j = 0; j < nz[i]; j++)
269  (*m)(i, columns[indices[i] + j]) = values[k++];
270 
271  M = *m;
272 
273  delete[] I;
274  delete[] J;
275  delete[] V;
276 
277  delete[] filled;
278  delete[] indices;
279  delete[] columns;
280  delete[] values;
281  delete[] nz;
282 
283  delete m;
284 
285  return true;
286 }
287 
288 inline void SetMatrixMarketValueTypeCode(MM_typecode& mm_code, const double& value)
289 {
290  mm_set_real(&mm_code);
291 }
292 
293 inline void SetMatrixMarketValueTypeCode(MM_typecode& mm_code, const std::complex<double>& value)
294 {
295  mm_set_complex(&mm_code);
296 }
297 
298 inline int WriteMatrixMarketMatrixEntry(FILE *f, int I, int J, const double& entry)
299 {
300  return fprintf(f, "%d %d %.12e\n", I, J, entry);
301 }
302 
303 inline int WriteMatrixMarketMatrixEntry(FILE *f, int I, int J, const std::complex<double>& entry)
304 {
305  return fprintf(f, "%d %d %.12e %.12e\n", I, J, std::real(entry), std::imag(entry));
306 }
307 
308 template <typename CompressedMatrixType> inline bool WriteMatrixMarketMatrix(const char *FileName, CompressedMatrixType &M, bool Symmetric)
309 {
310  // Open MM file for writing
311  FILE *f = fopen(FileName, "w");
312 
313  if (f == NULL)
314  {
315  printf("WriteMatrixMarketMatrix(): unable to open %s.\n", FileName);
316  return false;
317  }
318 
319  // Write MM file header
320  MM_typecode mm_code;
321 
322  mm_initialize_typecode(&mm_code);
323 
324  mm_set_matrix(&mm_code);
325  mm_set_coordinate(&mm_code);
326  SetMatrixMarketValueTypeCode(mm_code, *M.begin1().begin());
327 
328  if (Symmetric)
329  mm_set_symmetric(&mm_code);
330  else
331  mm_set_general(&mm_code);
332 
333  mm_write_banner(f, mm_code);
334 
335  // Find out the actual number of non-zeros in case of a symmetric matrix
336  int nnz;
337 
338  if (Symmetric)
339  {
340  nnz = 0;
341 
342  typename CompressedMatrixType::iterator1 a_iterator = M.begin1();
343 
344  for (unsigned int i = 0; i < M.size1(); i++)
345  {
346 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
347  for (typename CompressedMatrixType::iterator2 row_iterator = a_iterator.begin(); row_iterator != a_iterator.end(); ++row_iterator)
348 #else
349  for (typename CompressedMatrixType::iterator2 row_iterator = begin(a_iterator, iterator1_tag()); row_iterator != end(a_iterator, iterator1_tag()); ++row_iterator)
350 #endif
351  {
352  if (a_iterator.index1() >= row_iterator.index2())
353  nnz++;
354  }
355 
356  a_iterator++;
357  }
358  }
359  else
360  nnz = M.nnz();
361 
362  // Write MM file sizes
363  mm_write_mtx_crd_size(f, M.size1(), M.size2(), nnz);
364 
365  if (Symmetric)
366  {
367  typename CompressedMatrixType::iterator1 a_iterator = M.begin1();
368 
369  for (unsigned int i = 0; i < M.size1(); i++)
370  {
371 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
372  for (typename CompressedMatrixType::iterator2 row_iterator = a_iterator.begin(); row_iterator != a_iterator.end(); ++row_iterator)
373 #else
374  for (typename CompressedMatrixType::iterator2 row_iterator = begin(a_iterator, iterator1_tag()); row_iterator != end(a_iterator, iterator1_tag()); ++row_iterator)
375 #endif
376  {
377  int I = a_iterator.index1(), J = row_iterator.index2();
378 
379  if (I >= J)
380  if (WriteMatrixMarketMatrixEntry(f, I+1, J+1, *row_iterator) < 0)
381  {
382  printf("WriteMatrixMarketMatrix(): unable to write data.\n");
383  fclose(f);
384  return false;
385  }
386  }
387 
388  a_iterator++;
389  }
390  }
391  else
392  {
393  typename CompressedMatrixType::iterator1 a_iterator = M.begin1();
394 
395  for (unsigned int i = 0; i < M.size1(); i++)
396  {
397 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
398  for (typename CompressedMatrixType::iterator2 row_iterator = a_iterator.begin(); row_iterator != a_iterator.end(); ++row_iterator)
399 #else
400  for (typename CompressedMatrixType::iterator2 row_iterator = begin(a_iterator, iterator1_tag()); row_iterator != end(a_iterator, iterator1_tag()); ++row_iterator)
401 #endif
402  {
403  int I = a_iterator.index1(), J = row_iterator.index2();
404 
405  if (WriteMatrixMarketMatrixEntry(f, I+1, J+1, *row_iterator) < 0)
406  {
407  printf("WriteMatrixMarketMatrix(): unable to write data.\n");
408  fclose(f);
409  return false;
410  }
411  }
412 
413  a_iterator++;
414  }
415  }
416 
417  fclose(f);
418 
419  return true;
420 }
421 
422 // Vector I/O routines
423 
424 inline bool ReadMatrixMarketVectorEntry(FILE *f, double& entry)
425 {
426  return fscanf(f, "%lg", &entry) == 1;
427 }
428 
429 inline bool ReadMatrixMarketVectorEntry(FILE *f, std::complex<double>& entry)
430 {
431  double real;
432  double imag;
433  const int i = fscanf(f, "%lg %lg", &real, &imag);
434  entry = std::complex<double>(real, imag);
435  return i == 2;
436 }
437 
438 template <typename VectorType> inline bool ReadMatrixMarketVector(const char *FileName, VectorType &V)
439 {
440  typedef typename VectorType::value_type ValueType;
441 
442  // Open MM file for reading
443  FILE *f = fopen(FileName, "r");
444 
445  if (f == NULL)
446  {
447  printf("ReadMatrixMarketVector(): unable to open %s.\n", FileName);
448  return false;
449  }
450 
451  // Process MM file header
452  MM_typecode mm_code;
453 
454  if (mm_read_banner(f, &mm_code) != 0)
455  {
456  printf("ReadMatrixMarketVector(): unable to read MatrixMarket banner.\n");
457  fclose(f);
458  return false;
459  }
460 
461  if (!mm_is_valid(mm_code))
462  {
463  printf("ReadMatrixMarketVector(): invalid MatrixMarket banner.\n");
464  fclose(f);
465  return false;
466  }
467 
468  // Check for supported types of MM file
469  if (!((!mm_is_pattern(mm_code)) && mm_is_array(mm_code)))
470  {
471  printf("ReadMatrixMarketVector(): unsupported MatrixMarket type, \"%s\".\n", mm_typecode_to_str(mm_code));
472  fclose(f);
473  return false;
474  }
475 
476  // Read MM dimensions
477  int size1, size2;
478 
479  if (mm_read_mtx_array_size(f, &size1, &size2) != 0)
480  {
481  printf("ReadMatrixMarketVector(): cannot read dimensions.\n");
482  fclose(f);
483  return false;
484  }
485 
486  // Check MM dimensions
487  if (size2 != 1)
488  {
489  printf("ReadMatrixMarketVector(): not a N x 1 array.\n");
490  fclose(f);
491  return false;
492  }
493 
494  VectorType *v = new VectorType(size1);
495  ValueType T;
496 
497  // Check if vector type matches MM file
498  if (!IsCorrectType<ValueType>(mm_code))
499  {
500  printf("ReadMatrixMarketVector(): MatrixMarket type, \"%s\" does not match provided vector type.\n", mm_typecode_to_str(mm_code));
501  fclose(f);
502  return false;
503  }
504 
505  // Read MM file
506 
507  for (int i = 0; i < size1; i++)
508  {
509  if (! ReadMatrixMarketVectorEntry(f, T))
510  {
511  printf("ReadMatrixMarketVector(): invalid data.\n");
512  fclose(f);
513 
514  return false;
515  }
516 
517  (*v)(i) = T;
518  }
519 
520  fclose(f);
521 
522  V = *v;
523 
524  delete v;
525 
526  return true;
527 }
528 
529 inline int WriteMatrixMarketVectorEntry(FILE *f, const double& entry)
530 {
531  return fprintf(f, "%e\n", entry);
532 }
533 
534 inline int WriteMatrixMarketVectorEntry(FILE *f, const std::complex<double>& entry)
535 {
536  return fprintf(f, "%e %e\n", std::real(entry), std::imag(entry));
537 }
538 
539 template <typename VectorType> inline bool WriteMatrixMarketVector(const char *FileName, VectorType &V)
540 {
541  // Open MM file for writing
542  FILE *f = fopen(FileName, "w");
543 
544  if (f == NULL)
545  {
546  printf("WriteMatrixMarketVector(): unable to open %s.\n", FileName);
547  return false;
548  }
549 
550  // Write MM file header
551  MM_typecode mm_code;
552 
553  mm_initialize_typecode(&mm_code);
554 
555  mm_set_matrix(&mm_code);
556  mm_set_array(&mm_code);
557  SetMatrixMarketValueTypeCode(mm_code, V(0));
558 
559  mm_write_banner(f, mm_code);
560 
561  // Write MM file sizes
562  mm_write_mtx_array_size(f, V.size(), 1);
563 
564  for (unsigned int i = 0; i < V.size(); i++)
565  if (WriteMatrixMarketVectorEntry(f, V(i)) < 0)
566  {
567  printf("WriteMatrixMarketVector(): unable to write data.\n");
568  fclose(f);
569  return false;
570  }
571 
572  fclose(f);
573 
574  return true;
575 }
576 
577 } // namespace Kratos
double value_type
Definition: array_1d.h:75
#define mm_is_complex(typecode)
Definition: mmio.h:40
int mm_write_banner(FILE *f, MM_typecode matcode)
Definition: mmio.c:387
#define mm_set_complex(typecode)
Definition: mmio.h:61
#define mm_set_array(typecode)
Definition: mmio.h:57
#define mm_set_general(typecode)
Definition: mmio.h:68
char MM_typecode[4]
Definition: mmio.h:18
int mm_write_mtx_array_size(FILE *f, int M, int N)
Definition: mmio.c:250
#define mm_set_symmetric(typecode)
Definition: mmio.h:67
#define mm_set_coordinate(typecode)
Definition: mmio.h:56
#define mm_initialize_typecode(typecode)
Definition: mmio.h:75
#define mm_is_real(typecode)
Definition: mmio.h:41
#define mm_is_array(typecode)
Definition: mmio.h:38
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
Definition: mmio.c:221
#define mm_is_coordinate(typecode)
Definition: mmio.h:36
int mm_is_valid(MM_typecode matcode)
Definition: mmio.c:87
#define mm_is_pattern(typecode)
Definition: mmio.h:42
#define mm_set_matrix(typecode)
Definition: mmio.h:55
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz)
Definition: mmio.c:190
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
Definition: mmio.c:182
int mm_read_banner(FILE *f, MM_typecode *matcode)
Definition: mmio.c:97
#define mm_is_symmetric(typecode)
Definition: mmio.h:45
char * mm_typecode_to_str(MM_typecode matcode)
Definition: mmio.c:456
#define mm_is_sparse(typecode)
Definition: mmio.h:35
#define mm_set_real(typecode)
Definition: mmio.h:62
end
Definition: DEM_benchmarks.py:180
string FileName
Export to vtk.
Definition: GenerateWind.py:175
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
bool ReadMatrixMarketVectorEntry(FILE *f, double &entry)
Definition: matrix_market_interface.h:424
int WriteMatrixMarketVectorEntry(FILE *f, const double &entry)
Definition: matrix_market_interface.h:529
bool WriteMatrixMarketVector(const char *FileName, VectorType &V)
Definition: matrix_market_interface.h:539
int WriteMatrixMarketMatrixEntry(FILE *f, int I, int J, const double &entry)
Definition: matrix_market_interface.h:298
array_1d< double, 3 > VectorType
Definition: solid_mechanics_application_variables.cpp:19
bool WriteMatrixMarketMatrix(const char *FileName, CompressedMatrixType &M, bool Symmetric)
Definition: matrix_market_interface.h:308
constexpr bool IsCorrectType< double >(MM_typecode &mm_code)
Definition: matrix_market_interface.h:40
bool ReadMatrixMarketMatrix(const char *FileName, CompressedMatrixType &M)
Definition: matrix_market_interface.h:67
void SetMatrixMarketValueTypeCode(MM_typecode &mm_code, const double &value)
Definition: matrix_market_interface.h:288
bool ReadMatrixMarketVector(const char *FileName, VectorType &V)
Definition: matrix_market_interface.h:438
bool ReadMatrixMarketMatrixEntry(FILE *f, int &I, int &J, double &V)
Definition: matrix_market_interface.h:52
constexpr bool IsCorrectType(MM_typecode &mm_code)
list values
Definition: bombardelli_test.py:42
nz
Definition: cube_mesher.py:739
v
Definition: generate_convection_diffusion_explicit_element.py:114
f
Definition: generate_convection_diffusion_explicit_element.py:112
V
Definition: generate_droplet_dynamics.py:256
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int m
Definition: run_marine_rain_substepping.py:8
J
Definition: sensitivityMatrix.py:58
integer i
Definition: TensorModule.f:17