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.
calculate_signed_distance_to_3d_skin_process.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: Daniel Baumgaertner
11 // Johannes Wolf
12 //
13 
14 
15 #if !defined(KRATOS_CALCULATE_DISTANCE_PROCESS_H_INCLUDED )
16 #define KRATOS_CALCULATE_DISTANCE_PROCESS_H_INCLUDED
17 
18 
19 
20 // System includes
21 #include <string>
22 #include <iostream>
23 #include <ctime>
24 
25 // External includes
26 
27 
28 // Project includes
29 #include "includes/define.h"
30 #include "processes/process.h"
31 #include "includes/model_part.h"
33 
36 #include "utilities/timer.h"
37 #include "utilities/math_utils.h"
38 #include "utilities/geometry_utilities.h"
42 #include "includes/kratos_flags.h"
46 
47 #ifdef _OPENMP
48 #include "omp.h"
49 #endif
50 
51 using namespace boost::numeric::ublas;
52 
53 
54 namespace Kratos
55 {
56 
58 {
59 public:
61  {
62  double mDistance;
63  double mCoordinates[3];
64  std::size_t mId;
65  public:
66  double& Distance(){return mDistance;}
67  double& X() {return mCoordinates[0];}
68  double& Y() {return mCoordinates[1];}
69  double& Z() {return mCoordinates[2];}
70  double& operator[](int i) {return mCoordinates[i];}
71  std::size_t& Id(){return mId;}
72  };
73 
74 
75 
76 
79 
80  enum { Dimension = 3,
81  DIMENSION = 3,
82  MAX_LEVEL = 12,
83  MIN_LEVEL = 2 // this cannot be less than 2!!!
84  };
85 
86  typedef Point PointType;
87  typedef std::vector<double>::iterator DistanceIteratorType;
89  typedef ContainerType::value_type PointerType;
90  typedef ContainerType::iterator IteratorType;
92  typedef ResultContainerType::value_type ResultPointerType;
93  typedef ResultContainerType::iterator ResultIteratorType;
94 
95  typedef Element::Pointer pointer_type;
97  typedef std::vector<CellNodeData*> data_type;
98 
99  typedef std::vector<PointerType>::iterator PointerTypeIterator;
100 
101 
102 
103 
106 
110 
113 
116 
117 
121 
122 
126 
128  return new data_type(27, (CellNodeData*)NULL);
129  }
130 
131  static void CopyData(data_type* source, data_type* destination) {
132  *destination = *source;
133  }
134 
135  static void DeleteData(data_type* data) {
136  delete data;
137  }
138 
139  static inline void CalculateBoundingBox(const PointerType& rObject, PointType& rLowPoint, PointType& rHighPoint)
140  {
141  rHighPoint = rObject->GetGeometry().GetPoint(0);
142  rLowPoint = rObject->GetGeometry().GetPoint(0);
143 
144  for (unsigned int point = 0; point<rObject->GetGeometry().PointsNumber(); point++)
145  {
146  for(std::size_t i = 0; i<3; i++)
147  {
148  rLowPoint[i] = (rLowPoint[i] > rObject->GetGeometry().GetPoint(point)[i] ) ? rObject->GetGeometry().GetPoint(point)[i] : rLowPoint[i];
149  rHighPoint[i] = (rHighPoint[i] < rObject->GetGeometry().GetPoint(point)[i] ) ? rObject->GetGeometry().GetPoint(point)[i] : rHighPoint[i];
150  }
151  }
152  }
153 
154  static inline void GetBoundingBox(const PointerType rObject, double* rLowPoint, double* rHighPoint)
155  {
156 
157  for(std::size_t i = 0; i<3; i++)
158  {
159  rLowPoint[i] = rObject->GetGeometry().GetPoint(0)[i];
160  rHighPoint[i] = rObject->GetGeometry().GetPoint(0)[i];
161  }
162 
163  for (unsigned int point = 0; point<rObject->GetGeometry().PointsNumber(); point++)
164  {
165  for(std::size_t i = 0; i<3; i++)
166  {
167  rLowPoint[i] = (rLowPoint[i] > rObject->GetGeometry().GetPoint(point)[i] ) ? rObject->GetGeometry().GetPoint(point)[i] : rLowPoint[i];
168  rHighPoint[i] = (rHighPoint[i] < rObject->GetGeometry().GetPoint(point)[i] ) ? rObject->GetGeometry().GetPoint(point)[i] : rHighPoint[i];
169  }
170  }
171  }
172 
173  static inline bool Intersection(const PointerType& rObj_1, const PointerType& rObj_2)
174  {
175  Element::GeometryType& geom_1 = rObj_1->GetGeometry();
176  Element::GeometryType& geom_2 = rObj_2->GetGeometry();
177  return geom_1.HasIntersection(geom_2);
178 
179  }
180 
181 
182  static inline bool IntersectionBox(const PointerType& rObject, const PointType& rLowPoint, const PointType& rHighPoint)
183  {
184  return rObject->GetGeometry().HasIntersection(rLowPoint, rHighPoint);
185  }
186 
187 
188  static inline bool IsIntersected(const Element::Pointer rObject, double Tolerance, const double* rLowPoint, const double* rHighPoint)
189  {
190  Point low_point(rLowPoint[0] - Tolerance, rLowPoint[1] - Tolerance, rLowPoint[2] - Tolerance);
191  Point high_point(rHighPoint[0] + Tolerance, rHighPoint[1] + Tolerance, rHighPoint[2] + Tolerance);
192 
193  KRATOS_THROW_ERROR(std::logic_error, "Not Implemented method", "")
194  //return HasIntersection(rObject->GetGeometry(), low_point, high_point);
195  }
196 
197 
201 
202 
206 
207 
211 
213  virtual std::string Info() const
214  {
215  return " Spatial Containers Configure";
216  }
217 
219  virtual void PrintInfo(std::ostream& rOStream) const {}
220 
222  virtual void PrintData(std::ostream& rOStream) const {}
223 
224 
226 
227 protected:
228 
229 private:
230 
233 
236 
237 
238 }; // Class DistanceSpatialContainersConfigure
239 
242 
246 
247 
251 
255 
259 
261 
264  : public Process
265 {
266 public:
269 
272 
277  typedef Point PointType;
278  typedef OctreeType::cell_type::object_container_type object_container_type;
279  typedef struct{
282  unsigned int EdgeNode1;
283  unsigned int EdgeNode2;
285  typedef struct{
286  std::vector<IntersectionNodeStruct> IntNodes;
287  }TetEdgeStruct;
288 
289 
293 
295  CalculateSignedDistanceTo3DSkinProcess(ModelPart& rThisModelPartStruc, ModelPart& rThisModelPartFluid)
296  : mrSkinModelPart(rThisModelPartStruc), mrBodyModelPart(rThisModelPartStruc), mrFluidModelPart(rThisModelPartFluid)
297  {
298  }
299 
302  {
303  }
304 
305 
309 
310  void operator()()
311  {
312  Execute();
313  }
314 
315 
319 
322 
323  void Execute() override
324  {
325  KRATOS_TRY;
326 
327  GenerateOctree();
328 
329  //DistanceFluidStructure();
330 
331  CalculateDistanceToSkinProcess<3> distance_process(mrFluidModelPart, mrBodyModelPart);
332  distance_process.Execute();
333 
334  // ------------------------------------------------------------------
335  // GenerateNodes();
336  CalculateDistance2(); // I have to change this. Pooyan.
337  //mrSkinModelPart.GetCommunicator().AssembleCurrentData(DISTANCE);
338  // std::ofstream mesh_file1("octree1.post.msh");
339  // std::ofstream res_file("octree1.post.res");
340  // Timer::Start("Writing Gid conform Mesh");
341  // PrintGiDMesh(mesh_file1);
342  // PrintGiDResults(res_file);
343  // octree.PrintGiDMeshNew(mesh_file2);
344  // Timer::Stop("Writing Gid conform Mesh");
345  // delete octree. TODO: Carlos
346  // ------------------------------------------------------------------
347 
348  KRATOS_CATCH("");
349  }
350 
353 
360  {
361  //loop over nodes and find the tetra in which it falls, than do interpolation
362  Vector N;
363  const int max_results = 10000;
365  const int n_structure_nodes = mrSkinModelPart.Nodes().size();
366 
367 #pragma omp parallel for firstprivate(results,N)
368  //MY NEW LOOP: reset the viisted flaf
369  for (int i = 0; i < n_structure_nodes; i++)
370  {
371  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
372  Node ::Pointer p_structure_node = *(iparticle.base());
373  p_structure_node->Set(VISITED, false);
374  }
375  for (int i = 0; i < n_structure_nodes; i++)
376  {
377  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
378  Node ::Pointer p_structure_node = *(iparticle.base());
379  BinBasedFastPointLocator<3>::ResultIteratorType result_begin = results.begin();
380  Element::Pointer pElement;
381 
382  bool is_found = node_locator.FindPointOnMesh(p_structure_node->Coordinates(), N, pElement, result_begin, max_results);
383 
384  if (is_found == true)
385  {
386  array_1d<double,4> nodalPressures;
387  const Vector& ElementalDistances = pElement->GetValue(ELEMENTAL_DISTANCES);
388 
389  Geometry<Node >& geom = pElement->GetGeometry();
390 
391  for(unsigned int j=0; j<geom.size(); j++)
392  {
393  nodalPressures[j] = geom[j].FastGetSolutionStepValue(PRESSURE);
394  }
395 
396  if(pElement->GetValue(SPLIT_ELEMENT)==true)
397  {
398  array_1d<double,4> Npos,Nneg;
399 
400  // Do mapping
401  ComputeDiscontinuousInterpolation((*p_structure_node),pElement->GetGeometry(),ElementalDistances,Npos,Nneg);
402 
403  // Compute face pressure
404  double p_positive_structure = inner_prod(nodalPressures,Npos);
405  double p_negative_structure = inner_prod(nodalPressures,Nneg);
406 
407  // Assign ModelPart::ElementIteratorface pressure to structure node
408  p_structure_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE) = p_positive_structure;
409  p_structure_node->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE) = p_negative_structure;
410  p_structure_node->Set(VISITED);
411  }
412  else
413  {
414  double p = inner_prod(nodalPressures,N);
415  p_structure_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE) = p;
416  p_structure_node->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE) = p;
417  p_structure_node->Set(VISITED);
418  }
419  }
420  }
421  //AND NOW WE "TREAT" the bad nodes, the ones that belong to the structural faces that by some chance did not cross the fluid elements
422  //to such nodes we simply extrapolate the pressure from the neighbors
423  int n_bad_nodes=0;
424  for (int i = 0; i < n_structure_nodes; i++)
425  {
426  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
427  Node ::Pointer p_structure_node = *(iparticle.base());
428  if (p_structure_node->IsNot(VISITED))
429  n_bad_nodes++;
430  }
431  //KRATOS_WATCH("THERE WERE THIS MANY BAD NODES ORIGINALLY")
432  //KRATOS_WATCH(n_bad_nodes)
433  while (n_bad_nodes >= 1.0) {
434  int n_bad_nodes_backup = n_bad_nodes;
435 
436  for (int i = 0; i < n_structure_nodes; i++) {
437  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
438  Node ::Pointer p_structure_node = *(iparticle.base());
439 
440  //here we store the number of neigbor nodes that were given the pressure in the previous loop (i.e. were found)
441  if (p_structure_node->IsNot(VISITED)) {
442  int n_good_neighbors = 0;
443  double pos_pres = 0.0;
444  double neg_pres = 0.0;
445  GlobalPointersVector< Node >& neighours = p_structure_node->GetValue(NEIGHBOUR_NODES);
446 
447  for (GlobalPointersVector< Node >::iterator j = neighours.begin(); j != neighours.end(); j++) {
448  if (j->Is(VISITED)) {
449  n_good_neighbors++;
450  pos_pres += j->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE);
451  neg_pres += j->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE);
452  //KRATOS_WATCH("Good neighbor found")
453  }
454  }
455  if (n_good_neighbors != 0) {
456  pos_pres /= n_good_neighbors;
457  neg_pres /= n_good_neighbors;
458  p_structure_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE) = pos_pres;
459  p_structure_node->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE) = neg_pres;
460  p_structure_node->Set(VISITED);
461  n_bad_nodes--;
462  }
463  //KRATOS_WATCH(pos_pres)
464  //KRATOS_WATCH(neg_pres)
465  }
466  }
467 
468  if(n_bad_nodes == n_bad_nodes_backup) break; //WE BREAK THE WHILE HERE, OTHERWISE THE CODE HANGS (it was not able to remove any other node)
469 
470  /*int n_bad_nodes=0;
471  for (int i = 0; i < n_structure_nodes; i++)
472  {
473  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
474  Node ::Pointer p_structure_node = *(iparticle.base());
475  if (p_structure_node->IsNot(VISITED))
476  n_bad_nodes++;
477  }
478  */
479  //KRATOS_WATCH(n_bad_nodes)
480 
481  }
482  //THE BELOW ONE IS A "CHEAT".. THERE IS A PROBLEM OF INCORRECT PROJECTION BETWEEN THE MESHES AT SOME POINTS
483  //FOR NODES WITH PRESSURE VERY DIFFERENT FROM THAT OF THE NEIGHBORS, I JUST TAKE THE NEIGHBOR PRESSURE AVERAGED
484  for (int i = 0; i < n_structure_nodes; i++)
485  {
486  ModelPart::NodesContainerType::iterator iparticle = mrSkinModelPart.NodesBegin() + i;
487  Node ::Pointer p_structure_node = *(iparticle.base());
488 
489  double pos_pressure=p_structure_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE);
490  double neg_pressure=p_structure_node->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE);
491 
492  GlobalPointersVector< Node >& neighours = p_structure_node->GetValue(NEIGHBOUR_NODES);
493 
494  if (neighours.size()>=1.0)
495  {
496  double av_pos_pres=0.0;
497  double av_neg_pres=0.0;
499  j != neighours.end(); j++)
500  {
501 
502  av_pos_pres+=j->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE);
503  av_neg_pres+=j->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE);
504 
505  }
506  av_pos_pres/=neighours.size();
507  av_neg_pres/=neighours.size();
508 
509  //IF the average pressure of the neighbors is 10 times lower than of the given node, something is bad and we reset its value
510  if (fabs(pos_pressure)>3.0*fabs(av_pos_pres))
511  {
512  p_structure_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE) = av_pos_pres;
513  //KRATOS_WATCH("BAD NODE")
514  }
515  if (fabs(neg_pressure)>3.0*fabs(av_neg_pres))
516  {
517  p_structure_node->FastGetSolutionStepValue(NEGATIVE_FACE_PRESSURE) = av_neg_pres;
518  //KRATOS_WATCH("BAD NODE")
519  }
520 
521  }
522  }
523 
524 
525 
526  }
527 
530 
532  Geometry< Node >& geom,
533  const array_1d<double,4>& distances,
534  array_1d<double,4>& Npos,
535  array_1d<double,4>& Nneg)
536  {
537  //count positives
538  int n_positives = 0;
539  for(unsigned int i=0; i<distances.size(); i++)
540  if(distances[i]>0) n_positives++;
541 
542  //generate the points on the edges at the zero of the distance function
543  //generate "father nodes", defined as the end nodes of the edge on which the local point is located
544  std::vector< Point > edge_points;
545  edge_points.reserve(4);
546  array_1d<unsigned int, 4> positive_fathers, negative_fathers; //there are at most 4 cut edges
547  unsigned int k=0;
548  unsigned int l=0;
549 
550  for(unsigned int i=0; i<3; i++)
551  {
552  for(unsigned int j=i+1; j<4; j++) // go through the edges 01, 02, 03, 12, 13, 23
553  {
554  double di = distances[i];
555  double dj = distances[j];
556 
557  if(di*dj < 0) //edge is cut
558  {
559  //generate point on edge by linear interpolation
560  double Ni = fabs(dj) / ( fabs(di) + fabs(dj) );
561  double Nj = 1.0 - Ni;
562  Point edge_point(Ni * geom[i] + Nj * geom[j]);
563  edge_points.push_back(edge_point);
564 
565  //store the id of the positive and negative fathers
566  if(di > 0.0)
567  {
568  positive_fathers[k++] = i;
569  negative_fathers[l++] = j;
570  }
571  else
572  {
573  positive_fathers[k++] = j;
574  negative_fathers[l++] = i;
575  }
576  }
577  }
578  }
579 
580  if(edge_points.size() == 3)
581  {
582  //compute local shape functions (tell how to interpolate from the edge nodes)
583  Vector Nlocal(3);
584 
585  //form a triangle with the edge nodes
586  Triangle3D3< Point > triangle(Point::Pointer(new Point(edge_points[0])),
587  Point::Pointer(new Point(edge_points[1])),
588  Point::Pointer(new Point(edge_points[2]))
589  );
590 
591  array_1d<double,3> local_coords;
592  local_coords = triangle.PointLocalCoordinates(local_coords, pNode);
593 
594  for(unsigned int i=0; i<3;i++)
595  Nlocal[i] = triangle.ShapeFunctionValue(i, local_coords );
596 
597  noalias(Npos) = ZeroVector(4);
598  noalias(Nneg) = ZeroVector(4);
599  for(unsigned int i=0; i<3; i++)
600  {
601  Npos[ positive_fathers[i] ] += Nlocal[i];
602  Nneg[ negative_fathers[i] ] += Nlocal[i];
603  }
604  }
605 
606  if(edge_points.size() == 4)
607  {
608  //compute local shape functions (tell how to interpolate from the edge nodes)
609  Vector Nlocal(4);
610 
611  //form a quadrilatera with the 4 cut nodes
612  array_1d<double,3> x21 = edge_points[1] - edge_points[0];
613  array_1d<double,3> x31 = edge_points[2] - edge_points[0];
614  array_1d<double,3> x41 = edge_points[3] - edge_points[0];
615 
616  //define a vector oriented as x21
617  array_1d<double,3> v1 = x21 / norm_2(x21);
618 
620  array_1d<double,4> msN;
621  double Area;
622  GeometryUtils::CalculateGeometryData( geom, DN_DX, msN, Area );
623 
624  array_1d<double,3> n = prod(trans(DN_DX),distances);
625  n /= norm_2(n);
626 
628  MathUtils<double>::CrossProduct(v2,v1,n); // v2 = v1 x n
629 
630  array_1d<double,3> angles;
631  angles[0] = 0.0; //angle between x21 and v1
632  angles[1] = atan2( inner_prod(x31,v2), inner_prod(x31,v1) ); //angle between x31 and v1
633  angles[2] = atan2( inner_prod(x41,v2), inner_prod(x41,v1) ); //angle between x31 and v1
634 
635  double max_angle = 0.0;
636  double min_angle = 0.0;
637  unsigned int min_pos = 1;
638  unsigned int max_pos = 1;
639  for(unsigned int i=1; i<3; i++)
640  {
641  if(angles[i] < min_angle)
642  {
643  min_pos = i+1; //this is the local index of the edge point which forms the minimal angle
644  min_angle = angles[i];
645  }
646  else if(angles[i] > max_angle)
647  {
648  max_pos = i+1; //this is the local index of the edge point which forms the maximal angle
649  max_angle = angles[i];
650  }
651  }
652 
653  //find the pos of the center node
654  unsigned int center_pos = 0;
655  for(unsigned int i=1; i<4; i++)
656  {
657  if((i!= min_pos) && (i!=max_pos))
658  { center_pos = i; }
659  }
660 
661  //form a quadrilateral with the edge nodes
663  Point::Pointer(new Point(edge_points[0])),
664  Point::Pointer(new Point(edge_points[min_pos])),
665  Point::Pointer(new Point(edge_points[center_pos])),
666  Point::Pointer(new Point(edge_points[max_pos]))
667  );
668 
669  array_1d<double,3> local_coords;
670  local_coords = quad.PointLocalCoordinates(local_coords, pNode);
671 
673  indices[0] = 0;
674  indices[1] = min_pos;
675  indices[2] = center_pos;
676  indices[3] = max_pos;
677 
678  for(unsigned int i=0; i<4;i++)
679  Nlocal[ i ] = quad.ShapeFunctionValue(i, local_coords );
680 
681  noalias(Npos) = ZeroVector(4);
682  noalias(Nneg) = ZeroVector(4);
683  for(unsigned int i=0; i<4; i++)
684  {
685  Npos[ positive_fathers[i] ] += Nlocal[indices[i]];
686  Nneg[ negative_fathers[i] ] += Nlocal[indices[i]];
687  }
688  }
689  }
690 
693 
695  Node& node)
696  {
697  //loop over nodes and find the tetra in which it falls, than do interpolation
698  Vector N;
699  const int max_results = 10000;
701  BinBasedFastPointLocator<3>::ResultIteratorType result_begin = results.begin();
702  Element::Pointer pElement;
703 
704  bool is_found = node_locator.FindPointOnMesh(node.Coordinates(), N, pElement, result_begin, max_results);
705 
706  if (is_found == true)
707  {
708  array_1d<double,4> nodalPressures;
709  const Vector& ElementalDistances = pElement->GetValue(ELEMENTAL_DISTANCES);
710  Geometry<Node >& geom = pElement->GetGeometry();
711 
712  for(unsigned int i=0; i<4; i++)
713  nodalPressures[i] = geom[i].GetSolutionStepValue(PRESSURE);
714 
715  if(pElement->GetValue(SPLIT_ELEMENT)==true)
716  {
717  // Compute average of all positive and all negative values
718  double positiveAverage = 0;
719  double negativeAverage = 0;
720  unsigned int nPos = 0;
721  unsigned int nNeg = 0;
722 
723  for(unsigned int i=0 ; i<4 ; i++)
724  {
725  if(ElementalDistances[i]>=0)
726  {
727  positiveAverage += nodalPressures[i];
728  nPos++;
729  }
730  else
731  {
732  negativeAverage += nodalPressures[i];
733  nNeg++;
734  }
735  }
736 
737  positiveAverage /= nPos;
738  negativeAverage /= nNeg;
739 
740  // Assign Pressures
741  node.GetSolutionStepValue(POSITIVE_FACE_PRESSURE,0) = positiveAverage;
742  node.GetSolutionStepValue(NEGATIVE_FACE_PRESSURE,0) = negativeAverage;
743  }
744  else
745  {
746  // Compute average of all positive and all negative values
747  double Average = 0;
748 
749  // for output of
750  for(unsigned int i = 0 ; i<4 ; i++)
751  Average += nodalPressures[i];
752 
753  Average /= 4;
754 
755  // Assign Pressures
756  node.GetSolutionStepValue(POSITIVE_FACE_PRESSURE,0) = Average;
757  node.GetSolutionStepValue(NEGATIVE_FACE_PRESSURE,0) = Average;
758  }
759  }
760  }
761 
764 
766  {
767  //std::cout << "Start calculating Elemental distances..." << std::endl;
768 
769  // Initialize Elemental distances in the domain
770  Initialize();
771 
772  // Initialize index table that defines line Edges of fluid Element
773  BoundedMatrix<unsigned int,6,2> TetEdgeIndexTable;
774  SetIndexTable(TetEdgeIndexTable);
775 
776  // loop over all fluid Elements
777  // this loop is parallelized using openmp
778 #ifdef _OPENMP
779  int number_of_threads = omp_get_max_threads();
780 #else
781  int number_of_threads = 1;
782 #endif
783 
784  ModelPart::ElementsContainerType& pElements = mrFluidModelPart.Elements();
785 
786  DenseVector<unsigned int> Element_partition;
787  CreatePartition(number_of_threads, pElements.size(), Element_partition);
788 
789 #pragma omp parallel for
790  for (int k = 0; k < number_of_threads; k++)
791  {
792  ModelPart::ElementsContainerType::iterator it_begin = pElements.ptr_begin() + Element_partition[k];
793  ModelPart::ElementsContainerType::iterator it_end = pElements.ptr_begin() + Element_partition[k+1];
794 
795  // assemble all Elements
796  for (ModelPart::ElementIterator it = it_begin; it != it_end; ++it)
797  {
798  CalcElementDistances( it , TetEdgeIndexTable );
799  }
800  }
801 
802  // Finally, each tetrahedral Element has 4 distance values. But each node belongs to
803  // several Elements, such that it is assigned several distance values
804  // --> now synchronize these values by finding the minimal distance and assign to each node a minimal nodal distance
805  AssignMinimalNodalDistance();
806 
807  //std::cout << "Finished calculating Elemental distances..." << std::endl;
808  }
809 
812 
813  void Initialize()
814  {
815  const double initial_distance = 1.0;
816 
817  ModelPart::NodesContainerType::ContainerType& nodes = mrFluidModelPart.NodesArray();
818 
819  // reset the node distance to 1.0 which is the maximum distance in our normalized space.
820  int nodesSize = nodes.size();
821 
822 #pragma omp parallel for firstprivate(nodesSize)
823  for(int i = 0 ; i < nodesSize ; i++)
824  nodes[i]->GetSolutionStepValue(DISTANCE) = initial_distance;
825 
826  ModelPart::ElementsContainerType::ContainerType& fluid_Elements = mrFluidModelPart.ElementsArray();
827 
828  array_1d<double,4> ElementalDistances;
829  ElementalDistances[0] = initial_distance;
830  ElementalDistances[1] = initial_distance;
831  ElementalDistances[2] = initial_distance;
832  ElementalDistances[3] = initial_distance;
833 
834  // reset the Elemental distance to 1.0 which is the maximum distance in our normalized space.
835  // also initialize the embedded velocity of the fluid Element
836  int ElementsSize = fluid_Elements.size();
837 
838 #pragma omp parallel for firstprivate(ElementsSize)
839  for(int i = 0 ; i < ElementsSize ; i++)
840  {
841  fluid_Elements[i]->GetValue(ELEMENTAL_DISTANCES) = ElementalDistances;
842  fluid_Elements[i]->GetValue(SPLIT_ELEMENT) = false;
843  fluid_Elements[i]->GetValue(EMBEDDED_VELOCITY)=ZeroVector(3);
844  }
845 
846  }
847 
850 
852  {
853  // Initialize index table to define line Edges of fluid Element
854  TetEdgeIndexTable(0,0) = 0;
855  TetEdgeIndexTable(0,1) = 1;
856  TetEdgeIndexTable(1,0) = 0;
857  TetEdgeIndexTable(1,1) = 2;
858  TetEdgeIndexTable(2,0) = 0;
859  TetEdgeIndexTable(2,1) = 3;
860  TetEdgeIndexTable(3,0) = 1;
861  TetEdgeIndexTable(3,1) = 2;
862  TetEdgeIndexTable(4,0) = 1;
863  TetEdgeIndexTable(4,1) = 3;
864  TetEdgeIndexTable(5,0) = 2;
865  TetEdgeIndexTable(5,1) = 3;
866  }
867 
870 
872  BoundedMatrix<unsigned int,6,2> TetEdgeIndexTable )
873  {
874  std::vector<OctreeType::cell_type*> leaves;
875  std::vector<TetEdgeStruct> IntersectedTetEdges;
876  unsigned int NumberIntersectionsOnTetCorner = 0;
877 
878  // Get leaves of octree intersecting with fluid Element
879  mpOctree->GetIntersectedLeaves(*(i_fluidElement).base(),leaves);
880 
881  int intersection_counter = 0;
882 
883  // Loop over all 6 line Edges of the tetrahedra
884  for(unsigned int i_tetEdge = 0;
885  i_tetEdge < 6;
886  i_tetEdge++)
887  {
888  IdentifyIntersectionNodes( i_fluidElement, i_tetEdge, leaves, IntersectedTetEdges, NumberIntersectionsOnTetCorner, TetEdgeIndexTable, intersection_counter );
889  }
890 
891  if (intersection_counter!=0)
892  {
893  i_fluidElement->GetValue(EMBEDDED_VELOCITY) /= intersection_counter;
894  }
895 
896  if(IntersectedTetEdges.size() > 0)
897  CalcDistanceTo3DSkin( IntersectedTetEdges , i_fluidElement , NumberIntersectionsOnTetCorner );
898  }
899 
902 
904  unsigned int i_tetEdge,
905  std::vector<OctreeType::cell_type*>& leaves,
906  std::vector<TetEdgeStruct>& IntersectedTetEdges,
907  unsigned int& NumberIntersectionsOnTetCorner,
908  BoundedMatrix<unsigned int,6,2> TetEdgeIndexTable,
909  int& intersection_counter )
910  {
911  std::vector<unsigned int> IntersectingStructElemID;
912  TetEdgeStruct NewTetEdge;
913  unsigned int NumberIntersectionsOnTetCornerCurrentEdge = 0;
914 
915  // Get nodes of line Edge
916  unsigned int EdgeStartIndex = TetEdgeIndexTable(i_tetEdge,0);
917  unsigned int EdgeEndIndex = TetEdgeIndexTable(i_tetEdge,1);
918 
919  PointType& P1 = i_fluidElement->GetGeometry()[EdgeStartIndex];
920  PointType& P2 = i_fluidElement->GetGeometry()[EdgeEndIndex];
921 
922  double EdgeNode1[3] = {P1.X() , P1.Y() , P1.Z()};
923  double EdgeNode2[3] = {P2.X() , P2.Y() , P2.Z()};
924 
925  // loop over all octree cells which are intersected by the fluid Element
926  for(unsigned int i_cell = 0 ; i_cell < leaves.size() ; i_cell++)
927  {
928  // Structural Element contained in one cell of the octree
929  object_container_type* struct_elem = (leaves[i_cell]->pGetObjects());
930 
931  // loop over all structural Elements within each octree cell
932  for(object_container_type::iterator i_StructElement = struct_elem->begin(); i_StructElement != struct_elem->end(); i_StructElement++)
933  {
934 
935  if( StructuralElementNotYetConsidered( (*i_StructElement)->Id() , IntersectingStructElemID ) )
936  {
937 
938  // Calculate and associate intersection point to the current fluid Element
939  double IntersectionPoint[3] = {0.0 , 0.0 , 0.0};
940  int TetEdgeHasIntersections = IntersectionTriangleSegment( (*i_StructElement)->GetGeometry() , EdgeNode1 , EdgeNode2 , IntersectionPoint );
941 
942  if( TetEdgeHasIntersections == 1 )
943  {
944  IntersectionNodeStruct NewIntersectionNode;
945 
946  // Assign information to the intersection node
947  NewIntersectionNode.Coordinates[0] = IntersectionPoint[0];
948  NewIntersectionNode.Coordinates[1] = IntersectionPoint[1];
949  NewIntersectionNode.Coordinates[2] = IntersectionPoint[2];
950 
951  if( IsIntersectionNodeOnTetEdge( IntersectionPoint , EdgeNode1 , EdgeNode2 ) )
952  {
953  if ( IsNewIntersectionNode( NewIntersectionNode , IntersectedTetEdges ) )
954  {
955  // Calculate normal of the structural Element at the position of the intersection point
956  CalculateNormal3D((*i_StructElement)->GetGeometry()[0],
957  (*i_StructElement)->GetGeometry()[1],
958  (*i_StructElement)->GetGeometry()[2],
959  NewIntersectionNode.StructElemNormal);
960 
961  // check, how many intersection nodes are located on corner points of the tetrahedra
962  if ( IsIntersectionOnCorner( NewIntersectionNode , EdgeNode1 , EdgeNode2) )
963  {
964  NumberIntersectionsOnTetCornerCurrentEdge++;
965 
966  // only allow one intersection node on a tet edge
967  if(NumberIntersectionsOnTetCornerCurrentEdge < 2)
968  {
969  // add the new intersection point to the list of intersection points of the fluid Element
970  NewIntersectionNode.EdgeNode1 = EdgeStartIndex;
971  NewIntersectionNode.EdgeNode2 = EdgeEndIndex;
972  NewTetEdge.IntNodes.push_back(NewIntersectionNode);
973 
974  // if tet edge belonging to this intersection point is not already marked as "IntersectedTetEdge" --> put it into the respective container
975  // when a second intersection node is found, then it is not necessary to push_back again
976  if( NewTetEdge.IntNodes.size() == 1 )
977  IntersectedTetEdges.push_back(NewTetEdge);
978  }
979 
980  // this corner intersection node is only considered once for each tet edge
981  if(NumberIntersectionsOnTetCornerCurrentEdge==1)
982  {
983  NumberIntersectionsOnTetCorner++;
984  }
985  }
986  else
987  {
988  // add the new intersection point to the list of intersection points of the fluid Element
989  NewIntersectionNode.EdgeNode1 = EdgeStartIndex;
990  NewIntersectionNode.EdgeNode2 = EdgeEndIndex;
991  NewTetEdge.IntNodes.push_back(NewIntersectionNode);
992 
993  // velocity mapping structure --> fluid
994  array_1d<double,3> emb_vel = (*i_StructElement)->GetGeometry()[0].GetSolutionStepValue(VELOCITY);
995  emb_vel += (*i_StructElement)->GetGeometry()[1].GetSolutionStepValue(VELOCITY);
996  emb_vel += (*i_StructElement)->GetGeometry()[2].GetSolutionStepValue(VELOCITY);
997 
998  i_fluidElement->GetValue(EMBEDDED_VELOCITY) += emb_vel/3;
999  intersection_counter++;
1000  }
1001  }
1002  }
1003  }
1004  }
1005  }
1006  }
1007 
1008  // Finally put the found intersection nodes into the container
1009  if( NewTetEdge.IntNodes.size() > 0 )
1010  {
1011  if(NumberIntersectionsOnTetCornerCurrentEdge == 0)
1012  IntersectedTetEdges.push_back(NewTetEdge);
1013  }
1014  }
1015 
1018 
1019  bool StructuralElementNotYetConsidered( unsigned int IDCurrentStructElem,
1020  std::vector<unsigned int>& IntersectingStructElemID )
1021  {
1022  // check if the structural Element was already considered as intersecting Element
1023  for(unsigned int k = 0 ; k < IntersectingStructElemID.size() ; k++)
1024  {
1025  if( IDCurrentStructElem == IntersectingStructElemID[k] )
1026  return false;
1027  }
1028 
1029  // if structural Element has not been considered in another octree, which also intersects the fluid Element
1030  // add the new object ID to the vector
1031  IntersectingStructElemID.push_back( IDCurrentStructElem );
1032  return true;
1033  }
1034 
1037 
1038  bool IsIntersectionNodeOnTetEdge( double* IntersectionPoint,
1039  double* EdgeNode1,
1040  double* EdgeNode2 )
1041  {
1042  // check, if intersection point is located on any edge of the fluid Element
1043  array_1d<double,3> ConnectVectTetNodeIntNode1;
1044  array_1d<double,3> ConnectVectTetNodeIntNode2;
1045  array_1d<double,3> EdgeVector;
1046 
1047  ConnectVectTetNodeIntNode1[0] = IntersectionPoint[0] - EdgeNode1[0];
1048  ConnectVectTetNodeIntNode1[1] = IntersectionPoint[1] - EdgeNode1[1];
1049  ConnectVectTetNodeIntNode1[2] = IntersectionPoint[2] - EdgeNode1[2];
1050 
1051  ConnectVectTetNodeIntNode2[0] = IntersectionPoint[0] - EdgeNode2[0];
1052  ConnectVectTetNodeIntNode2[1] = IntersectionPoint[1] - EdgeNode2[1];
1053  ConnectVectTetNodeIntNode2[2] = IntersectionPoint[2] - EdgeNode2[2];
1054 
1055  double LengthConnectVect1 = norm_2( ConnectVectTetNodeIntNode1 );
1056  double LengthConnectVect2 = norm_2( ConnectVectTetNodeIntNode2 );
1057 
1058  EdgeVector[0] = EdgeNode2[0] - EdgeNode1[0];
1059  EdgeVector[1] = EdgeNode2[1] - EdgeNode1[1];
1060  EdgeVector[2] = EdgeNode2[2] - EdgeNode1[2];
1061 
1062  double MaxEdgeLength = norm_2( EdgeVector );
1063 
1064  // if both connection vectors (corner point --> intersection point)
1065  // are smaller or equal to the edge length of tetrahedra,
1066  // then intersection point is located on the edge
1067  if( (LengthConnectVect1 <= (MaxEdgeLength)) && (LengthConnectVect2 <= (MaxEdgeLength)) )
1068  return true;
1069  else
1070  return false;
1071  }
1072 
1075 
1076  bool IsNewIntersectionNode( IntersectionNodeStruct& NewIntersectionNode,
1077  std::vector<TetEdgeStruct>& IntersectedTetEdges )
1078  {
1079  array_1d<double,3> DiffVector;
1080  double NormDiffVector = 0;
1081  unsigned int NumberIntNodes = 0;
1082 
1083  for( unsigned int i_TetEdge = 0 ; i_TetEdge < IntersectedTetEdges.size() ; i_TetEdge++ )
1084  {
1085  NumberIntNodes = IntersectedTetEdges[i_TetEdge].IntNodes.size();
1086  for( unsigned int i_IntNode = 0 ; i_IntNode < NumberIntNodes ; i_IntNode++ )
1087  {
1088  DiffVector[0] = NewIntersectionNode.Coordinates[0] - IntersectedTetEdges[i_TetEdge].IntNodes[i_IntNode].Coordinates[0];
1089  DiffVector[1] = NewIntersectionNode.Coordinates[1] - IntersectedTetEdges[i_TetEdge].IntNodes[i_IntNode].Coordinates[1];
1090  DiffVector[2] = NewIntersectionNode.Coordinates[2] - IntersectedTetEdges[i_TetEdge].IntNodes[i_IntNode].Coordinates[2];
1091 
1092  NormDiffVector = norm_2(DiffVector);
1093 
1094  if( NormDiffVector < epsilon )
1095  return false;
1096  }
1097  }
1098 
1099  // if the new intersection node is not existing (as intersection with a corner point), then return false
1100  return true;
1101  }
1102 
1105 
1107  double* EdgeNode1,
1108  double* EdgeNode2 )
1109  {
1110  array_1d<double,3> DiffVector;
1111  double NormDiffVector;
1112 
1113  DiffVector[0] = EdgeNode1[0] - NewIntersectionNode.Coordinates[0];
1114  DiffVector[1] = EdgeNode1[1] - NewIntersectionNode.Coordinates[1];
1115  DiffVector[2] = EdgeNode1[2] - NewIntersectionNode.Coordinates[2];
1116  NormDiffVector = norm_2(DiffVector);
1117 
1118  if( NormDiffVector < epsilon )
1119  return true;
1120 
1121  DiffVector[0] = EdgeNode2[0] - NewIntersectionNode.Coordinates[0];
1122  DiffVector[1] = EdgeNode2[1] - NewIntersectionNode.Coordinates[1];
1123  DiffVector[2] = EdgeNode2[2] - NewIntersectionNode.Coordinates[2];
1124  NormDiffVector = norm_2(DiffVector);
1125 
1126  if( NormDiffVector < epsilon )
1127  return true;
1128  else
1129  return false;
1130  }
1131 
1134 
1135  void CalculateNormal3D( Point& Point1,
1136  Point& Point2,
1137  Point& Point3,
1138  array_1d<double,3>& rResultNormal )
1139  {
1140  array_1d<double,3> v1 = Point2 - Point1;
1141  array_1d<double,3> v2 = Point3 - Point1;
1142 
1143  MathUtils<double>::CrossProduct(rResultNormal,v1,v2);
1144  rResultNormal *= 0.5;
1145  }
1146 
1149 
1150  void CalcDistanceTo3DSkin( std::vector<TetEdgeStruct>& IntersectedTetEdges,
1152  unsigned int NumberIntersectionsOnTetCorner )
1153  {
1154  std::vector<IntersectionNodeStruct> NodesOfApproximatedStructure;
1155  array_1d<double,4> ElementalDistances;
1156 
1157  FillIntNodesContainer(IntersectedTetEdges,NodesOfApproximatedStructure);
1158 
1159  // Intersection with one corner point
1160  if( NodesOfApproximatedStructure.size() == 1 && NumberIntersectionsOnTetCorner == 1 )
1161  {
1162  CalcSignedDistancesToOneIntNode(i_fluid_Element,NodesOfApproximatedStructure,ElementalDistances);
1163  i_fluid_Element->GetValue(SPLIT_ELEMENT) = true;
1164  }
1165 
1166  // Intersection with two corner points / one tetrahedra edge
1167  if( NodesOfApproximatedStructure.size() == 2 && NumberIntersectionsOnTetCorner == 2 )
1168  {
1169  CalcSignedDistancesToTwoIntNodes(i_fluid_Element,NodesOfApproximatedStructure,ElementalDistances);
1170  i_fluid_Element->GetValue(SPLIT_ELEMENT) = true;
1171  }
1172 
1173  // Intersection with three tetrahedra edges
1174  if( NodesOfApproximatedStructure.size() == 3 )
1175  {
1176  CalcSignedDistancesToThreeIntNodes(i_fluid_Element,NodesOfApproximatedStructure,ElementalDistances);
1177  i_fluid_Element->GetValue(SPLIT_ELEMENT) = true;
1178  }
1179 
1180  // Intersection with more than three tetrahedra edges
1181  if( NodesOfApproximatedStructure.size() > 3 )
1182  {
1183  CalcSignedDistancesToMoreThanThreeIntNodes(i_fluid_Element,NodesOfApproximatedStructure,ElementalDistances,IntersectedTetEdges);
1184  i_fluid_Element->GetValue(SPLIT_ELEMENT) = true;
1185  }
1186 
1187  // Postprocessing treatment of Elemental distances
1188  if( i_fluid_Element->GetValue(SPLIT_ELEMENT) == true )
1189  AvoidZeroDistances(i_fluid_Element, ElementalDistances);
1190 
1191  // In case there is intersection with fluid Element: assign distances to the Element
1192  if( i_fluid_Element->GetValue(SPLIT_ELEMENT) == true )
1193  i_fluid_Element->GetValue(ELEMENTAL_DISTANCES) = ElementalDistances;
1194  }
1195 
1198 
1199  void FillIntNodesContainer( std::vector<TetEdgeStruct>& IntersectedTetEdges,
1200  std::vector<IntersectionNodeStruct>& NodesOfApproximatedStructure )
1201  {
1202  const unsigned int NumberCutEdges = IntersectedTetEdges.size();
1203 
1204  for(unsigned int i_TetEdge = 0 ; i_TetEdge < NumberCutEdges ; i_TetEdge++)
1205  {
1206  unsigned int NumberIntNodes = IntersectedTetEdges[i_TetEdge].IntNodes.size();
1207 
1208  for( unsigned int i_IntNode = 0 ; i_IntNode < NumberIntNodes ; i_IntNode++ )
1209  {
1210  NodesOfApproximatedStructure.push_back(IntersectedTetEdges[i_TetEdge].IntNodes[i_IntNode]);
1211  }
1212  }
1213  }
1214 
1217 
1219  std::vector<IntersectionNodeStruct> NodesOfApproximatedStructure,
1220  array_1d<double,4>& ElementalDistances )
1221  {
1222  Geometry< Node >& rFluidGeom = i_fluid_Element->GetGeometry();
1223 
1224  Point P1;
1225  P1.Coordinates() = NodesOfApproximatedStructure[0].Coordinates;
1226 
1227  array_1d<double,3>& Normal = NodesOfApproximatedStructure[0].StructElemNormal;
1228 
1229  // Compute distance values for all tet-nodes
1230  for(unsigned int i_TetNode = 0 ; i_TetNode < 4 ; i_TetNode++)
1231  {
1232  ElementalDistances[i_TetNode] = PointDistanceToPlane(P1, Normal, rFluidGeom[i_TetNode]);
1233  }
1234  }
1235 
1238 
1240  std::vector<IntersectionNodeStruct> NodesOfApproximatedStructure,
1241  array_1d<double,4>& ElementalDistances )
1242  {
1243  Geometry< Node >& rFluidGeom = i_fluid_Element->GetGeometry();
1244 
1245  Point P1;
1246  P1.Coordinates() = NodesOfApproximatedStructure[0].Coordinates;
1247 
1248  // Get normal at intersections, average them and check direction of distances
1249  array_1d<double,3> NormalAtIntersectionNode1 = NodesOfApproximatedStructure[0].StructElemNormal;
1250  array_1d<double,3> NormalAtIntersectionNode2 = NodesOfApproximatedStructure[1].StructElemNormal;
1251 
1252  // Compute normal of surface plane
1253  array_1d<double,3> Normal;
1254  Normal[0] = 0.5*(NormalAtIntersectionNode1[0] + NormalAtIntersectionNode2[0]);
1255  Normal[1] = 0.5*(NormalAtIntersectionNode1[1] + NormalAtIntersectionNode2[1]);
1256  Normal[2] = 0.5*(NormalAtIntersectionNode1[2] + NormalAtIntersectionNode2[2]);
1257 
1258  // Check whether orientation of normal is in direction of the normal of the intersecting structure
1259  // Note: The normal of the approx. surface can be max. 90deg to every surrounding normal of the structure at the intersection nodes
1260  const array_1d<double,3> NormalAtOneIntersectionNode = NodesOfApproximatedStructure[0].StructElemNormal;
1261 
1262  bool NormalWrongOriented = false;
1263  if(inner_prod(NormalAtOneIntersectionNode,Normal)<0)
1264  NormalWrongOriented = true;
1265 
1266  // switch direction of normal
1267  if(NormalWrongOriented)
1268  Normal *=-1;
1269 
1270  // Compute distance values for all tet-nodes
1271  for(unsigned int i_TetNode = 0 ; i_TetNode < 4 ; i_TetNode++)
1272  {
1273  ElementalDistances[i_TetNode] = PointDistanceToPlane(P1, Normal, rFluidGeom[i_TetNode]);
1274  }
1275  }
1276 
1279 
1281  std::vector<IntersectionNodeStruct>& NodesOfApproximatedStructure,
1282  array_1d<double,4>& ElementalDistances )
1283  {
1284  Geometry< Node >& rFluidGeom = i_fluid_Element->GetGeometry();
1285 
1286  Point P1;
1287  Point P2;
1288  Point P3;
1289 
1290  P1.Coordinates() = NodesOfApproximatedStructure[0].Coordinates;
1291  P2.Coordinates() = NodesOfApproximatedStructure[1].Coordinates;
1292  P3.Coordinates() = NodesOfApproximatedStructure[2].Coordinates;
1293 
1294  array_1d<double,3> Normal;
1295  CalculateNormal3D(P1,P2,P3,Normal);
1296 
1297  // Check whether orientation of normal is in direction of the normal of the intersecting structure
1298  // Note: The normal of the approx. surface can be max. 90deg to every surrounding normal of the structure at the intersection nodes
1299  const array_1d<double,3> NormalAtOneIntersectionNode = NodesOfApproximatedStructure[0].StructElemNormal;
1300 
1301  bool NormalWrongOriented = false;
1302  if(inner_prod(NormalAtOneIntersectionNode,Normal)<0)
1303  NormalWrongOriented = true;
1304 
1305  // switch direction of normal
1306  if(NormalWrongOriented)
1307  Normal *=-1;
1308 
1309  // Compute distance values for all tet-nodes
1310  for(unsigned int i_TetNode = 0 ; i_TetNode < 4 ; i_TetNode++)
1311  {
1312  ElementalDistances[i_TetNode] = PointDistanceToPlane(P1, Normal, rFluidGeom[i_TetNode] );
1313  }
1314  }
1315 
1318 
1320  std::vector<IntersectionNodeStruct> NodesOfApproximatedStructure,
1321  array_1d<double,4>& ElementalDistances,
1322  std::vector<TetEdgeStruct>& IntersectedTetEdges )
1323  {
1324  unsigned int numberCutEdges = NodesOfApproximatedStructure.size();
1325 
1326  // Compute average of the intersection nodes which is a node on the plane we look for
1327  Point P_mean;
1328  for(unsigned int k=0; k<numberCutEdges; k++)
1329  for(unsigned int i=0; i<3; i++)
1330  P_mean.Coordinates()[i] += NodesOfApproximatedStructure[k].Coordinates[i];
1331 
1332  for(unsigned int i=0; i<3; i++)
1333  P_mean.Coordinates()[i] /= numberCutEdges;
1334 
1335  // Compute normal for the best-fitted plane
1336  array_1d<double,3> N_mean;
1337 
1338  Matrix coordinates(numberCutEdges,3);
1339  for(unsigned int i=0; i<numberCutEdges; i++)
1340  for(unsigned int j=0; j<3; j++)
1341  coordinates(i,j) = NodesOfApproximatedStructure[i].Coordinates[j] - P_mean[j];
1342 
1343  Matrix A = prod(trans(coordinates),coordinates);
1344  Matrix V(3,3);
1345  Vector lambda(3);
1346 
1347  // Calculate the eigenvectors V and the corresponding eigenvalues lambda
1348  EigenVectors(A, V, lambda);
1349 
1350  // Look for the minimal eigenvalue all lambdas
1351  unsigned int min_pos = 0;
1352  double min_lambda = lambda[min_pos];
1353  for(unsigned int i=1;i<3; i++)
1354  if(min_lambda > lambda[i])
1355  {
1356  min_lambda = lambda[i];
1357  min_pos = i;
1358  }
1359 
1360  // the normal equals to the eigenvector which corresponds to the minimal eigenvalue
1361  for(unsigned int i=0;i<3; i++) N_mean[i] = V(min_pos,i);
1362  N_mean /= norm_2(N_mean);
1363 
1364  // Check whether orientation of normal is in direction of the normal of the intersecting structure
1365  // Note: The normal of the approx. surface can be max. 90deg to every surrounding normal of the structure at the intersection nodes
1366  array_1d<double,3> NormalAtOneIntersectionNode;
1367  NormalAtOneIntersectionNode = NodesOfApproximatedStructure[0].StructElemNormal;
1368 
1369  bool NormalWrongOriented = false;
1370  if(inner_prod(NormalAtOneIntersectionNode,N_mean)<0)
1371  NormalWrongOriented = true;
1372 
1373  // switch direction of normal
1374  if(NormalWrongOriented)
1375  N_mean *=-1;
1376 
1377  // Determine about the minimal distance by considering the distances to both triangles
1378  for(unsigned int i_TetNode = 0 ; i_TetNode < 4 ; i_TetNode++)
1379  {
1380  ElementalDistances[i_TetNode] = PointDistanceToPlane(P_mean, N_mean, i_fluid_Element->GetGeometry()[i_TetNode] );
1381  }
1382 
1383  // #################################################
1384  unsigned int numberDoubleCutEdges = 0;
1385  unsigned int indexDoubleCutEdge = 0;
1386 
1387  // figure out the edges which are cut more than once
1388  for(unsigned int i_TetEdge = 0 ; i_TetEdge < IntersectedTetEdges.size() ; i_TetEdge++)
1389  {
1390  unsigned int NumberIntNodes = IntersectedTetEdges[i_TetEdge].IntNodes.size();
1391  if(NumberIntNodes == 2)
1392  {
1393  numberDoubleCutEdges++;
1394  indexDoubleCutEdge = i_TetEdge;
1395  }
1396  }
1397 
1398  if((numberDoubleCutEdges >= 1))
1399  {
1400  array_1d<double,3> normal_1 = IntersectedTetEdges[indexDoubleCutEdge].IntNodes[0].StructElemNormal;
1401  array_1d<double,3> normal_2 = IntersectedTetEdges[indexDoubleCutEdge].IntNodes[1].StructElemNormal;
1402 
1403  // normalize normals
1404  normal_1 /= norm_2(normal_1);
1405  normal_2 /= norm_2(normal_2);
1406 
1407  const double pi = 3.1415926;
1408 
1409  // compute angle between normals
1410  double angle_n1n2 = acos( inner_prod(normal_1,normal_2) );
1411  // rad --> degree
1412  angle_n1n2 *= 180 / pi;
1413 
1414  // if angle between -60º and 120º, take the mean
1415  if( (angle_n1n2 > -60) && (angle_n1n2 < 120) )
1416  {
1417  // take the mean of the normals
1418  N_mean = 0.5 * (normal_1 + normal_2);
1419  }
1420  else
1421  {
1422  N_mean = 0.5 * (normal_1 - normal_2);
1423  }
1424 
1425  // Based on N_mean and P_mean compute the distances to that plane
1426  for(unsigned int i_TetNode = 0 ; i_TetNode < 4 ; i_TetNode++)
1427  {
1428  ElementalDistances[i_TetNode] = PointDistanceToPlane(P_mean, N_mean, i_fluid_Element->GetGeometry()[i_TetNode] );
1429  }
1430  }
1431  }
1432 
1435 
1443  double PointDistanceToPlane( Point& planeBasePoint,
1444  array_1d<double, 3>& planeNormal,
1445  Point& ToPoint)
1446  {
1447  // calculate vector pointing from a node in the plane (e.g. triangle point 1) to the considered node ToPoint
1448  array_1d<double,3> planeToPointVec = ToPoint - planeBasePoint;
1449 
1450  // projection of node on the plane
1451  const double sn = inner_prod(planeToPointVec,planeNormal);
1452  const double sd = inner_prod(planeNormal,planeNormal);
1453  double DistanceToPlane = sn / sqrt(sd);
1454 
1455  if( fabs(DistanceToPlane) < epsilon )
1456  DistanceToPlane = 0;
1457 
1458  return DistanceToPlane;
1459  }
1460 
1463 
1465  {
1466  // loop over all fluid Elements
1467  for( ModelPart::ElementIterator i_fluid_Element = mrFluidModelPart.ElementsBegin();
1468  i_fluid_Element != mrFluidModelPart.ElementsEnd();
1469  i_fluid_Element++)
1470  {
1471  Geometry< Node >& geom = i_fluid_Element->GetGeometry();
1472  const Vector& ElementalDistances = i_fluid_Element->GetValue(ELEMENTAL_DISTANCES);
1473 
1474  // Assign distances to the single nodes, if a smaller value is found
1475  for( unsigned int i_TetNode = 0; i_TetNode < 4; i_TetNode++ )
1476  {
1477  double currentNodeDist = geom[i_TetNode].GetSolutionStepValue(DISTANCE);
1478  double nodeInElemDist = ElementalDistances[i_TetNode];
1479 
1480  if( fabs( nodeInElemDist ) < fabs( currentNodeDist ) )
1481  geom[i_TetNode].GetSolutionStepValue(DISTANCE) = nodeInElemDist; // overwrite nodal distance (which is global)
1482  } // loop i_TetNode
1483  } // loop i_fluidElement
1484  }
1485 
1488 
1497  array_1d<double,4>& ElementalDistances)
1498  {
1499  // Assign a distance limit
1500  double dist_limit = 1e-5;
1501 // bool distChangedToLimit = false; //variable to indicate that a distance value < tolerance is set to a limit distance = tolerance
1502 //
1503 // for(unsigned int i_node = 0; i_node < 4; i_node++)
1504 // {
1505 // if(fabs(ElementalDistances[i_node]) < dist_limit)
1506 // {
1507 // ElementalDistances[i_node] = dist_limit;
1508 // distChangedToLimit = true;
1509 // }
1510 // }
1511 //
1512 // // Check, if this approach changes the split-flag (might be, that Element is not cut anymore if node with zero distance gets a positive limit distance value
1513 // unsigned int numberNodesPositiveDistance = 0;
1514 // for(unsigned int i_node = 0; i_node < 4; i_node++)
1515 // {
1516 // if((ElementalDistances[i_node]) > 0)
1517 // numberNodesPositiveDistance++;
1518 // }
1519 
1520  for(unsigned int i_node = 0; i_node < 4; i_node++)
1521  {
1522  double & di = ElementalDistances[i_node];
1523  if(fabs(di) < dist_limit)
1524  {
1525  if(di >= 0) di = dist_limit;
1526  else di = -dist_limit;
1527  }
1528  }
1529 
1530  // Element is not set
1531 // if(numberNodesPositiveDistance == 4 && distChangedToLimit == true)
1532 // Element->GetValue(SPLIT_ELEMENT) = false;
1533  }
1534 
1537 
1538  void GenerateSkinModelPart( ModelPart& mrNewSkinModelPart )
1539  {
1540  unsigned int id_node = mrFluidModelPart.NumberOfNodes() + 1;
1541  unsigned int id_condition = mrFluidModelPart.NumberOfConditions() + 1;
1542 
1543  mrNewSkinModelPart.Nodes().reserve(mrFluidModelPart.Nodes().size());
1544  mrNewSkinModelPart.Conditions().reserve(mrFluidModelPart.Elements().size());
1545 
1546  for(ModelPart::ElementIterator i_fluid_element = mrFluidModelPart.ElementsBegin();
1547  i_fluid_element != mrFluidModelPart.ElementsEnd();
1548  i_fluid_element++)
1549  {
1550  bool is_split = i_fluid_element->Is(TO_SPLIT);
1551  if(is_split == true)
1552  {
1553  const Vector& distances = i_fluid_element->GetValue(ELEMENTAL_DISTANCES);
1554  Geometry< Node >& geom = i_fluid_element->GetGeometry();
1555 
1556  // generate the points on the edges at the zero of the distance function
1557  std::vector< Point > edge_points;
1558  edge_points.reserve(4);
1559 
1560  // loop over all 6 edges of the tetrahedra
1561  for(unsigned int i=0; i<3; i++)
1562  {
1563  for(unsigned int j=i+1; j<4; j++) // go through the edges 01, 02, 03, 12, 13, 23
1564  {
1565  double di = distances[i];
1566  double dj = distances[j];
1567 
1568  if(di*dj < 0) //edge is cut
1569  {
1570  // generate point on edge by linear interpolation
1571  double Ni = fabs(dj) / ( fabs(di) + fabs(dj) );
1572  double Nj = 1.0 - Ni;
1573  Point edge_point(Ni * geom[i] + Nj * geom[j]);
1574  edge_points.push_back(edge_point);
1575  }
1576  }
1577  }
1578 
1579  // three intersection nodes
1580  if(edge_points.size() == 3)
1581  {
1582  // ######## ADDING NEW NODE #########
1583  Node::Pointer pnode1 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[0].X(),edge_points[0].Y(),edge_points[0].Z());
1584  Node::Pointer pnode2 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[1].X(),edge_points[1].Y(),edge_points[1].Z());
1585  Node::Pointer pnode3 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[2].X(),edge_points[2].Y(),edge_points[2].Z());
1586 
1587  // ######## ADDING NEW CONDITION #########
1588  //form a triangle
1589  Triangle3D3< Node > triangle(pnode1, pnode2, pnode3);
1590 
1591  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D");
1592  Properties::Pointer properties = mrNewSkinModelPart.rProperties()(0);
1593  Condition::Pointer p_condition = rReferenceCondition.Create(id_condition++, triangle, properties);
1594 
1595  mrNewSkinModelPart.Conditions().push_back(p_condition);
1596  }
1597 
1598  // four intersection nodes
1599  if(edge_points.size() == 4)
1600  {
1601  //form a quadrilatera with the 4 cut nodes
1602  array_1d<double,3> x21 = edge_points[1] - edge_points[0];
1603  array_1d<double,3> x31 = edge_points[2] - edge_points[0];
1604  array_1d<double,3> x41 = edge_points[3] - edge_points[0];
1605 
1606  //define a vector oriented as x21
1607  array_1d<double,3> v1 = x21 / norm_2(x21);
1608 
1610  array_1d<double,4> msN;
1611  double Area;
1612  GeometryUtils::CalculateGeometryData( geom, DN_DX, msN, Area );
1613 
1614  array_1d<double,3> n = prod(trans(DN_DX),distances);
1615  n /= norm_2(n);
1616 
1617  array_1d<double,3> v2;
1618  MathUtils<double>::CrossProduct(v2,v1,n); // v2 = v1 x n
1619 
1620  array_1d<double,3> angles;
1621  angles[0] = 0.0; //angle between x21 and v1
1622  angles[1] = atan2( inner_prod(x31,v2), inner_prod(x31,v1) ); //angle between x31 and v1
1623  angles[2] = atan2( inner_prod(x41,v2), inner_prod(x41,v1) ); //angle between x31 and v1
1624 
1625  double max_angle = 0.0;
1626  double min_angle = 0.0;
1627  unsigned int min_pos = 1;
1628  unsigned int max_pos = 1;
1629  for(unsigned int i=1; i<3; i++)
1630  {
1631  if(angles[i] < min_angle)
1632  {
1633  min_pos = i+1; //this is the local index of the edge point which forms the minimal angle
1634  min_angle = angles[i];
1635  }
1636  else if(angles[i] > max_angle)
1637  {
1638  max_pos = i+1; //this is the local index of the edge point which forms the maximal angle
1639  max_angle = angles[i];
1640  }
1641  }
1642 
1643  //find the pos of the center node
1644  unsigned int center_pos = 0;
1645  for(unsigned int i=1; i<4; i++)
1646  {
1647  if((i!= min_pos) && (i!=max_pos))
1648  { center_pos = i; }
1649  }
1650 
1651  // ######## ADDING NEW NODE #########
1652  Node::Pointer pnode1 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[0].X(),edge_points[0].Y(),edge_points[0].Z());
1653  Node::Pointer pnode2 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[min_pos].X(),edge_points[min_pos].Y(),edge_points[min_pos].Z());
1654  Node::Pointer pnode3 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[center_pos].X(),edge_points[center_pos].Y(),edge_points[center_pos].Z());
1655  Node::Pointer pnode4 = mrNewSkinModelPart.CreateNewNode(id_node++,edge_points[max_pos].X(),edge_points[max_pos].Y(),edge_points[max_pos].Z());
1656 
1657  // ######## ADDING NEW CONDITION #########
1658  //form two triangles
1659  Triangle3D3< Node > triangle1(pnode1, pnode2, pnode3);
1660  Triangle3D3< Node > triangle2(pnode1, pnode3, pnode4);
1661 
1662  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D");
1663 
1664  Properties::Pointer properties = mrNewSkinModelPart.rProperties()(0);
1665 
1666  Condition::Pointer p_condition1 = rReferenceCondition.Create(id_condition++, triangle1, properties);
1667  Condition::Pointer p_condition2 = rReferenceCondition.Create(id_condition++, triangle2, properties);
1668 
1669  mrNewSkinModelPart.Conditions().push_back(p_condition1);
1670  mrNewSkinModelPart.Conditions().push_back(p_condition2);
1671 
1672  }
1673 
1674  }
1675  }
1676 
1677  }
1678 
1681 
1683  {
1684  Timer::Start("Generating Octree");
1685  //std::cout << "Generating the Octree..." << std::endl;
1686  auto temp_octree = Kratos::make_shared<OctreeType>();
1687  //OctreeType::Pointer temp_octree = OctreeType::Pointer(new OctreeType() );
1688  mpOctree.swap(temp_octree);
1689 
1690  double low[3];
1691  double high[3];
1692 
1693  for (int i = 0 ; i < 3; i++)
1694  {
1695  low[i] = high[i] = mrFluidModelPart.NodesBegin()->Coordinates()[i];
1696  }
1697 
1698  // loop over all nodes in the bounding box
1699  for(ModelPart::NodeIterator i_node = mrFluidModelPart.NodesBegin();
1700  i_node != mrFluidModelPart.NodesEnd();
1701  i_node++)
1702  {
1703  const array_1d<double,3>& r_coordinates = i_node->Coordinates();
1704  for (int i = 0 ; i < 3; i++)
1705  {
1706  low[i] = r_coordinates[i] < low[i] ? r_coordinates[i] : low[i];
1707  high[i] = r_coordinates[i] > high[i] ? r_coordinates[i] : high[i];
1708  }
1709  }
1710 
1711  // loop over all skin nodes
1712  for(ModelPart::NodeIterator i_node = mrSkinModelPart.NodesBegin();
1713  i_node != mrSkinModelPart.NodesEnd();
1714  i_node++)
1715  {
1716  const array_1d<double,3>& r_coordinates = i_node->Coordinates();
1717  for (int i = 0 ; i < 3; i++)
1718  {
1719  low[i] = r_coordinates[i] < low[i] ? r_coordinates[i] : low[i];
1720  high[i] = r_coordinates[i] > high[i] ? r_coordinates[i] : high[i];
1721  }
1722  }
1723 
1724  mpOctree->SetBoundingBox(low,high);
1725 
1726  //mpOctree->RefineWithUniformSize(0.0625);
1727 
1728  // loop over all structure nodes
1729  for(ModelPart::NodeIterator i_node = mrSkinModelPart.NodesBegin();
1730  i_node != mrSkinModelPart.NodesEnd();
1731  i_node++)
1732  {
1733  double temp_point[3];
1734  temp_point[0] = i_node->X();
1735  temp_point[1] = i_node->Y();
1736  temp_point[2] = i_node->Z();
1737  mpOctree->Insert(temp_point);
1738  }
1739 
1740  //mpOctree->Constrain2To1(); // To be removed. Pooyan.
1741 
1742  // loop over all structure elements
1743  for(ModelPart::ElementIterator i_element = mrSkinModelPart.ElementsBegin();
1744  i_element != mrSkinModelPart.ElementsEnd();
1745  i_element++)
1746  {
1747  mpOctree->Insert(*(i_element).base());
1748  }
1749 
1750  Timer::Stop("Generating Octree");
1751 
1752 // KRATOS_WATCH(mpOctree);
1753 
1754 // std::cout << "######## WRITING OCTREE MESH #########" << std::endl;
1755 // std::ofstream myfile;
1756 // myfile.open ("octree.post.msh");
1757 // mpOctree.PrintGiDMesh(myfile);
1758 // myfile.close();
1759 
1760  //std::cout << "Generating the Octree finished" << std::endl;
1761  }
1762 
1765 
1767  {
1768  Timer::Start("Generating Nodes");
1769  std::vector<OctreeType::cell_type*> all_leaves;
1770  mpOctree->GetAllLeavesVector(all_leaves);
1771 
1772  int leaves_size = all_leaves.size();
1773 
1774 #pragma omp parallel for
1775  for (int i = 0; i < leaves_size; i++)
1776  {
1777  *(all_leaves[i]->pGetDataPointer()) = ConfigurationType::AllocateData();
1778  }
1779 
1780 
1781  std::size_t last_id = mrBodyModelPart.NumberOfNodes() + 1;
1782 
1783  for (std::size_t i = 0; i < all_leaves.size(); i++)
1784  {
1785  CellType* cell = all_leaves[i];
1786  GenerateCellNode(cell, last_id);
1787  }
1788 
1789  Timer::Stop("Generating Nodes");
1790 
1791  }
1792 
1795 
1796  void GenerateCellNode(CellType* pCell, std::size_t& LastId)
1797  {
1798  for (int i_pos=0; i_pos < 8; i_pos++) // position 8 is for center
1799  {
1801  if(p_node == 0)
1802  {
1804 
1805  (*(pCell->pGetData()))[i_pos]->Id() = LastId++;
1806 
1807  mOctreeNodes.push_back((*(pCell->pGetData()))[i_pos]);
1808 
1809  SetNodeInNeighbours(pCell,i_pos,(*(pCell->pGetData()))[i_pos]);
1810  }
1811 
1812  }
1813  }
1814 
1817 
1818  void SetNodeInNeighbours(CellType* pCell, int Position, CellNodeDataType* pNode)
1819  {
1820  CellType::key_type point_key[3];
1821  pCell->GetKey(Position, point_key);
1822 
1823  for (std::size_t i_direction = 0; i_direction < 8; i_direction++) {
1824  CellType::key_type neighbour_key[3];
1825  if (pCell->GetNeighbourKey(Position, i_direction, neighbour_key)) {
1826  CellType* neighbour_cell = mpOctree->pGetCell(neighbour_key);
1827  if (!neighbour_cell || (neighbour_cell == pCell))
1828  continue;
1829 
1830  std::size_t position = neighbour_cell->GetLocalPosition(point_key);
1831  if((*neighbour_cell->pGetData())[position])
1832  {
1833  std::cout << "ERROR!! Bad Position calculated!!!!!!!!!!! position :" << position << std::endl;
1834  continue;
1835  }
1836 
1837  (*neighbour_cell->pGetData())[position] = pNode;
1838  }
1839  }
1840  }
1841 
1844 
1846  {
1847  Timer::Start("Calculate Distances2");
1848  ModelPart::NodesContainerType::ContainerType& nodes = mrFluidModelPart.NodesArray();
1849  int nodes_size = nodes.size();
1850  // // first of all we reset the node distance to 1.00 which is the maximum distnace in our normalized space.
1851  //#pragma omp parallel for firstprivate(nodes_size)
1852  // for(int i = 0 ; i < nodes_size ; i++)
1853  // nodes[i]->GetSolutionStepValue(DISTANCE) = 1.00;
1854 
1855  std::vector<CellType*> leaves;
1856 
1857  mpOctree->GetAllLeavesVector(leaves);
1858  //int leaves_size = leaves.size();
1859 
1860  // for(int i = 0 ; i < leaves_size ; i++)
1861  // CalculateNotEmptyLeavesDistance(leaves[i]);
1862 
1863 #pragma omp parallel for firstprivate(nodes_size)
1864  for(int i = 0 ; i < nodes_size ; i++)
1865  {
1866  CalculateNodeDistance(*(nodes[i]));
1867  }
1868  Timer::Stop("Calculate Distances2");
1869 
1870  }
1871 
1874 
1875  // void CalculateDistance3()
1876  // {
1877  // Timer::Start("Calculate Distances2");
1878  // ModelPart::NodesContainerType::ContainerType& nodes = mrFluidModelPart.NodesArray();
1879  // int nodes_size = nodes.size();
1881  //#pragma omp parallel for firstprivate(nodes_size)
1882  // for(int i = 0 ; i < nodes_size ; i++)
1883  // nodes[i]->GetSolutionStepValue(DISTANCE) = 1.00;
1884 
1885  // std::vector<CellType*> leaves;
1886 
1887  // mpOctree->GetAllLeavesVector(leaves);
1888  // int leaves_size = leaves.size();
1889 
1890  // for(int i = 0 ; i < leaves_size ; i++)
1891  // CalculateNotEmptyLeavesDistance(leaves[i]);
1892 
1893  //#pragma omp parallel for firstprivate(nodes_size)
1894  // for(int i = 0 ; i < nodes_size ; i++)
1895  // {
1896  // CalculateNodeDistance(*(nodes[i]));
1897  // }
1898  // Timer::Stop("Calculate Distances2");
1899 
1900  // }
1901  // void CalculateDistance4()
1902  // {
1903  // Timer::Start("Calculate Distances3");
1904  // ModelPart::NodesContainerType::ContainerType& nodes = mrFluidModelPart.NodesArray();
1905  // int nodes_size = nodes.size();
1906  // std::vector<CellType*> leaves;
1907 
1908  // mpOctree->GetAllLeavesVector(leaves);
1909  // int leaves_size = leaves.size();
1910 
1911  //#pragma omp parallel for firstprivate(nodes_size)
1912  // for(int i = 0 ; i < nodes_size ; i++)
1913  // {
1914  // CalculateNodeDistanceFromCell(*(nodes[i]));
1915  // }
1916  // Timer::Stop("Calculate Distances3");
1917 
1918  // }
1919 
1921  {
1922  Timer::Start("Calculate Distances");
1923  DistanceSpatialContainersConfigure::data_type& nodes = mOctreeNodes;
1924  int nodes_size = nodes.size();
1925  // first of all we reste the node distance to 1.00 which is the maximum distnace in our normalized space.
1926 #pragma omp parallel for firstprivate(nodes_size)
1927  for(int i = 0 ; i < nodes_size ; i++)
1928  nodes[i]->Distance() = 1.00;
1929 
1930 
1931  std::vector<CellType*> leaves;
1932 
1933  mpOctree->GetAllLeavesVector(leaves);
1934  int leaves_size = leaves.size();
1935 
1936  for(int i = 0 ; i < leaves_size ; i++)
1937  CalculateNotEmptyLeavesDistance(leaves[i]);
1938 
1939  for(int i_direction = 0 ; i_direction < 1 ; i_direction++)
1940  {
1941 
1942  //#pragma omp parallel for firstprivate(nodes_size)
1943  for(int i = 0 ; i < nodes_size ; i++)
1944  {
1945  if(nodes[i]->X() < 1.00 && nodes[i]->Y() < 1.00 && nodes[i]->Z() < 1.00)
1946  // if((*nodes[i])[i_direction] == 0.00)
1947  CalculateDistance(*(nodes[i]), i_direction);
1948  }
1949  }
1950  Timer::Stop("Calculate Distances");
1951 
1952  }
1953 
1954  void CalculateDistance(CellNodeDataType& rNode, int i_direction)
1955  {
1956  double coords[3] = {rNode.X(), rNode.Y(), rNode.Z()};
1957  // KRATOS_WATCH_3(coords);
1958 
1959  //This function must color the positions in space defined by 'coords'.
1960  //coords is of dimension (3) normalized in (0,1)^3 space
1961 
1962  typedef Element::GeometryType triangle_type;
1963  typedef std::vector<std::pair<double, triangle_type*> > intersections_container_type;
1964 
1965  intersections_container_type intersections;
1967 
1968 
1969  const double epsilon = 1e-12;
1970 
1971  double distance = 1.0;
1972 
1973  // Creating the ray
1974  double ray[3] = {coords[0], coords[1], coords[2]};
1975 
1976  mpOctree->NormalizeCoordinates(ray);
1977  ray[i_direction] = 0; // starting from the lower extreme
1978 
1979  // KRATOS_WATCH_3(ray)
1980  GetIntersectionsAndNodes(ray, i_direction, intersections, nodes_array);
1981  // KRATOS_WATCH(nodes_array.size())
1982  for (std::size_t i_node = 0; i_node < nodes_array.size() ; i_node++)
1983  {
1984  double coord = (*nodes_array[i_node])[i_direction];
1985  // KRATOS_WATCH(intersections.size());
1986 
1987  int ray_color= 1;
1988  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_intersection = intersections.begin();
1989  while (i_intersection != intersections.end()) {
1990  double d = coord - i_intersection->first;
1991  if (d > epsilon) {
1992 
1993  ray_color = -ray_color;
1994  distance = d;
1995  } else if (d > -epsilon) {//interface
1996  distance = 0.00;
1997  break;
1998  } else {
1999  if(distance > -d)
2000  distance = -d;
2001  break;
2002  }
2003 
2004  i_intersection++;
2005  }
2006 
2007  distance *= ray_color;
2008 
2009  double& node_distance = nodes_array[i_node]->Distance();
2010  if(fabs(distance) < fabs(node_distance))
2011  node_distance = distance;
2012  else if (distance*node_distance < 0.00) // assigning the correct sign
2013  node_distance = -node_distance;
2014 
2015 
2016  }
2017  }
2018 
2020  {
2021  //typedef Element::GeometryType triangle_type;
2022  typedef OctreeType::cell_type::object_container_type object_container_type;
2023 
2024  object_container_type* objects = (pCell->pGetObjects());
2025 
2026  // There are no intersection in empty cells
2027  if (objects->empty())
2028  return;
2029 
2030 
2031  for (int i_pos=0; i_pos < 8; i_pos++) // position 8 is for center
2032  {
2033  double distance = 1.00; // maximum distance is 1.00
2034 
2035  for(object_container_type::iterator i_object = objects->begin(); i_object != objects->end(); i_object++)
2036  {
2038  pCell->GetKey(i_pos,keys);
2039 
2040  double cell_point[3];
2041  mpOctree->CalculateCoordinates(keys,cell_point);
2042 
2043  double d = GeometryUtils::PointDistanceToTriangle3D((*i_object)->GetGeometry()[0], (*i_object)->GetGeometry()[1], (*i_object)->GetGeometry()[2], Point(cell_point[0], cell_point[1], cell_point[2]));
2044 
2045  if(d < distance)
2046  distance = d;
2047  }
2048 
2049  double& node_distance = (*(pCell->pGetData()))[i_pos]->Distance();
2050  if(distance < node_distance)
2051  node_distance = distance;
2052 
2053  }
2054 
2055  }
2056 
2058  {
2059  double coord[3] = {rNode.X(), rNode.Y(), rNode.Z()};
2060  double distance = DistancePositionInSpace(coord);
2061  double& node_distance = rNode.GetSolutionStepValue(DISTANCE);
2062 
2063  //const double epsilon = 1.00e-12;
2064  //if(fabs(node_distance) > fabs(distance))
2065  // node_distance = distance;
2066  /*else*/ if (distance*node_distance < 0.00) // assigning the correct sign
2067  node_distance = -node_distance;
2068  }
2069 
2070  // void CalculateNodeDistanceFromCell(Node& rNode)
2071  // {
2072  // OctreeType::key_type node_key[3] = {octree->CalcKeyNormalized(rNode.X()), octree->CalcKeyNormalized(rNode.Y()), octree->CalcKeyNormalized(rNode.Z())};
2073  // OctreeType::cell_type* pcell = octree->pGetCell(node_key);
2074 
2075  // object_container_type* objects = (pCell->pGetObjects());
2076 
2077  // // We interpolate the cell distances for the node in empty cells
2078  // if (objects->empty())
2079  // {
2080 
2081  // }
2082 
2083  // double distance = DistancePositionInSpace(coord);
2084  // double& node_distance = rNode.GetSolutionStepValue(DISTANCE);
2085 
2086  // //const double epsilon = 1.00e-12;
2087  // if(fabs(node_distance) > fabs(distance))
2088  // node_distance = distance;
2089  // else if (distance*node_distance < 0.00) // assigning the correct sign
2090  // node_distance = -node_distance;
2091  // }
2092 
2093  double DistancePositionInSpace(double* coords)
2094  {
2095  //This function must color the positions in space defined by 'coords'.
2096  //coords is of dimension (3) normalized in (0,1)^3 space
2097 
2098  typedef Element::GeometryType triangle_type;
2099  typedef std::vector<std::pair<double, triangle_type*> > intersections_container_type;
2100 
2101  intersections_container_type intersections;
2102 
2103  const int dimension = 3;
2104  const double epsilon = 1e-12;
2105 
2106  double distances[3] = {1.0, 1.0, 1.0};
2107 
2108  for (int i_direction = 0; i_direction < dimension; i_direction++)
2109  {
2110  // Creating the ray
2111  double ray[3] = {coords[0], coords[1], coords[2]};
2112 
2113  mpOctree->NormalizeCoordinates(ray);
2114  ray[i_direction] = 0; // starting from the lower extreme
2115 
2116  GetIntersections(ray, i_direction, intersections);
2117 
2118  // if(intersections.size() == 1)
2119  // KRATOS_WATCH_3(ray)
2120 
2121  // KRATOS_WATCH(intersections.size());
2122 
2123  int ray_color= 1;
2124  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_intersection = intersections.begin();
2125  while (i_intersection != intersections.end()) {
2126  double d = coords[i_direction] - i_intersection->first;
2127  if (d > epsilon) {
2128 
2129  ray_color = -ray_color;
2130  distances[i_direction] = d;
2131  // if(distances[i_direction] > d) // I think this is redundunt. Pooyan.
2132  // {
2133  // if(ray_color > 0.00)
2134  // distances[i_direction] = d;
2135  // else
2136  // distances[i_direction] = -d;
2137  // }
2138  } else if (d > -epsilon) {//interface
2139  distances[i_direction] = 0.00;
2140  break;
2141  } else {
2142  if(distances[i_direction] > -d)
2143  distances[i_direction] = -d;
2144  break;
2145  }
2146 
2147  i_intersection++;
2148  }
2149 
2150  distances[i_direction] *= ray_color;
2151  }
2152 
2153  // if(distances[0]*distances[1] < 0.00 || distances[2]*distances[1] < 0.00)
2154  // KRATOS_WATCH_3(distances);
2155 
2156 //#ifdef _DEBUG
2157 // std::cout << "colors : " << colors[0] << ", " << colors[1] << ", " << colors[2] << std::endl;
2158 //#endif
2159  double distance = (fabs(distances[0]) > fabs(distances[1])) ? distances[1] : distances[0];
2160  distance = (fabs(distance) > fabs(distances[2])) ? distances[2] : distance;
2161 
2162  return distance;
2163 
2164  }
2165 
2166  void GetIntersectionsAndNodes(double* ray, int direction, std::vector<std::pair<double,Element::GeometryType*> >& intersections, DistanceSpatialContainersConfigure::data_type& rNodesArray)
2167  {
2168  //This function passes the ray through the model and gives the hit point to all objects in its way
2169  //ray is of dimension (3) normalized in (0,1)^3 space
2170  // direction can be 0,1,2 which are x,y and z respectively
2171 
2172  const double epsilon = 1.00e-12;
2173 
2174  // first clearing the intersections points vector
2175  intersections.clear();
2176 
2177  //OctreeType* octree = &mOctree;
2178  OctreeType* octree = mpOctree.get();
2179 
2180  OctreeType::key_type ray_key[3] = {octree->CalcKeyNormalized(ray[0]), octree->CalcKeyNormalized(ray[1]), octree->CalcKeyNormalized(ray[2])};
2181  OctreeType::key_type cell_key[3];
2182 
2183  // getting the entrance cell from lower extreme
2184  ray_key[direction] = 0;
2185  OctreeType::cell_type* cell = octree->pGetCell(ray_key);
2186 
2187  while (cell) {
2188  std::size_t position = cell->GetLocalPosition(ray_key); // Is this the local position!?!?!?!
2189  OctreeType::key_type node_key[3];
2190  cell->GetKey(position, node_key);
2191  if((node_key[0] == ray_key[0]) && (node_key[1] == ray_key[1]) && (node_key[2] == ray_key[2]))
2192  {
2193  if(cell->pGetData())
2194  {
2195  if(cell->pGetData()->size() > position)
2196  {
2197  CellNodeDataType* p_node = (*cell->pGetData())[position];
2198  if(p_node)
2199  {
2200  //KRATOS_WATCH(p_node->Id())
2201  rNodesArray.push_back(p_node);
2202  }
2203  }
2204  else
2205  KRATOS_WATCH(cell->pGetData()->size())
2206  }
2207  }
2208 
2209 
2210  // std::cout << ".";
2211  GetCellIntersections(cell, ray, ray_key, direction, intersections);
2212 
2213  // Add the cell's middle node if existed
2214  // cell->GetKey(8, cell_key); // 8 is the central position
2215  // ray_key[direction]=cell_key[direction]; // positioning the ray in the middle of cell in its direction
2216 
2217  // position = cell->GetLocalPosition(ray_key);
2218  // if(position < 27) // principal nodes
2219  // {
2220  // if(cell->pGetData())
2221  // {
2222  // if(cell->pGetData()->size() > position)
2223  // {
2224  // Node* p_node = (*cell->pGetData())[position];
2225  // if(p_node)
2226  // {
2227  // //KRATOS_WATCH(p_node->Id())
2228  // rNodesArray.push_back(p_node);
2229  // }
2230  // }
2231  // else
2232  // KRATOS_WATCH(cell->pGetData()->size())
2233  // }
2234  // }
2235  // else
2236  // {
2237  // KRATOS_WATCH(position);
2238  // KRATOS_WATCH(*cell);
2239  // }
2240 
2241 
2242  // go to the next cell
2243  if (cell->GetNeighbourKey(1 + direction * 2, cell_key)) {
2244  ray_key[direction] = cell_key[direction];
2245  cell = octree->pGetCell(ray_key);
2246  ray_key[direction] -= 1 ;//the key returned by GetNeighbourKey is inside the cell (minkey +1), to ensure that the corresponding
2247  //cell get in pGetCell is the right one.
2248 //#ifdef _DEBUG
2249 // Octree_Pooyan::key_type min_key[3];
2250 // cell->GetMinKey(min_key[0],min_key[1],min_key[2]);
2251 // Octree_Pooyan::key_type tmp;
2252 // tmp= min_key[direction];
2253 // assert(ray_key[direction]==tmp);
2254 //#endif
2255  } else
2256  cell = NULL;
2257  }
2258 
2259 
2260 
2261  // KRATOS_WATCH(rNodesArray.size());
2262  // now eliminating the repeated objects
2263  if (!intersections.empty()) {
2264  //sort
2265  std::sort(intersections.begin(), intersections.end());
2266  // unique
2267  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_begin = intersections.begin();
2268  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_intersection = intersections.begin();
2269  while (++i_begin != intersections.end()) {
2270  // considering the very near points as the same points
2271  if (fabs(i_begin->first - i_intersection->first) > epsilon) // if the hit points are far enough they are not the same
2272  *(++i_intersection) = *i_begin;
2273  }
2274  intersections.resize((++i_intersection) - intersections.begin());
2275 
2276  }
2277  }
2278 
2279  void GetIntersections(double* ray, int direction, std::vector<std::pair<double,Element::GeometryType*> >& intersections)
2280  {
2281  //This function passes the ray through the model and gives the hit point to all objects in its way
2282  //ray is of dimension (3) normalized in (0,1)^3 space
2283  // direction can be 0,1,2 which are x,y and z respectively
2284 
2285  const double epsilon = 1.00e-12;
2286 
2287  // first clearing the intersections points vector
2288  intersections.clear();
2289 
2290  //OctreeType* octree = &mOctree;
2291  OctreeType* octree = mpOctree.get();
2292 
2293  OctreeType::key_type ray_key[3] = {octree->CalcKeyNormalized(ray[0]), octree->CalcKeyNormalized(ray[1]), octree->CalcKeyNormalized(ray[2])};
2294  OctreeType::key_type cell_key[3];
2295 
2296  // getting the entrance cell from lower extreme
2297  OctreeType::cell_type* cell = octree->pGetCell(ray_key);
2298 
2299  while (cell) {
2300  // std::cout << ".";
2301  GetCellIntersections(cell, ray, ray_key, direction, intersections);
2302  // go to the next cell
2303  if (cell->GetNeighbourKey(1 + direction * 2, cell_key)) {
2304  ray_key[direction] = cell_key[direction];
2305  cell = octree->pGetCell(ray_key);
2306  ray_key[direction] -= 1 ;//the key returned by GetNeighbourKey is inside the cell (minkey +1), to ensure that the corresponding
2307  //cell get in pGetCell is the right one.
2308 //#ifdef _DEBUG
2309 // Octree_Pooyan::key_type min_key[3];
2310 // cell->GetMinKey(min_key[0],min_key[1],min_key[2]);
2311 // Octree_Pooyan::key_type tmp;
2312 // tmp= min_key[direction];
2313 // assert(ray_key[direction]==tmp);
2314 //#endif
2315  } else
2316  cell = NULL;
2317  }
2318 
2319 
2320  // now eliminating the repeated objects
2321  if (!intersections.empty()) {
2322  //sort
2323  std::sort(intersections.begin(), intersections.end());
2324  // unique
2325  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_begin = intersections.begin();
2326  std::vector<std::pair<double, Element::GeometryType*> >::iterator i_intersection = intersections.begin();
2327  while (++i_begin != intersections.end()) {
2328  // considering the very near points as the same points
2329  if (fabs(i_begin->first - i_intersection->first) > epsilon) // if the hit points are far enough they are not the same
2330  *(++i_intersection) = *i_begin;
2331  }
2332  intersections.resize((++i_intersection) - intersections.begin());
2333 
2334  }
2335  }
2336 
2338  OctreeType::key_type* ray_key, int direction,
2339  std::vector<std::pair<double, Element::GeometryType*> >& intersections) {
2340  //This function passes the ray through the cell and gives the hit point to all objects in its way
2341  //ray is of dimension (3) normalized in (0,1)^3 space
2342  // direction can be 0,1,2 which are x,y and z respectively
2343 
2344  //typedef Element::GeometryType triangle_type;
2345  typedef OctreeType::cell_type::object_container_type object_container_type;
2346 
2347  object_container_type* objects = (cell->pGetObjects());
2348 
2349  // There are no intersection in empty cells
2350  if (objects->empty())
2351  return 0;
2352 
2353  // std::cout << "X";
2354  // calculating the two extreme of the ray segment inside the cell
2355  double ray_point1[3] = {ray[0], ray[1], ray[2]};
2356  double ray_point2[3] = {ray[0], ray[1], ray[2]};
2357  double normalized_coordinate;
2358  mpOctree->CalculateCoordinateNormalized(ray_key[direction], normalized_coordinate);
2359  ray_point1[direction] = normalized_coordinate;
2360  ray_point2[direction] = ray_point1[direction] + mpOctree->CalcSizeNormalized(cell);
2361 
2362  mpOctree->ScaleBackToOriginalCoordinate(ray_point1);
2363  mpOctree->ScaleBackToOriginalCoordinate(ray_point2);
2364 
2365  for (object_container_type::iterator i_object = objects->begin(); i_object != objects->end(); i_object++) {
2366  double intersection[3]={0.00,0.00,0.00};
2367 
2368  int is_intersected = IntersectionTriangleSegment((*i_object)->GetGeometry(), ray_point1, ray_point2, intersection); // This intersection has to be optimized for axis aligned rays
2369 
2370  if (is_intersected == 1) // There is an intersection but not coplanar
2371  intersections.push_back(std::pair<double, Element::GeometryType*>(intersection[direction], &((*i_object)->GetGeometry())));
2372  //else if(is_intersected == 2) // coplanar case
2373  }
2374 
2375  return 0;
2376  }
2377 
2378  int IntersectionTriangleSegment(Element::GeometryType& rGeometry, double* RayPoint1, double* RayPoint2, double* IntersectionPoint)
2379  {
2380  // This is the adaption of the implemnetation provided in:
2381  // http://www.softsurfer.com/Archive/algorithm_0105/algorithm_0105.htm#intersect_RayTriangle()
2382 
2383  const double epsilon = 1.00e-12;
2384 
2385  array_1d<double,3> u, v, n; // triangle vectors
2386  array_1d<double,3> dir, w0, w; // ray vectors
2387  double r, a, b; // params to calc ray-plane intersect
2388 
2389 
2390  // get triangle edge vectors and plane normal
2391  u = rGeometry[1] - rGeometry[0];
2392  v = rGeometry[2] - rGeometry[0];
2393 
2394  MathUtils<double>::CrossProduct(n, u, v); // cross product
2395 
2396  if (norm_2(n) == 0) // triangle is degenerate
2397  return -1; // do not deal with this case
2398 
2399  double triangle_origin_distance = -inner_prod(n, rGeometry[0]);
2400  Point ray_point_1, ray_point_2;
2401 
2402  for(int i = 0 ; i < 3 ; i++)
2403  {
2404  dir[i] = RayPoint2[i] - RayPoint1[i]; // ray direction vector
2405  w0[i] = RayPoint1[i] - rGeometry[0][i];
2406  ray_point_1[i] = RayPoint1[i];
2407  ray_point_2[i] = RayPoint2[i];
2408  }
2409 
2410  double sign_distance_1 = inner_prod(n, ray_point_1) + triangle_origin_distance;
2411  double sign_distance_2 = inner_prod(n, ray_point_2) + triangle_origin_distance;
2412 
2413  if (sign_distance_1*sign_distance_2 > epsilon) // segment line point on the same side of plane
2414  return 0;
2415  a = -inner_prod(n,w0);
2416  b = inner_prod(n,dir);
2417 
2418  if (fabs(b) < epsilon) { // ray is parallel to triangle plane
2419  if (a == 0) // ray lies in triangle plane
2420  return 2;
2421  else return 0; // ray disjoint from plane
2422  }
2423 
2424  // get intersect point of ray with triangle plane
2425  r = a / b;
2426  if (r < 0.0) // ray goes away from triangle
2427  return 0; // => no intersect
2428  // for a segment, also test if (r > 1.0) => no intersect
2429 
2430  for(int i = 0 ; i < 3 ; i++)
2431  IntersectionPoint[i] = RayPoint1[i] + r * dir[i]; // intersect point of ray and plane
2432 
2433  // is I inside T?
2434  double uu, uv, vv, wu, wv, D;
2435  uu = inner_prod(u,u);
2436  uv = inner_prod(u,v);
2437  vv = inner_prod(v,v);
2438 
2439 
2440  for(int i = 0 ; i < 3 ; i++)
2441  w[i] = IntersectionPoint[i] - rGeometry[0][i];
2442 
2443 
2444  wu = inner_prod(w,u);
2445  wv = inner_prod(w,v);
2446  D = uv * uv - uu * vv;
2447 
2448  // get and test parametric coords
2449  double s, t;
2450  s = (uv * wv - vv * wu) / D;
2451  if (s < 0.0 - epsilon || s > 1.0 + epsilon) // I is outside T
2452  return 0;
2453  t = (uv * wu - uu * wv) / D;
2454  if (t < 0.0 - epsilon || (s + t) > 1.0 + epsilon) // I is outside T
2455  return 0;
2456 
2457  return 1; // I is in T
2458 
2459  }
2460 
2464 
2465 
2469 
2470 
2474 
2476  std::string Info() const override
2477  {
2478  return "CalculateSignedDistanceTo3DSkinProcess";
2479  }
2480 
2482  void PrintInfo(std::ostream& rOStream) const override
2483  {
2484  rOStream << "CalculateSignedDistanceTo3DSkinProcess";
2485  }
2486 
2488  void PrintData(std::ostream& rOStream) const override
2489  {
2490  }
2491 
2492  void PrintGiDMesh(std::ostream & rOStream) const {
2493  std::vector<CellType*> leaves;
2494 
2495  mpOctree->GetAllLeavesVector(leaves);
2496 
2497  std::cout << "writing " << leaves.size() << " leaves" << std::endl;
2498  rOStream << "MESH \"leaves\" dimension 3 ElemType Hexahedra Nnode 8" << std::endl;
2499  rOStream << "# color 96 96 96" << std::endl;
2500  rOStream << "Coordinates" << std::endl;
2501  rOStream << "# node number coordinate_x coordinate_y coordinate_z " << std::endl;
2502 
2503  for(DistanceSpatialContainersConfigure::data_type::const_iterator i_node = mOctreeNodes.begin() ; i_node != mOctreeNodes.end() ; i_node++)
2504  {
2505  rOStream << (*i_node)->Id() << " " << (*i_node)->X() << " " << (*i_node)->Y() << " " << (*i_node)->Z() << std::endl;
2506  //mpOctree->Insert(temp_point);
2507  }
2508  std::cout << "Nodes written..." << std::endl;
2509  rOStream << "end coordinates" << std::endl;
2510  rOStream << "Elements" << std::endl;
2511  rOStream << "# Element node_1 node_2 node_3 material_number" << std::endl;
2512 
2513  for (std::size_t i = 0; i < leaves.size(); i++) {
2514  if ((leaves[i]->pGetData()))
2515  {
2516  DistanceSpatialContainersConfigure::data_type& nodes = (*(leaves[i]->pGetData()));
2517 
2518  rOStream << i + 1;
2519  for(int j = 0 ; j < 8 ; j++)
2520  rOStream << " " << nodes[j]->Id();
2521  rOStream << std::endl;
2522  }
2523  }
2524  rOStream << "end Elements" << std::endl;
2525 
2526  }
2527 
2528  void PrintGiDResults(std::ostream & rOStream) const {
2529  std::vector<CellType*> leaves;
2530 
2531  mpOctree->GetAllLeavesVector(leaves);
2532 
2533  rOStream << "GiD Post Results File 1.0" << std::endl << std::endl;
2534 
2535  rOStream << "Result \"Distance\" \"Kratos\" 1 Scalar OnNodes" << std::endl;
2536 
2537  rOStream << "Values" << std::endl;
2538 
2539  for(DistanceSpatialContainersConfigure::data_type::const_iterator i_node = mOctreeNodes.begin() ; i_node != mOctreeNodes.end() ; i_node++)
2540  {
2541  rOStream << (*i_node)->Id() << " " << (*i_node)->Distance() << std::endl;
2542  }
2543  rOStream << "End Values" << std::endl;
2544 
2545  }
2546 
2550 
2551 
2553 
2554 protected:
2557 
2558 
2562 
2563 
2567 
2568 
2572 
2573 
2577 
2578 
2582 
2583 
2587 
2588 
2590 
2591 private:
2594 
2595 
2599  ModelPart& mrSkinModelPart;
2600  ModelPart& mrBodyModelPart;
2601  ModelPart& mrFluidModelPart;
2602 
2604 
2606 
2607  static const double epsilon;
2608 
2622  static inline void EigenVectors(const Matrix& A, Matrix& vectors, Vector& lambda, double zero_tolerance =1e-9, int max_iterations = 10)
2623  {
2624  Matrix Help= A;
2625 
2626  for(int i=0; i<3; i++)
2627  for(int j=0; j<3; j++)
2628  Help(i,j)= Help(i,j);
2629 
2630 
2631  vectors.resize(Help.size1(),Help.size2(),false);
2632 
2633  lambda.resize(Help.size1(),false);
2634 
2635  Matrix HelpDummy(Help.size1(),Help.size2());
2636 
2637  bool is_converged = false;
2638 
2639  Matrix unity=ZeroMatrix(Help.size1(),Help.size2());
2640 
2641  for(unsigned int i=0; i< Help.size1(); i++)
2642  unity(i,i)= 1.0;
2643 
2644  Matrix V= unity;
2645 
2646  Matrix VDummy(Help.size1(),Help.size2());
2647 
2648  Matrix Rotation(Help.size1(),Help.size2());
2649 
2650 
2651  for(int iterations=0; iterations<max_iterations; iterations++)
2652  {
2653 
2654  is_converged= true;
2655 
2656  double a= 0.0;
2657 
2658  unsigned int index1= 0;
2659 
2660  unsigned int index2= 1;
2661 
2662  for(unsigned int i=0; i< Help.size1(); i++)
2663  {
2664  for(unsigned int j=(i+1); j< Help.size2(); j++)
2665  {
2666  if((fabs(Help(i,j)) > a ) && (fabs(Help(i,j)) > zero_tolerance))
2667  {
2668  a= fabs(Help(i,j));
2669 
2670  index1= i;
2671  index2= j;
2672 
2673  is_converged= false;
2674  }
2675  }
2676  }
2677 
2678  // KRATOS_WATCH(Help);
2679 
2680  if(is_converged)
2681  break;
2682 
2683  //Calculation of Rotationangle
2684 
2685  double gamma= (Help(index2,index2)-Help(index1,index1))/(2*Help(index1,index2));
2686 
2687  double u=1.0;
2688 
2689  if(fabs(gamma) > zero_tolerance && fabs(gamma)< (1/zero_tolerance))
2690  {
2691  u= gamma/fabs(gamma)*1.0/(fabs(gamma)+sqrt(1.0+gamma*gamma));
2692  }
2693  else
2694  {
2695  if (fabs(gamma)>= (1.0/zero_tolerance))
2696  u= 0.5/gamma;
2697  }
2698 
2699  double c= 1.0/(sqrt(1.0+u*u));
2700 
2701  double s= c*u;
2702 
2703  double teta= s/(1.0+c);
2704 
2705  //Ratotion of the Matrix
2706  HelpDummy= Help;
2707 
2708  HelpDummy(index2,index2)= Help(index2,index2)+u*Help(index1,index2);
2709  HelpDummy(index1,index1)= Help(index1,index1)-u*Help(index1,index2);
2710  HelpDummy(index1,index2)= 0.0;
2711  HelpDummy(index2,index1)= 0.0;
2712 
2713  for(unsigned int i=0; i<Help.size1(); i++)
2714  {
2715  if((i!= index1) && (i!= index2))
2716  {
2717  HelpDummy(index2,i)=Help(index2,i)+s*(Help(index1,i)- teta*Help(index2,i));
2718  HelpDummy(i,index2)=Help(index2,i)+s*(Help(index1,i)- teta*Help(index2,i));
2719 
2720  HelpDummy(index1,i)=Help(index1,i)-s*(Help(index2,i)+ teta*Help(index1,i));
2721  HelpDummy(i,index1)=Help(index1,i)-s*(Help(index2,i)+ teta*Help(index1,i));
2722  }
2723  }
2724 
2725 
2726  Help= HelpDummy;
2727 
2728  //Calculation of the eigenvectors V
2729  Rotation =unity;
2730  Rotation(index2,index1)=-s;
2731  Rotation(index1,index2)=s;
2732  Rotation(index1,index1)=c;
2733  Rotation(index2,index2)=c;
2734 
2735  // Help=ZeroMatrix(A.size1(),A.size1());
2736 
2737  VDummy = ZeroMatrix(Help.size1(), Help.size2());
2738 
2739  for(unsigned int i=0; i< Help.size1(); i++)
2740  {
2741  for(unsigned int j=0; j< Help.size1(); j++)
2742  {
2743  for(unsigned int k=0; k< Help.size1(); k++)
2744  {
2745  VDummy(i,j) += V(i,k)*Rotation(k,j);
2746  }
2747  }
2748  }
2749  V= VDummy;
2750  }
2751 
2752  if(!(is_converged))
2753  {
2754  std::cout<<"########################################################"<<std::endl;
2755  std::cout<<"Max_Iterations exceed in Jacobi-Seidel-Iteration (eigenvectors)"<<std::endl;
2756  std::cout<<"########################################################"<<std::endl;
2757  }
2758 
2759  for(unsigned int i=0; i< Help.size1(); i++)
2760  {
2761  for(unsigned int j=0; j< Help.size1(); j++)
2762  {
2763  vectors(i,j)= V(j,i);
2764  }
2765  }
2766 
2767  for(unsigned int i=0; i<Help.size1(); i++)
2768  lambda(i)= Help(i,i);
2769 
2770  return;
2771  }
2772 
2773 
2774  inline void CreatePartition(unsigned int number_of_threads, const int number_of_rows, DenseVector<unsigned int>& partitions)
2775  {
2776  partitions.resize(number_of_threads + 1);
2777  int partition_size = number_of_rows / number_of_threads;
2778  partitions[0] = 0;
2779  partitions[number_of_threads] = number_of_rows;
2780  for (unsigned int i = 1; i < number_of_threads; i++)
2781  partitions[i] = partitions[i - 1] + partition_size;
2782  }
2783 
2787 
2788 
2792 
2793 
2797 
2798 
2802 
2803 
2807 
2809  CalculateSignedDistanceTo3DSkinProcess& operator=(CalculateSignedDistanceTo3DSkinProcess const& rOther);
2810 
2812  //CalculateSignedDistanceTo3DSkinProcess(CalculateSignedDistanceTo3DSkinProcess const& rOther);
2813 
2814 
2816 
2817 }; // Class CalculateSignedDistanceTo3DSkinProcess
2818 
2820 
2823 
2824 
2828 
2829 
2831 inline std::istream& operator >> (std::istream& rIStream,
2833 
2835 inline std::ostream& operator << (std::ostream& rOStream,
2837 {
2838  rThis.PrintInfo(rOStream);
2839  rOStream << std::endl;
2840  rThis.PrintData(rOStream);
2841 
2842  return rOStream;
2843 }
2845 
2846 const double CalculateSignedDistanceTo3DSkinProcess::epsilon = 1e-18;
2847 
2848 
2849 } // namespace Kratos.
2850 
2851 #endif // KRATOS_CALCULATE_DISTANCE_PROCESS_H_INCLUDED defined
2852 
2853 
PeriodicInterfaceProcess & operator=(const PeriodicInterfaceProcess &)=delete
This class is designed to allow the fast location of MANY points on the top of a 3D mesh.
Definition: binbased_fast_point_locator.h:68
ConfigureType::ResultIteratorType ResultIteratorType
Definition: binbased_fast_point_locator.h:82
ConfigureType::ResultContainerType ResultContainerType
Definition: binbased_fast_point_locator.h:81
void Execute() override
Executes the CalculateDiscontinuousDistanceToSkinProcess This method automatically does all the calls...
Definition: calculate_discontinuous_distance_to_skin_process.cpp:195
Calculates the nodal distances using elemental discontinuous distances.
Definition: calculate_distance_to_skin_process.h:40
Short class definition.
Definition: calculate_signed_distance_to_3d_skin_process.h:265
void GetIntersections(double *ray, int direction, std::vector< std::pair< double, Element::GeometryType * > > &intersections)
Definition: calculate_signed_distance_to_3d_skin_process.h:2279
DistanceSpatialContainersConfigure ConfigurationType
Definition: calculate_signed_distance_to_3d_skin_process.h:273
~CalculateSignedDistanceTo3DSkinProcess() override
Destructor.
Definition: calculate_signed_distance_to_3d_skin_process.h:301
int GetCellIntersections(OctreeType::cell_type *cell, double *ray, OctreeType::key_type *ray_key, int direction, std::vector< std::pair< double, Element::GeometryType * > > &intersections)
Definition: calculate_signed_distance_to_3d_skin_process.h:2337
void CalcElementDistances(ModelPart::ElementsContainerType::iterator &i_fluidElement, BoundedMatrix< unsigned int, 6, 2 > TetEdgeIndexTable)
Definition: calculate_signed_distance_to_3d_skin_process.h:871
void AveragePressureToNode(BinBasedFastPointLocator< 3 > &node_locator, Node &node)
Definition: calculate_signed_distance_to_3d_skin_process.h:694
Point PointType
Definition: calculate_signed_distance_to_3d_skin_process.h:277
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: calculate_signed_distance_to_3d_skin_process.h:2488
double PointDistanceToPlane(Point &planeBasePoint, array_1d< double, 3 > &planeNormal, Point &ToPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:1443
void Initialize()
Definition: calculate_signed_distance_to_3d_skin_process.h:813
void CalcSignedDistancesToMoreThanThreeIntNodes(ModelPart::ElementsContainerType::iterator &i_fluid_Element, std::vector< IntersectionNodeStruct > NodesOfApproximatedStructure, array_1d< double, 4 > &ElementalDistances, std::vector< TetEdgeStruct > &IntersectedTetEdges)
Definition: calculate_signed_distance_to_3d_skin_process.h:1319
CalculateSignedDistanceTo3DSkinProcess(ModelPart &rThisModelPartStruc, ModelPart &rThisModelPartFluid)
Constructor.
Definition: calculate_signed_distance_to_3d_skin_process.h:295
void CalcSignedDistancesToThreeIntNodes(ModelPart::ElementsContainerType::iterator &i_fluid_Element, std::vector< IntersectionNodeStruct > &NodesOfApproximatedStructure, array_1d< double, 4 > &ElementalDistances)
Definition: calculate_signed_distance_to_3d_skin_process.h:1280
ConfigurationType::cell_node_data_type CellNodeDataType
Definition: calculate_signed_distance_to_3d_skin_process.h:276
void SetNodeInNeighbours(CellType *pCell, int Position, CellNodeDataType *pNode)
Definition: calculate_signed_distance_to_3d_skin_process.h:1818
void IdentifyIntersectionNodes(ModelPart::ElementsContainerType::iterator &i_fluidElement, unsigned int i_tetEdge, std::vector< OctreeType::cell_type * > &leaves, std::vector< TetEdgeStruct > &IntersectedTetEdges, unsigned int &NumberIntersectionsOnTetCorner, BoundedMatrix< unsigned int, 6, 2 > TetEdgeIndexTable, int &intersection_counter)
Definition: calculate_signed_distance_to_3d_skin_process.h:903
void CalcDistanceTo3DSkin(std::vector< TetEdgeStruct > &IntersectedTetEdges, ModelPart::ElementsContainerType::iterator &i_fluid_Element, unsigned int NumberIntersectionsOnTetCorner)
Definition: calculate_signed_distance_to_3d_skin_process.h:1150
void CalcSignedDistancesToOneIntNode(ModelPart::ElementsContainerType::iterator &i_fluid_Element, std::vector< IntersectionNodeStruct > NodesOfApproximatedStructure, array_1d< double, 4 > &ElementalDistances)
Definition: calculate_signed_distance_to_3d_skin_process.h:1218
void GenerateOctree()
Definition: calculate_signed_distance_to_3d_skin_process.h:1682
void MappingPressureToStructure(BinBasedFastPointLocator< 3 > &node_locator)
Definition: calculate_signed_distance_to_3d_skin_process.h:359
int IntersectionTriangleSegment(Element::GeometryType &rGeometry, double *RayPoint1, double *RayPoint2, double *IntersectionPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:2378
void Execute() override
Execute method is used to execute the Process algorithms.
Definition: calculate_signed_distance_to_3d_skin_process.h:323
KRATOS_CLASS_POINTER_DEFINITION(CalculateSignedDistanceTo3DSkinProcess)
Pointer definition of CalculateSignedDistanceTo3DSkinProcess.
bool StructuralElementNotYetConsidered(unsigned int IDCurrentStructElem, std::vector< unsigned int > &IntersectingStructElemID)
Definition: calculate_signed_distance_to_3d_skin_process.h:1019
void GenerateCellNode(CellType *pCell, std::size_t &LastId)
Definition: calculate_signed_distance_to_3d_skin_process.h:1796
OctreeBinary< CellType > OctreeType
Definition: calculate_signed_distance_to_3d_skin_process.h:275
bool IsNewIntersectionNode(IntersectionNodeStruct &NewIntersectionNode, std::vector< TetEdgeStruct > &IntersectedTetEdges)
Definition: calculate_signed_distance_to_3d_skin_process.h:1076
void CalculateNodeDistance(Node &rNode)
Definition: calculate_signed_distance_to_3d_skin_process.h:2057
void PrintGiDResults(std::ostream &rOStream) const
Definition: calculate_signed_distance_to_3d_skin_process.h:2528
std::string Info() const override
Turn back information as a string.
Definition: calculate_signed_distance_to_3d_skin_process.h:2476
void AssignMinimalNodalDistance()
Definition: calculate_signed_distance_to_3d_skin_process.h:1464
void CalculateNormal3D(Point &Point1, Point &Point2, Point &Point3, array_1d< double, 3 > &rResultNormal)
Definition: calculate_signed_distance_to_3d_skin_process.h:1135
bool IsIntersectionNodeOnTetEdge(double *IntersectionPoint, double *EdgeNode1, double *EdgeNode2)
Definition: calculate_signed_distance_to_3d_skin_process.h:1038
void operator()()
Definition: calculate_signed_distance_to_3d_skin_process.h:310
void DistanceFluidStructure()
Definition: calculate_signed_distance_to_3d_skin_process.h:765
void CalculateDistance(CellNodeDataType &rNode, int i_direction)
Definition: calculate_signed_distance_to_3d_skin_process.h:1954
void GetIntersectionsAndNodes(double *ray, int direction, std::vector< std::pair< double, Element::GeometryType * > > &intersections, DistanceSpatialContainersConfigure::data_type &rNodesArray)
Definition: calculate_signed_distance_to_3d_skin_process.h:2166
void CalculateDistance()
Definition: calculate_signed_distance_to_3d_skin_process.h:1920
void ComputeDiscontinuousInterpolation(const Node &pNode, Geometry< Node > &geom, const array_1d< double, 4 > &distances, array_1d< double, 4 > &Npos, array_1d< double, 4 > &Nneg)
Definition: calculate_signed_distance_to_3d_skin_process.h:531
OctreeType::cell_type::object_container_type object_container_type
always the point 3D
Definition: calculate_signed_distance_to_3d_skin_process.h:278
void AvoidZeroDistances(ModelPart::ElementsContainerType::iterator &Element, array_1d< double, 4 > &ElementalDistances)
Definition: calculate_signed_distance_to_3d_skin_process.h:1496
void SetIndexTable(BoundedMatrix< unsigned int, 6, 2 > &TetEdgeIndexTable)
Definition: calculate_signed_distance_to_3d_skin_process.h:851
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: calculate_signed_distance_to_3d_skin_process.h:2482
double DistancePositionInSpace(double *coords)
Definition: calculate_signed_distance_to_3d_skin_process.h:2093
void CalculateNotEmptyLeavesDistance(CellType *pCell)
Definition: calculate_signed_distance_to_3d_skin_process.h:2019
void PrintGiDMesh(std::ostream &rOStream) const
Definition: calculate_signed_distance_to_3d_skin_process.h:2492
void GenerateSkinModelPart(ModelPart &mrNewSkinModelPart)
Definition: calculate_signed_distance_to_3d_skin_process.h:1538
bool IsIntersectionOnCorner(IntersectionNodeStruct &NewIntersectionNode, double *EdgeNode1, double *EdgeNode2)
Definition: calculate_signed_distance_to_3d_skin_process.h:1106
void FillIntNodesContainer(std::vector< TetEdgeStruct > &IntersectedTetEdges, std::vector< IntersectionNodeStruct > &NodesOfApproximatedStructure)
Definition: calculate_signed_distance_to_3d_skin_process.h:1199
void GenerateNodes()
Definition: calculate_signed_distance_to_3d_skin_process.h:1766
OctreeBinaryCell< ConfigurationType > CellType
Definition: calculate_signed_distance_to_3d_skin_process.h:274
void CalculateDistance2()
Definition: calculate_signed_distance_to_3d_skin_process.h:1845
void CalcSignedDistancesToTwoIntNodes(ModelPart::ElementsContainerType::iterator &i_fluid_Element, std::vector< IntersectionNodeStruct > NodesOfApproximatedStructure, array_1d< double, 4 > &ElementalDistances)
Definition: calculate_signed_distance_to_3d_skin_process.h:1239
Base class for all Conditions.
Definition: condition.h:59
virtual Pointer Create(IndexType NewId, NodesArrayType const &ThisNodes, PropertiesType::Pointer pProperties) const
It creates a new condition pointer.
Definition: condition.h:205
Definition: calculate_signed_distance_to_3d_skin_process.h:61
std::size_t & Id()
Definition: calculate_signed_distance_to_3d_skin_process.h:71
double & operator[](int i)
Definition: calculate_signed_distance_to_3d_skin_process.h:70
double & X()
Definition: calculate_signed_distance_to_3d_skin_process.h:67
double & Distance()
Definition: calculate_signed_distance_to_3d_skin_process.h:66
double & Y()
Definition: calculate_signed_distance_to_3d_skin_process.h:68
double & Z()
Definition: calculate_signed_distance_to_3d_skin_process.h:69
Definition: calculate_signed_distance_to_3d_skin_process.h:58
KRATOS_CLASS_POINTER_DEFINITION(DistanceSpatialContainersConfigure)
Pointer definition of DistanceSpatialContainersConfigure.
ModelPart::ElementsContainerType::ContainerType ContainerType
Definition: calculate_signed_distance_to_3d_skin_process.h:88
std::vector< PointerType >::iterator PointerTypeIterator
Definition: calculate_signed_distance_to_3d_skin_process.h:99
ContainerType::value_type PointerType
Definition: calculate_signed_distance_to_3d_skin_process.h:89
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: calculate_signed_distance_to_3d_skin_process.h:222
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: calculate_signed_distance_to_3d_skin_process.h:219
std::vector< CellNodeData * > data_type
Definition: calculate_signed_distance_to_3d_skin_process.h:97
ContainerType::iterator IteratorType
Definition: calculate_signed_distance_to_3d_skin_process.h:90
static void CalculateBoundingBox(const PointerType &rObject, PointType &rLowPoint, PointType &rHighPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:139
static bool Intersection(const PointerType &rObj_1, const PointerType &rObj_2)
Definition: calculate_signed_distance_to_3d_skin_process.h:173
ResultContainerType::iterator ResultIteratorType
Definition: calculate_signed_distance_to_3d_skin_process.h:93
Element::Pointer pointer_type
Definition: calculate_signed_distance_to_3d_skin_process.h:95
static void DeleteData(data_type *data)
Definition: calculate_signed_distance_to_3d_skin_process.h:135
ModelPart::ElementsContainerType::ContainerType ResultContainerType
Definition: calculate_signed_distance_to_3d_skin_process.h:91
virtual ~DistanceSpatialContainersConfigure()
Destructor.
Definition: calculate_signed_distance_to_3d_skin_process.h:115
Point PointType
Definition: calculate_signed_distance_to_3d_skin_process.h:86
static bool IntersectionBox(const PointerType &rObject, const PointType &rLowPoint, const PointType &rHighPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:182
static void CopyData(data_type *source, data_type *destination)
Definition: calculate_signed_distance_to_3d_skin_process.h:131
CellNodeData cell_node_data_type
Definition: calculate_signed_distance_to_3d_skin_process.h:96
virtual std::string Info() const
Turn back information as a string.
Definition: calculate_signed_distance_to_3d_skin_process.h:213
static data_type * AllocateData()
Definition: calculate_signed_distance_to_3d_skin_process.h:127
ResultContainerType::value_type ResultPointerType
Definition: calculate_signed_distance_to_3d_skin_process.h:92
DistanceSpatialContainersConfigure()
Default constructor.
Definition: calculate_signed_distance_to_3d_skin_process.h:112
static bool IsIntersected(const Element::Pointer rObject, double Tolerance, const double *rLowPoint, const double *rHighPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:188
std::vector< double >::iterator DistanceIteratorType
always the point 3D
Definition: calculate_signed_distance_to_3d_skin_process.h:87
static void GetBoundingBox(const PointerType rObject, double *rLowPoint, double *rHighPoint)
Definition: calculate_signed_distance_to_3d_skin_process.h:154
Base class for all Elements.
Definition: element.h:60
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
virtual bool HasIntersection(const GeometryType &ThisGeometry) const
Definition: geometry.h:1453
void reserve(int dim)
Definition: geometry.h:558
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: global_pointers_vector.h:79
iterator begin()
Definition: global_pointers_vector.h:221
size_type size() const
Definition: global_pointers_vector.h:307
iterator end()
Definition: global_pointers_vector.h:229
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
KratosComponents class encapsulates a lookup table for a family of classes in a generic way.
Definition: kratos_components.h:49
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
NodeType::Pointer CreateNewNode(int Id, double x, double y, double z, VariablesList::Pointer pNewVariablesList, IndexType ThisIndex=0)
Definition: model_part.cpp:270
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
PropertiesContainerType & rProperties(IndexType ThisIndex=0)
Definition: model_part.h:1003
MeshType::ElementIterator ElementIterator
Definition: model_part.h:174
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class defines the node.
Definition: node.h:65
TVariableType::Type & GetSolutionStepValue(const TVariableType &rThisVariable)
Definition: node.h:406
This class represents a cell in an octree to be used with Octree class.
Definition: octree_binary_cell.h:70
std::size_t GetLocalPosition(key_type *keys)
Definition: octree_binary_cell.h:327
const std::vector< pointer_type > * pGetObjects() const
Definition: octree_binary_cell.h:451
std::size_t key_type
Definition: octree_binary_cell.h:86
data_type * pGetData() const
Definition: octree_binary_cell.h:441
int GetKey(std::size_t position, key_type *keys) const
Definition: octree_binary_cell.h:241
int GetNeighbourKey(std::size_t direction, key_type *keys) const
Definition: octree_binary_cell.h:265
CellType cell_type
Definition: octree_binary.h:68
cell_type::key_type key_type
Definition: octree_binary.h:70
key_type CalcKeyNormalized(coordinate_type coordinate) const
Definition: octree_binary.h:199
cell_type * pGetCell(key_type *keys) const
Definition: octree_binary.h:429
Point class.
Definition: point.h:59
CoordinatesArrayType const & Coordinates() const
Definition: point.h:215
double Y() const
Definition: point.h:187
double Z() const
Definition: point.h:193
double X() const
Definition: point.h:181
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
ptr_iterator ptr_begin()
Returns an iterator pointing to the beginning of the underlying data container.
Definition: pointer_vector_set.h:386
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
void push_back(TPointerType x)
Adds a pointer to the end of the set.
Definition: pointer_vector_set.h:544
TContainerType ContainerType
Definition: pointer_vector_set.h:90
void reserve(int reservedsize)
Reserves memory for a specified number of elements.
Definition: pointer_vector_set.h:733
The base class for all processes in Kratos.
Definition: process.h:49
A four node 3D quadrilateral geometry with bi-linear shape functions.
Definition: quadrilateral_3d_4.h:76
double ShapeFunctionValue(IndexType ShapeFunctionIndex, const CoordinatesArrayType &rPoint) const override
Definition: quadrilateral_3d_4.h:1068
CoordinatesArrayType & PointLocalCoordinates(CoordinatesArrayType &rResult, const CoordinatesArrayType &rPoint) const override
Returns the local coordinates of a given arbitrary point.
Definition: quadrilateral_3d_4.h:522
A three node 3D triangle geometry with linear shape functions.
Definition: triangle_3d_3.h:77
double ShapeFunctionValue(IndexType ShapeFunctionIndex, const CoordinatesArrayType &rPoint) const override
Definition: triangle_3d_3.h:1348
CoordinatesArrayType & PointLocalCoordinates(CoordinatesArrayType &rResult, const CoordinatesArrayType &rPoint) const override
Returns the local coordinates of a given arbitrary point.
Definition: triangle_3d_3.h:917
BOOST_UBLAS_INLINE size_type size() const
Definition: array_1d.h:370
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_WATCH(variable)
Definition: define.h:806
#define KRATOS_TRY
Definition: define.h:109
std::ostream & operator<<(std::ostream &rOStream, const CalculateSignedDistanceTo3DSkinProcess &rThis)
output stream function
Definition: calculate_signed_distance_to_3d_skin_process.h:2835
std::istream & operator>>(std::istream &rIStream, CalculateSignedDistanceTo3DSkinProcess &rThis)
input stream function
sd
Definition: GenerateWind.py:148
pybind11::list keys(Parameters const &self)
Definition: add_kratos_parameters_to_python.cpp:32
void CalculateGeometryData(const GeometryType &rGeometry, const GeometryData::IntegrationMethod &rIntegrationMethod, Vector &rGaussWeights, Matrix &rNContainer, GeometryType::ShapeFunctionsGradientsType &rDN_DX)
Definition: rans_calculation_utilities.cpp:31
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
std::shared_ptr< T > shared_ptr
Definition: smart_pointers.h:27
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
int max_iterations
Definition: ProjectParameters.py:53
def GetSolutionStepValue(entity, variable, solution_step_index)
Definition: coupling_interface_data.py:253
def CrossProduct(A, B)
Definition: define_wake_process_3d.py:13
v
Definition: generate_convection_diffusion_explicit_element.py:114
w
Definition: generate_convection_diffusion_explicit_element.py:108
V
Definition: generate_droplet_dynamics.py:256
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
float gamma
Definition: generate_two_fluid_navier_stokes.py:131
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
def Average(vector_container, current_values, k_calc, pp)
Definition: initial_time_bounds.py:102
int dimension
Definition: isotropic_damage_automatic_differentiation.py:123
data
Definition: mesh_to_mdpa_converter.py:59
int t
Definition: ode_solve.py:392
int d
Definition: ode_solve.py:397
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
dir
Definition: radii_error_plotter.py:10
A
Definition: sensitivityMatrix.py:70
p
Definition: sensitivityMatrix.py:52
N
Definition: sensitivityMatrix.py:29
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
double precision, public pi
Definition: TensorModule.f:16
e
Definition: run_cpp_mpi_tests.py:31
Definition: calculate_signed_distance_to_3d_skin_process.h:279
unsigned int EdgeNode1
Definition: calculate_signed_distance_to_3d_skin_process.h:282
array_1d< double, 3 > Coordinates
Definition: calculate_signed_distance_to_3d_skin_process.h:280
unsigned int EdgeNode2
Definition: calculate_signed_distance_to_3d_skin_process.h:283
array_1d< double, 3 > StructElemNormal
Definition: calculate_signed_distance_to_3d_skin_process.h:281
Definition: calculate_signed_distance_to_3d_skin_process.h:285
std::vector< IntersectionNodeStruct > IntNodes
Definition: calculate_signed_distance_to_3d_skin_process.h:286
Definition: mesh_converter.cpp:38