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.
csr_matrix.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 #if !defined(KRATOS_CSR_MATRIX_H_INCLUDED )
14 #define KRATOS_CSR_MATRIX_H_INCLUDED
15 
16 
17 // System includes
18 #include <iostream>
19 #include <limits>
20 #include <span/span.hpp>
21 
27 #include "includes/key_hash.h"
29 
30 // Project includes
31 #include "includes/define.h"
32 
33 namespace Kratos
34 {
37 
40 
44 
48 
52 
56 
58 template< class TDataType=double, class TIndexType=std::size_t>
59 class CsrMatrix final
60 {
61 public:
64  typedef TIndexType IndexType;
65  typedef std::unordered_map<std::pair<IndexType, IndexType>,
66  double,
70 
73 
77  CsrMatrix() //needs to be public, since one could use the low level API to construc the CSR matrix
78  {
79  mpComm = &ParallelEnvironment::GetDataCommunicator("Serial");
80  }
81 
82  CsrMatrix(const DataCommunicator& rComm) //needs to be public, since one could use the low level API to construc the CSR matrix
83  {
84  if(rComm.IsDistributed())
85  KRATOS_ERROR << "Attempting to construct a serial CsrMatrix with a distributed communicator" << std::endl;
86 
87  mpComm = &rComm;
88  }
89 
90 
92  template<class TGraphType>
93  CsrMatrix(const TGraphType& rSparseGraph)
94  {
95  mpComm = rSparseGraph.pGetComm();
96  TIndexType row_data_size=0;
97  TIndexType col_data_size=0;
98  rSparseGraph.ExportCSRArrays(mpRowIndicesData,row_data_size,mpColIndicesData, col_data_size);
99  mRowIndices = Kratos::span<TIndexType>(mpRowIndicesData, row_data_size); //no copying of data happening here
100  mColIndices = Kratos::span<TIndexType>(mpColIndicesData, col_data_size);
101 
102  mNrows = size1();
103 
104  ComputeColSize();
105 
106  //initialize mValuesVector to zero
107  ResizeValueData(mColIndices.size());
108  SetValue(0.0);
109  }
110 
111  CsrMatrix(const MatrixMapType& matrix_map)
112  {
114  for(const auto& item : matrix_map){
115  IndexType I = item.first.first;
116  IndexType J = item.first.second;
117  Agraph.AddEntry(I,J);
118  }
119  Agraph.Finalize();
120 
121  this->BeginAssemble();
122  for(const auto item : matrix_map){
123  IndexType I = item.first.first;
124  IndexType J = item.first.second;
125  TDataType value = item.second;
126  this->AssembleEntry(value,I,J);
127  }
128  this->FinalizeAssemble();
129  }
130 
131  explicit CsrMatrix(const CsrMatrix<TDataType,TIndexType>& rOtherMatrix)
132  {
133  mpComm = rOtherMatrix.mpComm;
134  ResizeIndex1Data(rOtherMatrix.mRowIndices.size());
135  ResizeIndex2Data(rOtherMatrix.mColIndices.size());
136  ResizeValueData(rOtherMatrix.mValuesVector.size());
137 
138  mNrows = rOtherMatrix.mNrows;
139  mNcols = rOtherMatrix.mNcols;
140 
141  IndexPartition<IndexType>(mRowIndices.size()).for_each( [&](IndexType i)
142  {
143  mRowIndices[i] = rOtherMatrix.mRowIndices[i];
144  });
145 
146  IndexPartition<IndexType>(mColIndices.size()).for_each( [&](IndexType i)
147  {
148  mColIndices[i] = rOtherMatrix.mColIndices[i];
149  });
150 
151  IndexPartition<IndexType>(mValuesVector.size()).for_each( [&](IndexType i)
152  {
153  mValuesVector[i] = rOtherMatrix.mValuesVector[i];
154  });
155  }
156 
157  //move constructor
159  {
160  mIsOwnerOfData=rOtherMatrix.mIsOwnerOfData;
161  rOtherMatrix.mIsOwnerOfData=false;
162 
163  //swap the pointers to take owership of data
164  mpRowIndicesData = rOtherMatrix.mpRowIndicesData;
165  mpColIndicesData = rOtherMatrix.mpColIndicesData;
166  mpValuesVectorData = rOtherMatrix.mpValuesVectorData;
167 
168  //here we assign the span
169  mRowIndices = rOtherMatrix.mRowIndices;
170  mColIndices = rOtherMatrix.mColIndices;
171  mValuesVector = rOtherMatrix.mValuesVector;
172 
173  mNrows = rOtherMatrix.mNrows;
174  mNcols = rOtherMatrix.mNcols;
175 
176  }
177 
180  {
181  AssignIndex1Data(nullptr,0);
182  AssignIndex2Data(nullptr,0);
183  AssignValueData(nullptr,0);
184  }
185 
187  CsrMatrix& operator=(CsrMatrix const& rOtherMatrix) = delete; //i really think this should not be allowed, too risky
188 
189  //move assignement operator
190  CsrMatrix& operator=(CsrMatrix&& rOtherMatrix)
191  {
192  mpComm = rOtherMatrix.mpComm;
193  mIsOwnerOfData=rOtherMatrix.mIsOwnerOfData;
194  rOtherMatrix.mIsOwnerOfData=false;
195 
196  //swap the pointers to take owership of data
197  mpRowIndicesData = rOtherMatrix.mpRowIndicesData;
198  mpColIndicesData = rOtherMatrix.mpColIndicesData;
199  mpValuesVectorData = rOtherMatrix.mpValuesVectorData;
200 
201  //here we assign the span
202  mRowIndices = rOtherMatrix.mRowIndices;
203  mColIndices = rOtherMatrix.mColIndices;
204  mValuesVector = rOtherMatrix.mValuesVector;
205 
206  mNrows = rOtherMatrix.mNrows;
207  mNcols = rOtherMatrix.mNcols;
208  return *this;
209  }
213  void Clear()
214  {
215  AssignIndex1Data(nullptr,0);
216  AssignIndex2Data(nullptr,0);
217  AssignValueData(nullptr,0);
218  mNrows=0;
219  mNcols=0;
220  }
221 
222  const DataCommunicator& GetComm() const
223  {
224  return *mpComm;
225  }
226 
227  const DataCommunicator* pGetComm() const
228  {
229  return mpComm;
230  }
231 
232  void SetValue(const TDataType value)
233  {
234  IndexPartition<IndexType>(mValuesVector.size()).for_each([&](IndexType i)
235  {
236  mValuesVector[i] = value;
237  });
238  }
239 
240  IndexType size1() const
241  {
242  return mRowIndices.size()-1;
243  }
244 
245  IndexType size2() const
246  {
247  return mNcols;
248  }
249 
250  inline IndexType nnz() const
251  {
252  return index2_data().size();
253  }
254 
255  bool IsOwnerOfData() const
256  {
257  return mIsOwnerOfData;
258  }
259 
260  void SetIsOwnerOfData(bool IsOwner)
261  {
262  mIsOwnerOfData = IsOwner;
263  }
264 
265  inline Kratos::span<IndexType>& index1_data()
266  {
267  return mRowIndices;
268  }
269  inline Kratos::span<IndexType>& index2_data()
270  {
271  return mColIndices;
272  }
273  inline Kratos::span<TDataType>& value_data()
274  {
275  return mValuesVector;
276  }
277 
278  inline const Kratos::span<IndexType>& index1_data() const
279  {
280  return mRowIndices;
281  }
282  inline const Kratos::span<IndexType>& index2_data() const
283  {
284  return mColIndices;
285  }
286  inline const Kratos::span<TDataType>& value_data() const
287  {
288  return mValuesVector;
289  }
290 
291  void SetColSize(IndexType Ncols)
292  {
293  mNcols = Ncols;
294  }
295 
296  void SetRowSize(IndexType Nrows)
297  {
298  mNrows = Nrows;
299  }
300 
302  {
303  //compute the max id
304  IndexType max_col = IndexPartition<IndexType>(mColIndices.size()).template for_each< MaxReduction<double> >([&](IndexType i)
305  {
306  return mColIndices[i];
307  });
308 
309  mNcols = max_col+1; //note that we must add 1 to the greatest column id
310  }
311 
312  void AssignIndex1Data(TIndexType* pExternalData, TIndexType DataSize)
313  {
314  if(IsOwnerOfData() && mpRowIndicesData != nullptr)
315  delete [] mpRowIndicesData;
316  mpRowIndicesData = pExternalData;
317  if(DataSize!=0)
318  mRowIndices = Kratos::span<TIndexType>(mpRowIndicesData, DataSize);
319  else
320  mRowIndices = Kratos::span<TIndexType>();
321  }
322 
323  void AssignIndex2Data(TIndexType* pExternalData, TIndexType DataSize)
324  {
325  if(IsOwnerOfData() && mpColIndicesData != nullptr)
326  delete [] mpColIndicesData;
327  mpColIndicesData = pExternalData;
328  if(DataSize!=0)
329  mColIndices = Kratos::span<TIndexType>(mpColIndicesData, DataSize);
330  else
331  mColIndices = Kratos::span<TIndexType>();
332  }
333 
334  void AssignValueData(TDataType* pExternalData, TIndexType DataSize)
335  {
336  if(IsOwnerOfData() && mpValuesVectorData != nullptr)
337  delete [] mpValuesVectorData;
338  mpValuesVectorData = pExternalData;
339  if(DataSize!=0)
340  mValuesVector = Kratos::span<TDataType>(mpValuesVectorData, DataSize);
341  else
342  mValuesVector = Kratos::span<TDataType>();
343  }
344 
345  void ResizeIndex1Data(TIndexType DataSize)
346  {
347  KRATOS_ERROR_IF_NOT(IsOwnerOfData()) << "ResizeIndex1Data is only allowed if the data are locally owned" << std::endl;
348  if(mpRowIndicesData != nullptr)
349  delete [] mpRowIndicesData;
350  mpRowIndicesData = new TIndexType[DataSize];
351  mRowIndices = Kratos::span<TIndexType>(mpRowIndicesData, DataSize);
352  }
353 
354  void ResizeIndex2Data(TIndexType DataSize)
355  {
356  KRATOS_ERROR_IF_NOT(IsOwnerOfData()) << "ResizeIndex2Data is only allowed if the data are locally owned" << std::endl;
357  if(mpColIndicesData != nullptr)
358  delete [] mpColIndicesData;
359  mpColIndicesData = new TIndexType[DataSize];
360  mColIndices = Kratos::span<TIndexType>(mpColIndicesData, DataSize);
361  }
362 
363  void ResizeValueData(TIndexType DataSize)
364  {
365  KRATOS_ERROR_IF_NOT(IsOwnerOfData()) << "ResizeValueData is only allowed if the data are locally owned" << std::endl;
366  if(mpValuesVectorData != nullptr)
367  delete [] mpValuesVectorData;
368  mpValuesVectorData = new TDataType[DataSize];
369  mValuesVector = Kratos::span<TDataType>(mpValuesVectorData, DataSize);
370  }
371 
372 
373 
375  {
376  IndexType max_col = 0;
377  for(IndexType i=0; i<mColIndices.size(); ++i)
378  max_col = std::max(max_col,mColIndices[i]);
379  if(max_col > mNcols)
380  KRATOS_ERROR << " max column index : " << max_col << " exceeds mNcols :" << mNcols << std::endl;
381  }
382 
384  {
385  const IndexType row_begin = index1_data()[I];
386  const IndexType row_end = index1_data()[I+1];
387  IndexType k = BinarySearch(index2_data(), row_begin, row_end, J);
388  KRATOS_DEBUG_ERROR_IF(k==std::numeric_limits<IndexType>::max()) << "local indices I,J : " << I << " " << J << " not found in matrix" << std::endl;
389  return value_data()[k];
390  }
391 
392  const TDataType& operator()(IndexType I, IndexType J) const
393  {
394  const IndexType row_begin = index1_data()[I];
395  const IndexType row_end = index1_data()[I+1];
396  IndexType k = BinarySearch(index2_data(), row_begin, row_end, J);
397  KRATOS_DEBUG_ERROR_IF(k==std::numeric_limits<IndexType>::max()) << "local indices I,J : " << I << " " << J << " not found in matrix" << std::endl;
398  return value_data()[k];
399  }
400 
401  bool Has(IndexType I, IndexType J) const
402  {
403  const IndexType row_begin = index1_data()[I];
404  const IndexType row_end = index1_data()[I+1];
405  IndexType k = BinarySearch(index2_data(), row_begin, row_end, J);
407  }
408 
409  // y += A*x -- where A is *this
410  template<class TInputVectorType, class TOutputVectorType>
411  void SpMV(const TInputVectorType& x, TOutputVectorType& y) const
412  {
413  KRATOS_ERROR_IF(size1() != y.size() ) << "SpMV: mismatch between row sizes : " << size1() << " and destination vector size " << y.size() << std::endl;
414  KRATOS_ERROR_IF(size2() != x.size() ) << "SpmV: mismatch between col sizes : " << size2() << " and input vector size " << x.size() << std::endl;
415  if(nnz() != 0)
416  {
418  {
419  IndexType row_begin = index1_data()[i];
420  IndexType row_end = index1_data()[i+1];
421  for(IndexType k = row_begin; k < row_end; ++k)
422  {
423  IndexType col = index2_data()[k];
424  y(i) += value_data()[k] * x(col);
425  }
426  });
427  }
428  }
429 
430  //y = alpha*y + beta*A*x
431  template<class TInputVectorType, class TOutputVectorType>
432  void SpMV(const TDataType alpha,
433  const TInputVectorType& x,
434  const TDataType beta,
435  TOutputVectorType& y) const
436  {
437  KRATOS_ERROR_IF(size1() != y.size() ) << "SpMV: mismatch between matrix sizes : " << size1() << " " <<size2() << " and destination vector size " << y.size() << std::endl;
438  KRATOS_ERROR_IF(size2() != x.size() ) << "SpmV: mismatch between matrix sizes : " << size1() << " " <<size2() << " and input vector size " << x.size() << std::endl;
440  {
441  IndexType row_begin = index1_data()[i];
442  IndexType row_end = index1_data()[i+1];
443  TDataType aux = TDataType();
444  for(IndexType k = row_begin; k < row_end; ++k)
445  {
446  IndexType col = index2_data()[k];
447  aux += value_data()[k] * x(col);
448  }
449  y(i) = beta*y(i) + alpha*aux;
450  });
451  }
452 
453  // y += A^t*x -- where A is *this
454  template<class TInputVectorType, class TOutputVectorType>
455  void TransposeSpMV(const TInputVectorType& x, TOutputVectorType& y) const
456  {
457  KRATOS_ERROR_IF(size2() != y.size() ) << "TransposeSpMV: mismatch between transpose matrix sizes : " << size2() << " " <<size1() << " and destination vector size " << y.size() << std::endl;
458  KRATOS_ERROR_IF(size1() != x.size() ) << "TransposeSpMV: mismatch between transpose matrix sizes : " << size2() << " " <<size1() << " and input vector size " << x.size() << std::endl;
460  {
461  IndexType row_begin = index1_data()[i];
462  IndexType row_end = index1_data()[i+1];
463  for(IndexType k = row_begin; k < row_end; ++k)
464  {
465  IndexType j = index2_data()[k];
466  AtomicAdd(y(j), value_data()[k] * x(i) );
467  }
468  });
469  }
470 
471  //y = alpha*y + beta*A^t*x
472  template<class TInputVectorType, class TOutputVectorType>
473  void TransposeSpMV(const TDataType alpha,
474  const TInputVectorType& x,
475  const TDataType beta,
476  TOutputVectorType& y) const
477  {
478  KRATOS_ERROR_IF(size2() != y.size() ) << "TransposeSpMV: mismatch between transpose matrix sizes : " << size2() << " " <<size1() << " and destination vector size " << y.size() << std::endl;
479  KRATOS_ERROR_IF(size1() != x.size() ) << "TransposeSpMV: mismatch between transpose matrix sizes : " << size2() << " " <<size1() << " and input vector size " << x.size() << std::endl;
480  y *= beta;
482  {
483  IndexType row_begin = index1_data()[i];
484  IndexType row_end = index1_data()[i+1];
485  TDataType aux = alpha*x(i);
486  for(IndexType k = row_begin; k < row_end; ++k)
487  {
488  IndexType j = index2_data()[k];
489  AtomicAdd(y(j), value_data()[k] * x(i) );
490  }
491  });
492  }
493 
494  TDataType NormFrobenius() const
495  {
496  auto sum2 = IndexPartition<TIndexType>(this->value_data().size()).template for_each< SumReduction<TDataType> >( [this](TIndexType i)
497  {
498  return std::pow(this->value_data()[i],2);
499  });
500  return std::sqrt(sum2);
501  }
502 
506  //TODO
507  //+=
508  //-=
509  //+
510  //-
511  //*
512 
514  {
515  ResizeIndex1Data(NRows+1);
516 
517  if(NRows > 0)
518  index1_data()[0] = 0;
519 
522  mNrows = NRows;
523  }
524 
526  {
527  MatrixMapType value_map;
528  for(unsigned int i=0; i<size1(); ++i)
529  {
530  IndexType row_begin = index1_data()[i];
531  IndexType row_end = index1_data()[i+1];
532  for(IndexType k = row_begin; k < row_end; ++k)
533  {
534  IndexType j = index2_data()[k];
535  TDataType v = value_data()[k];
536  value_map[ {i,j}] = v;
537  }
538  }
539  return value_map;
540  }
541 
542  void BeginAssemble() {} //the SMP version does nothing. This function is there to be implemented in the MPI case
543 
544  void FinalizeAssemble() {} //the SMP version does nothing. This function is there to be implemented in the MPI case
545 
546 
547  template<class TMatrixType, class TIndexVectorType >
548  void Assemble(
549  const TMatrixType& rMatrixInput,
550  const TIndexVectorType& EquationId
551  )
552  {
553  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size1() != EquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
554  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size2() != EquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
555 
556  const unsigned int local_size = rMatrixInput.size1();
557 
558  for (unsigned int i_local = 0; i_local < local_size; ++i_local) {
559  const IndexType I = EquationId[i_local];
560  const IndexType row_begin = index1_data()[I];
561  const IndexType row_end = index1_data()[I+1];
562 
563  //find first entry (note that we know it exists since local_size > 0)
564  IndexType J = EquationId[0];
565  IndexType k = BinarySearch(index2_data(), row_begin, row_end, EquationId[0]);
566  IndexType lastJ = J;
567 
568  AtomicAdd(value_data()[k], rMatrixInput(i_local,0));
569 
570  //now find other entries. note that we assume that it is probably that next entries immediately follow in the ordering
571  for(unsigned int j_local=1; j_local<local_size; ++j_local) {
572  J = EquationId[j_local];
573 
574  if(k+1<row_end && index2_data()[k+1] == J) {
575  k = k+1;
576  } else if(J > lastJ) { //note that the case k+2 >= index2_data().size() should be impossible
577  k = BinarySearch(index2_data(), k+2, row_end, J);
578  } else if(J < lastJ) {
579  k = BinarySearch(index2_data(), row_begin, k-1, J);
580  }
581  //the last missing case is J == lastJ, which should never happen in FEM. If that happens we can reuse k
582 
583  AtomicAdd(value_data()[k], rMatrixInput(i_local,j_local));
584 
585  lastJ = J;
586  }
587  }
588  }
589 
590  template<class TMatrixType, class TIndexVectorType >
591  void Assemble(
592  const TMatrixType& rMatrixInput,
593  const TIndexVectorType& RowEquationId,
594  const TIndexVectorType& ColEquationId
595  )
596  {
597  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size1() != RowEquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
598  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size2() != ColEquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
599 
600  const unsigned int local_size = rMatrixInput.size1();
601  const unsigned int col_size = rMatrixInput.size2();
602 
603  for (unsigned int i_local = 0; i_local < local_size; ++i_local) {
604  const IndexType I = RowEquationId[i_local];
605  const IndexType row_begin = index1_data()[I];
606  const IndexType row_end = index1_data()[I+1];
607 
608  //find first entry (note that we know it exists since local_size > 0)
609  IndexType J = ColEquationId[0];
610  IndexType k = BinarySearch(index2_data(), row_begin, row_end, J);
611  IndexType lastJ = J;
612 
613  AtomicAdd(value_data()[k], rMatrixInput(i_local,0));
614 
615  //now find other entries. note that we assume that it is probably that next entries immediately follow in the ordering
616  for(unsigned int j_local=1; j_local<col_size; ++j_local) {
617  J = ColEquationId[j_local];
618 
619  if(k+1<row_end && index2_data()[k+1] == J) {
620  k = k+1;
621  } else if(J > lastJ) { //note that the case k+2 >= index2_data().size() should be impossible
622  k = BinarySearch(index2_data(), k+2, row_end, J);
623  } else if(J < lastJ) {
624  k = BinarySearch(index2_data(), row_begin, k-1, J);
625  }
626  //the last case is J == lastJ, which should never happen in FEM. If that happens we can reuse k
627  AtomicAdd(value_data()[k], rMatrixInput(i_local,j_local));
628 
629  lastJ = J;
630  }
631  }
632  }
633 
634  void AssembleEntry(const TDataType Value, const IndexType GlobalI, const IndexType GlobalJ)
635  {
636  IndexType k = BinarySearch(index2_data(), index1_data()[GlobalI], index1_data()[GlobalI+1], GlobalJ);
637  AtomicAdd(value_data()[k], Value);
638  }
639 
640  //TODO
641  // LeftScaling
642  // RightScaling
643  // SymmetricScaling
644 
645  template<class TVectorType1, class TVectorType2=TVectorType1>
646  void ApplyHomogeneousDirichlet(const TVectorType1& rFreeDofsVector,
647  const TDataType DiagonalValue,
648  TVectorType2& rRHS)
649  {
650  KRATOS_ERROR_IF(size1() != rFreeDofsVector.size() ) << "ApplyDirichlet: mismatch between row sizes : " << size1()
651  << " and free_dofs_vector size " << rFreeDofsVector.size() << std::endl;
652  KRATOS_ERROR_IF(size2() != rFreeDofsVector.size() ) << "ApplyDirichlet: mismatch between col sizes : " << size2()
653  << " and free_dofs_vector size " << rFreeDofsVector.size() << std::endl;
654 
655  if(nnz() != 0) {
657  //set to zero the relevant row in the RHS
658  rRHS[i] *= rFreeDofsVector[i];
659 
660  const IndexType row_begin = index1_data()[i];
661  const IndexType row_end = index1_data()[i+1];
662  if(std::abs(rFreeDofsVector[i]-1.0) < 1e-14) { //row corresponding to free dofs NOTE that we check if it is approx zero TODO: Epsilon?
663  for(IndexType k = row_begin; k < row_end; ++k) {
664  IndexType col = index2_data()[k];
665  value_data()[k] *= rFreeDofsVector[col]; //note that here we assume that rFreeDofsVector is either 0 or 1
666  }
667  } else { //row corresponding to a fixed dof
668  for(IndexType k = row_begin; k < row_end; ++k) {
669  IndexType col = index2_data()[k];
670  if(col!=i) //out-diagonal term
671  value_data()[k] = TDataType();
672  else
673  value_data()[k] = DiagonalValue;
674  }
675  }
676  });
677  }
678  }
679 
680  //TODO
681  //NormFrobenius
682 
686 
687 
691 
692 
696 
698  std::string Info() const
699  {
700  std::stringstream buffer;
701  buffer << "CsrMatrix" ;
702  return buffer.str();
703  }
704 
706  void PrintInfo(std::ostream& rOStream) const
707  {
708  rOStream << "CsrMatrix" << std::endl;
709  PrintData(rOStream);
710  }
711 
713  void PrintData(std::ostream& rOStream) const
714  {
715  rOStream << "size1 : " << size1() <<std::endl;
716  rOStream << "size2 : " << size2() <<std::endl;
717  rOStream << "nnz : " << nnz() <<std::endl;
718  rOStream << "index1_data : " << std::endl;
719  for(auto item : index1_data())
720  rOStream << item << ",";
721  rOStream << std::endl;
722  rOStream << "index2_data : " << std::endl;
723  for(auto item : index2_data())
724  rOStream << item << ",";
725  rOStream << std::endl;
726  rOStream << "value_data : " << std::endl;
727  for(auto item : value_data())
728  rOStream << item << ",";
729  rOStream << std::endl;
730  }
731 
735 
736 
738 
739 protected:
742 
743 
747 
748 
752  // A non-recursive binary search function. It returns
753  // location of x in given array arr[l..r] is present,
754  // otherwise std::dec << std::numeric_limits<IndexType>::max()
755  template< class TVectorType >
756  inline IndexType BinarySearch(const TVectorType& arr,
757  IndexType l, IndexType r, IndexType x) const
758  {
759  while (l <= r)
760  {
761  int m = l + (r - l) / 2;
762 
763  // Check if x is present at mid
764  if (arr[m] == x)
765  return m;
766 
767  // If x greater, ignore left half
768  if (arr[m] < x)
769  l = m + 1;
770 
771  // If x is smaller, ignore right half
772  else
773  r = m - 1;
774  }
775 
776  // if we reach here, then element was not present
778  }
779 
783 
784 
788 
789 
793 
794 
798 
799 
801 
802 private:
805 
806 
810  const DataCommunicator* mpComm;
811  bool mIsOwnerOfData = true;
812  IndexType* mpRowIndicesData = nullptr;
813  IndexType* mpColIndicesData = nullptr;
814  TDataType* mpValuesVectorData = nullptr;
815  Kratos::span<IndexType> mRowIndices;
816  Kratos::span<IndexType> mColIndices;
817  Kratos::span<TDataType> mValuesVector;
818  IndexType mNrows=0;
819  IndexType mNcols=0;
820 
824  friend class Serializer;
825 
826  void save(Serializer& rSerializer) const
827  {
828  rSerializer.save("IsOwnerOfData",mIsOwnerOfData);
829 
830  rSerializer.save("nrows",mRowIndices.size());
831  for(IndexType i=0; i<mRowIndices.size(); ++i)
832  rSerializer.save("i",mRowIndices[i]);
833 
834  rSerializer.save("cols_size",mColIndices.size());
835  for(IndexType i=0; i<mColIndices.size(); ++i)
836  rSerializer.save("i",mColIndices[i]);
837 
838  rSerializer.save("val_size",mValuesVector.size());
839  for(IndexType i=0; i<mValuesVector.size(); ++i)
840  rSerializer.save("d",mValuesVector[i]);
841 
842  rSerializer.save("Nrow",mNrows);
843  rSerializer.save("Ncol",mNcols);
844  }
845 
846  void load(Serializer& rSerializer)
847  {
848  rSerializer.load("IsOwnerOfData",mIsOwnerOfData);
849  if(mIsOwnerOfData == false)
850  {
851  mIsOwnerOfData=true;
852  KRATOS_WARNING("csr_matrix becomes owner of a copy of data after serialization");
853  }
854 
855  IndexType rows_size;
856  rSerializer.load("nrows",rows_size);
857  mpRowIndicesData = new TIndexType[rows_size];
858  mRowIndices = Kratos::span<TIndexType>(mpRowIndicesData, rows_size);
859  for(IndexType i=0; i<rows_size; ++i)
860  rSerializer.load("i",mRowIndices[i]);
861 
862  IndexType cols_size;
863  rSerializer.load("cols_size",cols_size);
864  mpColIndicesData = new TIndexType[cols_size];
865  mColIndices = Kratos::span<TIndexType>(mpRowIndicesData, cols_size);
866  for(IndexType i=0; i<mColIndices.size(); ++i)
867  rSerializer.load("i",mColIndices[i]);
868 
869  IndexType vals_size;
870  rSerializer.load("val_size",vals_size);
871  mpValuesVectorData = new TDataType[vals_size];
872  mValuesVector = Kratos::span<TDataType>(mpValuesVectorData, vals_size);
873  for(IndexType i=0; i<mValuesVector.size(); ++i)
874  rSerializer.load("d",mValuesVector[i]);
875 
876  rSerializer.load("Nrow",mNrows);
877  rSerializer.load("Ncol",mNcols);
878  }
879 
880 
884 
885 
889 
890 
894 
895 
899 
900 
901 
903 
904 }; // Class CsrMatrix
905 
907 
910 
911 
915 
916 
918 template< class TDataType>
919 inline std::istream& operator >> (std::istream& rIStream,
920  CsrMatrix<TDataType>& rThis)
921 {
922  return rIStream;
923 }
924 
926 template< class TDataType>
927 inline std::ostream& operator << (std::ostream& rOStream,
928  const CsrMatrix<TDataType>& rThis)
929 {
930  rThis.PrintInfo(rOStream);
931  rOStream << std::endl;
932  rThis.PrintData(rOStream);
933 
934  return rOStream;
935 }
937 
939 
940 } // namespace Kratos.
941 
942 #endif // KRATOS_CSR_MATRIX_H_INCLUDED defined
This class implements "serial" CSR matrix, including capabilities for FEM assembly.
Definition: csr_matrix.h:60
IndexType BinarySearch(const TVectorType &arr, IndexType l, IndexType r, IndexType x) const
Definition: csr_matrix.h:756
Kratos::span< TDataType > & value_data()
Definition: csr_matrix.h:273
CsrMatrix(const MatrixMapType &matrix_map)
Definition: csr_matrix.h:111
void AssignValueData(TDataType *pExternalData, TIndexType DataSize)
Definition: csr_matrix.h:334
void BeginAssemble()
Definition: csr_matrix.h:542
void CheckColSize()
Definition: csr_matrix.h:374
void TransposeSpMV(const TDataType alpha, const TInputVectorType &x, const TDataType beta, TOutputVectorType &y) const
Definition: csr_matrix.h:473
IndexType nnz() const
Definition: csr_matrix.h:250
bool IsOwnerOfData() const
Definition: csr_matrix.h:255
IndexType size1() const
Definition: csr_matrix.h:240
IndexType size2() const
Definition: csr_matrix.h:245
CsrMatrix(const DataCommunicator &rComm)
Definition: csr_matrix.h:82
const DataCommunicator & GetComm() const
Definition: csr_matrix.h:222
CsrMatrix()
Definition: csr_matrix.h:77
void SetRowSize(IndexType Nrows)
Definition: csr_matrix.h:296
TDataType & operator()(IndexType I, IndexType J)
Definition: csr_matrix.h:383
void ComputeColSize()
Definition: csr_matrix.h:301
const Kratos::span< TDataType > & value_data() const
Definition: csr_matrix.h:286
void SpMV(const TDataType alpha, const TInputVectorType &x, const TDataType beta, TOutputVectorType &y) const
Definition: csr_matrix.h:432
void SetValue(const TDataType value)
Definition: csr_matrix.h:232
void SpMV(const TInputVectorType &x, TOutputVectorType &y) const
Definition: csr_matrix.h:411
void AssignIndex1Data(TIndexType *pExternalData, TIndexType DataSize)
Definition: csr_matrix.h:312
void Assemble(const TMatrixType &rMatrixInput, const TIndexVectorType &RowEquationId, const TIndexVectorType &ColEquationId)
Definition: csr_matrix.h:591
CsrMatrix & operator=(CsrMatrix const &rOtherMatrix)=delete
Assignment operator.
void AssembleEntry(const TDataType Value, const IndexType GlobalI, const IndexType GlobalJ)
Definition: csr_matrix.h:634
const Kratos::span< IndexType > & index1_data() const
Definition: csr_matrix.h:278
void Clear()
Definition: csr_matrix.h:213
const DataCommunicator * pGetComm() const
Definition: csr_matrix.h:227
TIndexType IndexType
Definition: csr_matrix.h:64
void FinalizeAssemble()
Definition: csr_matrix.h:544
void SetColSize(IndexType Ncols)
Definition: csr_matrix.h:291
CsrMatrix(const TGraphType &rSparseGraph)
constructor.
Definition: csr_matrix.h:93
void ResizeValueData(TIndexType DataSize)
Definition: csr_matrix.h:363
TDataType NormFrobenius() const
Definition: csr_matrix.h:494
void Assemble(const TMatrixType &rMatrixInput, const TIndexVectorType &EquationId)
Definition: csr_matrix.h:548
void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: csr_matrix.h:713
void TransposeSpMV(const TInputVectorType &x, TOutputVectorType &y) const
Definition: csr_matrix.h:455
Kratos::span< IndexType > & index2_data()
Definition: csr_matrix.h:269
std::unordered_map< std::pair< IndexType, IndexType >, double, PairHasher< IndexType, IndexType >, PairComparor< IndexType, IndexType > > MatrixMapType
Definition: csr_matrix.h:69
const TDataType & operator()(IndexType I, IndexType J) const
Definition: csr_matrix.h:392
bool Has(IndexType I, IndexType J) const
Definition: csr_matrix.h:401
CsrMatrix & operator=(CsrMatrix &&rOtherMatrix)
Definition: csr_matrix.h:190
KRATOS_CLASS_POINTER_DEFINITION(CsrMatrix)
Pointer definition of CsrMatrix.
CsrMatrix(CsrMatrix< TDataType, TIndexType > &&rOtherMatrix)
Definition: csr_matrix.h:158
void SetIsOwnerOfData(bool IsOwner)
Definition: csr_matrix.h:260
std::string Info() const
Turn back information as a string.
Definition: csr_matrix.h:698
void ApplyHomogeneousDirichlet(const TVectorType1 &rFreeDofsVector, const TDataType DiagonalValue, TVectorType2 &rRHS)
Definition: csr_matrix.h:646
void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: csr_matrix.h:706
void ResizeIndex2Data(TIndexType DataSize)
Definition: csr_matrix.h:354
void AssignIndex2Data(TIndexType *pExternalData, TIndexType DataSize)
Definition: csr_matrix.h:323
void reserve(IndexType NRows, IndexType nnz)
Definition: csr_matrix.h:513
Kratos::span< IndexType > & index1_data()
Definition: csr_matrix.h:265
void ResizeIndex1Data(TIndexType DataSize)
Definition: csr_matrix.h:345
const Kratos::span< IndexType > & index2_data() const
Definition: csr_matrix.h:282
CsrMatrix(const CsrMatrix< TDataType, TIndexType > &rOtherMatrix)
Definition: csr_matrix.h:131
~CsrMatrix()
Destructor.
Definition: csr_matrix.h:179
MatrixMapType ToMap() const
Definition: csr_matrix.h:525
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
virtual bool IsDistributed() const
Check whether this DataCommunicator is aware of parallelism.
Definition: data_communicator.h:606
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
static DataCommunicator & GetDataCommunicator(const std::string &rName)
Retrieve a registered DataCommunicator instance.
Definition: parallel_environment.cpp:26
The serialization consists in storing the state of an object into a storage format like data file or ...
Definition: serializer.h:123
void load(std::string const &rTag, TDataType &rObject)
Definition: serializer.h:207
void save(std::string const &rTag, std::array< TDataType, TDataSize > const &rObject)
Definition: serializer.h:545
Short class definition.
Definition: sparse_graph.h:66
void Finalize()
Definition: sparse_graph.h:204
void AddEntry(const IndexType RowIndex, const IndexType ColIndex)
Definition: sparse_graph.h:161
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
#define KRATOS_WARNING(label)
Definition: logger.h:265
static double max(double a, double b)
Definition: GeometryFunctions.h:79
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
void AtomicAdd(TDataType &target, const TDataType &value)
Definition: atomic_utilities.h:55
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
v
Definition: generate_convection_diffusion_explicit_element.py:114
alpha
Definition: generate_convection_diffusion_explicit_element.py:113
int local_size
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:17
def load(f)
Definition: ode_solve.py:307
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
x
Definition: sensitivityMatrix.py:49
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
This is a key comparer between two indexes pairs.
Definition: key_hash.h:432
This is a hasher for pairs.
Definition: key_hash.h:412