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.
body_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: Antonia Laresse
11 // Riccardo Rossi
12 //
13 //
14 
15 #include "includes/model_part.h"
16 
17 #if !defined(KRATOS_BODY_DISTANCE_CALCULATION_UTILS )
18 #define KRATOS_BODY_DISTANCE_CALCULATION_UTILS
19 
20 
21 /* System includes */
22 
23 
24 /* External includes */
25 
26 
27 /* Project includes */
28 //#include "utilities/math_utils.h"
29 #include "utilities/geometry_utilities.h"
32 
33 
34 namespace Kratos
35 {
36 
93 {
94 public:
108 
109 
123  //***********************************************************************
124  //***********************************************************************
133  template< unsigned int TDim>
135  ElementsArrayType& rElements,
136  Variable<double>& rDistanceVar,
137  const double max_distance)
138  {
139  KRATOS_TRY
140 
141 
142  //std::cout << "dimension in distance computation " << TDim << std::endl;
143 
144  //defining work arrays
145  PointerVector< Element > elements_to_solve;
146  elements_to_solve.reserve(rElements.size());
147 
148  PointerVector< Node > active_nodes;
149  active_nodes.reserve(rElements.size());
150 
151  std::vector<double> node_distance_values;
152  node_distance_values.reserve(rElements.size());
153 
154  PointerVector< Node > failed_nodes;
155 
156 
157 
158  //fill the list of the first elements to be solved for the "distance"
159  for (ElementsArrayType::iterator it = rElements.begin(); it != rElements.end(); it++)
160  {
161  //reset is visited flag for the elements
162  it->GetValue(IS_VISITED) = 0.0;
163 
164  unsigned int visited_nodes = 0;
165  Element::GeometryType& geom = it->GetGeometry();
166 
167  for (unsigned int kk = 0; kk < TDim + 1; kk++)
168  {
169  if (geom[kk].GetValue(IS_VISITED) == 1)
170  visited_nodes += 1;
171  else
172  geom[kk].FastGetSolutionStepValue(rDistanceVar) = max_distance;
173  }
174 
175  //save in the elements to solve if just one node is missing to be determined
176  if (visited_nodes == TDim)
177  {
178  elements_to_solve.push_back(*(it.base()));
179  it->GetValue(IS_VISITED) = 1;
180  }
181 
182  }
183  //KRATOS_WATCH(elements_to_solve.size());
184 
185  //this is the "total" solution loop
188 
190 
191  while (elements_to_solve.size() != 0)
192  {
193 // KRATOS_WATCH(elements_to_solve.size());
194  //compute all of the candidate elements
195  for (unsigned int current_position = 0; current_position != elements_to_solve.size(); current_position++)
196  {
197  PointerVector< Element >::iterator current_element = (elements_to_solve.begin() + current_position);
198  Geometry< Node >& geom = current_element->GetGeometry();
199 
200  unsigned int unknown_node_index = 0;
201 
202 
203 
204  double Volume;
205  GeometryUtils::CalculateGeometryData(geom, DN_DX, N, Volume);
206 
207  //compute discriminant
208  noalias(d) = ZeroVector(TDim);
209  for (unsigned int iii = 0; iii < TDim + 1; iii++)
210  {
211  const double distance = geom[iii].FastGetSolutionStepValue(rDistanceVar);
212  double node_is_known = geom[iii].GetValue(IS_VISITED);
213  if (node_is_known == 1) //identyfing the unknown node
214  for (unsigned int jjj = 0; jjj < TDim; jjj++)
215  d[jjj] += DN_DX(iii, jjj) * distance;
216  else
217  unknown_node_index = iii;
218  }
219 
220  //finalizing computation of discriminant
221  double c = -1.0;
222  double a = 0.0;
223  double b = 0.0;
224  for (unsigned int jjj = 0; jjj < TDim; jjj++)
225  {
226  a += DN_DX(unknown_node_index, jjj) * DN_DX(unknown_node_index, jjj);
227  b += d[jjj] * DN_DX(unknown_node_index, jjj);
228  c += d[jjj] * d[jjj];
229  }
230  b *= 2.0;
231  double distance;
232  double discriminant = b * b - 4.0 * a*c;
233 
234  if (discriminant < 0.0) //element distance computation fails - we may have to tread specially this node
235  {
236  distance = -b / (2.0*a);
237 // failed_nodes.push_back(geom(unknown_node_index));
238  }
239  else
240  {
241  //(accurate) computation of the distance
242  //requires the solution of a*x^2+b*x+c=0
243  double q, root1, root2;/*, distance*/;
244  double sqrt_det = sqrt(discriminant);
245  if (a != 0.0)
246  {
247  if (b > 0) q = -0.5 * (b + sqrt_det);
248  else q = -0.5 * (b - sqrt_det);
249  root1 = q / a;
250  root2 = c / q;
251  if (root1 > root2) distance = root1;
252  else distance = root2;
253  }
254  else //in this case we have a linear equation
255  {
256  distance = -c / b;
257  }
258 
259  //saving the distance
260  active_nodes.push_back(geom(unknown_node_index)); //save the pointer to the node to update
261  node_distance_values.push_back(distance); //save a value
262  // geom[unknown_node_index].FastGetSolutionStepValue(rDistanceVar) = distance;
263  // geom[unknown_node_index].GetValue(IS_VISITED) = 1.0;
264  }
265  }
266  // }
267 
268  //now loop over all of the active nodes, and assign the minimum value of distance
269  for (unsigned int k = 0; k < active_nodes.size(); k++)
270  {
271 // std::cout << " " << active_nodes[k].Id() << " " << active_nodes[k].FastGetSolutionStepValue(rDistanceVar) <<" " << node_distance_values[k];
272  if (active_nodes(k)->FastGetSolutionStepValue(rDistanceVar) > node_distance_values[k])
273  active_nodes(k)->FastGetSolutionStepValue(rDistanceVar) = node_distance_values[k];
274 // std::cout << " " << active_nodes[k].FastGetSolutionStepValue(rDistanceVar) << std::endl;
275  active_nodes(k)->GetValue(IS_VISITED) = 1;
276  }
277 
278 
279  //CHAPUZA TEST
280 // for (PointerVector< Node >::iterator it = failed_nodes.begin(); it != failed_nodes.end(); it++)
281 // {
282 // if (it->GetValue(IS_VISITED) != 1) //it was not possible to calculate the distance
283 // {
284 // for (GlobalPointersVector< Element >::iterator ie = it->GetValue(NEIGHBOUR_ELEMENTS).begin();
285 // ie != it->GetValue(NEIGHBOUR_ELEMENTS).end(); ie++)
286 // ie->GetValue(IS_VISITED)=1;
287 // }
288 // }
289 
290 // KRATOS_WATCH(active_nodes.size());
291 // KRATOS_WATCH(node_distance_values.size());
292 //
293 // unsigned int k=0;
294 // for (PointerVector< Node >::iterator it = active_nodes.begin(); it != active_nodes.end(); it++)
295 // {
296 // if (it->FastGetSolutionStepValue(rDistanceVar) > node_distance_values[k])
297 // it->FastGetSolutionStepValue(rDistanceVar) = node_distance_values[k];
298 //
299 // it->GetValue(IS_VISITED) = 1.0;
300 // k++;
301 // }
302 
303 
304 
305  elements_to_solve.clear();
306 
307 
308  //now loop over all of the active nodes, and assign the minimum value of distance
309  for (PointerVector< Node >::iterator it = active_nodes.begin(); it != active_nodes.end(); it++)
310  {
311  if(it->FastGetSolutionStepValue(rDistanceVar) < max_distance)
312  {
313  //loop over neighbour elements and add them to the todo list
314  // for (GlobalPointersVector< Element >::iterator ie = it->GetValue(NEIGHBOUR_ELEMENTS).ptr_begin();
315  // ie != it->GetValue(NEIGHBOUR_ELEMENTS).ptr_end(); ie++)
316  for(auto ie : it->GetValue(NEIGHBOUR_ELEMENTS).GetContainer())
317  {
318  unsigned int visited_nodes = 0;
319  Element::GeometryType& geom = ie->GetGeometry();
320 
321  for (unsigned int kk = 0; kk < TDim + 1; kk++)
322  {
323  if (geom[kk].GetValue(IS_VISITED) == 1)
324  visited_nodes += 1;
325  }
326 
327  if (visited_nodes == TDim)
328  if( ie->GetValue(IS_VISITED) != 1 ) //it is to be used for the next step (an was not added before by another element)
329  {
330  ie->GetValue(IS_VISITED) = 1;
331  elements_to_solve.push_back( Element::Pointer(ie->shared_from_this()) );
332  }
333 
334  // if(visited_nodes == TDim+1)
335  // std::cout << "should not add the element" << ie->Id() << std::endl;
336 
337  }
338  }
339  }
340 
341 
342 
343  //erase working arrays
344  active_nodes.clear();
345  node_distance_values.clear();
346 
347 
348  }
349 
350 
351 
352  //approximate computation of distance on failed nodes
353  unsigned int confirmed_failures = 0;
354  for (PointerVector< Node >::iterator it = failed_nodes.begin(); it != failed_nodes.end(); it++)
355  {
356  if (it->GetValue(IS_VISITED) != 1 ) //it was not possible to calculate the distance
357  {
358  confirmed_failures++;
359  double davg = 0.0;
360  double counter = 0.0;
361  for (GlobalPointersVector< Node >::iterator in = it->GetValue(NEIGHBOUR_NODES).begin(); in != it->GetValue(NEIGHBOUR_NODES).end(); in++)
362  {
363  if (in->GetValue(IS_VISITED) == 1)
364  {
365  davg += in->FastGetSolutionStepValue(rDistanceVar);
366  counter += 1.0;
367  }
368  }
369 //CHAPUZA WITH MAX DISTANCE
370  if (counter != 0.0)
371  {
372  double estimated_distance = davg / counter;
373  if(estimated_distance < max_distance)
374  it->FastGetSolutionStepValue(rDistanceVar) = estimated_distance;
375  else
376  it->FastGetSolutionStepValue(rDistanceVar) = max_distance;
377  }
378  else
379  {
380  KRATOS_WATCH("distance computation failed for node:");
381  KRATOS_WATCH(it->Id());
382  // KRATOS_WATCH("distance is set to zero:");
383  //it->FastGetSolutionStepValue(rDistanceVar) = 0.0;
384  KRATOS_THROW_ERROR(std::logic_error, "no neighbour nodes was succesfully computed ... impossible to recover", "");
385  }
386  }
387  }
388 
389  //set all of the elements as not visited
390 
391 
392 
393 
394  KRATOS_CATCH("")
395 
396  }
397 
398 
399 
417 private:
425  //this function adds the Contribution of one of the geometries
426  //to the corresponding nodes
427 
434  class CompareElementDistance
435  {
436  public:
437 
438  CompareElementDistance(const Variable<double>& rDistanceVar) : mrDistanceVar(rDistanceVar) { }
439 
440  bool operator()(const Element::Pointer a,
441  const Element::Pointer b) const
442  {
443  return a->GetValue(mrDistanceVar) < b->GetValue(mrDistanceVar);
444  }
445 
446  private:
447  const Variable<double>& mrDistanceVar;
448 
449  };
469  //BodyDistanceCalculationUtils(void);
470 
471  //BodyDistanceCalculationUtils(BodyDistanceCalculationUtils& rSource);
472 
473 
476 }; /* Class ClassName */
477 
486 } /* namespace Kratos.*/
487 
488 #endif /* KRATOS_BODY_DISTANCE_CALCULATION_UTILS defined */
489 
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
virtual ~BodyDistanceCalculationUtils()
Definition: body_distance_calculation_utils.h:107
ModelPart::NodesContainerType NodesArrayType
Definition: body_distance_calculation_utils.h:97
BodyDistanceCalculationUtils()
Definition: body_distance_calculation_utils.h:106
ModelPart::ElementsContainerType ElementsArrayType
Definition: body_distance_calculation_utils.h:98
Geometry base class.
Definition: geometry.h:71
void push_back(PointPointerType x)
Definition: geometry.h:548
TVariableType::Type & GetValue(const TVariableType &rThisVariable)
Definition: geometry.h:627
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
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
void clear()
Definition: pointer_vector.h:309
size_type size() const
Definition: pointer_vector.h:255
iterator end()
Definition: pointer_vector.h:177
void reserve(size_type dim)
Definition: pointer_vector.h:319
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: pointer_vector.h:89
iterator begin()
Definition: pointer_vector.h:169
void push_back(const TPointerType &x)
Definition: pointer_vector.h:270
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
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
iterator begin()
Returns an iterator pointing to the beginning of the container.
Definition: pointer_vector_set.h:278
iterator end()
Returns an iterator pointing to the end of the container.
Definition: pointer_vector_set.h:314
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_WATCH(variable)
Definition: define.h:806
#define KRATOS_TRY
Definition: define.h:109
Parameters GetValue(Parameters &rParameters, const std::string &rEntry)
Definition: add_kratos_parameters_to_python.cpp:53
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
q
Definition: generate_convection_diffusion_explicit_element.py:109
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
int d
Definition: ode_solve.py:397
int k
Definition: quadrature.py:595
int counter
Definition: script_THERMAL_CORRECT.py:218
N
Definition: sensitivityMatrix.py:29