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.
edge_swapping_2d_modeler.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Pooyan Dadvand
11 //
12 //
13 
14 #if !defined(KRATOS_EDGE_SWAPPING_2D_MODELER_H_INCLUDED )
15 #define KRATOS_EDGE_SWAPPING_2D_MODELER_H_INCLUDED
16 
17 // System includes
18 #include <string>
19 #include <iostream>
20 
21 // External includes
22 
23 // Project includes
24 #include "includes/define.h"
25 #include "modeler/modeler.h"
27 #include "utilities/geometry_utilities.h"
28 #include "utilities/math_utils.h"
29 #include "utilities/timer.h"
31 
32 namespace Kratos
33 {
34 
37 
39 
50 {
51 
52 
53  struct SwappingData
54  {
55  public:
56  SwappingData()
57  {
58  Reset();
59  }
60  void Reset()
61  {
62  for(int i = 0 ; i < 3 ; i++)
63  {
64  NeighbourElements[i] = -1;
65  OppositeNodes[i] = -1;
66  OppositeEdge[i] = -1;
67  IsInside[i] = false;
68  }
69  IsSwapCandidate = false;
70  IsElementErased = false;
71  SwapWith = -1;
72  }
73  array_1d<int, 3> NeighbourElements;
74  array_1d<int, 3> OppositeNodes;
75  array_1d<int, 3> OppositeEdge;
76  array_1d<bool, 3> IsInside;
77  bool IsSwapCandidate;
78  bool IsElementErased;
79  int SwapWith;
80  int SwapEdge;
81  };
82 
83  struct CollapsingData
84  {
85  public:
86  CollapsingData()
87  {
88  Reset();
89  }
90  void Reset()
91  {
92  for(int i = 0 ; i < 2 ; i++)
93  {
94  CollapseElements[i] = -1;
95  }
96  MinimumDistance = -1;
97  NearestNodeId = -1;
98  }
99  double MinimumDistance;
100  int NearestNodeId;
101  array_1d<int, 2> CollapseElements;
102  };
103 
104 
105 
106 public:
109 
112 
115  typedef Modeler BaseType;
116 
117  typedef Point PointType;
118 
121  typedef Node NodeType;
122 
126 
127 
131 
132  typedef std::size_t SizeType;
133 
137 
140  {
141  }
142 
145 
146 
147 
151 
152 
153 
162  void Remesh(ModelPart& rThisModelPart)
163  {
164  Timer::Start("Edge Swapping");
165  const int maximum_repeat_number = 10;
166 
167  unsigned int number_of_bad_quality_elements = 1 ;//MarkBadQualityElements(rThisModelPart);
168  //unsigned int number_of_bad_quality_elements_old = number_of_bad_quality_elements;
169 
170 
171  // FindElementalNeighboursProcess find_element_neighbours_process(rThisModelPart, 2);
172 
173 
174  // find_element_neighbours_process.Execute();
175 
176 
177  // WriteMesh(rThisModelPart, "/home/pooyan/kratos/tests/before_remesh.post.msh");
178  for(int repeat = 0 ; (repeat < maximum_repeat_number) & (number_of_bad_quality_elements != 0) ; repeat++)
179  {
180  ModelPart::NodesContainerType::ContainerType& nodes_array = rThisModelPart.NodesArray();
181  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
182 
183  const int number_of_nodes = rThisModelPart.NumberOfNodes();
184  const int number_of_elements = rThisModelPart.NumberOfElements();
185 
186  IndexPartition<std::size_t>(number_of_nodes).for_each([&nodes_array](std::size_t Index){
187  nodes_array[Index]->SetId(Index+1);
188  });
189 
190  IndexPartition<std::size_t>(number_of_elements).for_each([&elements_array](std::size_t Index){
191  elements_array[Index]->SetId(Index+1);
192  });
193 
194  std::cout << "Edge swapping iteration #" << repeat; // << " : No. of bad quality elements = " << number_of_bad_quality_elements;
195  SetSwappingData(rThisModelPart);
196 
197 
198  unsigned int swap_counter = 0;
199  for(int i = 0 ; i < number_of_elements ; i++)
200  {
201  if(mSwappingData[i].IsSwapCandidate == false)
202  //if(mBadQuality[i])
203  {
204  for(int j = 0 ; j < 3 ; j++)
205  {
206  const int neighbour_index = mSwappingData[i].NeighbourElements[j] - 1;
207  if(neighbour_index >= 0)
208  {
209  if(mSwappingData[neighbour_index].IsSwapCandidate == false)
210  {
211  // std::cout << "check element #" << elements_array[i]->Id() << " with nodes: " << (*(elements_array[i])).GetGeometry()[0].Id() << "," << (*(elements_array[i])).GetGeometry()[1].Id() << "," << (*(elements_array[i])).GetGeometry()[2].Id() << std::endl;
212  if(mSwappingData[i].IsInside[j])
213  // if(IsInElementSphere(*(elements_array[i]), *(nodes_array[mSwappingData[i].OppositeNodes[j]-1])))
214  {
215  swap_counter++;
216  mSwappingData[neighbour_index].IsSwapCandidate = true;
217  mSwappingData[neighbour_index].SwapEdge = mSwappingData[i].OppositeEdge[j];
218  mSwappingData[i].IsSwapCandidate = true;
219  mSwappingData[i].SwapWith = neighbour_index;
220  mSwappingData[i].SwapEdge = j;
221  break;
222  }
223  }
224  }
225  }
226  }
227  }
228  std::cout << " number of swaps = " << swap_counter << std::endl;
229  if(swap_counter == 0)
230  break;
231 
232  // for(int i = 0 ; i < number_of_elements ; i++)
233  // {
234  // if(mSwappingData[i].SwapWith != -1)
235  // {
236  // std::cout << "Element #" << i + 1 << " : " ;
237  // std::cout << mSwappingData[i].NeighbourElements << ",";
238  // std::cout << mSwappingData[i].OppositeNodes << ",";
239  // std::cout << mSwappingData[i].SwapWith;
240  // std::cout << std::endl;
241  // }
242  // }
243 
244 
245  for(int i = 0 ; i < number_of_elements ; i++)
246  {
247  if(mSwappingData[i].SwapWith != -1)
248  {
249  //if((elements_array[i]->Id() > 3100 ) && (elements_array[i]->Id() < 3200 ))
250  // std::cout << "swapping element #" << elements_array[i]->Id() << " with element #" << elements_array[mSwappingData[i].SwapWith]->Id() << std::endl;
251  Swap(*(elements_array[i]),*(elements_array[mSwappingData[i].SwapWith]), mSwappingData[i].SwapEdge, mSwappingData[mSwappingData[i].SwapWith].SwapEdge);
252  }
253  }
254  //KRATOS_WATCH("Swapping done!!");
255  //number_of_bad_quality_elements = MarkBadQualityElements(rThisModelPart);
256  //if(number_of_bad_quality_elements == number_of_bad_quality_elements_old)
257  //{
258  // break;
259  //}
260  //else
261  //{
262  // number_of_bad_quality_elements_old=number_of_bad_quality_elements;
263  //}
264  //WriteMesh(rThisModelPart, "/home/pooyan/kratos/tests/before_collapse.post.msh");
265 
266  CollapseNodes(rThisModelPart);
267  //WriteMesh(rThisModelPart, "/home/pooyan/kratos/tests/after_collapse.post.msh");
268 
269  }
270  //WriteMesh(rThisModelPart, "/home/pooyan/kratos/tests/after_remesh.post.msh");
271 
272  //set the coordinates to the original value
273  /* for( ModelPart::NodeIterator it = rThisModelPart.NodesBegin(); it!= rThisModelPart.NodesEnd(); it++)
274  {
275  const array_1d<double,3>& disp = (it)->FastGetSolutionStepValue(DISPLACEMENT);
276  (it)->X0() = (it)->X() - disp[0];
277  (it)->Y0() = (it)->Y() - disp[1];
278  (it)->Z0() = 0.0;
279  }
280  */
281  Timer::Stop("Edge Swapping");
282  }
283 
286  void WriteMesh(ModelPart& rThisModelPart, const std::string& Filename)
287  {
288  std::ofstream temp_file(Filename.c_str());
289 
290  temp_file << "MESH \"Kratos_Triangle2D3_Mesh\" dimension 2 ElemType Triangle Nnode 3" << std::endl;
291 
292  temp_file << "Coordinates" << std::endl;
293 
294  for(ModelPart::NodeIterator i_node = rThisModelPart.NodesBegin() ; i_node != rThisModelPart.NodesEnd() ; i_node++)
295  temp_file << i_node->Id() << " " << i_node->X() << " " << i_node->Y() << " " << i_node->Z() << std::endl;
296 
297  temp_file << "End Coordinates" << std::endl;
298 
299  temp_file << "Elements" << std::endl;
300 
301  for(ModelPart::ElementIterator i_element = rThisModelPart.ElementsBegin() ; i_element != rThisModelPart.ElementsEnd() ; i_element++)
302  temp_file << i_element->Id() << " " << i_element->GetGeometry()[0].Id() << " " << i_element->GetGeometry()[1].Id() << " " << i_element->GetGeometry()[2].Id() << " 0"<< std::endl;
303 
304 
305  temp_file << "End Elements" << std::endl;
306 
307 
308 
309  }
310 
311 
312 
313 
317 
318 
322 
323 
327 
329  virtual std::string Info() const override
330  {
331  return "EdgeSwapping2DModeler";
332  }
333 
335  virtual void PrintInfo(std::ostream& rOStream) const override
336  {
337  rOStream << Info();
338  }
339 
341  virtual void PrintData(std::ostream& rOStream) const override
342  {
343  }
344 
345 
346 
347 
349 
350 private:
351 
352 
355 
356 
360 
361  std::vector<int> mBadQuality;
362  std::vector<std::vector<int> > mNodalNeighbourElements;
363  std::vector<CollapsingData> mCollapsingData;
364  std::vector<SwappingData > mSwappingData;
365 
369 
370 
374 
375  void CollapseNodes(ModelPart& rThisModelPart)
376  {
377  FindNodalNeighbours(rThisModelPart);
378  SetCollapsingData(rThisModelPart);
379  //const double threshold = 0.2;
380 
381  ModelPart::NodesContainerType::ContainerType& nodes_array = rThisModelPart.NodesArray();
382  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
383 
384  const int number_of_nodes = rThisModelPart.NumberOfNodes();
385  const int number_of_elements = rThisModelPart.NumberOfElements();
386 
387  for(int i = 0 ; i < number_of_nodes ; i++)
388  {
389  NodeType& r_node = *(nodes_array[i]);
390 
391  // std::cout << "node #" << r_node.Id() << " TO_ERASE : " << r_node.Is(TO_ERASE) << std::endl;
392 
393  if(r_node.Is(TO_ERASE))
394  {
395  const int node_index = r_node.Id() - 1;
396  const int nearest_node_id = mCollapsingData[i].NearestNodeId;
397 
398  if(nearest_node_id != -1) // Exist some node to collapsed to
399  {
400  NodeType::Pointer p_node = nodes_array[nearest_node_id - 1];
401  //look for the elements around node
402  for(std::vector<int>::iterator i = mNodalNeighbourElements[node_index].begin() ; i != mNodalNeighbourElements[node_index].end() ; i++)
403  {
404  //look for the this node in neighbour elements
405  Geometry<Node >& r_neighbour_element_geometry = elements_array[*i-1]->GetGeometry();
406  for( unsigned int node_i = 0 ; node_i < r_neighbour_element_geometry.size(); node_i++)
407  {
408  int other_node_id = r_neighbour_element_geometry[node_i].Id();
409  if(other_node_id == static_cast<int>(r_node.Id()))
410  {
411  r_neighbour_element_geometry(node_i) = p_node;
412  }
413  else if(other_node_id == nearest_node_id)
414  {
415  mSwappingData[*i-1].IsElementErased = true;
416  }
417 
418  }
419  }
420  }
421  else
422  {
423  r_node.Set(TO_ERASE, false);
424  }
425  }
426  }
427 
428  rThisModelPart.RemoveNodes(TO_ERASE);
429 
430  ModelPart::ElementsContainerType temp_elements_container;
431  temp_elements_container.reserve(number_of_elements);
432 
433  temp_elements_container.swap(rThisModelPart.Elements());
434 
435 
436 
437  for(ModelPart::ElementsContainerType::iterator i_element = temp_elements_container.begin() ; i_element != temp_elements_container.end() ; i_element++)
438  {
439  if( static_cast<bool>(mSwappingData[i_element->Id()-1].IsElementErased) == false)
440  (rThisModelPart.Elements()).push_back(*(i_element.base()));
441  }
442 
443  }
444 
445 
446 
447  void SetCollapsingData(ModelPart& rThisModelPart)
448  {
449  const int number_of_nodes = static_cast<int>(rThisModelPart.NumberOfNodes());
450  ModelPart::NodesContainerType::ContainerType& nodes_array = rThisModelPart.NodesArray();
451 
452  if(static_cast<int>(mCollapsingData.size()) != number_of_nodes)
453  mCollapsingData.resize(number_of_nodes);
454 
455  for(int i = 0 ; i < number_of_nodes ; i++)
456  mCollapsingData[i].Reset();
457 
458  for(int i = 0 ; i < number_of_nodes ; i++)
459  {
460  NodeType& r_node = *(nodes_array[i]);
461 
462  if(r_node.Is(TO_ERASE))
463  {
464  SetNodalCollapsingData(r_node, rThisModelPart);
465  }
466  }
467  }
468 
469  void SetNodalCollapsingData(NodeType& rThisNode, ModelPart& rThisModelPart)
470  {
471  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
472  //const unsigned int number_of_elements = rThisModelPart.NumberOfElements();
473 
474  const int node_index = rThisNode.Id() - 1;
475 
476  int next[3] = {1,2,0};
477  int previous[3] = {2,0,1};
478 
479  //look for the elements around node
480  for(std::vector<int>::iterator i = mNodalNeighbourElements[node_index].begin() ; i != mNodalNeighbourElements[node_index].end() ; i++)
481  {
482  //look for the nodes of the neighbour faces
483  Geometry<Node >& r_neighbour_element_geometry = elements_array[*i-1]->GetGeometry();
484  for( unsigned int i_node = 0 ; i_node < r_neighbour_element_geometry.size(); i_node++)
485  {
486  if(r_neighbour_element_geometry[i_node].Is(TO_ERASE) == 0) // can be used for collapse and is not the same node!
487  {
488  int other_node_id = r_neighbour_element_geometry[i_node].Id();
489  if(other_node_id == mCollapsingData[node_index].NearestNodeId)
490  {
491  mCollapsingData[node_index].CollapseElements[1] = *i;
492  }
493  else if(r_neighbour_element_geometry[next[i_node]].Id() == rThisNode.Id())
494  {
495  double d=Distance2(r_neighbour_element_geometry[i_node], r_neighbour_element_geometry[next[i_node]]);
496 
497  if((d < mCollapsingData[node_index].MinimumDistance) || (mCollapsingData[node_index].MinimumDistance < 0.00))
498  {
499  mCollapsingData[node_index].MinimumDistance = d;
500  mCollapsingData[node_index].NearestNodeId = other_node_id;
501  mCollapsingData[node_index].CollapseElements[0] = *i;
502  }
503  }
504  else if(r_neighbour_element_geometry[previous[i_node]].Id() == rThisNode.Id())
505  {
506  double d=Distance2(r_neighbour_element_geometry[i_node], r_neighbour_element_geometry[previous[i_node]]);
507 
508  if((d < mCollapsingData[node_index].MinimumDistance) || (mCollapsingData[node_index].MinimumDistance < 0.00))
509  {
510  mCollapsingData[node_index].MinimumDistance = d;
511  mCollapsingData[node_index].NearestNodeId = other_node_id;
512  mCollapsingData[node_index].CollapseElements[0] = *i;
513  }
514  }
515 
516  }
517  }
518 
519  }
520  }
521 
522 
523 
524  double Distance2(NodeType& rNode1, NodeType& rNode2)
525  {
526  double dx = rNode1.X() - rNode2.X();
527  double dy = rNode1.Y() - rNode2.Y();
528 
529  return dx*dx + dy*dy;
530  }
531 
532  void Swap(Element& rElement1, Element& rElement2, int Edge1, int Edge2)
533  {
534 
535  int next2[3] = {2,0,1};
536 
537  /* std::cout << "Element1 #" << rElement1.Id() << " : " << rElement1.GetGeometry()[0].Id() << " : " << rElement1.GetGeometry()[1].Id() << " : " << rElement1.GetGeometry()[2].Id() << std::endl; */
538  /* std::cout << "Element2 #" << rElement2.Id() << " : " << rElement2.GetGeometry()[0].Id() << " : " << rElement2.GetGeometry()[1].Id() << " : " << rElement2.GetGeometry()[2].Id() << std::endl; */
539  //KRATOS_WATCH(Edge1);
540  //KRATOS_WATCH(Edge2);
541 
542  //KRATOS_WATCH(rElement1.GetGeometry().Area())
543  //KRATOS_WATCH(rElement2.GetGeometry().Area())
544 
545  rElement1.GetGeometry()(next2[Edge1]) = rElement2.GetGeometry()(Edge2);
546  rElement2.GetGeometry()(next2[Edge2]) = rElement1.GetGeometry()(Edge1);
547 
548  //KRATOS_WATCH(rElement1.GetGeometry().Area())
549  //KRATOS_WATCH(rElement2.GetGeometry().Area())
550 
551 
552  }
553 
554  unsigned int MarkBadQualityElements(ModelPart& rThisModelPart)
555  {
556 // unsigned int counter = 0;
557  unsigned int marked = 0;
558 
559  const double threshold = 0.25;
560 
561  if(mBadQuality.size() != rThisModelPart.NumberOfElements())
562  mBadQuality.resize(rThisModelPart.NumberOfElements());
563 
564  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
565  const int number_of_elements = rThisModelPart.NumberOfElements();
566 
567  IndexPartition<std::size_t>(number_of_elements).for_each([&](std::size_t Index){
568  if(ElementQuality(*elements_array[Index]) < threshold)
569  {
570  marked++;
571  mBadQuality[Index] = true;
572  }
573  });
574 
575 // To be parallelized.
576 // for(ModelPart::ElementIterator i_element = rThisModelPart.ElementsBegin() ; i_element != rThisModelPart.ElementsEnd() ; i_element++)
577 // {
578 // if(ElementQuality(*i_element) < threshold)
579 // {
580 // marked++;
581 // mBadQuality[counter] = true;
582 // }
583 // counter++;
584 // }
585 
586  return marked;
587  }
588 
589  double ElementQuality(Element& rThisElement)
590  {
591  double h_min;
592  double h_max;
593  double area = rThisElement.GetGeometry().Area();
594 
595  GeometryUtils::SideLenghts2D(rThisElement.GetGeometry(), h_min, h_max);
596 
597  return (area / (h_max*h_max));
598  }
599 
600  void FindNodalNeighbours(ModelPart& rThisModelPart)
601  {
602  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
603  const int number_of_nodes = static_cast<int>(rThisModelPart.NumberOfNodes());
604  const int number_of_elements = static_cast<int>(rThisModelPart.NumberOfElements());
605 
606  if(static_cast<int>(mNodalNeighbourElements.size()) != number_of_nodes)
607  mNodalNeighbourElements.resize(number_of_nodes);
608 
609  for(int i = 0 ; i < number_of_nodes ; i++)
610  mNodalNeighbourElements[i].clear();
611 
612  for(int i = 0 ; i < number_of_elements ; i++)
613  {
614  Element::GeometryType& r_geometry = elements_array[i]->GetGeometry();
615  for(unsigned int j = 0; j < r_geometry.size(); j++)
616  {
617  mNodalNeighbourElements[r_geometry[j].Id()-1].push_back(elements_array[i]->Id());
618  }
619  }
620 
621  for(int i = 0 ; i < number_of_nodes ; i++)
622  {
623  std::sort(mNodalNeighbourElements[i].begin(),mNodalNeighbourElements[i].end());
624  std::vector<int>::iterator new_end = std::unique(mNodalNeighbourElements[i].begin(),mNodalNeighbourElements[i].end());
625  mNodalNeighbourElements[i].erase(new_end, mNodalNeighbourElements[i].end());
626  }
627  }
628 
629  void SetSwappingData(ModelPart& rThisModelPart)
630  {
631  ModelPart::NodesContainerType::ContainerType& nodes_array = rThisModelPart.NodesArray();
632  ModelPart::ElementsContainerType::ContainerType& elements_array = rThisModelPart.ElementsArray();
633  const int number_of_elements = static_cast<int>(rThisModelPart.NumberOfElements());
634 
635  FindNodalNeighbours(rThisModelPart);
636 
637  if(static_cast<int>(mSwappingData.size()) != number_of_elements)
638  mSwappingData.resize(number_of_elements);
639 
640  IndexPartition<std::size_t>(number_of_elements).for_each([this](std::size_t Index){
641  mSwappingData[Index].Reset();
642  });
643 
644  IndexPartition<std::size_t>(number_of_elements).for_each([&](std::size_t Index){
645  Element::GeometryType& r_geometry = elements_array[Index]->GetGeometry();
646  int id = elements_array[Index]->Id();
647  FindNeighbourElement(r_geometry[1].Id(), r_geometry[2].Id(), id, elements_array, mSwappingData[Index], 0);
648  FindNeighbourElement(r_geometry[2].Id(), r_geometry[0].Id(), id, elements_array, mSwappingData[Index], 1);
649  FindNeighbourElement(r_geometry[0].Id(), r_geometry[1].Id(), id, elements_array, mSwappingData[Index], 2);
650  for(unsigned int j = 0; j < r_geometry.size(); j++)
651  {
652  mSwappingData[Index].IsInside[j] = IsInElementSphere(*(elements_array[Index]), *(nodes_array[mSwappingData[Index].OppositeNodes[j]-1]));
653  }
654  });
655  }
656 
657 
658  void FindNeighbourElement(unsigned int NodeId1, unsigned int NodeId2, int ElementId, ModelPart::ElementsContainerType::ContainerType const& ElementsArray, SwappingData& rSwappingData, int EdgeIndex)
659  {
660  const int node_index_1 = NodeId1 - 1;
661 
662  rSwappingData.NeighbourElements[EdgeIndex] = -1;
663 
664 
665  //look for the elements around node NodeId1
666  for(std::vector<int>::iterator i = mNodalNeighbourElements[node_index_1].begin() ; i != mNodalNeighbourElements[node_index_1].end() ; i++)
667  {
668  //look for the nodes of the neighbour faces
669  Geometry<Node >& r_neighbour_element_geometry = ElementsArray[*i-1]->GetGeometry();
670  rSwappingData.OppositeNodes[EdgeIndex] = -1;
671  for( int node_i = 0 ; node_i < static_cast<int>(r_neighbour_element_geometry.size()); node_i++)
672  {
673  int other_node_id = r_neighbour_element_geometry[node_i].Id();
674  if ((other_node_id != static_cast<int>(NodeId1)) && (other_node_id != static_cast<int>(NodeId2)))
675  {
676  rSwappingData.OppositeNodes[EdgeIndex] = other_node_id;
677  rSwappingData.OppositeEdge[EdgeIndex] = node_i;
678  }
679 
680  if (r_neighbour_element_geometry[node_i].Id() == NodeId2)
681  {
682  if(*i != ElementId)
683  {
684  rSwappingData.NeighbourElements[EdgeIndex] = *i;
685  }
686  }
687  }
688  if(rSwappingData.NeighbourElements[EdgeIndex] != -1)
689  return;
690  }
691  return;
692  }
693 
694  void PrepareForSwapping(ModelPart& rThisModelPart)
695  {
696  for(ModelPart::ElementIterator i_element = rThisModelPart.ElementsBegin() ; i_element != rThisModelPart.ElementsEnd() ; i_element++)
697  {
698  }
699  }
700 
701  bool IsInElementSphere(Element& rThisElement, NodeType& rThisNode)
702  {
703  Element::GeometryType& r_geometry = rThisElement.GetGeometry();
704 
705 
706  double ax = r_geometry[0].X();
707  double ay = r_geometry[0].Y();
708 
709  double bx = r_geometry[1].X();
710  double by = r_geometry[1].Y();
711 
712  double cx = r_geometry[2].X();
713  double cy = r_geometry[2].Y();
714 
715  double a2 = ax*ax + ay*ay;
716  double b2 = bx*bx + by*by;
717  double c2 = cx*cx + cy*cy;
718 
719  double vx = rThisNode.X();
720  double vy = rThisNode.Y();
721 
722  double v2 = vx*vx + vy*vy;
723 
724 
725  double a11 = r_geometry[0].X()-rThisNode.X();
726  double a12 = r_geometry[0].Y()-rThisNode.Y();
727  double a13 = a2 - v2;
728 
729  double a21 = r_geometry[1].X()-rThisNode.X();
730  double a22 = r_geometry[1].Y()-rThisNode.Y();
731  double a23 = b2 - v2;
732 
733  double a31 = r_geometry[2].X()-rThisNode.X();
734  double a32 = r_geometry[2].Y()-rThisNode.Y();
735  double a33 = c2 - v2;
736 
737  return ( ( a11*(a22*a33-a23*a32) + a12*(a23*a31-a21*a33) + a13*(a21*a32-a22*a31) ) > 0.0 );
738  }
739 
740 
744 
745 
749 
750 
754 
756  EdgeSwapping2DModeler& operator=(EdgeSwapping2DModeler const& rOther);
757 
760 
761 
763 
764 }; // Class EdgeSwapping2DModeler
765 
767 
770 
771 
775 
776 
778 inline std::istream& operator >> (std::istream& rIStream,
779  EdgeSwapping2DModeler& rThis);
780 
782 inline std::ostream& operator << (std::ostream& rOStream,
783  const EdgeSwapping2DModeler& rThis)
784 {
785  rThis.PrintInfo(rOStream);
786  rOStream << std::endl;
787  rThis.PrintData(rOStream);
788 
789  return rOStream;
790 }
792 
793 
794 } // namespace Kratos.
795 
796 #endif // KRATOS_EDGE_SWAPPING_2D_MODELER_H_INCLUDED defined
797 
798 
Optimizes a 2D mesh by swapping the edges between elements.
Definition: edge_swapping_2d_modeler.h:50
std::size_t SizeType
Definition: edge_swapping_2d_modeler.h:132
void Remesh(ModelPart &rThisModelPart)
Definition: edge_swapping_2d_modeler.h:162
Point PointType
Definition: edge_swapping_2d_modeler.h:117
void WriteMesh(ModelPart &rThisModelPart, const std::string &Filename)
Definition: edge_swapping_2d_modeler.h:286
KRATOS_CLASS_POINTER_DEFINITION(EdgeSwapping2DModeler)
Pointer definition of EdgeSwapping2DModeler.
Modeler BaseType
Definition: edge_swapping_2d_modeler.h:115
virtual std::string Info() const override
Turn back information as a string.
Definition: edge_swapping_2d_modeler.h:329
Node NodeType
Definition: edge_swapping_2d_modeler.h:121
PointerVector< NodeType > NodesVectorType
Definition: edge_swapping_2d_modeler.h:130
virtual ~EdgeSwapping2DModeler()
Empty destructor.
Definition: edge_swapping_2d_modeler.h:144
virtual void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: edge_swapping_2d_modeler.h:335
EdgeSwapping2DModeler()
Empty default constructor.
Definition: edge_swapping_2d_modeler.h:139
virtual void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: edge_swapping_2d_modeler.h:341
Geometry< NodeType > GeometryType
Definition: edge_swapping_2d_modeler.h:125
Geometry< NodeType > GeometryType
definition of the geometry type with given NodeType
Definition: element.h:83
void Set(const Flags ThisFlag)
Definition: flags.cpp:33
bool Is(Flags const &rOther) const
Definition: flags.h:274
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
static void SideLenghts2D(const GeometryType &rGeometry, double &hmin, double &hmax)
This function compute the maximum and minimum edge lenghts.
Definition: geometry_utilities.h:311
This class is useful for index iteration over containers.
Definition: parallel_utilities.h:451
void for_each(TUnaryFunction &&f)
Definition: parallel_utilities.h:514
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
MeshType::ElementsContainerType ElementsContainerType
Element container. A vector set of Elements with their Id's as key.
Definition: model_part.h:168
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
SizeType NumberOfElements(IndexType ThisIndex=0) const
Definition: model_part.h:1027
NodesContainerType::ContainerType & NodesArray(IndexType ThisIndex=0)
Definition: model_part.h:527
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
void RemoveNodes(Flags IdentifierFlag=TO_ERASE)
Definition: model_part.cpp:445
ElementIterator ElementsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1179
MeshType::ElementIterator ElementIterator
Definition: model_part.h:174
SizeType NumberOfNodes(IndexType ThisIndex=0) const
Definition: model_part.h:341
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
ElementsContainerType::ContainerType & ElementsArray(IndexType ThisIndex=0)
Definition: model_part.h:1209
Modeler to interact with ModelParts.
Definition: modeler.h:39
This class defines the node.
Definition: node.h:65
IndexType Id() const
Definition: node.h:262
Point class.
Definition: point.h:59
double Y() const
Definition: point.h:187
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(int reservedsize)
Reserves memory for a specified number of elements.
Definition: pointer_vector_set.h:733
static void Start(std::string const &rIntervalName)
This method starts the timer meassures.
Definition: timer.cpp:109
static void Stop(std::string const &rIntervalName)
This method stops the timer meassures.
Definition: timer.cpp:125
end
Definition: DEM_benchmarks.py:180
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
ax
Definition: all_t_win_vs_m_fixed_error.py:238
def Index()
Definition: hdf5_io_tools.py:38
threshold
Definition: isotropic_damage_automatic_differentiation.py:135
int d
Definition: ode_solve.py:397
int j
Definition: quadrature.py:648
integer i
Definition: TensorModule.f:17
Configure::ContainerType ContainerType
Definition: transfer_utility.h:247