OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
SparseMatrix_petsc.hpp
1 /*
2  * SparseMatrix_petsc.hpp
3  *
4  * Created on: Apr 26, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_NUMERICS_SRC_MATRIX_SPARSEMATRIX_PETSC_HPP_
9 #define OPENFPM_NUMERICS_SRC_MATRIX_SPARSEMATRIX_PETSC_HPP_
10 
11 #include "util/petsc_util.hpp"
12 #include "Vector/map_vector.hpp"
13 #include <boost/mpl/int.hpp>
14 #include <petscmat.h>
15 
16 #define PETSC_BASE 2
17 
24 template<typename T>
25 class triplet<T,PETSC_BASE>
26 {
28  PetscInt row_;
29 
31  PetscInt col_;
32 
34  PetscScalar val_;
35 
36 public:
37 
43  PetscInt & row()
44  {
45  return row_;
46  }
47 
53  PetscInt & col()
54  {
55  return col_;
56  }
57 
63  PetscScalar & value()
64  {
65  return val_;
66  }
67 
75  triplet(long int i, long int j, T val)
76  {
77  row_ = i;
78  col_ = j;
79  val_ = val;
80  }
81 
82  // Default constructor
83  triplet()
84  :row_(0),col_(0),val_(0)
85  {};
86 };
87 
95 template<typename T, typename id_t>
96 class SparseMatrix<T,id_t, PETSC_BASE>
97 {
98 public:
99 
101  typedef boost::mpl::int_<PETSC_BASE> triplet_impl;
102 
105 
106 private:
107 
109  size_t g_row;
111  size_t g_col;
112 
114  size_t l_row;
116  size_t l_col;
117 
119  size_t start_row;
120 
122  bool m_created = false;
123 
125  Mat mat;
126 
129 
130 
139 
144  void fill_petsc()
145  {
146  d_nnz.resize(l_row);
147  o_nnz.resize(l_row);
148 
149  d_nnz.fill(0);
150  o_nnz.fill(0);
151 
152  // Here we explore every row to count how many non zero we have in the diagonal matrix part,
153  // and the non diagonal matrix part, needed by MatMPIAIJSetPreallocation
154 
155  size_t i = 0;
156 
157  // Set the Matrix from triplet
158  while (i < trpl.size())
159  {
160  PetscInt row = trpl.get(i).row();
161 
162  while(i < trpl.size() && row == trpl.get(i).row())
163  {
164  if ((size_t)trpl.get(i).col() >= start_row && (size_t)trpl.get(i).col() < start_row + l_row)
165  d_nnz.get(row - start_row)++;
166  else
167  o_nnz.get(row - start_row)++;
168  i++;
169  }
170  }
171 
172  PETSC_SAFE_CALL(MatMPIAIJSetPreallocation(mat,0,static_cast<const PetscInt*>(d_nnz.getPointer()),0,
173  static_cast<const PetscInt*>(o_nnz.getPointer())));
174 
175  // Counter i is zero
176  i = 0;
177 
178  // Set the Matrix from triplet
179  while (i < trpl.size())
180  {
181  vals.clear();
182  cols.clear();
183 
184  PetscInt row = trpl.get(i).row();
185 
186  while(i < trpl.size() && row == trpl.get(i).row())
187  {
188  vals.add(trpl.get(i).value());
189  cols.add(trpl.get(i).col());
190  i++;
191  }
192  PETSC_SAFE_CALL(MatSetValues(mat,1,&row,cols.size(),static_cast<const PetscInt*>(cols.getPointer()),
193  static_cast<const PetscScalar *>(vals.getPointer()),
194  INSERT_VALUES));
195  }
196 
197  PETSC_SAFE_CALL(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY));
198  PETSC_SAFE_CALL(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY));
199 
200  m_created = true;
201  }
202 
203 
204 public:
205 
213  SparseMatrix(size_t N1, size_t N2, size_t n_row_local)
214  :g_row(N1),g_col(N2),l_row(n_row_local),l_col(n_row_local)
215  {
216  PETSC_SAFE_CALL(MatCreate(PETSC_COMM_WORLD,&mat));
217  PETSC_SAFE_CALL(MatSetType(mat,MATMPIAIJ));
218  PETSC_SAFE_CALL(MatSetSizes(mat,n_row_local,n_row_local,N1,N2));
219 
220  Vcluster & v_cl = create_vcluster();
221 
222  openfpm::vector<size_t> vn_row_local;
223  v_cl.allGather(l_row,vn_row_local);
224  v_cl.execute();
225 
226  // Calculate the starting row for this processor
227 
228  start_row = 0;
229  for (size_t i = 0 ; i < v_cl.getProcessUnitID() ; i++)
230  start_row += vn_row_local.get(i);
231  }
232 
237  :g_row(0),g_col(0),l_row(0l),l_col(0),start_row(0)
238  {
239  PETSC_SAFE_CALL(MatCreate(PETSC_COMM_WORLD,&mat));
240  PETSC_SAFE_CALL(MatSetType(mat,MATMPIAIJ));
241  }
242 
243  ~SparseMatrix()
244  {
245  // Destroy the matrix
246  if (is_openfpm_init() == true)
247  {PETSC_SAFE_CALL(MatDestroy(&mat));}
248  }
249 
258  {
259  m_created = false;
260 
261  return this->trpl;
262  }
263 
269  const Mat & getMat() const
270  {
271  if (m_created == false)
272  {fill_petsc();}
273 
274  return mat;
275  }
276 
282  Mat & getMat()
283  {
284  if (m_created == false)
285  {fill_petsc();}
286 
287  return mat;
288  }
289 
298  void resize(size_t row, size_t col, size_t l_row, size_t l_col)
299  {
300  this->g_row = row;
301  this->g_col = col;
302 
303  this->l_row = l_row;
304  this->l_col = l_col;
305 
306  PETSC_SAFE_CALL(MatSetSizes(mat,l_row,l_col,g_row,g_col));
307 
308  Vcluster & v_cl = create_vcluster();
309 
310  openfpm::vector<size_t> vn_row_local;
311  v_cl.allGather(l_row,vn_row_local);
312  v_cl.execute();
313 
314  // Calculate the starting row for this processor
315 
316  start_row = 0;
317  for (size_t i = 0 ; i < v_cl.getProcessUnitID() ; i++)
318  start_row += vn_row_local.get(i);
319  }
320 
328  T operator()(id_t i, id_t j)
329  {
330  T v;
331 
332  MatGetValues(mat,1,&i,1,&j,&v);
333 
334  return v;
335  }
336 
345  T getValue(size_t r, size_t c)
346  {
347  for (size_t i = 0 ; i < trpl.size() ; i++)
348  {
349  if (r == (size_t)trpl.get(i).row() && c == (size_t)trpl.get(i).col())
350  return trpl.get(i).value();
351  }
352 
353  return 0;
354  }
355 };
356 
357 
358 #endif /* OPENFPM_NUMERICS_SRC_MATRIX_SPARSEMATRIX_PETSC_HPP_ */
size_t g_row
Number of matrix row (global)
boost::mpl::int_< PETSC_BASE > triplet_impl
Triplet implementation id.
size_t getProcessUnitID()
Get the process unit id.
void execute()
Execute all the requests.
PetscScalar val_
Value of the Matrix.
T getValue(size_t r, size_t c)
Get the value from triplet.
It store the non zero elements of the matrix.
void fill_petsc()
Fill the petsc Matrix.
Mat & getMat()
Get the Petsc Matrix object.
SparseMatrix()
Create an empty Matrix.
PetscInt & row()
Return the row of the triplet.
openfpm::vector< triplet_type > trpl
Triplets of the matrix.
const Mat & getMat() const
Get the Patsc Matrix object.
Implementation of VCluster class.
Definition: VCluster.hpp:36
triplet< T, PETSC_BASE > triplet_type
Triplet type.
PetscInt & col()
Return the colum of the triplet.
size_t start_row
starting row for this processor
Sparse Matrix implementation.
T operator()(id_t i, id_t j)
Get the row i and the colum j of the Matrix.
triplet(long int i, long int j, T val)
Constructor from row, colum and value.
void resize(size_t row, size_t col, size_t l_row, size_t l_col)
Resize the Sparse Matrix.
SparseMatrix(size_t N1, size_t N2, size_t n_row_local)
Create an empty Matrix.
openfpm::vector< triplet_type > & getMatrixTriplets()
Get the Matrix triplets buffer.
PetscInt col_
Colum of the sparse matrix.
openfpm::vector< PetscInt > d_nnz
PETSC d_nnz.
size_t l_row
Number of matrix row (local)
openfpm::vector< PetscInt > o_nnz
PETSC o_nnz.
openfpm::vector< PetscInt > cols
temporary list of colums
It store one non-zero element in the sparse matrix.
PetscInt row_
Row of the sparse matrix.
PetscScalar & value()
Return the value of the triplet.
size_t l_col
Number of matrix colums (local)
size_t g_col
Number of matrix colums (global)
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:61
bool allGather(T &send, openfpm::vector< T, Mem, gr > &v)
Gather the data from all processors.
openfpm::vector< PetscScalar > vals
temporary list of values