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.
boundary_normals_calculation_utilities.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosDelaunayMeshingApplication $
3 // Created by: $Author: JMCarbonell $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: April 2018 $
6 // Revision: $Revision: 0.0 $
7 //
8 //
9 
10 #include "includes/model_part.h"
11 
12 #if !defined(KRATOS_BOUNDARY_NORMALS_CALCULATION_UTILITIES_H_INCLUDED)
13 #define KRATOS_BOUNDARY_NORMALS_CALCULATION_UTILITIES_H_INCLUDED
14 
15 // System includes
16 
17 // External includes
18 
19 // Project includes
22 
23 namespace Kratos
24 {
25 
28 
32 
36 
40 
44 
48  {
49  public:
52 
57 
61 
71 
73 
82 
84  {
85 
86  mEchoLevel = EchoLevel;
87 
88  if (!rModelPart.IsSubModelPart())
89  {
90 
91  this->ResetBodyNormals(rModelPart); // clear boundary normals
92 
93  // FLUID Domains
94  for (auto &i_mp : rModelPart.SubModelParts())
95  {
96  if ((i_mp.Is(FLUID) || i_mp.Is(SOLID) || i_mp.Is(RIGID)) && i_mp.IsNot(ACTIVE) && i_mp.IsNot(BOUNDARY) && i_mp.IsNot(CONTACT))
97  {
98 
99  CalculateBoundaryNormals(i_mp);
100 
101  // standard assignation // fails in sharp edges angle<90
102  AddNormalsToNodes(i_mp);
103  }
104  }
105 
106  }
107  else
108  {
109 
110  this->ResetBodyNormals(rModelPart); // clear boundary normals
111 
112  CalculateBoundaryNormals(rModelPart);
113 
114  // standard assignation // fails in sharp edges angle<90
115  AddNormalsToNodes(rModelPart);
116  }
117 
118  // For MPI: correct values on partition boundaries
119  rModelPart.GetCommunicator().AssembleCurrentData(NORMAL);
120  }
121 
124  {
125 
126  std::cout << "DO NOT ENTER HERE ---- CalculateWeightedBoundaryNormals " << std::endl;
127  mEchoLevel = EchoLevel;
128 
129  if (!rModelPart.IsSubModelPart())
130  {
131 
132  this->ResetBodyNormals(rModelPart); // clear boundary normals
133 
134  // FLUID Domains
135  for (auto &i_mp : rModelPart.SubModelParts())
136  {
137  if (i_mp.Is(FLUID) && i_mp.IsNot(ACTIVE) && i_mp.IsNot(BOUNDARY) && i_mp.IsNot(CONTACT))
138  {
139 
140  CalculateBoundaryNormals(i_mp);
141 
142  // assignation for solid boundaries : Unity Normals on nodes and Shrink_Factor on nodes
143  AddWeightedNormalsToNodes(i_mp);
144  }
145  }
146  // SOLID Domains
147  for (auto &i_mp : rModelPart.SubModelParts())
148  {
149  if (i_mp.Is(SOLID) && i_mp.IsNot(ACTIVE) && i_mp.IsNot(BOUNDARY) && i_mp.IsNot(CONTACT))
150  {
151 
152  CalculateBoundaryNormals(i_mp);
153 
154  // assignation for solid boundaries : Unity Normals on nodes and Shrink_Factor on nodes
155  AddWeightedNormalsToNodes(i_mp);
156  }
157  }
158  // RIGID Domains
159  for (auto &i_mp : rModelPart.SubModelParts())
160  {
161  if (i_mp.Is(RIGID) && i_mp.IsNot(ACTIVE) && i_mp.IsNot(BOUNDARY) && i_mp.IsNot(CONTACT))
162  {
163 
164  CalculateBoundaryNormals(i_mp);
165 
166  // assignation for solid boundaries : Unity Normals on nodes and Shrink_Factor on nodes
167  AddWeightedNormalsToNodes(i_mp);
168  }
169  }
170  }
171  else
172  {
173 
174  this->ResetBodyNormals(rModelPart); // clear boundary normals
175 
176  CalculateBoundaryNormals(rModelPart);
177 
178  // assignation for solid boundaries: Unity Normals on nodes and Shrink_Factor on nodes
179  // AddWeightedNormalsToNodes(rModelPart);
180  }
181 
182  // For MPI: correct values on partition boundaries
183  rModelPart.GetCommunicator().AssembleCurrentData(NORMAL);
184  rModelPart.GetCommunicator().AssembleCurrentData(SHRINK_FACTOR);
185  }
186 
200  protected:
222 
223  private:
229 
230  int mEchoLevel;
231 
239 
241  void CalculateBoundaryNormals(ModelPart &rModelPart)
242  {
243  KRATOS_TRY
244 
245  const unsigned int dimension = rModelPart.GetProcessInfo()[SPACE_DIMENSION];
246 
247  if (rModelPart.NumberOfConditions() && this->CheckConditionsLocalSpace(rModelPart, dimension - 1))
248  {
249 
250  if (mEchoLevel > 0)
251  std::cout << " [" << rModelPart.Name() << "] (BC)" << std::endl;
252 
253  this->CalculateBoundaryNormals(rModelPart.Conditions());
254  }
255  else if (rModelPart.NumberOfElements())
256  {
257 
258  if (this->CheckElementsLocalSpace(rModelPart, dimension))
259  {
260 
261  if (mEchoLevel > 0)
262  std::cout << " [" << rModelPart.Name() << "] (BVE)" << std::endl;
263 
264  this->CalculateVolumeBoundaryNormals(rModelPart);
265  }
266  else if (this->CheckElementsLocalSpace(rModelPart, dimension - 1))
267  {
268 
269  if (mEchoLevel > 0)
270  std::cout << " [" << rModelPart.Name() << "] (BE)" << std::endl;
271 
272  ElementsContainerType &rElements = rModelPart.Elements();
273 
274  this->CalculateBoundaryNormals(rElements);
275  }
276  }
277 
278  KRATOS_CATCH("")
279  }
280 
281  // this function adds the Contribution of one of the geometries
282  // to the corresponding nodes
283  static void CalculateUnitNormal2D(Condition &rCondition, array_1d<double, 3> &An)
284  {
285  Geometry<Node> &rGeometry = rCondition.GetGeometry();
286 
287  // Attention: normal criterion changed for line conditions (vs line elements)
288  An[0] = rGeometry[1].Y() - rGeometry[0].Y();
289  An[1] = -(rGeometry[1].X() - rGeometry[0].X());
290  An[2] = 0.00;
291 
292  array_1d<double, 3> &normal = rCondition.GetValue(NORMAL);
293  noalias(normal) = An / norm_2(An);
294  }
295 
296  static void CalculateUnitNormal3D(Condition &rCondition, array_1d<double, 3> &An,
297  array_1d<double, 3> &v1, array_1d<double, 3> &v2)
298  {
299  Geometry<Node> &rGeometry = rCondition.GetGeometry();
300 
301  v1[0] = rGeometry[1].X() - rGeometry[0].X();
302  v1[1] = rGeometry[1].Y() - rGeometry[0].Y();
303  v1[2] = rGeometry[1].Z() - rGeometry[0].Z();
304 
305  v2[0] = rGeometry[2].X() - rGeometry[0].X();
306  v2[1] = rGeometry[2].Y() - rGeometry[0].Y();
307  v2[2] = rGeometry[2].Z() - rGeometry[0].Z();
308 
310 
311  array_1d<double, 3> &normal = rCondition.GetValue(NORMAL);
312 
313  noalias(normal) = An / norm_2(An);
314  }
315 
316  // this function adds the Contribution of one of the geometries
317  // to the corresponding nodes
318  static void CalculateUnitNormal2D(Element &rElement, array_1d<double, 3> &An)
319  {
320  Geometry<Node> &rGeometry = rElement.GetGeometry();
321 
322  if (rGeometry.size() < 2)
323  {
324  std::cout << " Warning 2D geometry with only " << rGeometry.size() << " node :: multiple normal definitions " << std::endl;
325  rElement.GetValue(NORMAL).clear();
326  }
327  else
328  {
329 
330  An[0] = -(rGeometry[1].Y() - rGeometry[0].Y());
331  An[1] = rGeometry[1].X() - rGeometry[0].X();
332  An[2] = 0.00;
333 
334  array_1d<double, 3> &normal = rElement.GetValue(NORMAL);
335  noalias(normal) = An / norm_2(An);
336  }
337  }
338 
339  static void CalculateUnitNormal3D(Element &rElement, array_1d<double, 3> &An,
340  array_1d<double, 3> &v1, array_1d<double, 3> &v2)
341  {
342  Geometry<Node> &rGeometry = rElement.GetGeometry();
343 
344  if (rGeometry.size() < 3)
345  {
346  std::cout << " Warning 3D geometry with only " << rGeometry.size() << " nodes :: multiple normal definitions " << std::endl;
347  rElement.GetValue(NORMAL).clear();
348  }
349  else
350  {
351 
352  v1[0] = rGeometry[1].X() - rGeometry[0].X();
353  v1[1] = rGeometry[1].Y() - rGeometry[0].Y();
354  v1[2] = rGeometry[1].Z() - rGeometry[0].Z();
355 
356  v2[0] = rGeometry[2].X() - rGeometry[0].X();
357  v2[1] = rGeometry[2].Y() - rGeometry[0].Y();
358  v2[2] = rGeometry[2].Z() - rGeometry[0].Z();
359 
361  An *= 0.5;
362 
363  array_1d<double, 3> &normal = rElement.GetValue(NORMAL);
364 
365  noalias(normal) = An / norm_2(An);
366  }
367  }
368 
369  void ResetBodyNormals(ModelPart &rModelPart)
370  {
371  // resetting the normals
372  for (auto &i_node : rModelPart.Nodes())
373  {
374  i_node.GetSolutionStepValue(NORMAL).clear();
375  }
376  }
377 
378  void CheckBodyNormals(ModelPart &rModelPart)
379  {
380  // resetting the normals
381  for (const auto &i_node : rModelPart.Nodes())
382  {
383  std::cout << " ID: " << i_node.Id() << " normal: " << i_node.GetSolutionStepValue(NORMAL) << std::endl;
384  }
385  }
386 
388 
397  void CalculateBoundaryNormals(ConditionsContainerType &rConditions)
398  {
399  KRATOS_TRY
400 
401  // resetting the normals
402  // for(ConditionsContainerType::iterator it = rConditions.begin();
403  // it != rConditions.end(); ++it)
404  // {
405  // Element::GeometryType& rNodes = it->GetGeometry();
406  // for(unsigned int in = 0; in<rNodes.size(); ++in)
407  // ((rNodes[in]).GetSolutionStepValue(NORMAL)).clear();
408  // }
409 
410  const unsigned int dimension = rConditions.begin()->GetGeometry().WorkingSpaceDimension();
411 
412  // std::cout<<" condition geometry: "<<(rConditions.begin())->GetGeometry()<<std::endl;
413 
414  // calculating the normals and storing on the conditions
415  array_1d<double, 3> An;
416  if (dimension == 2)
417  {
418  for (auto &i_cond : rConditions)
419  {
420  if (i_cond.IsNot(CONTACT) && i_cond.Is(BOUNDARY))
421  CalculateUnitNormal2D(i_cond, An);
422  }
423  }
424  else if (dimension == 3)
425  {
426  array_1d<double, 3> v1;
427  array_1d<double, 3> v2;
428  for (auto &i_cond : rConditions)
429  {
430  // calculate the normal on the given condition
431  if (i_cond.IsNot(CONTACT) && i_cond.Is(BOUNDARY))
432  {
433  CalculateUnitNormal3D(i_cond, An, v1, v2);
434  }
435  }
436  }
437 
438  KRATOS_CATCH("")
439  }
440 
442 
451  void CalculateBoundaryNormals(ElementsContainerType &rElements)
452 
453  {
454  KRATOS_TRY
455 
456  // resetting the normals
457  // for(ElementsContainerType::iterator it = rElements.begin(); it != rElements.end(); ++it)
458  // {
459  // Element::GeometryType& rNodes = it->GetGeometry();
460  // for(unsigned int in = 0; in<rNodes.size(); ++in)
461  // ((rNodes[in]).GetSolutionStepValue(NORMAL)).clear();
462  // }
463 
464  const unsigned int dimension = (rElements.begin())->GetGeometry().WorkingSpaceDimension();
465 
466  // std::cout<<" element geometry: "<<(rElements.begin())->GetGeometry()<<std::endl;
467 
468  // calculating the normals and storing on elements
469  array_1d<double, 3> An;
470  if (dimension == 2)
471  {
472  for (auto &i_elem : rElements)
473  {
474  if (i_elem.IsNot(CONTACT))
475  {
476  i_elem.Set(BOUNDARY); // give an error in set flags (for the created rigid body)
477  CalculateUnitNormal2D(i_elem, An);
478  }
479  }
480  }
481  else if (dimension == 3)
482  {
483  array_1d<double, 3> v1;
484  array_1d<double, 3> v2;
485  for (auto &i_elem : rElements)
486  {
487  // calculate the normal on the given surface element
488  if (i_elem.IsNot(CONTACT))
489  {
490  i_elem.Set(BOUNDARY); // give an error in set flags (for the created rigid body)
491  CalculateUnitNormal3D(i_elem, An, v1, v2);
492  }
493  }
494  }
495 
496  KRATOS_CATCH("")
497  }
498 
499  // Check if the mesh has elements with the spatial dimension
500  bool CheckElementsDimension(ModelPart &rModelPart, unsigned int dimension)
501  {
502  KRATOS_TRY
503 
504  ElementsContainerType &rElements = rModelPart.Elements();
505 
506  ElementsContainerType::iterator it = rElements.begin();
507 
508  if ((it)->GetGeometry().WorkingSpaceDimension() == dimension)
509  {
510  return true;
511  }
512  else
513  {
514  return false;
515  }
516 
517  KRATOS_CATCH("")
518  }
519 
520  // Check if the mesh has boundary conditions with the spatial dimension
521  bool CheckConditionsDimension(ModelPart &rModelPart, unsigned int dimension)
522  {
523  KRATOS_TRY
524 
525  if (rModelPart.Conditions().begin()->GetGeometry().WorkingSpaceDimension() == dimension)
526  {
527  return true;
528  }
529  else
530  {
531  return false;
532  }
533 
534  KRATOS_CATCH("")
535  }
536 
537  // Check if the elements local space is equal to the spatial dimension
538  bool CheckElementsLocalSpace(ModelPart &rModelPart, unsigned int dimension)
539  {
540  KRATOS_TRY
541 
542  if (rModelPart.Elements().begin()->GetGeometry().LocalSpaceDimension() == dimension)
543  {
544  return true;
545  }
546  else
547  {
548  return false;
549  }
550 
551  KRATOS_CATCH("")
552  }
553 
554  // Check if the conditions local space is equal to the spatial dimension
555  bool CheckConditionsLocalSpace(ModelPart &rModelPart, unsigned int dimension)
556  {
557  KRATOS_TRY
558 
559  if (rModelPart.Conditions().begin()->GetGeometry().LocalSpaceDimension() == dimension)
560  {
561  return true;
562  }
563  else
564  {
565  return false;
566  }
567 
568  KRATOS_CATCH("")
569  }
570 
572  // using a consistent way: SOTO & CODINA
573  // fails in sharp edges angle<90
574  void CalculateVolumeBoundaryNormals(ModelPart &rModelPart)
575  {
576  KRATOS_TRY
577 
578  const unsigned int dimension = rModelPart.GetProcessInfo()[SPACE_DIMENSION];
579 
580  // Reset normals
581  ModelPart::NodesContainerType &rNodes = rModelPart.Nodes();
582  ModelPart::ElementsContainerType &rElements = rModelPart.Elements();
583 
584  // Check if the neigbours search is already done and set
585  bool neighsearch = false;
586  unsigned int number_of_nodes = rElements.begin()->GetGeometry().PointsNumber();
587  for (unsigned int i = 0; i < number_of_nodes; ++i)
588  if ((rElements.begin()->GetGeometry()[i].GetValue(NEIGHBOUR_ELEMENTS)).size() > 1)
589  neighsearch = true;
590 
591  if (!neighsearch)
592  std::cout << " WARNING :: Neighbour Search Not PERFORMED " << std::endl;
593 
594  for (auto &i_node : rNodes)
595  {
596  i_node.GetSolutionStepValue(NORMAL).clear();
597  if (!neighsearch)
598  {
599  i_node.GetValue(NEIGHBOUR_ELEMENTS).clear();
600  i_node.Reset(BOUNDARY);
601  }
602  }
603 
604  if (!neighsearch)
605  {
606  for (auto i_elem(rElements.begin()); i_elem != rElements.end(); ++i_elem)
607  {
608  Element::GeometryType &rGeometry = i_elem->GetGeometry();
609  for (unsigned int i = 0; i < rGeometry.size(); ++i)
610  {
611  rGeometry[i].GetValue(NEIGHBOUR_ELEMENTS).push_back(*i_elem.base());
612  }
613  }
614  }
615 
616  // calculating the normals and storing it on nodes
617 
618  Vector An(3);
620  int PointNumber = 0; // one gauss point
621  Matrix J;
622  Matrix InvJ;
623  double detJ;
624  Matrix DN_DX;
625 
626  unsigned int assigned = 0;
627  unsigned int not_assigned = 0;
628  unsigned int boundary_nodes = 0;
629  // int boundarycounter=0;
630  for (auto &i_node : rNodes)
631  {
632  noalias(An) = ZeroVector(3);
633 
634  // if(i_node.Is(BOUNDARY)){
635 
636  ElementWeakPtrVectorType &nElements = i_node.GetValue(NEIGHBOUR_ELEMENTS);
637 
638  for (auto &i_nelem : nElements)
639  {
640 
641  Element::GeometryType &rGeometry = i_nelem.GetGeometry();
642 
643  if (rGeometry.EdgesNumber() > 1 && rGeometry.LocalSpaceDimension() == dimension)
644  {
645 
646  //********** Compute the element integral ******//
647  const Element::GeometryType::IntegrationPointsArrayType &integration_points = rGeometry.IntegrationPoints(mIntegrationMethod);
648  const Element::GeometryType::ShapeFunctionsGradientsType &DN_De = rGeometry.ShapeFunctionsLocalGradients(mIntegrationMethod);
649 
650  J.resize(dimension, dimension, false);
651  J = rGeometry.Jacobian(J, PointNumber, mIntegrationMethod);
652 
653  InvJ.clear();
654  detJ = 0;
655  // Calculating the inverse of the jacobian and the parameters needed
656  if (dimension == 2)
657  {
658  MathUtils<double>::InvertMatrix2(J, InvJ, detJ);
659  }
660  else if (dimension == 3)
661  {
662  MathUtils<double>::InvertMatrix3(J, InvJ, detJ);
663  }
664  else
665  {
666  MathUtils<double>::InvertMatrix(J, InvJ, detJ);
667  }
668 
669  // Compute cartesian derivatives for one gauss point
670  DN_DX = prod(DN_De[PointNumber], InvJ);
671 
672  double IntegrationWeight = integration_points[PointNumber].Weight() * detJ;
673 
674  for (unsigned int i = 0; i < rGeometry.size(); ++i)
675  {
676  if (i_node.Id() == rGeometry[i].Id())
677  {
678 
679  for (unsigned int d = 0; d < dimension; ++d)
680  {
681  An[d] += DN_DX(i, d) * IntegrationWeight;
682  }
683  }
684  }
685 
686  //********** Compute the element integral ******//
687  }
688 
689  if (norm_2(An) > 1e-12)
690  {
691  noalias(i_node.FastGetSolutionStepValue(NORMAL)) = An / norm_2(An);
692  assigned += 1;
693  if (!neighsearch)
694  {
695  i_node.Set(BOUNDARY);
696  }
697  }
698  else
699  {
700  (i_node.FastGetSolutionStepValue(NORMAL)).clear();
701  // std::cout<<" ERROR: normal not set "<<std::endl;
702  not_assigned += 1;
703  if (!neighsearch)
704  {
705  i_node.Set(BOUNDARY, false);
706  }
707  }
708  }
709 
710  if (i_node.Is(BOUNDARY))
711  boundary_nodes += 1;
712 
713  // boundarycounter++;
714  // }
715  }
716 
717  if (mEchoLevel > 0)
718  std::cout << " [ Boundary_Normals (Mesh Nodes:" << rNodes.size() << ")[Boundary nodes: " << boundary_nodes << " (SET:" << assigned << " / NOT_SET:" << not_assigned << ")] ]" << std::endl;
719 
720  // std::cout<<" Boundary COUNTER "<<boundarycounter<<std::endl;
721  KRATOS_CATCH("")
722  }
723 
724  //**************************************************************************
725  //**************************************************************************
726 
727  void AddNormalsToNodes(ModelPart &rModelPart)
728  {
729  KRATOS_TRY
730 
731  const unsigned int dimension = rModelPart.GetProcessInfo()[SPACE_DIMENSION];
732 
733  if (rModelPart.NumberOfConditions() && this->CheckConditionsDimension(rModelPart, dimension - 1))
734  {
735 
736  // ConditionsContainerType& rConditions = rModelPart.Conditions();
737 
738  // adding the normals to the nodes
739  for (auto &i_cond : rModelPart.Conditions())
740  {
741  Geometry<Node> &rGeometry = i_cond.GetGeometry();
742  double coeff = 1.00 / rGeometry.size();
743  const array_1d<double, 3> &An = i_cond.GetValue(NORMAL);
744 
745  for (unsigned int i = 0; i < rGeometry.size(); ++i)
746  {
747  noalias(rGeometry[i].FastGetSolutionStepValue(NORMAL)) += coeff * An;
748  }
749  }
750  }
751  else if (rModelPart.NumberOfElements() && this->CheckElementsDimension(rModelPart, dimension - 1))
752  {
753 
754  // adding the normals to the nodes
755  for (auto &i_elem : rModelPart.Elements())
756  {
757  Geometry<Node> &rGeometry = i_elem.GetGeometry();
758  double coeff = 1.00 / rGeometry.size();
759  const array_1d<double, 3> &An = i_elem.GetValue(NORMAL);
760 
761  for (unsigned int i = 0; i < rGeometry.size(); ++i)
762  {
763  noalias(rGeometry[i].FastGetSolutionStepValue(NORMAL)) += coeff * An;
764  }
765  }
766  }
767 
768  KRATOS_CATCH("")
769  }
770 
771  //**************************************************************************
772  //**************************************************************************
773 
774  void AddWeightedNormalsToNodes(ModelPart &rModelPart)
775  {
776  KRATOS_TRY
777 
778  const unsigned int dimension = rModelPart.GetProcessInfo()[SPACE_DIMENSION];
779 
780  ModelPart::NodesContainerType &rNodes = rModelPart.Nodes();
781 
782  unsigned int MaxNodeId = MesherUtilities::GetMaxNodeId(rModelPart);
783  std::vector<int> NodeNeighboursIds(MaxNodeId + 1);
784  std::fill(NodeNeighboursIds.begin(), NodeNeighboursIds.end(), 0);
785 
786  if (mEchoLevel > 1)
787  std::cout << " [" << rModelPart.Name() << "] [conditions:" << rModelPart.NumberOfConditions() << ", elements:" << rModelPart.NumberOfElements() << "] dimension: " << dimension << std::endl;
788 
789  if (rModelPart.NumberOfConditions() && this->CheckConditionsLocalSpace(rModelPart, dimension - 1))
790  {
791 
792  if (mEchoLevel > 0)
793  std::cout << " [" << rModelPart.Name() << "] (C)" << std::endl;
794 
795  // add the neighbour boundary conditions to all the nodes in the mesh
796  std::vector<ConditionWeakPtrVectorType> Neighbours(rNodes.size() + 1);
797 
798  unsigned int id = 1;
799  for (auto i_cond(rModelPart.Conditions().begin()); i_cond != rModelPart.Conditions().end(); ++i_cond)
800  {
801  if (i_cond->IsNot(CONTACT) && i_cond->Is(BOUNDARY))
802  {
803 
804  Condition::GeometryType &rGeometry = i_cond->GetGeometry();
805 
806  if (mEchoLevel > 2)
807  std::cout << " Condition ID " << i_cond->Id() << " id " << id << std::endl;
808 
809  for (unsigned int i = 0; i < rGeometry.size(); ++i)
810  {
811  if (mEchoLevel > 2)
812  {
813  if (NodeNeighboursIds.size() <= rGeometry[i].Id())
814  std::cout << " Shrink node in geom " << rGeometry[i].Id() << " number of nodes " << NodeNeighboursIds.size() << std::endl;
815  }
816 
817  if (NodeNeighboursIds[rGeometry[i].Id()] == 0)
818  {
819  NodeNeighboursIds[rGeometry[i].Id()] = id;
820  Neighbours[id].push_back(*i_cond.base());
821  id++;
822  }
823  else
824  {
825  Neighbours[NodeNeighboursIds[rGeometry[i].Id()]].push_back(*i_cond.base());
826  }
827  }
828  }
829  }
830 
831  //**********Set Boundary Nodes Only
832  if (id > 1)
833  {
834  ModelPart::NodesContainerType::iterator nodes_begin = rNodes.begin();
835  ModelPart::NodesContainerType BoundaryNodes;
836 
837  if (rModelPart.Is(FLUID))
838  {
839  for (unsigned int i = 0; i < rNodes.size(); ++i)
840  {
841  if ((nodes_begin + i)->Is(BOUNDARY) && (nodes_begin + i)->IsNot(RIGID) && NodeNeighboursIds[(nodes_begin + i)->Id()] != 0)
842  {
843  BoundaryNodes.push_back(*(nodes_begin + i).base());
844  }
845  }
846  }
847  else
848  {
849 
850  for (unsigned int i = 0; i < rNodes.size(); ++i)
851  {
852  if ((nodes_begin + i)->Is(BOUNDARY) && NodeNeighboursIds[(nodes_begin + i)->Id()] != 0)
853  {
854  BoundaryNodes.push_back(*(nodes_begin + i).base());
855  }
856  }
857  }
858 
859  ComputeBoundaryShrinkage<Condition>(BoundaryNodes, Neighbours, NodeNeighboursIds, dimension);
860  }
861  }
862  else if (rModelPart.NumberOfElements() && this->CheckElementsLocalSpace(rModelPart, dimension - 1))
863  {
864 
865  if (mEchoLevel > 0)
866  std::cout << " [" << rModelPart.Name() << "] (E) " << std::endl;
867 
868  // add the neighbour boundary elements to all the nodes in the mesh
869  ModelPart::ElementsContainerType &rElements = rModelPart.Elements();
870 
871  std::vector<ElementWeakPtrVectorType> Neighbours(rNodes.size() + 1);
872 
873  unsigned int id = 1;
874  for (auto i_elem(rElements.begin()); i_elem != rElements.end(); ++i_elem)
875  {
876  if (i_elem->IsNot(CONTACT) && i_elem->Is(BOUNDARY))
877  {
878 
879  Condition::GeometryType &rGeometry = i_elem->GetGeometry();
880 
881  if (mEchoLevel > 2)
882  std::cout << " Element ID " << i_elem->Id() << " id " << id << std::endl;
883 
884  for (unsigned int i = 0; i < rGeometry.size(); ++i)
885  {
886  if (mEchoLevel > 2)
887  {
888  if (NodeNeighboursIds.size() <= rGeometry[i].Id())
889  std::cout << " Shrink node in geom " << rGeometry[i].Id() << " number of nodes " << NodeNeighboursIds.size() << " Ids[id] " << NodeNeighboursIds[rGeometry[i].Id()] << std::endl;
890  }
891 
892  if (NodeNeighboursIds[rGeometry[i].Id()] == 0)
893  {
894  NodeNeighboursIds[rGeometry[i].Id()] = id;
895  Neighbours[id].push_back(*i_elem.base());
896  id++;
897  }
898  else
899  {
900  Neighbours[NodeNeighboursIds[rGeometry[i].Id()]].push_back(*i_elem.base());
901  }
902  }
903  }
904  }
905 
906  //**********Set Boundary Nodes Only
907  if (id > 1)
908  {
909  ModelPart::NodesContainerType::iterator nodes_begin = rNodes.begin();
910  ModelPart::NodesContainerType BoundaryNodes;
911 
912  for (unsigned int i = 0; i < rNodes.size(); ++i)
913  {
914  if ((nodes_begin + i)->Is(BOUNDARY) && NodeNeighboursIds[(nodes_begin + i)->Id()] != 0)
915  {
916  BoundaryNodes.push_back(*((nodes_begin + i).base()));
917  }
918  }
919 
920  ComputeBoundaryShrinkage<Element>(BoundaryNodes, Neighbours, NodeNeighboursIds, dimension);
921  }
922  }
923 
924  KRATOS_CATCH("")
925  }
926 
927  //**************************************************************************
928  //**************************************************************************
929 
930  template <class TClassType>
931  void ComputeBoundaryShrinkage(ModelPart::NodesContainerType &rNodes, const std::vector<GlobalPointersVector<TClassType>> &rNeighbours, const std::vector<int> &rNodeNeighboursIds, const unsigned int &dimension)
932  {
933  KRATOS_TRY
934 
935  //********** Construct the normals in order to have a good direction and length for applying a contraction
936  ModelPart::NodesContainerType::iterator NodesBegin = rNodes.begin();
937  int NumberOfNodes = rNodes.size();
938 
939  int not_assigned = 0;
940 
941 #pragma omp parallel for reduction(+ \
942  : not_assigned)
943  for (int pn = 0; pn < NumberOfNodes; ++pn)
944  {
945  ModelPart::NodesContainerType::iterator iNode = NodesBegin + pn;
946  unsigned int Id = rNodeNeighboursIds[(iNode)->Id()];
947 
948  double MeanCosinus = 0;
949 
950  // are integer values that will be used as quotients
951  double TotalFaces = 0;
952  double ProjectionValue = 0;
953  double NumberOfNormals = 0;
954 
955  int SingleFaces = 0;
956  int TipAcuteAngles = 0;
957 
958  array_1d<double, 3> &rNormal = (iNode)->FastGetSolutionStepValue(NORMAL);
959  double &rShrinkFactor = (iNode)->FastGetSolutionStepValue(SHRINK_FACTOR);
960 
961  // Initialize
962  unsigned int NumberOfNeighbourNormals = rNeighbours[Id].size();
963  if (NumberOfNeighbourNormals != 0)
964  {
965  noalias(rNormal) = ZeroVector(3);
966  rShrinkFactor = 0;
967  }
968 
969  if (mEchoLevel > 1)
970  {
971 
972  std::cout << " Id " << Id << " normals size " << NumberOfNeighbourNormals << " normal " << rNormal << " shrink " << rShrinkFactor << std::endl;
973  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
974  {
975  std::cout << " normal [" << i_norm << "][" << (iNode)->Id() << "]: " << rNeighbours[Id][i_norm].GetValue(NORMAL) << std::endl;
976  }
977  }
978 
979  Vector FaceNormals(NumberOfNeighbourNormals);
980  noalias(FaceNormals) = ZeroVector(NumberOfNeighbourNormals);
981  Vector TipNormals(NumberOfNeighbourNormals);
982  noalias(TipNormals) = ZeroVector(NumberOfNeighbourNormals);
983 
984  // Check coincident faces-normals
985  // Boundary normal is the reference normal:
986  // Neighbour normals : FaceNormals[i] = 0 (not coincident and not similar normal) 1 (coincident) 2 (similar) -> other(quotient or similar normals)
987  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
988  {
989 
990  const array_1d<double, 3> &rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions-elements
991 
992  if (FaceNormals[i_norm] != 1)
993  { // if is not marked as coincident
994 
995  double CloseProjection = 0;
996  for (unsigned int j_norm = i_norm + 1; j_norm < NumberOfNeighbourNormals; ++j_norm) // loop over node neighbour faces
997  {
998 
999  const array_1d<double, 3> &rNormalVector = rNeighbours[Id][j_norm].GetValue(NORMAL); // conditions-elements
1000 
1001  ProjectionValue = inner_prod(rEntityNormal, rNormalVector);
1002 
1003  if (FaceNormals[j_norm] == 0)
1004  { // in order to not have coincident normals
1005  // coincident normal
1006  if (ProjectionValue > 0.995)
1007  {
1008  FaceNormals[j_norm] = 1;
1009  }
1010  // close normal
1011  else if (ProjectionValue > 0.955)
1012  {
1013  CloseProjection += 1;
1014  FaceNormals[j_norm] = 2;
1015  FaceNormals[i_norm] = 2;
1016  }
1017  }
1018 
1019  if (ProjectionValue < -0.005)
1020  {
1021  TipAcuteAngles += 1;
1022  TipNormals[j_norm] += 1;
1023  TipNormals[i_norm] += 1;
1024  }
1025 
1026  } // end for the j_norm for
1027 
1028  for (unsigned int j_norm = i_norm; j_norm < NumberOfNeighbourNormals; ++j_norm) // loop over node neighbour faces
1029  {
1030  if (FaceNormals[j_norm] == 2 && CloseProjection > 0)
1031  FaceNormals[j_norm] = (1.0 / (CloseProjection + 1));
1032  }
1033 
1034  if (FaceNormals[i_norm] != 0)
1035  { // it is assigned
1036  rNormal += rEntityNormal * FaceNormals[i_norm]; // outer normal
1037  NumberOfNormals += FaceNormals[i_norm];
1038  }
1039  else
1040  {
1041  rNormal += rEntityNormal; // outer normal
1042  NumberOfNormals += 1;
1043  }
1044 
1045  TotalFaces += 1;
1046  }
1047  }
1048 
1049  // Modify direction of tip normals in 3D --------- start ----------
1050 
1051  if (dimension == 3 && NumberOfNormals >= 3 && TipAcuteAngles > 0)
1052  {
1053 
1054  std::vector<array_1d<double, 3>> NormalsTriad(3);
1055  SingleFaces = 0;
1056 
1057  if (NumberOfNormals == 3)
1058  { // Deterministic solution when there are 3 no-coplanar planes
1059 
1060  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
1061  {
1062  if (TipNormals[i_norm] >= 1 && FaceNormals[i_norm] == 0)
1063  { // tip normal and no coincident, no similar face normal
1064 
1065  const array_1d<double, 3> &rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1066  NormalsTriad[SingleFaces] = rEntityNormal;
1067  SingleFaces += 1;
1068  }
1069  }
1070  }
1071  else if (NumberOfNormals > 3)
1072  { // Reduction to the deterministic solution with 3 planes
1073 
1074  std::vector<int> SignificativeNormals(NumberOfNeighbourNormals);
1075  std::fill(SignificativeNormals.begin(), SignificativeNormals.end(), -1);
1076 
1077  double MaxProjection = 0;
1078  double Projection = 0;
1079 
1080  // get the positive largest projection between planes
1081  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
1082  {
1083  MaxProjection = std::numeric_limits<double>::min();
1084 
1085  if (TipNormals[i_norm] >= 1 && FaceNormals[i_norm] != 1)
1086  { // tip normal and no coincident face normal
1087 
1088  const array_1d<double, 3> &rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1089 
1090  for (unsigned int j_norm = 0; j_norm < NumberOfNeighbourNormals; ++j_norm) // loop over node neighbour faces to check the most coplanar ones
1091  {
1092  if (TipNormals[j_norm] >= 1 && FaceNormals[j_norm] != 1 && i_norm != j_norm)
1093  { // tip normal and no coincident face normal
1094 
1095  const array_1d<double, 3> &rNormalVector = rNeighbours[Id][j_norm].GetValue(NORMAL); // conditions
1096  Projection = inner_prod(rEntityNormal, rNormalVector);
1097 
1098  if (MaxProjection < Projection && Projection > 0.3)
1099  { // most coplanar normals with a projection largest than 0.3
1100  MaxProjection = Projection;
1101  SignificativeNormals[i_norm] = j_norm; // set in SignificativeNormals
1102  }
1103  }
1104  }
1105  }
1106  }
1107 
1108  // std::cout<<" SignificativeNormals [ ";
1109  // for(unsigned int i_norm=0;i_norm<NumberOfNeighbourNormals;++i_norm)//loop over node neighbour faces
1110  // {
1111  // std::cout <<SignificativeNormals[i_norm] <<" ";
1112  // }
1113  // std::cout<<"]"<<std::endl;
1114  // std::cout<<" Face: "<<FaceNormals<<" Tip: "<<TipNormals<<" Id: "<<(iNode)->Id()<<" NumberOfNormals "<<NumberOfNormals<<" SingleFaces "<<SingleFaces<<std::endl;
1115 
1116  // get the most obtuse planes normals
1117  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
1118  {
1119 
1120  if (SingleFaces < 3)
1121  {
1122 
1123  if (TipNormals[i_norm] >= 1 && FaceNormals[i_norm] != 1)
1124  { // tip normal and no coincident face normal
1125 
1126  array_1d<double, 3> EntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1127 
1128  if (FaceNormals[i_norm] != 0) // similar face normal
1129  EntityNormal *= FaceNormals[i_norm];
1130 
1131  for (unsigned int j_norm = i_norm + 1; j_norm < NumberOfNeighbourNormals; ++j_norm) // loop over node neighbour faces to check the most obtuse planes
1132  {
1133  if (TipNormals[j_norm] >= 1 && FaceNormals[j_norm] != 1)
1134  { // tip normal and no coincident face normal
1135 
1136  if (i_norm == (unsigned int)SignificativeNormals[j_norm])
1137  { // i_norm is a significative normal with a close coincident projection
1138 
1139  const array_1d<double, 3> &rNormalVector = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1140 
1141  if (FaceNormals[i_norm] != 0)
1142  { // similar face normal
1143  EntityNormal += rNormalVector * FaceNormals[i_norm]; // product with the quotient
1144  }
1145  else
1146  {
1147  EntityNormal += rNormalVector;
1148  }
1149 
1150  if (norm_2(EntityNormal) != 0)
1151  EntityNormal = EntityNormal / norm_2(EntityNormal);
1152 
1153  FaceNormals[j_norm] = 1; // mark as coincident in order to not use this plane again
1154  }
1155  }
1156  }
1157 
1158  NormalsTriad[SingleFaces] = EntityNormal;
1159  ++SingleFaces;
1160  }
1161  }
1162  }
1163  }
1164 
1165  if (SingleFaces < 3)
1166  {
1167 
1168  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
1169  {
1170  if (SingleFaces == 3)
1171  break;
1172 
1173  if (TipNormals[i_norm] >= 1 && FaceNormals[i_norm] != 0 && FaceNormals[i_norm] != 1)
1174  { // tip normal and similar face normal
1175  const array_1d<double, 3> &rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1176  NormalsTriad[SingleFaces] = rEntityNormal;
1177  ++SingleFaces;
1178  }
1179 
1180  if (TipNormals[i_norm] == 0 && FaceNormals[i_norm] == 0 && SingleFaces > 0)
1181  { // if only two of the tip normals are acute one is not set
1182  const array_1d<double, 3> &rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1183  NormalsTriad[SingleFaces] = rEntityNormal;
1184  ++SingleFaces;
1185  }
1186  }
1187  }
1188 
1189  if (SingleFaces == 2)
1190  {
1191 
1192  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neighbour faces
1193  {
1194  if (SingleFaces == 3)
1195  break;
1196 
1197  if (TipNormals[i_norm] == 0 && FaceNormals[i_norm] != 0 && FaceNormals[i_norm] != 1 && SingleFaces > 0)
1198  { // if only two of the tip normals are acute one is not set
1199  NormalsTriad[SingleFaces] = rNormal;
1200  ++SingleFaces;
1201  }
1202  }
1203  }
1204 
1205  if (SingleFaces == 3)
1206  {
1207 
1208  array_1d<double, 3> CrossProductN;
1209  MathUtils<double>::CrossProduct(CrossProductN, NormalsTriad[1], NormalsTriad[2]);
1210  double Projection = inner_prod(NormalsTriad[0], CrossProductN);
1211 
1212  if (fabs(Projection) > 1e-15)
1213  {
1214  rNormal = CrossProductN;
1215  MathUtils<double>::CrossProduct(CrossProductN, NormalsTriad[2], NormalsTriad[0]);
1216  rNormal += CrossProductN;
1217  MathUtils<double>::CrossProduct(CrossProductN, NormalsTriad[0], NormalsTriad[1]);
1218  rNormal += CrossProductN;
1219 
1220  rNormal /= Projection; // intersection of three planes
1221  }
1222  else
1223  {
1224  rNormal = 0.5 * (NormalsTriad[1] + NormalsTriad[2]);
1225  // std::cout<<" Projection of the THREE planes value "<<Projection<<" Id: "<<(iNode)->Id()<<std::endl;
1226  // std::cout<<" Face: "<<FaceNormals<<" Tip: "<<TipNormals<<" Id: "<<(iNode)->Id()<<" NumberOfNormals "<<NumberOfNormals<<" SingleFaces "<<SingleFaces<<" Normals: "<<NormalsTriad[0]<<" "<<NormalsTriad[1]<<" "<<NormalsTriad[2]<<std::endl;
1227  }
1228  }
1229  else if (SingleFaces == 2)
1230  {
1231  rNormal = 0.5 * (NormalsTriad[0] + NormalsTriad[1]);
1232  // std::cout<<" WARNING something was wrong in normal calculation Triad Not found" <<std::endl;
1233  // std::cout<<" Face: "<<FaceNormals<<" Tip: "<<TipNormals<<" Id: "<<(iNode)->Id()<<" NumberOfNormals "<<NumberOfNormals<<" SingleFaces "<<SingleFaces<<std::endl;
1234  }
1235  else
1236  {
1237  std::cout << " WARNING something was wrong in normal calculation Triad Not found" << std::endl;
1238  std::cout << " Face: " << FaceNormals << " Tip: " << TipNormals << " Id: " << (iNode)->Id() << " NumberOfNormals " << NumberOfNormals << " SingleFaces " << SingleFaces << std::endl;
1239  }
1240 
1241  // Check Boundary
1242  if (norm_2(rNormal) > 2)
1243  { // not an attractive solution but needed to ensure consistency
1244  rNormal = rNormal / norm_2(rNormal);
1245  rNormal *= 1.2;
1246  }
1247 
1248  // Check inconsistencies
1249  // unsigned int inverted = 0;
1250  // for (unsigned int i_norm=0;i_norm<NumberOfNeighbourNormals;++i_norm)//loop over node neighbour faces
1251  // {
1252  // const array_1d<double,3>& rEntityNormal = rNeighbours[Id][i_norm]->GetValue(NORMAL); //conditions
1253  // if( inner_prod(rEntityNormal,rNormal) < 0 )
1254  // ++inverted;
1255  // }
1256 
1257  // if( inverted == NumberOfNeighbourNormals )
1258  // std::cout<<" DIRECTION NEGATIVE "<<rNormal<<" Id: "<<(iNode)->Id()<<std::endl;
1259 
1260  // if( norm_2(rNormal) < 1e-5 )
1261  // std::cout<<" ZERO NORMAL "<<rNormal<<" Id: "<<(iNode)->Id()<<std::endl;
1262 
1263  // Modify direction of tip normals in 3D ----------- end -----------
1264  }
1265  else
1266  {
1267 
1268  if (norm_2(rNormal) != 0)
1269  rNormal = rNormal / norm_2(rNormal);
1270 
1271  for (unsigned int i_norm = 0; i_norm < NumberOfNeighbourNormals; ++i_norm) // loop over node neigbour faces
1272  {
1273  if (FaceNormals[i_norm] != 1)
1274  { // not coincident normal
1275 
1276  array_1d<double, 3> rEntityNormal = rNeighbours[Id][i_norm].GetValue(NORMAL); // conditions
1277 
1278  if (norm_2(rEntityNormal))
1279  rEntityNormal /= norm_2(rEntityNormal);
1280 
1281  ProjectionValue = inner_prod(rEntityNormal, rNormal);
1282 
1283  MeanCosinus += ProjectionValue;
1284  }
1285  }
1286 
1287  if (TotalFaces != 0)
1288  MeanCosinus *= (1.0 / TotalFaces);
1289 
1290  // acute angles are problematic, reduction of the modulus in that cases
1291  if (MeanCosinus <= 0.3)
1292  {
1293  MeanCosinus = 0.8;
1294  }
1295 
1296  if (MeanCosinus > 3)
1297  std::cout << " WARNING WRONG MeanCosinus " << MeanCosinus << std::endl;
1298 
1299  if (MeanCosinus != 0 && MeanCosinus > 1e-3)
1300  { // to ensure consistency
1301  MeanCosinus = 1.0 / MeanCosinus;
1302  rNormal *= MeanCosinus; // only to put the correct length
1303  }
1304  else
1305  {
1306  std::cout << " Mean Cosinus not consistent " << MeanCosinus << " [" << (iNode)->Id() << "] rNormal " << rNormal[0] << " " << rNormal[1] << " " << rNormal[2] << std::endl;
1307  }
1308  }
1309 
1310  // Now Normalize Normal and store the Shrink_Factor
1311  rShrinkFactor = norm_2(rNormal);
1312 
1313  if (rShrinkFactor != 0)
1314  {
1315  if (mEchoLevel > 1)
1316  std::cout << "[Id " << (iNode)->Id() << " shrink_factor " << rShrinkFactor << " Normal " << rNormal[0] << " " << rNormal[1] << " " << rNormal[2] << " MeanCosinus " << MeanCosinus << "] shrink " << std::endl;
1317  rNormal /= rShrinkFactor;
1318  }
1319  else
1320  {
1321 
1322  if (mEchoLevel > 1)
1323  std::cout << "[Id " << (iNode)->Id() << " Normal " << rNormal[0] << " " << rNormal[1] << " " << rNormal[2] << " MeanCosinus " << MeanCosinus << "] no shrink " << std::endl;
1324 
1325  noalias(rNormal) = ZeroVector(3);
1326  rShrinkFactor = 1;
1327 
1328  ++not_assigned;
1329  }
1330  }
1331 
1332  if (mEchoLevel > 0)
1333  std::cout << " [NORMALS SHRINKAGE (BOUNDARY NODES:" << NumberOfNodes << ") [SET:" << NumberOfNodes - not_assigned << " / NOT_SET:" << not_assigned << "] " << std::endl;
1334 
1335  KRATOS_CATCH("")
1336  }
1337 
1338  // template<class TClassType>
1339  // void ComputeBoundaryShrinkage(ModelPart::NodesContainerType& rNodes, const std::vector<GlobalPointersVector<TClassType> >& rNeighbours, const std::vector<int>& rIds, const unsigned int& dimension )
1340  // {
1341 
1342  // KRATOS_TRY
1343 
1344  // //********** Construct the normals in order to have a good direction and length for applying a contraction
1345  // std::vector<double> storenorm;
1346  // std::vector<double> tipnormal;
1347 
1348  // ModelPart::NodesContainerType::iterator boundary_nodes_begin = rNodes.begin();
1349  // int boundary_nodes = rNodes.size();
1350 
1351  // int not_assigned = 0;
1352 
1353  // int pn=0;
1354  // // #pragma omp parallel for private(pn,storenorm,tipnormal)
1355  // for (pn=0; pn<boundary_nodes; ++pn)
1356  // {
1357 
1358  // double cosmedio=0;
1359  // double totalnorm=0;
1360  // double directiontol=0;
1361  // double numnorm=0;
1362  // int indepnorm=0,acuteangle=0;
1363 
1364  // array_1d<double,3>& Normal=(boundary_nodes_begin + pn)->FastGetSolutionStepValue(NORMAL);
1365  // double& shrink_factor=(boundary_nodes_begin + pn)->FastGetSolutionStepValue(SHRINK_FACTOR);
1366 
1367  // //initialize
1368 
1369  // unsigned int normals_size = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]].size();
1370  // if( normals_size != 0 )
1371  // {
1372  // Normal.clear();
1373  // shrink_factor=0;
1374  // }
1375 
1376  // if( mEchoLevel > 1 ){
1377  // std::cout<<" Id "<<rIds[(boundary_nodes_begin + pn)->Id()]<<" normals size "<<normals_size<<" normal "<<Normal<<" shrink "<<shrink_factor<<std::endl;
1378  // for (unsigned int esnod=0; esnod<normals_size; ++esnod)//loop over node neighbor faces
1379  // {
1380  // std::cout<<" normal ["<<esnod<<"]["<<(boundary_nodes_begin + pn)->Id()<<"]: "<<rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL)<<std::endl;
1381  // }
1382  // }
1383 
1384  // storenorm.resize(normals_size);
1385  // std::fill(storenorm.begin(), storenorm.end(), 0 );
1386 
1387  // tipnormal.resize(normals_size);
1388  // std::fill(tipnormal.begin(), tipnormal.end(), 0 );
1389 
1390  // //Check coincident faces-normals
1391  // for (unsigned int esnod=0; esnod<normals_size; ++esnod)//loop over node neighbor faces
1392  // {
1393 
1394  // const array_1d<double,3>& AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1395 
1396  // if (storenorm[esnod]!=1){ //if is not marked as coincident
1397 
1398  // if (esnod+1<normals_size){
1399 
1400  // double tooclose=0;
1401  // for (unsigned int esn=esnod+1; esn<normals_size; ++esn)//loop over node neighbor faces
1402  // {
1403 
1404  // const array_1d<double,3>& NormalVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esn].GetValue(NORMAL); //conditions
1405 
1406  // directiontol=inner_prod(AuxVector,NormalVector);
1407 
1408  // //std::cout<<" -- > direction tol"<<directiontol<<" AuxVector "<<AuxVector<<" NormalVector "<<NormalVector<<std::endl;
1409 
1410  // if (directiontol>0.995 && storenorm[esn]==0){//to not have coincident normals
1411  // storenorm[esn]=1;
1412  // }
1413  // else{
1414  // if (directiontol>0.95 && directiontol<0.995 && storenorm[esn]==0){//to not have close normals
1415  // tooclose+=1;
1416  // storenorm[esn] =2;
1417  // storenorm[esnod]=2;
1418  // }
1419  // else{
1420  // if(directiontol<-0.005){
1421  // //std::cout<<" acute angle "<<directiontol<<std::endl;
1422  // acuteangle +=1;
1423  // tipnormal[esn] +=1;
1424  // tipnormal[esnod]+=1;
1425  // }
1426  // }
1427  // }
1428 
1429  // }//end for the esnod for
1430 
1431  // for (unsigned int esn=esnod; esn<normals_size; ++esn)//loop over node neighbour faces
1432  // {
1433  // if(storenorm[esn]==2 && tooclose>0)
1434  // storenorm[esn]=(1.0/(tooclose+1));
1435  // }
1436 
1437  // }
1438 
1439  // if(storenorm[esnod]!=0){ //!=1
1440 
1441  // Normal+=AuxVector*storenorm[esnod]; //outer normal
1442  // numnorm +=storenorm[esnod];
1443 
1444  // }
1445  // else{
1446 
1447  // Normal+=AuxVector; //outer normal
1448  // numnorm +=1;
1449 
1450  // }
1451 
1452  // totalnorm+=1;
1453 
1454  // }
1455 
1456  // }
1457 
1458  // //std::cout<<" Normal "<<Normal<<" ID "<<(boundary_nodes_begin + pn)->Id()<<std::endl;
1459 
1460  // //Modify direction of tip normals in 3D --------- start ----------
1461 
1462  // if(dimension==3 && numnorm>=3 && acuteangle){
1463 
1464  // //std::cout<<" pn "<<pn<<" normal number: "<<numnorm<<" acute angles: "<<acuteangle<<std::endl;
1465  // //std::cout<<"storenormal"<<storenorm<<std::endl;
1466  // //std::cout<<"tipnormal"<<tipnormal<<std::endl;
1467 
1468  // std::vector< array_1d<double,3> > N(3);
1469  // indepnorm=0;
1470 
1471  // if(numnorm==3){ //Definite solution for 3 planes
1472 
1473  // for (unsigned int esnod=0;esnod<normals_size;++esnod)//loop over node neighbor faces
1474  // {
1475  // if(tipnormal[esnod]>=1 && storenorm[esnod]==0){ //tip node correction
1476 
1477  // const array_1d<double,3>& AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1478  // N[indepnorm]=AuxVector;
1479  // indepnorm+=1;
1480  // }
1481  // }
1482 
1483  // }
1484  // else{ //I must select only 3 planes
1485 
1486  // double maxprojection=0;
1487  // double projection=0;
1488  // std::vector<int> pronormal(normals_size);
1489  // pronormal.clear();
1490 
1491  // //get the positive biggest projection between planes
1492  // for (unsigned int esnod=0;esnod<normals_size;++esnod)//loop over node neighbor faces
1493  // {
1494  // maxprojection=0;
1495 
1496  // if(tipnormal[esnod]>=1 && storenorm[esnod]!=1){
1497 
1498  // const array_1d<double,3>& AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1499 
1500  // for (unsigned int esn=0;esn<normals_size;++esn)//loop over node neighbor faces to check the most coplanar
1501  // {
1502  // if(tipnormal[esn]>=1 && storenorm[esn]!=1 && esnod!=esn){
1503 
1504  // const array_1d<double,3>& NormalVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esn].GetValue(NORMAL); //conditions
1505  // projection=inner_prod(AuxVector,NormalVector);
1506 
1507  // if(maxprojection<projection && projection>0.5){
1508  // maxprojection=projection;
1509  // pronormal[esnod]=esn+1; //set in pronormal one position added to the real one the most coplanar planes
1510  // }
1511  // }
1512  // }
1513 
1514  // }
1515 
1516  // }
1517 
1518  // // std::cout<<" PROJECTIONS "<<pn<<" pronormal"<<pronormal<<std::endl;
1519 
1520  // //get the most obtuse normals
1521  // for (unsigned int esnod=0;esnod<normals_size;++esnod)//loop over node neighbor faces
1522  // {
1523 
1524  // if(indepnorm<3){
1525 
1526  // if(tipnormal[esnod]>=1 && storenorm[esnod]!=1){ //tip node correction
1527 
1528  // array_1d<double,3> AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1529 
1530  // if(storenorm[esnod]!=0) //!=1
1531  // AuxVector*=storenorm[esnod];
1532 
1533  // for (unsigned int esn=esnod+1;esn<normals_size;++esn)//loop over node neighbor faces to check the most coplanar
1534  // {
1535  // if(tipnormal[esn]>=1 && storenorm[esn]!=1){ //tip node correction
1536 
1537  // if(esnod+1==(unsigned int)pronormal[esn]){
1538 
1539  // const array_1d<double,3>& NormalVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1540 
1541  // if(storenorm[esnod]!=0){ //!=1
1542  // AuxVector+=NormalVector*storenorm[esnod];
1543  // }
1544  // else{
1545  // AuxVector+=NormalVector;
1546  // }
1547  // AuxVector=AuxVector/norm_2(AuxVector);
1548  // //std::cout<<" plane "<<esnod<<" esn "<<esn<<std::endl;
1549  // storenorm[esn]=1; //to not use this plane again
1550  // }
1551  // }
1552 
1553  // }
1554 
1555  // N[indepnorm]=AuxVector;
1556  // indepnorm+=1;
1557 
1558  // }
1559 
1560  // }
1561  // // else{
1562 
1563  // // std::cout<<" pn "<<pn<<" pronormal"<<pronormal<<std::endl;
1564  // // }
1565 
1566  // }
1567 
1568  // }
1569 
1570  // //std::cout<<" indepnorm "<<indepnorm<<std::endl;
1571 
1572  // if(indepnorm<3){
1573 
1574  // for (unsigned int esnod=0;esnod<normals_size;++esnod)//loop over node neighbor faces
1575  // {
1576  // if(indepnorm==3)
1577  // break;
1578 
1579  // if(tipnormal[esnod]>=1 && storenorm[esnod]!=0 && storenorm[esnod]!=1){ //tip node correction
1580  // const array_1d<double,3>& AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1581  // N[indepnorm]=AuxVector;
1582  // indepnorm+=1;
1583  // }
1584 
1585  // if(storenorm[esnod]==0 && tipnormal[esnod]==0 && indepnorm>0){ //if only two of the tip normals are acute one is not stored (corrected here 05/09/2011)
1586  // const array_1d<double,3>& AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1587  // N[indepnorm]=AuxVector;
1588  // indepnorm+=1;
1589  // }
1590 
1591  // }
1592  // }
1593 
1594  // if(indepnorm==3){
1595  // array_1d<double,3> CrossProductN;
1596  // MathUtils<double>::CrossProduct(CrossProductN,N[1],N[2]);
1597  // double aux=inner_prod(N[0],CrossProductN);
1598  // if(aux!=0){
1599  // MathUtils<double>::CrossProduct(CrossProductN,N[1],N[2]);
1600  // Normal = CrossProductN;
1601  // MathUtils<double>::CrossProduct(CrossProductN,N[2],N[0]);
1602  // Normal += CrossProductN;
1603  // MathUtils<double>::CrossProduct(CrossProductN,N[0],N[1]);
1604  // Normal += CrossProductN;
1605  // if( aux > 1e-15 )
1606  // Normal /= aux; //intersection of three planes
1607  // }
1608  // // else{
1609  // // std::cout<<" aux "<<aux<<" Normals :";
1610  // // }
1611 
1612  // }
1613 
1614  // //Check Boundary
1615  // if(norm_2(Normal)>2){ //a bad solution... but too ensure consistency
1616  // //Normal.write(" TO LARGE NORMAL ");
1617  // //std::cout<<" modulus 1 "<<Normal.modulus()<<std::endl;
1618  // Normal=Normal/norm_2(Normal);
1619  // Normal*=1.2;
1620  // //Normal.write(" CORRRECTION ");
1621  // //std::cout<<" modulus 2 "<<Normal.modulus()<<std::endl;
1622  // }
1623 
1624  // //Modify direction of tip normals in 3D ----------- end -----------
1625 
1626  // }
1627  // else{
1628 
1629  // //std::cout<<" Normal "<<Normal<<std::endl;
1630 
1631  // if(norm_2(Normal)!=0)
1632  // Normal=Normal/norm_2(Normal); //normalize normal *this/modulus();
1633 
1634  // for(unsigned int esnod=0;esnod<normals_size;++esnod)//loop over node neigbour faces
1635  // {
1636  // if (storenorm[esnod]!=1){
1637 
1638  // array_1d<double,3> AuxVector = rNeighbours[rIds[(boundary_nodes_begin + pn)->Id()]][esnod].GetValue(NORMAL); //conditions
1639 
1640  // if(norm_2(AuxVector))
1641  // AuxVector/=norm_2(AuxVector);
1642 
1643  // directiontol=inner_prod(AuxVector,Normal);
1644 
1645  // cosmedio+=directiontol;
1646 
1647  // }
1648  // }
1649 
1650  // if (totalnorm!=0)
1651  // cosmedio*=(1.0/totalnorm);
1652 
1653  // //acute angles are problematic, reduction of the modulus in that cases
1654  // if (cosmedio<=0.3){
1655  // cosmedio=0.8;
1656  // //std::cout<<" acute correction "<<std::endl;
1657  // }
1658 
1659  // if(cosmedio>3)
1660  // std::cout<<" cosmedio "<<cosmedio<<std::endl;
1661 
1662  // //if (cosmedio!=0) {
1663  // if (cosmedio!=0 && cosmedio>1e-3) { //to ensure consistency
1664  // cosmedio=1.0/cosmedio;
1665  // Normal*=cosmedio; //only to put the correct length
1666  // //(boundary_nodes_begin + pn)->SetValue(Normal);
1667  // //std::cout<<pn<<" cosmedio "<<cosmedio<<" Normal "<<Normal[0]<<" "<<Normal[1]<<" "<<Normal[2]<<std::endl;
1668  // }
1669  // }
1670 
1671  // //std::cout<<(boundary_nodes_begin + pn)->Id()<<" Normal "<<Normal[0]<<" "<<Normal[1]<<" "<<Normal[2]<<std::endl;
1672 
1673  // //Now Normalize Normal and store the Shrink_Factor
1674  // shrink_factor=norm_2(Normal);
1675 
1676  // if(shrink_factor!=0)
1677  // {
1678  // if( mEchoLevel > 2 )
1679  // std::cout<<"[Id "<<rIds[(boundary_nodes_begin + pn)->Id()]<<" shrink_factor "<<shrink_factor<<" Normal "<<Normal[0]<<" "<<Normal[1]<<" "<<Normal[2]<<" cosmedio "<<cosmedio<<"] shrink "<<std::endl;
1680  // Normal/=shrink_factor;
1681 
1682  // }
1683  // else{
1684 
1685  // if( mEchoLevel > 1 )
1686  // std::cout<<"[Id "<<rIds[(boundary_nodes_begin + pn)->Id()]<<" Normal "<<Normal[0]<<" "<<Normal[1]<<" "<<Normal[2]<<" cosmedio "<<cosmedio<<"] no shrink "<<std::endl;
1687 
1688  // Normal.clear();
1689  // shrink_factor=1;
1690 
1691  // //std::cout<<" ERROR: normal shrinkage calculation failed "<<std::endl;
1692  // not_assigned +=1;
1693  // }
1694 
1695  // }
1696 
1697  // if(mEchoLevel > 0)
1698  // std::cout<<" [NORMALS SHRINKAGE (BOUNDARY NODES:"<<boundary_nodes<<") [SET:"<<boundary_nodes-not_assigned<<" / NOT_SET:"<<not_assigned<<"] "<<std::endl;
1699 
1700  // KRATOS_CATCH( "" )
1701 
1702  // }
1703 
1716 
1717  }; // Class BoundaryNormalsCalculationUtilities
1718 
1720 
1723 
1728 
1729 } // namespace Kratos.
1730 
1731 #endif // KRATOS_BOUNDARY_NORMALS_CALCULATION_UTILITIES_H_INCLUDED defined
Definition: boundary_normals_calculation_utilities.hpp:48
void CalculateUnitBoundaryNormals(ModelPart &rModelPart, int EchoLevel=0)
Calculates the area normal (vector oriented as the normal with a dimension proportional to the area).
Definition: boundary_normals_calculation_utilities.hpp:83
GlobalPointersVector< Node > NodeWeakPtrVectorType
Definition: boundary_normals_calculation_utilities.hpp:58
ModelPart::NodesContainerType NodesArrayType
Definition: boundary_normals_calculation_utilities.hpp:53
ModelPart::MeshType MeshType
Definition: boundary_normals_calculation_utilities.hpp:56
GlobalPointersVector< Condition > ConditionWeakPtrVectorType
Definition: boundary_normals_calculation_utilities.hpp:60
void CalculateWeightedBoundaryNormals(ModelPart &rModelPart, int EchoLevel=0)
Calculates the area normal (unitary vector oriented as the normal) and weight the normal to shrink.
Definition: boundary_normals_calculation_utilities.hpp:123
ModelPart::ElementsContainerType ElementsContainerType
Definition: boundary_normals_calculation_utilities.hpp:54
GlobalPointersVector< Element > ElementWeakPtrVectorType
Definition: boundary_normals_calculation_utilities.hpp:59
ModelPart::ConditionsContainerType ConditionsContainerType
Definition: boundary_normals_calculation_utilities.hpp:55
virtual bool AssembleCurrentData(Variable< int > const &ThisVariable)
Definition: communicator.cpp:502
Geometry< NodeType > GeometryType
definition of the geometry type with given NodeType
Definition: condition.h:83
GeometryData::IntegrationMethod IntegrationMethod
Type definition for integration methods.
Definition: element.h:105
Geometry< NodeType > GeometryType
definition of the geometry type with given NodeType
Definition: element.h:83
std::vector< IntegrationPointType > IntegrationPointsArrayType
Definition: geometry.h:161
GeometryData::ShapeFunctionsGradientsType ShapeFunctionsGradientsType
Definition: geometry.h:189
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
static void InvertMatrix3(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet)
It inverts matrices of order 3.
Definition: math_utils.h:449
static void InvertMatrix2(const TMatrix1 &rInputMatrix, TMatrix2 &rInvertedMatrix, double &rInputMatrixDet)
It inverts matrices of order 2.
Definition: math_utils.h:416
static T CrossProduct(const T &a, const T &b)
Performs the vector product of the two input vectors a,b.
Definition: math_utils.h:762
static BoundedMatrix< double, TDim, TDim > InvertMatrix(const BoundedMatrix< double, TDim, TDim > &rInputMatrix, double &rInputMatrixDet, const double Tolerance=ZeroTolerance)
Calculates the inverse of a 2x2, 3x3 and 4x4 matrices (using bounded matrix for performance)
Definition: math_utils.h:197
static unsigned int GetMaxNodeId(ModelPart &rModelPart)
Definition: mesher_utilities.hpp:1408
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
MeshType::ConditionsContainerType ConditionsContainerType
Condintions container. A vector set of Conditions with their Id's as key.
Definition: model_part.h:183
bool IsSubModelPart() const
Definition: model_part.h:1893
MeshType::ElementsContainerType ElementsContainerType
Element container. A vector set of Elements with their Id's as key.
Definition: model_part.h:168
Communicator & GetCommunicator()
Definition: model_part.h:1821
std::string & Name()
Definition: model_part.h:1811
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
SizeType NumberOfElements(IndexType ThisIndex=0) const
Definition: model_part.h:1027
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
SubModelPartsContainerType & SubModelParts()
Definition: model_part.h:1718
SizeType NumberOfConditions(IndexType ThisIndex=0) const
Definition: model_part.h:1218
void push_back(TPointerType x)
Adds a pointer to the end of the set.
Definition: pointer_vector_set.h:544
iterator begin()
Returns an iterator pointing to the beginning of the container.
Definition: pointer_vector_set.h:278
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
static int EchoLevel
Definition: co_sim_EMPIRE_API.h:42
static double min(double a, double b)
Definition: GeometryFunctions.h:71
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
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
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
list coeff
Definition: bombardelli_test.py:41
pn
Definition: generate_droplet_dynamics.py:65
int dimension
Definition: isotropic_damage_automatic_differentiation.py:123
int d
Definition: ode_solve.py:397
J
Definition: sensitivityMatrix.py:58
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31