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.
sparse_contiguous_row_graph.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 <iostream>
17 #include <unordered_map>
18 #include <unordered_set>
19 
20 // External includes
21 #include <span/span.hpp>
22 
23 // Project includes
24 #include "includes/define.h"
26 #include "includes/serializer.h"
27 #include "includes/lock_object.h"
30 
31 namespace Kratos
32 {
35 
38 
42 
46 
50 
54 
56 //class to construct and store a matrix graph. Can be used to construct efficiently a CSR matrix (or other sparse matrix types)
57 
63 template<typename TIndexType=std::size_t>
65 {
66 public:
69  typedef TIndexType IndexType;
72 
75 
79 
82  {
83  mpComm = &ParallelEnvironment::GetDataCommunicator("Serial");
84  }
85 
87  {
88  mpComm = &ParallelEnvironment::GetDataCommunicator("Serial");
89  mGraph.resize(GraphSize,false);
90  mLocks = decltype(mLocks)(GraphSize);
91 
92  // @RiccardoRossi why is this needed? isn't this done with resizing?
93  //doing first touching
95  // mLocks[i] = LockObject();
96  mGraph[i] = std::unordered_set<IndexType>();
97  });
98  }
99 
102 
105  // {
106  // this->AddEntries(rOther.GetGraph());
107  // return *this;
108  // }
109 
112  {
113  mpComm = rOther.mpComm;
114  mGraph.resize(rOther.mGraph.size());
115  IndexPartition<IndexType>(rOther.mGraph.size()).for_each([&](IndexType i) {
116  mGraph[i] = std::unordered_set<IndexType>();
117  });
118  mLocks = decltype(mLocks)(rOther.mLocks.size());
119  this->AddEntries(rOther);
120  }
121 
122  const DataCommunicator& GetComm() const
123  {
124  return *mpComm;
125  }
126 
127  const DataCommunicator* pGetComm() const
128  {
129  return mpComm;
130  }
131 
135  void Clear()
136  {
137  mGraph.clear();
138  mLocks.clear();
139  }
140 
141  inline IndexType Size() const{
142  return mGraph.size();
143  }
144 
145  bool Has(const IndexType I, const IndexType J) const
146  {
147  const auto& row = mGraph[I];
148  return (row.find(J) != row.end());
149  }
150 
151  const typename GraphType::value_type& operator[](const IndexType& Key) const
152  {
153  return mGraph[Key];
154  }
155 
157  return GlobalIndex;
158  }
159 
161  return LocalIndex;
162  }
163 
164  void AddEntry(const IndexType RowIndex, const IndexType ColIndex)
165  {
166  mLocks[RowIndex].lock();
167  mGraph[RowIndex].insert(ColIndex);
168  mLocks[RowIndex].unlock();
169  }
170 
171  template<class TContainerType>
172  void AddEntries(const IndexType RowIndex, const TContainerType& rColIndices)
173  {
174  mLocks[RowIndex].lock();
175  mGraph[RowIndex].insert(rColIndices.begin(), rColIndices.end());
176  mLocks[RowIndex].unlock();
177  }
178 
179  template<class TIteratorType>
180  void AddEntries(const IndexType RowIndex,
181  const TIteratorType& rColBegin,
182  const TIteratorType& rColEnd
183  )
184  {
185  mLocks[RowIndex].lock();
186  mGraph[RowIndex].insert(rColBegin, rColEnd);
187  mLocks[RowIndex].unlock();
188  }
189 
190  //adds a square FEM matrix, identified by rIndices
191  template<class TContainerType>
192  void AddEntries(const TContainerType& rIndices)
193  {
194  for(auto I : rIndices){
195  KRATOS_DEBUG_ERROR_IF(I > this->Size()) << "Index : " << I
196  << " exceeds the graph size : " << Size() << std::endl;
197  mLocks[I].lock();
198  mGraph[I].insert(rIndices.begin(), rIndices.end());
199  mLocks[I].unlock();
200  }
201  }
202 
203  template<class TContainerType>
204  void AddEntries(const TContainerType& rRowIndices, const TContainerType& rColIndices)
205  {
206  for(auto I : rRowIndices){
207  AddEntries(I, rColIndices);
208  }
209  }
210 
211 
212  void AddEntries(const SparseContiguousRowGraph& rOtherGraph)
213  {
214  for(IndexType i=0; i<rOtherGraph.Size(); ++i)
215  {
216  AddEntries(i, rOtherGraph.GetGraph()[i]);
217  }
218  }
219 
220  void Finalize()
221  {
222 
223  }
224 
225  const GraphType& GetGraph() const{
226  return mGraph;
227  }
228 
229  //note that this function is slightly less efficient than the span version below
230  template<class TVectorType=DenseVector<IndexType>>
232  TVectorType& rRowIndices,
233  TVectorType& rColIndices
234  ) const
235  {
236  IndexType* pRowIndicesData=nullptr;
237  IndexType RowIndicesDataSize=0;
238  IndexType* pColIndicesData=nullptr;
239  IndexType ColIndicesDataSize=0;
240  ExportCSRArrays(pRowIndicesData,RowIndicesDataSize,pColIndicesData,ColIndicesDataSize);
241  if(rRowIndices.size() != RowIndicesDataSize)
242  rRowIndices.resize(RowIndicesDataSize);
243  IndexPartition<IndexType>(RowIndicesDataSize).for_each(
244  [&](IndexType i){rRowIndices[i] = pRowIndicesData[i];}
245  );
246 
247  delete [] pRowIndicesData;
248  if(rColIndices.size() != ColIndicesDataSize)
249  rColIndices.resize(ColIndicesDataSize);
250  IndexPartition<IndexType>(ColIndicesDataSize).for_each(
251  [&](IndexType i){rColIndices[i] = pColIndicesData[i];}
252  );
253  delete [] pColIndicesData;
254 
255  return rRowIndices.size();
256  }
257 
259  Kratos::span<IndexType>& rRowIndices,
260  Kratos::span<IndexType>& rColIndices
261  ) const = delete;
262 
263  //NOTE this function will transfer ownership of pRowIndicesData and pColIndicesData to the caller
264  //hence the caller will be in charge of deleting that array
266  IndexType*& pRowIndicesData,
267  IndexType& rRowDataSize,
268  IndexType*& pColIndicesData,
269  IndexType& rColDataSize
270  ) const
271  {
272  //need to detect the number of rows this way since there may be gaps
273  IndexType nrows=Size();
274 
275  pRowIndicesData = new IndexType[nrows+1];
276  rRowDataSize=nrows+1;
277  Kratos::span<IndexType> row_indices(pRowIndicesData, nrows+1);
278 
279  if(nrows == 0) //empty
280  {
281  row_indices[0] = 0;
282  }
283  else
284  {
285  //set it to zero in parallel to allow first touching
287  row_indices[i] = 0;
288  });
289 
290  //count the entries
292  row_indices[i+1] = mGraph[i].size();
293  });
294 
295  //sum entries
296  for(IndexType i = 1; i<static_cast<IndexType>(row_indices.size()); ++i){
297  row_indices[i] += row_indices[i-1];
298  }
299  }
300 
301  IndexType nnz = row_indices[nrows];
302  rColDataSize=nnz;
303  pColIndicesData = new IndexType[nnz];
304  Kratos::span<IndexType> col_indices(pColIndicesData,nnz);
305 
306  //set it to zero in parallel to allow first touching
307  IndexPartition<IndexType>(col_indices.size()).for_each([&](IndexType i){
308  col_indices[i] = 0;
309  });
310 
311  //count the entries
313 
314  IndexType start = row_indices[i];
315 
316  IndexType counter = 0;
317  for(auto index : mGraph[i]){
318  col_indices[start+counter] = index;
319  counter++;
320  }
321  });
322 
323  //reorder columns
324  IndexPartition<IndexType>(row_indices.size()-1).for_each([&](IndexType i){
325  std::sort(col_indices.begin()+row_indices[i], col_indices.begin()+row_indices[i+1]);
326  });
327 
328  return nrows;
329  }
330 
331  //this function returns the Graph as a single vector
332  //in the form of
333  // RowIndex NumberOfEntriesInTheRow .... list of all Indices in the row
334  //every row is pushed back one after the other
335  std::vector<IndexType> ExportSingleVectorRepresentation()
336  {
337  std::vector< IndexType > IJ;
338  IJ.push_back(GetGraph().size()); //number of rows
339  for(unsigned int I=0; I<GetGraph().size(); ++I)
340  {
341  IJ.push_back(I); //id of the row
342  IJ.push_back(mGraph[I].size()); //number of Js in the row
343  for(auto J : mGraph[I])
344  IJ.push_back(J); //J
345  }
346  return IJ;
347  }
348 
349  void AddFromSingleVectorRepresentation(const std::vector<IndexType>& rSingleVectorRepresentation)
350  {
351  auto graph_size = rSingleVectorRepresentation[0];
352  KRATOS_ERROR_IF(graph_size > GetGraph().size() ) << "mismatching size - attempting to add a graph with more rows than the ones allowed in graph" << std::endl;
353  IndexType counter = 1;
354  while(counter < rSingleVectorRepresentation.size())
355  {
356  auto I = rSingleVectorRepresentation[counter++];
357  auto nrow = rSingleVectorRepresentation[counter++];
358  auto begin = &rSingleVectorRepresentation[counter];
359  AddEntries(I, begin, begin+nrow);
360  counter += nrow;
361  }
362  }
363 
367 
368 
373  {
374  const_row_iterator map_iterator;
375  const_row_iterator mbegin;
376  public:
377  using iterator_category = std::forward_iterator_tag;
378  using difference_type = std::ptrdiff_t;
380  using pointer = typename GraphType::value_type*;
381  using reference = typename GraphType::value_type&;
382 
383  const_iterator_adaptor(const_row_iterator it) :map_iterator(it),mbegin(it) {}
385  : map_iterator(it.map_iterator),mbegin(it.mbegin) {}
386  const_iterator_adaptor& operator++() { map_iterator++; return *this; }
389  { return map_iterator == rhs.map_iterator; }
391  { return map_iterator != rhs.map_iterator; }
392  //TODO: is it correct that the two following operators are the same?
393  const typename GraphType::value_type& operator*() const { return *map_iterator; }
394  const typename GraphType::value_type& operator->() const { return *map_iterator; }
395  const_row_iterator& base() { return map_iterator; }
396  const_row_iterator const& base() const { return map_iterator; }
398  return map_iterator-mbegin;
399  }
400  };
401 
403  {
404  return const_iterator_adaptor( mGraph.begin() );
405  }
407  {
408  return const_iterator_adaptor( mGraph.end() );
409  }
410 
411 
415 
416 
420 
422  std::string Info() const
423  {
424  std::stringstream buffer;
425  buffer << "SparseContiguousRowGraph" ;
426  return buffer.str();
427  }
428 
430  void PrintInfo(std::ostream& rOStream) const {rOStream << "SparseContiguousRowGraph";}
431 
433  void PrintData(std::ostream& rOStream) const {}
434 
438 
439 
441 
442 protected:
445 
446 
450 
451 
455 
456 
460 
461 
465 
466 
470 
471 
475 
476 
478 
479 private:
482 
483 
487  DataCommunicator* mpComm;
488  GraphType mGraph;
489  std::vector<LockObject> mLocks;
490 
494  friend class Serializer;
495 
496  void save(Serializer& rSerializer) const
497  {
498  const IndexType N = this->Size();
499  rSerializer.save("GraphSize",N);
500  for(IndexType I=0; I<N; ++I)
501  {
502  IndexType row_size = mGraph[I].size();
503  rSerializer.save("row_size",row_size);
504  for(auto J : mGraph[I]){
505  rSerializer.save("J",J);
506  }
507  }
508  }
509 
510  void load(Serializer& rSerializer)
511  {
512  IndexType size;
513  rSerializer.load("GraphSize",size);
514 
515  mLocks = decltype(mLocks)(size);
516  mGraph.resize(size);
517 
518  for(IndexType I=0; I<size; ++I)
519  {
520  IndexType row_size;
521  rSerializer.load("row_size",row_size);
522  for(IndexType k=0; k<row_size; ++k){
523  IndexType J;
524  rSerializer.load("J",J);
525  AddEntry(I,J);
526  }
527  }
528  }
529 
530 
534 
535 
536 
540 
541 
545 
546 
550 
551 
552 
554 
555 }; // Class SparseContiguousRowGraph
556 
558 
561 
562 
566 
567 
569 template<class TIndexType=std::size_t>
570 inline std::istream& operator >> (std::istream& rIStream,
572  return rIStream;
573  }
574 
576 template<class TIndexType=std::size_t>
577 inline std::ostream& operator << (std::ostream& rOStream,
579 {
580  rThis.PrintInfo(rOStream);
581  rOStream << std::endl;
582  rThis.PrintData(rOStream);
583 
584  return rOStream;
585 }
587 
589 
590 } // namespace Kratos.
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
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
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
iterator end()
Definition: amatrix_interface.h:243
void clear()
Definition: amatrix_interface.h:284
iterator begin()
Definition: amatrix_interface.h:241
TDataType value_type
Definition: amatrix_interface.h:56
AMatrix::RandomAccessIterator< const TDataType > const_iterator
Definition: amatrix_interface.h:53
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 save(std::string const &rTag, std::array< TDataType, TDataSize > const &rObject)
Definition: serializer.h:545
Definition: sparse_contiguous_row_graph.h:373
const_iterator_adaptor & operator++()
Definition: sparse_contiguous_row_graph.h:386
const_iterator_adaptor(const_row_iterator it)
Definition: sparse_contiguous_row_graph.h:383
IndexType GetRowIndex() const
Definition: sparse_contiguous_row_graph.h:397
typename GraphType::value_type * pointer
Definition: sparse_contiguous_row_graph.h:380
const_row_iterator & base()
Definition: sparse_contiguous_row_graph.h:395
std::forward_iterator_tag iterator_category
Definition: sparse_contiguous_row_graph.h:377
typename GraphType::value_type value_type
Definition: sparse_contiguous_row_graph.h:379
typename GraphType::value_type & reference
Definition: sparse_contiguous_row_graph.h:381
const_row_iterator const & base() const
Definition: sparse_contiguous_row_graph.h:396
bool operator==(const const_iterator_adaptor &rhs) const
Definition: sparse_contiguous_row_graph.h:388
const_iterator_adaptor operator++(int)
Definition: sparse_contiguous_row_graph.h:387
const GraphType::value_type & operator->() const
Definition: sparse_contiguous_row_graph.h:394
const_iterator_adaptor(const const_iterator_adaptor &it)
Definition: sparse_contiguous_row_graph.h:384
bool operator!=(const const_iterator_adaptor &rhs) const
Definition: sparse_contiguous_row_graph.h:390
std::ptrdiff_t difference_type
Definition: sparse_contiguous_row_graph.h:378
const GraphType::value_type & operator*() const
Definition: sparse_contiguous_row_graph.h:393
Short class definition.
Definition: sparse_contiguous_row_graph.h:65
void Finalize()
Definition: sparse_contiguous_row_graph.h:220
void AddEntries(const TContainerType &rIndices)
Definition: sparse_contiguous_row_graph.h:192
void AddEntries(const SparseContiguousRowGraph &rOtherGraph)
Definition: sparse_contiguous_row_graph.h:212
void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: sparse_contiguous_row_graph.h:430
void AddEntries(const TContainerType &rRowIndices, const TContainerType &rColIndices)
Definition: sparse_contiguous_row_graph.h:204
void Clear()
Definition: sparse_contiguous_row_graph.h:135
const DataCommunicator * pGetComm() const
Definition: sparse_contiguous_row_graph.h:127
bool Has(const IndexType I, const IndexType J) const
Definition: sparse_contiguous_row_graph.h:145
IndexType GlobalIndex(const IndexType LocalIndex) const
Definition: sparse_contiguous_row_graph.h:160
IndexType LocalIndex(const IndexType GlobalIndex) const
Definition: sparse_contiguous_row_graph.h:156
std::vector< IndexType > ExportSingleVectorRepresentation()
Definition: sparse_contiguous_row_graph.h:335
SparseContiguousRowGraph()
Default constructor. - needs to be public for communicator, but it will fail if used in any other mod...
Definition: sparse_contiguous_row_graph.h:81
IndexType ExportCSRArrays(TVectorType &rRowIndices, TVectorType &rColIndices) const
Definition: sparse_contiguous_row_graph.h:231
SparseContiguousRowGraph(const SparseContiguousRowGraph &rOther)
Copy constructor.
Definition: sparse_contiguous_row_graph.h:111
GraphType::const_iterator const_row_iterator
Definition: sparse_contiguous_row_graph.h:71
void AddEntries(const IndexType RowIndex, const TIteratorType &rColBegin, const TIteratorType &rColEnd)
Definition: sparse_contiguous_row_graph.h:180
void AddEntry(const IndexType RowIndex, const IndexType ColIndex)
Definition: sparse_contiguous_row_graph.h:164
void AddEntries(const IndexType RowIndex, const TContainerType &rColIndices)
Definition: sparse_contiguous_row_graph.h:172
const_iterator_adaptor end() const
Definition: sparse_contiguous_row_graph.h:406
KRATOS_CLASS_POINTER_DEFINITION(SparseContiguousRowGraph)
Pointer definition of SparseContiguousRowGraph.
SparseContiguousRowGraph & operator=(SparseContiguousRowGraph const &rOther)=delete
Assignment operator. TODO: decide if we do want to allow it.
void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: sparse_contiguous_row_graph.h:433
DenseVector< std::unordered_set< IndexType > > GraphType
Definition: sparse_contiguous_row_graph.h:70
IndexType ExportCSRArrays(IndexType *&pRowIndicesData, IndexType &rRowDataSize, IndexType *&pColIndicesData, IndexType &rColDataSize) const
Definition: sparse_contiguous_row_graph.h:265
SparseContiguousRowGraph(IndexType GraphSize)
Definition: sparse_contiguous_row_graph.h:86
const DataCommunicator & GetComm() const
Definition: sparse_contiguous_row_graph.h:122
IndexType Size() const
Definition: sparse_contiguous_row_graph.h:141
void AddFromSingleVectorRepresentation(const std::vector< IndexType > &rSingleVectorRepresentation)
Definition: sparse_contiguous_row_graph.h:349
friend class Serializer
Definition: sparse_contiguous_row_graph.h:494
std::string Info() const
Turn back information as a string.
Definition: sparse_contiguous_row_graph.h:422
const GraphType::value_type & operator[](const IndexType &Key) const
Definition: sparse_contiguous_row_graph.h:151
~SparseContiguousRowGraph()
Destructor.
Definition: sparse_contiguous_row_graph.h:101
TIndexType IndexType
Definition: sparse_contiguous_row_graph.h:69
const_iterator_adaptor begin() const
Definition: sparse_contiguous_row_graph.h:402
const GraphType & GetGraph() const
Definition: sparse_contiguous_row_graph.h:225
IndexType ExportCSRArrays(Kratos::span< IndexType > &rRowIndices, Kratos::span< IndexType > &rColIndices) const =delete
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
start
Definition: DEM_benchmarks.py:17
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
rhs
Definition: generate_frictional_mortar_condition.py:297
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
def load(f)
Definition: ode_solve.py:307
int k
Definition: quadrature.py:595
int counter
Definition: script_THERMAL_CORRECT.py:218
J
Definition: sensitivityMatrix.py:58
N
Definition: sensitivityMatrix.py:29
integer i
Definition: TensorModule.f:17