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.
trigen_droplet_refine.h
Go to the documentation of this file.
1 // KRATOS __ __ _____ ____ _ _ ___ _ _ ____
2 // | \/ | ____/ ___|| | | |_ _| \ | |/ ___|
3 // | |\/| | _| \___ \| |_| || || \| | | _
4 // | | | | |___ ___) | _ || || |\ | |_| |
5 // |_| |_|_____|____/|_| |_|___|_| \_|\____| APPLICATION
6 //
7 // License: BSD License
8 // license: MeshingApplication/license.txt
9 //
10 // Main authors:
11 //
12 
13 #if !defined(KRATOS_TRIGEN_DROPLET_MODELER_H_INCLUDED )
14 #define KRATOS_TRIGEN_DROPLET_MODELER_H_INCLUDED
15 
16 // System includes
17 
18 // External includes
19 #include "triangle.h"
20 
21 // Project includes
22 #include "includes/define.h"
23 #include "includes/model_part.h"
28 #include "utilities/timer.h"
29 
30 namespace Kratos
31 {
32 extern "C" {
33  void triangulate(char *, struct triangulateio *, struct triangulateio *,struct triangulateio *);
34  //void trifree();
35 }
36 
37 
40 
44 
48 
52 
56 
58 
61 {
62 public:
65 
68  typedef Node PointType;
69  typedef Node::Pointer PointPointerType;
70  typedef std::vector<PointType::Pointer> PointVector;
71  typedef PointVector::iterator PointIterator;
72  typedef std::vector<double> DistanceVector;
73  typedef std::vector<double>::iterator DistanceIterator;
76 
80 
83  mJ(ZeroMatrix(2,2)), //local jacobian
84  mJinv(ZeroMatrix(2,2)), //inverse jacobian
85  mC(ZeroVector(2)), //dimension = number of nodes
86  mRhs(ZeroVector(2)) {}
87  //mpNodeEraseProcess(NULL){} //dimension = number of nodes
88 
90  virtual ~TriGenDropletModeler() {}
91 
92 
96 
97 
101 
102 
103  //*******************************************************************************************
104  //*******************************************************************************************
106  ModelPart& ThisModelPart ,
107  Element const& rReferenceElement,
108  Condition const& rReferenceBoundaryCondition,
109  EntitiesEraseProcess<Node>& node_erase, bool rem_nodes = true, bool add_nodes=true,
110  double my_alpha = 1.4, double h_factor=0.5)
111  {
112 
113  KRATOS_TRY
114  if (ThisModelPart.NodesBegin()->SolutionStepsDataHas(IS_FREE_SURFACE)==false )
115  KRATOS_THROW_ERROR(std::logic_error,"Add ----IS_FREE_SURFACE---- variable!!!!!! ERROR","");
116  if (ThisModelPart.NodesBegin()->SolutionStepsDataHas(IS_STRUCTURE)==false )
117  KRATOS_THROW_ERROR(std::logic_error,"Add ----IS_STRUCTURE---- variable!!!!!! ERROR","");
118  if (ThisModelPart.NodesBegin()->SolutionStepsDataHas(IS_BOUNDARY)==false )
119  KRATOS_THROW_ERROR(std::logic_error,"Add ----IS_BOUNDARY---- variable!!!!!! ERROR","");
120  if (ThisModelPart.NodesBegin()->SolutionStepsDataHas(IS_FLUID)==false )
121  KRATOS_THROW_ERROR(std::logic_error,"Add ----IS_FLUID---- variable!!!!!! ERROR","");
122 
123  KRATOS_WATCH("Trigen Droplet Refining Mesher")
124  const auto inital_time = std::chrono::steady_clock::now();
125 
126 
127 //clearing elements
128 
129  int step_data_size = ThisModelPart.GetNodalSolutionStepDataSize();
130 
131 
132  ThisModelPart.Elements().clear();
133 
134  //20150909 ajarauta
135  int id = (ThisModelPart.Nodes().end() - 1)->Id() + 1;
136  for(ModelPart::ConditionsContainerType::iterator ic = ThisModelPart.ConditionsBegin() ;
137  ic != ThisModelPart.ConditionsEnd() ; ic++)
138  {
139  if (ic->GetGeometry().size()==2)
140  {
141 // KRATOS_WATCH("LALALALLA")
142  //Original:
143  unsigned int n_flag=ic->GetGeometry()[0].FastGetSolutionStepValue(IS_FREE_SURFACE);
144  n_flag+=ic->GetGeometry()[1].FastGetSolutionStepValue(IS_FREE_SURFACE);
145  //Enhanced for any segment at the boundary
146 // int n_flag=ic->GetGeometry()[0].FastGetSolutionStepValue(IS_BOUNDARY);
147 // n_flag+=ic->GetGeometry()[1].FastGetSolutionStepValue(IS_BOUNDARY);
148  unsigned int n_trip=ic->GetGeometry()[0].FastGetSolutionStepValue(TRIPLE_POINT);
149  n_trip+=ic->GetGeometry()[1].FastGetSolutionStepValue(TRIPLE_POINT);
150  //Only for IS_STRUCTURE segments
151  unsigned int n_struct=ic->GetGeometry()[0].FastGetSolutionStepValue(IS_STRUCTURE);
152  n_struct+=ic->GetGeometry()[1].FastGetSolutionStepValue(IS_STRUCTURE);
153  unsigned int n_sum = n_flag + n_trip;
154 
155  //THIS REFINES THE NODES OF INTERNAL ELEMENTS OF THE SURFACE WHERE THE INBLOW IS: FLAG_VAR=1
156  if (n_flag==ic->GetGeometry().size() || n_struct==ic->GetGeometry().size() || n_sum==ic->GetGeometry().size())
157 // if (n_struct==ic->GetGeometry().size())
158  {
159  double x0=ic->GetGeometry()[0].X();
160  double y0=ic->GetGeometry()[0].Y();
161  double x1=ic->GetGeometry()[1].X();
162  double y1=ic->GetGeometry()[1].Y();
163  double edge01=sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
164 
165  //ajarauta: position correction of the middle node -> CHECK WHAT HAPPENS FOR TRIPLE POINT!!
166  // NORMAL is set to 0 in triple_point in the monolithic_embedded_solver right now...
167  /*
168  double n0x, n0y, n0norm, n0xunit,n0yunit,n1x,n1y,n1norm,n1xunit,n1yunit, x01, y01, xM, yM;
169  double v01norm, scprod, costh, delt_dist, ndx, ndy, ndx_d, ndy_d, ndxnorm;
170  double curv0 = ic->GetGeometry()[0].FastGetSolutionStepValue(CURVATURE);
171  double curv1 = ic->GetGeometry()[1].FastGetSolutionStepValue(CURVATURE);
172  double mean_curv = 0.5*(curv0 + curv1);
173  double is_flat = 0.0;
174  double xp = 0.0;
175  double yp = 0.0;
176  double n_struct = 0.0;
177  n_struct += ic->GetGeometry()[0].FastGetSolutionStepValue(IS_STRUCTURE);
178  n_struct += ic->GetGeometry()[1].FastGetSolutionStepValue(IS_STRUCTURE);
179  if (mean_curv == 0.0 || n_struct > 1.0)
180  is_flat = 1.0;
181  if (mean_curv != 0.0 && n_struct > 1.0) //avoid cases when alpha shape deletes an element with two IS_STRUCTURE nodes
182  {
183  n0x = ic->GetGeometry()[0].FastGetSolutionStepValue(NORMAL_X);
184  n0y = ic->GetGeometry()[0].FastGetSolutionStepValue(NORMAL_Y);
185  n0norm = sqrt(n0x*n0x + n0y*n0y);
186  n0xunit = n0x/n0norm;
187  n0yunit = n0y/n0norm;
188  n1x = ic->GetGeometry()[1].FastGetSolutionStepValue(NORMAL_X);
189  n1y = ic->GetGeometry()[1].FastGetSolutionStepValue(NORMAL_Y);
190  n1norm = sqrt(n1x*n1x + n1y*n1y);
191  n1xunit = n1x/n1norm;
192  n1yunit = n1y/n1norm;
193  x01 = x1-x0;
194  y01 = y1-y0;
195  v01norm = sqrt(x01*x01 + y01*y01);
196  scprod = (-n1yunit)*x01 + n1xunit*y01;
197  if (scprod < 0.0)
198  costh = scprod/v01norm;
199  else
200  costh = -scprod/v01norm;
201  delt_dist = (1.0 + costh)/mean_curv;
202  ndx = 0.5*(n0xunit+n1xunit);
203  ndy = 0.5*(n0yunit+n1yunit);
204  ndxnorm = sqrt(ndx*ndx+ndy*ndy);
205  ndx_d = ndx*delt_dist/ndxnorm;
206  ndy_d = ndy*delt_dist/ndxnorm;
207  xM = 0.5*(x0+x1);
208  yM = 0.5*(y0+y1);
209  xp = xM + ndx_d;
210  yp = yM + ndy_d;
211  }
212  */
213 
215  // IMPORTANT!!
216  // The following step only makes sense if NODAL_LENGTH is the initial value and is taken as a reference
217  // for remeshing. If it is calculated every time step, it will never fulfill the condition
218  // edge01 > factor*nodal_h!!!
220  double nodal_h=ic->GetGeometry()[0].FastGetSolutionStepValue(NODAL_H);
221  nodal_h+=ic->GetGeometry()[1].FastGetSolutionStepValue(NODAL_H);
222  nodal_h*=0.5;
223  //if the edge of the segment (condition) is too long, we split it into two by adding a node in the middle
224 
225  Node::DofsContainerType& reference_dofs = (ThisModelPart.NodesBegin())->GetDofs();
226 
227 
228  double factor=2.0;
229  if (edge01>factor*nodal_h)
230  {
231  id++;
232  double x = 0.5*(x0+x1);
233  double y = 0.5*(y0+y1);;
234  double z = 0.0;
235  Node::Pointer pnode = ThisModelPart.CreateNewNode(id,x,y,z);
236 
237  //putting the new node also in an auxiliary list
238  //KRATOS_WATCH("adding nodes to list")
239 
240  //std::cout << "new node id = " << pnode->Id() << std::endl;
241  //generating the dofs
242  for(Node::DofsContainerType::iterator iii = reference_dofs.begin(); iii != reference_dofs.end(); iii++)
243  {
244  Node::DofType& rDof = **iii;
245  Node::DofType::Pointer p_new_dof = pnode->pAddDof( rDof );
246  (p_new_dof)->FreeDof();
247  }
248  Geometry<Node >& geom = ic->GetGeometry();
249 
250  InterpolateOnEdge(geom, 0, 1, step_data_size, pnode);
251  const array_1d<double,3>& disp = pnode->FastGetSolutionStepValue(DISPLACEMENT);
252  pnode->X0() = pnode->X() - disp[0];
253  pnode->Y0() = pnode->Y() - disp[1];
254  KRATOS_WATCH("Added node at the EDGE")
255  }
256 
257  }
258  }
259  }
260 
261 
262  ThisModelPart.Conditions().clear();
263 
265 
266 
267 
268  // bucket types
269  //typedef Bucket<3, PointType, ModelPart::NodesContainerType, PointPointerType, PointIterator, DistanceIterator > BucketType;
270  //typedef Bins< 3, PointType, PointVector, PointPointerType, PointIterator, DistanceIterator > StaticBins;
271  // bucket types
272 
273  //typedef Tree< StaticBins > Bin; //Binstree;
274  unsigned int bucket_size = 20;
275 
276  //performing the interpolation - all of the nodes in this list will be preserved
277  unsigned int max_results = 100;
278  //PointerVector<PointType> res(max_results);
279  //NodeIterator res(max_results);
280  PointVector res(max_results);
281  DistanceVector res_distances(max_results);
282  Node work_point(0,0.0,0.0,0.0);
283  //if the remove_node switch is activated, we check if the nodes got too close
284 
285  if (rem_nodes==true)
286  {
287  PointVector list_of_nodes;
288  list_of_nodes.reserve(ThisModelPart.Nodes().size());
289  for(ModelPart::NodesContainerType::iterator i_node = ThisModelPart.NodesBegin() ; i_node != ThisModelPart.NodesEnd() ; i_node++)
290  {
291  (list_of_nodes).push_back(*(i_node.base()));
292  }
293 
294  KdtreeType nodes_tree1(list_of_nodes.begin(),list_of_nodes.end(), bucket_size);
295 
296  RemoveCloseNodes(ThisModelPart, nodes_tree1, node_erase, h_factor);
297  }
298 
300  // //
301  // Now we shall pass the Alpha Shape for the second time, having the "bad nodes" removed //
303  //creating the containers for the input and output
304  struct triangulateio in_mid;
305  struct triangulateio out_mid;
306  struct triangulateio vorout_mid;
307 
308  initialize_triangulateio(in_mid);
309  initialize_triangulateio(out_mid);
310  initialize_triangulateio(vorout_mid);
311 
312  //assigning the size of the input containers
313 
314  in_mid.numberofpoints = ThisModelPart.Nodes().size();
315  in_mid.pointlist = (REAL *) malloc(in_mid.numberofpoints * 2 * sizeof(REAL));
316 
317  //reorder the id's and give the coordinates to the mesher
318  ModelPart::NodesContainerType::iterator nodes_begin = ThisModelPart.NodesBegin();
319  for(unsigned int i = 0; i<ThisModelPart.Nodes().size(); i++)
320  {
321  int base = i*2;
322  //int base = ((nodes_begin + i)->Id() - 1 ) * 2;
323 
324  //from now on it is consecutive
325  (nodes_begin + i)->SetId(i+1);
326 // (nodes_begin + i)->Id() = i+1;
327 
328  in_mid.pointlist[base] = (nodes_begin + i)->X();
329  in_mid.pointlist[base+1] = (nodes_begin + i)->Y();
330 
331  auto& node_dofs = (nodes_begin + i)->GetDofs();
332  for(auto iii = node_dofs.begin(); iii != node_dofs.end(); iii++)
333  {
334  (**iii).SetEquationId(i+1);
335  }
336  }
337  //in_mid.numberoftriangles = ThisModelPart.Elements().size();
338  //in_mid.trianglelist = (int*) malloc(in_mid.numberoftriangles * 3 * sizeof(int));
339 
340  // "P" suppresses the output .poly file. Saves disk space, but you
341  //lose the ability to maintain constraining segments on later refinements of the mesh.
342  // "B" Suppresses boundary markers in the output .node, .poly, and .edge output files
343  // "n" outputs a list of triangles neighboring each triangle.
344  // "e" outputs edge list (i.e. all the "connectivities")
345  char options1[] = "Pne";
346  triangulate(options1, &in_mid, &out_mid, &vorout_mid);
347  //print out the mesh generation time
348  std::cout << "mesh generation time = " << Timer::ElapsedSeconds(inital_time) << std::endl;
349  //number of newly generated triangles
350  unsigned int el_number=out_mid.numberoftriangles;
351 
352  //PASSING THE CREATED ELEMENTS TO THE ALPHA-SHAPE
353  std::vector<int> preserved_list1(el_number);
354  preserved_list1.resize(el_number);
355 
356  int number_of_preserved_elems= PassAlphaShape(ThisModelPart, preserved_list1, el_number, my_alpha, out_mid);
357 
358  //freeing memory
359 
360  clean_triangulateio(in_mid);
361  clean_triangulateio(vorout_mid);
362  KRATOS_WATCH("ln367");
363  //NOW WE SHALL PERFORM ADAPTIVE REMESHING, i.e. insert and remove nodes based upon mesh quality
364  // and prescribed sizes
365  struct triangulateio in2;
366  struct triangulateio out2;
367  struct triangulateio vorout2;
368 
369  initialize_triangulateio(in2);
370  initialize_triangulateio(out2);
371  initialize_triangulateio(vorout2);
372 
373 // in2.firstnumber = 1;
374  in2.numberofpoints = ThisModelPart.Nodes().size();
375  in2.pointlist = (REAL *) malloc(in2.numberofpoints * 2 * sizeof(REAL));
376 
377  //writing the input point list
378  for(unsigned int i = 0; i<ThisModelPart.Nodes().size(); i++)
379  {
380  int base = i*2;
381  in2.pointlist[base] = (nodes_begin + i)->X();
382  in2.pointlist[base+1] = (nodes_begin + i)->Y();
383  }
384  in2.numberoftriangles=number_of_preserved_elems;
385 
386  in2.trianglelist = (int *) malloc(in2.numberoftriangles * 3 * sizeof(int));
387  in2.trianglearealist = (REAL *) malloc(in2.numberoftriangles * sizeof(REAL));
388 // in2.trianglelist = new int[in2.numberoftriangles * 3];
389 // in2.trianglearealist = new double[in2.numberoftriangles];
390 
391  KRATOS_WATCH(el_number);
392  int counter = 0;
393  //here I will assign a huge number of NODAL_H to the free surface nodes, so that there no nodes will be added
394  for(ModelPart::NodesContainerType::iterator i_node = ThisModelPart.NodesBegin() ; i_node != ThisModelPart.NodesEnd() ; i_node++)
395  {
396  if (i_node->FastGetSolutionStepValue(IS_FREE_SURFACE)!=0)
397  {
398 
399  double& val=i_node->FastGetSolutionStepValue(NODAL_H);
400  val*=2.0;
401  //i_node->FastGetSolutionStepValue(NODAL_H,1)=val;
402  //KRATOS_WATCH("AAAAAAAAAAAAAAAAAAAAAAAA!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
403  }
404  }
405 
406 
407  for (unsigned int el=0; el<el_number; el++)
408  {
409  if( static_cast<bool>(preserved_list1[el]) == true )
410  {
411  //saving the list of ONLY preserved triangles, the ones that passed alpha-shape check
412  int new_base = counter*3;
413  int old_base = el*3;
414  //copying in case it is preserved
415  in2.trianglelist[new_base] = out_mid.trianglelist[old_base];
416  in2.trianglelist[new_base+1] = out_mid.trianglelist[old_base+1];
417  in2.trianglelist[new_base+2] = out_mid.trianglelist[old_base+2];
418 
419  //calculate the prescribed h
420  double prescribed_h = (nodes_begin + out_mid.trianglelist[old_base]-1)->FastGetSolutionStepValue(NODAL_H);
421  prescribed_h += (nodes_begin + out_mid.trianglelist[old_base+1]-1)->FastGetSolutionStepValue(NODAL_H);
422  prescribed_h += (nodes_begin + out_mid.trianglelist[old_base+2]-1)->FastGetSolutionStepValue(NODAL_H);
423  prescribed_h *= 0.3333;
424  //if h is the height of a equilateral triangle, the area is 1/2*h*h
425  in2.trianglearealist[counter] = 0.5*(1.5*prescribed_h*1.5*prescribed_h);
426  counter += 1;
427  }
428 
429  }
430  //now I set back the nodal_h
431  for(ModelPart::NodesContainerType::iterator i_node = ThisModelPart.NodesBegin() ; i_node != ThisModelPart.NodesEnd() ; i_node++)
432  {
433  if (i_node->FastGetSolutionStepValue(IS_FREE_SURFACE)!=0)
434  {
435  double& nodal_h=i_node->FastGetSolutionStepValue(NODAL_H);
436  nodal_h/=2.0;
437  }
438  }
439 
440 
441  clean_triangulateio(out_mid);
442  KRATOS_WATCH("ln420");
443  //here we generate a new mesh adding/removing nodes, by initializing "q"-quality mesh and "a"-area constraint switches
444  //
445  // MOST IMPORTANT IS "r" switch, that refines previously generated mesh!!!!!!!!!!(that is the one given inside in2)
446  //char mesh_regen_opts[] = "YYJaqrn";
447  //char mesh_regen_opts[] = "YJq1.4arn";
448  if (add_nodes==true)
449  {
450  char mesh_regen_opts[] = "YJq1.4arn";
451  triangulate(mesh_regen_opts, &in2, &out2, &vorout2);
452  KRATOS_WATCH("Adaptive remeshing executed")
453  }
454  else
455  {
456  char mesh_regen_opts[] = "YJrn";
457  triangulate(mesh_regen_opts, &in2, &out2, &vorout2);
458  KRATOS_WATCH("Non-Adaptive remeshing executed")
459  }
460 
461  //and now we shall find out where the new nodes belong to
462  //defintions for spatial search
463  typedef Node PointType;
464  typedef Node::Pointer PointPointerType;
465  typedef std::vector<PointType::Pointer> PointVector;
466  //typedef std::vector<PointType::Pointer>::iterator PointIterator;
467  typedef PointVector::iterator PointIterator;
468  typedef std::vector<double> DistanceVector;
469  typedef std::vector<double>::iterator DistanceIterator;
470  KRATOS_WATCH("ln449");
471 
473 
474  typedef Tree< KDTreePartition<BucketType> > kd_tree; //Kdtree;
475 
476  //int step_data_size = ThisModelPart.GetNodalSolutionStepDataSize();
477 
478  //creating an auxiliary list for the new nodes
479  PointVector list_of_new_nodes;
480 
481  //node to get the DOFs from
482  Node::DofsContainerType& reference_dofs = (ThisModelPart.NodesBegin())->GetDofs();
483 
484  double z = 0.0;
485  int n_points_before_refinement = in2.numberofpoints;
486  //if points were added, we add them as nodes to the ModelPart
487  if (out2.numberofpoints > n_points_before_refinement )
488  {
489  for(int i = n_points_before_refinement; i<out2.numberofpoints; i++)
490  {
491  int id=i+1;
492  int base = i*2;
493  double& x= out2.pointlist[base];
494  double& y= out2.pointlist[base+1];
495 
496  Node::Pointer pnode = ThisModelPart.CreateNewNode(id,x,y,z);
497 
498  pnode->SetBufferSize(ThisModelPart.NodesBegin()->GetBufferSize() );
499 
500  list_of_new_nodes.push_back( pnode );
501 
502  //std::cout << "new node id = " << pnode->Id() << std::endl;
503  //generating the dofs
504  for(Node::DofsContainerType::iterator iii = reference_dofs.begin(); iii != reference_dofs.end(); iii++)
505  {
506  Node::DofType& rDof = **iii;
507  Node::DofType::Pointer p_new_dof = pnode->pAddDof( rDof );
508 
509  (p_new_dof)->FreeDof();
510 // (p_new_dof)->EquationId() = -1;
511 
512  }
513 
514  }
515  }
516 
517  std::cout << "During refinement we added " << out2.numberofpoints-n_points_before_refinement<< " nodes " <<std::endl;
518  //unsigned int bucket_size = 20;
519  //performing the interpolation - all of the nodes in this list will be preserved
520  //unsigned int max_results = 50;
521  //PointVector results(max_results);
522  //DistanceVector results_distances(max_results);
524 
526 
527  //int number_of_preserved_elems=0;
528 
529  int point_base;
530  //WHAT ARE THOSE????
531 // Node work_point(0,0.0,0.0,0.0);
532  unsigned int MaximumNumberOfResults = list_of_new_nodes.size();
533  PointVector Results(MaximumNumberOfResults);
534  DistanceVector ResultsDistances(MaximumNumberOfResults);
535 
536  step_data_size = ThisModelPart.GetNodalSolutionStepDataSize();
537 
538  if(out2.numberofpoints-n_points_before_refinement > 0) //if we added points
539  {
540 
541  kd_tree nodes_tree2(list_of_new_nodes.begin(),list_of_new_nodes.end(),bucket_size);
542  nodes_begin = ThisModelPart.NodesBegin();
543 
544  for(int el = 0; el< in2.numberoftriangles; el++)
545  {
546  int base = el * 3;
547  //coordinates
548  point_base = (in2.trianglelist[base] - 1)*2;
549  x1[0] = in2.pointlist[point_base];
550  x1[1] = in2.pointlist[point_base+1];
551 
552  point_base = (in2.trianglelist[base+1] - 1)*2;
553  x2[0] = in2.pointlist[point_base];
554  x2[1] = in2.pointlist[point_base+1];
555 
556  point_base = (in2.trianglelist[base+2] - 1)*2;
557  x3[0] = in2.pointlist[point_base];
558  x3[1] = in2.pointlist[point_base+1];
559 
560 
561  //find the center and "radius" of the element
562  double xc, yc, radius;
563  CalculateCenterAndSearchRadius( x1[0], x1[1],
564  x2[0], x2[1],
565  x3[0], x3[1],
566  xc,yc,radius);
567 
568  //find all of the new nodes within the radius
569  int number_of_points_in_radius;
570  work_point.X() = xc;
571  work_point.Y() = yc;
572  work_point.Z() = 0.0;
573 
574  number_of_points_in_radius = nodes_tree2.SearchInRadius(work_point, radius*1.01, Results.begin(),
575  ResultsDistances.begin(), MaximumNumberOfResults);
576 
577  Triangle2D3<Node > geom(
578  *( (nodes_begin + in2.trianglelist[base]-1).base() ),
579  *( (nodes_begin + in2.trianglelist[base+1]-1).base() ),
580  *( (nodes_begin + in2.trianglelist[base+2]-1).base() )
581  );
582 
583  //check if inside and eventually interpolate
584  for( PointIterator it_found = Results.begin(); it_found != Results.begin() + number_of_points_in_radius; it_found++)
585  {
586  bool is_inside = false;
587  is_inside = CalculatePosition(x1[0], x1[1],
588  x2[0], x2[1],
589  x3[0], x3[1],
590  (*it_found)->X(),(*it_found)->Y(),N);
591 
592 
593  if(is_inside == true)
594  {
595  Interpolate( geom, N, step_data_size, *(it_found ) );
596 
597  }
598  }
599  }
600  }
601 
602  ThisModelPart.Elements().clear();
603 
604  //set the coordinates to the original value
605  for( PointVector::iterator it = list_of_new_nodes.begin(); it!=list_of_new_nodes.end(); it++)
606  {
607  const array_1d<double,3>& disp = (*it)->FastGetSolutionStepValue(DISPLACEMENT);
608  (*it)->X0() = (*it)->X() - disp[0];
609  (*it)->Y0() = (*it)->Y() - disp[1];
610  (*it)->Z0() = 0.0;
611  }
612  //cleaning unnecessary data
613  //in2.deinitialize();
614  //in2.initialize();
615  //free( in2.pointlist );
616 
617  //add preserved elements to the kratos
618  Properties::Pointer properties = ThisModelPart.GetMesh().pGetProperties(1);
619  nodes_begin = ThisModelPart.NodesBegin();
620  (ThisModelPart.Elements()).reserve(out2.numberoftriangles);
621 
622  for(int iii = 0; iii< out2.numberoftriangles; iii++)
623  {
624  int id = iii + 1;
625  int base = iii * 3;
626  Triangle2D3<Node > geom(
627  *( (nodes_begin + out2.trianglelist[base]-1).base() ),
628  *( (nodes_begin + out2.trianglelist[base+1]-1).base() ),
629  *( (nodes_begin + out2.trianglelist[base+2]-1).base() )
630  );
631 
632 
633 #ifdef _DEBUG
634  ModelPart::NodesContainerType& ModelNodes = ThisModelPart.Nodes();
635  if( *(ModelNodes).find( out2.trianglelist[base]).base() == *(ThisModelPart.Nodes().end()).base() )
636  KRATOS_THROW_ERROR(std::logic_error,"trying to use an inexisting node","");
637  if( *(ModelNodes).find( out2.trianglelist[base+1]).base() == *(ThisModelPart.Nodes().end()).base() )
638  KRATOS_THROW_ERROR(std::logic_error,"trying to use an inexisting node","");
639  if( *(ModelNodes).find( out2.trianglelist[base+2]).base() == *(ThisModelPart.Nodes().end()).base() )
640  KRATOS_THROW_ERROR(std::logic_error,"trying to use an inexisting node","");
641 
642 #endif
643 
644  Element::Pointer p_element = rReferenceElement.Create(id, geom, properties);
645  (ThisModelPart.Elements()).push_back(p_element);
646 
647  }
648  ThisModelPart.Elements().Sort();
649 
650  //filling the neighbour list
651  ModelPart::ElementsContainerType::const_iterator el_begin = ThisModelPart.ElementsBegin();
652  for(ModelPart::ElementsContainerType::const_iterator iii = ThisModelPart.ElementsBegin();
653  iii != ThisModelPart.ElementsEnd(); iii++)
654  {
655  //Geometry< Node >& geom = iii->GetGeometry();
656  int base = ( iii->Id() - 1 )*3;
657 
658  (iii->GetValue(NEIGHBOUR_ELEMENTS)).resize(3);
659  GlobalPointersVector< Element >& neighb = iii->GetValue(NEIGHBOUR_ELEMENTS);
660  for(int i = 0; i<3; i++)
661  {
662  int index = out2.neighborlist[base+i];
663  if(index > 0)
664  neighb(i) = GlobalPointer<Element>(&*(el_begin + index-1));
665  else
666  neighb(i) = Element::WeakPointer();
667  }
668  }
669  //identifying boundary, creating skin
670  IdentifyBoundary(ThisModelPart, rReferenceBoundaryCondition, properties, out2);
671 
672  KRATOS_WATCH("ln749");
673 
674  clean_triangulateio(in2);
675  KRATOS_WATCH("ln752");
676  clean_triangulateio(out2);
677  KRATOS_WATCH("ln754");
678  clean_triangulateio(vorout2);
679  KRATOS_WATCH("Finished remeshing with Trigen_Droplet_Refine")
680 
681  KRATOS_CATCH("")
682  }
683 
684 
688 
689 
693 
694 
698 
700  virtual std::string Info() const
701  {
702  return "";
703  }
704 
706  virtual void PrintInfo(std::ostream& rOStream) const {}
707 
709  virtual void PrintData(std::ostream& rOStream) const {}
710 
711 
715 
716 
718 
719 protected:
722 
723 
727  //KdtreeType mKdtree;
728 
732 
733 
737 
738 
742 
743 
747 
748 
752 
753 
755 
756 private:
759 
760 
764  boost::numeric::ublas::bounded_matrix<double,2,2> mJ; //local jacobian
765  boost::numeric::ublas::bounded_matrix<double,2,2> mJinv; //inverse jacobian
766  array_1d<double,2> mC; //center pos
767  array_1d<double,2> mRhs; //center pos
768  //EntitiesEraseProcess<Node>* mpNodeEraseProcess;
769 
770 
774  void RemoveCloseNodes(ModelPart& ThisModelPart, KdtreeType& nodes_tree1, EntitiesEraseProcess<Node>& node_erase, double& h_factor)
775  {
776  //unsigned int bucket_size = 20;
777 
778  //performing the interpolation - all of the nodes in this list will be preserved
779  unsigned int max_results = 100;
780  //PointerVector<PointType> res(max_results);
781  //NodeIterator res(max_results);
782  PointVector res(max_results);
783  DistanceVector res_distances(max_results);
784  Node work_point(0,0.0,0.0,0.0);
785 
786  unsigned int n_points_in_radius;
787  //radius means the distance, closer than which no node shall be allowd. if closer -> mark for erasing
788  double radius;
789 
790  for(ModelPart::NodesContainerType::const_iterator in = ThisModelPart.NodesBegin(); in != ThisModelPart.NodesEnd(); in++)
791  {
792  radius=h_factor*in->FastGetSolutionStepValue(NODAL_H);
793 
794  work_point[0]=in->X();
795  work_point[1]=in->Y();
796  work_point[2]=in->Z();
797 
798  n_points_in_radius = nodes_tree1.SearchInRadius(work_point, radius, res.begin(),res_distances.begin(), max_results);
799  if (n_points_in_radius>1)
800  {
801  if (in->FastGetSolutionStepValue(IS_BOUNDARY)==0.0 && in->FastGetSolutionStepValue(IS_STRUCTURE)==0.0)
802  {
803  //look if we are already erasing any of the other nodes
804  double erased_nodes = 0;
805  for(PointIterator i=res.begin(); i!=res.begin() + n_points_in_radius ; i++)
806  erased_nodes += in->Is(TO_ERASE);
807 
808  if( erased_nodes < 1) //we cancel the node if no other nodes are being erased
809  in->Set(TO_ERASE,true);
810 
811  }
812  else if ( (in)->FastGetSolutionStepValue(IS_STRUCTURE)!=1.0) //boundary nodes will be removed if they get REALLY close to another boundary node (0.2 * h_factor)
813  {
814  //here we loop over the neighbouring nodes and if there are nodes
815  //with IS_BOUNDARY=1 which are closer than 0.2*nodal_h from our we remove the node we are considering
816  unsigned int k = 0;
817  unsigned int counter = 0;
818  for(PointIterator i=res.begin(); i!=res.begin() + n_points_in_radius ; i++)
819  {
820  if ( (*i)->FastGetSolutionStepValue(IS_BOUNDARY,1)==1.0 && res_distances[k] < 0.2*radius && res_distances[k] > 0.0 )
821  {
822  // KRATOS_WATCH( res_distances[k] );
823  counter += 1;
824  }
825  k++;
826  }
827  if(counter > 0)
828  in->Set(TO_ERASE,true);
829  }
830  }
831 
832  }
833 
834 
835  node_erase.Execute();
836 
837  KRATOS_WATCH("Number of nodes after erasing")
838  KRATOS_WATCH(ThisModelPart.Nodes().size())
839  }
840 
841 
842  int PassAlphaShape(ModelPart& ThisModelPart, std::vector<int>& preserved_list1, unsigned int & el_number, double& my_alpha, struct triangulateio& out_mid)
843  {
844  //NOTE THAT preserved_list1 will be overwritten, only the elements that passed alpha-shaoe check will enter it
845 
846  //prepairing for alpha shape passing : creating necessary arrays
847  //list of preserved elements is created: at max el_number can be preserved (all elements)
848 
849 
850  array_1d<double,3> x1,x2,x3,xc;
851 
852  //int number_of_preserved_elems=0;
853  int number_of_preserved_elems=0;
854  int point_base;
855  //loop for passing alpha shape
856  for(unsigned int el = 0; el< el_number; el++)
857  {
858  int base = el * 3;
859 
860  //coordinates
861  point_base = (out_mid.trianglelist[base] - 1)*2;
862  x1[0] = out_mid.pointlist[point_base];
863  x1[1] = out_mid.pointlist[point_base+1];
864 
865  point_base = (out_mid.trianglelist[base+1] - 1)*2;
866  x2[0] = out_mid.pointlist[point_base];
867  x2[1] = out_mid.pointlist[point_base+1];
868 
869  point_base = (out_mid.trianglelist[base+2] - 1)*2;
870  x3[0] = out_mid.pointlist[point_base];
871  x3[1] = out_mid.pointlist[point_base+1];
872 
873  //here we shall temporarily save the elements and pass them afterwards to the alpha shape
874  Geometry<Node > temp;
875 
876  temp.push_back( *((ThisModelPart.Nodes()).find( out_mid.trianglelist[base]).base() ) );
877  temp.push_back( *((ThisModelPart.Nodes()).find( out_mid.trianglelist[base+1]).base() ) );
878  temp.push_back( *((ThisModelPart.Nodes()).find( out_mid.trianglelist[base+2]).base() ) );
879 
880  int number_of_structure_nodes = int( temp[0].FastGetSolutionStepValue(IS_STRUCTURE) );
881  number_of_structure_nodes += int( temp[1].FastGetSolutionStepValue(IS_STRUCTURE) );
882  number_of_structure_nodes += int( temp[2].FastGetSolutionStepValue(IS_STRUCTURE) );
883 
884  //check the number of nodes of boundary
885  int nfs = int( temp[0].FastGetSolutionStepValue(IS_FREE_SURFACE) );
886  nfs += int( temp[1].FastGetSolutionStepValue(IS_FREE_SURFACE) );
887  nfs += int( temp[2].FastGetSolutionStepValue(IS_FREE_SURFACE) );
888 
889  //check the number of nodes of boundary
890  int nfluid = int( temp[0].FastGetSolutionStepValue(IS_FLUID) );
891  nfluid += int( temp[1].FastGetSolutionStepValue(IS_FLUID) );
892  nfluid += int( temp[2].FastGetSolutionStepValue(IS_FLUID) );
893 
894  //check the number of nodes of boundary
895  // int nboundary = int( temp[0].FastGetSolutionStepValue(IS_BOUNDARY) );
896  // nboundary += int( temp[1].FastGetSolutionStepValue(IS_BOUNDARY) );
897  // nboundary += int( temp[2].FastGetSolutionStepValue(IS_BOUNDARY) );
898  //first check that we are working with fluid elements, otherwise throw an error
899  //if (nfluid!=3)
900  // KRATOS_ERROR(std::logic_error,"THATS NOT FLUID or NOT TRIANGLE!!!!!! ERROR","");
901  //otherwise perform alpha shape check
902 
903 
904  if(number_of_structure_nodes!=3) //if it is = 3 it is a completely fixed element -> do not add it
905  {
906 
907  if (nfs != 0 || nfluid != 3) //in this case it is close to the surface so i should use alpha shape
908  {
909 
910  if( (AlphaShape(my_alpha,temp) && number_of_structure_nodes!=3)) //if alpha shape says to preserve
911  {
912 // if(nboundary==3 && number_of_structure_nodes > 1 && nfs > 0) //if it is = 3 pressure problems -> do not add it
913 // {
914 // preserved_list1[el] = false;
915 // }
916 // else
917 // {
918  preserved_list1[el] = true;
919  number_of_preserved_elems += 1;
920 // }
921  }
922 // if (nfs == 2) //elements at boundary should ALWAYS be preserved in surface tension problems!!
923 // {
924 // preserved_list1[el] = true;
925 // number_of_preserved_elems += 1;
926 // }
927  }
928  else //internal triangle --- should be ALWAYS preserved
929  {
930  double bigger_alpha = my_alpha*10.0;
931  if( AlphaShape(bigger_alpha,temp) && number_of_structure_nodes!=3)
932  {
933 // if(nboundary==3 && number_of_structure_nodes > 1 && nfs > 0) //if it is = 3 pressure problems -> do not add it
934 // {
935 // preserved_list1[el] = false;
936 // }
937 // else
938 // {
939  preserved_list1[el] = true;
940  number_of_preserved_elems += 1;
941 // }
942  }
943  }
944  }
945  else
946  preserved_list1[el] = false;
947 
948  }
949  return number_of_preserved_elems;
950  }
951 
952 
953 
954 
955 
956  void IdentifyBoundary(ModelPart& ThisModelPart, Condition const& rReferenceBoundaryCondition, Properties::Pointer& properties, struct triangulateio& out2)
957  {
958 
959  //reset the boundary flag
960  for(ModelPart::NodesContainerType::const_iterator in = ThisModelPart.NodesBegin(); in!=ThisModelPart.NodesEnd(); in++)
961  {
962  in->FastGetSolutionStepValue(IS_BOUNDARY) = 0;
963  }
964  //filling the elemental neighbours list (from now on the elements list can not change)
965  ModelPart::ElementsContainerType::iterator elements_end = ThisModelPart.Elements().end();
966 
967  ThisModelPart.Elements().Unique();
968 
969  //now the boundary faces
970  for(ModelPart::ElementsContainerType::iterator iii = ThisModelPart.ElementsBegin(); iii != ThisModelPart.ElementsEnd(); iii++)
971  {
972  int base = ( iii->Id() - 1 )*3;
973 
974  ModelPart::ElementsContainerType::iterator el_neighb;
975  /*each face is opposite to the corresponding node number so
976  0 ----- 1 2
977  1 ----- 2 0
978  2 ----- 0 1
979  */
980 
982  //
983  //********************************************************************
984  //first face
985  el_neighb = (ThisModelPart.Elements()).find( out2.neighborlist[base] );
986  if( el_neighb == elements_end )
987  {
988  //std::cout << "node0" << std::endl;
989  //if no neighnour is present => the face is free surface
990  iii->GetGeometry()[1].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
991  iii->GetGeometry()[2].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
992 
993  //Generate condition
995  temp1.reserve(2);
996  temp1.push_back(iii->GetGeometry()(1));
997  temp1.push_back(iii->GetGeometry()(2));
998 
999  Geometry< Node >::Pointer cond = Geometry< Node >::Pointer(new Geometry< Node >(temp1) );
1000  int id = (iii->Id()-1)*3;
1001  Condition::Pointer p_cond = rReferenceBoundaryCondition.Create(id, temp1, properties);
1002  ThisModelPart.Conditions().push_back(p_cond);
1003 
1004  }
1005 
1006  //********************************************************************
1007  //second face
1008  el_neighb = (ThisModelPart.Elements()).find( out2.neighborlist[base+1] );
1009  //if( el != ThisModelPart.Elements().end() )
1010  if( el_neighb == elements_end )
1011  {
1012  //if no neighnour is present => the face is free surface
1013  iii->GetGeometry()[2].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
1014  iii->GetGeometry()[0].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
1015 
1016  //Generate condition
1018  temp1.reserve(2);
1019  temp1.push_back(iii->GetGeometry()(2));
1020  temp1.push_back(iii->GetGeometry()(0));
1021 
1022  Geometry< Node >::Pointer cond = Geometry< Node >::Pointer(new Geometry< Node >(temp1) );
1023  int id = (iii->Id()-1)*3+1;
1024  Condition::Pointer p_cond = rReferenceBoundaryCondition.Create(id, temp1, properties);
1025  ThisModelPart.Conditions().push_back(p_cond);
1026 
1027 
1028  }
1029 
1030  //********************************************************************
1031  //third face
1032  el_neighb = (ThisModelPart.Elements()).find( out2.neighborlist[base+2] );
1033  if( el_neighb == elements_end )
1034  {
1035  //if no neighnour is present => the face is free surface
1036  iii->GetGeometry()[0].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
1037  iii->GetGeometry()[1].FastGetSolutionStepValue(IS_BOUNDARY) = 1;
1038 
1039 // Generate condition
1041  temp1.reserve(2);
1042  temp1.push_back(iii->GetGeometry()(0));
1043  temp1.push_back(iii->GetGeometry()(1));
1044 
1045  Geometry< Node >::Pointer cond = Geometry< Node >::Pointer(new Geometry< Node >(temp1) );
1046  int id = (iii->Id()-1)*3+2;
1047  Condition::Pointer p_cond = rReferenceBoundaryCondition.Create(id, temp1, properties);
1048  ThisModelPart.Conditions().push_back(p_cond);
1049 
1050  }
1051 
1052 
1053  }
1054  }
1055 
1056 
1057  //returns false if it should be removed
1058  bool AlphaShape(double alpha_param, Geometry<Node >& pgeom)
1059  //bool AlphaShape(double alpha_param, Triangle2D<Node >& pgeom)
1060  {
1061  KRATOS_TRY
1062 
1063 
1064  double x0 = pgeom[0].X();
1065  double x1 = pgeom[1].X();
1066  double x2 = pgeom[2].X();
1067 
1068  double y0 = pgeom[0].Y();
1069  double y1 = pgeom[1].Y();
1070  double y2 = pgeom[2].Y();
1071 
1072  mJ(0,0)=2.0*(x1-x0);
1073  mJ(0,1)=2.0*(y1-y0);
1074  mJ(1,0)=2.0*(x2-x0);
1075  mJ(1,1)=2.0*(y2-y0);
1076 
1077 
1078  double detJ = mJ(0,0)*mJ(1,1)-mJ(0,1)*mJ(1,0);
1079 
1080  mJinv(0,0) = mJ(1,1);
1081  mJinv(0,1) = -mJ(0,1);
1082  mJinv(1,0) = -mJ(1,0);
1083  mJinv(1,1) = mJ(0,0);
1084 
1085  bounded_matrix<double,2,2> check;
1086 
1087 //calculate average h
1088  double h;
1089  h = pgeom[0].FastGetSolutionStepValue(NODAL_H);
1090  h += pgeom[1].FastGetSolutionStepValue(NODAL_H);
1091  h += pgeom[2].FastGetSolutionStepValue(NODAL_H);
1092  h *= 0.333333333;
1093 
1094 
1095  if(detJ < 5e-3*h*h)
1096  {
1097  //std::cout << "detJ = " << detJ << std::endl;
1099  pgeom[0].GetSolutionStepValue(IS_BOUNDARY) = 1;
1100  pgeom[1].GetSolutionStepValue(IS_BOUNDARY) = 1;
1101  pgeom[2].GetSolutionStepValue(IS_BOUNDARY) = 1;
1102  return false;
1103  }
1104 
1105  else
1106  {
1107 
1108  double x0_2 = x0*x0 + y0*y0;
1109  double x1_2 = x1*x1 + y1*y1;
1110  double x2_2 = x2*x2 + y2*y2;
1111 
1112  //finalizing the calculation of the inverted matrix
1113  //std::cout<<"MATR INV"<<MatrixInverse(mJ)<<std::endl;
1114  mJinv /= detJ;
1115  //calculating the RHS
1116  mRhs[0] = (x1_2 - x0_2);
1117  mRhs[1] = (x2_2 - x0_2);
1118 
1119  //calculate position of the center
1120  noalias(mC) = prod(mJinv,mRhs);
1121 
1122  double radius = sqrt(pow(mC[0]-x0,2)+pow(mC[1]-y0,2));
1123 
1124 
1125  if (radius < h*alpha_param)
1126  {
1127  return true;
1128  }
1129  else
1130  {
1131  return false;
1132  }
1133  }
1134 
1135 
1136  KRATOS_CATCH("")
1137  }
1138  //AUXILLIARY FCTNS
1139  inline void CalculateCenterAndSearchRadius(const double x0, const double y0,
1140  const double x1, const double y1,
1141  const double x2, const double y2,
1142  double& xc, double& yc, double& R
1143  )
1144  {
1145  xc = 0.3333333333333333333*(x0+x1+x2);
1146  yc = 0.3333333333333333333*(y0+y1+y2);
1147 
1148  double R1 = (xc-x0)*(xc-x0) + (yc-y0)*(yc-y0);
1149  double R2 = (xc-x1)*(xc-x1) + (yc-y1)*(yc-y1);
1150  double R3 = (xc-x2)*(xc-x2) + (yc-y2)*(yc-y2);
1151 
1152  R = R1;
1153  if(R2 > R) R = R2;
1154  if(R3 > R) R = R3;
1155 
1156  R = sqrt(R);
1157  }
1158 
1159  inline double CalculateVol( const double x0, const double y0,
1160  const double x1, const double y1,
1161  const double x2, const double y2
1162  )
1163  {
1164  return 0.5*( (x1-x0)*(y2-y0)- (y1-y0)*(x2-x0) );
1165  }
1166 
1167  inline bool CalculatePosition( const double x0, const double y0,
1168  const double x1, const double y1,
1169  const double x2, const double y2,
1170  const double xc, const double yc,
1171  array_1d<double,3>& N
1172  )
1173  {
1174  double area = CalculateVol(x0,y0,x1,y1,x2,y2);
1175 
1176  if(area < 0.000000000000001)
1177  {
1178  KRATOS_THROW_ERROR(std::logic_error,"element with zero area found","");
1179  }
1180 
1181 
1182 
1183  N[0] = CalculateVol(x1,y1,x2,y2,xc,yc) / area;
1184  N[1] = CalculateVol(x2,y2,x0,y0,xc,yc) / area;
1185  N[2] = CalculateVol(x0,y0,x1,y1,xc,yc) / area;
1186 
1187  /* N[0] = CalculateVol(x0,y0,x1,y1,xc,yc) * inv_area;
1188  N[1] = CalculateVol(x1,y1,x2,y2,xc,yc) * inv_area;
1189  N[2] = CalculateVol(x2,y2,x0,y0,xc,yc) * inv_area;*/
1190  double tol = 1e-4;
1191  double upper_limit = 1.0+tol;
1192  double lower_limit = -tol;
1193 
1194  if(N[0] >= lower_limit && N[1] >= lower_limit && N[2] >= lower_limit && N[0] <= upper_limit && N[1] <= upper_limit && N[2] <= upper_limit) //if the xc yc is inside the triangle
1195  //if(N[0] >= 0.0 && N[1] >= 0.0 && N[2] >= 0.0 && N[0] <= 1.0 && N[1] <= 1.0 && N[2] <= 1.0) //if the xc yc is inside the triangle return true
1196  return true;
1197 
1198  return false;
1199  }
1200 
1201  void Interpolate( Triangle2D3<Node >& geom, const array_1d<double,3>& N,
1202  unsigned int step_data_size,
1203  Node::Pointer pnode)
1204  {
1205  unsigned int buffer_size = pnode->GetBufferSize();
1206  //KRATOS_WATCH("Buffer size")
1207  //KRATOS_WATCH(buffer_size)
1208 
1209  for(unsigned int step = 0; step<buffer_size; step++)
1210  {
1211 
1212  //getting the data of the solution step
1213  double* step_data = (pnode)->SolutionStepData().Data(step);
1214 
1215 
1216  double* node0_data = geom[0].SolutionStepData().Data(step);
1217  double* node1_data = geom[1].SolutionStepData().Data(step);
1218  double* node2_data = geom[2].SolutionStepData().Data(step);
1219 
1220  //copying this data in the position of the vector we are interested in
1221  for(unsigned int j= 0; j<step_data_size; j++)
1222  {
1223 
1224  step_data[j] = N[0]*node0_data[j] + N[1]*node1_data[j] + N[2]*node2_data[j];
1225 
1226 
1227  }
1228  }
1229  //20150916 ajarauta
1230  pnode->FastGetSolutionStepValue(IS_LAGRANGIAN_INLET) = 0.0;
1231  pnode->FastGetSolutionStepValue(TRIPLE_POINT) = 0.0;
1232  /*
1233  if (pnode->FastGetSolutionStepValue(IS_BOUNDARY) == 0.0)
1234  {
1235  pnode->FastGetSolutionStepValue(TRIPLE_POINT) = 0.0;
1236  pnode->FastGetSolutionStepValue(FORCE_X) = 0.0;
1237  pnode->FastGetSolutionStepValue(FORCE_Y) = 0.0;
1238  }
1239  */
1240 
1241  if (N[0]==0.0 && N[1]==0.0 && N[2]==0.0)
1242  KRATOS_THROW_ERROR(std::logic_error,"SOMETHING's wrong with the added nodes!!!!!! ERROR","");
1243 
1244  //if ( pnode->FastGetSolutionStepValue(BULK_MODULUS)==0.0)
1245  // KRATOS_ERROR(std::logic_error,"SOMETHING's wrong with the added nodes!!!!!! ERROR","");
1246 
1247  //now we assure that the flag variables are set coorect!! since we add nodes inside of the fluid volume only
1248  //we manually reset the IS_BOUNDARY, IS_FLUID, IS_STRUCTURE, IS_FREE_SURFACE values in a right way
1249  //not to have values, like 0.33 0.66 resulting if we would have been interpolating them in the same way
1250  //as the normal variables, like Velocity etc
1251 
1252 
1253  pnode->FastGetSolutionStepValue(IS_BOUNDARY)=0.0;
1254  pnode->FastGetSolutionStepValue(IS_STRUCTURE)=0.0;
1255  pnode->FastGetSolutionStepValue(IS_INTERFACE)=0.0;
1256  pnode->Set(TO_ERASE,false);
1257  pnode->FastGetSolutionStepValue(IS_FREE_SURFACE)=0.0;
1258  pnode->FastGetSolutionStepValue(IS_FLUID)=1.0;
1259  }
1260 
1261  void initialize_triangulateio( triangulateio& tr )
1262  {
1263  tr.pointlist = (REAL*) NULL;
1264  tr.pointattributelist = (REAL*) NULL;
1265  tr.pointmarkerlist = (int*) NULL;
1266  tr.numberofpoints = 0;
1267  tr.numberofpointattributes = 0;
1268  tr.trianglelist = (int*) NULL;
1269  tr.triangleattributelist = (REAL*) NULL;
1270  tr.trianglearealist = (REAL*) NULL;
1271  tr.neighborlist = (int*) NULL;
1272  tr.numberoftriangles = 0;
1273  tr.numberofcorners = 3;
1274  tr.numberoftriangleattributes = 0;
1275  tr.segmentlist = (int*) NULL;
1276  tr.segmentmarkerlist = (int*) NULL;
1277  tr.numberofsegments = 0;
1278  tr.holelist = (REAL*) NULL;
1279  tr.numberofholes = 0;
1280  tr.regionlist = (REAL*) NULL;
1281  tr.numberofregions = 0;
1282  tr.edgelist = (int*) NULL;
1283  tr.edgemarkerlist = (int*) NULL;
1284  tr.normlist = (REAL*) NULL;
1285  tr.numberofedges = 0;
1286  };
1287 
1288  void clean_triangulateio( triangulateio& tr )
1289  {
1290  if(tr.pointlist != NULL) free(tr.pointlist );
1291  if(tr.pointattributelist != NULL) free(tr.pointattributelist );
1292  if(tr.pointmarkerlist != NULL) free(tr.pointmarkerlist );
1293  if(tr.trianglelist != NULL) free(tr.trianglelist );
1294  if(tr.triangleattributelist != NULL) free(tr.triangleattributelist );
1295  if(tr.trianglearealist != NULL) free(tr.trianglearealist );
1296  if(tr.neighborlist != NULL) free(tr.neighborlist );
1297  if(tr.segmentlist != NULL) free(tr.segmentlist );
1298  if(tr.segmentmarkerlist != NULL) free(tr.segmentmarkerlist );
1299  if(tr.holelist != NULL) free(tr.holelist );
1300  if(tr.regionlist != NULL) free(tr.regionlist );
1301  if(tr.edgelist != NULL) free(tr.edgelist );
1302  if(tr.edgemarkerlist != NULL) free(tr.edgemarkerlist );
1303  if(tr.normlist != NULL) free(tr.normlist );
1304  };
1305 
1306  void InterpolateOnEdge( Geometry<Node >& geom, int point1, int point2, unsigned int step_data_size, Node::Pointer pnode)
1307  {
1308  unsigned int buffer_size = pnode->GetBufferSize();
1309  KRATOS_INFO("TriGenDropletModeler") << "buffer_size: " << buffer_size << std::endl;
1310 
1311  for(unsigned int step = 0; step<buffer_size; step++) {
1312  //getting the data of the solution step
1313  double* step_data = (pnode)->SolutionStepData().Data(step);
1314 
1315  if (point1>2 || point1<0 || point2>2 || point2<0 || (point1==point2)) {
1316  KRATOS_INFO("TriGenDropletModeler") << "point1: " << point1 << std::endl;
1317  KRATOS_INFO("TriGenDropletModeler") << "point2: " << point2 << std::endl;
1318  KRATOS_ERROR << "THE EDGE POINTS ARE INVALID " << std::endl;
1319  }
1320 
1321  double* node0_data = geom[point1].SolutionStepData().Data(step);
1322  double* node1_data = geom[point2].SolutionStepData().Data(step);
1323 
1324  //copying this data in the position of the vector we are interested in
1325  for(unsigned int j= 0; j<step_data_size; j++) {
1326  step_data[j] = 0.5*(node0_data[j] + node1_data[j]);
1327  }
1328  }
1329  //now we assure that the flag variables are set coorect!! since we add nodes inside of the fluid volume only
1330  //we manually reset the IS_BOUNDARY, IS_FLUID, IS_STRUCTURE, IS_FREE_SURFACE values in a right way
1331  //not to have values, like 0.33 0.66 resulting if we would have been interpolating them in the same way
1332  //as the normal variables, like Velocity etc
1333 
1334  //pnode->FastGetSolutionStepValue(IS_BOUNDARY)=1.0;
1335  //pnode->FastGetSolutionStepValue(FLAG_VARIABLE)=1.0;
1336 
1337  pnode->FastGetSolutionStepValue(IS_LAGRANGIAN_INLET)=0.0;
1338  pnode->FastGetSolutionStepValue(IS_BOUNDARY)=1.0;
1339  pnode->FastGetSolutionStepValue(IS_FLUID)=1.0;
1340  pnode->FastGetSolutionStepValue(TRIPLE_POINT)=0.0;
1341  pnode->FastGetSolutionStepValue(CONTACT_ANGLE)=0.0;
1342  //pnode->FastGetSolutionStepValue(SOLID_FRACTION_GRADIENT_X)=0.0;
1343 
1344  pnode->Set(TO_ERASE,false);
1345 
1346  if (pnode->FastGetSolutionStepValue(IS_INTERFACE)>0.9)
1347  pnode->FastGetSolutionStepValue(IS_INTERFACE)=1.0;
1348  else
1349  pnode->FastGetSolutionStepValue(IS_INTERFACE)=0.0;
1350  if (pnode->FastGetSolutionStepValue(IS_FREE_SURFACE)>0.9)
1351  pnode->FastGetSolutionStepValue(IS_FREE_SURFACE)=1.0;
1352  else
1353  pnode->FastGetSolutionStepValue(IS_FREE_SURFACE)=0.0;
1354  if (pnode->FastGetSolutionStepValue(FLAG_VARIABLE)>0.9)
1355  pnode->FastGetSolutionStepValue(FLAG_VARIABLE)=1.0;
1356  else
1357  pnode->FastGetSolutionStepValue(FLAG_VARIABLE)=0.0;
1358  if (pnode->FastGetSolutionStepValue(IS_STRUCTURE)>0.9)
1359  {
1360  pnode->FastGetSolutionStepValue(IS_STRUCTURE)=1.0;
1361  pnode->FastGetSolutionStepValue(IS_INTERFACE)=0.0;
1362  pnode->FastGetSolutionStepValue(IS_FREE_SURFACE)=0.0;
1363  }
1364  else
1365  pnode->FastGetSolutionStepValue(IS_STRUCTURE)=0.0;
1366 
1367  };
1368 
1369 
1373 
1374 
1378 
1379 
1383 
1384 
1388 
1391 
1392 
1394 
1395 }; // Class TriGenPFEMModeler
1396 
1398 
1401 
1402 
1406 
1407 
1409 inline std::istream& operator >> (std::istream& rIStream,
1410  TriGenPFEMModeler& rThis);
1411 
1413 inline std::istream& operator >> (std::istream& rIStream,
1414  TriGenDropletModeler& rThis);
1415 
1417 inline std::ostream& operator << (std::ostream& rOStream,
1418  const TriGenDropletModeler& rThis)
1419 {
1420  rThis.PrintInfo(rOStream);
1421  rOStream << std::endl;
1422  rThis.PrintData(rOStream);
1423 
1424  return rOStream;
1425 }
1427 
1428 
1429 } // namespace Kratos.
1430 
1431 #endif // KRATOS_TRIGEN_PFEM_MODELER_H_INCLUDED defined
PeriodicInterfaceProcess & operator=(const PeriodicInterfaceProcess &)=delete
Short class definition.
Definition: bucket.h:57
Base class for all Conditions.
Definition: condition.h:59
Geometry< NodeType >::PointsArrayType NodesArrayType
definition of nodes container type, redefined from GeometryType
Definition: condition.h:86
Dof represents a degree of freedom (DoF).
Definition: dof.h:86
Base class for all Elements.
Definition: element.h:60
virtual Pointer Create(IndexType NewId, NodesArrayType const &ThisNodes, PropertiesType::Pointer pProperties) const
It creates a new element pointer.
Definition: element.h:202
This process removes the entities from a model part with the flag TO_ERASE.
Definition: entity_erase_process.h:70
void Execute() override
Execute method is used to execute the Process algorithms.
Geometry base class.
Definition: geometry.h:71
This class is a wrapper for a pointer to a data that is located in a different rank.
Definition: global_pointer.h:44
Definition: amatrix_interface.h:497
Definition: amatrix_interface.h:530
PropertiesType::Pointer pGetProperties(IndexType PropertiesId)
Definition: mesh.h:394
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
NodeType::Pointer CreateNewNode(int Id, double x, double y, double z, VariablesList::Pointer pNewVariablesList, IndexType ThisIndex=0)
Definition: model_part.cpp:270
ConditionIterator ConditionsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1361
SizeType GetNodalSolutionStepDataSize()
Definition: model_part.h:571
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
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
ElementIterator ElementsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1179
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
MeshType & GetMesh(IndexType ThisIndex=0)
Definition: model_part.h:1791
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
ConditionIterator ConditionsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1371
This class defines the node.
Definition: node.h:65
std::vector< std::unique_ptr< Dof< double > >> DofsContainerType
The DoF container type definition.
Definition: node.h:92
double Y() const
Definition: point.h:187
double Z() const
Definition: point.h:193
double X() const
Definition: point.h:181
void reserve(size_type dim)
Definition: pointer_vector.h:319
static double ElapsedSeconds(const std::chrono::steady_clock::time_point StartTime)
This method returns the resulting time.
Definition: timer.h:179
A generic tree data structure for spatial partitioning.
Definition: tree.h:190
Short class definition.
Definition: trigen_droplet_refine.h:61
Node::Pointer PointPointerType
Definition: trigen_droplet_refine.h:69
Tree< KDTreePartition< BucketType > > KdtreeType
Definition: trigen_droplet_refine.h:75
Bucket< 3, PointType, PointVector, PointPointerType, PointIterator, DistanceIterator > BucketType
Definition: trigen_droplet_refine.h:74
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: trigen_droplet_refine.h:709
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: trigen_droplet_refine.h:706
Node PointType
Definition: trigen_droplet_refine.h:68
virtual std::string Info() const
Turn back information as a string.
Definition: trigen_droplet_refine.h:700
virtual ~TriGenDropletModeler()
Destructor.
Definition: trigen_droplet_refine.h:90
std::vector< double >::iterator DistanceIterator
Definition: trigen_droplet_refine.h:73
TriGenDropletModeler()
Default constructor.
Definition: trigen_droplet_refine.h:82
KRATOS_CLASS_POINTER_DEFINITION(TriGenDropletModeler)
Pointer definition of TriGenModeler.
std::vector< PointType::Pointer > PointVector
Definition: trigen_droplet_refine.h:70
void ReGenerateMeshDroplet(ModelPart &ThisModelPart, Element const &rReferenceElement, Condition const &rReferenceBoundaryCondition, EntitiesEraseProcess< Node > &node_erase, bool rem_nodes=true, bool add_nodes=true, double my_alpha=1.4, double h_factor=0.5)
Definition: trigen_droplet_refine.h:105
PointVector::iterator PointIterator
Definition: trigen_droplet_refine.h:71
std::vector< double > DistanceVector
Definition: trigen_droplet_refine.h:72
Short class definition.
Definition: trigen_pfem_refine.h:64
A three node 2D triangle geometry with linear shape functions.
Definition: triangle_2d_3.h:74
#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
#define REAL
Definition: delaunator_utilities.cpp:16
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_INFO(label)
Definition: logger.h:250
Kratos::ModelPart ModelPart
Definition: kratos_wrapper.h:31
z
Definition: GenerateWind.py:163
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
bool CalculatePosition(Geometry< Node > &geom, const double xc, const double yc, const double zc, array_1d< double, 3 > &N)
Definition: transfer_utility.h:343
double CalculateVol(const double x0, const double y0, const double x1, const double y1, const double x2, const double y2)
Definition: transfer_utility.h:424
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
std::vector< PointTypePointer > PointVector
Definition: internal_variables_interpolation_process.h:53
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
void triangulate(char *, struct triangulateio *, struct triangulateio *, struct triangulateio *)
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
PointVector::iterator PointIterator
Definition: internal_variables_interpolation_process.h:54
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
std::vector< double > DistanceVector
Definition: internal_variables_interpolation_process.h:55
int step
Definition: face_heat.py:88
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
res
Definition: generate_convection_diffusion_explicit_element.py:211
h
Definition: generate_droplet_dynamics.py:91
x2
Definition: generate_frictional_mortar_condition.py:122
x1
Definition: generate_frictional_mortar_condition.py:121
int tol
Definition: hinsberg_optimization.py:138
R
Definition: isotropic_damage_automatic_differentiation.py:172
float radius
Definition: mesh_to_mdpa_converter.py:18
def Interpolate(variable, entity, sf_values, historical_value)
Definition: point_output_process.py:231
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
el
Definition: read_stl.py:25
float temp
Definition: rotating_cone.py:85
float xc
Definition: rotating_cone.py:77
float yc
Definition: rotating_cone.py:78
int counter
Definition: script_THERMAL_CORRECT.py:218
int n_flag
check to ensure that no node has zero density or pressure
Definition: script_THERMAL_CORRECT.py:113
add_nodes
Definition: script.py:96
N
Definition: sensitivityMatrix.py:29
x
Definition: sensitivityMatrix.py:49
namespace
Definition: array_1d.h:793
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
float factor
for node in (self.combined_model_part).Nodes: pold = node.GetSolutionStepValue(PRESSURE,...
Definition: ulf_PGLASS.py:254