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_system_vector.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 #if !defined(KRATOS_DISTRIBUTED_SYSTEM_VECTOR_H_INCLUDED )
13 #define KRATOS_DISTRIBUTED_SYSTEM_VECTOR_H_INCLUDED
14 
15 
16 // System includes
17 #include <string>
18 #include <iostream>
19 #include <functional>
20 
21 // External includes
22 
23 
24 // Project includes
25 #include "includes/define.h"
33 
34 namespace Kratos
35 {
38 
41 
45 
49 
53 
57 
59 template<class TDataType=double, class TIndexType=std::size_t>
61 {
62 public:
65  typedef TDataType value_type;
66  typedef TIndexType IndexType;
67  typedef int MpiIndexType;
68 
69 
72 
76 
78  :
79  mpComm(&rGraph.GetComm())
80  {
81  mpNumbering = Kratos::make_unique< DistributedNumbering<IndexType> >( rGraph.GetRowNumbering());
82 
83  mLocalData.resize(rGraph.LocalSize(),false);
84 
85  //now add entries in nonlocal data;
86  const auto& r_non_local_graphs = rGraph.GetNonLocalGraphs();
87 
88  for(IndexType cpu_id=0; cpu_id < r_non_local_graphs.size(); cpu_id++) //this loop cannot be done in parallel since we need to allocate memory in the unordered_map
89  {
90  const auto& graph = r_non_local_graphs[cpu_id];
91  for(auto item=graph.begin(); item!=graph.end(); ++item)
92  {
93  IndexType global_id = GetNumbering().RemoteGlobalId(item.GetRowIndex(), cpu_id);
94  mNonLocalData[global_id] = TDataType(); //first touching of nonlocaldata
95  }
96  }
97  }
98 
101  :
102  mpComm(&rOther.GetComm())
103  {
104  mpNumbering = Kratos::make_unique<DistributedNumbering<IndexType>>(rOther.GetNumbering());
105  KRATOS_ERROR_IF(LocalSize() != rOther.LocalSize());
106  KRATOS_ERROR_IF(Size() != rOther.Size());
107  //copying the data
108  mLocalData.resize(rOther.LocalSize(),false);
110  (mLocalData)[i] = rOther[i];
111  });
112  mNonLocalData = rOther.mNonLocalData;
113  if(rOther.mpexporter != nullptr) //this will happen if Finalize was not called on the vector we construct from
114  mpexporter = Kratos::make_unique<DistributedVectorExporter<IndexType>>(rOther.GetExporter());
115  }
116 
117  //WARNING: if a Distributed vector is constructed using this constructor, it cannot be used for assembly (non local entries are not precomputed)
119  :
120  mpComm(&rNumbering.GetComm())
121  {
122  mpNumbering = Kratos::make_unique< DistributedNumbering<IndexType> >( rNumbering );
123  mLocalData.resize(rNumbering.LocalSize(),false);
124  }
125 
128 
132  const DataCommunicator& GetComm() const{
133  return *mpComm;
134  }
135 
136  const DataCommunicator* pGetComm() const{
137  return mpComm;
138  }
139 
141  {
142  return *mpNumbering;
143  }
144 
145  void Clear()
146  {
147  mLocalData.clear();
148  }
149 
150  void SetValue(const TDataType value)
151  {
152  IndexPartition<IndexType>(mLocalData.size()).for_each([&](IndexType i){
153  mLocalData[i] = value;
154  });
155  }
156 
157  TDataType& operator()(IndexType I){
158  return mLocalData[I];
159  }
160 
161 
162  const TDataType& operator()(IndexType I) const{
163  return mLocalData[I];
164  }
165 
166  TDataType& operator[](IndexType I){
167  return mLocalData[I];
168  }
169 
170  const TDataType& operator[](IndexType I) const{
171  return mLocalData[I];
172  }
173 
174  inline IndexType Size() const{
175  return mpNumbering->Size();
176  }
177 
178  inline IndexType LocalSize() const{
179  return mpNumbering->LocalSize();
180  }
181 
183  return mLocalData;
184  }
185 
187  return mLocalData;
188  }
189 
191  KRATOS_DEBUG_ERROR_IF(mpexporter==nullptr) << " mpexporter was not initialized, GetExporter() cannot be used" << std::endl;
192  return *mpexporter;
193  }
194 
195  //function to add and empty entry to mNonLocalData
196  void AddEntry(TIndexType GlobalI) //WARNING: NOT THREADSAFE!
197  {
198  if( !GetNumbering().IsLocal(GlobalI))
199  mNonLocalData[GlobalI] = TDataType();
200  }
201 
202  //function to add empty entries entry to mNonLocalData
203  template<class TIteratorType>
204  void AddEntries(TIteratorType it_begin, TIteratorType it_end) //WARNING: NOT THREADSAFE!
205  {
206  for(TIteratorType it=it_begin; it!=it_end; ++it)
207  AddEntry(*it);
208  }
209 
210  TDataType Dot(const DistributedSystemVector& rOtherVector, MpiIndexType gather_on_rank=0)
211  {
212  const auto& other_data = rOtherVector.GetLocalData();
213  TDataType dot_value = IndexPartition<IndexType>(mLocalData.size()).template for_each<SumReduction<TDataType>>([&](IndexType i){
214  return mLocalData[i]*other_data[i];
215  });
216 
217  dot_value = GetComm().Sum(dot_value, gather_on_rank);
218  if(GetComm().Rank() != gather_on_rank) dot_value = -1; //give an impossible result in case it is not on the reduction rank
219  return dot_value; // note that the value to be reduced should be returned
220  }
221 
222 
223  void Add(const TDataType factor,
224  const DistributedSystemVector& rOtherVector
225  )
226  {
227  KRATOS_ERROR_IF(LocalSize() != rOtherVector.LocalSize()) << "size mismatch in Add Function. LocalSize is " << LocalSize()
228  << " " << " rOtherVector.LocalSize() " << rOtherVector.LocalSize() << std::endl;
229 
231  (mLocalData)[i] += factor*rOtherVector.mLocalData[i];
232  });
233  }
234 
237  KRATOS_ERROR_IF(LocalSize() != rOtherVector.LocalSize()) << "size mismatch in assinement operator. LocalSize is " << LocalSize()
238  << " " << " rOtherVector.LocalSize() " << rOtherVector.LocalSize() << std::endl;
240  (mLocalData)[i] = rOtherVector.mLocalData[i];
241  });
242  return *this;
243  }
244 
245 
247  {
248  KRATOS_ERROR_IF(LocalSize() != rOtherVector.LocalSize()) << "size mismatch in += operator. LocalSize is " << LocalSize()
249  << " " << " rOtherVector.LocalSize() " << rOtherVector.LocalSize() << std::endl;
251  (mLocalData)[i] += rOtherVector.mLocalData[i];
252  });
253  return *this;
254  }
255 
257  {
258  KRATOS_ERROR_IF(LocalSize() != rOtherVector.LocalSize()) << "size mismatch in -= operator. LocalSize is " << LocalSize()
259  << " " << " rOtherVector.LocalSize() " << rOtherVector.LocalSize() << std::endl;
261  (mLocalData)[i] -= rOtherVector.mLocalData[i];
262  });
263  return *this;
264  }
265 
266  DistributedSystemVector& operator*=(const TDataType& multiplier_factor)
267  {
269  (mLocalData)[i] *= multiplier_factor;
270  });
271  return *this;
272  }
273 
274  DistributedSystemVector& operator/=(const TDataType& divide_factor)
275  {
277  (mLocalData)[i] /= divide_factor;
278  });
279  return *this;
280  }
281 
286 
287  //mount exporter. After this point it will be all threadsafe since we will consider as frozen the mNonLocalData structure
288  DenseVector<double> non_local_global_ids(mNonLocalData.size());
289  IndexType counter = 0;
290  for(auto & item : mNonLocalData) //cannot be done in parallel
291  {
292  non_local_global_ids[counter] = item.first;
293  item.second = 0.0; //set to zero prior to assmeply
294  counter++;
295  }
296  auto ptmp = Kratos::make_unique< DistributedVectorExporter<TIndexType> >(GetComm(), non_local_global_ids, GetNumbering());
297  mpexporter.swap(ptmp);
298  }
299 
300  //communicate data to finalize the assembly
302  {
303  DenseVector<double> non_local_data(mNonLocalData.size());
304 
305  IndexType counter = 0;
306  for(auto & item : mNonLocalData) //cannot be done in parallel
307  {
308  non_local_data[counter] = item.second;
309  counter++;
310  }
311 
312  mpexporter->Apply(*this,non_local_data);
313  }
314 
315  template<class TVectorType, class TIndexVectorType >
316  void Assemble(
317  const TVectorType& rVectorInput,
318  const TIndexVectorType& EquationId
319  )
320  {
321  KRATOS_DEBUG_ERROR_IF(rVectorInput.size() != EquationId.size());
322 
323  for(unsigned int i=0; i<EquationId.size(); ++i){
324  IndexType global_i = EquationId[i];
325 
326  if(GetNumbering().IsLocal(global_i))
327  {
328  IndexType local_i = GetNumbering().LocalId(global_i);
329  AtomicAdd(mLocalData(local_i) , rVectorInput[i]);
330  }
331  else
332  {
333  auto it = (mNonLocalData.find( global_i ));
334  KRATOS_DEBUG_ERROR_IF(it == mNonLocalData.end()) << "global_i = "<< global_i << " not in mNonLocalData. Please note that the mNonLocalData structure is assumed fixed after InitializeAssemble is called" << std::endl; //this error is needed for threadsafety
335  TDataType& value = (*it).second;
336  AtomicAdd(value , rVectorInput[i]);
337  }
338  }
339  }
340 
344 
345 
349 
350 
354 
356  std::string Info() const
357  {
358  std::stringstream buffer;
359  buffer << "DistributedSystemVector" ;
360  return buffer.str();
361  }
362 
364  void PrintInfo(std::ostream& rOStream) const
365  {
366  rOStream << "DistributedSystemVector LOCAL DATA:" << std::endl;
367  }
368 
370  void PrintData(std::ostream& rOStream) const {
371  const auto k = GetComm().Rank();
372  std::cout << "Local Size=" << LocalSize() << " Total Size=" << GetNumbering().Size() << std::endl;
373  std::cout << "Numbering begins with " << GetNumbering().GetCpuBounds()[k] << " ends at " << GetNumbering().GetCpuBounds()[k+1] << std::endl;
374  std::cout << mLocalData << std::endl;
375  }
376 
380 
381 
383 
384 protected:
387 
388 
392 
393 
397 
398 
402 
403 
407 
408 
412 
413 
417 
418 
420 
421 private:
424 
425 
429  const DataCommunicator* mpComm;
431 
432  DenseVector<TDataType> mLocalData; //contains the local data
433  std::unordered_map<IndexType, TDataType> mNonLocalData; //contains non local data as {global_id,value}
434 
435  typename DistributedVectorExporter<TIndexType>::UniquePointer mpexporter = nullptr;
436 
440 
441 
445 
446 
450 
451 
455 
456 
460 
461 
463 
464 }; // Class DistributedSystemVector
465 
467 
470 
471 
475 
476 
478 template<class TDataType, class TIndexType>
479 inline std::istream& operator >> (std::istream& rIStream,
481  {
482  return rIStream;
483  }
484 
486 template<class TDataType, class TIndexType>
487 inline std::ostream& operator << (std::ostream& rOStream,
489 {
490  rThis.PrintInfo(rOStream);
491  rOStream << std::endl;
492  rThis.PrintData(rOStream);
493 
494  return rOStream;
495 }
497 
499 
500 } // namespace Kratos.
501 
502 #endif // KRATOS_DISTRIBUTED_SYSTEM_VECTOR_H_INCLUDED defined
503 
504 
Serial (do-nothing) version of a wrapper class for MPI communication.
Definition: data_communicator.h:318
virtual int Rank() const
Get the parallel rank for this DataCommunicator.
Definition: data_communicator.h:587
IndexType LocalSize() const
Definition: distributed_numbering.h:161
IndexType RemoteGlobalId(const IndexType rRemoteLocalId, const IndexType rOwnerRank) const
Definition: distributed_numbering.h:195
IndexType LocalId(const IndexType rGlobalId) const
Definition: distributed_numbering.h:178
const std::vector< IndexType > & GetCpuBounds() const
Definition: distributed_numbering.h:215
IndexType Size() const
Definition: distributed_numbering.h:167
Short class definition.
Definition: distributed_sparse_graph.h:68
const DenseVector< NonLocalGraphType > & GetNonLocalGraphs() const
Definition: distributed_sparse_graph.h:295
const DistributedNumbering< IndexType > & GetRowNumbering() const
Definition: distributed_sparse_graph.h:111
IndexType LocalSize() const
Definition: distributed_sparse_graph.h:121
Provides a DistributedSystemVector which implements FEM assemble capabilities.
Definition: distributed_system_vector.h:61
TDataType value_type
Definition: distributed_system_vector.h:65
TDataType & operator[](IndexType I)
Definition: distributed_system_vector.h:166
void Add(const TDataType factor, const DistributedSystemVector &rOtherVector)
Definition: distributed_system_vector.h:223
const DataCommunicator & GetComm() const
Definition: distributed_system_vector.h:132
void FinalizeAssemble()
Definition: distributed_system_vector.h:301
DistributedSystemVector & operator+=(const DistributedSystemVector &rOtherVector)
Definition: distributed_system_vector.h:246
IndexType LocalSize() const
Definition: distributed_system_vector.h:178
TDataType & operator()(IndexType I)
Definition: distributed_system_vector.h:157
TDataType Dot(const DistributedSystemVector &rOtherVector, MpiIndexType gather_on_rank=0)
Definition: distributed_system_vector.h:210
TIndexType IndexType
Definition: distributed_system_vector.h:66
DenseVector< TDataType > & GetLocalData()
Definition: distributed_system_vector.h:182
DistributedSystemVector(const DistributedSparseGraph< IndexType > &rGraph)
Definition: distributed_system_vector.h:77
~DistributedSystemVector()
Destructor.
Definition: distributed_system_vector.h:127
void AddEntry(TIndexType GlobalI)
Definition: distributed_system_vector.h:196
void BeginAssemble()
Definition: distributed_system_vector.h:285
DistributedSystemVector & operator=(DistributedSystemVector const &rOtherVector)
Assignment operator.
Definition: distributed_system_vector.h:236
std::string Info() const
Turn back information as a string.
Definition: distributed_system_vector.h:356
IndexType Size() const
Definition: distributed_system_vector.h:174
void Assemble(const TVectorType &rVectorInput, const TIndexVectorType &EquationId)
Definition: distributed_system_vector.h:316
void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: distributed_system_vector.h:370
DistributedSystemVector(DistributedSystemVector const &rOther)
Copy constructor.
Definition: distributed_system_vector.h:100
const DistributedNumbering< IndexType > & GetNumbering() const
Definition: distributed_system_vector.h:140
const DistributedVectorExporter< TIndexType > & GetExporter() const
Definition: distributed_system_vector.h:190
const DataCommunicator * pGetComm() const
Definition: distributed_system_vector.h:136
DistributedSystemVector & operator-=(const DistributedSystemVector &rOtherVector)
Definition: distributed_system_vector.h:256
KRATOS_CLASS_POINTER_DEFINITION(DistributedSystemVector)
Pointer definition of DistributedSystemVector.
const DenseVector< TDataType > & GetLocalData() const
Definition: distributed_system_vector.h:186
DistributedSystemVector & operator*=(const TDataType &multiplier_factor)
Definition: distributed_system_vector.h:266
void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: distributed_system_vector.h:364
DistributedSystemVector(const DistributedNumbering< IndexType > &rNumbering)
Definition: distributed_system_vector.h:118
const TDataType & operator[](IndexType I) const
Definition: distributed_system_vector.h:170
void SetValue(const TDataType value)
Definition: distributed_system_vector.h:150
DistributedSystemVector & operator/=(const TDataType &divide_factor)
Definition: distributed_system_vector.h:274
const TDataType & operator()(IndexType I) const
Definition: distributed_system_vector.h:162
void Clear()
Definition: distributed_system_vector.h:145
void AddEntries(TIteratorType it_begin, TIteratorType it_end)
Definition: distributed_system_vector.h:204
int MpiIndexType
Definition: distributed_system_vector.h:67
Provides a DistributedVectorExporter which implements FEM assemble capabilities.
Definition: distributed_vector_exporter.h:54
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
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_DEBUG_ERROR_IF(conditional)
Definition: exception.h:171
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
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
int k
Definition: quadrature.py:595
int counter
Definition: script_THERMAL_CORRECT.py:218
integer i
Definition: TensorModule.f:17
float factor
for node in (self.combined_model_part).Nodes: pold = node.GetSolutionStepValue(PRESSURE,...
Definition: ulf_PGLASS.py:254