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.
trilinos_block_builder_and_solver_periodic.h
Go to the documentation of this file.
1 // KRATOS _____ _ _ _
2 // |_ _| __(_) (_)_ __ ___ ___
3 // | || '__| | | | '_ \ / _ \/ __|
4 // | || | | | | | | | | (_) \__
5 // |_||_| |_|_|_|_| |_|\___/|___/ APPLICATION
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Jordi Cotela
11 //
12 
13 #ifndef KRATOS_TRILINOS_BLOCK_BUILDER_AND_SOLVER_PERIODIC_H
14 #define KRATOS_TRILINOS_BLOCK_BUILDER_AND_SOLVER_PERIODIC_H
15 
16 /* System includes */
17 #include <set>
18 /* #include <omp.h> */
19 
20 /* External includes */
21 // Trilinos includes
22 #include "Epetra_MpiComm.h"
23 #include "Epetra_Map.h"
24 #include "Epetra_Vector.h"
25 #include "Epetra_FECrsGraph.h"
26 #include "Epetra_FECrsMatrix.h"
27 #include "Epetra_IntSerialDenseVector.h"
28 #include "Epetra_SerialDenseMatrix.h"
29 #include "Epetra_SerialDenseVector.h"
30 
31 /* Project includes */
32 #include "includes/define.h"
33 #include "utilities/timer.h"
35 
36 namespace Kratos
37 {
38 
41 
67 template<class TSparseSpace,
68  class TDenseSpace,
69  class TLinearSolver //= LinearSolver<TSparseSpace,TDenseSpace>
70  >
72  : public TrilinosBlockBuilderAndSolver< TSparseSpace,TDenseSpace, TLinearSolver >
73 {
74 public:
78 
79 
81 
82  typedef TSparseSpace SparseSpaceType;
83 
85 
86  typedef typename BaseType::TDataType TDataType;
87 
89 
91 
93 
95 
99 
103 
105 
114  int guess_row_size,
115  typename TLinearSolver::Pointer pNewLinearSystemSolver,
116  const Kratos::Variable<int>& PeriodicIdVar):
117  TrilinosBlockBuilderAndSolver< TSparseSpace,TDenseSpace,TLinearSolver >(Comm,guess_row_size,pNewLinearSystemSolver),
118  mPeriodicIdVar(PeriodicIdVar)
119  {}
120 
121 
122 
126 
133 
140  void SetUpSystem(ModelPart &rModelPart) override
141  {
142  KRATOS_TRY;
143 
144  const int Rank = this->mrComm.MyPID();
145 
146  // Count the Dofs on this partition (on periodic node pairs, only the dofs on the node with higher Id are counted)
147  int DofCount = 0;
148 
149  for (typename DofsArrayType::iterator itDof = this->mDofSet.begin(); itDof != this->mDofSet.end(); ++itDof)
150  if ( (itDof->GetSolutionStepValue(PARTITION_INDEX) == Rank) && ( itDof->GetSolutionStepValue(mPeriodicIdVar) < static_cast<int>(itDof->Id())) )
151  DofCount++;
152 
153  // Periodic conditions on corners are counted separately
154  unsigned int ExtraDofs = SetUpEdgeDofs(rModelPart);
155  DofCount += ExtraDofs;
156 
157  // Comunicate the Dof counts to set a global numbering
158  int DofOffset;
159 
160  int ierr = this->mrComm.ScanSum(&DofCount,&DofOffset,1);
161  if (ierr != 0)
162  KRATOS_THROW_ERROR(std::runtime_error,"In TrilinosBlockBuilderAndSolverPeriodic::SetUpSystem: Found Epetra_MpiComm::ScanSum failure with error code ",ierr);
163 
164  DofOffset -= DofCount;
165  this->mFirstMyId = DofOffset;
166 
167  // Assing Id to all local nodes except for the second nodes on a periodic pair
168  for (typename DofsArrayType::iterator itDof = this->mDofSet.begin(); itDof != this->mDofSet.end(); ++itDof)
169  if ( (itDof->GetSolutionStepValue(PARTITION_INDEX) == Rank) && ( itDof->GetSolutionStepValue(mPeriodicIdVar) < static_cast<int>(itDof->Id()) ) )
170  itDof->SetEquationId(DofOffset++);
171  else
172  // If this rank is not responsible for assigning an EquationId to this Dof, reset the current value
173  // This is necessary when dealing with changing meshes, as we risk inadvertently reusing the previous EqIdValue
174  itDof->SetEquationId(0);
175 
176  // Synchronize Dof Ids across processes
177  rModelPart.GetCommunicator().SynchronizeDofs();
178 
179  // Once the non-repeated EquationId are assigned and synchronized, copy the EquationId to the second node on each periodic pair
180  for (ModelPart::ConditionIterator itCond = rModelPart.ConditionsBegin(); itCond != rModelPart.ConditionsEnd(); ++itCond)
181  {
182  ModelPart::ConditionType::GeometryType& rGeom = itCond->GetGeometry();
183  if (rGeom.PointsNumber() == 2) // Regular 2-noded conditions
184  {
185  int Node0 = rGeom[0].Id();
186  int Node0Pair = rGeom[0].FastGetSolutionStepValue(mPeriodicIdVar);
187 
188  int Node1 = rGeom[1].Id();
189  int Node1Pair = rGeom[1].FastGetSolutionStepValue(mPeriodicIdVar);
190  if ( Node0Pair == 0 || Node1Pair == 0 )
191  KRATOS_THROW_ERROR(std::runtime_error,"ERROR: a periodic condition has no periodic pair ids assigned. Condition Id is: ",itCond->Id());
192 
193  // If the nodes are marked as a periodic pair (this is to avoid acting on two-noded conditions that are not PeriodicCondition)
194  if ( ( Node0 == Node1Pair ) && ( Node1 == Node0Pair ) )
195  {
196  if ( Node0 < Node0Pair ) // If Node0 is the one with lower Id (the one that does not have an EquationId yet)
197  CopyEquationId(rGeom[1],rGeom[0]);
198  else
199  CopyEquationId(rGeom[0],rGeom[1]);
200  }
201  }
202  else if (rGeom.PointsNumber() == 4) // Special treatment for edge nodes
203  {
204  for (unsigned int i = 1; i < 4; i++)
205  CopyEquationId(rGeom[0],rGeom[i]);
206  }
207  else if (rGeom.PointsNumber() == 8) // Special treatment for edge nodes
208  {
209  for (unsigned int i = 1; i < 8; i++)
210  CopyEquationId(rGeom[0],rGeom[i]);
211  }
212  }
213 
214  // Synchronize Dof Ids across processes a second time to transfer the Ids of periodic nodes.
215  // Note that a custom communication routine is used, as the one provided by the communicator synchronizes all ghost values to the
216  // value on the owner process, while here the EquationId value is given by the owner of the PeriodicCondition,
217  // which is not necessarily the same as the owner of the node.
218  CommunicateEquationId(rModelPart.GetCommunicator());
219 
220  // Clean temporary values to ensure that future calls to SetUpDofSet work as intended
221  this->CleanEdgeDofData(rModelPart);
222 
223  // Store local and gloabal system size
224  int TotalDofNum;
225  ierr = this->mrComm.SumAll(&DofCount,&TotalDofNum,1);
226  if (ierr != 0)
227  KRATOS_THROW_ERROR(std::runtime_error,"In TrilinosBlockBuilderAndSolverPeriodic::SetUpSystem: Found Epetra_MpiComm::SumAll failure with error code ",ierr);
228 
229  this->mLocalSystemSize = DofCount;
230  this->mEquationSystemSize = TotalDofNum;
231  this->mLastMyId = DofOffset;
232 
233  /* some prints useful for debug
234  //std::cout << Rank << ": mLocalSystemSize " << this->mLocalSystemSize << " mEquationSystemSize " << this->mEquationSystemSize << " mLastMyId " << this->mLastMyId << " mFirstMyId " << this->mFirstMyId << std::endl;
235  for (typename DofsArrayType::iterator itDof = this->mDofSet.begin(); itDof != this->mDofSet.end(); ++itDof)
236  //if ( (itDof->GetSolutionStepValue(PARTITION_INDEX) == Rank) && ( itDof->GetSolutionStepValue(mPeriodicIdVar) < static_cast<int>(itDof->Id())) )
237  if (itDof->EquationId() == 0)
238  std::cout << "Rank: " << Rank << " node id " << itDof->Id() << " eq Id " << itDof->EquationId() << " var " << itDof->GetVariable().Name() << " partition index " << itDof->GetSolutionStepValue(PARTITION_INDEX) << " flag variable " << itDof->GetSolutionStepValue(FLAG_VARIABLE) << " periodic pair index " << itDof->GetSolutionStepValue(mPeriodicIdVar) << std::endl;
239  //std::cout << Rank << ": mLocalSystemSize " << this->mLocalSystemSize << " mEquationSystemSize " << this->mEquationSystemSize << " mLastMyId " << this->mLastMyId << " mFirstMyId " << this->mFirstMyId << std::endl;
240  */
241 
242  KRATOS_CATCH("");
243  }
244 
262 protected:
303 private:
312  const Kratos::Variable<int>& mPeriodicIdVar;
313 
324  void CopyEquationId(ModelPart::NodeType& rOrigin,
325  ModelPart::NodeType& rDest)
326  {
327  for ( Node::DofsContainerType::iterator itDof = rOrigin.GetDofs().begin(); itDof != rOrigin.GetDofs().end(); itDof++)
328  rDest.pGetDof( (*itDof)->GetVariable() )->SetEquationId( (*itDof)->EquationId() );
329  }
330 
332  void CommunicateEquationId(Communicator& rComm)
333  {
334  int rank;
335  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
336 
337  int destination = 0;
338 
339  Communicator::NeighbourIndicesContainerType& neighbours_indices = rComm.NeighbourIndices();
340 
341  for (unsigned int i_color = 0; i_color < neighbours_indices.size(); i_color++)
342  if ((destination = neighbours_indices[i_color]) >= 0)
343  {
344  Communicator::NodesContainerType& r_origin_nodes = rComm.GhostMesh(i_color).Nodes();
345  Communicator::NodesContainerType& r_dest_nodes = rComm.LocalMesh(i_color).Nodes();
346 
347  // Calculating send and received buffer size
348  unsigned int send_buffer_size = 0;
349  unsigned int receive_buffer_size = 0;
350 
351  for (Communicator::NodesContainerType::iterator i_node = r_origin_nodes.begin(); i_node != r_origin_nodes.end(); ++i_node)
352  send_buffer_size += i_node->GetDofs().size();
353 
354  for (Communicator::NodesContainerType::iterator i_node = r_dest_nodes.begin(); i_node != r_dest_nodes.end(); ++i_node)
355  receive_buffer_size += i_node->GetDofs().size();
356 
357  unsigned int position = 0;
358  int* send_buffer = new int[send_buffer_size];
359  int* receive_buffer = new int[receive_buffer_size];
360 
361 
362  // Filling the buffer
363  for (ModelPart::NodeIterator i_node = r_origin_nodes.begin(); i_node != r_origin_nodes.end(); ++i_node)
364  for (ModelPart::NodeType::DofsContainerType::iterator i_dof = i_node->GetDofs().begin(); i_dof != i_node->GetDofs().end(); i_dof++)
365  send_buffer[position++] = (*i_dof)->EquationId();
366 
367 
368  MPI_Status status;
369 
370  if (position > send_buffer_size)
371  std::cout << rank << " Error in estimating send buffer size...." << std::endl;
372 
373 
374  int send_tag = i_color;
375  int receive_tag = i_color;
376 
377  MPI_Sendrecv(send_buffer, send_buffer_size, MPI_INT, destination, send_tag, receive_buffer, receive_buffer_size, MPI_INT, destination, receive_tag,
378  MPI_COMM_WORLD, &status);
379 
380  // Updating nodes
381  position = 0;
382  for (ModelPart::NodeIterator i_node = r_dest_nodes.begin();
383  i_node != r_dest_nodes.end(); i_node++)
384  for (ModelPart::NodeType::DofsContainerType::iterator i_dof = i_node->GetDofs().begin(); i_dof != i_node->GetDofs().end(); i_dof++)
385  {
386  unsigned int NewId = static_cast<unsigned int>(receive_buffer[position++]);
387  if (NewId > (*i_dof)->EquationId()) // Note: in a general case, only one rank will have assinged an EquationId, the others will send 0s
388  (*i_dof)->SetEquationId(NewId);
389  }
390 
391  if (position > receive_buffer_size)
392  std::cout << rank << " Error in estimating receive buffer size...." << std::endl;
393 
394  delete [] send_buffer;
395  delete [] receive_buffer;
396  }
397 
398  // Once we are sure that the owner process of all nodes knows its equation id, replicate its value to all ghost images
399  rComm.SynchronizeDofs();
400  }
401 
403 
406  unsigned int SetUpEdgeDofs(ModelPart& rModelPart)
407  {
408  int LocalNodesNum = rModelPart.GetCommunicator().LocalMesh().Nodes().size();
409  int GlobalNodesNum = 0;
410  this->mrComm.SumAll(&LocalNodesNum,&GlobalNodesNum,1);
411 
412  int NumProcs = this->mrComm.NumProc();
413  int* ExtraDofs = new int[NumProcs];
414  for (int i = 0; i < NumProcs; i++) ExtraDofs[i] = 0;
415 
417  const ProcessInfo& rProcessInfo = rModelPart.GetProcessInfo();
418  for (ModelPart::ConditionIterator itCond = rModelPart.ConditionsBegin(); itCond != rModelPart.ConditionsEnd(); ++itCond)
419  {
420  Condition::GeometryType& rGeom = itCond->GetGeometry();
421  const unsigned int NumNodes = rGeom.PointsNumber();
422  // mPeriodicIdVar > GlobalNodesNum is an imposible value for regular periodic nodes, which we use to signal edges
423  if ( ( NumNodes == 4 || NumNodes == 8 ) && rGeom[0].FastGetSolutionStepValue(mPeriodicIdVar) > GlobalNodesNum )
424  {
425  unsigned int FirstNode = rGeom[0].Id();
426  // KLUDGE: the following call should go through the scheme!!
427  itCond->GetDofList(DofList,rProcessInfo);
428  for(typename Condition::DofsVectorType::iterator iDof = DofList.begin() ; iDof != DofList.end() ; ++iDof)
429  if ( (*iDof)->Id() == FirstNode)
430  ExtraDofs[(*iDof)->GetSolutionStepValue(PARTITION_INDEX)]++;
431 
432  rGeom[0].GetValue(mPeriodicIdVar) = rGeom[0].FastGetSolutionStepValue(mPeriodicIdVar);
433  }
434  }
435 
436  int* TotalExtraDofs = new int[NumProcs];
437  for (int i = 0; i < NumProcs; i++) TotalExtraDofs[i] = 0;
438 
439  this->mrComm.SumAll(ExtraDofs,TotalExtraDofs,NumProcs);
440 
441  // free memory
442  int LocalExtraDofs = TotalExtraDofs[this->mrComm.MyPID()];
443  delete [] ExtraDofs;
444  delete [] TotalExtraDofs;
445 
446  // Prepare edge dofs so only one of the duplicates gets an equation Id
447  rModelPart.GetCommunicator().AssembleNonHistoricalData(mPeriodicIdVar);
448  for ( ModelPart::NodeIterator iNode = rModelPart.NodesBegin(); iNode != rModelPart.NodesEnd(); iNode++)
449  if ( iNode->GetValue(mPeriodicIdVar) != 0)
450  iNode->FastGetSolutionStepValue(mPeriodicIdVar) = 0;
451 
452  return LocalExtraDofs;
453  }
454 
456 
458  void CleanEdgeDofData(ModelPart& rModelPart)
459  {
460  for ( ModelPart::NodeIterator iNode = rModelPart.NodesBegin(); iNode != rModelPart.NodesEnd(); iNode++)
461  if ( iNode->GetValue(mPeriodicIdVar) != 0)
462  {
463  iNode->FastGetSolutionStepValue(mPeriodicIdVar) = iNode->GetValue(mPeriodicIdVar);
464  iNode->GetValue(mPeriodicIdVar) = 0;
465  }
466  }
467 
468 
486 }; /* Class TrilinosBlockBuilderAndSolverPeriodic */
487 
497 
498 } /* namespace Kratos.*/
499 
500 
501 #endif // KRATOS_TRILINOS_BLOCK_BUILDER_AND_SOLVER_PERIODIC_H
TSparseSpace::VectorType TSystemVectorType
Definition of the vector size.
Definition: builder_and_solver.h:85
ModelPart::NodesContainerType NodesArrayType
The containers of the entities.
Definition: builder_and_solver.h:109
TSparseSpace::MatrixType TSystemMatrixType
Definition of the sparse matrix.
Definition: builder_and_solver.h:82
ModelPart::ConditionsContainerType ConditionsArrayType
Definition: builder_and_solver.h:111
TDenseSpace::MatrixType LocalSystemMatrixType
The local matrix definition.
Definition: builder_and_solver.h:94
TSparseSpace::VectorPointerType TSystemVectorPointerType
Definition of the pointer to the vector.
Definition: builder_and_solver.h:91
TSparseSpace::DataType TDataType
Definition of the data type.
Definition: builder_and_solver.h:79
DofsArrayType mDofSet
Pointer to the linear solver.
Definition: builder_and_solver.h:739
TDenseSpace::VectorType LocalSystemVectorType
The local vector definition.
Definition: builder_and_solver.h:97
TSparseSpace::MatrixPointerType TSystemMatrixPointerType
Definition of the pointer to the sparse matrix.
Definition: builder_and_solver.h:88
unsigned int mEquationSystemSize
Flag taking in account if it is needed or not to calculate the reactions.
Definition: builder_and_solver.h:747
ModelPart::ElementsContainerType ElementsArrayType
Definition: builder_and_solver.h:110
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: communicator.h:99
virtual bool SynchronizeDofs()
Definition: communicator.cpp:352
DenseVector< int > NeighbourIndicesContainerType
Definition: communicator.h:92
std::vector< DofType::Pointer > DofsVectorType
Definition: condition.h:100
Geometry< NodeType > GeometryType
definition of the geometry type with given NodeType
Definition: condition.h:83
void SetEquationId(EquationIdType NewEquationId)
Definition: dof.h:331
Geometry base class.
Definition: geometry.h:71
SizeType PointsNumber() const
Definition: geometry.h:528
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ConditionIterator ConditionsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1361
Communicator & GetCommunicator()
Definition: model_part.h:1821
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
MeshType::ConditionIterator ConditionIterator
Definition: model_part.h:189
ConditionIterator ConditionsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1371
This class defines the node.
Definition: node.h:65
DofsContainerType & GetDofs()
Definition: node.h:694
DofType::Pointer pGetDof(TVariableType const &rDofVariable) const
Get DoF counted pointer for a given variable.
Definition: node.h:711
A sorted associative container similar to an STL set, but uses a vector to store pointers to its data...
Definition: pointer_vector_set.h:72
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: pointer_vector_set.h:95
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
iterator begin()
Returns an iterator pointing to the beginning of the container.
Definition: pointer_vector_set.h:278
This class provides the implementation of the basic tasks that are needed by the solution strategy.
Definition: scheme.h:56
Current class provides an implementation for trilinos builder and solving operations.
Definition: trilinos_block_builder_and_solver.h:85
EpetraCommunicatorType & mrComm
Definition: trilinos_block_builder_and_solver.h:1175
int mFirstMyId
The local system size.
Definition: trilinos_block_builder_and_solver.h:1178
IndexType mLocalSystemSize
The guess row size.
Definition: trilinos_block_builder_and_solver.h:1177
int mLastMyId
Auxiliary Id (the first row of the local system)
Definition: trilinos_block_builder_and_solver.h:1179
Definition: trilinos_block_builder_and_solver_periodic.h:73
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
BaseType::TSystemVectorType TSystemVectorType
Definition: trilinos_block_builder_and_solver_periodic.h:92
BaseType::TSchemeType TSchemeType
Definition: trilinos_block_builder_and_solver_periodic.h:84
BaseType::ElementsContainerType ElementsContainerType
Definition: trilinos_block_builder_and_solver_periodic.h:104
BaseType::LocalSystemVectorType LocalSystemVectorType
Definition: trilinos_block_builder_and_solver_periodic.h:94
void SetUpSystem(ModelPart &rModelPart) override
Assign an Equation Id to all degrees of freedom in the system.
Definition: trilinos_block_builder_and_solver_periodic.h:140
BaseType::NodesArrayType NodesArrayType
Definition: trilinos_block_builder_and_solver_periodic.h:100
BaseType::LocalSystemMatrixType LocalSystemMatrixType
Definition: trilinos_block_builder_and_solver_periodic.h:96
BaseType::TSystemMatrixType TSystemMatrixType
Definition: trilinos_block_builder_and_solver_periodic.h:90
TSparseSpace SparseSpaceType
Definition: trilinos_block_builder_and_solver_periodic.h:82
TrilinosBlockBuilderAndSolverPeriodic(Epetra_MpiComm &Comm, int guess_row_size, typename TLinearSolver::Pointer pNewLinearSystemSolver, const Kratos::Variable< int > &PeriodicIdVar)
Definition: trilinos_block_builder_and_solver_periodic.h:113
TrilinosBlockBuilderAndSolver< TSparseSpace, TDenseSpace, TLinearSolver > BaseType
Definition: trilinos_block_builder_and_solver_periodic.h:80
BaseType::TDataType TDataType
Definition: trilinos_block_builder_and_solver_periodic.h:86
BaseType::TSystemMatrixPointerType TSystemMatrixPointerType
Definition: trilinos_block_builder_and_solver_periodic.h:97
virtual ~TrilinosBlockBuilderAndSolverPeriodic()
Definition: trilinos_block_builder_and_solver_periodic.h:125
BaseType::ConditionsArrayType ConditionsArrayType
Definition: trilinos_block_builder_and_solver_periodic.h:102
BaseType::DofsArrayType DofsArrayType
Definition: trilinos_block_builder_and_solver_periodic.h:88
BaseType::ElementsArrayType ElementsArrayType
Definition: trilinos_block_builder_and_solver_periodic.h:101
BaseType::TSystemVectorPointerType TSystemVectorPointerType
Definition: trilinos_block_builder_and_solver_periodic.h:98
KRATOS_CLASS_POINTER_DEFINITION(TrilinosBlockBuilderAndSolverPeriodic)
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
ProcessInfo
Definition: edgebased_PureConvection.py:116
integer i
Definition: TensorModule.f:17