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.
static_condensation_utility.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: Klauss B Sautter
11 // Philipp Bucher
12 // Vahid Galavi
13 
14 #if !defined(KRATOS_GEO_STATIC_CONDENSATION_UTILITY_H_INCLUDED )
15 #define KRATOS_GEO_STATIC_CONDENSATION_UTILITY_H_INCLUDED
16 
17 
18 // System includes
19 
20 
21 // External includes
22 
23 
24 // Project includes
25 #include "includes/define.h"
26 #include "utilities/math_utils.h"
27 
28 
29 namespace Kratos
30 {
31 
40 {
41 public:
43 typedef std::size_t SizeType;
45 
54  ElementType& rTheElement,
55  MatrixType& rLeftHandSideMatrix,
56  const std::vector<int> & rDofList)
57 {
59  const SizeType num_dofs_condensed = rDofList.size();
60  const SizeType num_dofs_remaining = GetNumDofsElement(rTheElement) - num_dofs_condensed;
61  const double numerical_limit = std::numeric_limits<double>::epsilon();
62 
63  std::vector<MatrixType> sub_matrices = CalculateSchurComplements(rTheElement, rLeftHandSideMatrix,rDofList);
64  //1.) inverse K22
65  MatrixType K_temp = ZeroMatrix(sub_matrices[3].size1());
66  double detK22 = 0.00;
67  MathUtils<double>::InvertMatrix(sub_matrices[3],K_temp,detK22);
68  KRATOS_ERROR_IF(std::abs(detK22) < numerical_limit) << "Element " << rTheElement.Id()
69  << " is singular !" << std::endl;
70 
71  //2.) K_cond = K11 - K12*inv(K22)*K21
72  K_temp = prod(K_temp,sub_matrices[2]);
73  K_temp = prod(sub_matrices[1],K_temp);
74  K_temp = sub_matrices[0]-K_temp;
75 
76  //3.) Fill rLeftHandSide to maintain same matrix size
77  const std::vector<int> remaining_dof_list = CreateRemainingDofList(rTheElement, rDofList);
78  rLeftHandSideMatrix.clear();
79 
80  SizeType dofA = 0;
81  SizeType dofB = 0;
82  for (SizeType i=0; i<num_dofs_remaining; ++i)
83  {
84  dofA = remaining_dof_list[i];
85  for (SizeType j=0; j<num_dofs_remaining; ++j)
86  {
87  dofB = remaining_dof_list[j];
88  rLeftHandSideMatrix(dofA,dofB) = K_temp(i,j);
89  }
90  }
91  KRATOS_CATCH("")
92 }
93 
101 static std::vector<MatrixType> CalculateSchurComplements(
102  ElementType& rTheElement,
103  const MatrixType& rLeftHandSideMatrix,
104  const std::vector<int> & rDofList)
105 {
106  KRATOS_TRY
107  // K11(0) K12(1)
108  // K21(2) K22(3) K22->dofs to be cond.
109  // rDofList -> List of dofs to be condensed
110  const std::vector<int> remaining_dof_list = CreateRemainingDofList(rTheElement, rDofList);
111  const SizeType num_dofs_condensed = rDofList.size();
112  const SizeType num_dofs_remaining = GetNumDofsElement(rTheElement)-num_dofs_condensed;
113 
114  KRATOS_ERROR_IF(num_dofs_remaining != remaining_dof_list.size()) << "unequal remaining dof size" << std::endl;
115 
116  std::vector<MatrixType> sub_matrices(4);
117  sub_matrices[0] = ZeroMatrix(num_dofs_remaining, num_dofs_remaining);
118  sub_matrices[1] = ZeroMatrix(num_dofs_remaining, num_dofs_condensed);
119  sub_matrices[2] = ZeroMatrix(num_dofs_condensed, num_dofs_remaining);
120  sub_matrices[3] = ZeroMatrix(num_dofs_condensed, num_dofs_condensed);
121 
122  FillSchurComplements(sub_matrices[0], rLeftHandSideMatrix, remaining_dof_list,
123  remaining_dof_list, num_dofs_remaining, num_dofs_remaining);
124 
125  FillSchurComplements(sub_matrices[1], rLeftHandSideMatrix, remaining_dof_list,
126  rDofList, num_dofs_remaining, num_dofs_condensed);
127 
128  FillSchurComplements(sub_matrices[2], rLeftHandSideMatrix, rDofList,
129  remaining_dof_list, num_dofs_condensed, num_dofs_remaining);
130 
131  FillSchurComplements(sub_matrices[3], rLeftHandSideMatrix, rDofList,
132  rDofList, num_dofs_condensed, num_dofs_condensed);
133 
134  return sub_matrices;
135  KRATOS_CATCH("")
136 }
137 
144 static std::vector<int> CreateRemainingDofList(
145  ElementType& rTheElement,
146  const std::vector<int> & rDofList)
147 {
148  KRATOS_TRY
149  const SizeType num_dofs_condensed = rDofList.size();
150 
151  //fill remaining dofs
152  std::vector<int> remaining_dofs_vec(0);
153  for (SizeType i=0; i<GetNumDofsElement(rTheElement); ++i)
154  {
155  int current_dof = i;
156  bool check = false;
157  for (SizeType j = 0; j<num_dofs_condensed; ++j)
158  {
159  if (current_dof == rDofList[j]) check = true;
160  }
161  if (check) continue;
162  else remaining_dofs_vec.push_back(current_dof);
163  }
164  return remaining_dofs_vec;
165 
166  KRATOS_CATCH("")
167 }
168 
180  MatrixType& Submatrix,
181  const MatrixType& rLeftHandSideMatrix,
182  const std::vector<int>& rVecA,
183  const std::vector<int>& rVecB,
184  const SizeType& rSizeA,
185  const SizeType& rSizeB) //maybe inline
186 {
187  KRATOS_TRY
188  SizeType current_dof_a = 0;
189  SizeType current_dof_b = 0;
190 
191  for (SizeType i=0; i<rSizeA; ++i)
192  {
193  current_dof_a = rVecA[i];
194  for (SizeType j=0; j<rSizeB; ++j)
195  {
196  current_dof_b = rVecB[j];
197  Submatrix(i,j) = rLeftHandSideMatrix(current_dof_a, current_dof_b);
198  }
199  }
200  KRATOS_CATCH("")
201 }
202 
213  ElementType& rTheElement,
214  Vector& rLocalizedDofVector,
215  Vector& rValues,
216  const std::vector<int>& rDofList,
217  const MatrixType& rLeftHandSideMatrix)
218 {
219  KRATOS_TRY
220  const double numerical_limit = std::numeric_limits<double>::epsilon();
221  const std::vector<int> remaining_dof_list = CreateRemainingDofList(rTheElement, rDofList);
222  const SizeType num_dofs_condensed = rDofList.size();
223 
224  const SizeType num_dofs_element = GetNumDofsElement(rTheElement);
225 
226  const SizeType num_dofs_remaining = num_dofs_element - num_dofs_condensed;
227  std::vector<MatrixType> sub_matrices = CalculateSchurComplements(rTheElement, rLeftHandSideMatrix,rDofList);
228 
229  //1.) create u1
230  Vector remaining_dofs_disp = ZeroVector(num_dofs_remaining);
231  // Vector all_dofs_disp = ZeroVector(num_dofs_element);
232  // rTheElement.GetValuesVector(all_dofs_disp);
233  // rTheElement.LocalizeVector(all_dofs_disp); // localize global displacement -> element lvl
234  // Note: "rLocalizedDofVector" is what was "all_dofs_disp" previously
235  for (SizeType i=0; i<num_dofs_remaining; ++i) remaining_dofs_disp[i] = rLocalizedDofVector[remaining_dof_list[i]];
236 
237  //2.) inverse K22
238  MatrixType K22_inv = ZeroMatrix(sub_matrices[3].size1());
239  double detK22 = 0.00;
240  MathUtils<double>::InvertMatrix(sub_matrices[3], K22_inv, detK22);
241 
242  KRATOS_ERROR_IF(std::abs(detK22) < numerical_limit) << "Element " << rTheElement.Id() << " is singular !" << std::endl;
243 
244  //3.) u2=inv(K22)*(F2-K21*u1),F2=0->u2=-inv(K22)*K21*u1
245  Vector CondensedDofsDisp = ZeroVector(num_dofs_condensed);
246  CondensedDofsDisp = prod(sub_matrices[2],remaining_dofs_disp);
247  CondensedDofsDisp = -prod(K22_inv,CondensedDofsDisp);
248 
249  //4.) Fill rValues to maintain same matrix size
250  rValues = ZeroVector(num_dofs_element);
251  for (int i=0; i<static_cast<int>(num_dofs_element); ++i)
252  {
253  bool check = false;
254  //check if dof i is condensed
255  for (SizeType j=0;j<num_dofs_condensed;++j)
256  {
257  if (i == rDofList[j])
258  {
259  rValues[i] = CondensedDofsDisp[j];
260  check = true;
261  break;
262  }
263  }
264 
265  if (check) continue; // found respective dof -> search for next dof
266  //check remaining dofs
267  else
268  {
269  for (SizeType j=0; j<num_dofs_remaining; ++j)
270  {
271  if (i == remaining_dof_list[j])
272  {
273  rValues[i] = remaining_dofs_disp[j];
274  break;
275  }
276  }
277  }
278  }
279  // rTheElement.GlobalizeVector(rValues); // globalize local displacements -> global lvl
280  KRATOS_CATCH("")
281 }
282 
289 {
290  Vector all_dof_values = Vector(0);
291  rTheElement.GetValuesVector(all_dof_values);
292  return all_dof_values.size();
293 }
294 
295 }; // class StaticCondensationUtility
296 
297 } // namespace Kratos.
298 
299 #endif // KRATOS_GEO_STATIC_CONDENSATION_UTILITY_H_INCLUDED defined
300 
301 
Base class for all Elements.
Definition: element.h:60
virtual void GetValuesVector(Vector &values, int Step=0) const
Definition: element.h:300
This utilitiy condenses given degrees of freedom from any element stiffness matrix to model e....
Definition: static_condensation_utility.h:40
Element ElementType
Definition: static_condensation_utility.h:42
static SizeType GetNumDofsElement(ElementType &rTheElement)
This function returns the number of dofs of the respective element by using the following input:
Definition: static_condensation_utility.h:288
Matrix MatrixType
Definition: static_condensation_utility.h:44
static void ConvertingCondensation(ElementType &rTheElement, Vector &rLocalizedDofVector, Vector &rValues, const std::vector< int > &rDofList, const MatrixType &rLeftHandSideMatrix)
This function re-calculates the condensed degree of freedom in relation to the remaining dofs by usin...
Definition: static_condensation_utility.h:212
static std::vector< MatrixType > CalculateSchurComplements(ElementType &rTheElement, const MatrixType &rLeftHandSideMatrix, const std::vector< int > &rDofList)
This function calculates the 4 schur-complements linking the dofs to be condensed to the dofs to rema...
Definition: static_condensation_utility.h:101
static void CondenseLeftHandSide(ElementType &rTheElement, MatrixType &rLeftHandSideMatrix, const std::vector< int > &rDofList)
This function is the main operation of this utility. It sorts the reference matrix w....
Definition: static_condensation_utility.h:53
static void FillSchurComplements(MatrixType &Submatrix, const MatrixType &rLeftHandSideMatrix, const std::vector< int > &rVecA, const std::vector< int > &rVecB, const SizeType &rSizeA, const SizeType &rSizeB)
This function creates the single schur-complements, called by CalculateSchurComplements,...
Definition: static_condensation_utility.h:179
std::size_t SizeType
Definition: static_condensation_utility.h:43
static std::vector< int > CreateRemainingDofList(ElementType &rTheElement, const std::vector< int > &rDofList)
This function creates a list containing all dofs to remain by using the following inputs:
Definition: static_condensation_utility.h:144
IndexType Id() const
Definition: indexed_object.h:107
void clear()
Definition: amatrix_interface.h:284
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
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
int j
Definition: quadrature.py:648
integer i
Definition: TensorModule.f:17