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.
remove_nodes_mesher_process.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosDelaunayMeshingApplication $
3 // Created by: $Author: JMCarbonell $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: April 2018 $
6 // Revision: $Revision: 0.0 $
7 //
8 //
9 
10 #if !defined(KRATOS_REMOVE_NODES_MESHER_PROCESS_H_INCLUDED )
11 #define KRATOS_REMOVE_NODES_MESHER_PROCESS_H_INCLUDED
12 
13 
14 // External includes
15 
16 // System includes
17 
18 // Project includes
21 
22 #include "includes/model_part.h"
26 
28 //Data: NORMAL, MASTER_NODES, NEIGHBOR_NODES, NEIGBOUR_ELEMENTS
29 //StepData: MEAN_ERROR, CONTACT_FORCE
30 //Flags: (checked) TO_ERASE, BOUNDARY, CONTACT, NEW_ENTITY, BLOCKED
31 // (set) TO_ERASE(conditions,nodes)(set), NEW_ENTITY(conditions,nodes)(set), BLOCKED(nodes)(set), INSIDE(nodes)(set)
32 // (modified)
33 // (reset)
34 //(set):=(set in this process)
35 
36 namespace Kratos
37 {
38 
41 
43 
62  : public MesherProcess
63 {
64  public:
67 
70 
74  typedef Bucket<3, Node, std::vector<Node::Pointer>, Node::Pointer, std::vector<Node::Pointer>::iterator, std::vector<double>::iterator > BucketType;
77 
84 
87  MesherUtilities::MeshingParameters& rRemeshingParameters,
88  int EchoLevel)
89  : mrModelPart(rModelPart),
90  mrRemesh(rRemeshingParameters)
91  {
93  }
94 
95 
98 
99 
103 
105  void operator()()
106  {
107  Execute();
108  }
109 
110 
114 
115 
117  void Execute() override
118  {
119  KRATOS_TRY
120 
121  if( mEchoLevel > 0 ){
122  std::cout<<" [ REMOVE CLOSE NODES: "<<std::endl;
123  //std::cout<<" Nodes before erasing : "<<mrModelPart.Nodes().size()<<std::endl;
124  }
125 
127  std::cout<<" ModelPart Supplied do not corresponds to the Meshing Domain: ("<<mrModelPart.Name()<<" != "<<mrRemesh.SubModelPartName<<")"<<std::endl;
128 
129 
130  mrRemesh.Refine->Info.BodyNodesRemoved.Initialize();
131  mrRemesh.Refine->Info.BoundaryNodesRemoved.Initialize();
132 
133  double RemovedConditions = mrModelPart.NumberOfConditions();
134  double NumberOfNodes = mrModelPart.NumberOfNodes();
135 
136  bool any_node_removed = false;
137  bool any_condition_removed = false;
138 
139  //set flags for the local process execution
140  mMesherUtilities.SetFlagsToNodes(mrModelPart,{RIGID,INLET},{BLOCKED});
141 
142  //if the remove_node switch is activated, we check if the nodes got too close
143  if (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES) || (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES)) )
144  {
145  bool any_node_removed_on_error = false;
147  if (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES_ON_ERROR) && mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES) )
148  {
149  any_node_removed_on_error = this->RemoveNodesOnError(mrModelPart, mrRemesh.Refine->Info.BodyNodesRemoved.on_error); //2D and 3D
150  }
152 
153  bool any_convex_condition_removed = false;
155  if (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES))
156  {
157  any_convex_condition_removed = this->RemoveNonConvexBoundary(mrModelPart); //2D only
158  }
160 
161 
162  bool any_node_removed_on_distance = false;
164  if (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES_ON_DISTANCE) || mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES_ON_DISTANCE))
165  {
166  any_node_removed_on_distance = this->RemoveNodesOnDistance(mrModelPart, mrRemesh.Refine->Info.BodyNodesRemoved.on_distance, mrRemesh.Refine->Info.BoundaryNodesRemoved.on_distance, any_condition_removed); //2D only (RebuildBoundary is only 2D)
167  }
168  // REMOVE ON DISTANCE
170 
171 
173  // REMOVE CONTACT NODES (and boundary near the contact)
174  if ( mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES_ON_DISTANCE) )
175  {
176  bool any_node_removed_on_contact = this->RemoveNodesOnContact( mrModelPart, mrRemesh.Refine->Info.BodyNodesRemoved.on_distance, mrRemesh.Refine->Info.BoundaryNodesRemoved.on_distance, any_condition_removed);
177  if ( any_node_removed_on_contact || any_node_removed_on_distance)
178  any_node_removed_on_distance = true;
179  }
181 
182  if(any_node_removed_on_error || any_node_removed_on_distance)
183  any_node_removed = true;
184 
185  std::cout << " any_node_removed " << any_node_removed << std::endl;
186  if(any_convex_condition_removed || any_condition_removed)
187  any_condition_removed = true;
188 
189 
190  if(any_node_removed || any_condition_removed){
191  std::cout<<" Removed Nodes: ( error "<<any_node_removed_on_error<<" distance "<<any_node_removed_on_distance<<" conv_cond "<<any_convex_condition_removed<<" cond "<< any_condition_removed<<")"<<std::endl;
193  }
194 
195  if(any_condition_removed){
196  //Clean Conditions
197  ModelPart::ConditionsContainerType PreservedConditions;
198 
199  //id = 0;
200  for(auto i_cond(mrModelPart.Conditions().begin()); i_cond != mrModelPart.Conditions().end(); ++i_cond)
201  {
202 
203  if(i_cond->IsNot(TO_ERASE)){
204  //id+=1;
205  PreservedConditions.push_back(*i_cond.base());
206  //PreservedConditions.back().SetId(id);
207  }
208  else{
209  std::cout<<" Condition RELEASED:"<<i_cond->Id()<<std::endl;
210  }
211  }
212 
213  mrModelPart.Conditions().swap(PreservedConditions);
214 
215  }
216 
217 
218  }
219 
220 
221  //check
222  for(auto& i_node : mrModelPart.Nodes())
223  {
224  if( i_node.Is(TO_ERASE) && i_node.Is(BLOCKED) )
225  std::cout<<" REMOVE NOT ALLOWED entity NODE : "<<i_node.Id()<<" "<<i_node.Coordinates()<<std::endl;
226  }
227 
228  //reset flags for the local process execution
229  mMesherUtilities.SetFlagsToNodes(mrModelPart,{BLOCKED},{BLOCKED.AsFalse()});
230 
231  // number of removed nodes:
232  mrRemesh.Info->RemovedNodes = NumberOfNodes - mrModelPart.NumberOfNodes();
233  RemovedConditions -= mrModelPart.NumberOfConditions();
234 
235  if( mEchoLevel > 0 ){
236  std::cout<<" [ CONDITIONS ( removed : "<<RemovedConditions<<" ) ]"<<std::endl;
237  std::cout<<" [ NODES ( removed : "<<mrRemesh.Info->RemovedNodes<<" ) ]"<<std::endl;
238 
239  if( this->mEchoLevel >=1 ){
240  mrRemesh.Refine->Info.BodyNodesRemoved.EchoStats();
241  mrRemesh.Refine->Info.BoundaryNodesRemoved.EchoStats();
242  }
243 
244  //std::cout<<" Nodes after erasing : "<<mrModelPart.Nodes().size()<<std::endl;
245  std::cout<<" REMOVE CLOSE NODES ]; "<<std::endl;
246  }
247 
248 
249  KRATOS_CATCH(" ")
250  }
251 
252 
256 
257 
261 
262 
266 
268  std::string Info() const override
269  {
270  return "RemoveNodesMesherProcess";
271  }
272 
274  void PrintInfo(std::ostream& rOStream) const override
275  {
276  rOStream << "RemoveNodesMesherProcess";
277  }
278 
280  void PrintData(std::ostream& rOStream) const override
281  {
282  }
283 
284 
288 
290 
291  protected:
292 
298 
300 
302 
304 
306 
313 
314 
315  //**************************************************************************
316  //**************************************************************************
317 
318  void CleanRemovedNodes(ModelPart& rModelPart)
319  {
320  KRATOS_TRY
321 
322  //MESH 0 total domain mesh
323  ModelPart::NodesContainerType temporal_nodes;
324  temporal_nodes.reserve(rModelPart.Nodes().size());
325 
326  temporal_nodes.swap(rModelPart.Nodes());
327 
328  for(auto i_node(temporal_nodes.begin()); i_node != temporal_nodes.end(); ++i_node)
329  {
330  if( i_node->IsNot(TO_ERASE) ){
331  rModelPart.Nodes().push_back(*i_node.base());
332  }
333  else{
334  if( i_node->Is(BOUNDARY) ) {
335  if( mEchoLevel > 0 )
336  std::cout<<" BOUNDARY NODE RELEASED "<<i_node->Id()<<std::endl;
337  std::cout << " Removing Boundary " << i_node->Id() << " :: " << i_node->X() << " , " << i_node->Y() << std::endl;
338  } else {
339  std::cout << " Removing NONboundary " << i_node->Id() << " :: " << i_node->X() << " , " << i_node->Y() << std::endl;
340  }
341  }
342  }
343 
344  rModelPart.Nodes().Sort();
345 
346 
347  KRATOS_CATCH( "" )
348  }
349 
350 
351  //**************************************************************************
352  //**************************************************************************
353 
354  virtual bool RemoveNodesOnDistance(ModelPart& rModelPart, unsigned int& inside_nodes_removed, unsigned int& boundary_nodes_removed, bool& any_condition_removed)
355  {
356  KRATOS_TRY
357 
358 
359  //***SIZES :::: parameters do define the tolerance in mesh size:
360  double size_for_distance_inside = 1.0 * mrRemesh.Refine->CriticalRadius; //compared with element radius
361  double size_for_distance_boundary = 1.5 * size_for_distance_inside; //compared with element radius
362 
363 
364  bool any_node_removed = false;
365 
366  //bucket size definition:
367  unsigned int bucket_size = 20;
368 
369  //create the list of the nodes to be check during the search
370  std::vector<Node::Pointer> list_of_nodes;
371  list_of_nodes.reserve(rModelPart.NumberOfNodes());
372  for(auto i_node(rModelPart.Nodes().begin()); i_node != rModelPart.Nodes().end(); ++i_node)
373  {
374  list_of_nodes.push_back(*i_node.base());
375  }
376 
377  KdtreeType nodes_tree(list_of_nodes.begin(),list_of_nodes.end(), bucket_size);
378 
380 
381  //all of the nodes in this list will be preserved
382  unsigned int num_neighbours = 100;
383 
384  std::vector<Node::Pointer> neighbours (num_neighbours);
385  std::vector<double> neighbour_distances(num_neighbours);
386 
387 
388  //radius means the distance, if the distance between two nodes is closer to radius -> mark for removing
389  double radius=0;
390  Node work_point(0,0.0,0.0,0.0);
391  unsigned int n_points_in_radius;
392 
393 
394  for(auto& i_node : rModelPart.Nodes())
395  {
396 
397  bool on_contact_tip = false;
398  bool contact_active = false;
399 
400  if( i_node.SolutionStepsDataHas(CONTACT_FORCE) ){
401  array_1d<double, 3 > & ContactForceNormal = i_node.FastGetSolutionStepValue(CONTACT_FORCE);
402  if(norm_2(ContactForceNormal)>0)
403  contact_active = true;
404  }
405 
406  if(contact_active || i_node.Is(CONTACT) )
407  on_contact_tip = true;
408 
409  if( i_node.IsNot(NEW_ENTITY) && i_node.IsNot(BLOCKED) && i_node.IsNot(TO_ERASE) )
410  {
411  radius = size_for_distance_inside;
412 
413  work_point[0]=i_node.X();
414  work_point[1]=i_node.Y();
415  work_point[2]=i_node.Z();
416 
417  n_points_in_radius = nodes_tree.SearchInRadius(work_point, radius, neighbours.begin(),neighbour_distances.begin(), num_neighbours);
418 
419  if (n_points_in_radius>1)
420  {
421  //std::cout<<" Points in Radius "<< n_points_in_radius<<" radius "<<radius<<std::endl;
422  if( i_node.IsNot(BOUNDARY) )
423  {
424  if( mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES_ON_DISTANCE) ){
425 
426  if( !this->CheckEngagedNode(i_node,neighbours,neighbour_distances,n_points_in_radius) ){ //we release the node if no other nodes neighbours are being erased
427  i_node.Set(TO_ERASE);
428  any_node_removed = true;
429  inside_nodes_removed++;
430  //distance_remove++;
431  //std::cout<<" Distance Criterion Node ["<<i_node.Id()<<"] TO_ERASE "<<std::endl;
432  }
433 
434  }
435 
436  }
437  else if ( (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES) && mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES_ON_DISTANCE)) ) //boundary nodes will be removed if they get REALLY close to another boundary node (0.2(=extra_factor) * h_factor)
438  {
439 
440  //std::cout<<" Remove close boundary nodes: Candidate ["<<i_node.Id()<<"]"<<std::endl;
441 
442  //here we loop over the neighbouring nodes and if there are nodes
443  //with BOUNDARY flag and closer than 0.2*nodal_h from our node, we remove the node we are considering
444  unsigned int k = 0;
445  unsigned int counter = 0;
446  for(std::vector<Node::Pointer>::iterator i_nnode=neighbours.begin(); i_nnode!=neighbours.begin() + n_points_in_radius ; ++i_nnode)
447  {
448  bool nn_on_contact_tip = false;
449  bool contact_active = false;
450 
451  if( (*i_nnode)->SolutionStepsDataHas(CONTACT_FORCE) ){
452  array_1d<double, 3 > & ContactForceNormal = (*i_nnode)->FastGetSolutionStepValue(CONTACT_FORCE);
453  if(norm_2(ContactForceNormal)>0)
454  contact_active = true;
455  }
456 
457  if(contact_active || (*i_nnode)->Is(CONTACT) )
458  nn_on_contact_tip = true;
459 
460  //std::cout<<" radius * extra_factor "<<(extra_factor*radius)<<" >? "<<neighbour_distances[k]<<std::endl;
461  if ( (*i_nnode)->Is(BOUNDARY) && !nn_on_contact_tip && neighbour_distances[k] < size_for_distance_boundary && neighbour_distances[k] > 0.0 )
462  {
463  //KRATOS_WATCH( neighbours_distances[k] )
464  if((*i_nnode)->IsNot(TO_ERASE)){
465  counter += 1;
466  }
467  }
468 
469 
470  k++;
471  }
472 
473  if(counter > 1 && !on_contact_tip ){ //Can be inserted in the boundary refine
474  i_node.Set(TO_ERASE);
475  //std::cout<<" Removed Boundary Node ["<<i_node.Id()<<"] on Distance "<<std::endl;
476  any_node_removed = true;
477  boundary_nodes_removed++;
478  //distance_remove ++;
479  }
480 
481  }
482 
483  //}
484 
485  }
486 
487  }
488  }
489 
490  //Build boundary after removing boundary nodes due distance criterion
491  if(boundary_nodes_removed){
492  any_condition_removed = RebuildBoundary(rModelPart);
493  }
494  //Build boundary after removing boundary nodes due distance criterion
495 
496 
497  return any_node_removed;
498 
499  KRATOS_CATCH(" ")
500 
501  }
502 
503  //**************************************************************************
504  //**************************************************************************
505 
506  virtual bool CheckEngagedNode(Node& rNode, std::vector<Node::Pointer>& rNeighbours, std::vector<double>& rNeighbourDistances, unsigned int& rn_points_in_radius)
507  {
508  KRATOS_TRY
509 
510  //look if we are already erasing any of the other nodes
511  bool engaged_node = false;
512 
513  //trying to remove the node in the shorter distance anyway
514  double min_distance = std::numeric_limits<double>::max();
515  unsigned int counter = 0;
516  unsigned int closest_node = 0;
517 
518  for(std::vector<double>::iterator nd=rNeighbourDistances.begin(); nd!=rNeighbourDistances.begin()+rn_points_in_radius; ++nd)
519  {
520  if( (*nd) < min_distance && (*nd) > 0.0 ){
521  min_distance = (*nd);
522  closest_node = counter;
523  }
524  //std::cout<<" Distances "<<counter<<" "<< (*nd) <<std::endl;
525  ++counter;
526  }
527 
528  if( rNeighbours[closest_node]->Is(TO_ERASE) && rNeighbours[closest_node]->IsNot(BOUNDARY) ){
529  engaged_node = true;
530  }
531  else{
532  counter = 0;
533  unsigned int erased_node = 0;
534  for(std::vector<Node::Pointer>::iterator i_nnode=rNeighbours.begin(); i_nnode!=rNeighbours.begin()+rn_points_in_radius; ++i_nnode)
535  {
536  if( (*i_nnode)->IsNot(BOUNDARY) && (*i_nnode)->Is(TO_ERASE) )
537  {
538  erased_node = counter;
539  engaged_node = true;
540  break;
541  }
542  ++counter;
543  }
544  if( engaged_node ){
545  // if the distance is 5 times smaller remove anyway
546  if( rNeighbourDistances[closest_node] * 5 < rNeighbourDistances[erased_node] ){
547  engaged_node = false;
548  //std::cout<<" Distance Criterion Node ["<<in->Id()<<"] TO_ERASE "<<closest_node<<" "<<erased_node<<std::endl;
549  }
550  }
551  }
552 
553  return engaged_node;
554 
555  KRATOS_CATCH(" ")
556  }
557 
558  //**************************************************************************
559  //**************************************************************************
560 
561  virtual bool RemoveNodesOnError(ModelPart& rModelPart, unsigned int& error_removed_nodes)
562  {
563  KRATOS_TRY
564 
565  //***SIZES :::: parameters do define the tolerance in mesh size:
566  double size_for_criterion_error = 2.0 * mrRemesh.Refine->CriticalRadius; //compared with mean node radius
567 
568  bool any_node_removed = false;
569 
570  MeshErrorCalculationUtilities MeshErrorDistribution;
571  MeshErrorDistribution.SetEchoLevel(mEchoLevel);
572 
573  std::vector<double> NodalError(rModelPart.NumberOfNodes()+1);
574 
575  unsigned int number_of_nodes = 0;
576 
578  number_of_nodes = mrRemesh.NodeMaxId+1;
579  else
580  number_of_nodes = MesherUtilities::GetMaxNodeId(rModelPart)+1;
581 
582  std::vector<int> nodes_ids(number_of_nodes);
583 
584 
585  MeshErrorDistribution.NodalErrorCalculation(rModelPart,NodalError,nodes_ids,mrRemesh.Refine->GetErrorVariable());
586 
587  for(auto& i_node : rModelPart.Nodes())
588  {
589 
590  NodeWeakPtrVectorType& nNodes = i_node.GetValue(NEIGHBOUR_NODES);
591  int erased_nodes =0;
592  for(auto& i_nnode : nNodes)
593  {
594  if(i_nnode.Is(TO_ERASE))
595  erased_nodes += 1;
596  }
597 
598 
599  if(i_node.IsNot(BOUNDARY) && erased_nodes < 1)
600  {
601  double& MeanError = i_node.FastGetSolutionStepValue(MEAN_ERROR);
602  MeanError = NodalError[nodes_ids[i_node.Id()]];
603 
604  ElementWeakPtrVectorType& nElements = i_node.GetValue(NEIGHBOUR_ELEMENTS);
605  double mean_node_radius = 0;
606  for(auto& i_nelem : nElements)
607  {
608  mean_node_radius+= mMesherUtilities.CalculateElementRadius(i_nelem.GetGeometry()); //Triangle 2D, Tetrahedron 3D
609  }
610 
611  mean_node_radius /= double(nElements.size());
612 
613  if(NodalError[nodes_ids[i_node.Id()]] < mrRemesh.Refine->ReferenceError && mean_node_radius < size_for_criterion_error)
614  {
615  //std::cout<<" Energy : node remove ["<<i_node.Id()<<"] : "<<NodalError[nodes_ids[i_node.Id()]]<<std::endl;
616  //std::cout<<" mean_node_radius "<<mean_node_radius<<" < "<<size_for_criterion_error<<" size_for_criterion_error"<<std::endl;
617  i_node.Set(TO_ERASE);
618  any_node_removed = true;
619  error_removed_nodes++;
620  }
621  }
622  }
623 
624  return any_node_removed;
625 
626  KRATOS_CATCH(" ")
627 
628  }
629 
630  //**************************************************************************
631  //**************************************************************************
632 
633  virtual bool RemoveNodesOnContact(ModelPart& rModelPart, unsigned int& inside_nodes_removed, unsigned int& boundary_nodes_removed, bool& any_condition_removed)
634  {
635  KRATOS_TRY
636 
637 
638  if( mEchoLevel > 0 ){
639  std::cout<<" [ REMOVE NODES ON CONTACT AND BEYOND : "<<std::endl;
640  std::cout<<" Starting Conditions : "<<rModelPart.Conditions().size()<<std::endl;
641  }
642 
643  // sizes
644  double size_for_distance_inside = 1.0 * mrRemesh.Refine->CriticalRadius;
645  double size_for_distance_boundary = 1.5 * size_for_distance_inside;
646 
647  double size_for_wall_tip_contact_side = (0.5 * mrRemesh.Refine->CriticalSide); // the distance to refine
648  size_for_wall_tip_contact_side *= 0.5; // half the distance
649  size_for_wall_tip_contact_side = size_for_wall_tip_contact_side * size_for_wall_tip_contact_side; // the return of search in radius is distance^2
650 
651  double SF = 0.80;
652  size_for_wall_tip_contact_side *= SF*SF;
653 
654 
655  bool any_node_removed = false;
656 
657  //bucket size definition:
658  unsigned int bucket_size = 20;
659 
660  //create the list of the nodes to be check during the search
661  std::vector<Node::Pointer> list_of_nodes;
662  list_of_nodes.reserve(mrModelPart.NumberOfNodes());
663  for(auto i_node(mrModelPart.Nodes().begin()); i_node != mrModelPart.Nodes().end(); ++i_node)
664  {
665  list_of_nodes.push_back(*i_node.base());
666  }
667 
668  KdtreeType nodes_tree(list_of_nodes.begin(),list_of_nodes.end(), bucket_size);
669 
671 
672  //all of the nodes in this list will be preserved
673  unsigned int num_neighbours = 100;
674 
675  std::vector<Node::Pointer> neighbours (num_neighbours);
676  std::vector<double> neighbour_distances(num_neighbours);
677 
678 
679  //radius means the distance, if the distance between two nodes is closer to radius -> mark for removing
680  double radius=0;
681  Node work_point(0,0.0,0.0,0.0);
682  unsigned int n_points_in_radius;
683 
684 
685  for(ModelPart::NodesContainerType::const_iterator in = mrModelPart.NodesBegin(); in != mrModelPart.NodesEnd(); ++in)
686  {
687  bool on_contact_tip = false;
688  array_1d<double, 3 > & ContactForceNormal = in->FastGetSolutionStepValue(CONTACT_FORCE);
689 
690  if(norm_2(ContactForceNormal)>0 || in->Is(CONTACT) )
691  on_contact_tip = true;
692 
693  bool on_contact_tip_strict = false;
694  if (norm_2(ContactForceNormal) > 0)
695  on_contact_tip_strict = true;
696 
697  if( in->IsNot(NEW_ENTITY) )
698  {
699  radius = size_for_distance_inside;
700 
701  work_point[0]=in->X();
702  work_point[1]=in->Y();
703  work_point[2]=in->Z();
704 
705  n_points_in_radius = nodes_tree.SearchInRadius(work_point, radius, neighbours.begin(),neighbour_distances.begin(), num_neighbours);
706 
707  if (n_points_in_radius>1)
708  {
709 
710  if ( in->IsNot(BOUNDARY) )
711  {
712 
713  if( mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_NODES_ON_DISTANCE) ){
714  //look if we are already erasing any of the other nodes
715  unsigned int contact_nodes = 0;
716  unsigned int erased_nodes = 0;
717  unsigned int near_to_contact_nodes = 0;
718  unsigned int kk = 0;
719  for(std::vector<Node::Pointer>::iterator nn=neighbours.begin(); nn!=neighbours.begin() + n_points_in_radius ; ++nn)
720  {
721  if( (*nn)->Is(BOUNDARY) && (*nn)->Is(CONTACT) )
722  contact_nodes += 1;
723 
724  if( (*nn)->Is(TO_ERASE) )
725  erased_nodes += 1;
726 
727  // to remove a node that is very close to a contact node (two times the safety factor)
728  if ( (*nn)->Is(BOUNDARY) && (*nn)->Is(CONTACT) && (neighbour_distances[kk] < SF*size_for_wall_tip_contact_side) )
729  near_to_contact_nodes += 1;
730 
731  kk++;
732 
733  } // end for neighbours
734 
735  if ( erased_nodes < 1 && contact_nodes < 2 && near_to_contact_nodes == 1) // we release node if it is very very near a contact
736  {
737  // to remove an interior node to is to close to a contacting node
738  in->Set(TO_ERASE);
739  any_node_removed = true;
740  inside_nodes_removed++;
741  std::cout <<" RemovingC0, an interior node very very near to a (possibly) contacting node " << in->Id() << std::endl;
742  std::cout <<" X: " << in->X() << " Y: " << in->Y() << std::endl;
743  } // end else if
744 
745  }
746 
747  }
748  else if ( (mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES) && mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES_ON_DISTANCE)) && (in)->IsNot(TO_ERASE))
749  //boundary nodes will be removed if they get REALLY close to another boundary node (0.2(=extra_factor) * h_factor)
750  {
751 
752  //std::cout<<" Remove close boundary nodes: Candidate ["<<in->Id()<<"]"<<std::endl;
753 
754  //here we loop over the neighbouring nodes and if there are nodes
755  //with BOUNDARY flag and closer than 0.2*nodal_h from our node, we remove the node we are considering
756  unsigned int k = 0;
757  unsigned int counterC2 = 0, counterC3 = 0;
758  for(std::vector<Node::Pointer>::iterator nn=neighbours.begin(); nn!=neighbours.begin() + n_points_in_radius ; ++nn)
759  {
760 
761 
762  bool nn_on_contact_tip = false;
763  array_1d<double, 3 > & ContactForceNormal = (*nn)->FastGetSolutionStepValue(CONTACT_FORCE);
764 
765  if(norm_2(ContactForceNormal)>0 || (*nn)->Is(CONTACT) )
766  nn_on_contact_tip = true;
767 
768  bool nn_on_contact_tip_strict = false;
769  if (norm_2(ContactForceNormal)>0)
770  nn_on_contact_tip_strict = true;
771 
772  if ( (*nn)->Is(BOUNDARY) && neighbour_distances[k] > 0.0 && (*nn)->IsNot(TO_ERASE) )
773  {
774  //KRATOS_WATCH( neighbours_distances[k] )
775  if ( neighbour_distances[k] < size_for_wall_tip_contact_side ) {
776  if ( nn_on_contact_tip_strict && (*nn)->IsNot(NEW_ENTITY) ) {
777  counterC2 += 1;
778  }
779  if ( nn_on_contact_tip && nn_on_contact_tip_strict && neighbour_distances[k] < SF*size_for_distance_boundary ) {
780  counterC3 += 1;
781  }
782  }
783  }
784 
785  k++;
786  } // end for each neighbour
787 
788  if ( counterC2 > 1 && in->IsNot(NEW_ENTITY) && on_contact_tip_strict) {
789  in->Set(TO_ERASE);
790  std::cout << " RemovingC2: three contacting nodes where close, removing the middle one [" << in->Id() << "]" << std::endl;
791  any_node_removed = true;
792  boundary_nodes_removed++;
793  std::cout << " X: " << in->X() << " Y: " << in->Y() << std::endl;
794  }
795  else if ( counterC3 > 0 && in->IsNot(NEW_ENTITY) && on_contact_tip && !on_contact_tip_strict ) {
796 
797  in->Set(TO_ERASE);
798  any_node_removed = true;
799  boundary_nodes_removed++;
800  std::cout << " RemovingC3: a non_contacting_node was to close to a contacting. removing the non_contacting " << in->Id() << std::endl;
801  std::cout << " X: " << in->X() << " Y: " << in->Y() << std::endl;
802 
803  }
804  }
805  }
806 
807  }
808  }
809 
810  // New loop to see if just two contacting nodes are very near. (it has to be done after the others to not to remove a pair)
811 
812  if ( mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES) && mrRemesh.Refine->RemovingOptions.Is(MesherUtilities::REMOVE_BOUNDARY_NODES_ON_DISTANCE) )
813  {
814  for (ModelPart::NodesContainerType::const_iterator in = mrModelPart.NodesBegin(); in != mrModelPart.NodesEnd(); ++in)
815  {
816 
817  bool on_contact_tip = false;
818  array_1d<double, 3 > & ContactForceNormal = in->FastGetSolutionStepValue(CONTACT_FORCE);
819 
820  if(norm_2(ContactForceNormal)>0 || in->Is(CONTACT) )
821  on_contact_tip = true;
822 
823  bool on_contact_tip_strict = false;
824  if (norm_2(ContactForceNormal) > 0)
825  on_contact_tip_strict = true;
826 
827  if ( in->IsNot(NEW_ENTITY) && in->IsNot(TO_ERASE) && in->Is(BOUNDARY) && on_contact_tip )
828  {
829  radius = size_for_distance_inside;
830 
831  work_point[0]=in->X();
832  work_point[1]=in->Y();
833  work_point[2]=in->Z();
834 
835  n_points_in_radius = nodes_tree.SearchInRadius(work_point, radius, neighbours.begin(),neighbour_distances.begin(), num_neighbours);
836 
837  if (n_points_in_radius>1)
838  {
839  unsigned int k = 0;
840  unsigned int counterC4 = 0;
841  for (std::vector<Node::Pointer>::iterator nn = neighbours.begin(); nn!=neighbours.begin() + n_points_in_radius; ++nn)
842  {
843  bool nn_on_contact_tip = false;
844  array_1d<double, 3 > & ContactForceNormal = (*nn)->FastGetSolutionStepValue(CONTACT_FORCE);
845 
846  // alternative definition
847  if(norm_2(ContactForceNormal)>0 || (*nn)->Is(CONTACT) )
848  nn_on_contact_tip = true;
849  bool nn_on_contact_tip_strict = false;
850  if (norm_2(ContactForceNormal) > 0)
851  nn_on_contact_tip_strict = true;
852 
853  if ( (*nn)->IsNot(NEW_ENTITY) && (*nn)->IsNot(TO_ERASE) && (*nn)->Is(BOUNDARY) && neighbour_distances[k] > 0.0)
854  {
855  if ( nn_on_contact_tip && nn_on_contact_tip_strict && neighbour_distances[k] < SF*SF*size_for_wall_tip_contact_side)
856  {
857  counterC4 += 1;
858  std::cout << " THIS IS THE CONTRARY NODE: " << (*nn)->X() << " " << (*nn)->Y() << std::endl;
859  std::cout << " THIS IS THE CONTRARY FORCE: " << ContactForceNormal << std::endl;
860  std::cout << " module " << norm_2(ContactForceNormal) << std::endl;
861  }
862  } // first if for C4 Condi
863  k++;
864  } // end for all Neighbours
865 
866  if (counterC4 > 0 && in->IsNot(NEW_ENTITY) && on_contact_tip && on_contact_tip_strict )
867  {
868  in->Set(TO_ERASE);
869  any_node_removed = true;
870  boundary_nodes_removed++;
871  std::cout << " RemovingC4: two contacting nodes are very very near, removing one " << in->Id() << std::endl;
872  std::cout << " X: " << in->X() << " Y: " << in->Y() << std::endl;
873  }
874  }
875  }
876 
877  }
878  }
879 
880  if ( mEchoLevel > 0) {
881  std::cout << " inside nodes removed " << inside_nodes_removed << std::endl;
882  std::cout << " boundary_nodes_removed " << boundary_nodes_removed << std::endl;
883  std::cout<<" REMOVE NODES ON CONTACT AND BEYOND ]; "<<std::endl;
884  }
885 
886  //Build boundary after removing boundary nodes due distance criterion
887  if(boundary_nodes_removed){
888  any_condition_removed = RebuildBoundary(rModelPart);
889  }
890  //Build boundary after removing boundary nodes due distance criterion
891 
892 
893  return any_node_removed;
894  KRATOS_CATCH("")
895  }
896 
897  //**************************************************************************
898  //**************************************************************************
899 
900  bool RebuildBoundary(ModelPart& rModelPart)
901  {
902  KRATOS_TRY
903 
904  bool any_condition_removed = false;
905 
906  unsigned int number_of_nodes = 0;
908  number_of_nodes = mrRemesh.NodeMaxId+1;
909  else
910  number_of_nodes = MesherUtilities::GetMaxNodeId(rModelPart)+1;
911 
912  std::vector<std::vector<Condition::Pointer> > node_shared_conditions(number_of_nodes); //all domain nodes
913 
914  for(auto i_cond(rModelPart.Conditions().begin()); i_cond != rModelPart.Conditions().end(); ++i_cond)
915  {
916  if(i_cond->IsNot(NEW_ENTITY) && i_cond->IsNot(TO_ERASE)){
917  Geometry< Node >& rConditionGeom = i_cond->GetGeometry();
918  for(unsigned int i=0; i<rConditionGeom.size(); ++i){
919  //std::cout<<"["<<i_cond->Id()<<"] i "<<i<<" condition "<<rConditionGeom[i].Id()<<std::endl;
920  if(rConditionGeom[i].Is(TO_ERASE)){
921  if( mEchoLevel > 0 )
922  std::cout<<" Released node condition ["<<rConditionGeom[i].Id()<<"]: WARNING "<<std::endl;
923  }
924 
925  node_shared_conditions[rConditionGeom[i].Id()].push_back(*i_cond.base());
926  }
927  }
928 
929  }
930 
931  //set flags for the local process execution
932  mMesherUtilities.SetFlagsToNodes(mrModelPart,{MODIFIED},{MODIFIED.AsFalse()});
933 
934  //nodes
935  int i=0,j=0;
936 
937  unsigned int initial_cond_size = 0;
938  if( !rModelPart.IsSubModelPart() )
939  initial_cond_size = rModelPart.NumberOfConditions()+1; //total model part conditions size
940  else
941  initial_cond_size = rModelPart.GetParentModelPart().NumberOfConditions()+1;
942 
943  unsigned int id = 1;
944  unsigned int new_id = 0;
945 
946  for(ModelPart::NodesContainerType::const_iterator in = rModelPart.NodesBegin(); in != rModelPart.NodesEnd(); ++in)
947  {
948 
949  if( in->Is(BOUNDARY) && in->IsNot(MODIFIED) && in->IsNot(NEW_ENTITY) && in->Is(TO_ERASE) ){
950 
951  unsigned int nodeId = in->Id();
952 
953  if(node_shared_conditions[nodeId].size()>=2){
954 
955  // std::cout<<" nodeId "<<nodeId<<std::endl;
956  if(node_shared_conditions[nodeId][0]->IsNot(TO_ERASE) && node_shared_conditions[nodeId][1]->IsNot(TO_ERASE)){
957 
958  if(node_shared_conditions[nodeId][0]->GetGeometry()[0].Id() == in->Id()){
959  i = 1;
960  j = 0;
961  }
962  else{
963  i = 0;
964  j = 1;
965  }
966 
967 
968  Geometry< Node >& rConditionGeom1 = node_shared_conditions[nodeId][i]->GetGeometry();
969  Geometry< Node >& rConditionGeom2 = node_shared_conditions[nodeId][j]->GetGeometry();
970 
971  //node in id Node1;
972 
973  Node::Pointer pNode0 = rConditionGeom1(0); // other node in condition [1]
974  Node::Pointer pNode2 = rConditionGeom2(1); // other node in condition [2]
975 
976  node_shared_conditions[nodeId][i]->Set(TO_ERASE); //release condition [1]
977  node_shared_conditions[nodeId][j]->Set(TO_ERASE); //release condition [2]
978 
979  //condition will be removed
980  any_condition_removed = true;
981 
982  Condition::Pointer NewCond = node_shared_conditions[nodeId][i];
983 
984  pNode0->Set(MODIFIED);
985  pNode2->Set(MODIFIED);
986 
987  //create new condition Node0-NodeB
989  face.reserve(2);
990 
991  face.push_back(rConditionGeom1(0));
992  face.push_back(rConditionGeom2(1));
993 
994  new_id = initial_cond_size + id;
995  //properties to be used in the generation
996  Condition::Pointer pcond = NewCond->Clone(new_id, face);
997  // std::cout<<" ID"<<id<<" 1s "<<pcond1->GetGeometry()[0].Id()<<" "<<pcond1->GetGeometry()[1].Id()<<std::endl;
998 
999  pcond->Set(NEW_ENTITY);
1000  if ( pcond->Is(TO_ERASE) ) {
1001  pcond->Reset(TO_ERASE); // due to the new cloning
1002  }
1003 
1004 
1005  //std::cout<<" Condition INSERTED (Id: "<<new_id<<") ["<<rConditionGeom1[0].Id()<<", "<<rConditionGeom2[1].Id()<<"] "<<std::endl;
1006 
1007  pcond->SetValue(NORMAL, NewCond->GetValue(NORMAL) );
1008  pcond->SetValue(MASTER_NODES, NewCond->GetValue(MASTER_NODES) );
1009 
1010  MeshDataTransferUtilities TransferUtilities;
1011  TransferUtilities.TransferBoundaryData(pcond, NewCond, *(mrRemesh.Transfer));
1012 
1013  (rModelPart.Conditions()).push_back(pcond);
1014 
1015  id +=1;
1016  }
1017 
1018  } else {
1019  in->Set(TO_ERASE, false);
1020  std::cout << "FINALLY NOT Removing " << in->Id() << std::endl;
1021  std::cout << " is boundary?? " << in->Is(BOUNDARY) << std::endl;
1022  std::cout << " is blocked?? " << in->IsNot(BLOCKED) << std::endl;
1023  std::cout << " is NEW_ENDITY " << in->IsNot(NEW_ENTITY) << std::endl;
1024  std::cout << " to erase " << in->Is(TO_ERASE) << std::endl;
1025  }
1026  }
1027 
1028  }
1029 
1030  //reset flags for the local process execution
1031  mMesherUtilities.SetFlagsToNodes(mrModelPart,{MODIFIED},{MODIFIED.AsFalse()});
1032 
1033  return any_condition_removed;
1034 
1035  KRATOS_CATCH(" ")
1036  }
1037 
1048 
1049  private:
1050 
1062 
1063 
1064 
1065  //**************************************************************************
1066  //**************************************************************************
1067 
1068  bool RemoveNonConvexBoundary(ModelPart& rModelPart)
1069  {
1070  KRATOS_TRY
1071 
1072  if( mEchoLevel > 0 ){
1073  std::cout<<" [ REMOVE NON CONVEX BOUNDARY : "<<std::endl;
1074  //std::cout<<" Starting Conditions : "<<rModelPart.Conditions().size()<<std::endl;
1075  }
1076 
1077  double RemovedConditions = rModelPart.NumberOfConditions();
1078 
1079  //***SIZES :::: parameters do define the tolerance in mesh size:
1080  double critical_angle = -120;
1081  double size_for_side_normal = mrRemesh.Refine->CriticalRadius;
1082 
1083 
1084  unsigned int number_of_nodes = 0;
1086  number_of_nodes = mrRemesh.NodeMaxId+1;
1087  else
1088  number_of_nodes = MesherUtilities::GetMaxNodeId(rModelPart)+1;
1089 
1090 
1091  std::vector<std::vector<Condition::Pointer> > node_shared_conditions(number_of_nodes); //all domain nodes
1092 
1093  //std::cout<<" Shared Conditions Size "<<node_shared_conditions.size()<<std::endl;
1094 
1095  for(ModelPart::ConditionsContainerType::iterator ic = rModelPart.ConditionsBegin(); ic!= rModelPart.ConditionsEnd(); ++ic)
1096  {
1097  if(ic->IsNot(NEW_ENTITY) && ic->IsNot(TO_ERASE)){
1098  Geometry< Node >& rConditionGeom = ic->GetGeometry();
1099  for(unsigned int i=0; i<rConditionGeom.size(); ++i){
1100  //std::cout<<"["<<ic->Id()<<"] i "<<i<<" condition "<<rConditionGeom[i].Id()<<std::endl;
1101  if(rConditionGeom[i].Is(TO_ERASE))
1102  std::cout<<" WARNING: Released node condition "<<std::endl;
1103 
1104  node_shared_conditions[rConditionGeom[i].Id()].push_back(*(ic.base()));
1105  }
1106  }
1107  else if ( ic->Is(TO_ERASE))
1108  {
1109  std::cout << " we are here with a condition to erase " << ic->Id() << std::endl;
1110  }
1111  }
1112 
1113  //std::cout<<" Node Shared Conditions (Pair of Condition Nodes) is now set "<<std::endl;
1114 
1115 
1116  //set flags for the local process execution
1117  mMesherUtilities.SetFlagsToNodes(mrModelPart,{MODIFIED},{MODIFIED.AsFalse()});
1118 
1119 
1120  //vector of the neighbour conditions
1121  array_1d<double,3> S1;
1122  array_1d<double,3> S2;
1123  S1.clear();
1124  S2.clear();
1125 
1126  //normals of the neighbour conditions
1127  array_1d<double,3> N1;
1128  array_1d<double,3> N2;
1129  N1.clear();
1130  N2.clear();
1131 
1132  //nodes
1133  int i=0,j=0;
1134 
1135  //condition id and size
1136 
1137  unsigned int initial_cond_size = 0;
1138  if( !rModelPart.IsSubModelPart() )
1139  initial_cond_size = rModelPart.NumberOfConditions()+1; //total model part conditions size
1140  else
1141  initial_cond_size = rModelPart.GetParentModelPart().NumberOfConditions()+1;
1142 
1143 
1144  unsigned int id = 1;
1145  unsigned int new_id = 0;
1146  int RemovedNodes =0;
1147 
1148  for(ModelPart::NodesContainerType::const_iterator in = rModelPart.NodesBegin(); in != rModelPart.NodesEnd(); ++in)
1149  {
1150 
1151  //angles
1152  double condition_angle = 0;
1153 
1154  if( in->Is(BOUNDARY) && in->IsNot(MODIFIED) && in->IsNot(NEW_ENTITY) )
1155  {
1156  unsigned int nodeId = in->Id();
1157 
1158  if(node_shared_conditions[nodeId].size()>=2){
1159 
1160  // std::cout<<" nodeId "<<nodeId<<std::endl;
1161  if(node_shared_conditions[nodeId][0]->IsNot(TO_ERASE) && node_shared_conditions[nodeId][1]->IsNot(TO_ERASE)){
1162 
1163  if(node_shared_conditions[nodeId][0]->GetGeometry()[0].Id() == in->Id()){
1164  i = 1;
1165  j = 0;
1166  }
1167  else{
1168  i = 0;
1169  j = 1;
1170  }
1171 
1172 
1173  //Node1* neighbour conditions in 2D: (Node0) ---[1]--- (Node1*)
1174 
1175  //normal condition [1]
1176  N1 = node_shared_conditions[nodeId][i]->GetValue(NORMAL);
1177  //normal condition [2]
1178  N2 = node_shared_conditions[nodeId][j]->GetValue(NORMAL);
1179 
1180  // std::cout<<" N1 "<<N1<<std::endl;
1181  // std::cout<<" N2 "<<N2<<std::endl;
1182 
1183 
1184  Geometry< Node >& rConditionGeom1 = node_shared_conditions[nodeId][i]->GetGeometry();
1185  Geometry< Node >& rConditionGeom2 = node_shared_conditions[nodeId][j]->GetGeometry();
1186 
1187  //node in id Node1;
1188 
1189  Node::Pointer pNode0 = rConditionGeom1(0); // other node in condition [1]
1190  Node::Pointer pNode2 = rConditionGeom2(1); // other node in condition [2]
1191 
1192 
1193  // std::cout<<" Node0: "<<rConditionGeom1[0].Id()<<" Node 1: "<<rConditionGeom1[1].Id()<<std::endl;
1194  // std::cout<<" Node1: "<<rConditionGeom2[0].Id()<<" Node 2: "<<rConditionGeom2[1].Id()<<std::endl;
1195 
1196  //segment condition [1]
1197  S1[0] = rConditionGeom1[1].X() - rConditionGeom1[0].X();
1198  S1[1] = rConditionGeom1[1].Y() - rConditionGeom1[0].Y();
1199 
1200 
1201  //segment condition [2]
1202  S2[0] = rConditionGeom2[1].X() - rConditionGeom2[0].X();
1203  S2[1] = rConditionGeom2[1].Y() - rConditionGeom2[0].Y();
1204 
1205 
1206  // std::cout<<" S1 "<<S1<<std::endl;
1207  // std::cout<<" S2 "<<S2<<std::endl;
1208 
1209 
1210  bool remove_S1 = false;
1211  if(norm_2(S1)<size_for_side_normal)
1212  remove_S1 = true;
1213 
1214  bool remove_S2 = false;
1215  if(norm_2(S2)<size_for_side_normal)
1216  remove_S2 = true;
1217 
1218  if(norm_2(S1)!=0)
1219  S1/=norm_2(S1);
1220 
1221 
1222  if(norm_2(S2)!=0)
1223  S2/=norm_2(S2);
1224 
1225  if(remove_S1 || remove_S2){
1226 
1227  node_shared_conditions[nodeId][i]->Set(TO_ERASE); //release condition [1]
1228  node_shared_conditions[nodeId][j]->Set(TO_ERASE); //release condition [2]
1229  in->Set(TO_ERASE); //release Node1*
1230 
1231  Condition::Pointer NewCond = node_shared_conditions[nodeId][i];
1232 
1233  pNode0->Set(MODIFIED);
1234  pNode2->Set(MODIFIED);
1235 
1236  //create new condition Node0-NodeB
1238  face.reserve(2);
1239 
1240  face.push_back(rConditionGeom1(0));
1241  face.push_back(rConditionGeom2(1));
1242 
1243  new_id = initial_cond_size + id;
1244  //properties to be used in the generation
1245  Condition::Pointer pcond = NewCond->Clone(new_id, face);
1246  // std::cout<<" ID"<<id<<" 1s "<<pcond1->GetGeometry()[0].Id()<<" "<<pcond1->GetGeometry()[1].Id()<<std::endl;
1247 
1248  pcond->Set(NEW_ENTITY);
1249  if ( pcond->Is(TO_ERASE) ) {
1250  std::cout << " was to erase? " << pcond->Is(TO_ERASE) << std::endl;
1251  pcond->Reset(TO_ERASE); // due to the new cloning
1252  std::cout << " but now is like " << pcond->Is(TO_ERASE) << std::endl;
1253  }
1254 
1255  //std::cout<<" Condition INSERTED (Id: "<<new_id<<") ["<<rConditionGeom1[0].Id()<<", "<<rConditionGeom2[1].Id()<<"] "<<std::endl;
1256 
1257  pcond->SetValue(NORMAL, NewCond->GetValue(NORMAL) );
1258  pcond->SetValue(MASTER_NODES, NewCond->GetValue(MASTER_NODES) );
1259 
1260  MeshDataTransferUtilities TransferUtilities;
1261  TransferUtilities.TransferBoundaryData(pcond, NewCond,*(mrRemesh.Transfer));
1262 
1263  (rModelPart.Conditions()).push_back(pcond);
1264 
1265  RemovedNodes += 1;
1266  id +=1;
1267 
1268 
1269  }
1270  else{
1271 
1272  double projection_sides = inner_prod(S1,S2);
1273  double projection_normals = inner_prod(N1,N2);
1274  double relative_angle = 0;
1275 
1276  if(projection_normals!=0)
1277  relative_angle = projection_sides/projection_normals;
1278 
1279  if(relative_angle<=1 && relative_angle>=-1 )
1280  condition_angle = (180.0/3.14159) * std::acos(relative_angle);
1281 
1282  if(inner_prod(S1,N2)<0)
1283  condition_angle *=(-1);
1284 
1285  // std::cout<<" projection_sides "<<projection_sides<<std::endl;
1286  // std::cout<<" projection_normals "<<projection_normals<<std::endl;
1287  // std::cout<<" relative_angle "<<relative_angle<<std::endl;
1288  // std::cout<<" condition_angle "<<condition_angle<<" critical_angle "<<critical_angle<<std::endl;
1289 
1290 
1291  if( condition_angle < -40 ){
1292  // std::cout<<" B NODE "<<in->Id()<<std::endl;
1293  // std::cout<<" projection_sides "<<projection_sides<<std::endl;
1294  // std::cout<<" projection_normals "<<projection_normals<<std::endl;
1295  // std::cout<<" relative_angle "<<relative_angle<<std::endl;
1296  // std::cout<<" condition_angle "<<condition_angle<<" critical_angle "<<critical_angle<<std::endl;
1297 
1298  //review this flag it is reused in laplacian smoothing....
1299  in->Set(INSIDE);
1300 
1301  pNode0->Set(INSIDE);
1302  pNode2->Set(INSIDE);
1303 
1304  }
1305 
1306  if(condition_angle<critical_angle){
1307 
1308 
1309  //Path of neighbour conditions in 2D: (NodeA) ---[0]--- (Node0) ---[1]--- (Node1*) ---[2]--- (Node2) --- [3]--- (NodeB)
1310 
1311  //realease positions:
1312  node_shared_conditions[nodeId][i]->Set(TO_ERASE); //release condition [1]
1313  node_shared_conditions[nodeId][j]->Set(TO_ERASE); //release condition [2]
1314 
1315  in->Set(TO_ERASE); //release Node1*
1316  pNode2->Set(TO_ERASE); //release Node2
1317 
1318  if( mEchoLevel > 0 ){
1319  std::cout<<" Node Release/Modify i "<<in->Id()<<std::endl;
1320  std::cout<<" Node Release/Modify j "<<pNode2->Id()<<std::endl;
1321  }
1322 
1323  //set Node0 to a new position (between 0 and 2)
1324  pNode0->Coordinates() = 0.5 * (pNode0->Coordinates() + pNode2->Coordinates());
1325 
1326  //assign data to dofs
1327  VariablesList& variables_list = rModelPart.GetNodalSolutionStepVariablesList();
1328 
1329  PointsArrayType PointsArray;
1330  PointsArray.push_back( *(in.base()) );
1331  //PointsArray.push_back( pNode2 );
1332  PointsArray.push_back( rConditionGeom2(1) );
1333 
1334  Geometry<Node > geom( PointsArray );
1335 
1336  std::vector<double> ShapeFunctionsN(2);
1337  std::fill( ShapeFunctionsN.begin(), ShapeFunctionsN.end(), 0.0 );
1338  ShapeFunctionsN[0] = 0.5;
1339  ShapeFunctionsN[1] = 0.5;
1340 
1341  MeshDataTransferUtilities DataTransferUtilities;
1342  DataTransferUtilities.Interpolate( geom, ShapeFunctionsN, variables_list, pNode0);
1343 
1344 
1345  //recover the original position of the node
1346  pNode0->GetInitialPosition() = Point{pNode0->Coordinates() - pNode0->FastGetSolutionStepValue(DISPLACEMENT)};
1347 
1348  //search shared condition of Node0 and Node A
1349  if(node_shared_conditions[pNode0->Id()][0]->Id() == pNode0->Id()){
1350  i = 1;
1351  }
1352  else{
1353  i = 0;
1354  }
1355 
1356  Geometry<Node >& rConditionGeom0 = node_shared_conditions[pNode0->Id()][i]->GetGeometry();
1357  Node::Pointer pNodeA = rConditionGeom0(0);
1358 
1359  //search shared condition of Node2 and Node B
1360  if(node_shared_conditions[pNode2->Id()][0]->Id() == pNode2->Id()){
1361  i = 0;
1362  }
1363  else{
1364  i = 1;
1365  }
1366 
1367  //New conditions profile in 2D: (NodeA) ---[0]--- (Node0**) ---[3]--- (NodeB) where (Node0**) is (Node0) in another position
1368 
1369  Condition::Pointer NewCond = node_shared_conditions[pNode2->Id()][i];
1370  NewCond->Set(TO_ERASE);
1371  Geometry<Node >& rConditionGeom3 = NewCond->GetGeometry();
1372  Node::Pointer pNodeB = rConditionGeom3(1);
1373 
1374  pNodeA->Set(MODIFIED);
1375  pNodeB->Set(MODIFIED);
1376  pNode0->Set(MODIFIED);
1377 
1378  //create new condition Node0-NodeB
1380  face.reserve(2);
1381 
1382  face.push_back(rConditionGeom1(0));
1383  face.push_back(rConditionGeom3(1));
1384 
1385  new_id = initial_cond_size + id;
1386  //properties to be used in the generation
1387  Condition::Pointer pcond = NewCond->Clone(new_id, face);
1388  // std::cout<<" ID"<<id<<" 1s "<<pcond1->GetGeometry()[0].Id()<<" "<<pcond1->GetGeometry()[1].Id()<<std::endl;
1389 
1390  pcond->Set(NEW_ENTITY);
1391 
1392  if( mEchoLevel > 0 ){
1393  std::cout<<" Condition INSERTED (Id: "<<new_id<<") ["<<rConditionGeom1[0].Id()<<", "<<rConditionGeom3[1].Id()<<"] "<<std::endl;
1394  }
1395 
1396  rConditionGeom1[0].Set(TO_ERASE,false); // do not release Node1
1397  rConditionGeom3[1].Set(TO_ERASE,false); // do not release Node2
1398 
1399 
1400  pcond->SetValue(NORMAL, NewCond->GetValue(NORMAL) );
1401  pcond->SetValue(MASTER_NODES, NewCond->GetValue(MASTER_NODES) );
1402 
1403  MeshDataTransferUtilities TransferUtilities;
1404  TransferUtilities.TransferBoundaryData(pcond, NewCond, *(mrRemesh.Transfer) );
1405 
1406  (rModelPart.Conditions()).push_back(pcond);
1407 
1408  RemovedNodes += 1;
1409  id +=1;
1410 
1411  }
1412  }
1413  }
1414  }
1415  }
1416  }
1417 
1418  //reset flags for the local process execution
1419  mMesherUtilities.SetFlagsToNodes(mrModelPart,{MODIFIED},{MODIFIED.AsFalse()});
1420 
1421 
1422  RemovedConditions = rModelPart.Conditions().size() - RemovedConditions;
1423 
1424  if( mEchoLevel > 0 ){
1425  std::cout<<" [ CONDITIONS ( removed : "<<RemovedConditions<<" ) ]"<<std::endl;
1426  std::cout<<" [ NODES ( removed : "<<RemovedNodes<<" ) ]"<<std::endl;
1427 
1428  std::cout<<" Ending Conditions : "<<rModelPart.Conditions().size()<<" (Removed nodes: "<< RemovedNodes<<" ) "<<std::endl;
1429  std::cout<<" REMOVE NON CONVEX BOUNDARY ]; "<<std::endl;
1430  }
1431 
1432  if(RemovedNodes)
1433  return true;
1434  else
1435  return false;
1436 
1437  KRATOS_CATCH(" ")
1438 
1439  }
1440 
1450 
1452  RemoveNodesMesherProcess& operator=(RemoveNodesMesherProcess const& rOther);
1453 
1455 
1457  //Process(Process const& rOther);
1458 
1459 
1461 
1462 }; // Class Process
1463 
1465 
1468 
1469 
1473 
1474 
1476 inline std::istream& operator >> (std::istream& rIStream,
1477  RemoveNodesMesherProcess& rThis);
1478 
1480 inline std::ostream& operator << (std::ostream& rOStream,
1481  const RemoveNodesMesherProcess& rThis)
1482 {
1483  rThis.PrintInfo(rOStream);
1484  rOStream << std::endl;
1485  rThis.PrintData(rOStream);
1486 
1487  return rOStream;
1488 }
1490 
1491 
1492 } // namespace Kratos.
1493 
1494 #endif // KRATOS_REMOVE_NODES_MESHER_PROCESS_H_INCLUDED defined
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
Flags AsFalse() const
Definition: flags.h:241
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
SizeType size() const
Definition: geometry.h:518
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
PointerVector< TPointType > PointsArrayType
Definition: geometry.h:118
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
Short class definition.
Definition: mesh_data_transfer_utilities.hpp:46
void TransferBoundaryData(Condition::Pointer rCurrentCondition, Condition::Pointer rReferenceCondition, const TransferParameters &rTransferVariables)
Definition: mesh_data_transfer_utilities.cpp:194
Short class definition.
Definition: mesh_error_calculation_utilities.hpp:50
void NodalErrorCalculation(ModelPart &rModelPart, std::vector< double > &rNodalError, std::vector< int > &rIds, const Variable< double > &rVariable)
Definition: mesh_error_calculation_utilities.hpp:82
virtual void SetEchoLevel(int Level)
Definition: mesh_error_calculation_utilities.hpp:284
The base class for processes passed to the solution scheme.
Definition: mesher_process.hpp:37
Short class definition.
Definition: mesher_utilities.hpp:49
void SetFlagsToNodes(ModelPart &rModelPart, const std::vector< Flags > rControlFlags, const std::vector< Flags > rAssignFlags)
Definition: mesher_utilities.cpp:174
static unsigned int GetMaxNodeId(ModelPart &rModelPart)
Definition: mesher_utilities.hpp:1408
static double CalculateElementRadius(Geometry< Node > &rGeometry)
Definition: mesher_utilities.hpp:1142
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
MeshType::ConditionsContainerType ConditionsContainerType
Condintions container. A vector set of Conditions with their Id's as key.
Definition: model_part.h:183
ConditionIterator ConditionsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1361
bool IsSubModelPart() const
Definition: model_part.h:1893
std::string & Name()
Definition: model_part.h:1811
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
SizeType NumberOfConditions(IndexType ThisIndex=0) const
Definition: model_part.h:1218
SizeType NumberOfNodes(IndexType ThisIndex=0) const
Definition: model_part.h:341
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
ModelPart & GetParentModelPart()
Definition: model_part.cpp:2124
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
VariablesList & GetNodalSolutionStepVariablesList()
Definition: model_part.h:549
ConditionIterator ConditionsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1371
This class defines the node.
Definition: node.h:65
double Y() const
Definition: point.h:187
double Z() const
Definition: point.h:193
double X() const
Definition: point.h:181
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
void reserve(size_type dim)
Definition: pointer_vector.h:319
void push_back(const TPointerType &x)
Definition: pointer_vector.h:270
Properties encapsulates data shared by different Elements or Conditions. It can store any type of dat...
Definition: properties.h:69
Remove Mesh Nodes Process for 2D and 3D cases.
Definition: remove_nodes_mesher_process.hpp:63
MesherUtilities mMesherUtilities
Definition: remove_nodes_mesher_process.hpp:303
GlobalPointersVector< Element > ElementWeakPtrVectorType
Definition: remove_nodes_mesher_process.hpp:79
MesherUtilities::MeshingParameters & mrRemesh
Definition: remove_nodes_mesher_process.hpp:301
GlobalPointersVector< Node > NodeWeakPtrVectorType
Definition: remove_nodes_mesher_process.hpp:78
virtual bool RemoveNodesOnDistance(ModelPart &rModelPart, unsigned int &inside_nodes_removed, unsigned int &boundary_nodes_removed, bool &any_condition_removed)
Definition: remove_nodes_mesher_process.hpp:354
KRATOS_CLASS_POINTER_DEFINITION(RemoveNodesMesherProcess)
Pointer definition of Process.
GlobalPointersVector< Condition > ConditionWeakPtrVectorType
Definition: remove_nodes_mesher_process.hpp:80
ModelPart & mrModelPart
Definition: remove_nodes_mesher_process.hpp:299
void operator()()
This operator is provided to call the process as a function and simply calls the Execute method.
Definition: remove_nodes_mesher_process.hpp:105
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: remove_nodes_mesher_process.hpp:280
virtual bool RemoveNodesOnError(ModelPart &rModelPart, unsigned int &error_removed_nodes)
Definition: remove_nodes_mesher_process.hpp:561
bool RebuildBoundary(ModelPart &rModelPart)
Definition: remove_nodes_mesher_process.hpp:900
ModelPart::MeshType::GeometryType::PointsArrayType PointsArrayType
Definition: remove_nodes_mesher_process.hpp:76
virtual ~RemoveNodesMesherProcess()
Destructor.
Definition: remove_nodes_mesher_process.hpp:97
RemoveNodesMesherProcess(ModelPart &rModelPart, MesherUtilities::MeshingParameters &rRemeshingParameters, int EchoLevel)
Default constructor.
Definition: remove_nodes_mesher_process.hpp:86
Tree< KDTreePartition< BucketType > > KdtreeType
Definition: remove_nodes_mesher_process.hpp:75
ConditionType::GeometryType GeometryType
Definition: remove_nodes_mesher_process.hpp:73
std::string Info() const override
Turn back information as a string.
Definition: remove_nodes_mesher_process.hpp:268
void CleanRemovedNodes(ModelPart &rModelPart)
Definition: remove_nodes_mesher_process.hpp:318
int mEchoLevel
Definition: remove_nodes_mesher_process.hpp:305
Bucket< 3, Node, std::vector< Node::Pointer >, Node::Pointer, std::vector< Node::Pointer >::iterator, std::vector< double >::iterator > BucketType
Definition: remove_nodes_mesher_process.hpp:74
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: remove_nodes_mesher_process.hpp:274
virtual bool CheckEngagedNode(Node &rNode, std::vector< Node::Pointer > &rNeighbours, std::vector< double > &rNeighbourDistances, unsigned int &rn_points_in_radius)
Definition: remove_nodes_mesher_process.hpp:506
ModelPart::PropertiesType PropertiesType
Definition: remove_nodes_mesher_process.hpp:72
ModelPart::ConditionType ConditionType
Definition: remove_nodes_mesher_process.hpp:71
virtual bool RemoveNodesOnContact(ModelPart &rModelPart, unsigned int &inside_nodes_removed, unsigned int &boundary_nodes_removed, bool &any_condition_removed)
Definition: remove_nodes_mesher_process.hpp:633
void Execute() override
Execute method is used to execute the Process algorithms.
Definition: remove_nodes_mesher_process.hpp:117
A generic tree data structure for spatial partitioning.
Definition: tree.h:190
SizeType SearchInRadius(PointType const &ThisPoint, CoordinateType Radius, IteratorType Results, DistanceIteratorType ResultsDistances, SizeType MaxNumberOfResults)
Search for points within a given radius of a point.
Definition: tree.h:434
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
static int EchoLevel
Definition: co_sim_EMPIRE_API.h:42
static double max(double a, double b)
Definition: GeometryFunctions.h:79
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
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
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
float radius
Definition: mesh_to_mdpa_converter.py:18
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int counter
Definition: script_THERMAL_CORRECT.py:218
integer i
Definition: TensorModule.f:17
Definition: mesher_utilities.hpp:631
MeshingInfoParameters::Pointer Info
Definition: mesher_utilities.hpp:681
RefiningParameters::Pointer Refine
Definition: mesher_utilities.hpp:684
TransferParametersType::Pointer Transfer
Definition: mesher_utilities.hpp:690
bool InputInitializedFlag
Definition: mesher_utilities.hpp:661
std::string SubModelPartName
Definition: mesher_utilities.hpp:642
unsigned int NodeMaxId
Definition: mesher_utilities.hpp:666