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.
select_mesh_elements_for_fluids_process.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosPfemFluidDynamicsApplication $
3 // Created by: $Author: AFranci $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: October 2016 $
6 // Revision: $Revision: 0.0 $
7 //
8 //
9 
10 #if !defined(KRATOS_SELECT_MESH_ELEMENTS_FOR_FLUIDS_PROCESS_H_INCLUDED)
11 #define KRATOS_SELECT_MESH_ELEMENTS_FOR_FLUIDS_PROCESS_H_INCLUDED
12 
13 // External includes
14 
15 // System includes
16 
17 // Project includes
20 
21 #include "includes/model_part.h"
28 
30 // Data:
31 // Flags: (checked) TO_ERASE, BOUNDARY, NEW_ENTITY
32 // (set)
33 // (modified)
34 // (reset)
35 //(set):=(set in this process)
36 
37 namespace Kratos
38 {
39 
42 
44 
49  : public MesherProcess
50  {
51  public:
54 
57 
62  typedef std::size_t SizeType;
66 
69  MesherUtilities::MeshingParameters &rRemeshingParameters,
70  int EchoLevel)
71  : mrModelPart(rModelPart),
72  mrRemesh(rRemeshingParameters)
73  {
74  mEchoLevel = EchoLevel;
75  }
76 
79 
83 
85  void operator()()
86  {
87  Execute();
88  }
89 
93 
95  void Execute() override
96  {
98 
99  if (mEchoLevel > 1)
100  {
101  std::cout << " [ SELECT MESH ELEMENTS in PfemFluid: (" << mrRemesh.OutMesh.GetNumberOfElements() << ") " << std::endl;
102  std::cout << "MODEL PART InNumberOfElements " << mrRemesh.InMesh.GetNumberOfElements() << std::endl;
103  std::cout << "MODEL PART InNumberOfPoints " << mrRemesh.InMesh.GetNumberOfPoints() << std::endl;
104  std::cout << "MODEL PART OutNumberOfElements " << mrRemesh.OutMesh.GetNumberOfElements() << std::endl;
105  std::cout << "MODEL PART OutNumberOfPoints " << mrRemesh.OutMesh.GetNumberOfPoints() << std::endl;
106  }
107  const int &OutNumberOfElements = mrRemesh.OutMesh.GetNumberOfElements();
108  mrRemesh.PreservedElements.clear();
109  mrRemesh.PreservedElements.resize(OutNumberOfElements, false);
110  std::fill(mrRemesh.PreservedElements.begin(), mrRemesh.PreservedElements.end(), 0);
111  mrRemesh.MeshElementsSelectedFlag = true;
112 
113  MesherUtilities MesherUtils;
114  double ModelPartVolume = MesherUtils.ComputeModelPartVolume(mrModelPart);
115  double CriticalVolume = 0.05 * ModelPartVolume / double(mrModelPart.Elements().size());
116 
117  mrRemesh.Info->NumberOfElements = 0;
118 
119  const ProcessInfo &rCurrentProcessInfo = mrModelPart.GetProcessInfo();
120  double currentTime = rCurrentProcessInfo[TIME];
121  double timeInterval = rCurrentProcessInfo[DELTA_TIME];
122  bool box_side_element = false;
123  bool wrong_added_node = false;
124  int number_of_slivers = 0;
125 
126  bool refiningBox = false;
127  for (SizeType index = 0; index < mrRemesh.UseRefiningBox.size(); index++)
128  {
129  if (mrRemesh.UseRefiningBox[index] == true && currentTime > mrRemesh.RefiningBoxInitialTime[index] && currentTime < mrRemesh.RefiningBoxFinalTime[index])
130  {
131  refiningBox = true;
132  }
133  }
134 
135  if (mrRemesh.ExecutionOptions.IsNot(MesherUtilities::SELECT_TESSELLATION_ELEMENTS))
136  {
137  for (int el = 0; el < OutNumberOfElements; el++)
138  {
139  mrRemesh.PreservedElements[el] = 1;
140  mrRemesh.Info->NumberOfElements += 1;
141  }
142  }
143  else
144  {
145  if (mEchoLevel > 1)
146  std::cout << " Start Element Selection " << OutNumberOfElements << std::endl;
147 
148  ModelPart::ElementsContainerType::iterator element_begin = mrModelPart.ElementsBegin();
149  const SizeType nds = element_begin->GetGeometry().size();
150  const SizeType dimension = element_begin->GetGeometry().WorkingSpaceDimension();
151  int *OutElementList = mrRemesh.OutMesh.GetElementList();
152  ModelPart::NodesContainerType &rNodes = mrModelPart.Nodes();
153 
154  int el = 0;
155  int number = 0;
156 
157  // #pragma omp parallel for reduction(+:number) private(el)
158  for (el = 0; el < OutNumberOfElements; el++)
159  {
160  Geometry<Node> vertices;
161  double meanMeshSize = mrRemesh.Refine->CriticalRadius; // this must be inside because if there is a refined zone, each element has a different critical radius
162  SizeType numfreesurf = 0;
163  SizeType numboundary = 0;
164  SizeType numrigid = 0;
165  SizeType numInletNodes = 0;
166  SizeType numisolated = 0;
167  bool noremesh = false;
168  std::vector<double> normVelocityP;
169  normVelocityP.resize(nds, false);
170  SizeType checkedNodes = 0;
171  box_side_element = false;
172  SizeType countIsolatedWallNodes = 0;
173  bool increaseAlfa = false;
174  SizeType previouslyFreeSurfaceNodes = 0;
175  SizeType previouslyIsolatedNodes = 0;
176  SizeType sumPreviouslyIsolatedFreeSurf = 0;
177  SizeType sumIsolatedFreeSurf = 0;
178  std::vector<array_1d<double, 3>> nodesCoordinates;
179  nodesCoordinates.resize(nds);
180  std::vector<array_1d<double, 3>> nodesVelocities;
181  nodesVelocities.resize(nds);
182  SizeType isolatedNodesInTheElement = 0;
183  double rigidNodeLocalMeshSize = 0;
184  double rigidNodeMeshCounter = 0;
185 
186  for (SizeType pn = 0; pn < nds; pn++)
187  {
188  if (OutElementList[el * nds + pn] <= 0)
189  std::cout << " ERROR: something is wrong: nodal id < 0 " << el << std::endl;
190 
191  if ((SizeType)OutElementList[el * nds + pn] > mrRemesh.NodalPreIds.size())
192  {
193  wrong_added_node = true;
194  std::cout << " ERROR: something is wrong: node out of bounds " << std::endl;
195  break;
196  }
197  vertices.push_back(rNodes(OutElementList[el * nds + pn]));
198 
199  if (vertices.back().IsNot(RIGID) && vertices.back().IsNot(SOLID))
200  {
201  isolatedNodesInTheElement += vertices.back().FastGetSolutionStepValue(ISOLATED_NODE);
202  }
203  // check flags on nodes
204  if (vertices.back().Is(ISOLATED))
205  {
206  numisolated++;
207  }
208  if (vertices.back().Is(PFEMFlags::PREVIOUS_FREESURFACE))
209  {
210  previouslyFreeSurfaceNodes++;
211  }
212  if (vertices.back().Is(PFEMFlags::PREVIOUS_ISOLATED))
213  {
214  previouslyIsolatedNodes++;
215  }
216  if (vertices.back().Is(BOUNDARY))
217  {
218  numboundary++;
219  }
220  if (vertices.back().GetValue(NO_MESH))
221  {
222  noremesh = true;
223  }
224 
225  if (vertices.back().Is(RIGID) || vertices.back().Is(SOLID))
226  {
227  if (vertices.back().Is(RIGID))
228  {
229  rigidNodeLocalMeshSize += vertices.back().FastGetSolutionStepValue(NODAL_H_WALL);
230  rigidNodeMeshCounter += 1.0;
231  }
232 
233  numrigid++;
234 
235  NodeWeakPtrVectorType &rN = vertices.back().GetValue(NEIGHBOUR_NODES);
236  bool localIsolatedWallNode = true;
237  for (SizeType i = 0; i < rN.size(); i++)
238  {
239  if (rN[i].IsNot(RIGID))
240  {
241  localIsolatedWallNode = false;
242  }
243  }
244  if (localIsolatedWallNode == true)
245  {
246  countIsolatedWallNodes++;
247  }
248  }
249 
250  if (vertices.back().IsNot(RIGID) && vertices.back().Is(BOUNDARY))
251  {
252  numfreesurf++;
253  const array_1d<double, 3> &velocityP0 = vertices.back().FastGetSolutionStepValue(VELOCITY, 0);
254  normVelocityP[pn] = norm_2(velocityP0);
255  nodesVelocities[pn] = velocityP0;
256  checkedNodes++;
257  }
258  else if (vertices.back().Is(ISOLATED))
259  {
260  const array_1d<double, 3> &velocityP0 = vertices.back().FastGetSolutionStepValue(VELOCITY, 0);
261  normVelocityP[pn] = norm_2(velocityP0);
262  nodesVelocities[pn] = velocityP0;
263  checkedNodes++;
264  }
265  if (vertices.back().Is(INLET))
266  {
267  numInletNodes++;
268  }
269 
270  if (refiningBox == true && vertices.back().IsNot(RIGID))
271  {
272  if (dimension == 2)
273  {
274  MesherUtils.DefineMeshSizeInTransitionZones2D(mrRemesh, currentTime, vertices.back().Coordinates(), meanMeshSize, increaseAlfa);
275  }
276  else if (dimension == 3)
277  {
278  MesherUtils.DefineMeshSizeInTransitionZones3D(mrRemesh, currentTime, vertices.back().Coordinates(), meanMeshSize, increaseAlfa);
279  }
280  CriticalVolume = 0.05 * (std::pow(meanMeshSize, 3) / (6.0 * std::sqrt(2)));
281  }
282 
283  if (dimension == 3)
284  {
285  nodesCoordinates[pn] = vertices.back().Coordinates();
286  }
287  }
288 
289  if (box_side_element || wrong_added_node)
290  {
291  std::cout << " ,,,,,,,,,,,,,,,,,,,,,,,,,,,,, Box_Side_Element " << std::endl;
292  continue;
293  }
294 
295  double Alpha = mrRemesh.AlphaParameter; //*nds;
296 
297  if (rigidNodeMeshCounter > 0)
298  {
299  const double rigidWallMeshSize = rigidNodeLocalMeshSize / rigidNodeMeshCounter;
300  const double ratio = rigidWallMeshSize / meanMeshSize;
301  double tolerance = 1.8;
302  if (currentTime < 10 * timeInterval)
303  {
304  tolerance = 1.5;
305  }
306  if (ratio > tolerance && numfreesurf == 0 && previouslyFreeSurfaceNodes == 0)
307  {
308  meanMeshSize *= 0.5;
309  meanMeshSize += 0.5 * rigidWallMeshSize;
310  }
311  }
312 
313  if (refiningBox == true)
314  {
315  IncreaseAlphaForRefininedZones(Alpha, increaseAlfa, nds, numfreesurf, numrigid, numisolated);
316  }
317 
318  sumIsolatedFreeSurf = numisolated + numfreesurf;
319  sumPreviouslyIsolatedFreeSurf = previouslyFreeSurfaceNodes + previouslyIsolatedNodes;
320 
321  if (dimension == 2)
322  {
323  if (numrigid == 0 && numfreesurf == 0 && numisolated == 0 && previouslyIsolatedNodes == 0 && previouslyFreeSurfaceNodes == 0)
324  {
325  Alpha *= 1.5;
326  }
327  else if (numfreesurf == 0 && numisolated == 0 && previouslyIsolatedNodes == 0 && previouslyFreeSurfaceNodes == 0)
328  {
329  Alpha *= 1.25;
330  }
331  else if (numisolated == 0 && previouslyIsolatedNodes == 0 && numfreesurf < nds && previouslyFreeSurfaceNodes < nds)
332  {
333  Alpha *= 1.125;
334  }
335  else
336  {
337  Alpha *= 0.975;
338  }
339  }
340  else if (dimension == 3)
341  {
342  if (numrigid == 0 && numfreesurf == 0 && numisolated == 0 && previouslyIsolatedNodes == 0 && previouslyFreeSurfaceNodes == 0)
343  {
344  Alpha *= 1.5;
345  }
346  else if (numfreesurf == 0 && numisolated == 0 && previouslyIsolatedNodes == 0 && previouslyFreeSurfaceNodes == 0)
347  {
348  Alpha *= 1.25;
349  }
350  else if (numisolated == 0 && previouslyIsolatedNodes == 0 && numfreesurf < nds && previouslyFreeSurfaceNodes < nds)
351  {
352  Alpha *= 1.05;
353  }
354  else
355  {
356  Alpha *= 0.95;
357  }
358 
359  if (numrigid == nds)
360  {
361  Alpha *= 0.95;
362  }
363  if (mrRemesh.ExecutionOptions.Is(MesherUtilities::REFINE_WALL_CORNER))
364  {
365  if (numrigid == 3 && numfreesurf == 0 && numisolated == 0)
366  {
367  Alpha *= 1.1;
368  }
369  if (numrigid == 2 && numfreesurf == 0 && numisolated == 0)
370  {
371  Alpha *= 1.05;
372  }
373  }
374  }
375 
376  if (numInletNodes > 0)
377  {
378  Alpha *= 1.5;
379  }
380 
381  bool accepted = false;
382 
383  accepted = MesherUtils.AlphaShape(Alpha, vertices, dimension, meanMeshSize);
384 
385  if (numrigid == nds || noremesh == true)
386  {
387  accepted = false;
388  }
389 
390  if (accepted == true && (numfreesurf == nds || sumIsolatedFreeSurf == nds || sumPreviouslyIsolatedFreeSurf == nds))
391  {
392  if (dimension == 2)
393  {
394  // this is to avoid the formation of isolated elements with different velocity fields. They can give convergence problems
395  if ((numfreesurf == nds || sumIsolatedFreeSurf == nds) && numrigid == 0)
396  {
397  if (checkedNodes == nds)
398  {
399  const double maxValue = 1.5;
400  const double minValue = 1.0 / maxValue;
401  if (normVelocityP[0] / normVelocityP[1] > maxValue || normVelocityP[0] / normVelocityP[1] < minValue ||
402  normVelocityP[0] / normVelocityP[2] > maxValue || normVelocityP[0] / normVelocityP[2] < minValue ||
403  normVelocityP[1] / normVelocityP[2] > maxValue || normVelocityP[1] / normVelocityP[2] < minValue)
404  {
405  accepted = false;
406  }
407  else
408  {
409  const double cosAngle01 = (nodesVelocities[0][0] * nodesVelocities[1][0] + nodesVelocities[0][1] * nodesVelocities[1][1]) /
410  (std::sqrt(std::pow(nodesVelocities[0][0], 2) + std::pow(nodesVelocities[0][1], 2)) *
411  std::sqrt(std::pow(nodesVelocities[1][0], 2) + std::pow(nodesVelocities[1][1], 2)));
412  const double cosAngle02 = (nodesVelocities[0][0] * nodesVelocities[2][0] + nodesVelocities[0][1] * nodesVelocities[2][1]) /
413  (std::sqrt(std::pow(nodesVelocities[0][0], 2) + std::pow(nodesVelocities[0][1], 2)) *
414  std::sqrt(std::pow(nodesVelocities[2][0], 2) + std::pow(nodesVelocities[2][1], 2)));
415  const double cosAngle12 = (nodesVelocities[1][0] * nodesVelocities[2][0] + nodesVelocities[1][1] * nodesVelocities[2][1]) /
416  (std::sqrt(std::pow(nodesVelocities[1][0], 2) + std::pow(nodesVelocities[1][1], 2)) *
417  std::sqrt(std::pow(nodesVelocities[2][0], 2) + std::pow(nodesVelocities[2][1], 2)));
418 
419  if (std::abs(cosAngle01) < 0.95 || std::abs(cosAngle02) < 0.95 || std::abs(cosAngle12) < 0.95)
420  {
421  accepted = false;
422  // std::cout << isolatedNodesInTheElement << " isolatedNodesInTheElement The angle between the velocity vectors is too big" << std::endl;
423  }
424  }
425  }
426  }
427  Geometry<Node> *triangle = new Triangle2D3<Node>(vertices);
428  double elementArea = triangle->Area();
429  if (elementArea < CriticalVolume)
430  {
431  accepted = false;
432  // std::cout << "ATTENTION!!! ELEMENT WITH AREA = " << elementArea << " versus critical area " << CriticalVolume << std::endl;
433  }
434  delete triangle;
435  }
436  else if (dimension == 3)
437  {
438  if ((numfreesurf == nds || sumIsolatedFreeSurf == nds || previouslyIsolatedNodes == nds || previouslyFreeSurfaceNodes == nds) && numrigid == 0 && isolatedNodesInTheElement > 0)
439  {
440  if (checkedNodes == nds)
441  {
442  const double maxValue = 2.5;
443  const double minValue = 1.0 / maxValue;
444  if (normVelocityP[0] / normVelocityP[1] < minValue || normVelocityP[0] / normVelocityP[2] < minValue || normVelocityP[0] / normVelocityP[3] < minValue ||
445  normVelocityP[0] / normVelocityP[1] > maxValue || normVelocityP[0] / normVelocityP[2] > maxValue || normVelocityP[0] / normVelocityP[3] > maxValue ||
446  normVelocityP[1] / normVelocityP[2] < minValue || normVelocityP[1] / normVelocityP[3] < minValue ||
447  normVelocityP[1] / normVelocityP[2] > maxValue || normVelocityP[1] / normVelocityP[3] > maxValue ||
448  normVelocityP[2] / normVelocityP[3] < minValue ||
449  normVelocityP[2] / normVelocityP[3] > maxValue)
450  {
451  accepted = false;
452  }
453  else
454  {
455  const double cosAngle01 = (nodesVelocities[0][0] * nodesVelocities[1][0] + nodesVelocities[0][1] * nodesVelocities[1][1] + nodesVelocities[0][1] * nodesVelocities[1][2]) /
456  (std::sqrt(std::pow(nodesVelocities[0][0], 2) + std::pow(nodesVelocities[0][1], 2) + std::pow(nodesVelocities[0][2], 2)) *
457  std::sqrt(std::pow(nodesVelocities[1][0], 2) + std::pow(nodesVelocities[1][1], 2) + std::pow(nodesVelocities[1][2], 2)));
458  const double cosAngle02 = (nodesVelocities[0][0] * nodesVelocities[2][0] + nodesVelocities[0][1] * nodesVelocities[2][1] + nodesVelocities[0][1] * nodesVelocities[2][2]) /
459  (std::sqrt(std::pow(nodesVelocities[0][0], 2) + std::pow(nodesVelocities[0][1], 2) + std::pow(nodesVelocities[0][2], 2)) *
460  std::sqrt(std::pow(nodesVelocities[2][0], 2) + std::pow(nodesVelocities[2][1], 2) + std::pow(nodesVelocities[2][2], 2)));
461  const double cosAngle03 = (nodesVelocities[0][0] * nodesVelocities[3][0] + nodesVelocities[0][1] * nodesVelocities[3][1] + nodesVelocities[0][1] * nodesVelocities[3][2]) /
462  (std::sqrt(std::pow(nodesVelocities[0][0], 2) + std::pow(nodesVelocities[0][1], 2) + std::pow(nodesVelocities[0][2], 2)) *
463  std::sqrt(std::pow(nodesVelocities[3][0], 2) + std::pow(nodesVelocities[3][1], 2) + std::pow(nodesVelocities[3][2], 2)));
464  const double cosAngle12 = (nodesVelocities[1][0] * nodesVelocities[2][0] + nodesVelocities[1][1] * nodesVelocities[2][1] + nodesVelocities[1][1] * nodesVelocities[2][2]) /
465  (std::sqrt(std::pow(nodesVelocities[1][0], 2) + std::pow(nodesVelocities[1][1], 2) + std::pow(nodesVelocities[1][2], 2)) *
466  std::sqrt(std::pow(nodesVelocities[2][0], 2) + std::pow(nodesVelocities[2][1], 2) + std::pow(nodesVelocities[2][2], 2)));
467  const double cosAngle13 = (nodesVelocities[1][0] * nodesVelocities[3][0] + nodesVelocities[1][1] * nodesVelocities[3][1] + nodesVelocities[1][1] * nodesVelocities[3][2]) /
468  (std::sqrt(std::pow(nodesVelocities[1][0], 2) + std::pow(nodesVelocities[1][1], 2) + std::pow(nodesVelocities[1][2], 2)) *
469  std::sqrt(std::pow(nodesVelocities[3][0], 2) + std::pow(nodesVelocities[3][1], 2) + std::pow(nodesVelocities[3][2], 2)));
470  const double cosAngle23 = (nodesVelocities[2][0] * nodesVelocities[3][0] + nodesVelocities[2][1] * nodesVelocities[3][1] + nodesVelocities[2][1] * nodesVelocities[3][2]) /
471  (std::sqrt(std::pow(nodesVelocities[2][0], 2) + std::pow(nodesVelocities[2][1], 2) + std::pow(nodesVelocities[2][2], 2)) *
472  std::sqrt(std::pow(nodesVelocities[3][0], 2) + std::pow(nodesVelocities[3][1], 2) + std::pow(nodesVelocities[3][2], 2)));
473 
474  if (std::abs(cosAngle01) < 0.85 || std::abs(cosAngle02) < 0.85 || std::abs(cosAngle03) < 0.85 || std::abs(cosAngle12) < 0.85 || std::abs(cosAngle13) < 0.85 || std::abs(cosAngle23) < 0.85)
475  {
476  accepted = false;
477  // std::cout << "The angle between the velocity vectors is too big" << std::endl;
478  }
479  }
480  }
481  }
482  }
483  }
484 
485  // // to control that the element has a good shape
486  if (dimension == 3 && accepted && numrigid < 3 &&
487  (previouslyIsolatedNodes == 4 || previouslyFreeSurfaceNodes == 4 || sumIsolatedFreeSurf == 4 || numfreesurf == 4 || numisolated == 4 || (numrigid == 2 && isolatedNodesInTheElement > 1)))
488  {
489  Geometry<Node> *tetrahedron = new Tetrahedra3D4<Node>(vertices);
490  double Volume = tetrahedron->Volume();
491 
492  // a1 slope x for plane on the first triangular face of the tetrahedra (nodes A,B,C)
493  // b1 slope y for plane on the first triangular face of the tetrahedra (nodes A,B,C)
494  // c1 slope z for plane on the first triangular face of the tetrahedra (nodes A,B,C)
495  const double a1 = (nodesCoordinates[1][1] - nodesCoordinates[0][1]) * (nodesCoordinates[2][2] - nodesCoordinates[0][2]) - (nodesCoordinates[2][1] - nodesCoordinates[0][1]) * (nodesCoordinates[1][2] - nodesCoordinates[0][2]);
496  const double b1 = (nodesCoordinates[1][2] - nodesCoordinates[0][2]) * (nodesCoordinates[2][0] - nodesCoordinates[0][0]) - (nodesCoordinates[2][2] - nodesCoordinates[0][2]) * (nodesCoordinates[1][0] - nodesCoordinates[0][0]);
497  const double c1 = (nodesCoordinates[1][0] - nodesCoordinates[0][0]) * (nodesCoordinates[2][1] - nodesCoordinates[0][1]) - (nodesCoordinates[2][0] - nodesCoordinates[0][0]) * (nodesCoordinates[1][1] - nodesCoordinates[0][1]);
498  // a2 slope x for plane on the second triangular face of the tetrahedra (nodes A,B,D)
499  // b2 slope y for plane on the second triangular face of the tetrahedra (nodes A,B,D)
500  // c2 slope z for plane on the second triangular face of the tetrahedra (nodes A,B,D)
501  const double a2 = (nodesCoordinates[1][1] - nodesCoordinates[0][1]) * (nodesCoordinates[3][2] - nodesCoordinates[0][2]) - (nodesCoordinates[3][1] - nodesCoordinates[0][1]) * (nodesCoordinates[1][2] - nodesCoordinates[0][2]);
502  const double b2 = (nodesCoordinates[1][2] - nodesCoordinates[0][2]) * (nodesCoordinates[3][0] - nodesCoordinates[0][0]) - (nodesCoordinates[3][2] - nodesCoordinates[0][2]) * (nodesCoordinates[1][0] - nodesCoordinates[0][0]);
503  const double c2 = (nodesCoordinates[1][0] - nodesCoordinates[0][0]) * (nodesCoordinates[3][1] - nodesCoordinates[0][1]) - (nodesCoordinates[3][0] - nodesCoordinates[0][0]) * (nodesCoordinates[1][1] - nodesCoordinates[0][1]);
504  // a3 slope x for plane on the third triangular face of the tetrahedra (nodes B,C,D)
505  // b3 slope y for plane on the third triangular face of the tetrahedra (nodes B,C,D)
506  // c3 slope z for plane on the third triangular face of the tetrahedra (nodes B,C,D)
507  const double a3 = (nodesCoordinates[1][1] - nodesCoordinates[2][1]) * (nodesCoordinates[3][2] - nodesCoordinates[2][2]) - (nodesCoordinates[3][1] - nodesCoordinates[2][1]) * (nodesCoordinates[1][2] - nodesCoordinates[2][2]);
508  const double b3 = (nodesCoordinates[1][2] - nodesCoordinates[2][2]) * (nodesCoordinates[3][0] - nodesCoordinates[2][0]) - (nodesCoordinates[3][2] - nodesCoordinates[2][2]) * (nodesCoordinates[1][0] - nodesCoordinates[2][0]);
509  const double c3 = (nodesCoordinates[1][0] - nodesCoordinates[2][0]) * (nodesCoordinates[3][1] - nodesCoordinates[2][1]) - (nodesCoordinates[3][0] - nodesCoordinates[2][0]) * (nodesCoordinates[1][1] - nodesCoordinates[2][1]);
510  // a4 slope x for plane on the fourth triangular face of the tetrahedra (nodes A,C,D)
511  // b4 slope y for plane on the fourth triangular face of the tetrahedra (nodes A,C,D)
512  // c4 slope z for plane on the fourth triangular face of the tetrahedra (nodes A,C,D)
513  const double a4 = (nodesCoordinates[0][1] - nodesCoordinates[2][1]) * (nodesCoordinates[3][2] - nodesCoordinates[2][2]) - (nodesCoordinates[3][1] - nodesCoordinates[2][1]) * (nodesCoordinates[0][2] - nodesCoordinates[2][2]);
514  const double b4 = (nodesCoordinates[0][2] - nodesCoordinates[2][2]) * (nodesCoordinates[3][0] - nodesCoordinates[2][0]) - (nodesCoordinates[3][2] - nodesCoordinates[2][2]) * (nodesCoordinates[0][0] - nodesCoordinates[2][0]);
515  const double c4 = (nodesCoordinates[0][0] - nodesCoordinates[2][0]) * (nodesCoordinates[3][1] - nodesCoordinates[2][1]) - (nodesCoordinates[3][0] - nodesCoordinates[2][0]) * (nodesCoordinates[0][1] - nodesCoordinates[2][1]);
516 
517  const double cosAngle12 = (a1 * a2 + b1 * b2 + c1 * c2) / (std::sqrt(std::pow(a1, 2) + std::pow(b1, 2) + std::pow(c1, 2)) * std::sqrt(std::pow(a2, 2) + std::pow(b2, 2) + std::pow(c2, 2)));
518  const double cosAngle13 = (a1 * a3 + b1 * b3 + c1 * c3) / (std::sqrt(std::pow(a1, 2) + std::pow(b1, 2) + std::pow(c1, 2)) * std::sqrt(std::pow(a3, 2) + std::pow(b3, 2) + std::pow(c3, 2)));
519  const double cosAngle14 = (a1 * a4 + b1 * b4 + c1 * c4) / (std::sqrt(std::pow(a1, 2) + std::pow(b1, 2) + std::pow(c1, 2)) * std::sqrt(std::pow(a4, 2) + std::pow(b4, 2) + std::pow(c4, 2)));
520  const double cosAngle23 = (a3 * a2 + b3 * b2 + c3 * c2) / (std::sqrt(std::pow(a3, 2) + std::pow(b3, 2) + std::pow(c3, 2)) * std::sqrt(std::pow(a2, 2) + std::pow(b2, 2) + std::pow(c2, 2)));
521  const double cosAngle24 = (a4 * a2 + b4 * b2 + c4 * c2) / (std::sqrt(std::pow(a4, 2) + std::pow(b4, 2) + std::pow(c4, 2)) * std::sqrt(std::pow(a2, 2) + std::pow(b2, 2) + std::pow(c2, 2)));
522  const double cosAngle34 = (a4 * a3 + b4 * b3 + c4 * c3) / (std::sqrt(std::pow(a4, 2) + std::pow(b4, 2) + std::pow(c4, 2)) * std::sqrt(std::pow(a3, 2) + std::pow(b3, 2) + std::pow(c3, 2)));
523 
524  if (std::abs(cosAngle12) > 0.999 || std::abs(cosAngle13) > 0.999 || std::abs(cosAngle14) > 0.999 || std::abs(cosAngle23) > 0.999 || std::abs(cosAngle24) > 0.999 || std::abs(cosAngle34) > 0.999) // if two faces are coplanar, I will erase the element (which is probably a sliver)
525  {
526  accepted = false;
527  number_of_slivers++;
528  }
529  else if (Volume <= CriticalVolume)
530  {
531  accepted = false;
532  number_of_slivers++;
533  }
534  delete tetrahedron;
535  }
536 
537  if (accepted)
538  {
539  number += 1;
540  mrRemesh.PreservedElements[el] = number;
541  }
542  }
543  mrRemesh.Info->NumberOfElements = number;
544  }
545 
546  if (mEchoLevel > 1)
547  {
548  std::cout << "Number of Preserved Fluid Elements " << mrRemesh.Info->NumberOfElements << " (slivers detected: " << number_of_slivers << ") " << std::endl;
549  std::cout << "TOTAL removed nodes " << mrRemesh.Info->RemovedNodes << std::endl;
550  }
551  if (mrRemesh.ExecutionOptions.IsNot(MesherUtilities::KEEP_ISOLATED_NODES))
552  {
553  ModelPart::ElementsContainerType::iterator element_begin = mrModelPart.ElementsBegin();
554  const SizeType nds = (*element_begin).GetGeometry().size();
555 
556  int *OutElementList = mrRemesh.OutMesh.GetElementList();
557 
558  ModelPart::NodesContainerType &rNodes = mrModelPart.Nodes();
559 
560  // check engaged nodes
561  for (int el = 0; el < OutNumberOfElements; el++)
562  {
563  if (mrRemesh.PreservedElements[el])
564  {
565  for (SizeType pn = 0; pn < nds; pn++)
566  {
567  // set vertices
568  rNodes[OutElementList[el * nds + pn]].Set(BLOCKED);
569  }
570  }
571  }
572 
573  int count_release = 0;
574  for (ModelPart::NodesContainerType::iterator i_node = rNodes.begin(); i_node != rNodes.end(); i_node++)
575  {
576  if (i_node->IsNot(BLOCKED))
577  {
578  if (!(i_node->Is(FREE_SURFACE) || i_node->Is(RIGID)))
579  {
580  i_node->Set(TO_ERASE);
581  if (mEchoLevel > 0)
582  std::cout << " NODE " << i_node->Id() << " RELEASE " << std::endl;
583  if (i_node->Is(BOUNDARY))
584  std::cout << " ERROR: node " << i_node->Id() << " IS BOUNDARY RELEASE " << std::endl;
585  }
586  }
587  if (i_node->Is(TO_ERASE))
588  {
589  count_release++;
590  }
591 
592  i_node->Reset(BLOCKED);
593  }
594 
595  if (mEchoLevel > 0)
596  std::cout << " fluid NUMBER OF RELEASED NODES " << count_release << std::endl;
597  }
598  else
599  {
600  ModelPart::NodesContainerType &rNodes = mrModelPart.Nodes();
601  for (ModelPart::NodesContainerType::iterator i_node = rNodes.begin(); i_node != rNodes.end(); i_node++)
602  {
603  i_node->Reset(BLOCKED);
604  }
605  }
606 
607  mrRemesh.InputInitializedFlag = false;
608  mMesherUtilities.SetNodes(mrModelPart, mrRemesh);
609  mrRemesh.InputInitializedFlag = true;
610 
611  if (mEchoLevel > 1)
612  {
613  std::cout << " Generated_Elements :" << OutNumberOfElements << std::endl;
614  std::cout << " Passed_AlphaShape :" << mrRemesh.Info->NumberOfElements << std::endl;
615  std::cout << " SELECT MESH ELEMENTS ]; " << std::endl;
616  }
617 
618  KRATOS_CATCH("")
619  }
620 
624 
628 
632 
634  std::string Info() const override
635  {
636  return "SelectMeshElementsForFluidsProcess";
637  }
638 
640  void PrintInfo(std::ostream &rOStream) const override
641  {
642  rOStream << "SelectMeshElementsForFluidsProcess";
643  }
644 
646  void PrintData(std::ostream &rOStream) const override
647  {
648  }
649 
653 
655 
656  private:
659 
663  ModelPart &mrModelPart;
665  MesherUtilities mMesherUtilities;
666  int mEchoLevel;
667 
671 
675 
679 
683 
687 
688  void IncreaseAlphaForRefininedZones(double &Alpha,
689  bool increaseAlfa,
690  SizeType nds,
691  SizeType numfreesurf,
692  SizeType numrigid,
693  SizeType numisolated)
694  {
695  KRATOS_TRY
696 
697  if (increaseAlfa == true)
698  {
699  if (numfreesurf < nds && numisolated == 0)
700  {
701  Alpha *= 1.2;
702  }
703  else if (numfreesurf == 0 && numrigid == 0 && numisolated == 0)
704  {
705  Alpha *= 1.4;
706  }
707  else if (numfreesurf == 0 && numrigid > (0.5 * nds) && numisolated == 0)
708  {
709  Alpha *= 5.0;
710  }
711  else if (numfreesurf == 0 && numrigid > 0 && numisolated == 0)
712  {
713  Alpha *= 1.8;
714  }
715  }
716 
717  KRATOS_CATCH("")
718  }
719 
722 
724 
726  // Process(Process const& rOther);
727 
729 
730  }; // Class Process
731 
733 
736 
740 
742  inline std::istream &operator>>(std::istream &rIStream,
744 
746  inline std::ostream &operator<<(std::ostream &rOStream,
748  {
749  rThis.PrintInfo(rOStream);
750  rOStream << std::endl;
751  rThis.PrintData(rOStream);
752 
753  return rOStream;
754  }
756 
757 } // namespace Kratos.
758 
759 #endif // KRATOS_SELECT_MESH_ELEMENTS_FOR_FLUIDS_PROCESS_H_INCLUDED defined
Base class for all Conditions.
Definition: condition.h:59
bool Is(Flags const &rOther) const
Definition: flags.h:274
bool IsNot(Flags const &rOther) const
Definition: flags.h:291
Geometry base class.
Definition: geometry.h:71
void push_back(PointPointerType x)
Definition: geometry.h:548
virtual double Volume() const
This method calculate and return volume of this geometry.
Definition: geometry.h:1358
PointReferenceType back()
Definition: geometry.h:507
virtual double Area() const
This method calculate and return area or surface area of this geometry depending to it's dimension.
Definition: geometry.h:1345
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
size_type size() const
Definition: global_pointers_vector.h:307
The base class for processes passed to the solution scheme.
Definition: mesher_process.hpp:37
Short class definition.
Definition: mesher_utilities.hpp:49
double ComputeModelPartVolume(ModelPart &rModelPart)
Definition: mesher_utilities.cpp:228
void SetNodes(ModelPart &rModelPart, MeshingParameters &rMeshingVariables)
Definition: mesher_utilities.cpp:2021
void DefineMeshSizeInTransitionZones2D(MeshingParameters &rMeshingVariables, double currentTime, array_1d< double, 3 > NodeCoordinates, double &meanMeshSize, bool &insideTransitionZone)
Definition: mesher_utilities.cpp:2153
void DefineMeshSizeInTransitionZones3D(MeshingParameters &rMeshingVariables, double currentTime, array_1d< double, 3 > NodeCoordinates, double &meanMeshSize, bool &insideTransitionZone)
Definition: mesher_utilities.cpp:2311
bool AlphaShape(double AlphaParameter, Geometry< Node > &rGeometry, const unsigned int dimension)
Definition: mesher_utilities.cpp:1182
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ElementIterator ElementsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1169
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
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
Properties encapsulates data shared by different Elements or Conditions. It can store any type of dat...
Definition: properties.h:69
Refine Mesh Elements Process 2D and 3D.
Definition: select_mesh_elements_for_fluids_process.hpp:50
void Execute() override
Execute method is used to execute the Process algorithms.
Definition: select_mesh_elements_for_fluids_process.hpp:95
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: select_mesh_elements_for_fluids_process.hpp:646
ConditionType::GeometryType GeometryType
Definition: select_mesh_elements_for_fluids_process.hpp:60
KRATOS_CLASS_POINTER_DEFINITION(SelectMeshElementsForFluidsProcess)
Pointer definition of Process.
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: select_mesh_elements_for_fluids_process.hpp:640
std::string Info() const override
Turn back information as a string.
Definition: select_mesh_elements_for_fluids_process.hpp:634
SelectMeshElementsForFluidsProcess(ModelPart &rModelPart, MesherUtilities::MeshingParameters &rRemeshingParameters, int EchoLevel)
Default constructor.
Definition: select_mesh_elements_for_fluids_process.hpp:68
std::size_t SizeType
Definition: select_mesh_elements_for_fluids_process.hpp:62
void operator()()
This operator is provided to call the process as a function and simply calls the Execute method.
Definition: select_mesh_elements_for_fluids_process.hpp:85
virtual ~SelectMeshElementsForFluidsProcess()
Destructor.
Definition: select_mesh_elements_for_fluids_process.hpp:78
ModelPart::PropertiesType PropertiesType
Definition: select_mesh_elements_for_fluids_process.hpp:59
GlobalPointersVector< Node > NodeWeakPtrVectorType
Definition: select_mesh_elements_for_fluids_process.hpp:61
ModelPart::ConditionType ConditionType
Definition: select_mesh_elements_for_fluids_process.hpp:58
A four node tetrahedra geometry with linear shape functions.
Definition: tetrahedra_3d_4.h:59
A three node 2D triangle geometry with linear shape functions.
Definition: triangle_2d_3.h:74
#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
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
std::size_t SizeType
The definition of the size type.
Definition: mortar_classes.h:43
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
pn
Definition: generate_droplet_dynamics.py:65
int dimension
Definition: isotropic_damage_automatic_differentiation.py:123
def Alpha(n, j)
Definition: quadrature.py:93
el
Definition: read_stl.py:25
integer i
Definition: TensorModule.f:17
int * GetElementList()
Definition: mesher_utilities.hpp:178
int & GetNumberOfPoints()
Definition: mesher_utilities.hpp:182
int & GetNumberOfElements()
Definition: mesher_utilities.hpp:183
Definition: mesher_utilities.hpp:631
MeshingInfoParameters::Pointer Info
Definition: mesher_utilities.hpp:681
std::vector< int > PreservedElements
Definition: mesher_utilities.hpp:669
RefiningParameters::Pointer Refine
Definition: mesher_utilities.hpp:684
bool MeshElementsSelectedFlag
Definition: mesher_utilities.hpp:662
MeshContainer InMesh
Definition: mesher_utilities.hpp:674
MeshContainer OutMesh
Definition: mesher_utilities.hpp:675
std::vector< double > RefiningBoxFinalTime
Definition: mesher_utilities.hpp:706
std::vector< bool > UseRefiningBox
Definition: mesher_utilities.hpp:704
bool InputInitializedFlag
Definition: mesher_utilities.hpp:661
std::vector< int > NodalPreIds
Definition: mesher_utilities.hpp:668
double AlphaParameter
Definition: mesher_utilities.hpp:651
Flags ExecutionOptions
Definition: mesher_utilities.hpp:648
std::vector< double > RefiningBoxInitialTime
Definition: mesher_utilities.hpp:705