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.
rigid_body_utilities.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosContactMechanicsApplication $
3 // Created by: $Author: JMCarbonell $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: July 2016 $
6 // Revision: $Revision: 0.0 $
7 //
8 //
9 
10 #if !defined(KRATOS_RIGID_BODY_UTILITIES_H_INCLUDED )
11 #define KRATOS_RIGID_BODY_UTILITIES_H_INCLUDED
12 
13 #ifdef FIND_MAX
14 #undef FIND_MAX
15 #endif
16 
17 #define FIND_MAX(a, b) ((a)>(b)?(a):(b))
18 
19 // System includes
20 #include <cmath>
21 #include <set>
22 
23 #ifdef _OPENMP
24 #include <omp.h>
25 #endif
26 
27 // External includes
28 #include "boost/smart_ptr.hpp"
29 #include "utilities/timer.h"
30 
31 // Project includes
32 #include "includes/model_part.h"
33 #include "includes/define.h"
34 #include "includes/variables.h"
35 #include "utilities/openmp_utils.h"
36 
38 
39 
40 namespace Kratos
41 {
44 
48 
52 
56 
60 
62 
70  {
71  public:
72 
75 
79 
83 
85  RigidBodyUtilities(){ mEchoLevel = 0; mParallel = true; };
86 
87  RigidBodyUtilities(bool Parallel){ mEchoLevel = 0; mParallel = Parallel; };
88 
89 
92 
93 
97 
98 
102 
103 
104  //**************************************************************************
105  //**************************************************************************
106 
108  {
109  KRATOS_TRY
110 
111  Vector VolumeAcceleration = ZeroVector(3);
112 
113  ModelPart::NodeType& rNode = rModelPart.Nodes().front();
114 
115  if( rNode.SolutionStepsDataHas(VOLUME_ACCELERATION) ){
116  array_1d<double,3>& rVolumeAcceleration = rNode.FastGetSolutionStepValue(VOLUME_ACCELERATION);
117  for(unsigned int i=0; i<3; i++)
118  VolumeAcceleration[i] = rVolumeAcceleration[i];
119  }
120 
121  //alternative:
122 
123  // double num_nodes = 0;
124 
125  // for(ModelPart::NodesContainerType::const_iterator in = rModelPart.NodesBegin(); in != rModelPart.NodesEnd(); in++)
126  // {
127 
128  // if( in->SolutionStepsDataHas(VOLUME_ACCELERATION) ){ //temporary, will be checked once at the beginning only
129  // VolumeAcceleration += in->FastGetSolutionStepValue(VOLUME_ACCELERATION);
130  // num_nodes+=1;
131  // }
132 
133  // }
134 
135  // VolumeAcceleration/=num_nodes;
136 
137  //std::cout<<" VolumeAcceleration "<<VolumeAcceleration<<std::endl;
138 
139  return VolumeAcceleration;
140 
141 
142  KRATOS_CATCH( "" )
143  }
144 
145 
146  //**************************************************************************
147  //**************************************************************************
148 
149  double GetElasticModulus(ModelPart& rModelPart)
150  {
151  KRATOS_TRY
152 
153  double ElasticModulus = 0;
154 
155  ModelPart::ElementType& rElement = rModelPart.Elements().front();
156 
157  ElasticModulus = rElement.GetProperties()[YOUNG_MODULUS];
158 
159  return ElasticModulus;
160 
161 
162  KRATOS_CATCH( "" )
163  }
164 
165  //**************************************************************************
166  //**************************************************************************
167 
168  double VolumeCalculation(ModelPart& rModelPart)
169  {
170  KRATOS_TRY
171 
172  double ModelVolume = 0;
173 
174  bool mAxisymmetric = false;
175 
176  if( mAxisymmetric ){
177 
178  //std::cout<<" AXISYMMETRIC MODEL "<<std::endl;
179 
180  double radius = 0;
181  double two_pi = 6.28318530717958647693;
182 
183 
184  //Search and calculation in parallel
185  ModelPart::ElementsContainerType& pElements = rModelPart.Elements();
186 
187  #ifdef _OPENMP
188  int number_of_threads = omp_get_max_threads();
189  #else
190  int number_of_threads = 1;
191  #endif
192 
193  if( mParallel == false )
194  number_of_threads = 1;
195 
196  vector<unsigned int> element_partition;
197  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
198 
199  Vector ModelVolumePartition = ZeroVector(number_of_threads);
200 
201  #pragma omp parallel
202  {
203  int k = OpenMPUtils::ThisThread();
204  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
205  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
206 
207 
208  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
209  {
210 
211  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
212 
213  if( dimension > 2 )
214  std::cout<<" Axisymmetric problem with dimension: "<<dimension<<std::endl;
215 
216  radius = 0;
217  for( unsigned int i=0; i<ie->GetGeometry().size(); i++ )
218  radius += ie->GetGeometry()[i].X();
219 
220  radius/=double(ie->GetGeometry().size());
221 
222  ModelVolumePartition[k] += ie->GetGeometry().Area() * two_pi * radius ;
223 
224 
225  }
226 
227  }
228 
229  for(int i=0; i<number_of_threads; i++)
230  ModelVolume += ModelVolumePartition[i];
231 
232  }
233  else{
234 
235 
236  //Search and calculation in parallel
237  ModelPart::ElementsContainerType& pElements = rModelPart.Elements();
238 
239  #ifdef _OPENMP
240  int number_of_threads = omp_get_max_threads();
241  #else
242  int number_of_threads = 1;
243  #endif
244 
245  if( mParallel == false )
246  number_of_threads = 1;
247 
248  vector<unsigned int> element_partition;
249  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
250 
251  Vector ModelVolumePartition = ZeroVector(number_of_threads);
252 
253  #pragma omp parallel
254  {
255  int k = OpenMPUtils::ThisThread();
256  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
257  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
258 
259 
260  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
261  {
262  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
263  if( dimension == 2){
264  ModelVolumePartition[k] += ie->GetGeometry().Area() * ie->GetProperties()[THICKNESS];
265  }
266  else if( dimension == 3){
267  ModelVolumePartition[k] += ie->GetGeometry().Volume();
268  }
269  else{
270  //do nothing.
271  }
272 
273  }
274 
275  }
276 
277  for(int i=0; i<number_of_threads; i++)
278  ModelVolume += ModelVolumePartition[i];
279 
280 
281  }
282 
283  return ModelVolume;
284 
285 
286  KRATOS_CATCH( "" )
287  }
288 
289 
290  //**************************************************************************
291  //**************************************************************************
292 
293  double MassCalculation(ModelPart& rModelPart)
294  {
295  KRATOS_TRY
296 
297  double ModelMass = 0;
298 
299  bool mAxisymmetric = false;
300 
301  if( mAxisymmetric ){
302 
303  //std::cout<<" AXISYMMETRIC MODEL "<<std::endl;
304 
305  double radius = 0;
306  double two_pi = 6.28318530717958647693;
307 
308  //Search and calculation in parallel
309  ModelPart::ElementsContainerType& pElements = rModelPart.Elements();
310 
311  #ifdef _OPENMP
312  int number_of_threads = omp_get_max_threads();
313  #else
314  int number_of_threads = 1;
315  #endif
316 
317  if( mParallel == false )
318  number_of_threads = 1;
319 
320  vector<unsigned int> element_partition;
321  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
322 
323  Vector ModelMassPartition = ZeroVector(number_of_threads);
324 
325  #pragma omp parallel
326  {
327  int k = OpenMPUtils::ThisThread();
328  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
329  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
330 
331 
332  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
333  {
334 
335  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
336 
337  if( dimension > 2 )
338  std::cout<<" Axisymmetric problem with dimension: "<<dimension<<std::endl;
339 
340  radius = 0;
341  for( unsigned int i=0; i<ie->GetGeometry().size(); i++ )
342  radius += ie->GetGeometry()[i].X();
343 
344  radius/=double(ie->GetGeometry().size());
345 
346  ModelMassPartition[k] += ie->GetGeometry().Area() * two_pi * radius * ie->GetProperties()[DENSITY];
347 
348 
349  }
350  }
351 
352  for(int i=0; i<number_of_threads; i++)
353  ModelMass += ModelMassPartition[i];
354 
355  }
356  else{
357 
358 
359  //Search and calculation in parallel
360  ModelPart::ElementsContainerType& pElements = rModelPart.Elements();
361 
362  #ifdef _OPENMP
363  int number_of_threads = omp_get_max_threads();
364  #else
365  int number_of_threads = 1;
366  #endif
367 
368  if( mParallel == false )
369  number_of_threads = 1;
370 
371  vector<unsigned int> element_partition;
372  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
373 
374  Vector ModelMassPartition = ZeroVector(number_of_threads);
375 
376  #pragma omp parallel
377  {
378  int k = OpenMPUtils::ThisThread();
379  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
380  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
381 
382 
383  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
384  {
385  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
386  if( dimension == 2){
387  ModelMassPartition[k] += ie->GetGeometry().Area() * ie->GetProperties()[THICKNESS] * ie->GetProperties()[DENSITY];
388  }
389  else if( dimension == 3){
390  ModelMassPartition[k] += ie->GetGeometry().Volume() * ie->GetProperties()[DENSITY];
391  }
392  else{
393  //do nothing.
394  }
395 
396  }
397  }
398 
399  for(int i=0; i<number_of_threads; i++)
400  ModelMass += ModelMassPartition[i];
401 
402 
403  }
404 
405  return ModelMass;
406 
407 
408  KRATOS_CATCH( "" )
409  }
410 
411 
412  //**************************************************************************
413  //**************************************************************************
414 
416  {
417  KRATOS_TRY
418 
419 
420  ModelPart::MeshType& rMesh = rModelPart.GetMesh();
421 
422  return this->CenterOfMassCalculation(rMesh);
423 
424 
425  KRATOS_CATCH( "" )
426  }
427 
428  //**************************************************************************
429  //**************************************************************************
430 
432  {
433 
434  KRATOS_TRY
435 
436  double ModelMass = 0;
437  Vector CenterOfMass = ZeroVector(3);
438 
439  double Thickness = 1;
440 
441  bool mAxisymmetric = false;
442 
443  if( mAxisymmetric ){
444 
445  //std::cout<<" AXISYMMETRIC MODEL "<<std::endl;
446 
447  double radius = 0;
448  double two_pi = 6.28318530717958647693;
449 
450 
451  //Search and calculation in parallel
452  ModelPart::ElementsContainerType& pElements = rMesh.Elements();
453 
454  #ifdef _OPENMP
455  int number_of_threads = omp_get_max_threads();
456  #else
457  int number_of_threads = 1;
458  #endif
459 
460  if( mParallel == false )
461  number_of_threads = 1;
462 
463  vector<unsigned int> element_partition;
464  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
465 
466  Vector ModelMassPartition = ZeroVector(number_of_threads);
467 
468  #pragma omp parallel
469  {
470  int k = OpenMPUtils::ThisThread();
471  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
472  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
473 
474 
475  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
476  {
477 
478  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
479 
480  if( dimension > 2 )
481  std::cout<<" Axisymmetric problem with dimension: "<<dimension<<std::endl;
482 
483  radius = 0;
484  for( unsigned int i=0; i<ie->GetGeometry().size(); i++ )
485  radius += ie->GetGeometry()[i].X();
486 
487  radius/=double(ie->GetGeometry().size());
488 
489  ModelMassPartition[k] += ie->GetGeometry().Area() * two_pi * radius * ie->GetProperties()[DENSITY];
490  }
491  }
492 
493  for(int i=0; i<number_of_threads; i++)
494  ModelMass += ModelMassPartition[i];
495 
496  }
497  else{
498 
499 
500  //Search and calculation in parallel
501  ModelPart::ElementsContainerType& pElements = rMesh.Elements();
502 
503  #ifdef _OPENMP
504  int number_of_threads = omp_get_max_threads();
505  #else
506  int number_of_threads = 1;
507  #endif
508 
509  if( mParallel == false )
510  number_of_threads = 1;
511 
512  vector<unsigned int> element_partition;
513  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
514 
515  Vector ModelMassPartition = ZeroVector(number_of_threads);
516 
517  std::vector<Vector> CenterOfMassPartition(number_of_threads);
518  for(int i=0; i<number_of_threads; i++)
519  CenterOfMassPartition[i] = ZeroVector(3);
520 
521 
522  #pragma omp parallel
523  {
524  int k = OpenMPUtils::ThisThread();
525  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
526  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
527 
528 
529  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
530  {
531 
532  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
533 
534  if( dimension == 2){
535  Thickness = ie->GetProperties()[THICKNESS];
536  ModelMassPartition[k] += ie->GetGeometry().Area() * Thickness * ie->GetProperties()[DENSITY];
537 
538  }
539  else if( dimension == 3){
540  ModelMassPartition[k] += ie->GetGeometry().Volume() * ie->GetProperties()[DENSITY];
541  }
542  else{
543  //do nothing.
544  }
545 
546 
547  const unsigned int number_of_nodes = ie->GetGeometry().PointsNumber();
548 
549  GeometryType::IntegrationMethod IntegrationMethod = ie->GetGeometry().GetDefaultIntegrationMethod();
550 
552  J = ie->GetGeometry().Jacobian( J, IntegrationMethod );
553 
554  Matrix mInvJ;
555  double mDetJ = 0;
556 
557  const Matrix& Ncontainer = ie->GetGeometry().ShapeFunctionsValues( IntegrationMethod );
558 
559  //reading integration points
560  const GeometryType::IntegrationPointsArrayType& integration_points = ie->GetGeometry().IntegrationPoints( IntegrationMethod );
561 
562  for ( unsigned int PointNumber = 0; PointNumber < integration_points.size(); PointNumber++ )
563  {
564 
565  MathUtils<double>::InvertMatrix( J[PointNumber], mInvJ, mDetJ );
566 
567  double IntegrationWeight = mDetJ * integration_points[PointNumber].Weight() * Thickness;
568 
569  Vector N = row( Ncontainer, PointNumber);
570 
571  for ( unsigned int i = 0; i < number_of_nodes; i++ )
572  {
573 
574  array_1d<double, 3> &CurrentPosition = ie->GetGeometry()[i].Coordinates();
575 
576  for ( unsigned int j = 0; j < dimension; j++ )
577  {
578  CenterOfMassPartition[k][j] += IntegrationWeight * N[i] * ie->GetProperties()[DENSITY] * CurrentPosition[j];
579  }
580  }
581  }
582 
583  }
584 
585  }
586 
587  for(int i=0; i<number_of_threads; i++){
588  ModelMass += ModelMassPartition[i];
589  CenterOfMass += CenterOfMassPartition[i];
590  }
591 
592  }
593 
594  if(ModelMass!=0)
595  CenterOfMass /= ModelMass;
596  else
597  std::cout<<" [ WARNING: RIGID BODY WITH NO MASS ] "<<std::endl;
598 
599  return CenterOfMass;
600 
601 
602  KRATOS_CATCH( "" )
603  }
604 
605 
606  //**************************************************************************
607  //**************************************************************************
608 
609 
611  {
612  KRATOS_TRY
613 
614  ModelPart::MeshType& rMesh = rModelPart.GetMesh();
615 
616  return this->InertiaTensorCalculation(rMesh);
617 
618  KRATOS_CATCH( "" )
619  }
620 
621  //**************************************************************************
622  //**************************************************************************
623 
624 
626  {
627  KRATOS_TRY
628 
629  double ModelMass = 0;
630  Vector Center = CenterOfMassCalculation(rMesh);
631 
632  array_1d<double, 3> CenterOfMass;
633  for ( unsigned int k = 0; k < 3; k++ )
634  {
635  CenterOfMass[k] = Center[k];
636  }
637 
638  Matrix InertiaTensor = ZeroMatrix(3,3);
639 
640  double Thickness = 1;
641 
642  bool mAxisymmetric = false;
643 
644  if( mAxisymmetric ){
645 
646  //std::cout<<" AXISYMMETRIC MODEL "<<std::endl;
647 
648  double radius = 0;
649  double two_pi = 6.28318530717958647693;
650 
651  //Search and calculation in parallel
652  ModelPart::ElementsContainerType& pElements = rMesh.Elements();
653 
654  #ifdef _OPENMP
655  int number_of_threads = omp_get_max_threads();
656  #else
657  int number_of_threads = 1;
658  #endif
659 
660  if( mParallel == false )
661  number_of_threads = 1;
662 
663  vector<unsigned int> element_partition;
664  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
665 
666  Vector ModelMassPartition = ZeroVector(number_of_threads);
667 
668  #pragma omp parallel
669  {
670  int k = OpenMPUtils::ThisThread();
671  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
672  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
673 
674 
675  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
676  {
677 
678  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
679 
680  if( dimension > 2 )
681  std::cout<<" Axisymmetric problem with dimension: "<<dimension<<std::endl;
682 
683  radius = 0;
684  for( unsigned int i=0; i<ie->GetGeometry().size(); i++ )
685  radius += ie->GetGeometry()[i].X();
686 
687  radius/=double(ie->GetGeometry().size());
688 
689  ModelMassPartition[k] += ie->GetGeometry().Area() * two_pi * radius * ie->GetProperties()[DENSITY];
690  }
691  }
692 
693  for(int i=0; i<number_of_threads; i++)
694  ModelMass += ModelMassPartition[i];
695 
696 
697  }
698  else{
699 
700 
701  //Search and calculation in parallel
702  ModelPart::ElementsContainerType& pElements = rMesh.Elements();
703 
704  #ifdef _OPENMP
705  int number_of_threads = omp_get_max_threads();
706  #else
707  int number_of_threads = 1;
708  #endif
709 
710  if( mParallel == false )
711  number_of_threads = 1;
712 
713  vector<unsigned int> element_partition;
714  OpenMPUtils::CreatePartition(number_of_threads, pElements.size(), element_partition);
715 
716  Vector ModelMassPartition = ZeroVector(number_of_threads);
717  std::vector<Matrix> InertiaTensorPartition(number_of_threads);
718  for(int i=0; i<number_of_threads; i++)
719  InertiaTensorPartition[i] = ZeroMatrix(3,3);
720 
721 
722  #pragma omp parallel
723  {
724  int k = OpenMPUtils::ThisThread();
725  ModelPart::ElementsContainerType::iterator ElemBegin = pElements.begin() + element_partition[k];
726  ModelPart::ElementsContainerType::iterator ElemEnd = pElements.begin() + element_partition[k + 1];
727 
728 
729  for(ModelPart::ElementsContainerType::const_iterator ie = ElemBegin; ie != ElemEnd; ie++)
730  {
731 
732  const unsigned int dimension = ie->GetGeometry().WorkingSpaceDimension();
733 
734  if( dimension == 2){
735  Thickness = ie->GetProperties()[THICKNESS];
736  ModelMassPartition[k] += ie->GetGeometry().Area() * Thickness * ie->GetProperties()[DENSITY];
737 
738  }
739  else if( dimension == 3){
740  ModelMassPartition[k] += ie->GetGeometry().Volume() * ie->GetProperties()[DENSITY];
741  }
742  else{
743  //do nothing.
744  }
745 
746  const unsigned int number_of_nodes = ie->GetGeometry().PointsNumber();
747 
748  GeometryType::IntegrationMethod IntegrationMethod = ie->GetGeometry().GetDefaultIntegrationMethod();
749 
751  J = ie->GetGeometry().Jacobian( J, IntegrationMethod );
752 
753  Matrix mInvJ;
754  double mDetJ = 0;
755 
756  const Matrix& Ncontainer = ie->GetGeometry().ShapeFunctionsValues( IntegrationMethod );
757 
758  //reading integration points
759  const GeometryType::IntegrationPointsArrayType& integration_points = ie->GetGeometry().IntegrationPoints( IntegrationMethod );
760 
761  for ( unsigned int PointNumber = 0; PointNumber < integration_points.size(); PointNumber++ )
762  {
763 
764  MathUtils<double>::InvertMatrix( J[PointNumber], mInvJ, mDetJ );
765 
766  double IntegrationWeight = mDetJ * integration_points[PointNumber].Weight() * Thickness;
767 
768  Vector N = row( Ncontainer, PointNumber);
769 
770  double MassAB = 0;
771  Matrix OuterAB = ZeroMatrix(3,3);
772  double InnerAB = 0;
773  Matrix Identity = IdentityMatrix(3);
774 
775  for ( unsigned int i = 0; i < number_of_nodes; i++ )
776  {
777  array_1d<double, 3> CurrentPositionA = ie->GetGeometry()[i].Coordinates();
778 
779  CurrentPositionA -= CenterOfMass;
780 
781  for ( unsigned int j = 0; j < number_of_nodes; j++ )
782  {
783  array_1d<double, 3> CurrentPositionB = ie->GetGeometry()[j].Coordinates();
784 
785  CurrentPositionB -= CenterOfMass;
786 
787  MassAB = IntegrationWeight * N[i] * N[j] * ie->GetProperties()[DENSITY];
788 
789  OuterAB = outer_prod( CurrentPositionA, CurrentPositionB );
790  InnerAB = inner_prod( CurrentPositionA, CurrentPositionB );
791 
792  InertiaTensorPartition[k] += MassAB * ( InnerAB * Identity - OuterAB );
793 
794  }
795 
796  }
797  }
798 
799  }
800  }
801 
802  for(int i=0; i<number_of_threads; i++){
803  ModelMass += ModelMassPartition[i];
804  InertiaTensor += InertiaTensorPartition[i];
805  }
806  }
807 
808  // test to clean negligible values:
809  //clear_numerical_errors(InertiaTensor);
810 
811  return InertiaTensor;
812 
813 
814  KRATOS_CATCH( "" )
815  }
816 
817 
818 
819  //**************************************************************************
820  //**************************************************************************
821 
822 
824  {
825  KRATOS_TRY
826 
827  Matrix InertiaTensor = ZeroMatrix(3,3);
828  InertiaTensor = this->CalculateInertiaTensor(rModelPart);
829 
830  this->InertiaTensorToMainAxes(InertiaTensor, MainAxes);
831 
832  return InertiaTensor;
833 
834 
835  KRATOS_CATCH( "" )
836  }
837 
838 
839  //**************************************************************************
840  //**************************************************************************
841 
842 
843  void InertiaTensorToMainAxes(Matrix& InertiaTensor, Matrix& MainAxes)
844  {
845  KRATOS_TRY
846 
847  MainAxes = ZeroMatrix(3,3);
848  Vector MainInertias = ZeroVector(3);
849  EigenVectors3x3(InertiaTensor, MainAxes ,MainInertias);
850 
851  InertiaTensor = ZeroMatrix(3,3);
852  for(unsigned int i=0; i<3; i++)
853  InertiaTensor(i,i) = MainInertias[i];
854 
855 
856  KRATOS_CATCH( "" )
857  }
858 
859 
860 
861  void TransferRigidBodySkinToModelPart(ModelPart& rSourceModelPart, ModelPart& rDestinationModelPart, const int mesh_id){
862 
863  ElementsContainerType& mesh_elements = rSourceModelPart.GetMesh(mesh_id).Elements();
864 
865  for(unsigned int i=0; i<mesh_elements.size(); i++) {
866  ElementsContainerType::ptr_iterator pTubeElement = mesh_elements.ptr_begin()+i;
867  (rDestinationModelPart.Elements()).push_back(*pTubeElement);
868  }
869 
870  NodesContainerType& mesh_nodes = rSourceModelPart.GetMesh(mesh_id).Nodes();
871 
872  for(unsigned int i=0; i<mesh_nodes.size(); i++) {
873  NodesContainerType::ptr_iterator pTubeNode = mesh_nodes.ptr_begin()+i;
874  (rDestinationModelPart.Nodes()).push_back(*pTubeNode);
875  }
876 
877  }
878 
879 
880  //**************************************************************************
881  //**************************************************************************
882 
883 
884 
888  virtual void SetEchoLevel(int Level)
889  {
890  mEchoLevel = Level;
891  }
892 
894  {
895  return mEchoLevel;
896  }
897 
901 
902 
906 
907 
911 
915 
916 
918 
919 
920  protected:
923 
924 
928 
929 
933 
934 
938 
939 
943 
944 
948 
949 
953 
954 
956  private:
959 
960 
964  int mEchoLevel;
965 
966  bool mParallel;
967 
971 
975 
976 
977  inline void clear_numerical_errors(Matrix& rMatrix)
978  {
979  double Maximum = 0;
980 
981  //get max value
982  for(unsigned int i=0; i<rMatrix.size1(); i++)
983  {
984  for(unsigned int j=0; j<rMatrix.size2(); j++)
985  {
986  if(Maximum<fabs(rMatrix(i,j)))
987  Maximum = fabs(rMatrix(i,j));
988  }
989  }
990 
991  //set zero value if value is < Maximum *1e-5
992  double Critical = Maximum*1e-5;
993 
994  for(unsigned int i=0; i<rMatrix.size1(); i++)
995  {
996  for(unsigned int j=0; j<rMatrix.size2(); j++)
997  {
998  if(fabs(rMatrix(i,j))<Critical)
999  rMatrix(i,j) = 0;
1000  }
1001  }
1002 
1003  }
1004 
1005 
1014  static inline void EigenVectors3x3(const Matrix& A, Matrix&V, Vector& d)
1015  {
1016 
1017  if(A.size1()!=3 || A.size2()!=3)
1018  std::cout<<" GIVEN MATRIX IS NOT 3x3 eigenvectors calculation "<<std::endl;
1019 
1020  Vector e = ZeroVector(3);
1021  V = ZeroMatrix(3,3);
1022 
1023  for (int i = 0; i < 3; i++) {
1024  for (int j = 0; j < 3; j++) {
1025  V(i,j) = A(i,j);
1026  }
1027  }
1028 
1029  // *******************//
1030  //Symmetric Housholder reduction to tridiagonal form
1031 
1032  for (int j = 0; j < 3; j++) {
1033  d[j] = V(2,j);
1034  }
1035 
1036  // Householder reduction to tridiagonal form.
1037 
1038  for (int i = 2; i > 0; i--) {
1039 
1040  // Scale to avoid under/overflow.
1041 
1042  double scale = 0.0;
1043  double h = 0.0;
1044  for (int k = 0; k < i; k++) {
1045  scale = scale + fabs(d[k]);
1046  }
1047  if (scale == 0.0) {
1048  e[i] = d[i-1];
1049  for (int j = 0; j < i; j++) {
1050  d[j] = V(i-1,j);
1051  V(i,j) = 0.0;
1052  V(j,i) = 0.0;
1053  }
1054  } else {
1055 
1056  // Generate Householder vector.
1057 
1058  for (int k = 0; k < i; k++) {
1059  d[k] /= scale;
1060  h += d[k] * d[k];
1061  }
1062  double f = d[i-1];
1063  double g = sqrt(h);
1064  if (f > 0) {
1065  g = -g;
1066  }
1067  e[i] = scale * g;
1068  h = h - f * g;
1069  d[i-1] = f - g;
1070  for (int j = 0; j < i; j++) {
1071  e[j] = 0.0;
1072  }
1073 
1074  // Apply similarity transformation to remaining columns.
1075 
1076  for (int j = 0; j < i; j++) {
1077  f = d[j];
1078  V(j,i) = f;
1079  g = e[j] + V(j,j) * f;
1080  for (int k = j+1; k <= i-1; k++) {
1081  g += V(k,j) * d[k];
1082  e[k] += V(k,j) * f;
1083  }
1084  e[j] = g;
1085  }
1086  f = 0.0;
1087  for (int j = 0; j < i; j++) {
1088  e[j] /= h;
1089  f += e[j] * d[j];
1090  }
1091  double hh = f / (h + h);
1092  for (int j = 0; j < i; j++) {
1093  e[j] -= hh * d[j];
1094  }
1095  for (int j = 0; j < i; j++) {
1096  f = d[j];
1097  g = e[j];
1098  for (int k = j; k <= i-1; k++) {
1099  V(k,j) -= (f * e[k] + g * d[k]);
1100  }
1101  d[j] = V(i-1,j);
1102  V(i,j) = 0.0;
1103  }
1104  }
1105  d[i] = h;
1106  }
1107 
1108  // Accumulate transformations.
1109 
1110  for (int i = 0; i < 2; i++) {
1111  V(2,i) = V(i,i);
1112  V(i,i) = 1.0;
1113  double h = d[i+1];
1114  if (h != 0.0) {
1115  for (int k = 0; k <= i; k++) {
1116  d[k] = V(k,i+1) / h;
1117  }
1118  for (int j = 0; j <= i; j++) {
1119  double g = 0.0;
1120  for (int k = 0; k <= i; k++) {
1121  g += V(k,i+1) * V(k,j);
1122  }
1123  for (int k = 0; k <= i; k++) {
1124  V(k,j) -= g * d[k];
1125  }
1126  }
1127  }
1128  for (int k = 0; k <= i; k++) {
1129  V(k,i+1) = 0.0;
1130  }
1131  }
1132  for (int j = 0; j < 3; j++) {
1133  d[j] = V(2,j);
1134  V(2,j) = 0.0;
1135  }
1136  V(2,2) = 1.0;
1137  e[0] = 0.0;
1138 
1139  // *******************//
1140 
1141  // Symmetric tridiagonal QL algorithm.
1142 
1143  for (int i = 1; i < 3; i++) {
1144  e[i-1] = e[i];
1145  }
1146  e[2] = 0.0;
1147 
1148  double f = 0.0;
1149  double tst1 = 0.0;
1150  double eps = std::pow(2.0,-52.0);
1151  for (int l = 0; l < 3; l++) {
1152 
1153  // Find small subdiagonal element
1154 
1155  tst1 = FIND_MAX(tst1,fabs(d[l]) + fabs(e[l]));
1156  int m = l;
1157  while (m < 3) {
1158  if (fabs(e[m]) <= eps*tst1) {
1159  break;
1160  }
1161  m++;
1162  }
1163 
1164  // If m == l, d[l] is an eigenvalue,
1165  // otherwise, iterate.
1166 
1167  if (m > l) {
1168  int iter = 0;
1169  do {
1170  iter = iter + 1; // (Could check iteration count here.)
1171 
1172  // Compute implicit shift
1173 
1174  double g = d[l];
1175  double p = (d[l+1] - g) / (2.0 * e[l]);
1176  double r = hypot2(p,1.0);
1177  if (p < 0) {
1178  r = -r;
1179  }
1180  d[l] = e[l] / (p + r);
1181  d[l+1] = e[l] * (p + r);
1182  double dl1 = d[l+1];
1183  double h = g - d[l];
1184  for (int i = l+2; i < 3; i++) {
1185  d[i] -= h;
1186  }
1187  f = f + h;
1188 
1189  // Implicit QL transformation.
1190 
1191  p = d[m];
1192  double c = 1.0;
1193  double c2 = c;
1194  double c3 = c;
1195  double el1 = e[l+1];
1196  double s = 0.0;
1197  double s2 = 0.0;
1198  for (int i = m-1; i >= l; i--) {
1199  c3 = c2;
1200  c2 = c;
1201  s2 = s;
1202  g = c * e[i];
1203  h = c * p;
1204  r = hypot2(p,e[i]);
1205  e[i+1] = s * r;
1206  s = e[i] / r;
1207  c = p / r;
1208  p = c * d[i] - s * g;
1209  d[i+1] = h + s * (c * g + s * d[i]);
1210 
1211  // Accumulate transformation.
1212 
1213  for (int k = 0; k < 3; k++) {
1214  h = V(k,i+1);
1215  V(k,i+1) = s * V(k,i) + c * h;
1216  V(k,i) = c * V(k,i) - s * h;
1217  }
1218  }
1219  p = -s * s2 * c3 * el1 * e[l] / dl1;
1220  e[l] = s * p;
1221  d[l] = c * p;
1222 
1223  // Check for convergence.
1224 
1225  } while (fabs(e[l]) > eps*tst1);
1226  }
1227  d[l] = d[l] + f;
1228  e[l] = 0.0;
1229  }
1230 
1231  // Sort eigenvalues and corresponding vectors.
1232 
1233  for (int i = 0; i < 2; i++) {
1234  int k = i;
1235  double p = d[i];
1236  for (int j = i+1; j < 3; j++) {
1237  if (d[j] < p) {
1238  k = j;
1239  p = d[j];
1240  }
1241  }
1242  if (k != i) {
1243  d[k] = d[i];
1244  d[i] = p;
1245  for (int j = 0; j < 3; j++) {
1246  p = V(j,i);
1247  V(j,i) = V(j,k);
1248  V(j,k) = p;
1249  }
1250  }
1251  }
1252 
1253  V = trans(V);
1254 
1255  // *******************//
1256 
1257 
1258  }
1259 
1260 
1261  static double hypot2(double x, double y) {
1262  return std::sqrt(x*x+y*y);
1263  }
1264 
1268 
1269 
1273 
1274 
1278 
1280 
1281 
1282  }; // Class RigidBodyUtilities
1283 
1287 
1288 
1292 
1294 
1295 } // namespace Kratos.
1296 
1297 #endif // KRATOS_RIGID_BODY_UTILITIES_H_INCLUDED defined
Base class for all Elements.
Definition: element.h:60
PropertiesType & GetProperties()
Definition: element.h:1024
IntegrationMethod
Definition: geometry_data.h:76
Geometry base class.
Definition: geometry.h:71
std::vector< IntegrationPointType > IntegrationPointsArrayType
Definition: geometry.h:161
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
NodesContainerType & Nodes()
Definition: mesh.h:346
ElementsContainerType & Elements()
Definition: mesh.h:568
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
MeshType::ElementsContainerType ElementsContainerType
Element container. A vector set of Elements with their Id's as key.
Definition: model_part.h:168
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
MeshType & GetMesh(IndexType ThisIndex=0)
Definition: model_part.h:1791
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class defines the node.
Definition: node.h:65
TVariableType::Type & FastGetSolutionStepValue(const TVariableType &rThisVariable)
Definition: node.h:435
bool SolutionStepsDataHas(const VariableData &rThisVariable) const
Definition: node.h:427
static int ThisThread()
Wrapper for omp_get_thread_num().
Definition: openmp_utils.h:108
ptr_iterator ptr_begin()
Returns an iterator pointing to the beginning of the underlying data container.
Definition: pointer_vector_set.h:386
Short class definition.
Definition: rigid_body_utilities.hpp:70
Vector CalculateCenterOfMass(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:415
double GetElasticModulus(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:149
double VolumeCalculation(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:168
void TransferRigidBodySkinToModelPart(ModelPart &rSourceModelPart, ModelPart &rDestinationModelPart, const int mesh_id)
Definition: rigid_body_utilities.hpp:861
ModelPart::ElementsContainerType ElementsContainerType
Definition: rigid_body_utilities.hpp:77
Vector CenterOfMassCalculation(ModelPart::MeshType &rMesh)
Definition: rigid_body_utilities.hpp:431
Matrix InertiaTensorCalculation(ModelPart::MeshType &rMesh)
Definition: rigid_body_utilities.hpp:625
RigidBodyUtilities(bool Parallel)
Definition: rigid_body_utilities.hpp:87
double MassCalculation(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:293
Vector GetVolumeAcceleration(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:107
Matrix CalculateInertiaTensor(ModelPart &rModelPart)
Definition: rigid_body_utilities.hpp:610
ModelPart::MeshType::GeometryType GeometryType
Definition: rigid_body_utilities.hpp:78
ModelPart::NodesContainerType NodesContainerType
Definition: rigid_body_utilities.hpp:76
void InertiaTensorToMainAxes(Matrix &InertiaTensor, Matrix &MainAxes)
Definition: rigid_body_utilities.hpp:843
virtual void SetEchoLevel(int Level)
Definition: rigid_body_utilities.hpp:888
Matrix InertiaTensorMainAxesCalculation(ModelPart &rModelPart, Matrix &MainAxes)
Definition: rigid_body_utilities.hpp:823
RigidBodyUtilities()
Default constructor.
Definition: rigid_body_utilities.hpp:85
int GetEchoLevel()
Definition: rigid_body_utilities.hpp:893
~RigidBodyUtilities()
Destructor.
Definition: rigid_body_utilities.hpp:91
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
AMatrix::IdentityMatrix< double > IdentityMatrix
Definition: amatrix_interface.h:564
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
AMatrix::VectorOuterProductExpression< TExpression1Type, TExpression2Type > outer_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:582
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
f
Definition: generate_convection_diffusion_explicit_element.py:112
V
Definition: generate_droplet_dynamics.py:256
h
Definition: generate_droplet_dynamics.py:91
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
int dimension
Definition: isotropic_damage_automatic_differentiation.py:123
float radius
Definition: mesh_to_mdpa_converter.py:18
int d
Definition: ode_solve.py:397
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int m
Definition: run_marine_rain_substepping.py:8
J
Definition: sensitivityMatrix.py:58
A
Definition: sensitivityMatrix.py:70
p
Definition: sensitivityMatrix.py:52
N
Definition: sensitivityMatrix.py:29
x
Definition: sensitivityMatrix.py:49
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
#define FIND_MAX(a, b)
Definition: rigid_body_utilities.hpp:17