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.
distributed_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_DISTRIBUTED_CSR_MATRIX_H_INCLUDED )
14 #define KRATOS_DISTRIBUTED_CSR_MATRIX_H_INCLUDED
15 
16 
17 // System includes
18 #include <iostream>
19 
20 // External includes
21 
22 // Project includes
23 #include "includes/define.h"
24 #include "containers/csr_matrix.h"
28 #include "includes/key_hash.h"
30 
31 namespace Kratos
32 {
35 
38 
42 
46 
50 
54 
56 template< class TDataType=double, class TIndexType=std::size_t>
58 {
59 public:
62  typedef TIndexType IndexType;
63  typedef int MpiIndexType;
66 
69 
73 
74  //default constructor. To be used for low level operations
76  {}
77 
79  : mpComm(&rComm)
80  {}
81 
83  :
84  mpComm(&rSparseGraph.GetComm())
85  {
86  mpRowNumbering = Kratos::make_unique< DistributedNumbering<TIndexType> >( rSparseGraph.GetRowNumbering());
87 
88  //compute the columns size
89  TIndexType max_col_index = rSparseGraph.ComputeMaxGlobalColumnIndex();
90  TIndexType tot_col_size = max_col_index+1;
91 
92  //this ensures that diagonal blocks are square for square matrices
93  if (tot_col_size == mpRowNumbering->Size()) {
94  mpColNumbering = Kratos::make_unique<DistributedNumbering<TIndexType>>(*mpComm, mpRowNumbering->GetCpuBounds());
95  } else {
96  mpColNumbering = Kratos::make_unique<DistributedNumbering<TIndexType>>(*mpComm, tot_col_size, mpComm->Size());
97  }
98 
99  mOffDiagonalLocalIds.clear(); //this is the map that allows to transform from global_ids to local Ids for entries in the non_diag block
100 
101  //count entries in diagonal and off_diag blocks
102  const auto& local_graph = rSparseGraph.GetLocalGraph();
103  const TIndexType nlocal_rows = local_graph.Size();
104 
105  TIndexType diag_nnz = 0, offdiag_nnz=0;
106  for(const auto& entries : local_graph) {
107  for(const auto& global_j : entries) {
108  if(GetColNumbering().IsLocal(global_j)) {
109  diag_nnz += 1;
110  } else {
111  offdiag_nnz += 1;
112  mOffDiagonalLocalIds[global_j] = 0;
113  }
114  }
115  }
116 
117  //begin by computing local Ids for non diagonal block
118  TIndexType counter = 0;
119  for(auto& item : mOffDiagonalLocalIds)
120  item.second = counter++;
121 
122  mOffDiagonalGlobalIds.resize(mOffDiagonalLocalIds.size(), false);
123  counter = 0;
124  for(auto& item : mOffDiagonalLocalIds) {
125  TIndexType global_i = item.first;
126  mOffDiagonalGlobalIds[counter++] = global_i;
127  }
128 
129  //*******************************
130  //construct diagonal block
131  GetDiagonalBlock().reserve(nlocal_rows, diag_nnz);
132 
133  if(diag_nnz == 0) { //empty matrix
134  for(unsigned int i=0; i<nlocal_rows+1; ++i)
135  GetDiagonalBlock().index1_data()[i] = 0;
136  GetDiagonalBlock().SetColSize(GetColNumbering().LocalSize());
137  } else {
138  counter = 0;
139  for(const auto& entries : local_graph) {
140  unsigned int k = 0;
141  TIndexType row_begin = GetDiagonalBlock().index1_data()[counter];
142  for(auto global_j : entries) {
143  if(GetColNumbering().IsLocal(global_j)) {
144  TIndexType local_j = GetColNumbering().LocalId(global_j);
145  GetDiagonalBlock().index2_data()[row_begin+k] = local_j;
146  GetDiagonalBlock().value_data()[row_begin+k] = 0.0;
147  k++;
148  }
149  }
150  GetDiagonalBlock().index1_data()[counter+1] = row_begin + k;
151  counter++;
152  }
153 
154  GetDiagonalBlock().SetColSize(GetColNumbering().LocalSize());
155  }
156 #ifdef KRATOS_DEBUG
157  GetDiagonalBlock().CheckColSize();
158 #endif
159  //ensure columns are ordered
160  for(TIndexType i = 0; i<nlocal_rows; ++i) {
161  TIndexType row_begin = GetDiagonalBlock().index1_data()[i];
162  TIndexType row_end = GetDiagonalBlock().index1_data()[i+1];
163 
164  if(row_end - row_begin > 0)
165  std::sort(GetDiagonalBlock().index2_data().begin() + row_begin,GetDiagonalBlock().index2_data().begin()+row_end);
166  }
167 
168  //*******************************
169  //construct offdiagonal block
170 
171  //store off-diagonal block
172  GetOffDiagonalBlock().reserve(nlocal_rows, offdiag_nnz);
173  if(offdiag_nnz == 0) { //empty matrix
174  for(unsigned int i=0; i<nlocal_rows+1; ++i)
175  GetOffDiagonalBlock().index1_data()[i] = 0;
176  GetOffDiagonalBlock().SetColSize(mOffDiagonalLocalIds.size());
177  } else {
178  counter = 0;
179  for(const auto& entries : local_graph) {
180  unsigned int k = 0;
181  TIndexType row_begin = GetOffDiagonalBlock().index1_data()[counter];
182  for(auto global_j : entries) {
183  if( ! GetColNumbering().IsLocal(global_j)) {
184  TIndexType local_j = GetOffDiagonalBlockLocalId(global_j);
185  GetOffDiagonalBlock().index2_data()[row_begin+k] = local_j;
186  GetOffDiagonalBlock().value_data()[row_begin+k] = 0.0;
187  k++;
188  }
189  }
190  GetOffDiagonalBlock().index1_data()[counter+1] = row_begin + k;
191  counter++;
192  }
193  GetOffDiagonalBlock().SetColSize(mOffDiagonalLocalIds.size());
194  }
195 #ifdef KRATOS_DEBUG
196  GetOffDiagonalBlock().CheckColSize();
197 #endif
198 
199  //ensure columns are ordered
200  for(TIndexType i = 0; i<nlocal_rows; ++i) {
201  TIndexType row_begin = GetOffDiagonalBlock().index1_data()[i];
202  TIndexType row_end = GetOffDiagonalBlock().index1_data()[i+1];
203  if(row_end - row_begin > 0)
204  std::sort(GetOffDiagonalBlock().index2_data().begin() + row_begin,GetOffDiagonalBlock().index2_data().begin()+row_end);
205  }
206 
207  PrepareNonLocalCommunications(rSparseGraph);
208 
209  //mount importer for SpMV calculations
210  auto pimporter = Kratos::make_unique<DistributedVectorImporter<TDataType,TIndexType>>(GetComm(),mOffDiagonalGlobalIds, GetColNumbering());
211  mpVectorImporter.swap(pimporter);
212  }
213 
214  explicit DistributedCsrMatrix(const DistributedCsrMatrix& rOtherMatrix)
215  :
216  mpComm(rOtherMatrix.mpComm),
217  mpRowNumbering(Kratos::make_unique< DistributedNumbering<TIndexType> >( rOtherMatrix.GetRowNumbering())),
218  mpColNumbering(Kratos::make_unique< DistributedNumbering<TIndexType> >( rOtherMatrix.GetColNumbering())),
219  mpDiagonalBlock(Kratos::make_unique<CsrMatrix<TDataType,TIndexType>>(rOtherMatrix.GetDiagonalBlock())),
220  mpOffDiagonalBlock(Kratos::make_unique<CsrMatrix<TDataType,TIndexType>>(rOtherMatrix.GetOffDiagonalBlock())),
221  mNonLocalData(rOtherMatrix.mNonLocalData),
222  mOffDiagonalLocalIds(rOtherMatrix.mOffDiagonalLocalIds),
223  mOffDiagonalGlobalIds(rOtherMatrix.mOffDiagonalGlobalIds),
224  mfem_assemble_colors(rOtherMatrix.mfem_assemble_colors),
225  mRecvCachedIJ(rOtherMatrix.mRecvCachedIJ),
226  mSendCachedIJ(rOtherMatrix.mSendCachedIJ),
227  mpVectorImporter(Kratos::make_unique<DistributedVectorImporter<TDataType,TIndexType>>(*rOtherMatrix.mpVectorImporter))
228  {
229  ReconstructDirectAccessVectors();
230  }
231 
232  //move constructor
234  :mpComm(rOtherMatrix.mpComm)
235  {
236  mpRowNumbering.swap(rOtherMatrix.pGetRowNumbering());
237  mpColNumbering.swap(rOtherMatrix.pGetColNumbering());
238  mpDiagonalBlock = std::move(rOtherMatrix.mpDiagonalBlock);
239  mpOffDiagonalBlock = std::move(rOtherMatrix.mpOffDiagonalBlock);
240  mNonLocalData = std::move(rOtherMatrix.mNonLocalData);
241  mSendCachedIJ = std::move(rOtherMatrix.mSendCachedIJ);
242  mRecvCachedIJ = std::move(rOtherMatrix.mRecvCachedIJ);
243  mOffDiagonalLocalIds = std::move(rOtherMatrix.mOffDiagonalLocalIds);
244  mOffDiagonalGlobalIds = std::move(rOtherMatrix.mOffDiagonalGlobalIds);
245  mfem_assemble_colors = std::move(rOtherMatrix.mfem_assemble_colors);
246  mpVectorImporter = std::move(rOtherMatrix.mpVectorImporter);
247  }
248 
249  //move assignement operator
251  {
252  mpComm = rOtherMatrix.mpComm,
253  mpRowNumbering.swap(rOtherMatrix.pGetRowNumbering());
254  mpColNumbering.swap(rOtherMatrix.pGetColNumbering());
255  mpDiagonalBlock = std::move(rOtherMatrix.mpDiagonalBlock);
256  mpOffDiagonalBlock = std::move(rOtherMatrix.mpOffDiagonalBlock);
257  mNonLocalData = std::move(rOtherMatrix.mNonLocalData);
258  mSendCachedIJ = std::move(rOtherMatrix.mSendCachedIJ);
259  mRecvCachedIJ = std::move(rOtherMatrix.mRecvCachedIJ);
260  mOffDiagonalLocalIds = std::move(rOtherMatrix.mOffDiagonalLocalIds);
261  mOffDiagonalGlobalIds = std::move(rOtherMatrix.mOffDiagonalGlobalIds);
262  mfem_assemble_colors = std::move(rOtherMatrix.mfem_assemble_colors);
263  mpVectorImporter = std::move(rOtherMatrix.mpVectorImporter);
264  }
267 
270  // {
271  // this->AddEntries(rOther.GetGraph());
272  // return *this;
273  // }
274 
278  void Clear()
279  {
280  }
281 
283  {
284  return *mpRowNumbering;
285  }
286 
288  {
289  return *mpColNumbering;
290  }
291 
292 
294  {
295  return mpRowNumbering;
296  }
297 
299  {
300  return mpColNumbering;
301  }
302 
304  {
305  return mpVectorImporter;
306  }
307 
308  void SetValue(const TDataType value)
309  {
310  GetDiagonalBlock().SetValue(value);
311  GetOffDiagonalBlock().SetValue(value);
312  }
313 
314  TIndexType local_size1() const
315  {
316  return GetDiagonalBlock().size1();
317  }
318 
319  TIndexType size2() const
320  {
321  return GetColNumbering().Size();
322  }
323 
324  inline TIndexType local_nnz() const
325  {
326  return GetDiagonalBlock().nnz();
327  }
328 
329  const DataCommunicator& GetComm() const
330  {
331  return *mpComm;
332  }
333 
334  const DataCommunicator* pGetComm() const
335  {
336  return mpComm;
337  }
338 
340  {
341  return mpDiagonalBlock;
342  }
344  {
345  return mpOffDiagonalBlock;
346  }
347 
349  {
350  return *mpDiagonalBlock;
351  }
353  {
354  return *mpOffDiagonalBlock;
355  }
356 
358  {
359  return *mpDiagonalBlock;
360  }
362  {
363  return *mpOffDiagonalBlock;
364  }
365 
366  const std::map<TIndexType, TIndexType>& GetOffDiagonalLocalIds() const
367  {
368  return mOffDiagonalLocalIds; //usage: mOffDiagonalLocalIds[global_id] contains the local_id associated to that global_id (for a off diagonal block entry)
369  }
370 
371  std::map<TIndexType, TIndexType>& GetOffDiagonalLocalIds()
372  {
373  return mOffDiagonalLocalIds; //usage: mOffDiagonalLocalIds[global_id] contains the local_id associated to that global_id (for a off diagonal block entry)
374  }
375 
377  {
378  return mOffDiagonalGlobalIds;
379  }
380 
382  {
383  return mOffDiagonalGlobalIds;
384  }
385 
386  TIndexType GetOffDiagonalBlockLocalId(TIndexType GlobalJ) const
387  {
388  auto it = mOffDiagonalLocalIds.find(GlobalJ);
389  KRATOS_DEBUG_ERROR_IF( it == mOffDiagonalLocalIds.end() ) << "GlobalJ is not in the nonlocal list" << std::endl;
390  return it->second;
391  }
392 
393  TIndexType GetOffDiaGlobalId(TIndexType LocalJ) const
394  {
395  return mOffDiagonalGlobalIds[LocalJ];
396  }
397 
398  TDataType& GetLocalDataByGlobalId(TIndexType GlobalI, TIndexType GlobalJ)
399  {
400  KRATOS_DEBUG_ERROR_IF( ! GetRowNumbering().IsLocal(GlobalI) ) << "non local row access for GlobalI,GlobalJ = " << GlobalI << " " << GlobalJ << std::endl;
401 
402  TIndexType LocalI = GetRowNumbering().LocalId(GlobalI);
403  if(GetColNumbering().IsLocal(GlobalJ))
404  {
405  return GetDiagonalBlock()( LocalI, GetColNumbering().LocalId(GlobalJ) );
406  }
407  else
408  {
409  return GetOffDiagonalBlock()( LocalI, GetOffDiagonalBlockLocalId(GlobalJ) );
410  }
411  }
412 
413  TDataType& GetNonLocalCachedDataByGlobalId(TIndexType GlobalI, TIndexType GlobalJ)
414  {
415  KRATOS_DEBUG_ERROR_IF( GetRowNumbering().IsLocal(GlobalI) ) << " local row access for GlobalI,GlobalJ = " << GlobalI << " " << GlobalJ << " expected to be nonlocal" << std::endl;
416  auto it = mNonLocalData.find(std::make_pair(GlobalI,GlobalJ));
417  KRATOS_DEBUG_ERROR_IF(it == mNonLocalData.end()) << " entry GlobalI,GlobalJ = " << GlobalI << " " << GlobalJ << " not found in NonLocalData" << std::endl;
418  return it->second;
419  }
420 
422  {
423  DenseVector<TIndexType> tmp(GetDiagonalBlock().index2_data().size());
424  IndexPartition<TIndexType>(tmp.size()).for_each([&](TIndexType i)
425  {
426  tmp[i] = GetColNumbering().GlobalId( GetDiagonalBlock().index2_data()[i] );
427  });
428  return tmp;
429  }
430 
432  {
433  DenseVector<TIndexType> tmp(GetOffDiagonalBlock().index2_data().size());
434  IndexPartition<TIndexType>(tmp.size()).for_each([&](TIndexType i)
435  {
436  tmp[i] = GetOffDiaGlobalId( GetOffDiagonalBlock().index2_data()[i] );
437  });
438  return tmp;
439  }
440 
442  const TDataType DiagonalValue,
444  {
445  KRATOS_TRY
446  KRATOS_ERROR_IF(local_size1() != rFreeDofsVector.LocalSize() ) << "ApplyHomogeneousDirichlet: mismatch between row sizes : " << local_size1()
447  << " and free_dofs_vector size " << rFreeDofsVector.LocalSize() << std::endl;
448 
449 
450  //diagonal block
451  GetDiagonalBlock().ApplyHomogeneousDirichlet(rFreeDofsVector.GetLocalData(), DiagonalValue, rRHS.GetLocalData());
452 
453  //off diagonal block
454  auto off_diag_free = mpVectorImporter->ImportData(rFreeDofsVector); //obtain the nonlocal components of the rFreeDofsVector
455  if(GetOffDiagonalBlock().nnz() != 0) {
456  KRATOS_ERROR_IF(GetOffDiagonalBlock().size1() != rFreeDofsVector.LocalSize() ) << "ApplyHomogeneousDirichlet - OffDiagonalBlock: mismatch between row sizes : " << GetOffDiagonalBlock().size1()
457  << " and free_dofs_vector size " << rFreeDofsVector.LocalSize() << std::endl;
458  KRATOS_ERROR_IF(GetOffDiagonalBlock().size2() != off_diag_free.size() ) << "ApplyHomogeneousDirichlet - OffDiagonalBlock: mismatch between col sizes : " << GetOffDiagonalBlock().size2()
459  << " and free_dofs_vector size " << off_diag_free.size() << std::endl;
461  {
462  const IndexType row_begin = GetOffDiagonalBlock().index1_data()[i];
463  const IndexType row_end = GetOffDiagonalBlock().index1_data()[i+1];
464  if(std::abs(rFreeDofsVector.GetLocalData()[i] - 1.0) < 1e-14) { //row corresponding to free dofs NOTE that we check if it is approx zero TODO: Epsilon?
465  for(IndexType k = row_begin; k < row_end; ++k) {
466  const IndexType col = GetOffDiagonalBlock().index2_data()[k];
467  GetOffDiagonalBlock().value_data()[k] *= off_diag_free[col]; //note that here we assume that rFreeDofsVector is either 0 or 1
468  }
469  } else { //row corresponding to a fixed dof - set to zero all non local row
470  for(IndexType k = row_begin; k < row_end; ++k) {
471  GetOffDiagonalBlock().value_data()[k] = TDataType();
472  }
473  }
474  });
475  }
476 
477  KRATOS_CATCH("")
478  }
479  // TDataType& operator()(TIndexType I, TIndexType J){
480  // }
481 
485  //TODO
486  //+=
487  //-=
488  //+
489  //-
490  //*
491 
492  // y += A*x -- where A is *this
495  {
496  //get off diagonal terms (requires communication)
497  auto off_diag_x = mpVectorImporter->ImportData(x);
498  GetOffDiagonalBlock().SpMV(off_diag_x,y.GetLocalData());
499  GetDiagonalBlock().SpMV(x.GetLocalData(),y.GetLocalData());
500  }
501 
502  //y = alpha*y + beta*A*x
503  void SpMV(const TDataType alpha,
505  const TDataType beta,
507  {
508  //get off diagonal terms (requires communication)
509  auto off_diag_x = mpVectorImporter->ImportData(x);
510  GetOffDiagonalBlock().SpMV(alpha,off_diag_x,beta,y.GetLocalData());
511  GetDiagonalBlock().SpMV(alpha,x.GetLocalData(),beta,y.GetLocalData());
512  }
513 
514  // y += A^t*x -- where A is *this
517  DistributedVectorExporter<TIndexType>* pTransposeExporter = nullptr
518  ) const
519  {
520  GetDiagonalBlock().TransposeSpMV(x.GetLocalData(),y.GetLocalData());
521 
522  DenseVector<TDataType> non_local_transpose_data = ZeroVector(GetOffDiagonalBlock().size2());
523  GetOffDiagonalBlock().TransposeSpMV(x.GetLocalData(),non_local_transpose_data);
524 
525  if(pTransposeExporter == nullptr) //if a nullptr is passed the DistributedVectorExporter is constructed on the flight
526  {
527  //constructing the exporter requires communication, so the efficiency of the TransposeSpMV can be increased by passing a constructed exporter
528  pTransposeExporter = new DistributedVectorExporter<TIndexType>(GetComm(),mOffDiagonalGlobalIds,y.GetNumbering());
529  }
530  pTransposeExporter->Apply(y,non_local_transpose_data);
531 
532  return pTransposeExporter;
533  }
534 
535  // y += A^t*x -- where A is *this
537  TDataType alpha,
539  TDataType beta,
541  DistributedVectorExporter<TIndexType>* pTransposeExporter = nullptr
542  ) const
543  {
544  GetDiagonalBlock().TransposeSpMV(alpha,x.GetLocalData(),beta,y.GetLocalData());
545 
546  DenseVector<TDataType> non_local_transpose_data = ZeroVector(GetOffDiagonalBlock().size2());
547  GetOffDiagonalBlock().TransposeSpMV(alpha,x.GetLocalData(),beta,non_local_transpose_data);
548 
549  if(pTransposeExporter == nullptr) //if a nullptr is passed the DistributedVectorExporter is constructed on the flight
550  {
551  //constructing the exporter requires communication, so the efficiency of the TransposeSpMV can be increased by passing a constructed exporter
552  pTransposeExporter = new DistributedVectorExporter<TIndexType>(GetComm(),mOffDiagonalGlobalIds,y.GetNumbering());
553  }
554  pTransposeExporter->Apply(y,non_local_transpose_data);
555 
556  return pTransposeExporter;
557  }
558 
559  TDataType NormFrobenius() const
560  {
561  TDataType diag_norm = GetDiagonalBlock().NormFrobenius();
562  TDataType off_diag_norm = GetOffDiagonalBlock().NormFrobenius();
563  TDataType sum_squared = std::pow(diag_norm,2) + std::pow(off_diag_norm,2);
564  sum_squared = GetComm().SumAll(sum_squared);
565  return std::sqrt(sum_squared);
566  }
567 
568 
570  {
571  //set to zero non local data
572  for(auto& item : mNonLocalData)
573  item.second = 0.0;
574  }
575 
577  {
578  //communicate data to finalize the assembly
579  auto& rComm = GetComm();
580 
581  std::vector<TDataType> send_data;
582  std::vector<TDataType> recv_data;
583 
584  //sendrecv data
585  for(auto color : mfem_assemble_colors) {
586  if(color >= 0) { //-1 would imply no communication
587  const auto& direct_senddata_access = mPointersToSendValues[color];
588  const auto& direct_recvdata_access = mPointersToRecvValues[color];
589 
590  send_data.resize(direct_senddata_access.size());
591  recv_data.resize(direct_recvdata_access.size());
592 
593  for(TIndexType i=0; i<send_data.size(); ++i) {
594  send_data[i] = *(direct_senddata_access[i]);
595  }
596 
597  rComm.SendRecv(send_data, color, 0, recv_data, color, 0);
598 
599  for(TIndexType i=0; i<recv_data.size(); ++i) {
600  *(direct_recvdata_access[i]) += recv_data[i]; //here we assemble the nonlocal contribution to the local data
601  }
602  }
603  }
604  }
605 
606  template<class TMatrixType, class TIndexVectorType >
607  void Assemble(
608  const TMatrixType& rMatrixInput,
609  const TIndexVectorType& EquationId
610  )
611  {
612  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size1() != EquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
613  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size2() != EquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
614 
615  for(unsigned int i=0; i<EquationId.size(); ++i) {
616  const TIndexType global_i = EquationId[i];
617  if(GetRowNumbering().IsLocal(global_i)) {
618  for(unsigned int j = 0; j<EquationId.size(); ++j) {
619  const TIndexType global_j = EquationId[j];
620  TDataType& value = GetLocalDataByGlobalId(global_i,global_j);
621  AtomicAdd(value, rMatrixInput(i,j));
622  }
623  } else {
624  for(unsigned int j = 0; j<EquationId.size(); ++j) {
625  const TIndexType global_j = EquationId[j];
626  TDataType& value = GetNonLocalCachedDataByGlobalId(global_i,global_j);
627  AtomicAdd(value, rMatrixInput(i,j));
628  }
629  }
630  }
631  }
632 
633  void AssembleEntry(const TDataType Value, const TIndexType GlobalI, const TIndexType GlobalJ)
634  {
635  if(GetRowNumbering().IsLocal(GlobalI)) {
636  TDataType& v = GetLocalDataByGlobalId(GlobalI,GlobalJ);
637  AtomicAdd(v, Value);
638  } else {
639  TDataType& v = GetNonLocalCachedDataByGlobalId(GlobalI,GlobalJ);
640  AtomicAdd(v, Value);
641  }
642  }
643 
644  template<class TMatrixType, class TIndexVectorType >
645  void Assemble(
646  const TMatrixType& rMatrixInput,
647  const TIndexVectorType& RowEquationId,
648  const TIndexVectorType& ColEquationId
649  )
650  {
651  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size1() != RowEquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
652  KRATOS_DEBUG_ERROR_IF(rMatrixInput.size2() != ColEquationId.size()) << "sizes of matrix and equation id do not match in Assemble" << std::endl;
653 
654  for(unsigned int i=0; i<RowEquationId.size(); ++i) {
655  const TIndexType global_i = RowEquationId[i];
656 
657  if(GetRowNumbering().IsLocal(global_i)) {
658  for(unsigned int j = 0; j<ColEquationId.size(); ++j) {
659  const TIndexType global_j = ColEquationId[j];
660  TDataType& value = GetLocalDataByGlobalId(global_i,global_j);
661  AtomicAdd(value, rMatrixInput(i,j));
662  }
663  } else {
664  for(unsigned int j = 0; j<ColEquationId.size(); ++j) {
665  const TIndexType global_j = ColEquationId[j];
666  TDataType& value = GetNonLocalCachedDataByGlobalId(global_i,global_j);
667  AtomicAdd(value, rMatrixInput(i,j));
668  }
669 
670  }
671  }
672  }
673 
675  {
676  MatrixMapType value_map;
677  for(unsigned int i=0; i<local_size1(); ++i) {
678  TIndexType row_begin = GetDiagonalBlock().index1_data()[i];
679  TIndexType row_end = GetDiagonalBlock().index1_data()[i+1];
680  for(TIndexType k = row_begin; k < row_end; ++k) {
681  TIndexType j = GetDiagonalBlock().index2_data()[k];
682  TDataType v = GetDiagonalBlock().value_data()[k];
683  value_map[ {GetRowNumbering().GlobalId(i),GetColNumbering().GlobalId(j)}] = v;
684  }
685  }
686 
687  for(unsigned int i=0; i<local_size1(); ++i) {
688  TIndexType row_begin = GetOffDiagonalBlock().index1_data()[i];
689  TIndexType row_end = GetOffDiagonalBlock().index1_data()[i+1];
690  for(TIndexType k = row_begin; k < row_end; ++k) {
691  TIndexType j = GetOffDiagonalBlock().index2_data()[k];
692  TDataType v = GetOffDiagonalBlock().value_data()[k];
693  value_map[ {GetRowNumbering().GlobalId(i),mOffDiagonalGlobalIds[j]}] = v;
694  }
695  }
696 
697  return value_map;
698  }
699 
701  {
702  // Flatten all data (both indices and values) into a single vector of doubles
703  std::vector<double> tmp_data;
704  tmp_data.reserve(GetDiagonalBlock().nnz()*3 + GetOffDiagonalBlock().nnz()*3);
705  for(unsigned int i=0; i<GetDiagonalBlock().size1(); ++i){
706  IndexType row_begin = GetDiagonalBlock().index1_data()[i];
707  IndexType row_end = GetDiagonalBlock().index1_data()[i+1];
708  for(IndexType k = row_begin; k < row_end; ++k){
709  const IndexType j = GetDiagonalBlock().index2_data()[k];
710  const TDataType v = GetDiagonalBlock().value_data()[k];
711  tmp_data.push_back(GetRowNumbering().GlobalId(i));
712  tmp_data.push_back(GetColNumbering().GlobalId(j));
713  tmp_data.push_back(v);
714  }
715  }
716  for(unsigned int i=0; i<GetOffDiagonalBlock().size1(); ++i){
717  IndexType row_begin = GetOffDiagonalBlock().index1_data()[i];
718  IndexType row_end = GetOffDiagonalBlock().index1_data()[i+1];
719  for(IndexType k = row_begin; k < row_end; ++k){
720  const IndexType j = GetOffDiagonalBlock().index2_data()[k];
721  const TDataType v = GetOffDiagonalBlock().value_data()[k];
722  tmp_data.push_back(GetRowNumbering().GlobalId(i));
723  tmp_data.push_back(mOffDiagonalGlobalIds[j]);
724  tmp_data.push_back(v);
725  }
726  }
727 
728  auto collected_data = GetComm().Gatherv(tmp_data,target_rank);
729 
730  const MpiIndexType num_processors = GetComm().Size();
731  const MpiIndexType my_rank = GetComm().Rank();
732 
734  typename CsrMatrix<TDataType,TIndexType>::Pointer p_csr_output;
735 
736  if(my_rank==target_rank){
738 
739  for(int i_proc=0; i_proc<num_processors; ++i_proc){
740  const auto& data = collected_data[i_proc];
741  for(IndexType i=0; i<data.size(); i+=3){
742  IndexType I = static_cast<IndexType>(data[i]);
743  IndexType J = static_cast<IndexType>(data[i+1]);
744  p_csr_graph->AddEntry(I,J);
745  }
746  }
747  p_csr_graph->Finalize();
748  }
749 
750  if(my_rank==target_rank){
751  p_csr_output = Kratos::make_shared<CsrMatrix<TDataType,TIndexType>>(*p_csr_graph);
752  p_csr_output->BeginAssemble();
753  for(int i_proc=0; i_proc<num_processors; ++i_proc){
754  const auto& data = collected_data[i_proc];
755  for(IndexType i=0; i<data.size(); i+=3){
756  const IndexType I = static_cast<IndexType>(data[i]);
757  const IndexType J = static_cast<IndexType>(data[i+1]);
758  const double v = data[i+2];
759  p_csr_output->AssembleEntry(v,I,J);
760  }
761  }
762  p_csr_output->FinalizeAssemble();
763  }
764 
765  return p_csr_output;
766  }
767 
768  //TODO
769  // LeftScaling
770  // RightScaling
771  // SymmetricScaling
772 
773  //TODO
774  //void ApplyDirichlet
775 
776  //TODO
777  //NormFrobenius
778 
782 
783 
787 
788 
792 
794  std::string Info() const
795  {
796  std::stringstream buffer;
797  buffer << "DistributedCsrMatrix" ;
798  return buffer.str();
799  }
800 
802  void PrintInfo(std::ostream& rOStream) const
803  {
804  rOStream << "DistributedCsrMatrix" << std::endl;
805  }
806 
808  void PrintData(std::ostream& rOStream) const
809  {
810  rOStream << "--- Diagonal Block: ---" << std::endl;
811  rOStream << "size1 : " << GetDiagonalBlock().size1() <<std::endl;
812  rOStream << "size2 : " << GetDiagonalBlock().size2() <<std::endl;
813  rOStream << "nnz : " << GetDiagonalBlock().nnz() <<std::endl;
814  rOStream << "index1_data : " << std::endl;
815  for(auto item : GetDiagonalBlock().index1_data())
816  rOStream << item << ",";
817  rOStream << std::endl;
818  rOStream << "index2_data in local numbering: " << std::endl;
819  for(auto item : GetDiagonalBlock().index2_data())
820  rOStream << item << ",";
821  rOStream << std::endl;
822  rOStream << "index2_data in global numbering: " << std::endl;
823  for(auto item : GetDiagonalIndex2DataInGlobalNumbering())
824  rOStream << item << ",";
825  rOStream << std::endl;
826  rOStream << "value_data : " << std::endl;
827  for(auto item : GetDiagonalBlock().value_data())
828  rOStream << item << ",";
829  rOStream << std::endl;
830  //rOStream << "as map : " << GetDiagonalBlock().ToMap() << std::endl;
831  rOStream << std::endl;
832  rOStream << "--- OffDiagonal Block: ---" << std::endl;
833  rOStream << "size1 : " << GetOffDiagonalBlock().size1() <<std::endl;
834  rOStream << "size2 : " << GetOffDiagonalBlock().size2() <<std::endl;
835  rOStream << "nnz : " << GetOffDiagonalBlock().nnz() <<std::endl;
836  rOStream << "index1_data : " << std::endl;
837  for(auto item : GetOffDiagonalBlock().index1_data())
838  rOStream << item << ",";
839  rOStream << std::endl;
840  rOStream << "index2_data in local numbering: " << std::endl;
841  for(auto item : GetOffDiagonalBlock().index2_data())
842  rOStream << item << ",";
843  rOStream << std::endl;
844  rOStream << "index2_data in global numbering: " << std::endl;
846  rOStream << item << ",";
847  rOStream << std::endl;
848  rOStream << "value_data : " << std::endl;
849  for(auto item : GetOffDiagonalBlock().value_data())
850  rOStream << item << ",";
851  rOStream << std::endl;
852  //rOStream << "as map : " << GetOffDiagonalBlock().ToMap() << std::endl;
853 
854 
855  }
856 
860 
861 
863 
864 protected:
867 
868 
872 
873 
877  // A non-recursive binary search function. It returns
878  // location of x in given array arr[l..r] is present,
879  // otherwise -1
880  template< class TVectorType >
881  inline TIndexType BinarySearch(const TVectorType& arr,
882  TIndexType l, TIndexType r, TIndexType x)
883  {
884  while (l <= r) {
885  int m = l + (r - l) / 2;
886 
887  // Check if x is present at mid
888  if (arr[m] == x)
889  return m;
890 
891  // If x greater, ignore left half
892  if (arr[m] < x)
893  l = m + 1;
894 
895  // If x is smaller, ignore right half
896  else
897  r = m - 1;
898  }
899 
900  // if we reach here, then element was not present
901  return -1;
902  }
903 
908  {
909  auto& rComm = GetComm();
910  const auto& nonlocal_graphs = rSparseGraph.GetNonLocalGraphs();
911  std::vector<int> send_list;
912  for(unsigned int id = 0; id<nonlocal_graphs.size(); ++id)
913  if( !nonlocal_graphs[id].IsEmpty())
914  send_list.push_back(id);
915 
916  mfem_assemble_colors = MPIColoringUtilities::ComputeCommunicationScheduling(send_list, rComm);
917 
918  //sendrecv data
919  for(auto color : mfem_assemble_colors) {
920  if(color >= 0) { //-1 would imply no communication
921  const auto& send_graph = nonlocal_graphs[color];
922  auto& direct_senddata_access = mPointersToSendValues[color];
923  auto& send_ij = mSendCachedIJ[color];
924 
925  for(auto row_it=send_graph.begin(); row_it!=send_graph.end(); ++row_it) {
926  const auto remote_local_I = row_it.GetRowIndex();
927  const auto remote_global_I = GetRowNumbering().RemoteGlobalId(remote_local_I, color);
928 
929  for(auto J : *row_it) {
930  TDataType& value = mNonLocalData[std::make_pair(remote_global_I,J)]; //here we create the I,J entry in the nonlocal data (entry was there in the graph!)
931  direct_senddata_access.push_back(&value); //storing a direct pointer to the value contained in the data structure
932  send_ij.push_back(remote_global_I);
933  send_ij.push_back(J);
934  }
935  }
936 
937  //NOTE: this can be made nonblocking
938  mRecvCachedIJ[color] = rComm.SendRecv(send_ij, color, color);
939  auto& recv_ij = mRecvCachedIJ[color];
940 
941  auto& direct_recvdata_access = mPointersToRecvValues[color];
942 
943  for(TIndexType k=0; k<recv_ij.size(); k+=2) {
944  TIndexType I = recv_ij[k];
945  TIndexType J = recv_ij[k+1];
946  auto& value = GetLocalDataByGlobalId(I,J);
947  direct_recvdata_access.push_back(&value);
948  }
949  }
950  }
951  }
952 
956 
957 
961 
962 
966 
967 
969 
970 private:
973 
974 
978  const DataCommunicator* mpComm;
979 
980  typename DistributedNumbering<TIndexType>::UniquePointer mpRowNumbering;
981  typename DistributedNumbering<TIndexType>::UniquePointer mpColNumbering;
982 
983  typename BlockMatrixType::UniquePointer mpDiagonalBlock = Kratos::make_unique< BlockMatrixType >();
984  typename BlockMatrixType::UniquePointer mpOffDiagonalBlock = Kratos::make_unique< BlockMatrixType >();
985  MatrixMapType mNonLocalData; //data which is assembled locally and needs to be communicated to the owner
986 
987  //this map tells for an index J which does not belong to the local diagonal block which is the corresponding localJ
988  std::map<TIndexType, TIndexType> mOffDiagonalLocalIds; //usage: mOffDiagonalLocalIds[global_id] contains the local_id associated to that global_id (for a off diagonal block entry)
989  DenseVector<TIndexType> mOffDiagonalGlobalIds; //usage: mOffDiagonalGlobalIds[local_id] contains the global_id associated
990 
991  std::vector<int> mfem_assemble_colors; //coloring of communication
992  std::unordered_map< unsigned int, std::vector<TIndexType> > mRecvCachedIJ; //recv_ij contains i,j to receive one after the other
993  std::unordered_map< unsigned int, std::vector<TIndexType> > mSendCachedIJ; //recv_ij contains i,j to receive one after the other
994  std::unordered_map< unsigned int, std::vector<TDataType*> > mPointersToRecvValues; //this contains direct pointers into the data contained in mNonLocalData, prepared so to speed up communications
995  std::unordered_map< unsigned int, std::vector<TDataType*> > mPointersToSendValues; //this contains direct pointers into mDiagonalBlock and mOffDiagonalBlock, prepared so to speed up communication
996 
997  std::unique_ptr<DistributedVectorImporter<TDataType,TIndexType>> mpVectorImporter;
998 
1002  friend class Serializer;
1003 
1004  void save(Serializer& rSerializer) const
1005  {
1006  rSerializer.save("CommunicatorName",ParallelEnvironment::RetrieveRegisteredName(*mpComm));
1007  rSerializer.save("RowNumbering",mpRowNumbering);
1008  rSerializer.save("ColNumbering",mpColNumbering);
1009  rSerializer.save("mpDiagonalBlock",mpDiagonalBlock);
1010  rSerializer.save("mpOffDiagonalBlock",mpOffDiagonalBlock);
1011  rSerializer.save("mNonLocalData",mNonLocalData);
1012  rSerializer.save("mSendCachedIJ",mSendCachedIJ);
1013  rSerializer.save("mRecvCachedIJ",mRecvCachedIJ);
1014  rSerializer.save("mOffDiagonalLocalIds",mOffDiagonalLocalIds);
1015  rSerializer.save("mfem_assemble_colors",mfem_assemble_colors);
1016  rSerializer.save("mpVectorImporter",mpVectorImporter);
1017  //note that the direct access vectors are not saved, we will need to reconstruct them basing on send_ij and recv_ij
1018 
1019  }
1020 
1021  void load(Serializer& rSerializer)
1022  {
1023  std::string comm_name;
1024  rSerializer.load("CommunicatorName",comm_name);
1025  mpComm = &ParallelEnvironment::GetDataCommunicator(comm_name);
1026  rSerializer.load("RowNumbering",mpRowNumbering);
1027  rSerializer.load("ColNumbering",mpColNumbering);
1028  rSerializer.load("mpDiagonalBlock",mpDiagonalBlock);
1029  rSerializer.load("mpOffDiagonalBlock",mpOffDiagonalBlock);
1030  rSerializer.load("mNonLocalData",mNonLocalData);
1031  rSerializer.load("mSendCachedIJ",mSendCachedIJ);
1032  rSerializer.load("mRecvCachedIJ",mRecvCachedIJ);
1033  rSerializer.load("mOffDiagonalLocalIds",mOffDiagonalLocalIds);
1034  rSerializer.load("mfem_assemble_colors",mfem_assemble_colors);
1035  rSerializer.load("mpVectorImporter",mpVectorImporter);
1036 
1037  ReconstructDirectAccessVectors();
1038  }
1039 
1040 
1044  void ReconstructDirectAccessVectors()
1045  {
1046  //compute direct pointers to data
1047  for(auto color : mfem_assemble_colors)
1048  {
1049  if(color >= 0) //-1 would imply no communication
1050  {
1051  const auto& send_ij = mSendCachedIJ[color];
1052  const auto& recv_ij = mRecvCachedIJ[color];
1053 
1054  auto& direct_senddata_access = mPointersToRecvValues[color];
1055  for(TIndexType i=0; i<send_ij.size(); i+=2)
1056  {
1057  TIndexType I = recv_ij[i];
1058  TIndexType J = recv_ij[i+1];
1059  auto& value = GetNonLocalCachedDataByGlobalId(I,J);
1060  direct_senddata_access.push_back(&value);
1061  }
1062 
1063  auto& direct_recvdata_access = mPointersToRecvValues[color];
1064  for(TIndexType k=0; k<recv_ij.size(); k+=2)
1065  {
1066  TIndexType I = recv_ij[k];
1067  TIndexType J = recv_ij[k+1];
1068  auto& value = GetLocalDataByGlobalId(I,J);
1069  direct_recvdata_access.push_back(&value);
1070  }
1071  }
1072  }
1073  }
1074 
1075 
1079 
1080 
1084 
1085 
1089 
1090 
1091 
1093 
1094 }; // Class DistributedCsrMatrix
1095 
1097 
1100 
1101 
1105 
1106 
1108 template< class TDataType>
1109 inline std::istream& operator >> (std::istream& rIStream,
1111 {
1112  return rIStream;
1113 }
1114 
1116 template< class TDataType>
1117 inline std::ostream& operator << (std::ostream& rOStream,
1118  const DistributedCsrMatrix<TDataType>& rThis)
1119 {
1120  rThis.PrintInfo(rOStream);
1121  rOStream << std::endl;
1122  rThis.PrintData(rOStream);
1123 
1124  return rOStream;
1125 }
1127 
1129 
1130 } // namespace Kratos.
1131 
1132 #endif // KRATOS_DISTRIBUTED_CSR_MATRIX_H_INCLUDED defined
1133 
1134 
This class implements "serial" CSR matrix, including capabilities for FEM assembly.
Definition: csr_matrix.h:60
void BeginAssemble()
Definition: csr_matrix.h:542
void AssembleEntry(const TDataType Value, const IndexType GlobalI, const IndexType GlobalJ)
Definition: csr_matrix.h:634
void FinalizeAssemble()
Definition: csr_matrix.h:544
std::unordered_map< std::pair< IndexType, IndexType >, double, PairHasher< IndexType, IndexType >, PairComparor< IndexType, IndexType > > MatrixMapType
Definition: csr_matrix.h:69
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
virtual int Size() const
Get the parallel size of this DataCommunicator.
Definition: data_communicator.h:597
virtual int Rank() const
Get the parallel rank for this DataCommunicator.
Definition: data_communicator.h:587
This class implements "serial" CSR matrix, including capabilities for FEM assembly.
Definition: distributed_csr_matrix.h:58
TIndexType local_size1() const
Definition: distributed_csr_matrix.h:314
CsrMatrix< TDataType, TIndexType > & GetOffDiagonalBlock()
Definition: distributed_csr_matrix.h:352
int MpiIndexType
Definition: distributed_csr_matrix.h:63
const DistributedNumbering< TIndexType > & GetColNumbering() const
Definition: distributed_csr_matrix.h:287
TIndexType size2() const
Definition: distributed_csr_matrix.h:319
DistributedNumbering< TIndexType >::UniquePointer & pGetColNumbering()
Definition: distributed_csr_matrix.h:298
TIndexType IndexType
Definition: distributed_csr_matrix.h:62
DistributedCsrMatrix & operator=(DistributedCsrMatrix const &rOther)=delete
Assignment operator. TODO: decide if we do want to allow it.
TIndexType GetOffDiagonalBlockLocalId(TIndexType GlobalJ) const
Definition: distributed_csr_matrix.h:386
CsrMatrix< TDataType, TIndexType >::UniquePointer & pGetDiagonalBlock()
Definition: distributed_csr_matrix.h:339
DistributedCsrMatrix(const DistributedCsrMatrix &rOtherMatrix)
Definition: distributed_csr_matrix.h:214
std::map< TIndexType, TIndexType > & GetOffDiagonalLocalIds()
Definition: distributed_csr_matrix.h:371
DistributedVectorImporter< TDataType, TIndexType >::UniquePointer & pGetVectorImporter()
Definition: distributed_csr_matrix.h:303
DenseVector< TIndexType > & GetOffDiagonalGlobalIds()
Definition: distributed_csr_matrix.h:381
TIndexType local_nnz() const
Definition: distributed_csr_matrix.h:324
const CsrMatrix< TDataType, TIndexType > & GetDiagonalBlock() const
Definition: distributed_csr_matrix.h:357
const DistributedNumbering< TIndexType > & GetRowNumbering() const
Definition: distributed_csr_matrix.h:282
DistributedCsrMatrix()
Definition: distributed_csr_matrix.h:75
DistributedCsrMatrix(const DistributedSparseGraph< TIndexType > &rSparseGraph)
Definition: distributed_csr_matrix.h:82
DenseVector< TIndexType > GetDiagonalIndex2DataInGlobalNumbering() const
Definition: distributed_csr_matrix.h:421
void SpMV(const TDataType alpha, const DistributedSystemVector< TDataType, TIndexType > &x, const TDataType beta, DistributedSystemVector< TDataType, TIndexType > &y) const
Definition: distributed_csr_matrix.h:503
DistributedNumbering< TIndexType >::UniquePointer & pGetRowNumbering()
Definition: distributed_csr_matrix.h:293
DistributedCsrMatrix(const DataCommunicator &rComm)
Definition: distributed_csr_matrix.h:78
const CsrMatrix< TDataType, TIndexType > & GetOffDiagonalBlock() const
Definition: distributed_csr_matrix.h:361
const DataCommunicator & GetComm() const
Definition: distributed_csr_matrix.h:329
KRATOS_CLASS_POINTER_DEFINITION(DistributedCsrMatrix)
Pointer definition of DistributedCsrMatrix.
DistributedCsrMatrix & operator=(DistributedCsrMatrix &&rOtherMatrix)
Definition: distributed_csr_matrix.h:250
CsrMatrix< TDataType, TIndexType >::UniquePointer & pGetOffDiagonalBlock()
Definition: distributed_csr_matrix.h:343
std::string Info() const
Turn back information as a string.
Definition: distributed_csr_matrix.h:794
void ApplyHomogeneousDirichlet(const DistributedSystemVector< TDataType, TIndexType > &rFreeDofsVector, const TDataType DiagonalValue, DistributedSystemVector< TDataType, TIndexType > &rRHS)
Definition: distributed_csr_matrix.h:441
CsrMatrix< TDataType, TIndexType >::Pointer ToSerialCSR(MpiIndexType target_rank=0) const
Definition: distributed_csr_matrix.h:700
void PrepareNonLocalCommunications(const DistributedSparseGraph< TIndexType > &rSparseGraph)
Definition: distributed_csr_matrix.h:907
TDataType NormFrobenius() const
Definition: distributed_csr_matrix.h:559
void BeginAssemble()
Definition: distributed_csr_matrix.h:569
void FinalizeAssemble()
Definition: distributed_csr_matrix.h:576
DistributedVectorExporter< TIndexType > * TransposeSpMV(const DistributedSystemVector< TDataType, TIndexType > &x, DistributedSystemVector< TDataType, TIndexType > &y, DistributedVectorExporter< TIndexType > *pTransposeExporter=nullptr) const
Definition: distributed_csr_matrix.h:515
DenseVector< TIndexType > GetOffDiagonalIndex2DataInGlobalNumbering() const
Definition: distributed_csr_matrix.h:431
void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: distributed_csr_matrix.h:802
CsrMatrix< TDataType, TIndexType > BlockMatrixType
Definition: distributed_csr_matrix.h:64
void SetValue(const TDataType value)
Definition: distributed_csr_matrix.h:308
const DenseVector< TIndexType > & GetOffDiagonalGlobalIds() const
Definition: distributed_csr_matrix.h:376
void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: distributed_csr_matrix.h:808
void Clear()
Definition: distributed_csr_matrix.h:278
void AssembleEntry(const TDataType Value, const TIndexType GlobalI, const TIndexType GlobalJ)
Definition: distributed_csr_matrix.h:633
DistributedVectorExporter< TIndexType > * TransposeSpMV(TDataType alpha, const DistributedSystemVector< TDataType, TIndexType > &x, TDataType beta, DistributedSystemVector< TDataType, TIndexType > &y, DistributedVectorExporter< TIndexType > *pTransposeExporter=nullptr) const
Definition: distributed_csr_matrix.h:536
DistributedCsrMatrix(DistributedCsrMatrix< TDataType, TIndexType > &&rOtherMatrix)
Definition: distributed_csr_matrix.h:233
MatrixMapType ToMap() const
Definition: distributed_csr_matrix.h:674
TDataType & GetLocalDataByGlobalId(TIndexType GlobalI, TIndexType GlobalJ)
Definition: distributed_csr_matrix.h:398
TIndexType GetOffDiaGlobalId(TIndexType LocalJ) const
Definition: distributed_csr_matrix.h:393
void Assemble(const TMatrixType &rMatrixInput, const TIndexVectorType &RowEquationId, const TIndexVectorType &ColEquationId)
Definition: distributed_csr_matrix.h:645
CsrMatrix< TDataType, TIndexType > & GetDiagonalBlock()
Definition: distributed_csr_matrix.h:348
void Assemble(const TMatrixType &rMatrixInput, const TIndexVectorType &EquationId)
Definition: distributed_csr_matrix.h:607
TDataType & GetNonLocalCachedDataByGlobalId(TIndexType GlobalI, TIndexType GlobalJ)
Definition: distributed_csr_matrix.h:413
CsrMatrix< TDataType, TIndexType >::MatrixMapType MatrixMapType
Definition: distributed_csr_matrix.h:65
const DataCommunicator * pGetComm() const
Definition: distributed_csr_matrix.h:334
const std::map< TIndexType, TIndexType > & GetOffDiagonalLocalIds() const
Definition: distributed_csr_matrix.h:366
~DistributedCsrMatrix()
Destructor.
Definition: distributed_csr_matrix.h:266
void SpMV(const DistributedSystemVector< TDataType, TIndexType > &x, DistributedSystemVector< TDataType, TIndexType > &y) const
Definition: distributed_csr_matrix.h:493
TIndexType BinarySearch(const TVectorType &arr, TIndexType l, TIndexType r, TIndexType x)
Definition: distributed_csr_matrix.h:881
This function provides essential capabilities for mapping between local and global ids in a distribut...
Definition: distributed_numbering.h:56
Short class definition.
Definition: distributed_sparse_graph.h:68
const DenseVector< NonLocalGraphType > & GetNonLocalGraphs() const
Definition: distributed_sparse_graph.h:295
IndexType ComputeMaxGlobalColumnIndex() const
Definition: distributed_sparse_graph.h:146
const DistributedNumbering< IndexType > & GetRowNumbering() const
Definition: distributed_sparse_graph.h:111
const LocalGraphType & GetLocalGraph() const
Definition: distributed_sparse_graph.h:285
Provides a DistributedSystemVector which implements FEM assemble capabilities.
Definition: distributed_system_vector.h:61
IndexType LocalSize() const
Definition: distributed_system_vector.h:178
DenseVector< TDataType > & GetLocalData()
Definition: distributed_system_vector.h:182
Provides a DistributedVectorExporter which implements FEM assemble capabilities.
Definition: distributed_vector_exporter.h:54
Provides a DistributedVectorImporter which implements FEM assemble capabilities.
Definition: distributed_vector_importer.h:57
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
Definition: amatrix_interface.h:41
static std::vector< int > ComputeCommunicationScheduling(const std::vector< int > &rLocalDestinationIds, const DataCommunicator &rComm)
Definition: communication_coloring_utilities.cpp:56
static std::string RetrieveRegisteredName(const DataCommunicator &rComm)
Get the MPI Comm size, as given by the default DataCommunicator.
Definition: parallel_environment.cpp:235
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_contiguous_row_graph.h:65
void Finalize()
Definition: sparse_contiguous_row_graph.h:220
void AddEntry(const IndexType RowIndex, const IndexType ColIndex)
Definition: sparse_contiguous_row_graph.h:164
IndexType Size() const
Definition: sparse_contiguous_row_graph.h:141
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
TSpaceType::IndexType Size(TSpaceType &dummy, typename TSpaceType::VectorType const &rV)
Definition: add_strategies_to_python.cpp:111
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
void AtomicAdd(TDataType &target, const TDataType &value)
Definition: atomic_utilities.h:55
unique_ptr< C > make_unique(Args &&...args)
Definition: smart_pointers.h:45
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
color
Definition: all_t_win_vs_m_fixed_error.py:230
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
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
data
Definition: mesh_to_mdpa_converter.py:59
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
int counter
Definition: script_THERMAL_CORRECT.py:218
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
def IsEmpty(_A)
Definition: custom_math.py:33