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.
additive_schwarz_preconditioner.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: Manuel Messmer
11 //
12 
13 #if !defined(KRATOS_ADDITIVE_SCHWARZ_PRECONDITIONER_H_INCLUDED )
14 #define KRATOS_ADDITIVE_SCHWARZ_PRECONDITIONER_H_INCLUDED
15 
16 // System includes
17 
18 // External includes
19 
20 // Project includes
21 #include "includes/define.h"
24 #include "utilities/math_utils.h"
27 
28 namespace Kratos
29 {
30 
33 
43 template<class TSparseSpaceType, class TDenseSpaceType>
44 class AdditiveSchwarzPreconditioner : public Preconditioner<TSparseSpaceType, TDenseSpaceType>
45 {
46 public:
49 
52 
53  typedef std::size_t SizeType;
54  typedef std::size_t IndexType;
55 
57 
59 
60  typedef typename TSparseSpaceType::MatrixPointerType SparseMatrixPointerType;
61 
63 
65 
67 
71 
74  {
76  }
77 
80 
83  {
84  }
85 
89 
92 
96 
98  {
99  return true;
100  }
101 
103  DofsArrayType& rdof_set, ModelPart& r_model_part ) override
104  {
106 
107  if( ! mMatrixIsInitializedFlag ){
108  InitializeMatrix(rA);
110  } else {
111  TSparseSpaceType::SetToZero(*mpS);
112  }
113 
114  std::vector<ModelPart::ElementIterator> elements_to_consider;
115  elements_to_consider.reserve(r_model_part.NumberOfElements());
116 
117  // Find all unique elements. In case of NURBS patches, multiple elements (Quadrature Point Geometries)
118  // might be located within the same knot span.
119  VariableUtils().SetFlag(VISITED, false, r_model_part.Nodes());
120  const auto element_it_begin = r_model_part.ElementsBegin();
122  for( IndexType i = 0; i < r_model_part.NumberOfElements(); ++i){
123  auto element_it = element_it_begin + i;
124  auto& r_geometry = element_it->GetGeometry();
125  if( element_it->GetGeometry().GetGeometryType() == geometry_type ){
126  if( r_geometry[0].IsNot(VISITED) ){
127  r_geometry[0].Set(VISITED,true);
128  elements_to_consider.push_back(element_it);
129  }
130  } else {
131  elements_to_consider.push_back(element_it);
132  }
133  }
134 
135  // Assemble additive schwarz blocks
136  const auto element_to_consider_it_begin = elements_to_consider.begin();
137  IndexPartition<IndexType>(elements_to_consider.size()).for_each([&](IndexType i){
138  auto element_it = element_to_consider_it_begin + i;
139 
140  auto& r_geometry = (*element_it)->GetGeometry();
141  const SizeType number_nodes = r_geometry.size();
142  const SizeType number_dofs_per_node = r_geometry[0].GetDofs().size();
143 
144  std::vector<std::size_t> equation_ids;
145  equation_ids.reserve(number_nodes*number_dofs_per_node);
146  for( IndexType j = 0; j < r_geometry.size(); ++j){
147  for(auto& dof : r_geometry[j].GetDofs()){
148  equation_ids.push_back(dof->EquationId());
149  }
150  }
151  // Relaxation parameter
152  // Values from: Jomo et al., Hierarchical multigrid approaches for the finite cell
153  // method on uniform and multi-level hp-refined grids, CMAME, 2010.
154  // @TODO: Values must be adopted for overlapping "IGA additive schwarz blocks".
155  double omega = 1;
156  if( r_geometry.LocalSpaceDimension() == 2 ){
157  omega = 1.0/6.0;
158  } else if (r_geometry.LocalSpaceDimension() == 3){
159  omega = 1.0/18.0;
160  }
161  // Assemble preconditioning matrix S.
162  AssembleContributions(rA, *mpS, equation_ids, omega);
163  });
164 
165  KRATOS_INFO("AdditiveSchwarzPreconditioner:") << "Build Matrix Time: " << timer.ElapsedSeconds() << std::endl;
166  }
167 
171 
173  {
174  return rX;
175  }
176 
177  void Mult(SparseMatrixType& rA, VectorType& rX, VectorType& rY) override
178  {
179 
180  VectorType tmp = rX;
181  TSparseSpaceType::Mult(rA, tmp, rY);
182 
183  ApplyLeft(rY);
184 
185  }
186 
188  {
189  VectorType tmp = rX;
191 
192  return rX;
193  }
194 
196 
197  return rX;
198  }
199 
203 
205  std::string Info() const override
206  {
207  return "AdditiveSchwarzPreconditioner";
208  }
209 
211  void PrintInfo(std::ostream& OStream) const override
212  {
213  OStream << "AdditiveSchwarzPreconditioner";
214  }
215 
216  void PrintData(std::ostream& OStream) const override
217  {
218  }
219 
221 protected:
224 
225 
231 
233 
234 private:
235 
236  //@name Private operations
237 
238  void InitializeMatrix(SparseMatrixType& rA){
239 
241  SparseMatrixType& S = *mpS;
242 
243  S.resize(rA.size1(), rA.size1(), false);
244  S.reserve(rA.nnz_capacity(), false);
245 
246  double* Avalues = S.value_data().begin();
247  std::size_t* Arow_indices = S.index1_data().begin();
248  std::size_t* Acol_indices = S.index2_data().begin();
249 
250  std::size_t* Arow_indices_old = rA.index1_data().begin();
251  std::size_t* Acol_indices_old = rA.index2_data().begin();
252 
253  // Copy row indices
254  IndexPartition<std::size_t>(rA.index1_data().size()).for_each([&](IndexType i){
255  Arow_indices[i] = Arow_indices_old[i];
256  });
257  // Copy column indices
258  IndexPartition<std::size_t>(rA.index2_data().size()).for_each([&](IndexType i){
259  Acol_indices[i] = Acol_indices_old[i];
260  Avalues[i] = 0.0;
261  });
262 
263  S.set_filled(rA.filled1(),rA.filled2());
264  }
265 
266  void AssembleContributions(
267  SparseMatrixType& rA,
268  SparseMatrixType& rS,
269  Element::EquationIdVectorType& rEquationId,
270  double omega
271  )
272  {
273  const SizeType local_size = rEquationId.size();
274  std::sort(rEquationId.begin(), rEquationId.end() );
275 
277  for (IndexType i_local = 0; i_local < local_size; ++i_local) {
278  const IndexType i_global = rEquationId[i_local];
279  GetRowEntries(rA, M, i_global, i_local, rEquationId);
280  }
281 
282  DenseMatrixType M2;
283  M2.resize(local_size, local_size);
284  for( IndexType i = 0; i < local_size; ++i){
285  for( IndexType j = 0; j < local_size; ++j){
286  M2(i,j) = rA(rEquationId[i],rEquationId[j]);
287  }
288  }
289 
290  double M_det = 0.0;
292  M_invert = omega * M_invert;
293  //@TODO Replace this by dense solver.
294  MathUtils<double>::InvertMatrix(M, M_invert, M_det, -1e-6);
295 
296  for (IndexType i_local = 0; i_local < local_size; ++i_local) {
297  const IndexType i_global = rEquationId[i_local];
298  AssembleRowEntries(rS, M_invert, i_global, i_local, rEquationId);
299  }
300  }
301 
302  void AssembleRowEntries(SparseMatrixType& rA, const DenseMatrixType& rAlocal, const unsigned int i, const unsigned int i_local, std::vector<std::size_t>& rEquationId){
303  double* values_vector = rA.value_data().begin();
304  std::size_t* index1_vector = rA.index1_data().begin();
305  std::size_t* index2_vector = rA.index2_data().begin();
306 
307  size_t left_limit = index1_vector[i];
308 
309  //find the first entry
310  size_t last_pos = ForwardFind(rEquationId[0],left_limit,index2_vector);
311  size_t last_found = rEquationId[0];
312 
313  double& r_a = values_vector[last_pos];
314  const double& v_a = rAlocal(i_local,0);
315  AtomicAdd(r_a, v_a);
316 
317  //now find all of the other entries
318  size_t pos = 0;
319  for (unsigned int j=1; j<rEquationId.size(); j++) {
320  unsigned int id_to_find = rEquationId[j];
321  if(id_to_find > last_found) {
322  pos = ForwardFind(id_to_find,last_pos+1,index2_vector);
323  } else if(id_to_find < last_found) {
324  pos = BackwardFind(id_to_find,last_pos-1,index2_vector);
325  } else {
326  pos = last_pos;
327  }
328 
329  double& r = values_vector[pos];
330  const double& v = rAlocal(i_local,j);
331  AtomicAdd(r, v);
332 
333  last_found = id_to_find;
334  last_pos = pos;
335  }
336  }
337 
338  void GetRowEntries(SparseMatrixType& rA, DenseMatrixType& rAlocal, const unsigned int i, const unsigned int i_local, std::vector<std::size_t>& rEquationId){
339  double* values_vector = rA.value_data().begin();
340  std::size_t* index1_vector = rA.index1_data().begin();
341  std::size_t* index2_vector = rA.index2_data().begin();
342 
343  size_t left_limit = index1_vector[i];
344 
345  // Find the first entry
346  size_t last_pos = ForwardFind(rEquationId[0],left_limit,index2_vector);
347  size_t last_found = rEquationId[0];
348 
349  const double& r_a = values_vector[last_pos];
350  double& v_a = rAlocal(i_local,0);
351  AtomicAdd(v_a, r_a);
352 
353  // Now find all of the other entries
354  size_t pos = 0;
355  for (unsigned int j=1; j<rEquationId.size(); j++) {
356  unsigned int id_to_find = rEquationId[j];
357  if(id_to_find > last_found) {
358  pos = ForwardFind(id_to_find,last_pos+1,index2_vector);
359  } else if(id_to_find < last_found) {
360  pos = BackwardFind(id_to_find,last_pos-1,index2_vector);
361  } else {
362  pos = last_pos;
363  }
364 
365  const double& r = values_vector[pos];
366  double& v = rAlocal(i_local,j);
367  AtomicAdd(v, r);
368 
369  last_found = id_to_find;
370  last_pos = pos;
371  }
372  }
373 
374  inline unsigned int ForwardFind(const unsigned int id_to_find,
375  const unsigned int start,
376  const std::size_t* index_vector)
377  {
378  unsigned int pos = start;
379  while(id_to_find != index_vector[pos]) pos++;
380  return pos;
381  }
382 
383  inline unsigned int BackwardFind(const unsigned int id_to_find,
384  const unsigned int start,
385  const std::size_t* index_vector)
386  {
387  unsigned int pos = start;
388  while(id_to_find != index_vector[pos]) pos--;
389  return pos;
390  }
391 
392 }; // Class AdditiveSchwarzPreconditioner
393 
396 
399 
401 template<class TSparseSpaceType, class TDenseSpaceType>
402 inline std::istream& operator >> (std::istream& IStream,
404 {
405  return IStream;
406 }
407 
409 template<class TSparseSpaceType, class TDenseSpaceType>
410 inline std::ostream& operator << (std::ostream& OStream,
412 {
413  rThis.PrintInfo(OStream);
414  OStream << std::endl;
415  rThis.PrintData(OStream);
416 
417  return OStream;
418 }
420 
421 } // namespace Kratos.
422 
423 #endif // KRATOS_ADDITIVE_SCHWARZ_PRECONDITIONER_H_INCLUDED defined
424 
Definition: additive_schwarz_preconditioner.h:45
Preconditioner< TSparseSpaceType, TDenseSpaceType > BaseType
Definition: additive_schwarz_preconditioner.h:56
TSparseSpaceType::MatrixPointerType SparseMatrixPointerType
Definition: additive_schwarz_preconditioner.h:60
AdditiveSchwarzPreconditioner & operator=(const AdditiveSchwarzPreconditioner &Other)=delete
Assignment operator.
void Mult(SparseMatrixType &rA, VectorType &rX, VectorType &rY) override
Definition: additive_schwarz_preconditioner.h:177
std::size_t IndexType
Definition: additive_schwarz_preconditioner.h:54
void ProvideAdditionalData(SparseMatrixType &rA, VectorType &rX, VectorType &rB, DofsArrayType &rdof_set, ModelPart &r_model_part) override
Definition: additive_schwarz_preconditioner.h:102
void PrintInfo(std::ostream &OStream) const override
Print information about this object.
Definition: additive_schwarz_preconditioner.h:211
void PrintData(std::ostream &OStream) const override
Print object's data.
Definition: additive_schwarz_preconditioner.h:216
std::string Info() const override
Return information about this object.
Definition: additive_schwarz_preconditioner.h:205
AdditiveSchwarzPreconditioner()
Default constructor.
Definition: additive_schwarz_preconditioner.h:73
~AdditiveSchwarzPreconditioner() override
Destructor.
Definition: additive_schwarz_preconditioner.h:82
ModelPart::DofsArrayType DofsArrayType
Definition: additive_schwarz_preconditioner.h:66
KRATOS_CLASS_POINTER_DEFINITION(AdditiveSchwarzPreconditioner)
Counted pointer of AdditiveSchwarzPreconditioner.
bool AdditionalPhysicalDataIsNeeded() override
Definition: additive_schwarz_preconditioner.h:97
VectorType & ApplyLeft(VectorType &rX) override
Definition: additive_schwarz_preconditioner.h:187
VectorType & ApplyInverseRight(VectorType &rX) override
Definition: additive_schwarz_preconditioner.h:172
TDenseSpaceType::MatrixType DenseMatrixType
Definition: additive_schwarz_preconditioner.h:64
TSparseSpaceType::MatrixType SparseMatrixType
Definition: additive_schwarz_preconditioner.h:58
VectorType & Finalize(VectorType &rX) override
Definition: additive_schwarz_preconditioner.h:195
bool mMatrixIsInitializedFlag
Definition: additive_schwarz_preconditioner.h:230
AdditiveSchwarzPreconditioner(const AdditiveSchwarzPreconditioner &Other)=delete
Copy constructor.
SparseMatrixPointerType mpS
Definition: additive_schwarz_preconditioner.h:229
std::size_t SizeType
Definition: additive_schwarz_preconditioner.h:53
TSparseSpaceType::VectorType VectorType
Definition: additive_schwarz_preconditioner.h:62
Definition: builtin_timer.h:26
std::vector< std::size_t > EquationIdVectorType
Definition: element.h:98
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
static BoundedMatrix< double, TDim, TDim > InvertMatrix(const BoundedMatrix< double, TDim, TDim > &rInputMatrix, double &rInputMatrixDet, const double Tolerance=ZeroTolerance)
Calculates the inverse of a 2x2, 3x3 and 4x4 matrices (using bounded matrix for performance)
Definition: math_utils.h:197
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ElementIterator ElementsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1169
SizeType NumberOfElements(IndexType ThisIndex=0) const
Definition: model_part.h:1027
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
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
Preconditioner class.
Definition: preconditioner.h:75
TSparseSpaceType::VectorType VectorType
Definition: preconditioner.h:85
TSparseSpaceType::MatrixType SparseMatrixType
Definition: preconditioner.h:83
This class implements a set of auxiliar, already parallelized, methods to perform some common tasks r...
Definition: variable_utils.h:63
void SetFlag(const Flags &rFlag, const bool FlagValue, TContainerType &rContainer)
Sets a flag according to a given status over a given container.
Definition: variable_utils.h:900
std::size_t IndexType
The definition of the index type.
Definition: key_hash.h:35
#define KRATOS_INFO(label)
Definition: logger.h:250
start
Definition: DEM_benchmarks.py:17
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
TSpaceType::MatrixPointerType CreateEmptyMatrixPointer(TSpaceType &dummy)
Definition: add_strategies_to_python.cpp:181
void Mult(TSpaceType &dummy, typename TSpaceType::MatrixType &rA, typename TSpaceType::VectorType &rX, typename TSpaceType::VectorType &rY)
Definition: add_strategies_to_python.cpp:98
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
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
std::size_t SizeType
The definition of the size type.
Definition: mortar_classes.h:43
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
v
Definition: generate_convection_diffusion_explicit_element.py:114
int local_size
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:17
S
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:39
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
int dof
Definition: ode_solve.py:393
int j
Definition: quadrature.py:648
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
Definition: timer.py:1