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.
signed_distance_calculation_utils.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Riccardo Rossi
11 //
12 //
13 
14 #ifndef _SIGNED_DISTANCE_CALCULATION_UTILS_H
15 #define _SIGNED_DISTANCE_CALCULATION_UTILS_H
16 /* System includes */
17 
18 
19 /* External includes */
20 
21 
22 /* Project includes */
23 //#include "utilities/math_utils.h"
24 #include "utilities/geometry_utilities.h"
25 #include "utilities/math_utils.h"
27 
28 
29 namespace Kratos
30 {
31 
80 template< unsigned int TDim>
82 {
83 public:
111  ModelPart& r_model_part,
112  Variable<double>& rDistanceVar,
113  const double max_distance
114  )
115  {
116  if constexpr (TDim == 2)
117  CalculateDistances2D(r_model_part, rDistanceVar, max_distance);
118  else if constexpr (TDim == 3)
119  CalculateDistances3D(r_model_part, rDistanceVar, max_distance);
120 
121  // r_model_part.GetCommunicator().SynchronizeCurrentDataToMin(rDistanceVar);
122  }
123 
124  //***********************************************************************
125  //***********************************************************************
127  ModelPart& r_model_part,
128  Variable<double>& rDistanceVar,
129  const double max_distance
130  )
131  {
132  KRATOS_TRY
133 
134  double large_distance = 1e6;
135  double tol = 1.0/large_distance;
136 
137  //copy rDistance var to GetValue database
138  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
139  {
140  it->GetValue(rDistanceVar) = it->FastGetSolutionStepValue(rDistanceVar);
141  it->FastGetSolutionStepValue(rDistanceVar) = large_distance;
142  it->GetValue(IS_VISITED) = 0;
143  }
144 
146  array_1d<double,TDim+1> N, distances;
147  array_1d<double,TDim> grad_d;
148  array_1d<double,3> coord_on_0(3,0.0);
150  BoundedMatrix<double, TDim, TDim> free_surface_points;
151 
152  //fill the list of the first elements to be solved for the "distance"
153  for(ElementsArrayType::iterator it = r_model_part.ElementsBegin(); it !=r_model_part.ElementsEnd(); it++)
154  {
155  Element::GeometryType& geom = it->GetGeometry();
156 
157  unsigned int n_positive = 0;
158  unsigned int n_negative = 0;
159  for(unsigned int kk = 0; kk<TDim+1 ; kk++)
160  {
161  const double dist = geom[kk].GetValue(rDistanceVar);
162  distances[kk] = dist;
163  if(dist < 0)
164  n_negative += 1;
165  else
166  n_positive += 1;
167  }
168 
169  if(n_negative > 0 && n_positive > 0) //ELEMENT IS CROSSED BY THE INTERFACE!
170  {
171 // //determine the positions at which the edges are cut by the free surface
172 // unsigned int counter = 0;
173 // for (unsigned int i = 0; i < TDim + 1; i++) {
174 // for (unsigned int j = i + 1; j < TDim + 1; j++) {
175 // if (distances[i] * distances[j] <= 0.0) {
176 // double fact = fabs(distances[i]) / (fabs(distances[i]) + fabs(distances[j]));
177 // //std::cout << i << " " << j << std::endl;
178 // for (unsigned int k = 0; k < TDim; k++)
179 // free_surface_points(counter, k) = geom[i].Coordinates()[k] + (geom[j].Coordinates()[k] - geom[i].Coordinates()[k]) * fact;
180 //
181 // counter++;
182 // // KRATOS_WATCH(counter);
183 // }
184 //
185 // if (counter >= TDim)
186 // break;
187 // }
188 // if (counter >= TDim)
189 // break;
190 // }
191 //
192 // //generate list of virtual points on the free surface (for the element divided)
193 // //and compute the distance of all of the nodes in the element from such list
194 // if constexpr (TDim == 2)
195 // KRATOS_THROW_ERROR(std::logic_error,"2d not yet implemented","")
196 // else
197 // {
198 // array_1d<double,3> N;
199 // //internal points
200 // ComputeDistancesFromVirtualPoint3D(geom,0.2, 0.2, N, free_surface_points, rDistanceVar );
201 // ComputeDistancesFromVirtualPoint3D(geom,0.6, 0.2, N,free_surface_points, rDistanceVar );
202 // ComputeDistancesFromVirtualPoint3D(geom,0.2, 0.6, N,free_surface_points, rDistanceVar );
203 // ComputeDistancesFromVirtualPoint3D(geom,0.33333333333333333333, 0.33333333333333333333, N, free_surface_points, rDistanceVar );
204 //
205 // //points on faces
206 // ComputeDistancesFromVirtualPoint3D(geom,0.5, 0.0, N,free_surface_points, rDistanceVar );
207 // ComputeDistancesFromVirtualPoint3D(geom,0.0, 0.5, N,free_surface_points, rDistanceVar );
208 // ComputeDistancesFromVirtualPoint3D(geom,0.5, 0.5, N,free_surface_points, rDistanceVar );
209 //
210 // //points on edges
214 //
215 // for(unsigned int kk = 0; kk<TDim+1 ; kk++)
216 // geom[kk].GetValue(IS_VISITED) = 1;
217 // }
218 
219 
220 
221 
222 //
223  double Volume;
224  GeometryUtils::CalculateGeometryData(geom,DN_DX,N,Volume);
225 
226  //compute the gradient of the distance and normalize it
227  noalias(grad_d) = prod(trans(DN_DX),distances);
228  double norm = norm_2(grad_d);
229  grad_d /= norm;
230 
231  //find one division point on one edge
232  for(unsigned int i = 1; i<TDim+1; i++)
233  {
234  if(distances[0]*distances[i]<=0) //if the edge is divided
235  {
236  double delta_d = fabs(distances[i]) + fabs(distances[0]);
237 
238  if(delta_d>1e-20)
239  {
240  double Ni = fabs(distances[0]) / delta_d;
241  double N0 = fabs(distances[i]) / delta_d;
242 
243  noalias(coord_on_0) = N0 * geom[0].Coordinates();
244  noalias(coord_on_0) += Ni * geom[i].Coordinates();
245  }
246  else
247  noalias(coord_on_0) = geom[0].Coordinates();
248 
249  break;
250 
251  }
252  }
253 
254  //now calculate the distance of all the nodes from the elemental free surface
255  for(unsigned int i = 0; i<TDim+1; i++)
256  {
257  noalias(temp) = geom[i].Coordinates();
258  noalias(temp) -= coord_on_0 ;
259 
260  double real_distance = 0.0;
261  for(unsigned int k=0; k<TDim; k++)
262  real_distance += temp[k]*grad_d[k];
263  real_distance = fabs(real_distance);
264 
265  double& dist_i = geom[i].FastGetSolutionStepValue(rDistanceVar);
266  if(real_distance < dist_i)
267  dist_i = real_distance;
268 
269  //select the nodes for the computation of the distance
270  geom[i].GetValue(IS_VISITED) = 1;
271  }
272 
273  }
274 
275 
276 
277  }
278 
279  //loop on all nodes to treat correctly the case of the surface coinciding with a node
280  //copy rDistance var to GetValue database
281  array_1d<double,3> aux;
282  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
283  {
284  if(fabs(it->GetValue(rDistanceVar)) < tol)
285  {
286  it->FastGetSolutionStepValue(rDistanceVar) = 0.0;
287  it->GetValue(IS_VISITED) = 1;
288 
289  //const array_1d<double,3>& center_coords = it->Coordinates();
290 
291  //now loop all of its neighbours and calculate the distance value
292 // for (GlobalPointersVector< Node >::iterator in = it->GetValue(NEIGHBOUR_NODES).begin();
293 // in != it->GetValue(NEIGHBOUR_NODES).end(); in++)
294 // {
295 // const array_1d<double,3>& coords = in->Coordinates();
296 // noalias(aux) = coords;
297 // noalias(aux) -= center_coords;
298 // double dist = norm_2(aux);
299 //
300 // if(in->FastGetSolutionStepValue(rDistanceVar) > dist)
301 // in->FastGetSolutionStepValue(rDistanceVar) = dist;
302 //
303 // in->GetValue(IS_VISITED)=1;
304 // }
305 
306  }
307  }
308 
309  //compute the distance using the element based approach
311  util.CalculateDistances<TDim>(r_model_part.Elements(),rDistanceVar,max_distance);
312 
313  //finally change the sign to the distance as needed
314  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
315  {
316  if(it->GetValue(rDistanceVar) < 0)
317  it->FastGetSolutionStepValue(rDistanceVar) = -it->FastGetSolutionStepValue(rDistanceVar);
318  }
319 
320  //check if something is wrong
321  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
322  {
323  if(fabs(it->FastGetSolutionStepValue(rDistanceVar)) == large_distance)
324  {
325  KRATOS_WATCH("error in the calculation of the distance for node")
326  KRATOS_WATCH(it->Id());
327 
328  }
329  }
330 
331 
332 
333 
334  KRATOS_CATCH("")
335 
336  }
337 
339  ModelPart& r_model_part,
340  Variable<double>& rDistanceVar,
341  const double max_distance
342  )
343  {
344  KRATOS_TRY
345 
346  const double large_distance = 1e9;
347 
348  std::vector<array_1d<double,TDim + 1> > distances;
349  std::vector<Element::Pointer> interface_elements;
350 
351  //copy rDistance var to GetValue database
352  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
353  {
354  it->GetValue(rDistanceVar) = it->FastGetSolutionStepValue(rDistanceVar);
355  it->GetValue(IS_VISITED) = 0;
356  }
357 
358  // Make a list of all elements crossed by interface and get their nodal distances
359  for(ElementsArrayType::iterator i_element = r_model_part.ElementsBegin(); i_element !=r_model_part.ElementsEnd(); i_element++)
360  {
361  // Get a reference to the geometry
362  Element::GeometryType& element_geometry = i_element->GetGeometry();
363  array_1d<double,TDim + 1> element_distance;
364 
365  bool positive = false;
366  bool negative = false;
367 
368  // loop over nodes to see if they have positive or negative distance.
369  for(unsigned int i_node = 0; i_node < element_geometry.size() ; i_node++)
370  {
371  const double distance = element_geometry[i_node].GetSolutionStepValue(rDistanceVar);
372  element_distance[i_node] = distance;
373  negative |= (distance < 0);
374  positive |= (distance >= 0);
375  }
376 
377  if(negative && positive) //ELEMENT IS CROSSED BY THE INTERFACE!
378  {
379  interface_elements.push_back(*(i_element.base()));
380  distances.push_back(element_distance);
381  }
382  }
383 
384  // Reset the distance to a large value maintaining the sign
385  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
386  {
387  double& distance = it->FastGetSolutionStepValue(rDistanceVar);
388 
389  if(distance >= 0.00)
390  distance = large_distance;
391  else
392  distance = -large_distance;
393  }
394 
395  // Now calculating the new distance for interface elements
396  int size = static_cast<int>(interface_elements.size());
397  for(int i = 0 ; i < size ; i++)
398  {
399  // Get a reference to the geometry
400  Element::GeometryType& element_geometry = interface_elements[i]->GetGeometry();
401 
402  GeometryUtils::CalculateTetrahedraDistances(element_geometry, distances[i]);
403 
404  // loop over nodes and apply the new distances.
405  for(unsigned int i_node = 0; i_node < element_geometry.size() ; i_node++)
406  {
407  double& distance = element_geometry[i_node].GetSolutionStepValue(rDistanceVar);
408  double new_distance = distances[i][i_node];
409 
410 // if(fabs(fabs(distance) - fabs(new_distance)) > 1.00e-9)
411 // {
412 // KRATOS_WATCH(interface_elements[i]->Id());
413 // KRATOS_WATCH(element_geometry[i_node]);
414 // KRATOS_WATCH(distance);
415 // KRATOS_WATCH(new_distance);
416 // }
417 
418 
419 
420  if(fabs(distance) > fabs(new_distance))
421  {
422  if(distance >= 0)
423  distance = new_distance;
424  else
425  distance = new_distance;
426  }
427  element_geometry[i_node].GetValue(IS_VISITED) = 1;
428  }
429  }
430  //compute the distance using the element based approach
432  util.CalculateDistances<TDim>(r_model_part.Elements(),rDistanceVar,max_distance);
433 
434  //finally change the sign to the distance as needed
435  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
436  {
437  if(it->GetValue(rDistanceVar) < 0)
438  it->FastGetSolutionStepValue(rDistanceVar) = -it->FastGetSolutionStepValue(rDistanceVar);
439  }
440 
441  //check if something is wrong
442  for(ModelPart::NodesContainerType::iterator it = r_model_part.NodesBegin(); it !=r_model_part.NodesEnd(); it++)
443  {
444  if(fabs(it->FastGetSolutionStepValue(rDistanceVar)) == large_distance)
445  {
446  KRATOS_WATCH("error in the calculation of the distance for node")
447  KRATOS_WATCH(it->Id());
448 
449  }
450  }
451 
452 // r_model_part.GetCommunicator().SynchronizeCurrentDataToMin(rDistanceVar);
453 //
454  KRATOS_CATCH("")
455 
456  }
457 
458  //**********************************************************************************+
459  //**********************************************************************************+
460  double FindMaximumEdgeSize(ModelPart& r_model_part)
461  {
462  KRATOS_TRY
463 
464  ModelPart::NodesContainerType& rNodes = r_model_part.Nodes();
465 
466  double h_max = 0.0;
467 
468  for (ModelPart::NodesContainerType::iterator in = rNodes.begin(); in != rNodes.end(); in++)
469  {
470  double xc = in->X();
471  double yc = in->Y();
472  double zc = in->Z();
473 
474  double h = 0.0;
475  for (GlobalPointersVector< Node >::iterator i = in->GetValue(NEIGHBOUR_NODES).begin();
476  i != in->GetValue(NEIGHBOUR_NODES).end(); i++)
477  {
478  double x = i->X();
479  double y = i->Y();
480  double z = i->Z();
481  double l = (x - xc)*(x - xc);
482  l += (y - yc)*(y - yc);
483  l += (z - zc)*(z - zc);
484 
485  if (l > h) h = l;
486  }
487  h = sqrt(h);
488 
489  if(h > h_max) h_max = h;
490 
491  }
492 
493  return h_max;
494 
495  KRATOS_CATCH("");
496  }
497 
515 private:
527 // void ComputeDistancesFromVirtualPoint3D(
528 // Geometry< Node >& geom,
529 // double xi, double eta,
530 // array_1d<double, 3 > N,
531 // const BoundedMatrix<double, TDim, TDim> free_surface_points,
532 // Variable<double>& rDistanceVar )
533 // {
534 // Point<3> aux(0.0, 0.0, 0.0);
535 // array_1d<double, 3 >& coords = aux.Coordinates();
536 //
537 // //setting the coordinates for the virtual points to the expected value
538 // N[0] = 1.0 - xi - eta;
539 // N[1] = xi;
540 // N[2] = eta;
541 // for (unsigned int i = 0; i < TDim; i++)
542 // {
543 // for (unsigned int j = 0; j < TDim; j++)
544 // coords[j] += N[i] * free_surface_points(i,j);
545 // }
546 //
547 // //now compute and verify the distance
548 // for (unsigned int i = 0; i < TDim+1; i++)
549 // {
550 // const array_1d<double,3>& node_coords = geom[i].Coordinates();
551 // double dist = 0.0;
552 // for (unsigned int j = 0; j < TDim; j++)
553 // dist += pow( coords[j] - node_coords[j] , 2);
554 //
555 // dist = sqrt(dist);
556 //
557 // double& node_dist = geom[i].FastGetSolutionStepValue(rDistanceVar);
558 // if(dist < node_dist)
559 // node_dist = dist;
560 // }
561 // }
562 
563 
587 }; /* Class ClassName */
588 
597 } /* namespace Kratos.*/
598 
599 
600 #endif /* _SIGNED_DISTANCE_CALCULATION_UTILS_H */
601 
Definition: body_distance_calculation_utils.h:93
void CalculateDistances(ElementsArrayType &rElements, Variable< double > &rDistanceVar, const double max_distance)
Definition: body_distance_calculation_utils.h:134
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
TVariableType::Type & GetValue(const TVariableType &rThisVariable)
Definition: geometry.h:627
static void CalculateTetrahedraDistances(const GeometryType &rGeometry, array_1d< double, TSize > &rDistances)
Calculate the exact distances to the interface TRIANGLE defined by a set of initial distances.
Definition: geometry_utilities.h:372
static void CalculateGeometryData(const GeometryType &rGeometry, BoundedMatrix< double, 4, 3 > &rDN_DX, array_1d< double, 4 > &rN, double &rVolume)
This function is designed to compute the shape function derivatives, shape functions and volume in 3D...
Definition: geometry_utilities.h:176
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: global_pointers_vector.h:79
Definition: amatrix_interface.h:41
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
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
ElementIterator ElementsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1179
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
A sorted associative container similar to an STL set, but uses a vector to store pointers to its data...
Definition: pointer_vector_set.h:72
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: pointer_vector_set.h:95
Definition: signed_distance_calculation_utils.h:82
void CalculateDistances(ModelPart &r_model_part, Variable< double > &rDistanceVar, const double max_distance)
Definition: signed_distance_calculation_utils.h:110
void CalculateDistances2D(ModelPart &r_model_part, Variable< double > &rDistanceVar, const double max_distance)
Definition: signed_distance_calculation_utils.h:126
double FindMaximumEdgeSize(ModelPart &r_model_part)
Definition: signed_distance_calculation_utils.h:460
void CalculateDistances3D(ModelPart &r_model_part, Variable< double > &rDistanceVar, const double max_distance)
Definition: signed_distance_calculation_utils.h:338
ModelPart::NodesContainerType NodesArrayType
Definition: signed_distance_calculation_utils.h:86
ModelPart::ElementsContainerType ElementsArrayType
Definition: signed_distance_calculation_utils.h:87
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_WATCH(variable)
Definition: define.h:806
#define KRATOS_TRY
Definition: define.h:109
z
Definition: GenerateWind.py:163
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
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
float dist
Definition: edgebased_PureConvection.py:89
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
h
Definition: generate_droplet_dynamics.py:91
int tol
Definition: hinsberg_optimization.py:138
int k
Definition: quadrature.py:595
float temp
Definition: rotating_cone.py:85
float xc
Definition: rotating_cone.py:77
float yc
Definition: rotating_cone.py:78
N
Definition: sensitivityMatrix.py:29
x
Definition: sensitivityMatrix.py:49
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31